OSDN Git Service

Initial contents of nt2chview
authorAkira <akohta001@gmail.com>
Sat, 20 Jul 2013 14:10:20 +0000 (23:10 +0900)
committerAkira <akohta001@gmail.com>
Sat, 20 Jul 2013 14:10:20 +0000 (23:10 +0900)
241 files changed:
NT2chCtrl245/DragDropData.cs [new file with mode: 0755]
NT2chCtrl245/FavoriteImageConverter.cs [new file with mode: 0755]
NT2chCtrl245/ListItemViewPopup.cs [new file with mode: 0755]
NT2chCtrl245/MenuItemPopup.cs [new file with mode: 0755]
NT2chCtrl245/NT2chCtrl245.csproj [new file with mode: 0755]
NT2chCtrl245/NTBoardData.cs [new file with mode: 0755]
NT2chCtrl245/NTSubjectViewPanel.xaml [new file with mode: 0755]
NT2chCtrl245/NTSubjectViewPanel.xaml.cs [new file with mode: 0755]
NT2chCtrl245/NTSubjectViewPanel_event.cs [new file with mode: 0755]
NT2chCtrl245/NTSubjectViewPanel_persistent.cs [new file with mode: 0755]
NT2chCtrl245/NTSubjectViewPanel_util.cs [new file with mode: 0755]
NT2chCtrl245/ObjectImpl.cs [new file with mode: 0755]
NT2chCtrl245/Properties/AssemblyInfo.cs [new file with mode: 0755]
NT2chCtrl45/DebugMemory.cs [new file with mode: 0755]
NT2chCtrl45/Dictionary1.xaml [new file with mode: 0755]
NT2chCtrl45/NT2chCtrl45.csproj [new file with mode: 0755]
NT2chCtrl45/NTMemoryInspectionWindow.xaml [new file with mode: 0755]
NT2chCtrl45/NTMemoryInspectionWindow.xaml.cs [new file with mode: 0755]
NT2chCtrl45/NTResViewPanel.xaml [new file with mode: 0755]
NT2chCtrl45/NTResViewPanel.xaml.cs [new file with mode: 0755]
NT2chCtrl45/NTResViewPanel_file.cs [new file with mode: 0755]
NT2chCtrl45/NTResViewPanel_misc.cs [new file with mode: 0755]
NT2chCtrl45/NTResViewPanel_util.cs [new file with mode: 0755]
NT2chCtrl45/NTScriptDebugger.xaml [new file with mode: 0755]
NT2chCtrl45/NTScriptDebugger.xaml.cs [new file with mode: 0755]
NT2chCtrl45/Properties/AssemblyInfo.cs [new file with mode: 0755]
NT2chCtrl45/Properties/Resources.Designer.cs [new file with mode: 0755]
NT2chCtrl45/Properties/Resources.resx [new file with mode: 0755]
NT2chCtrl45/Properties/Settings.Designer.cs [new file with mode: 0755]
NT2chCtrl45/Properties/Settings.settings [new file with mode: 0755]
NT2chCtrl45/ResListAdapter.cs [new file with mode: 0755]
NT2chCtrl45/ResListAdapter_callback.cs [new file with mode: 0755]
NT2chCtrl45/ResListAdapter_event.cs [new file with mode: 0755]
NT2chCtrl45/ResListAdapter_misc.cs [new file with mode: 0755]
NT2chCtrl45/ResViewCtrlState.cs [new file with mode: 0755]
NT2chCtrl45/ResViewPopup.cs [new file with mode: 0755]
NT2chCtrl45/ThreadDescription.cs [new file with mode: 0755]
NT2chCtrl45/ThreadHistoryUI.cs [new file with mode: 0755]
NT2chCtrl45/TouchSupportScrollViewer.cs [new file with mode: 0755]
NT2chCtrl45/UIElementListAdapter.cs [new file with mode: 0755]
NT2chCtrl45/UIElementListAdapter_event.cs [new file with mode: 0755]
NT2chCtrl45/UIElementListAdapter_timer.cs [new file with mode: 0755]
NT2chCtrl45/UIElementListAdapter_util.cs [new file with mode: 0755]
NT2chCtrl45/html/CommentElement.cs [new file with mode: 0755]
NT2chCtrl45/html/DebugContext.cs [new file with mode: 0755]
NT2chCtrl45/html/HtmlAttribute.cs [new file with mode: 0755]
NT2chCtrl45/html/HtmlColors.cs [new file with mode: 0755]
NT2chCtrl45/html/HtmlElement.cs [new file with mode: 0755]
NT2chCtrl45/html/HtmlElement_2chparser.cs [new file with mode: 0755]
NT2chCtrl45/html/HtmlElement_css.cs [new file with mode: 0755]
NT2chCtrl45/html/HtmlEscape.cs [new file with mode: 0755]
NT2chCtrl45/html/HtmlParser.cs [new file with mode: 0755]
NT2chCtrl45/html/HtmlToken.cs [new file with mode: 0755]
NT2chCtrl45/html/StringElement.cs [new file with mode: 0755]
NT2chCtrl45/html/css/Property.cs [new file with mode: 0755]
NT2chCtrl45/html/css/Select.cs [new file with mode: 0755]
NT2chCtrl45/html/css/Selector.cs [new file with mode: 0755]
NT2chCtrl45/html/css/cssColor.cs [new file with mode: 0755]
NT2chCtrl45/html/css/cssFont.cs [new file with mode: 0755]
NT2chCtrl45/html/css/cssLength.cs [new file with mode: 0755]
NT2chCtrl45/html/js/JsArrayValue.cs [new file with mode: 0755]
NT2chCtrl45/html/js/JsCmpFunction.cs [new file with mode: 0755]
NT2chCtrl45/html/js/JsDOMValue.cs [new file with mode: 0755]
NT2chCtrl45/html/js/JsDomFunction.cs [new file with mode: 0755]
NT2chCtrl45/html/js/JsDomStrFunction.cs [new file with mode: 0755]
NT2chCtrl45/html/js/JsError.cs [new file with mode: 0755]
NT2chCtrl45/html/js/JsFunction.cs [new file with mode: 0755]
NT2chCtrl45/html/js/JsFunctionContext.cs [new file with mode: 0755]
NT2chCtrl45/html/js/JsOpFunction.cs [new file with mode: 0755]
NT2chCtrl45/html/js/JsOpFunction2.cs [new file with mode: 0755]
NT2chCtrl45/html/js/JsOpFunction3.cs [new file with mode: 0755]
NT2chCtrl45/html/js/JsOpFunction4.cs [new file with mode: 0755]
NT2chCtrl45/html/js/JsParser.cs [new file with mode: 0755]
NT2chCtrl45/html/js/JsRootFunction.cs [new file with mode: 0755]
NT2chCtrl45/html/js/JsToken.cs [new file with mode: 0755]
NT2chCtrl45/html/js/JsVariable.cs [new file with mode: 0755]
NT2chCtrl45/html/js/JsVariant.cs [new file with mode: 0755]
NT2chCtrl45/html/wpf/FontCash.cs [new file with mode: 0755]
NT2chCtrl45/html/wpf/Html2FlowDoc.cs [new file with mode: 0755]
NT2chCtrl45/html/wpf/ImageCash.cs [new file with mode: 0755]
NT2chObject45/NT2chObject45.csproj [new file with mode: 0755]
NT2chObject45/NTConstants.cs [new file with mode: 0755]
NT2chObject45/NTInterfaceDecl.cs [new file with mode: 0755]
NT2chObject45/NTThread.cs [new file with mode: 0755]
NT2chObject45/Properties/AssemblyInfo.cs [new file with mode: 0755]
NT2chObject45/ThumbnailImageHelper.cs [new file with mode: 0755]
NT2chStyle45/CustomControl1.cs [new file with mode: 0755]
NT2chStyle45/MainDictionary-black.xaml [new file with mode: 0755]
NT2chStyle45/MainDictionary.xaml [new file with mode: 0755]
NT2chStyle45/NT2chStyle45.csproj [new file with mode: 0755]
NT2chStyle45/Properties/AssemblyInfo.cs [new file with mode: 0755]
NT2chStyle45/Properties/Resources.Designer.cs [new file with mode: 0755]
NT2chStyle45/Properties/Resources.resx [new file with mode: 0755]
NT2chStyle45/Properties/Settings.Designer.cs [new file with mode: 0755]
NT2chStyle45/Properties/Settings.settings [new file with mode: 0755]
NT2chStyle45/Themes/Generic.xaml [new file with mode: 0755]
NT2chStyle45/images/autoplay_btn.png [new file with mode: 0755]
NT2chStyle45/images/back_btn.png [new file with mode: 0755]
NT2chStyle45/images/back_btn_light.png [new file with mode: 0755]
NT2chStyle45/images/close_tab.png [new file with mode: 0755]
NT2chStyle45/images/down.png [new file with mode: 0755]
NT2chStyle45/images/enlarge_font.png [new file with mode: 0755]
NT2chStyle45/images/exit_btn.png [new file with mode: 0755]
NT2chStyle45/images/exit_btn_light.png [new file with mode: 0755]
NT2chStyle45/images/favo_off.png [new file with mode: 0755]
NT2chStyle45/images/favo_on.png [new file with mode: 0755]
NT2chStyle45/images/font_btn.png [new file with mode: 0755]
NT2chStyle45/images/font_btn_ics.png [new file with mode: 0755]
NT2chStyle45/images/hand_btn.png [new file with mode: 0755]
NT2chStyle45/images/history_btn.png [new file with mode: 0755]
NT2chStyle45/images/home_btn.png [new file with mode: 0755]
NT2chStyle45/images/home_btn_light.png [new file with mode: 0755]
NT2chStyle45/images/jmp_to_new.png [new file with mode: 0755]
NT2chStyle45/images/max_window2.png [new file with mode: 0755]
NT2chStyle45/images/pause_btn.png [new file with mode: 0755]
NT2chStyle45/images/play_btn.png [new file with mode: 0755]
NT2chStyle45/images/reduce_font.png [new file with mode: 0755]
NT2chStyle45/images/restore_window2.png [new file with mode: 0755]
NT2chStyle45/images/reverse.png [new file with mode: 0755]
NT2chStyle45/images/search_btn.png [new file with mode: 0755]
NT2chStyle45/images/search_btn_light.png [new file with mode: 0755]
NT2chStyle45/images/setup_btn.png [new file with mode: 0755]
NT2chStyle45/images/stop_btn.png [new file with mode: 0755]
NT2chStyle45/images/tag.png [new file with mode: 0755]
NT2chStyle45/images/tag_btn.png [new file with mode: 0755]
NT2chStyle45/images/texttools_btn.png [new file with mode: 0755]
NT2chStyle45/images/timer_btn.png [new file with mode: 0755]
NT2chStyle45/images/to_the_bottom.png [new file with mode: 0755]
NT2chStyle45/images/to_the_bottom_light.png [new file with mode: 0755]
NT2chStyle45/images/to_the_top.png [new file with mode: 0755]
NT2chStyle45/images/to_the_top_light.png [new file with mode: 0755]
NT2chStyle45/images/up.png [new file with mode: 0755]
NT2chStyle45/images/update_btn.png [new file with mode: 0755]
NT2chStyle45/images/update_btn_light.png [new file with mode: 0755]
NT2chStyle45/images/write_btn.png [new file with mode: 0755]
NT2chView45.sln [new file with mode: 0755]
NT2chView45/App.xaml [new file with mode: 0755]
NT2chView45/App.xaml.cs [new file with mode: 0755]
NT2chView45/MainWindow.xaml [new file with mode: 0755]
NT2chView45/MainWindow.xaml.cs [new file with mode: 0755]
NT2chView45/MainWindow_backgroudworker.cs [new file with mode: 0755]
NT2chView45/MainWindow_ctrl_event_handler.cs [new file with mode: 0755]
NT2chView45/MainWindow_delegates.cs [new file with mode: 0755]
NT2chView45/MainWindow_manipulate_ctrl.cs [new file with mode: 0755]
NT2chView45/MainWindow_toolbar_dragdrop.cs [new file with mode: 0755]
NT2chView45/NT2chView.csproj [new file with mode: 0755]
NT2chView45/NT2chView.csproj.user [new file with mode: 0755]
NT2chView45/NT2chView45.csproj [new file with mode: 0755]
NT2chView45/NT2chView45.csproj.user [new file with mode: 0755]
NT2chView45/NTAllboardSearch.cs [new file with mode: 0755]
NT2chView45/NTAppState.cs [new file with mode: 0755]
NT2chView45/NTAsciiArt.cs [new file with mode: 0755]
NT2chView45/NTBoard.cs [new file with mode: 0755]
NT2chView45/NTBoardPanel.xaml [new file with mode: 0755]
NT2chView45/NTBoardPanel.xaml.cs [new file with mode: 0755]
NT2chView45/NTBoardPopupMenu.cs [new file with mode: 0755]
NT2chView45/NTBoard_backgroundworker.cs [new file with mode: 0755]
NT2chView45/NTCategory.cs [new file with mode: 0755]
NT2chView45/NTCategoryPanel.xaml [new file with mode: 0755]
NT2chView45/NTCategoryPanel.xaml.cs [new file with mode: 0755]
NT2chView45/NTCreateThreadWindow.xaml [new file with mode: 0755]
NT2chView45/NTCreateThreadWindow.xaml.cs [new file with mode: 0755]
NT2chView45/NTDataRoot.cs [new file with mode: 0755]
NT2chView45/NTDebug.cs [new file with mode: 0755]
NT2chView45/NTDragDrop.cs [new file with mode: 0755]
NT2chView45/NTExportUtil.cs [new file with mode: 0755]
NT2chView45/NTFavorite.cs [new file with mode: 0755]
NT2chView45/NTFavoriteBoard.cs [new file with mode: 0755]
NT2chView45/NTFavoriteBoardPopupMenu.cs [new file with mode: 0755]
NT2chView45/NTFavoritePanel.xaml [new file with mode: 0755]
NT2chView45/NTFavoritePanel.xaml.cs [new file with mode: 0755]
NT2chView45/NTFavoriteTagEditWindow.xaml [new file with mode: 0755]
NT2chView45/NTFavoriteTagEditWindow.xaml.cs [new file with mode: 0755]
NT2chView45/NTFavoriteThread.cs [new file with mode: 0755]
NT2chView45/NTFavoriteThreadPopupMenu.cs [new file with mode: 0755]
NT2chView45/NTFavoriteThreadTag.cs [new file with mode: 0755]
NT2chView45/NTFavoriteThreadTagPopupMenu.cs [new file with mode: 0755]
NT2chView45/NTFontSelectDialog.xaml [new file with mode: 0755]
NT2chView45/NTFontSelectDialog.xaml.cs [new file with mode: 0755]
NT2chView45/NTFontUtil.cs [new file with mode: 0755]
NT2chView45/NTGraphicsPanel.xaml [new file with mode: 0755]
NT2chView45/NTGraphicsPanel.xaml.cs [new file with mode: 0755]
NT2chView45/NTHistory.cs [new file with mode: 0755]
NT2chView45/NTHistoryPanel.xaml [new file with mode: 0755]
NT2chView45/NTHistoryPanel.xaml.cs [new file with mode: 0755]
NT2chView45/NTHistoryThread.cs [new file with mode: 0755]
NT2chView45/NTMaru.cs [new file with mode: 0755]
NT2chView45/NTMenuCommand.cs [new file with mode: 0755]
NT2chView45/NTMovieHistory.cs [new file with mode: 0755]
NT2chView45/NTMovieHistoryPopup.cs [new file with mode: 0755]
NT2chView45/NTMoviePanel.xaml [new file with mode: 0755]
NT2chView45/NTMoviePanel.xaml.cs [new file with mode: 0755]
NT2chView45/NTNgItems.cs [new file with mode: 0755]
NT2chView45/NTOpenedThreadTable.cs [new file with mode: 0755]
NT2chView45/NTRes.cs [new file with mode: 0755]
NT2chView45/NTResMenuCommand.cs [new file with mode: 0755]
NT2chView45/NTResPopupMenu.cs [new file with mode: 0755]
NT2chView45/NTSetupAESWindow.xaml [new file with mode: 0755]
NT2chView45/NTSetupAESWindow.xaml.cs [new file with mode: 0755]
NT2chView45/NTSetupWindow.xaml [new file with mode: 0755]
NT2chView45/NTSetupWindow.xaml.cs [new file with mode: 0755]
NT2chView45/NTSimString.cs [new file with mode: 0755]
NT2chView45/NTTextFormat.cs [new file with mode: 0755]
NT2chView45/NTTextUtiles.cs [new file with mode: 0755]
NT2chView45/NTThreadCashData.cs [new file with mode: 0755]
NT2chView45/NTThreadInfoWindow.xaml [new file with mode: 0755]
NT2chView45/NTThreadInfoWindow.xaml.cs [new file with mode: 0755]
NT2chView45/NTThreadTitle.cs [new file with mode: 0755]
NT2chView45/NTUserPreference.cs [new file with mode: 0755]
NT2chView45/NTVagueSearchWord.cs [new file with mode: 0755]
NT2chView45/NTWriteResHistoryPopup.cs [new file with mode: 0755]
NT2chView45/NTWriteResResultWindow.xaml [new file with mode: 0755]
NT2chView45/NTWriteResResultWindow.xaml.cs [new file with mode: 0755]
NT2chView45/NTWriteResWindow.xaml [new file with mode: 0755]
NT2chView45/NTWriteResWindow.xaml.cs [new file with mode: 0755]
NT2chView45/NtFile/NTFileAccess.cs [new file with mode: 0755]
NT2chView45/NtFile/NTFileUtil.cs [new file with mode: 0755]
NT2chView45/NtFile/NTPersistentFileAccess.cs [new file with mode: 0755]
NT2chView45/NtHtml/NTHtmlParser.cs [new file with mode: 0755]
NT2chView45/NtHtml/NTHtmlUtils.cs [new file with mode: 0755]
NT2chView45/NtHtml/NTHtmlUtils_EscapeTable.cs [new file with mode: 0755]
NT2chView45/NtHtml/NTHtmlWriteResParser.cs [new file with mode: 0755]
NT2chView45/NtNet/NTCloud.cs [new file with mode: 0755]
NT2chView45/NtNet/NTCookie.cs [new file with mode: 0755]
NT2chView45/NtNet/NTCrypt.cs [new file with mode: 0755]
NT2chView45/NtNet/NTHttpAccess.cs [new file with mode: 0755]
NT2chView45/NtNet/NTHttpAccess_cloud.cs [new file with mode: 0755]
NT2chView45/NtNet/NTHttpAccess_user_cloud.cs [new file with mode: 0755]
NT2chView45/NtNet/NTHttpAccess_util.cs [new file with mode: 0755]
NT2chView45/NtNet/NTHttpUtils.cs [new file with mode: 0755]
NT2chView45/Properties/AssemblyInfo.cs [new file with mode: 0755]
NT2chView45/Properties/Resources.Designer.cs [new file with mode: 0755]
NT2chView45/Properties/Resources.resx [new file with mode: 0755]
NT2chView45/Properties/Settings.Designer.cs [new file with mode: 0755]
NT2chView45/Properties/Settings.settings [new file with mode: 0755]
NT2chView45/app.config [new file with mode: 0755]
NT2chView45/images/left.png [new file with mode: 0755]
NT2chView45/images/neetchan2.png [new file with mode: 0755]
NT2chView45/images/right.png [new file with mode: 0755]
NT2chView45/images/search_btn.png [new file with mode: 0755]
NT2chView45/neetchan6.ico [new file with mode: 0755]

diff --git a/NT2chCtrl245/DragDropData.cs b/NT2chCtrl245/DragDropData.cs
new file mode 100755 (executable)
index 0000000..86e8337
--- /dev/null
@@ -0,0 +1,12 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+\r
+namespace NT2chCtrl2\r
+{\r
+    class DragDropData\r
+    {\r
+        public const string BOARD_MENU_ITEM_DRAG_DATA = "BOARD_MENU_ITEM_DRAG_DATA";\r
+        public const int DRAG_START_MOVE_DELTA = 8;\r
+    }\r
+}\r
diff --git a/NT2chCtrl245/FavoriteImageConverter.cs b/NT2chCtrl245/FavoriteImageConverter.cs
new file mode 100755 (executable)
index 0000000..e26e3b4
--- /dev/null
@@ -0,0 +1,37 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Windows.Controls;\r
+using System.Windows.Data;\r
+using System.Windows.Media.Imaging;\r
+\r
+namespace NT2chCtrl2\r
+{\r
+    public class FavoriteImageConverter : IValueConverter\r
+    {\r
+\r
+        public object Convert(object value, Type targetType, object parameter,\r
+            System.Globalization.CultureInfo culture)\r
+        {\r
+            bool flag = (bool)value;\r
+\r
+            Uri oUri;\r
+            if(flag)\r
+                oUri = new Uri("pack://application:,,,/NT2chStyle45;component/images/favo_on.png", UriKind.RelativeOrAbsolute);\r
+            else\r
+                oUri = new Uri("pack://application:,,,/NT2chStyle45;component/images/favo_off.png", UriKind.RelativeOrAbsolute);\r
+            BitmapImage bi = new BitmapImage();\r
+            bi.BeginInit();\r
+            bi.UriSource = oUri;\r
+            bi.EndInit();\r
+            return bi;\r
+        }\r
+\r
+        public object ConvertBack(object value, Type targetType, object parameter,\r
+            System.Globalization.CultureInfo culture)\r
+        {\r
+            throw new NotSupportedException();\r
+        }\r
+\r
+    }\r
+}\r
diff --git a/NT2chCtrl245/ListItemViewPopup.cs b/NT2chCtrl245/ListItemViewPopup.cs
new file mode 100755 (executable)
index 0000000..5740371
--- /dev/null
@@ -0,0 +1,228 @@
+using NT2chObject;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Windows.Controls;\r
+using System.Windows.Controls.Primitives;\r
+using System.Windows.Documents;\r
+using System.Windows.Media;\r
+using System.Windows;\r
+\r
+namespace NT2chCtrl2\r
+{\r
+    class ListItemViewPopup : Popup\r
+    {\r
\r
+        IThread2 mThread;\r
+        ICommand2 mCommand;\r
+\r
+        public ListItemViewPopup(IThread2 ithread, ICommand2 command, bool exsitsLog) : base()\r
+        {\r
+            mThread = ithread;\r
+            mCommand = command;\r
+\r
+            string title = ithread.getTitle().Trim();\r
+            if (title.Length > 20)\r
+                title = title.Substring(0, 20);\r
+\r
+            StackPanel sp = new StackPanel();\r
+            sp.Orientation = Orientation.Horizontal;\r
+\r
+\r
+            StackPanel panel = new StackPanel();\r
+            Border border = new Border();\r
+            border.BorderThickness = new System.Windows.Thickness(1);\r
+            border.BorderBrush = new SolidColorBrush(Colors.DarkGray);\r
+\r
+\r
+            ListBoxItem item1 = new ListBoxItem();\r
+\r
+            sp = new StackPanel();\r
+            sp.Children.Add(new TextBlock(new Run(title)));\r
+            item1.Content = sp;\r
+            item1.Padding = new System.Windows.Thickness(10, 2, 10, 2);\r
+            panel.Children.Add(item1);\r
+\r
+            sp = new StackPanel();\r
+            sp.Children.Add(new Separator());\r
+            item1 = new ListBoxItem();\r
+            item1.BorderBrush = new SolidColorBrush(Colors.LightGray);\r
+            item1.BorderThickness = new System.Windows.Thickness(1);\r
+            item1.Height = 1;\r
+            item1.Content = sp;\r
+            panel.Children.Add(item1);\r
+            panel.Background = new SolidColorBrush(Colors.White);\r
+\r
+\r
+            sp = new StackPanel();\r
+            sp.Children.Add(new TextBlock(new Run("類似スレを検索")));\r
+            sp.MouseLeftButtonDown += itemSearchSimilarTitle_MouseLeftButtonDown;\r
+            sp.Tag = ithread;\r
+            item1 = new ListBoxItem();\r
+            item1.Padding = new System.Windows.Thickness(10, 2, 10, 2);\r
+            item1.Content = sp;\r
+            panel.Children.Add(item1);\r
+\r
+            sp = new StackPanel();\r
+            sp.Children.Add(new TextBlock(new Run("ログを削除")));\r
+            sp.MouseLeftButtonDown += itemDeleteLog_MouseLeftButtonDown;\r
+            sp.Tag = ithread;\r
+            item1 = new ListBoxItem();\r
+            item1.Padding = new System.Windows.Thickness(10, 2, 10, 2);\r
+            item1.Content = sp;\r
+            if (!exsitsLog)\r
+                item1.IsEnabled = false;\r
+            panel.Children.Add(item1);\r
+\r
+            sp = new StackPanel();\r
+            sp.Children.Add(new TextBlock(new Run("次スレ作成")));\r
+            sp.MouseLeftButtonDown += itemCreateNextThread_MouseLeftButtonDown;\r
+            sp.Tag = ithread;\r
+            item1 = new ListBoxItem();\r
+            item1.Padding = new System.Windows.Thickness(10, 2, 10, 2);\r
+            item1.Content = sp;\r
+            panel.Children.Add(item1);\r
+\r
+            sp = new StackPanel();\r
+            sp.Children.Add(new TextBlock(new Run("アドレスを表示")));\r
+            sp.MouseLeftButtonDown += itemShowAddress_MouseLeftButtonDown;\r
+            sp.Tag = ithread;\r
+            item1 = new ListBoxItem();\r
+            item1.Padding = new System.Windows.Thickness(10, 2, 10, 2);\r
+            item1.Content = sp;\r
+            panel.Children.Add(item1);\r
+\r
+            sp = new StackPanel();\r
+            sp.Children.Add(new TextBlock(new Run("閉じる")));\r
+            sp.MouseLeftButtonDown += itemClose_MouseLeftButtonDown;\r
+            item1 = new ListBoxItem();\r
+            item1.Padding = new System.Windows.Thickness(10, 2, 10, 2);\r
+            item1.Content = sp;\r
+            panel.Children.Add(item1);\r
+            border.Child = panel;\r
+            this.Child = border;\r
+\r
+        }\r
+\r
+\r
+        public void show()\r
+        {\r
+            IsOpen = true;\r
+            Placement = PlacementMode.Mouse;\r
+            Focus();\r
+            this.StaysOpen = false;\r
+      \r
+        }\r
+\r
+        string parse2chAddress(string address, string dat)\r
+        {\r
+            if (address == null)\r
+                return string.Empty;\r
+\r
+            int len = address.Length;\r
+            if(len == 0)\r
+                return string.Empty;\r
+\r
+            string address1;\r
+            string dat1;\r
+            if (dat == null)\r
+                dat1 = string.Empty;\r
+            else\r
+                dat1 = dat;\r
+\r
+\r
+            int idx = address.IndexOf("machi.to");\r
+            if (idx >= 0)\r
+            {\r
+                idx += "machi.to".Length;\r
+                address1 = address.Substring(0, idx);\r
+                address1 += "/bbs/read.cgi" + address.Substring(idx);\r
+                idx = dat1.IndexOf(".cgi");\r
+                if (idx >= 0)\r
+                {\r
+                    dat1 = dat.Substring(0, idx) + "/";\r
+                }\r
+            }\r
+            else\r
+            {\r
+                idx = address.LastIndexOf('/', len - 2);\r
+                if (idx <= 0)\r
+                    return string.Empty;\r
+\r
+                address1 = address.Substring(0, idx);\r
+                address1 += "/test/read.cgi" + address.Substring(idx);\r
+                idx = dat1.IndexOf(".dat");\r
+                if (idx >= 0)\r
+                {\r
+                    dat1 = dat.Substring(0, idx) + "/";\r
+                }\r
+            }\r
+\r
+            if (dat != null)\r
+                address1 += dat1;\r
+\r
+            return address1;\r
+        }\r
+\r
+\r
+        void itemCreateNextThread_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)\r
+        {\r
+            IsOpen = false;\r
+\r
+            string msg;\r
+            IBoard iboard;\r
+\r
+            if (mThread != null)\r
+            {\r
+                string caption = mThread.getTitle();\r
+                iboard = mThread.getBoard();\r
+                if (iboard != null)\r
+                {\r
+                    string address = parse2chAddress(iboard.getAddress(), mThread.getDatName());\r
+                    msg = "前スレ\n" +\r
+                        caption + "\n" +\r
+                        address + "\n";\r
+                    mCommand.CreateThread(iboard, caption, msg);\r
+                }\r
+            }\r
+        }\r
+\r
+        void itemShowAddress_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)\r
+        {\r
+            IsOpen = false;\r
+\r
+            string caption = string.Empty;\r
+            string address = string.Empty;\r
+            if (mThread != null)\r
+            {\r
+                caption = mThread.getTitle();\r
+                IBoard iboard = mThread.getBoard();\r
+                if (iboard != null)\r
+                    address = parse2chAddress(iboard.getAddress(), mThread.getDatName());\r
+            }\r
+            mCommand.ShowThreadInfoWindow(caption, address);\r
+            //MessageBox.Show(address, caption);\r
+\r
+        }\r
+        void itemDeleteLog_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)\r
+        {\r
+            IsOpen = false;\r
+\r
+            mCommand.DeleteLog(mThread);\r
+\r
+        }\r
+\r
+        void itemSearchSimilarTitle_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)\r
+        {\r
+            IsOpen = false;\r
+\r
+            mCommand.SearchSimilarTitle(mThread);\r
+\r
+        }\r
+\r
+        void itemClose_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)\r
+        {\r
+            IsOpen = false;\r
+        }\r
+    }\r
+}\r
diff --git a/NT2chCtrl245/MenuItemPopup.cs b/NT2chCtrl245/MenuItemPopup.cs
new file mode 100755 (executable)
index 0000000..731021f
--- /dev/null
@@ -0,0 +1,181 @@
+using NT2chObject;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Windows.Controls;\r
+using System.Windows.Controls.Primitives;\r
+using System.Windows.Documents;\r
+using System.Windows.Media;\r
+\r
+namespace NT2chCtrl2\r
+{\r
+    class MenuItemPopup : Popup\r
+    {\r
\r
+        IBoard mBoard;\r
+        ICommand2 mCommand;\r
+\r
+        public MenuItemPopup(IBoard iboard, ICommand2 command, ICloseTab closeTab)\r
+            : base()\r
+        {\r
+            mBoard = iboard;\r
+            mCommand = command;\r
+            mCloseTab = closeTab;\r
+\r
+            StackPanel sp = new StackPanel();\r
+            sp.Orientation = Orientation.Horizontal;\r
+\r
+\r
+            StackPanel panel = new StackPanel();\r
+            Border border = new Border();\r
+            border.BorderThickness = new System.Windows.Thickness(1);\r
+            border.BorderBrush = new SolidColorBrush(Colors.DarkGray);\r
+\r
+\r
+            ListBoxItem item1 = new ListBoxItem();\r
+\r
+            sp = new StackPanel();\r
+            sp.Children.Add(new TextBlock(new Run(mBoard.getName())));\r
+            item1.Content = sp;\r
+            item1.Padding = new System.Windows.Thickness(10, 2, 10, 2);\r
+            panel.Children.Add(item1);\r
+\r
+            sp = new StackPanel();\r
+            sp.Children.Add(new Separator());\r
+            item1 = new ListBoxItem();\r
+            item1.BorderBrush = new SolidColorBrush(Colors.LightGray);\r
+            item1.BorderThickness = new System.Windows.Thickness(1);\r
+            item1.Height = 1;\r
+            item1.Content = sp;\r
+            panel.Children.Add(item1);\r
+            panel.Background = new SolidColorBrush(Colors.White);\r
+\r
+\r
+            sp = new StackPanel();\r
+            sp.Children.Add(new TextBlock(new Run("お気に入りに追加")));\r
+            sp.MouseLeftButtonDown += itemAddFavorite_MouseLeftButtonDown;\r
+            sp.Tag = mBoard.getName();\r
+            item1 = new ListBoxItem();\r
+            item1.Padding = new System.Windows.Thickness(10, 2, 10, 2);\r
+            item1.Content = sp;\r
+            panel.Children.Add(item1);\r
+\r
+            sp = new StackPanel();\r
+            sp.Children.Add(new TextBlock(new Run("板のログを全て削除")));\r
+            sp.MouseLeftButtonDown += itemDeleteLog_MouseLeftButtonDown;\r
+            sp.Tag = mBoard.getName();\r
+            item1 = new ListBoxItem();\r
+            item1.Padding = new System.Windows.Thickness(10, 2, 10, 2);\r
+            item1.Content = sp;\r
+            panel.Children.Add(item1);\r
+\r
+            sp = new StackPanel();\r
+            sp.Children.Add(new TextBlock(new Run("このタブ以外を閉じる")));\r
+            sp.MouseLeftButtonDown += CloseAllTabExceptThis_MouseLeftButtonDown;\r
+            sp.Tag = mBoard.getName();\r
+            item1 = new ListBoxItem();\r
+            item1.Padding = new System.Windows.Thickness(10, 2, 10, 2);\r
+            item1.Content = sp;\r
+            panel.Children.Add(item1);\r
+\r
+            sp = new StackPanel();\r
+            sp.Children.Add(new TextBlock(new Run("左側のタブを閉じる")));\r
+            sp.MouseLeftButtonDown += CloseTabOnTheLeft_MouseLeftButtonDown;\r
+            sp.Tag = mBoard.getName();\r
+            item1 = new ListBoxItem();\r
+            item1.Padding = new System.Windows.Thickness(10, 2, 10, 2);\r
+            item1.Content = sp;\r
+            panel.Children.Add(item1);\r
+\r
+            sp = new StackPanel();\r
+            sp.Children.Add(new TextBlock(new Run("右側のタブを閉じる")));\r
+            sp.MouseLeftButtonDown += CloseTabOnTheRight_MouseLeftButtonDown;\r
+            sp.Tag = mBoard.getName();\r
+            item1 = new ListBoxItem();\r
+            item1.Padding = new System.Windows.Thickness(10, 2, 10, 2);\r
+            item1.Content = sp;\r
+            panel.Children.Add(item1);\r
+\r
+            sp = new StackPanel();\r
+            sp.Children.Add(new TextBlock(new Run("全てのタブを閉じる")));\r
+            sp.MouseLeftButtonDown += CloseAllTab_MouseLeftButtonDown;\r
+            sp.Tag = mBoard.getName();\r
+            item1 = new ListBoxItem();\r
+            item1.Padding = new System.Windows.Thickness(10, 2, 10, 2);\r
+            item1.Content = sp;\r
+            panel.Children.Add(item1);\r
+\r
+            sp = new StackPanel();\r
+            sp.Children.Add(new TextBlock(new Run("閉じる")));\r
+            sp.MouseLeftButtonDown += itemClose_MouseLeftButtonDown;\r
+            item1 = new ListBoxItem();\r
+            item1.Padding = new System.Windows.Thickness(10, 2, 10, 2);\r
+            item1.Content = sp;\r
+            panel.Children.Add(item1);\r
+            border.Child = panel;\r
+            this.Child = border;\r
+\r
+        }\r
+\r
+\r
+        public void show()\r
+        {\r
+            IsOpen = true;\r
+            Placement = PlacementMode.Mouse;\r
+            Focus();\r
+            this.StaysOpen = false;\r
+      \r
+        }\r
+        void itemAddFavorite_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)\r
+        {\r
+            IsOpen = false;\r
+\r
+            mCommand.AddBoardToFavorite(mBoard);\r
+\r
+        }\r
+        void itemDeleteLog_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)\r
+        {\r
+            IsOpen = false;\r
+\r
+            mCommand.DeleteLog(mBoard);\r
+\r
+        }\r
+\r
+        ICloseTab mCloseTab;\r
+        public interface ICloseTab\r
+        {\r
+            void CloseAllExceptThis(IBoard iboard);\r
+            void CloseOnTheLeft(IBoard iboard);\r
+            void CloseOnTheRight(IBoard iboard);\r
+            void CloseAll();\r
+        }\r
+\r
+        void CloseAllTabExceptThis_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)\r
+        {\r
+            IsOpen = false;\r
+            mCloseTab.CloseAllExceptThis(mBoard);\r
+        }\r
+        void CloseTabOnTheLeft_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)\r
+        {\r
+            IsOpen = false;\r
+            mCloseTab.CloseOnTheLeft(mBoard);\r
+\r
+        }\r
+        void CloseTabOnTheRight_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)\r
+        {\r
+            IsOpen = false;\r
+            mCloseTab.CloseOnTheRight(mBoard);\r
+        }\r
+        void CloseAllTab_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)\r
+        {\r
+            IsOpen = false;\r
+            mCloseTab.CloseAll();\r
+        }\r
+\r
+\r
+        void itemClose_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)\r
+        {\r
+            IsOpen = false;\r
+        }\r
+    }\r
+}\r
diff --git a/NT2chCtrl245/NT2chCtrl245.csproj b/NT2chCtrl245/NT2chCtrl245.csproj
new file mode 100755 (executable)
index 0000000..9fbbc92
--- /dev/null
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />\r
+  <PropertyGroup>\r
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>\r
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>\r
+    <ProjectGuid>{8AB65B58-6B41-47DC-AA6F-6CA444180556}</ProjectGuid>\r
+    <OutputType>Library</OutputType>\r
+    <AppDesignerFolder>Properties</AppDesignerFolder>\r
+    <RootNamespace>NT2chCtrl245</RootNamespace>\r
+    <AssemblyName>NT2chCtrl245</AssemblyName>\r
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>\r
+    <FileAlignment>512</FileAlignment>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">\r
+    <DebugSymbols>true</DebugSymbols>\r
+    <DebugType>full</DebugType>\r
+    <Optimize>false</Optimize>\r
+    <OutputPath>bin\Debug\</OutputPath>\r
+    <DefineConstants>TRACE;DEBUG;DOTNET45</DefineConstants>\r
+    <ErrorReport>prompt</ErrorReport>\r
+    <WarningLevel>4</WarningLevel>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">\r
+    <DebugType>pdbonly</DebugType>\r
+    <Optimize>true</Optimize>\r
+    <OutputPath>bin\Release\</OutputPath>\r
+    <DefineConstants>TRACE;DOTNET45</DefineConstants>\r
+    <ErrorReport>prompt</ErrorReport>\r
+    <WarningLevel>4</WarningLevel>\r
+  </PropertyGroup>\r
+  <PropertyGroup>\r
+    <SignAssembly>false</SignAssembly>\r
+  </PropertyGroup>\r
+  <PropertyGroup>\r
+    <AssemblyOriginatorKeyFile>\r
+    </AssemblyOriginatorKeyFile>\r
+  </PropertyGroup>\r
+  <ItemGroup>\r
+    <Reference Include="PresentationCore" />\r
+    <Reference Include="PresentationFramework" />\r
+    <Reference Include="System" />\r
+    <Reference Include="System.Core" />\r
+    <Reference Include="System.Xaml" />\r
+    <Reference Include="System.Xml.Linq" />\r
+    <Reference Include="System.Data.DataSetExtensions" />\r
+    <Reference Include="Microsoft.CSharp" />\r
+    <Reference Include="System.Data" />\r
+    <Reference Include="System.Xml" />\r
+    <Reference Include="WindowsBase" />\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <Compile Include="DragDropData.cs" />\r
+    <Compile Include="FavoriteImageConverter.cs" />\r
+    <Compile Include="ListItemViewPopup.cs" />\r
+    <Compile Include="MenuItemPopup.cs" />\r
+    <Compile Include="NTBoardData.cs" />\r
+    <Compile Include="NTSubjectViewPanel.xaml.cs">\r
+      <DependentUpon>NTSubjectViewPanel.xaml</DependentUpon>\r
+    </Compile>\r
+    <Compile Include="NTSubjectViewPanel_event.cs" />\r
+    <Compile Include="NTSubjectViewPanel_persistent.cs" />\r
+    <Compile Include="NTSubjectViewPanel_util.cs" />\r
+    <Compile Include="ObjectImpl.cs" />\r
+    <Compile Include="Properties\AssemblyInfo.cs" />\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ProjectReference Include="..\NT2chObject45\NT2chObject45.csproj">\r
+      <Project>{4e9cecf8-7dea-45db-9b25-d3f768a10c4b}</Project>\r
+      <Name>NT2chObject45</Name>\r
+    </ProjectReference>\r
+    <ProjectReference Include="..\NT2chStyle45\NT2chStyle45.csproj">\r
+      <Project>{d9d1b7b7-3e6e-4ced-b16a-1677ba957f73}</Project>\r
+      <Name>NT2chStyle45</Name>\r
+    </ProjectReference>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <Page Include="NTSubjectViewPanel.xaml">\r
+      <Generator>MSBuild:Compile</Generator>\r
+      <SubType>Designer</SubType>\r
+    </Page>\r
+  </ItemGroup>\r
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />\r
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. \r
+       Other similar extension points exist, see Microsoft.Common.targets.\r
+  <Target Name="BeforeBuild">\r
+  </Target>\r
+  <Target Name="AfterBuild">\r
+  </Target>\r
+  -->\r
+</Project>
\ No newline at end of file
diff --git a/NT2chCtrl245/NTBoardData.cs b/NT2chCtrl245/NTBoardData.cs
new file mode 100755 (executable)
index 0000000..37a6347
--- /dev/null
@@ -0,0 +1,61 @@
+using NT2chCtrl2;\r
+using NT2chObject;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Windows.Media;\r
+\r
+namespace NT2chCtrl2\r
+{\r
+    class NTBoardData\r
+    {\r
+        bool mDummy;\r
+        public IBoard mBoard;\r
+        double mWidth;\r
+        string mName;\r
+        Brush mBrush;\r
+        public NTBoardData(IBoard iboard)\r
+        {\r
+            mBoard = iboard;\r
+            if (iboard != null)\r
+                mName = iboard.getName();\r
+            else\r
+                mName = " ";\r
+            mDummy = false;\r
+            mWidth = 100;\r
+            mBrush = null;\r
+        }\r
+\r
+        static NTBoardData mDummyData = null;\r
+        public static NTBoardData getDummy()\r
+        {\r
+            if (mDummyData == null)\r
+            {\r
+                NTBoardData data = new NTBoardData(null);\r
+                data.mDummy = true;\r
+                data.mWidth = 10;\r
+                mDummyData = data;\r
+                data.mBrush = new SolidColorBrush(Colors.Yellow);\r
+            }\r
+            return mDummyData;        \r
+        }\r
+\r
+        public bool IsDummy()\r
+        {\r
+            return mDummy;\r
+        }\r
+\r
+        public string BoardName\r
+        {\r
+            get { return mName; }\r
+        }\r
+        public double Width\r
+        {\r
+            get { return mWidth; }\r
+        }\r
+        public Brush Background\r
+        {\r
+            get { return mBrush; }\r
+        }\r
+    }\r
+}\r
diff --git a/NT2chCtrl245/NTSubjectViewPanel.xaml b/NT2chCtrl245/NTSubjectViewPanel.xaml
new file mode 100755 (executable)
index 0000000..c27d2b1
--- /dev/null
@@ -0,0 +1,171 @@
+<UserControl x:Class="NT2chCtrl2.NTSubjectViewPanel"\r
+             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"\r
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"\r
+             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" \r
+             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" \r
+             xmlns:local="clr-namespace:NT2chCtrl2"\r
+             mc:Ignorable="d" \r
+             d:DesignHeight="250" d:DesignWidth="800" Loaded="NTSubjectViewPanel_Loaded">\r
+    <UserControl.Resources>\r
+        <local:FavoriteImageConverter x:Key="FavoriteImageConverter" />\r
+        <DataTemplate x:Key="MenuItemTemplate">\r
+            <Border BorderThickness="1" BorderBrush="SteelBlue" CornerRadius="2"\r
+                    >\r
+                <Grid Width="{Binding Path=Width}" \r
+                      Background="{Binding Path=Background, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem}}}">\r
+                    <TextBlock Text="{Binding Path=BoardName}" VerticalAlignment="Center" HorizontalAlignment="Center" \r
+                               Foreground="{Binding Path=Foreground, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem}}}"\r
+                               MouseLeftButtonDown="MenuItem_MouseLeftButtonDown" \r
+                               MouseMove="MenuItem_MouseMove" \r
+                               MouseLeftButtonUp="MenuItem_MouseLeftButtonUp" \r
+                               DragOver="MenuItem_DragOver"\r
+                               DragEnter="MenuItem_DragEnter"\r
+                               AllowDrop="True"\r
+                               Tag="{Binding}"\r
+                               MouseRightButtonUp="MenuItem_MouseRightButtonUp"\r
+                               Focusable="False"\r
+                               Padding="20,0"/>\r
+                    <Button x:Name="btnMenuClose" Click="MenuItemClose_Click"\r
+                            Background="Transparent"\r
+                            Tag="{Binding}" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="0,0,5,0">\r
+                        <Button.Content>\r
+                            <Image Source="/NT2chStyle45;component/images/close_tab.png" Stretch="None"/>\r
+                        </Button.Content>\r
+                    </Button>\r
+                    <TextBlock Text=" " Width="10"\r
+                               DragOver="MenuItem_DragOver"\r
+                               DragEnter="MenuItem_DragEnter"\r
+                               Drop="MenuItem_Drop"\r
+                               Tag="{Binding}"\r
+                               AllowDrop="True"\r
+                               HorizontalAlignment="Left" Margin="0"/>\r
+                </Grid>\r
+            </Border>\r
+            <DataTemplate.Triggers>\r
+                <Trigger Property="IsMouseOver" Value="False">\r
+                    <Setter TargetName="btnMenuClose" Property="Visibility"\r
+                                   Value="Collapsed"/>\r
+                </Trigger>\r
+            </DataTemplate.Triggers>\r
+        </DataTemplate>\r
+    </UserControl.Resources>\r
+    <Grid>\r
+        <Grid.RowDefinitions>\r
+            <RowDefinition Height="Auto"/>\r
+            <RowDefinition Height="*"/>\r
+        </Grid.RowDefinitions>\r
+        <ListBox x:Name="mLstMenu"\r
+                 Background="{StaticResource SubjectViewBkBrush}"\r
+                 Foreground="{StaticResource SubjectViewForeBrush}"\r
+                 ItemTemplate="{StaticResource MenuItemTemplate}"\r
+                 ScrollViewer.HorizontalScrollBarVisibility="Disabled">\r
+            <ListBox.ItemContainerStyle>\r
+                <Style>\r
+                    <Style.Triggers>\r
+                        <Trigger Property="ListBoxItem.IsSelected" Value="True">\r
+                            <Setter Property="ListBoxItem.Background" Value="{StaticResource SubjectViewSelectedItemBkBrush}" />\r
+                            <Setter Property="ListBoxItem.Foreground" Value="{StaticResource SubjectViewSelectedItemForeBrush}" />\r
+                        </Trigger>\r
+                    </Style.Triggers>\r
+                </Style>\r
+            </ListBox.ItemContainerStyle>\r
+            <ListBox.ItemsPanel>\r
+                <ItemsPanelTemplate>\r
+                    <WrapPanel />\r
+                </ItemsPanelTemplate>\r
+            </ListBox.ItemsPanel>\r
+        </ListBox>\r
+        <ListView x:Name="mLstThreadTitle" Grid.Row="1" \r
+                  MouseLeftButtonUp="ListViewItem_MouseLeftButtonUp"\r
+                  AlternationCount="1">\r
+            <ListView.View>\r
+                <GridView>\r
+                    <GridViewColumn DisplayMemberBinding="{Binding Path=SeqNo}">\r
+                        <GridViewColumn.HeaderTemplate>\r
+                            <DataTemplate>\r
+                                <TextBlock Text=" No " Tag="SeqNo"\r
+                                           MouseLeftButtonDown="ColumnHeader_MouseLeftButtonDown"/>\r
+                            </DataTemplate>\r
+                        </GridViewColumn.HeaderTemplate>\r
+                    </GridViewColumn>\r
+                    <GridViewColumn>\r
+                        <GridViewColumn.HeaderTemplate>\r
+                            <DataTemplate>\r
+                                <TextBlock Text="F" Tag="F"\r
+                                           MouseLeftButtonDown="ColumnHeader_MouseLeftButtonDown"/>\r
+                            </DataTemplate>\r
+                        </GridViewColumn.HeaderTemplate>\r
+                        <GridViewColumn.CellTemplate>\r
+                            <DataTemplate>\r
+                                <Button Click="FavoriteImage_Click" Tag="{Binding}" Background="Transparent"\r
+                                        BorderBrush="Transparent">\r
+                                    <Grid>\r
+                                        <Image Source="{Binding Path=IsFavorite, \r
+                                                Converter={StaticResource FavoriteImageConverter}}"/>\r
+                                    </Grid>\r
+                                </Button>\r
+                            </DataTemplate>\r
+                        </GridViewColumn.CellTemplate>\r
+                    </GridViewColumn>\r
+                    <GridViewColumn Width="400">\r
+                        <GridViewColumn.HeaderTemplate>\r
+                            <DataTemplate>\r
+                                <TextBlock Text="スレッドタイトル" Tag="Title"\r
+                                           MouseLeftButtonDown="ColumnHeader_MouseLeftButtonDown"/>\r
+                            </DataTemplate>\r
+                        </GridViewColumn.HeaderTemplate>\r
+                        <GridViewColumn.CellTemplate>\r
+                            <DataTemplate>\r
+                                <TextBlock Text="{Binding Path=Title}" \r
+                                           MouseLeftButtonUp="ListViewItem_MouseLeftButtonUp" \r
+                                           MouseRightButtonUp="ListViewItem_MouseRightButtonUp" \r
+                                           ToolTip="{Binding Path=Title}"\r
+                                           Tag="{Binding}"/>\r
+                            </DataTemplate>\r
+                        </GridViewColumn.CellTemplate>\r
+                    </GridViewColumn>\r
+                    <GridViewColumn DisplayMemberBinding="{Binding Path=ResCnt}">\r
+                        <GridViewColumn.HeaderTemplate>\r
+                            <DataTemplate>\r
+                                <TextBlock Text="レス数" Tag="ResCnt"\r
+                                           MouseLeftButtonDown="ColumnHeader_MouseLeftButtonDown"/>\r
+                            </DataTemplate>\r
+                        </GridViewColumn.HeaderTemplate>\r
+                    </GridViewColumn>\r
+                    <GridViewColumn DisplayMemberBinding="{Binding Path=ReadCnt}">\r
+                        <GridViewColumn.HeaderTemplate>\r
+                            <DataTemplate>\r
+                                <TextBlock Text=" 既読 " Tag="ReadCnt"\r
+                                           MouseLeftButtonDown="ColumnHeader_MouseLeftButtonDown"/>\r
+                            </DataTemplate>\r
+                        </GridViewColumn.HeaderTemplate>\r
+                    </GridViewColumn>\r
+                    <GridViewColumn DisplayMemberBinding="{Binding Path=RemainCnt}">\r
+                        <GridViewColumn.HeaderTemplate>\r
+                            <DataTemplate>\r
+                                <TextBlock Text=" 未読 " Tag="RemainCnt"\r
+                                           MouseLeftButtonDown="ColumnHeader_MouseLeftButtonDown"/>\r
+                            </DataTemplate>\r
+                        </GridViewColumn.HeaderTemplate>\r
+                    </GridViewColumn>\r
+                    <GridViewColumn DisplayMemberBinding="{Binding Path=LastMod}">\r
+                        <GridViewColumn.HeaderTemplate>\r
+                            <DataTemplate>\r
+                                <TextBlock Text=" 最終取得日 " Tag="LastMod"\r
+                                           MouseLeftButtonDown="ColumnHeader_MouseLeftButtonDown"/>\r
+                            </DataTemplate>\r
+                        </GridViewColumn.HeaderTemplate>\r
+                    </GridViewColumn>\r
+                    <GridViewColumn DisplayMemberBinding="{Binding Path=LastWrite}" >\r
+                        <GridViewColumn.HeaderTemplate>\r
+                            <DataTemplate>\r
+                                <TextBlock Text=" 最終書込日 " Tag="LastWrite"\r
+                                           MouseLeftButtonDown="ColumnHeader_MouseLeftButtonDown"/>\r
+                            </DataTemplate>\r
+                        </GridViewColumn.HeaderTemplate>\r
+                    </GridViewColumn>\r
+                </GridView>\r
+            </ListView.View>\r
+        </ListView>\r
+    </Grid>\r
+</UserControl>\r
diff --git a/NT2chCtrl245/NTSubjectViewPanel.xaml.cs b/NT2chCtrl245/NTSubjectViewPanel.xaml.cs
new file mode 100755 (executable)
index 0000000..05f68bd
--- /dev/null
@@ -0,0 +1,35 @@
+using NT2chCtrl2;\r
+using NT2chObject;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Windows;\r
+using System.Windows.Controls;\r
+using System.Windows.Data;\r
+using System.Windows.Documents;\r
+using System.Windows.Input;\r
+using System.Windows.Media;\r
+using System.Windows.Media.Imaging;\r
+using System.Windows.Navigation;\r
+using System.Windows.Shapes;\r
+\r
+namespace NT2chCtrl2\r
+{\r
+    /// <summary>\r
+    /// NTSubjectViewPanel.xaml の相互作用ロジック\r
+    /// </summary>\r
+    public partial class NTSubjectViewPanel : UserControl, ISubjectView, ISubjectViewJump\r
+    {\r
+        public NTSubjectViewPanel()\r
+        {\r
+            InitializeComponent();\r
+        }\r
+\r
+\r
+        private void NTSubjectViewPanel_Loaded(object sender, RoutedEventArgs e)\r
+        {\r
+        }\r
+\r
+\r
+    }\r
+}\r
diff --git a/NT2chCtrl245/NTSubjectViewPanel_event.cs b/NT2chCtrl245/NTSubjectViewPanel_event.cs
new file mode 100755 (executable)
index 0000000..ded1d58
--- /dev/null
@@ -0,0 +1,531 @@
+using NT2chCtrl2;\r
+using NT2chObject;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Collections.ObjectModel;\r
+using System.Text;\r
+using System.Windows;\r
+using System.Windows.Controls;\r
+using System.Windows.Input;\r
+\r
+namespace NT2chCtrl2\r
+{\r
+    public partial class NTSubjectViewPanel : UserControl, ISubjectView\r
+    {\r
+        private void MenuItemClose_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            Button btn = sender as Button;\r
+            if (btn == null)\r
+                return;\r
+\r
+            NTBoardData data = btn.Tag as NTBoardData;\r
+            if (data == null)\r
+                return;\r
+\r
+            int idx = mBoardList.IndexOf(data);\r
+            if(idx < 0)\r
+                return;\r
+\r
+            mBoardList.RemoveAt(idx);\r
+\r
+\r
+            ObservableCollection<NTThread> orgList = mLstThreadTitle.ItemsSource as ObservableCollection<NTThread>;\r
+            if (orgList == null)\r
+                return;\r
+\r
+            int cnt = mBoardList.Count;\r
+            if(idx == cnt)\r
+                idx--;\r
+\r
+            if (idx < 0)\r
+            {\r
+                orgList.Clear();\r
+            }\r
+            else\r
+            {\r
+                data = mBoardList[idx];\r
+                mCommand.TryToOpenBoard(data.mBoard);\r
+            }\r
+        }\r
+\r
+        private void ListViewItem_MouseRightButtonUp(object sender, MouseButtonEventArgs e)\r
+        {\r
+            TextBlock tb = sender as TextBlock;\r
+            if (tb == null)\r
+                return;\r
+\r
+            NTThread thread = tb.Tag as NTThread;\r
+            if (thread == null)\r
+                return;\r
+\r
+            bool existsLog = thread.ReadCnt > 0;\r
+\r
+            IThread2 ithread = findThread(thread) as IThread2;\r
+            if (ithread == null)\r
+                return;\r
+\r
+            ListItemViewPopup popup = new ListItemViewPopup(ithread, mCommand, existsLog);\r
+            popup.show();\r
+        }\r
+\r
+        IThread findThread(NTThread thread)\r
+        {\r
+            List<IThread> list = mCurrentBoard.getThreadList();\r
+            foreach (IThread ithread in list)\r
+            {\r
+                if(ithread.getDatName().Equals(thread.getDatName()))\r
+                    return ithread;\r
+            }\r
+            return null;\r
+        }\r
+        private void MenuItem_MouseRightButtonUp(object sender, MouseButtonEventArgs e)\r
+        {\r
+            TextBlock tb = sender as TextBlock;\r
+            if (tb == null)\r
+                return;\r
+\r
+            NTBoardData data = tb.Tag as NTBoardData;\r
+            if (data == null)\r
+                return;\r
+\r
+            MenuItemPopup popup = new MenuItemPopup(data.mBoard, mCommand, new CloseTab(this));\r
+            popup.show();\r
+        }\r
+\r
+        class CloseTab : NT2chCtrl2.MenuItemPopup.ICloseTab\r
+        {\r
+            NTSubjectViewPanel mParent;\r
+            public CloseTab(NTSubjectViewPanel panel)\r
+            {\r
+                mParent = panel;\r
+            }\r
+            public void CloseAllExceptThis(IBoard iboard)\r
+            {\r
+                int len = mParent.mBoardList.Count;\r
+                NTBoardData data = null;\r
+                int idx = 0;\r
+                for (; idx < len; idx++)\r
+                {\r
+                    data = mParent.mBoardList[idx];\r
+                    if (iboard.getName().Equals(data.BoardName))\r
+                    {\r
+                        break;\r
+                    }\r
+                }\r
+                if (idx == len)\r
+                    return;\r
+\r
+                mParent.mBoardList.Clear();\r
+                mParent.mBoardList.Add(data);\r
+                mParent.mCommand.TryToOpenBoard(data.mBoard);\r
+            }\r
+\r
+            public void CloseOnTheLeft(IBoard iboard)\r
+            {\r
+                int len = mParent.mBoardList.Count;\r
+                NTBoardData data = null;\r
+                int idx = 0;\r
+                for (; idx < len; idx++)\r
+                {\r
+                    data = mParent.mBoardList[idx];\r
+                    if (iboard.getName().Equals(data.BoardName))\r
+                    {\r
+                        break;\r
+                    }\r
+                }\r
+                if (idx == len)\r
+                    return;\r
+                for (int i = 0; i < idx; i++)\r
+                {\r
+                    mParent.mBoardList.RemoveAt(0);\r
+                }\r
+                mParent.mCommand.TryToOpenBoard(data.mBoard);\r
+            }\r
+\r
+            public void CloseOnTheRight(IBoard iboard)\r
+            {\r
+                int len = mParent.mBoardList.Count;\r
+                NTBoardData data = null;\r
+                int idx = 0;\r
+                for (; idx < len; idx++)\r
+                {\r
+                    data = mParent.mBoardList[idx];\r
+                    if (iboard.getName().Equals(data.BoardName))\r
+                    {\r
+                        break;\r
+                    }\r
+                }\r
+                if (idx == len)\r
+                    return;\r
+                for (int i = idx+1; i < len; i++)\r
+                {\r
+                    mParent.mBoardList.RemoveAt(idx+1);\r
+                }\r
+                mParent.mCommand.TryToOpenBoard(data.mBoard);\r
+            }\r
+\r
+            public void CloseAll()\r
+            {\r
+                ObservableCollection<NTThread> orgList = \r
+                    mParent.mLstThreadTitle.ItemsSource as ObservableCollection<NTThread>;\r
+                if (orgList == null)\r
+                    return;\r
+                mParent.mBoardList.Clear();\r
+                orgList.Clear();\r
+            }\r
\r
+        }\r
+\r
+        NTBoardData mObserveDragData = null;\r
+        Point mObserveMousePoint;\r
+        DateTime mClickedTime = DateTime.Now;\r
+        TextBlock mClickedTextBlock = null;\r
+\r
+        private bool chkDblClick(TextBlock tb)\r
+        {\r
+            DateTime dt = DateTime.Now;\r
+            TimeSpan ts = dt.Subtract(mClickedTime);\r
+            if((0 != ((int)(ts.TotalSeconds))) || \r
+                mClickedTextBlock == null ||\r
+                !mClickedTextBlock.Equals(tb))\r
+            {\r
+                mClickedTextBlock = tb;\r
+                mClickedTime = DateTime.Now;\r
+                return false;\r
+            }\r
+            return true;\r
+        }\r
+\r
+        private void MenuItem_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)\r
+        {\r
+            TextBlock tb = sender as TextBlock;\r
+            if (tb == null)\r
+                return;\r
+\r
+            NTBoardData data = tb.Tag as NTBoardData;\r
+            if (data == null)\r
+                return;\r
+            if (chkDblClick(tb))\r
+            {\r
+                mObserveDragData = null;\r
+                mCommand.UpdateBoard(data.mBoard);\r
+                return;\r
+            }\r
+            mObserveDragData = data;\r
+            mObserveMousePoint = e.GetPosition(tb);\r
+\r
+            //e.Handled = true;\r
+        }\r
+        \r
+        private void MenuItem_MouseMove(object sender, MouseEventArgs e)\r
+        {\r
+            if (mObserveDragData == null)\r
+                return;\r
+\r
+            TextBlock tb = sender as TextBlock;\r
+            if (tb == null)\r
+                return;\r
+\r
+            NTBoardData data = tb.Tag as NTBoardData;\r
+            if (data == null)\r
+                return;\r
+\r
+            Point point = e.GetPosition(tb);\r
+            Vector v = Point.Subtract(point, mObserveMousePoint);\r
+            if (v.Length > DragDropData.DRAG_START_MOVE_DELTA)\r
+            {\r
+                DataObject dObj = new DataObject(\r
+                    DragDropData.BOARD_MENU_ITEM_DRAG_DATA, mObserveDragData);\r
+                DragDrop.DoDragDrop(tb, dObj, DragDropEffects.Move);\r
+                //e.Handled = true;\r
+                mObserveDragData = null;\r
+\r
+                removeDummyData();\r
+            }\r
+\r
+        }\r
+\r
+        void MenuItem_DragEnter(object sender, DragEventArgs e)\r
+        {\r
+        //    e.Effects = DragDropEffects.Move;\r
+        //    e.Handled = true;\r
+        }\r
+\r
+        void MenuItem_DragOver(object sender, DragEventArgs e)\r
+        {\r
+            TextBlock tb = sender as TextBlock;\r
+            if (tb == null)\r
+                return;\r
+\r
+            NTBoardData data = tb.Tag as NTBoardData;\r
+            if (data == null)\r
+                return;\r
+\r
+            string text = tb.Text.Trim();\r
+            if (text.Length > 0)\r
+            {\r
+                removeDummyData();\r
+                return;\r
+            }\r
+            //Point point = e.GetPosition(tb);\r
+            //if(point.X < 20)\r
+            e.Effects = DragDropEffects.Move;\r
+            //else\r
+            //    e.Effects = DragDropEffects.None;\r
+            e.Handled = true;\r
+\r
+            insertDummyData(data);\r
+\r
+        }\r
+\r
+        \r
+        void MenuItem_Drop(object sender, DragEventArgs e)\r
+        {\r
+            \r
+            TextBlock tb = sender as TextBlock;\r
+            if (tb == null)\r
+                return;\r
+\r
+            NTBoardData target = tb.Tag as NTBoardData;\r
+            if (target == null)\r
+                return;\r
+\r
+            string text = tb.Text.Trim();\r
+            if (text.Length > 0)\r
+            {\r
+                removeDummyData();\r
+                return;\r
+            }\r
+          \r
+            IDataObject dataObj = e.Data;\r
+\r
+            if (!dataObj.GetDataPresent(DragDropData.BOARD_MENU_ITEM_DRAG_DATA))\r
+                return;\r
+\r
+            NTBoardData source =\r
+                    dataObj.GetData(DragDropData.BOARD_MENU_ITEM_DRAG_DATA)\r
+                    as NTBoardData;\r
+            if (source == null)\r
+                return;\r
+\r
+            int targetIdx = mBoardList.IndexOf(target);\r
+            int sourceIdx = mBoardList.IndexOf(source);\r
+            if (targetIdx < 0 || sourceIdx < 0)\r
+                return;\r
+\r
+            mBoardList.RemoveAt(sourceIdx);\r
+\r
+            if (targetIdx > sourceIdx)\r
+                targetIdx--;\r
+\r
+            mBoardList.Insert(targetIdx, source);\r
+\r
+            removeDummyData();\r
+            e.Effects = DragDropEffects.Move;\r
+            e.Handled = true;\r
+        }\r
+\r
+        void insertDummyData(NTBoardData target)\r
+        {\r
+            NTBoardData dummy = NTBoardData.getDummy();\r
+            int targetIdx = mBoardList.IndexOf(target);\r
+            if(targetIdx < 0)\r
+                return;\r
+            int dummyIdx = mBoardList.IndexOf(dummy);\r
+            if (dummyIdx >= 0)\r
+            {\r
+                mBoardList.RemoveAt(dummyIdx);\r
+\r
+                if (dummyIdx < targetIdx)\r
+                {\r
+                    targetIdx--;\r
+                }\r
+            }\r
+            mBoardList.Insert(targetIdx, dummy);\r
+        }\r
+\r
+        void removeDummyData()\r
+        {\r
+            NTBoardData dummy = NTBoardData.getDummy();\r
+            mBoardList.Remove(dummy);\r
+        }\r
+\r
+        private void MenuItem_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)\r
+        {\r
+            if (mObserveDragData != null)\r
+            {\r
+                mObserveDragData = null;\r
+            }\r
+\r
+            TextBlock tb = sender as TextBlock;\r
+            if (tb == null)\r
+                return;\r
+\r
+            NTBoardData data = tb.Tag as NTBoardData;\r
+            if (data == null)\r
+                return;\r
+\r
+            IBoard iboard = data.mBoard;\r
+            mCommand.TryToOpenBoard(iboard);\r
+        }\r
+\r
+        private void ListViewItem_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)\r
+        {\r
+            TextBlock tb = sender as TextBlock;\r
+            if (tb == null)\r
+                return;\r
+\r
+            NTThread thread = tb.Tag as NTThread;\r
+            if (thread == null)\r
+                return;\r
+\r
+            ThreadDescrption description = getThreadDescription(thread);\r
+            if (description != null)\r
+                mCommand.OpenThread(description);\r
+\r
+        }\r
+\r
+        void FavoriteImage_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            Button btn = sender as Button;\r
+            if(btn == null)\r
+                return;\r
+      \r
+            NTThread thread = btn.Tag as NTThread;\r
+            if (thread == null)\r
+                return;\r
+\r
+            ThreadDescrption threadDesc = getThreadDescription(thread);\r
+            if (threadDesc == null)\r
+                return;\r
+\r
+            bool favorite = !thread.IsFavorite;\r
+            if (favorite)\r
+            {\r
+                if (mCommand.AddThreadToFavorite(threadDesc))\r
+                    thread.IsFavorite = favorite;\r
+            }\r
+            else\r
+            {\r
+                if (mCommand.RemoveThreadFromFavorite(threadDesc))\r
+                    thread.IsFavorite = favorite;\r
+            }\r
+        }\r
+\r
+        void ColumnHeader_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)\r
+        {\r
+            TextBlock tb = sender as TextBlock;\r
+            if (tb == null)\r
+                return;\r
+\r
+            string tag = tb.Tag as string;\r
+            if (tag == null)\r
+                return;\r
+\r
+            ObservableCollection<NTThread> orgList = mLstThreadTitle.ItemsSource as ObservableCollection<NTThread>;\r
+            if (orgList == null)\r
+                return;\r
+\r
+            List<NTThread> list = new List<NTThread>();\r
+\r
+            foreach (NTThread thread in orgList)\r
+                list.Add(thread);\r
+\r
+            //Console.Out.WriteLine(tag);\r
+            switch (tag)\r
+            {\r
+                case "SeqNo":\r
+                    list.Sort(SubjectListSortBySeqNo);\r
+                    break;\r
+                case "F":\r
+                    list.Sort(SubjectListSortByIsFavorite);\r
+                    break;\r
+                case "Title":\r
+                    list.Sort(SubjectListSortByTitle);\r
+                    break;\r
+                case "ResCnt":\r
+                    list.Sort(SubjectListSortByResCnt);\r
+                    break;\r
+                case "ReadCnt":\r
+                    list.Sort(SubjectListSortByReadCnt);\r
+                    break;\r
+                case "RemainCnt":\r
+                    list.Sort(SubjectListSortByRemainCnt);\r
+                    break;\r
+                case "LastMod":\r
+                    list.Sort(SubjectListSortByLastMod);\r
+                    break;\r
+                case "LastWrite":\r
+                    list.Sort(SubjectListSortByLastWrite);\r
+                    break;\r
+            }\r
+\r
+            orgList.Clear();\r
+            foreach (NTThread thread in list)\r
+                orgList.Add(thread);\r
+        }\r
+        static int SubjectListSortBySeqNo(NTThread thread1, NTThread thread2)\r
+        {\r
+            return thread1.SeqNo - thread2.SeqNo;\r
+        }\r
+\r
+        static int SubjectListSortByIsFavorite(NTThread thread1, NTThread thread2)\r
+        {\r
+            if(thread1.IsFavorite == thread2.IsFavorite)\r
+                return 0;\r
+            return thread1.IsFavorite ? -1 : 1;\r
+        }\r
+\r
+        static int SubjectListSortByTitle(NTThread thread1, NTThread thread2)\r
+        {\r
+            return thread2.Title.CompareTo(thread1.Title);\r
+        }\r
+        static int SubjectListSortByResCnt(NTThread thread1, NTThread thread2)\r
+        {\r
+            return thread2.ResCnt - thread1.ResCnt;\r
+        }\r
+        static int SubjectListSortByReadCnt(NTThread thread1, NTThread thread2)\r
+        {\r
+            return thread2.ReadCnt - thread1.ReadCnt;\r
+        }\r
+        static int SubjectListSortByRemainCnt(NTThread thread1, NTThread thread2)\r
+        {\r
+            return thread2.RemainCnt - thread1.RemainCnt;\r
+        }\r
+        static int SubjectListSortByLastMod(NTThread thread1, NTThread thread2)\r
+        {\r
+            DateTime dt1 = DateTime.MinValue;\r
+            DateTime dt2 = DateTime.MinValue;\r
+            try\r
+            {\r
+                dt1 = DateTime.Parse(thread1.LastMod);\r
+            }\r
+            catch { }\r
+            try\r
+            {\r
+                dt2 = DateTime.Parse(thread2.LastMod);\r
+            }\r
+            catch { }\r
+\r
+            return dt2.CompareTo(dt1);\r
+        }\r
+\r
+        static int SubjectListSortByLastWrite(NTThread thread1, NTThread thread2)\r
+        {\r
+            DateTime dt1 = DateTime.MinValue;\r
+            DateTime dt2 = DateTime.MinValue;\r
+            try\r
+            {\r
+                dt1 = DateTime.Parse(thread1.LastWrite);\r
+            }\r
+            catch { }\r
+            try\r
+            {\r
+                dt2 = DateTime.Parse(thread2.LastWrite);\r
+            }\r
+            catch { }\r
+\r
+            return dt2.CompareTo(dt1);\r
+        }\r
+    }\r
+}\r
diff --git a/NT2chCtrl245/NTSubjectViewPanel_persistent.cs b/NT2chCtrl245/NTSubjectViewPanel_persistent.cs
new file mode 100755 (executable)
index 0000000..bd8dd1f
--- /dev/null
@@ -0,0 +1,115 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.IO;\r
+using System.Text;\r
+using System.Windows.Controls;\r
+using NT2chObject;\r
+\r
+namespace NT2chCtrl2\r
+{\r
+    public partial class NTSubjectViewPanel : UserControl, ISubjectView\r
+    {\r
+        private string mDataFilePath;\r
+        private const string CONTROL_DATA_PATH = @"\NT2chCtrl2.txt";\r
+        static char[] COMMA_CHAR = new char[] { ',' };\r
+\r
+        void saveData()\r
+        {\r
+            if (null == mDataFilePath)\r
+                return;\r
+\r
+            StringBuilder sb = new StringBuilder();\r
+\r
+            GridView gv = mLstThreadTitle.View as GridView;\r
+            if (gv != null)\r
+            {\r
+                int count = gv.Columns.Count;\r
+                for (int i = 0; i < count; i++)\r
+                {\r
+                    if (i != 0)\r
+                        sb.Append(",");\r
+                    GridViewColumn gvc = gv.Columns[i];\r
+                    sb.Append(gvc.ActualWidth);\r
+                }\r
+            }\r
+\r
+            FileStream fs = null;\r
+            try\r
+            {\r
+                fs = File.Open(mDataFilePath, FileMode.Create, FileAccess.Write);\r
+                StreamWriter sw = new StreamWriter(fs);\r
+\r
+                sw.WriteLine(sb.ToString());\r
+                sw.Flush();\r
+                fs.Flush();\r
+                fs.Close();\r
+                fs = null;\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                System.Diagnostics.Debug.WriteLine(e.StackTrace);\r
+            }\r
+            finally\r
+            {\r
+                if (null != fs)\r
+                    fs.Close();\r
+            }\r
+        }\r
+        bool loadData(string rootPath)\r
+        {\r
+            mDataFilePath = null;\r
+            if (rootPath == null)\r
+                return false;\r
+            \r
+            mDataFilePath = rootPath + CONTROL_DATA_PATH;\r
+\r
+            string line = null;\r
+\r
+            FileStream fs = null;\r
+            try\r
+            {\r
+                fs = File.Open(mDataFilePath, FileMode.Open, FileAccess.Read);\r
+                StreamReader sr = new StreamReader(fs);\r
+\r
+                line = sr.ReadLine();\r
+\r
+                fs.Close();\r
+                fs = null;\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                System.Diagnostics.Debug.WriteLine(e.StackTrace);\r
+            }\r
+            finally\r
+            {\r
+                if (null != fs)\r
+                    fs.Close();\r
+            }\r
+\r
+            if (line == null)\r
+                return true;\r
+\r
+\r
+            string[] lines = line.Split(COMMA_CHAR);\r
+            int lineLen = lines.Length;\r
+\r
+            GridView gv  = mLstThreadTitle.View as GridView;\r
+            if (gv != null)\r
+            {\r
+                int nVal;\r
+                int count = gv.Columns.Count;\r
+                count = Math.Min(count, lineLen);\r
+                for (int i = 0; i < count; i++)\r
+                {\r
+                    if (int.TryParse(lines[i], out nVal))\r
+                    {\r
+                        GridViewColumn gvc = gv.Columns[i];\r
+                        gvc.Width = nVal;\r
+                    }\r
+                }\r
+            }\r
+            return true;\r
+        }\r
+\r
+    }\r
+}\r
diff --git a/NT2chCtrl245/NTSubjectViewPanel_util.cs b/NT2chCtrl245/NTSubjectViewPanel_util.cs
new file mode 100755 (executable)
index 0000000..26b2d44
--- /dev/null
@@ -0,0 +1,156 @@
+using NT2chCtrl2;\r
+using NT2chObject;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Collections.ObjectModel;\r
+using System.Text;\r
+using System.Windows.Controls;\r
+\r
+namespace NT2chCtrl2\r
+{\r
+    public partial class NTSubjectViewPanel : UserControl, ISubjectView\r
+    {\r
+        private IUtil mUtil;\r
+        private ICommand2 mCommand;\r
+        private Dictionary<PREF_PARAM, object> mDict;\r
+        private ObservableCollection<NTBoardData> mBoardList = new ObservableCollection<NTBoardData>();\r
+        private IBoard mCurrentBoard;\r
+\r
+\r
+        public IBoard GetCurrentBoard()\r
+        {\r
+            return mCurrentBoard;\r
+        }\r
+        //フレームワークから呼ばれます。先頭のレスにジャンプしてください。\r
+        public void JumpToTop()\r
+        {\r
+            if (mLstThreadTitle.Items == null ||\r
+                mLstThreadTitle.Items.Count == 0)\r
+                return;\r
+\r
+            mLstThreadTitle.ScrollIntoView(mLstThreadTitle.Items[0]);\r
+        }\r
+        //フレームワークから呼ばれます。最後のレスにジャンプしてください。\r
+        public void JumpToBottom()\r
+        {\r
+            if (mLstThreadTitle.Items == null ||\r
+                mLstThreadTitle.Items.Count == 0)\r
+                return;\r
+            int cnt = mLstThreadTitle.Items.Count;\r
+            mLstThreadTitle.ScrollIntoView(mLstThreadTitle.Items[cnt - 1]);\r
+        }\r
+\r
+        public List<IBoard> QueryOpenedBoardList()\r
+        {\r
+            if (mBoardList == null)\r
+                return null;\r
+\r
+            saveData();\r
+\r
+\r
+            List<IBoard> boardList = new List<IBoard>();\r
+            foreach (NTBoardData data in mBoardList)\r
+            {\r
+                boardList.Add(data.mBoard);\r
+            }\r
+            return boardList;\r
+        }\r
+\r
+        public bool OpenBoard(IBoard iboard)\r
+        {\r
+            if (iboard == null)\r
+                return false;\r
+            NTBoardData data = findBoardData(iboard);\r
+            if (data == null)\r
+                return false;\r
+\r
+            mLstMenu.SelectedItem = data;\r
+\r
+            initFontSize();\r
+\r
+            List<IThread> threadList = iboard.getThreadList();\r
+\r
+            ObservableCollection<NTThread> list =\r
+                new ObservableCollection<NTThread>();\r
+            foreach (IThread2 ithread in threadList)\r
+            {\r
+                NTThread thread = ithread.getDependencyObject();\r
+                if (thread == null)\r
+                    continue;\r
+                list.Add(thread);\r
+            }\r
+            mLstThreadTitle.ItemsSource = list;\r
+\r
+            \r
+            mCurrentBoard = iboard;\r
+\r
+            JumpToTop();\r
+\r
+            return true;\r
+        }\r
+\r
+        public bool InitBoardList(List<IBoard> boardList)\r
+        {\r
+            foreach (IBoard iboard in boardList)\r
+            {\r
+                NTBoardData data = new NTBoardData(iboard);\r
+                mBoardList.Add(data);\r
+            }\r
+\r
+            mLstMenu.ItemsSource = mBoardList;\r
+            return true;\r
+        }\r
+\r
+        private NTBoardData findBoardData(IBoard iboard)\r
+        {\r
+            foreach (NTBoardData data in mBoardList)\r
+            {\r
+                if (data.BoardName.Equals(iboard.getName()))\r
+                    return data;\r
+            }\r
+            NTBoardData data1 = new NTBoardData(iboard);\r
+            mBoardList.Add(data1);\r
+            if(mBoardList.Count == 1)\r
+                mLstMenu.ItemsSource = mBoardList;\r
+\r
+            return data1;\r
+        }\r
+        private ThreadDescrption getThreadDescription(NTThread thread)\r
+        {\r
+            string title = thread.Title;\r
+            string datName = thread.getDatName();\r
+            if (title == null || datName == null ||\r
+                mCurrentBoard == null)\r
+                return null;\r
+\r
+            return new ThreadDescrption(title, datName, mCurrentBoard);\r
+        }\r
+        \r
+        public void OnInitApplicationInterface(ICommand2 command, IUtil util)\r
+        {\r
+            mCommand = command;\r
+            mUtil = util;\r
+\r
+            mDict = mCommand.GetPreference();\r
+            initFontSize();\r
+\r
+            if(command != null)\r
+                loadData(command.GetDataPath());\r
+\r
+        }\r
+\r
+        private void initFontSize()\r
+        {\r
+            if (null == mDict)\r
+                return;\r
+            object o;\r
+            if (mDict.TryGetValue(\r
+              PREF_PARAM.THREADTITLE_LIST_FONT_SIZE, out o))\r
+            {\r
+                double d = (double)o;\r
+                if(d != mLstThreadTitle.FontSize)\r
+                    mLstThreadTitle.FontSize = d;\r
+            }\r
+        }\r
+    }\r
+}\r
diff --git a/NT2chCtrl245/ObjectImpl.cs b/NT2chCtrl245/ObjectImpl.cs
new file mode 100755 (executable)
index 0000000..fd2731c
--- /dev/null
@@ -0,0 +1,39 @@
+using NT2chCtrl2;\r
+using NT2chObject;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+\r
+namespace NT2chCtrl2\r
+{\r
+    \r
+    class ThreadDescrption : IThreadDescription\r
+    {\r
+        string mTitle;\r
+        string mDatName;\r
+        IBoard mBoard;\r
+        public ThreadDescrption(string title, string datName, IBoard iboard)\r
+        {\r
+            mTitle = title;\r
+            mDatName = datName;\r
+            mBoard = iboard;\r
+\r
+        }\r
+\r
+        public string getTitle()\r
+        {\r
+            return mTitle;\r
+        }\r
+        public string getDatName()\r
+        {\r
+            return mDatName;\r
+        }\r
+        public IBoard getBoard()\r
+        {\r
+            return mBoard;\r
+        }\r
+\r
+    }\r
+\r
+    \r
+}\r
diff --git a/NT2chCtrl245/Properties/AssemblyInfo.cs b/NT2chCtrl245/Properties/AssemblyInfo.cs
new file mode 100755 (executable)
index 0000000..eb14eca
--- /dev/null
@@ -0,0 +1,36 @@
+using System.Reflection;\r
+using System.Runtime.CompilerServices;\r
+using System.Runtime.InteropServices;\r
+\r
+// アセンブリに関する一般情報は以下の属性セットをとおして制御されます。\r
+// アセンブリに関連付けられている情報を変更するには、\r
+// これらの属性値を変更してください。\r
+[assembly: AssemblyTitle("NT2chCtrl245")]\r
+[assembly: AssemblyDescription("")]\r
+[assembly: AssemblyConfiguration("")]\r
+[assembly: AssemblyCompany("")]\r
+[assembly: AssemblyProduct("NT2chCtrl245")]\r
+[assembly: AssemblyCopyright("Copyright ©  2013")]\r
+[assembly: AssemblyTrademark("")]\r
+[assembly: AssemblyCulture("")]\r
+\r
+// ComVisible を false に設定すると、その型はこのアセンブリ内で COM コンポーネントから \r
+// 参照不可能になります。COM からこのアセンブリ内の型にアクセスする場合は、\r
+// その型の ComVisible 属性を true に設定してください。\r
+[assembly: ComVisible(false)]\r
+\r
+// 次の GUID は、このプロジェクトが COM に公開される場合の、typelib の ID です\r
+[assembly: Guid("9faabbb5-c87b-4cc4-8051-5a939f2c22b7")]\r
+\r
+// アセンブリのバージョン情報は、以下の 4 つの値で構成されています:\r
+//\r
+//      Major Version\r
+//      Minor Version \r
+//      Build Number\r
+//      Revision\r
+//\r
+// すべての値を指定するか、下のように '*' を使ってビルドおよびリビジョン番号を \r
+// 既定値にすることができます:\r
+// [assembly: AssemblyVersion("1.0.*")]\r
+[assembly: AssemblyVersion("2.3.6.0")]\r
+[assembly: AssemblyFileVersion("2.3.6.0")]\r
diff --git a/NT2chCtrl45/DebugMemory.cs b/NT2chCtrl45/DebugMemory.cs
new file mode 100755 (executable)
index 0000000..7a99f10
--- /dev/null
@@ -0,0 +1,63 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading.Tasks;\r
+using NT2chCtrl.html.js;\r
+\r
+namespace NT2chCtrl\r
+{\r
+    public class DebugMemory\r
+    {\r
+        public string Scope { get; set; }\r
+        public string Name { get; set; }\r
+        public string Type { get; set; }\r
+        public string Value { get; set; }\r
+\r
+        public static DebugMemory createInstance(string name, JsVariant var, bool local)\r
+        {\r
+            DebugMemory mem = new DebugMemory();\r
+\r
+            mem.Scope = local ? "local" : "global";\r
+            mem.Name = name;\r
+            if (var is JsNullValue)\r
+            {\r
+                mem.Type = "Null";\r
+                mem.Value = "null";\r
+            }\r
+            else if (var is JsUndefValue)\r
+            {\r
+                mem.Type = "Undefined";\r
+                mem.Value = "undefined";\r
+            }\r
+            else if(var is JsBooleanValue){\r
+                mem.Type = "Bool";\r
+                mem.Value = var.getBooleanValue().getValue() ? "true" : "false";\r
+            }\r
+            else if(var is JsNumberValue){\r
+                mem.Type = "Number";\r
+                if(((JsNumberValue)var).IsNaN())\r
+                    mem.Value = "NaN";\r
+                else\r
+                    mem.Value = var.getStringValue().getValue();\r
+            }\r
+            else if (var is JsStringValue)\r
+            {\r
+                mem.Type = "Text";\r
+                mem.Value = var.getStringValue().getValue();\r
+            }\r
+            else if (var is JsDOMValue)\r
+            {\r
+                mem.Type = "DOM";\r
+                mem.Value = var.getStringValue().getValue();\r
+            }\r
+            else\r
+            {\r
+                mem.Type = "Unknown Type";\r
+                mem.Value = "---";\r
+            }\r
+            return mem;\r
+        }\r
+\r
+    }\r
+}\r
diff --git a/NT2chCtrl45/Dictionary1.xaml b/NT2chCtrl45/Dictionary1.xaml
new file mode 100755 (executable)
index 0000000..fb67ee0
--- /dev/null
@@ -0,0 +1,7 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"\r
+                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">\r
+        <ResourceDictionary.MergedDictionaries>\r
+            <ResourceDictionary\r
+                    Source = "/NT2chStyle45;Component/MainDictionary.xaml"/>\r
+        </ResourceDictionary.MergedDictionaries>\r
+</ResourceDictionary>
\ No newline at end of file
diff --git a/NT2chCtrl45/NT2chCtrl45.csproj b/NT2chCtrl45/NT2chCtrl45.csproj
new file mode 100755 (executable)
index 0000000..7a58f75
--- /dev/null
@@ -0,0 +1,186 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />\r
+  <PropertyGroup>\r
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>\r
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>\r
+    <ProjectGuid>{4873F294-5F91-4364-8E6B-2B539B76F495}</ProjectGuid>\r
+    <OutputType>library</OutputType>\r
+    <AppDesignerFolder>Properties</AppDesignerFolder>\r
+    <RootNamespace>NT2chCtrl45</RootNamespace>\r
+    <AssemblyName>NT2chCtrl45</AssemblyName>\r
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>\r
+    <FileAlignment>512</FileAlignment>\r
+    <ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>\r
+    <WarningLevel>4</WarningLevel>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">\r
+    <DebugSymbols>true</DebugSymbols>\r
+    <DebugType>full</DebugType>\r
+    <Optimize>false</Optimize>\r
+    <OutputPath>bin\Debug\</OutputPath>\r
+    <DefineConstants>TRACE;DEBUG;DOTNET45</DefineConstants>\r
+    <ErrorReport>prompt</ErrorReport>\r
+    <WarningLevel>4</WarningLevel>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">\r
+    <DebugType>pdbonly</DebugType>\r
+    <Optimize>true</Optimize>\r
+    <OutputPath>bin\Release\</OutputPath>\r
+    <DefineConstants>TRACE;DOTNET45</DefineConstants>\r
+    <ErrorReport>prompt</ErrorReport>\r
+    <WarningLevel>4</WarningLevel>\r
+  </PropertyGroup>\r
+  <PropertyGroup>\r
+    <SignAssembly>false</SignAssembly>\r
+  </PropertyGroup>\r
+  <PropertyGroup>\r
+    <AssemblyOriginatorKeyFile>\r
+    </AssemblyOriginatorKeyFile>\r
+  </PropertyGroup>\r
+  <ItemGroup>\r
+    <Reference Include="Accessibility" />\r
+    <Reference Include="PresentationUI, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />\r
+    <Reference Include="ReachFramework" />\r
+    <Reference Include="System" />\r
+    <Reference Include="System.Data" />\r
+    <Reference Include="System.Deployment" />\r
+    <Reference Include="System.Printing" />\r
+    <Reference Include="System.Xml" />\r
+    <Reference Include="Microsoft.CSharp" />\r
+    <Reference Include="System.Core" />\r
+    <Reference Include="System.Xml.Linq" />\r
+    <Reference Include="System.Data.DataSetExtensions" />\r
+    <Reference Include="System.Xaml">\r
+      <RequiredTargetFramework>4.0</RequiredTargetFramework>\r
+    </Reference>\r
+    <Reference Include="UIAutomationProvider" />\r
+    <Reference Include="UIAutomationTypes" />\r
+    <Reference Include="WindowsBase" />\r
+    <Reference Include="PresentationCore" />\r
+    <Reference Include="PresentationFramework" />\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <Compile Include="DebugMemory.cs" />\r
+    <Compile Include="html\CommentElement.cs" />\r
+    <Compile Include="html\css\cssColor.cs" />\r
+    <Compile Include="html\css\cssFont.cs" />\r
+    <Compile Include="html\css\cssLength.cs" />\r
+    <Compile Include="html\css\Property.cs" />\r
+    <Compile Include="html\css\Select.cs" />\r
+    <Compile Include="html\css\Selector.cs" />\r
+    <Compile Include="html\DebugContext.cs" />\r
+    <Compile Include="html\HtmlAttribute.cs" />\r
+    <Compile Include="html\HtmlColors.cs" />\r
+    <Compile Include="html\HtmlElement.cs" />\r
+    <Compile Include="html\HtmlElement_2chparser.cs" />\r
+    <Compile Include="html\HtmlElement_css.cs" />\r
+    <Compile Include="html\HtmlEscape.cs" />\r
+    <Compile Include="html\HtmlParser.cs" />\r
+    <Compile Include="html\HtmlToken.cs" />\r
+    <Compile Include="html\js\JsArrayValue.cs" />\r
+    <Compile Include="html\js\JsCmpFunction.cs" />\r
+    <Compile Include="html\js\JsDomFunction.cs" />\r
+    <Compile Include="html\js\JsDomStrFunction.cs" />\r
+    <Compile Include="html\js\JsDOMValue.cs" />\r
+    <Compile Include="html\js\JsError.cs" />\r
+    <Compile Include="html\js\JsFunction.cs" />\r
+    <Compile Include="html\js\JsFunctionContext.cs" />\r
+    <Compile Include="html\js\JsOpFunction.cs" />\r
+    <Compile Include="html\js\JsOpFunction2.cs" />\r
+    <Compile Include="html\js\JsOpFunction3.cs" />\r
+    <Compile Include="html\js\JsOpFunction4.cs" />\r
+    <Compile Include="html\js\JsParser.cs" />\r
+    <Compile Include="html\js\JsRootFunction.cs" />\r
+    <Compile Include="html\js\JsToken.cs" />\r
+    <Compile Include="html\js\JsVariable.cs" />\r
+    <Compile Include="html\js\JsVariant.cs" />\r
+    <Compile Include="html\StringElement.cs" />\r
+    <Compile Include="html\wpf\FontCash.cs" />\r
+    <Compile Include="html\wpf\Html2FlowDoc.cs" />\r
+    <Compile Include="html\wpf\ImageCash.cs" />\r
+    <Compile Include="NTMemoryInspectionWindow.xaml.cs">\r
+      <DependentUpon>NTMemoryInspectionWindow.xaml</DependentUpon>\r
+    </Compile>\r
+    <Compile Include="NTResViewPanel_file.cs" />\r
+    <Compile Include="NTScriptDebugger.xaml.cs">\r
+      <DependentUpon>NTScriptDebugger.xaml</DependentUpon>\r
+    </Compile>\r
+    <Compile Include="ResListAdapter.cs" />\r
+    <Compile Include="ResListAdapter_callback.cs" />\r
+    <Compile Include="ResListAdapter_event.cs" />\r
+    <Compile Include="ResListAdapter_misc.cs" />\r
+    <Compile Include="ResViewCtrlState.cs" />\r
+    <Compile Include="TouchSupportScrollViewer.cs" />\r
+    <Compile Include="UIElementListAdapter.cs" />\r
+    <Compile Include="UIElementListAdapter_event.cs" />\r
+    <Compile Include="UIElementListAdapter_timer.cs" />\r
+    <Compile Include="UIElementListAdapter_util.cs" />\r
+    <Page Include="Dictionary1.xaml">\r
+      <Generator>MSBuild:Compile</Generator>\r
+      <SubType>Designer</SubType>\r
+    </Page>\r
+    <Page Include="NTMemoryInspectionWindow.xaml">\r
+      <SubType>Designer</SubType>\r
+      <Generator>MSBuild:Compile</Generator>\r
+    </Page>\r
+    <Page Include="NTResViewPanel.xaml">\r
+      <SubType>Designer</SubType>\r
+      <Generator>MSBuild:Compile</Generator>\r
+    </Page>\r
+    <Compile Include="NTResViewPanel.xaml.cs">\r
+      <DependentUpon>NTResViewPanel.xaml</DependentUpon>\r
+    </Compile>\r
+    <Compile Include="NTResViewPanel_misc.cs" />\r
+    <Compile Include="NTResViewPanel_util.cs" />\r
+    <Compile Include="ResViewPopup.cs" />\r
+    <Compile Include="ThreadDescription.cs" />\r
+    <Compile Include="ThreadHistoryUI.cs" />\r
+    <Page Include="NTScriptDebugger.xaml">\r
+      <SubType>Designer</SubType>\r
+      <Generator>MSBuild:Compile</Generator>\r
+    </Page>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <Compile Include="Properties\AssemblyInfo.cs">\r
+      <SubType>Code</SubType>\r
+    </Compile>\r
+    <Compile Include="Properties\Resources.Designer.cs">\r
+      <AutoGen>True</AutoGen>\r
+      <DesignTime>True</DesignTime>\r
+      <DependentUpon>Resources.resx</DependentUpon>\r
+    </Compile>\r
+    <Compile Include="Properties\Settings.Designer.cs">\r
+      <AutoGen>True</AutoGen>\r
+      <DependentUpon>Settings.settings</DependentUpon>\r
+      <DesignTimeSharedInput>True</DesignTimeSharedInput>\r
+    </Compile>\r
+    <EmbeddedResource Include="Properties\Resources.resx">\r
+      <Generator>ResXFileCodeGenerator</Generator>\r
+      <LastGenOutput>Resources.Designer.cs</LastGenOutput>\r
+    </EmbeddedResource>\r
+    <None Include="Properties\Settings.settings">\r
+      <Generator>SettingsSingleFileGenerator</Generator>\r
+      <LastGenOutput>Settings.Designer.cs</LastGenOutput>\r
+    </None>\r
+    <AppDesigner Include="Properties\" />\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ProjectReference Include="..\NT2chObject45\NT2chObject45.csproj">\r
+      <Project>{4e9cecf8-7dea-45db-9b25-d3f768a10c4b}</Project>\r
+      <Name>NT2chObject45</Name>\r
+    </ProjectReference>\r
+    <ProjectReference Include="..\NT2chStyle45\NT2chStyle45.csproj">\r
+      <Project>{d9d1b7b7-3e6e-4ced-b16a-1677ba957f73}</Project>\r
+      <Name>NT2chStyle45</Name>\r
+    </ProjectReference>\r
+  </ItemGroup>\r
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />\r
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. \r
+       Other similar extension points exist, see Microsoft.Common.targets.\r
+  <Target Name="BeforeBuild">\r
+  </Target>\r
+  <Target Name="AfterBuild">\r
+  </Target>\r
+  -->\r
+</Project>
\ No newline at end of file
diff --git a/NT2chCtrl45/NTMemoryInspectionWindow.xaml b/NT2chCtrl45/NTMemoryInspectionWindow.xaml
new file mode 100755 (executable)
index 0000000..db81496
--- /dev/null
@@ -0,0 +1,25 @@
+<Window x:Class="NT2chCtrl.NTMemoryInspectionWindow"\r
+        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"\r
+        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"\r
+        Title="Memory inspector" Height="350" Width="350">\r
+    <Grid>\r
+        <ScrollViewer>\r
+        <ListView x:Name="mListMemView">\r
+            <ListView.View>\r
+                <GridView>\r
+                        <GridView.Columns>\r
+                            <GridViewColumn Header="Name" Width="80" DisplayMemberBinding="{Binding Path=Name}">\r
+                            </GridViewColumn>\r
+                            <GridViewColumn Header="Value"  Width="100" DisplayMemberBinding="{Binding Path=Value}">\r
+                            </GridViewColumn>\r
+                            <GridViewColumn Header="Scope" Width="50" DisplayMemberBinding="{Binding Path=Scope}">\r
+                            </GridViewColumn>\r
+                            <GridViewColumn Header="Type"  Width="60" DisplayMemberBinding="{Binding Path=Type}">\r
+                            </GridViewColumn>\r
+                        </GridView.Columns>\r
+                    </GridView>\r
+            </ListView.View>\r
+        </ListView>\r
+        </ScrollViewer>\r
+    </Grid>\r
+</Window>\r
diff --git a/NT2chCtrl45/NTMemoryInspectionWindow.xaml.cs b/NT2chCtrl45/NTMemoryInspectionWindow.xaml.cs
new file mode 100755 (executable)
index 0000000..1dce0bb
--- /dev/null
@@ -0,0 +1,38 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading.Tasks;\r
+using System.Windows;\r
+using System.Windows.Controls;\r
+using System.Windows.Data;\r
+using System.Windows.Documents;\r
+using System.Windows.Input;\r
+using System.Windows.Media;\r
+using System.Windows.Media.Imaging;\r
+using System.Windows.Shapes;\r
+\r
+namespace NT2chCtrl\r
+{\r
+    /// <summary>\r
+    /// NTMemoryInspectionWindow.xaml の相互作用ロジック\r
+    /// </summary>\r
+    public partial class NTMemoryInspectionWindow : Window\r
+    {\r
+        List<DebugMemory> mMemList;\r
+        public NTMemoryInspectionWindow()\r
+        {\r
+            InitializeComponent();\r
+        }\r
+\r
+        public void initParam(List<DebugMemory> memList)\r
+        {\r
+            mMemList = memList;\r
+            mListMemView.ItemsSource = mMemList;\r
+        }\r
+        public void ShowWindow()\r
+        {\r
+            this.Show();\r
+        }\r
+    }\r
+}\r
diff --git a/NT2chCtrl45/NTResViewPanel.xaml b/NT2chCtrl45/NTResViewPanel.xaml
new file mode 100755 (executable)
index 0000000..3a4bf6e
--- /dev/null
@@ -0,0 +1,211 @@
+<UserControl x:Class="NT2chCtrl.NTResViewPanel"\r
+             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"\r
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"\r
+             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" \r
+             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" \r
+             xmlns:custom="clr-namespace:NT2chCtrl"\r
+             mc:Ignorable="d" \r
+             d:DesignHeight="480" d:DesignWidth="640" Loaded="ResViewPanel_Loaded">\r
+    <UserControl.Resources>\r
+        <Style x:Key="ThreadButton" TargetType="Button">\r
+            <!--Setter Property="Foreground" Value="{StaticResource BasicForeBrush}"/-->\r
+            <Setter Property="FontSize" Value="12"/>\r
+            <Setter Property="Width" Value="200" />\r
+            <!--Setter Property="Height" Value="30" /-->\r
+            <Setter Property="Margin" Value="5,0,5,5" />\r
+            <Setter Property="Template">\r
+                <Setter.Value>\r
+                    <ControlTemplate TargetType="Button">\r
+                        <Border BorderThickness="1,0,0,1" BorderBrush="LightGray">\r
+                            <Grid x:Name="controlLayout"\r
+                                  Background="{StaticResource BasicBkBrush}">\r
+                                <!--Grid.Background >\r
+                                    DodgerBlue -->\r
+                                <!--LinearGradientBrush>\r
+                                        <GradientStop Color="White" Offset="1"/>                                    \r
+                                        <GradientStop Color="DodgerBlue" Offset="0.5"/>\r
+                                        <GradientStop Color="DimGray" Offset="0"/>\r
+                                    </LinearGradientBrush-->\r
+                                <!--/Grid.Background-->\r
+                                <!--Rectangle x:Name="buttonSurface"/ -->\r
+                                <Label Margin="5,0,0,0">\r
+                                    <TextBlock x:Name="buttonCaption" \r
+                                           TextWrapping="WrapWithOverflow" \r
+                                           Text="{TemplateBinding Content}"\r
+                                           Foreground="{StaticResource BasicForeBrush}"\r
+                                           FontWeight="Bold"\r
+                                           HorizontalAlignment="Left"\r
+                                           VerticalAlignment="Center"/>\r
+                                </Label>\r
+                            </Grid>\r
+                        </Border>\r
+                        <ControlTemplate.Triggers>\r
+                            <Trigger Property="IsMouseOver" Value="True">\r
+                                <Setter TargetName="controlLayout" \r
+                                        Property="Background" \r
+                                        Value="Yellow"/>\r
+                                <Setter TargetName="buttonCaption" \r
+                                        Property="Foreground"\r
+                                        Value="Green"/>\r
+                            </Trigger>\r
+                        </ControlTemplate.Triggers>\r
+                    </ControlTemplate>\r
+                </Setter.Value>\r
+            </Setter>\r
+        </Style>\r
+    </UserControl.Resources>\r
+    <DockPanel LastChildFill="True" Background="DimGray">\r
+        <Border  DockPanel.Dock="Right"  Background="DimGray" \r
+                 RenderTransformOrigin="0.5,0.5"\r
+                 Margin="2">\r
+            <!--Border.LayoutTransform>\r
+                <TransformGroup>\r
+                    <ScaleTransform x:Name="scaleTransform" ScaleX="0.5"/>\r
+                    <SkewTransform x:Name="skewTransfoem" AngleY="30" CenterX="1" CenterY="0"/>\r
+                    <RotateTransform/>\r
+                    <TranslateTransform/>\r
+                </TransformGroup>\r
+            </Border.LayoutTransform-->\r
+            <Grid>\r
+                <ScrollViewer x:Name="mThreadMenuScrollViewer"\r
+                    VerticalScrollBarVisibility="Auto">\r
+                    <StackPanel x:Name="mThreadHistoryPanel">\r
+                        <Button x:Name="btnThreadPlaceHolder1" Style="{DynamicResource ThreadButton}" Content="Place Holder1"></Button>\r
+                        <Button x:Name="btnThreadPlaceHolder2" Style="{DynamicResource ThreadButton}" Content="Place Holder2"></Button>\r
+                        <Button x:Name="btnThreadPlaceHolder3" Style="{DynamicResource ThreadButton}" Content="Place Holder3 Long long long long long "></Button>\r
+                    </StackPanel>\r
+                </ScrollViewer>\r
+                <!--Canvas x:Name="surfaceCanvas" Width="200" HorizontalAlignment="Left" >\r
+                    <Canvas.Background>\r
+                        <LinearGradientBrush  Opacity="0.5" EndPoint="1,0.5" StartPoint="0.5,0.5">\r
+                            <GradientStop Color="Transparent" Offset="1" />\r
+                            <GradientStop Color="DodgerBlue" Offset="0.3" />\r
+                            <GradientStop Color="DimGray" Offset="0"/>\r
+                        </LinearGradientBrush>\r
+                    </Canvas.Background>\r
+                </Canvas-->\r
+            </Grid>\r
+            <!--Border.Triggers>\r
+                <EventTrigger RoutedEvent="Border.MouseEnter">\r
+                    <EventTrigger.Actions>\r
+                        <BeginStoryboard>\r
+                            <Storyboard>\r
+                                <DoubleAnimation \r
+                                    Storyboard.TargetProperty="ScaleX" \r
+                                    Storyboard.TargetName="scaleTransform"\r
+                                    From="0.5" To="1" Duration="0:0:0.5"/>\r
+                                <DoubleAnimation \r
+                                    Storyboard.TargetProperty="AngleY" \r
+                                    Storyboard.TargetName="skewTransfoem"\r
+                                    From="30" To="0" Duration="0:0:0.5"/>\r
+                                <DoubleAnimation\r
+                                    Storyboard.TargetName="surfaceCanvas"\r
+                                    Storyboard.TargetProperty="Width"\r
+                                    To="0" Duration="0:0:0.5"/>\r
+                            </Storyboard>\r
+                        </BeginStoryboard>\r
+                    </EventTrigger.Actions>\r
+                </EventTrigger>\r
+                <EventTrigger RoutedEvent="Border.MouseLeave">\r
+                    <EventTrigger.Actions>\r
+                        <BeginStoryboard>\r
+                            <Storyboard>\r
+                                <DoubleAnimation \r
+                                    Storyboard.TargetProperty="ScaleX" \r
+                                    Storyboard.TargetName="scaleTransform"\r
+                                    To="0.5" Duration="0:0:0.5"/>\r
+                                <DoubleAnimation \r
+                                    Storyboard.TargetProperty="AngleY" \r
+                                    Storyboard.TargetName="skewTransfoem"\r
+                                    From="0" To="30" Duration="0:0:0.5"/>\r
+                                <DoubleAnimation\r
+                                    Storyboard.TargetName="surfaceCanvas"\r
+                                    Storyboard.TargetProperty="Width"\r
+                                    From="0" Duration="0:0:0.5"/>\r
+                            </Storyboard>\r
+                        </BeginStoryboard>\r
+                    </EventTrigger.Actions>\r
+                </EventTrigger>\r
+            </Border.Triggers-->\r
+        </Border>\r
+        <Border BorderBrush="AliceBlue" BorderThickness="0" CornerRadius="0">\r
+            <Border.Background>\r
+                <LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5"                                      >\r
+                    <GradientStop Color="White" Offset="0"/>\r
+                    <GradientStop Color="DimGray" Offset="0.5"/>\r
+                    <GradientStop Color="White" Offset="1"/>\r
+                </LinearGradientBrush>\r
+            </Border.Background>\r
+            <DockPanel\r
+                MinWidth="100"\r
+                MinHeight="100"\r
+                LastChildFill="True"\r
+                       Margin="0, 5, 0, 10" >\r
+                <DockPanel.Background>\r
+                    White\r
+                    <!--LinearGradientBrush EndPoint="1,0.5" StartPoint="0.5,0.5">\r
+                        <GradientStop Color="#FFAFF3E4" Offset="1"/>\r
+                        <GradientStop Color="White"/>\r
+                    </LinearGradientBrush-->\r
+                </DockPanel.Background>\r
+                <Border  BorderBrush="White" \r
+                         BorderThickness="1" CornerRadius="1" \r
+                         DockPanel.Dock="Top"\r
+                         >\r
+                    <Label x:Name="mLabelThreadTitle" \r
+                           Padding="5,0,5,0"\r
+                           Background="SteelBlue" Foreground="White"/>\r
+                </Border>\r
+                <StackPanel x:Name="mFontSetupToolbar"\r
+                    Orientation="Horizontal" FlowDirection="RightToLeft" DockPanel.Dock="Bottom" Margin="0,0,5,0">\r
+                    <Button Width="50" Background="{StaticResource BasicBkBrush}" Click="btnFontReduce_Click">\r
+                        <Image Source="/NT2chStyle45;component/images/reduce_font.png" Stretch="None" />\r
+                    </Button>\r
+                    <Button Width="50" Background="{StaticResource BasicBkBrush}" Click="btnFontEnlarge_Click">\r
+                        <Image Source="/NT2chStyle45;component/images/enlarge_font.png" Stretch="None" />\r
+                    </Button>\r
+                </StackPanel>\r
+                <Grid x:Name="mAutoScrollToolbar"\r
+                    DockPanel.Dock="Bottom" Margin="0,0,5,0">\r
+                    <Grid.ColumnDefinitions>\r
+                        <ColumnDefinition Width="Auto"/>\r
+                        <ColumnDefinition Width="*"/>\r
+                        <ColumnDefinition Width="Auto"/>\r
+                        <ColumnDefinition Width="Auto"/>\r
+                        <ColumnDefinition Width="Auto"/>\r
+                        <ColumnDefinition Width="Auto"/>\r
+                    </Grid.ColumnDefinitions>\r
+                    <TextBlock TextWrapping="Wrap" Text="x0.1"\r
+                               VerticalAlignment="Center"\r
+                               Margin="0,0,5,0"/>\r
+                    <Slider Grid.Column="1" x:Name="mAutoScrollRatioSlider" \r
+                               VerticalAlignment="Center"\r
+                            Maximum="20" Minimum="3.2" SmallChange="1"\r
+                            Value="10" ValueChanged="mAutoScrollRatioSlider_ValueChanged"/>\r
+                    <TextBlock Grid.Column="2" TextWrapping="Wrap" \r
+                               VerticalAlignment="Center"\r
+                               Text="x4" Margin="5,0,0,0"/>\r
+                    <TextBlock Grid.Column="3" x:Name="mAutoScrollRatio" \r
+                               VerticalAlignment="Center"\r
+                               Text="Current Speed x1" Margin="15,0"/>\r
+                    <Button  x:Name="mBtnReverseAutoPlay" Background="{StaticResource BasicBkBrush}"\r
+                        Grid.Column="4" Width="50" Click="mBtnReverseAutoPlay_Click">\r
+                        <Image Source="/NT2chStyle45;component/images/reverse.png" Stretch="None" />\r
+                    </Button>\r
+                    <Button  x:Name="mBtnPauseAutoPlay" Background="{StaticResource BasicBkBrush}"\r
+                        Grid.Column="5" Width="50" Click="mBtnPauseAutoPlay_Click">\r
+                        <Image Source="/NT2chStyle45;component/images/pause_btn.png" Stretch="None" />\r
+                    </Button>\r
+                    <Button  x:Name="mBtnResumeAutoPlay" Background="{StaticResource BasicBkBrush}"\r
+                        Grid.Column="5" Width="50" Click="mBtnResumeAutoPlay_Click">\r
+                        <Image Source="/NT2chStyle45;component/images/play_btn.png" Stretch="None" />\r
+                    </Button>\r
+                </Grid>\r
+                <custom:UIElementListPanel x:Name="mResListPanel" Loaded="UIElementListPanel_Loaded" />\r
+                \r
+                <!--FlowDocumentScrollViewer x:Name="mFlowDocResView">\r
+                </FlowDocumentScrollViewer-->\r
+            </DockPanel>\r
+        </Border>\r
+    </DockPanel>\r
+</UserControl>\r
diff --git a/NT2chCtrl45/NTResViewPanel.xaml.cs b/NT2chCtrl45/NTResViewPanel.xaml.cs
new file mode 100755 (executable)
index 0000000..5b62784
--- /dev/null
@@ -0,0 +1,351 @@
+using NT2chObject;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Windows;\r
+using System.Windows.Controls;\r
+using System.Windows.Data;\r
+using System.Windows.Documents;\r
+using System.Windows.Input;\r
+using System.Windows.Media;\r
+using System.Windows.Media.Imaging;\r
+using System.Windows.Navigation;\r
+using System.Windows.Shapes;\r
+using System.IO;\r
+using NT2chCtrl.html;\r
+\r
+namespace NT2chCtrl\r
+{\r
+\r
+    /// <summary>\r
+    /// NTResViewPanel.xaml の相互作用ロジック\r
+    /// \r
+    /// 2ぃとちゃん for Windowsのレス画面に表示される\r
+    /// コントロールを定義します。IResViewインターフェースのメソッドは\r
+    /// フレームワークから呼び出すので、削除しないで下さい。\r
+    /// また、このコントロールの名前も変更できません。\r
+    /// NTResViewPanel_util.csはアプリケーションフレームワークとの\r
+    /// インターフェースとなるヘルパーメソッドを定義してありますので\r
+    /// 編集しないで下さい。\r
+    /// フレームワークから渡される2chデータのオブジェクトについては\r
+    /// NTInterfaceDecl.csの定義を参照して下さい。\r
+    /// 基本的にNTが先頭に着くファイル名は本ファイルを除いて編集できません。\r
+    /// 本ファイルについては、IResViewインターフェースのメソッドが実装されている限り\r
+    /// 自由に由に変更できます。\r
+    /// \r
+    /// </summary>\r
+    public partial class NTResViewPanel : UserControl,\r
+        IResView , IResViewJump, IResViewSearch\r
+    {\r
+        IThread mCurrentThread = null;\r
+        //ResViewUI mResUI = null;\r
+        ThreadHistoryUI mThreadHistoryUI = null;\r
+        int mSavedPrevReadCount = 0;\r
+        ResListAdapter mResListAdapter = null;\r
+\r
+        public NTResViewPanel()\r
+        {\r
+            InitializeComponent();\r
+        }\r
+\r
+        private void ResViewPanel_Loaded(object sender, RoutedEventArgs e)\r
+        {\r
+            mThreadHistoryPanel.Children.Clear();\r
+            mFontSetupToolbar.Visibility = System.Windows.Visibility.Collapsed;\r
+            mAutoScrollToolbar.Visibility = System.Windows.Visibility.Collapsed;\r
+            mBtnResumeAutoPlay.Visibility = System.Windows.Visibility.Collapsed;\r
+\r
+#if DOTNET45\r
+            TouchSupportScrollViewer sv =\r
+                new TouchSupportScrollViewer(mThreadMenuScrollViewer,\r
+                    mThreadHistoryPanel);\r
+#endif\r
+        }\r
+\r
+        /*\r
+         * 現在アクティブなスレッドを確認する為にフレームワークから\r
+         * 呼び出されます。\r
+         */\r
+        public IThread getCurrentThread()\r
+        {\r
+            return mCurrentThread;\r
+        }\r
+\r
+\r
+        /*\r
+         * アプリケーションフレームワークから、新しいスレッドを表示する要求が\r
+         * 有った時に呼ばれます。\r
+         */\r
+        public bool OpenThread(IThread ithread)\r
+        {\r
+            mCurrentThread = ithread;\r
+            if (ithread == null)\r
+                return false;\r
+\r
+            setTitle(ithread);\r
+\r
+            if (mThreadHistoryUI != null)\r
+            {\r
+                mThreadHistoryUI.AddButton(ithread);\r
+                mThreadMenuScrollViewer.ScrollToTop();\r
+            }\r
+\r
+            mResListAdapter = new ResListAdapter(this, ithread, mCommand, mUtil);\r
+\r
+            mSavedPrevReadCount = ithread.getPrevReadCount();\r
+            if (mSavedPrevReadCount < 0)\r
+            {\r
+                mSavedPrevReadCount = 0;\r
+            }\r
+\r
+            mResListPanel.setAdapter(mResListAdapter, mSavedPrevReadCount);\r
+\r
+            continueAutoScroll();\r
+\r
+            return true;// mResUI.OpenThread(ithread, mFlowDocResView);     \r
+        }\r
+\r
+        private const string RES_LAYOUT_HTML_FILE = @"\res_layout.html";\r
+\r
+\r
+        public void initResLayout(bool debug)\r
+        {\r
+            if (mCommand == null)\r
+                return;\r
+\r
+            string path = mCommand.GetDataPath() + RES_LAYOUT_HTML_FILE;\r
+\r
+            string htmlSource = loadHtml(path);\r
+            //if (htmlSource == null)\r
+            //    return;\r
+            html.HtmlParser parser;\r
+            if (!ResViewCtrlState.getInstance().init(htmlSource, mCommand, out parser)\r
+                && debug && parser.hasError())\r
+            {\r
+                \r
+                NTScriptDebugger debugger = new NTScriptDebugger();\r
+                debugger.ErrorMessage = parser.getErrorMessage();\r
+                debugger.ErrorLine = parser.getErrorLine();\r
+                debugger.ErrorSrcIndex = parser.getErrorSrcIndex();\r
+                debugger.HtmlSource = htmlSource;\r
+\r
+                debugger.initParam();\r
+                NTScriptDebugger.ShowWindow(debugger);\r
+            }\r
+\r
+        }\r
+\r
+        //コントロール初期化時に、これまでに閲覧したスレッドの履歴リストが渡されます。\r
+        public bool SetThreadReadHistory(List<IThreadDescription> threadDescriptionList)\r
+        {\r
+            mThreadHistoryUI = new ThreadHistoryUI(mCommand,mUtil, threadDescriptionList,\r
+                mThreadHistoryPanel);\r
+\r
+            /*object o; \r
+            if(getDict().TryGetValue(PREF_PARAM.RES_VIEW_ZOOM_VALUE, out o))\r
+            {\r
+                string s = o as string;\r
+                if (s != null)\r
+                {\r
+                    double zoom;\r
+                    if (double.TryParse(s, out zoom))\r
+                    {\r
+                        //mFlowDocResView.Zoom = zoom;\r
+                    }\r
+                }\r
+            }*/\r
+            return true;\r
+        }\r
+\r
+        public void OnNotifyThreadUpdated(IBoard iboard)\r
+        {\r
+            if (mThreadHistoryUI == null)\r
+                return;\r
+            mThreadHistoryUI.UpdateButton(iboard);\r
+\r
+        }\r
+\r
+        //このコントロールで管理しているスレッド閲覧リストを取得する為に呼ばれます。\r
+        public List<IThreadDescription> QueryThreadReadHistory()\r
+        {\r
+            if (mThreadHistoryUI == null)\r
+                return null;\r
+            return mThreadHistoryUI.getCurrentList();\r
+        }\r
+        //オブジェクトがアンロードされる前に呼ばれます。\r
+        //ここで、オブジェクトの永続データーを保存して下さい。\r
+        public void SaveCurrentState()\r
+        {\r
+            //double zoom = mFlowDocResView.Zoom;\r
+            //getDict().Remove(PREF_PARAM.RES_VIEW_ZOOM_VALUE);\r
+            //getDict().Add(PREF_PARAM.RES_VIEW_ZOOM_VALUE, zoom.ToString());\r
+        }\r
+\r
+\r
+        public void ToggleFontSetupTool()\r
+        {\r
+            if(mFontSetupToolbar.Visibility != System.Windows.Visibility.Collapsed)\r
+                mFontSetupToolbar.Visibility = System.Windows.Visibility.Collapsed;\r
+            else\r
+                mFontSetupToolbar.Visibility = System.Windows.Visibility.Visible;\r
+        }\r
+\r
+        public void ToggleAutoScroll()\r
+        {\r
+            if (mAutoScrollToolbar.Visibility != System.Windows.Visibility.Collapsed)\r
+            {\r
+                mAutoScrollToolbar.Visibility = System.Windows.Visibility.Collapsed;\r
+                mResListPanel.setAutoScroll(false, 0);\r
+            }\r
+            else\r
+            {\r
+                mAutoScrollToolbar.Visibility = System.Windows.Visibility.Visible;\r
+                mResListPanel.setAutoScroll(true, mAutoScrollSliderValue);\r
+            }\r
+        }\r
+\r
+        public void UpdateTextSelMode(bool selMode)\r
+        {\r
+            if (null == mResListAdapter)\r
+                return;\r
+            mResListAdapter.updateTextSelMode(selMode);\r
+        }\r
+\r
+        void continueAutoScroll()\r
+        {\r
+            if (mAutoScrollToolbar.Visibility == System.Windows.Visibility.Visible)\r
+            {\r
+                mAutoScrollToolbar.Visibility = System.Windows.Visibility.Visible;\r
+                mResListPanel.setAutoScroll(true, mAutoScrollSliderValue);\r
+            }\r
+        }\r
+\r
+        /*\r
+           *  スレッドの先頭にスクロースする要求が有った時に呼ばれます。\r
+           */\r
+        public void JumpToTop()\r
+        {\r
+            mResListPanel.setScrollItemPosition(0);\r
+        }\r
+        /*\r
+         *  スレッドの最後にスクロースする要求が有った時に呼ばれます。\r
+         */\r
+        public void JumpToBottom()\r
+        {\r
+            List<IRes> resList = mCurrentThread.getResList();\r
+            int num = resList.Count;\r
+            num--;\r
+            if (num < 0)\r
+                num = 0;\r
+            mResListPanel.setScrollItemPosition(num);\r
+        }\r
+        /*\r
+         *  スレッドの新着にスクロースする要求が有った時に呼ばれます。\r
+         */\r
+        public void JumpToNew()\r
+        {\r
+            mResListPanel.setScrollItemPosition(mSavedPrevReadCount);\r
+        }\r
+        public void JumpTo(int position)\r
+        {\r
+            mResListPanel.setScrollItemPosition(position);\r
+        }\r
+        public void InvalidateItems()\r
+        {\r
+            mResListPanel.InvalidateItems();\r
+        }\r
+        /*\r
+         *  スレッドの新着にスクロースする要求が有った時に呼ばれます。\r
+         */\r
+        public void JumpToNextBookmark()\r
+        {\r
+            int current = mResListPanel.getCurrentPosition();\r
+            if (current < 0)\r
+                current = 0;\r
+            int scrollTo = mResListAdapter.NextBookmark(current);\r
+            if (scrollTo < 0)\r
+                return;\r
+\r
+            mResListPanel.setScrollItemPosition(scrollTo);\r
+        }\r
+\r
+        //指定された検索文字列を選択状態にして下さい。\r
+        public void SetSearchWord(string searchWord)\r
+        {\r
+            int current = mResListPanel.getCurrentPosition();\r
+            if (current < 0)\r
+                current = 0;\r
+            mResListAdapter.SetSearchWord(searchWord, current);\r
+        }\r
+        //指定された検索文字列の後方にマッチする文字列を選択して下さい。\r
+        public void SearchNext()\r
+        {\r
+            int cursor = mResListAdapter.SearchNext();\r
+            if (cursor < 0)\r
+                return;\r
+\r
+            mResListPanel.setScrollItemPosition(cursor);\r
+        }\r
+        //指定された検索文字列の前方にマッチする文字列を選択して下さい。\r
+        public void SearchPrev()\r
+        {\r
+            int cursor = mResListAdapter.SearchPrev();\r
+            if (cursor < 0)\r
+                return;\r
+\r
+            mResListPanel.setScrollItemPosition(cursor);\r
+        }\r
+\r
+        private void UIElementListPanel_Loaded(object sender, RoutedEventArgs e)\r
+        {\r
+            this.mResListPanel.init();\r
+        }\r
+\r
+        private void btnFontReduce_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            mResListAdapter.ZoomOut();\r
+        }\r
+\r
+        private void btnFontEnlarge_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            mResListAdapter.ZoomIn();\r
+        }\r
+\r
+        double mAutoScrollSliderValue = 1;\r
+        private void mAutoScrollRatioSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)\r
+        {\r
+            if (mAutoScrollRatio == null)\r
+                return;\r
+\r
+            double val = e.NewValue;\r
+            val *= val;\r
+            val /= 100;\r
+            mAutoScrollSliderValue = val;\r
+            string s =string.Format("Current Speed x{0:0.##}", val);\r
+            mAutoScrollRatio.Text = s;\r
+\r
+            mResListPanel.setAutoScroll(true, val);\r
+        }\r
+\r
+        private void mBtnPauseAutoPlay_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            mBtnResumeAutoPlay.Visibility = System.Windows.Visibility.Visible;\r
+            mBtnPauseAutoPlay.Visibility = System.Windows.Visibility.Collapsed;\r
+            mResListPanel.pauseAutoScroll();\r
+        }\r
+\r
+        private void mBtnResumeAutoPlay_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            mBtnResumeAutoPlay.Visibility = System.Windows.Visibility.Collapsed;\r
+            mBtnPauseAutoPlay.Visibility = System.Windows.Visibility.Visible;\r
+            mResListPanel.resumeAutoScroll();\r
+        }\r
+        private void mBtnReverseAutoPlay_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            mResListPanel.toggleScrollDirection();\r
+        }\r
+\r
+    }\r
+\r
+    \r
+}\r
diff --git a/NT2chCtrl45/NTResViewPanel_file.cs b/NT2chCtrl45/NTResViewPanel_file.cs
new file mode 100755 (executable)
index 0000000..bc46785
--- /dev/null
@@ -0,0 +1,42 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.IO;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading.Tasks;\r
+\r
+namespace NT2chCtrl\r
+{\r
+    public partial class NTResViewPanel\r
+    {\r
+\r
+        string loadHtml(string path)\r
+        {\r
+            string line = null;\r
+\r
+            FileStream fs = null;\r
+            try\r
+            {\r
+                fs = File.Open(path, FileMode.Open, FileAccess.Read);\r
+                StreamReader sr = new StreamReader(fs);\r
+\r
+                line = sr.ReadToEnd();\r
+\r
+                fs.Close();\r
+                fs = null;\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                System.Diagnostics.Debug.WriteLine(e.StackTrace);\r
+            }\r
+            finally\r
+            {\r
+                if (null != fs)\r
+                    fs.Close();\r
+            }\r
+\r
+            return line;\r
+        }\r
+\r
+    }\r
+}\r
diff --git a/NT2chCtrl45/NTResViewPanel_misc.cs b/NT2chCtrl45/NTResViewPanel_misc.cs
new file mode 100755 (executable)
index 0000000..b1c0eb4
--- /dev/null
@@ -0,0 +1,49 @@
+using NT2chObject;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Windows.Controls;\r
+using System.Windows.Documents;\r
+\r
+namespace NT2chCtrl\r
+{\r
+    partial class NTResViewPanel\r
+    {\r
+        private void setTitle(IThread ithread)\r
+        {\r
+            StackPanel sp = new StackPanel();\r
+            sp.Orientation = Orientation.Horizontal;\r
+            string title = ithread.getTitle();\r
+            sp.Children.Add(new TextBlock(new Run(title+" ")));\r
+            IBoard iboard = ithread.getBoard();\r
+            string boardName;\r
+            if (iboard != null)\r
+            {\r
+                boardName = iboard.getName();\r
+                if (boardName != null && boardName.Length > 0)\r
+                {\r
+                    Hyperlink hl = new Hyperlink(new Run("(" + boardName + ")"));\r
+                    sp.Children.Add(new TextBlock(hl));\r
+                    hl.Tag = iboard;\r
+                    hl.Click += hl_Click;\r
+                }\r
+            }\r
+            mLabelThreadTitle.Content = sp;\r
+        }\r
+\r
+        void hl_Click(object sender, System.Windows.RoutedEventArgs e)\r
+        {\r
+            Hyperlink hl = sender as Hyperlink;\r
+            if (hl == null)\r
+                return;\r
+\r
+            IBoard iboard = hl.Tag as IBoard;\r
+            if (iboard == null)\r
+                return;\r
+\r
+            mCommand.TryToOpenBoard(iboard);\r
+            \r
+        }\r
+\r
+    }\r
+}\r
diff --git a/NT2chCtrl45/NTResViewPanel_util.cs b/NT2chCtrl45/NTResViewPanel_util.cs
new file mode 100755 (executable)
index 0000000..4376e24
--- /dev/null
@@ -0,0 +1,103 @@
+using NT2chObject;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Windows.Controls;\r
+\r
+namespace NT2chCtrl\r
+{\r
+    /**\r
+     * このファイルは編集しないで下さい。\r
+     * \r
+     */\r
+    public partial class NTResViewPanel : UserControl, IResView\r
+    {\r
+        private static IUtil mUtil;\r
+        private static ICommand mCommand;\r
+        //アプリケーションフレームワークが呼び出します。\r
+        //ユーティリティ関数を設定します。\r
+        public void OnInitApplicationInterface(ICommand command, IUtil util)\r
+        {\r
+            mCommand = command;\r
+            mUtil = util;\r
+            //initParam();\r
+        }\r
+        public static IUtil getUtil()\r
+        {\r
+            return mUtil;\r
+        }\r
+\r
+        public static ICommand getCommand()\r
+        {\r
+            return mCommand;\r
+        }\r
+\r
+        private static Dictionary<PREF_PARAM, object> mDictPreference;\r
+        private static Dictionary<PREF_PARAM, object> getDict()\r
+        {\r
+            if(mUtil == null)\r
+                return null;\r
+            if(mDictPreference == null)\r
+                mDictPreference = mCommand.GetPreference();\r
+            return mDictPreference;\r
+        }\r
+\r
+        public bool getTextSelMode()\r
+        {\r
+            object o;\r
+            Dictionary<PREF_PARAM, object> dict = getDict();\r
+            if (!dict.TryGetValue(PREF_PARAM.RES_VIEW_TEXTSEL_MODE, out o))\r
+                return false;\r
+            bool? selMode = o as bool?;\r
+            if (selMode.HasValue)\r
+                return (bool)selMode;\r
+            return false;\r
+        }\r
+\r
+        public static string getResFontTypeface()\r
+        {\r
+            object o;\r
+            Dictionary<PREF_PARAM, object> dict = getDict();\r
+            if (!dict.TryGetValue(PREF_PARAM.RES_VIEW_FONT_TYPEFACE, out o))\r
+                return null;\r
+            string typeface = o as string;\r
+            return typeface;\r
+        }\r
+        public static string getResAAFontTypeface()\r
+        {\r
+            object o;\r
+            Dictionary<PREF_PARAM, object> dict = getDict();\r
+            if (!dict.TryGetValue(PREF_PARAM.RES_VIEW_AA_FONT_TYPEFACE, out o))\r
+                return null;\r
+            string typeface = o as string;\r
+            return typeface;\r
+        }\r
+        public static string [] getAAStringList()\r
+        {\r
+            object o;\r
+            Dictionary<PREF_PARAM, object> dict = getDict();\r
+            if (!dict.TryGetValue(PREF_PARAM.RES_VIEW_AA_STRING_LIST, out o))\r
+                return null;\r
+            string[] aaList = o as string[];\r
+            return aaList;\r
+        }\r
+\r
+        public static bool testAsciiArt(string source)\r
+        {\r
+            if (source == null || source.Length == 0)\r
+                return false;\r
+\r
+            string[] aaData = getAAStringList();\r
+            if (aaData == null)\r
+                return false;\r
+\r
+            foreach (string aa in aaData)\r
+            {\r
+                if (0 <= source.IndexOf(aa))\r
+                    return true;\r
+            }\r
+            return false;\r
+        }\r
+\r
+    }\r
+}\r
diff --git a/NT2chCtrl45/NTScriptDebugger.xaml b/NT2chCtrl45/NTScriptDebugger.xaml
new file mode 100755 (executable)
index 0000000..8e468d5
--- /dev/null
@@ -0,0 +1,35 @@
+<Window x:Class="NT2chCtrl.NTScriptDebugger"\r
+        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"\r
+        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"\r
+        Title="2ぃとちゃん スクリプトデバッガー" Height="800" Width="600" Closed="NTScriptDebugger_Closed">\r
+    <Grid>\r
+        <Grid.RowDefinitions>\r
+            <RowDefinition Height="Auto"/>\r
+            <RowDefinition Height="Auto"/>\r
+            <RowDefinition Height="*"/>\r
+        </Grid.RowDefinitions>\r
+        <Grid>\r
+            <Grid.ColumnDefinitions>\r
+                <ColumnDefinition Width="*"/>\r
+                <ColumnDefinition Width="Auto"/>\r
+                <ColumnDefinition Width="Auto"/>\r
+            </Grid.ColumnDefinitions>\r
+            <CheckBox x:Name="mChkDontShowWindow" VerticalAlignment="Center" Checked="mChkDontShowWindow_Checked" Unchecked="mChkDontShowWindow_Unchecked">\r
+                このプロセスではデバッグウインドウを表示しない\r
+            </CheckBox>\r
+            <Button x:Name="mBtnShowWatchWindow" HorizontalAlignment="Right" Grid.Column="1" Margin="10,5" Click="mBtnShowWatchWindow_Click" IsEnabled="False">\r
+                メモリーの表示\r
+            </Button>\r
+            <Button x:Name="mBtnClose" HorizontalAlignment="Right" Grid.Column="2" Margin="10,5" Click="mBtnClose_Click">\r
+                閉じる\r
+            </Button>\r
+        </Grid>\r
+        <Label Grid.Row="1" x:Name="mLblHeader" Margin="5" />\r
+        <FlowDocumentScrollViewer x:Name="mOutputBox" Grid.Row="2">\r
+            <FlowDocument>\r
+                <Paragraph x:Name="mParaBody">\r
+                </Paragraph>\r
+            </FlowDocument>\r
+        </FlowDocumentScrollViewer>\r
+    </Grid>\r
+</Window>\r
diff --git a/NT2chCtrl45/NTScriptDebugger.xaml.cs b/NT2chCtrl45/NTScriptDebugger.xaml.cs
new file mode 100755 (executable)
index 0000000..05b3a76
--- /dev/null
@@ -0,0 +1,166 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Windows;\r
+using System.Windows.Controls;\r
+using System.Windows.Data;\r
+using System.Windows.Documents;\r
+using System.Windows.Input;\r
+using System.Windows.Media;\r
+using System.Windows.Media.Imaging;\r
+using System.Windows.Shapes;\r
+using System.Windows.Threading;\r
+\r
+namespace NT2chCtrl\r
+{\r
+    /// <summary>\r
+    /// NTScriptDebugger.xaml の相互作用ロジック\r
+    /// </summary>\r
+    public partial class NTScriptDebugger : Window\r
+    {\r
+        public int ErrorLine { set; get; }\r
+        public int ErrorSrcIndex { set; get; }\r
+        public string ErrorMessage { set; get; }\r
+        public string HtmlSource { get; set; }\r
+        public html.js.JsFunctionContext FuncContext { get; set; }\r
+        public NTScriptDebugger()\r
+        {\r
+            InitializeComponent();\r
+        }\r
+\r
+        static bool mDontShowWindow = false;\r
+        static List<NTScriptDebugger> mWindows = new List<NTScriptDebugger>();\r
+        public static void ShowWindow(NTScriptDebugger wnd)\r
+        {\r
+            if (mDontShowWindow)\r
+                return;\r
+            if (mWindows.Count == 0)\r
+            {\r
+                wnd.Show();\r
+            }\r
+            mWindows.Add(wnd);\r
+        }\r
+\r
+\r
+        public void initParam()\r
+        {\r
+            //mLblHeader.Content = ErrorMessage;\r
+            //mOutputBox.AppendText(HtmlSource);\r
+            mFocusSpan = null;\r
+            string source = HtmlSource;\r
+            int length = source.Length;\r
+            int currLine = 1;\r
+            int textStart = 0;\r
+            int i = 0;\r
+            int column = -1;\r
+            for (; i < length; i++)\r
+            {\r
+                char c = source[i];\r
+                if (c == '\n')\r
+                {\r
+                    string line = source.Substring(textStart, i - textStart);\r
+                    if (currLine == ErrorLine)\r
+                    {\r
+                        addLine(currLine, line, true);\r
+                        if (ErrorSrcIndex < i && textStart <= ErrorSrcIndex)\r
+                        {\r
+                            column = ErrorSrcIndex - textStart;\r
+                        }\r
+                    }\r
+                    else\r
+                    {\r
+                        addLine(currLine, line, false);\r
+                    }\r
+                    currLine++;\r
+                    textStart = i + 1;\r
+                    continue;\r
+                }\r
+            }\r
+            if (mFocusSpan != null)\r
+            {\r
+                Timer timer = new Timer(TimerCallback, null,1000, Timeout.Infinite);\r
+\r
+                //mFocusSpan.Focus();\r
+            }\r
+            string error = "(行 " + ErrorLine + " - 列 " + (column > -1 ? column.ToString() : string.Empty);\r
+            error += ")"+ ErrorMessage;\r
+\r
+\r
+            mLblHeader.Content = error;\r
+\r
+            if (FuncContext != null)\r
+            {\r
+                mBtnShowWatchWindow.IsEnabled = true;\r
+            }\r
+        }\r
+\r
+        Span mFocusSpan = null;\r
+        private void addLine(int lineNo, string line, bool empasis)\r
+        {\r
+            Span span = new Span();\r
+            Run run = new Run(lineNo.ToString() + ": ");\r
+            span.Inlines.Add(run);\r
+            run = new Run(line);\r
+            span.Inlines.Add(run);\r
+            if (empasis)\r
+            {\r
+                span.Background = new SolidColorBrush(Colors.DeepPink);\r
+                span.Foreground = new SolidColorBrush(Colors.Silver);\r
+                mFocusSpan = span;\r
+            }\r
+            mParaBody.LineStackingStrategy = LineStackingStrategy.MaxHeight;\r
+            mParaBody.Inlines.Add(span);\r
+            mParaBody.Inlines.Add(new LineBreak());\r
+        }\r
+\r
+        private void TimerCallback(object param)\r
+        {\r
+            this.Dispatcher.BeginInvoke(DispatcherPriority.Normal,\r
+                (ThreadStart)delegate()\r
+            {\r
+                mFocusSpan.Focus();\r
+            });\r
+        }\r
+\r
+        private void NTScriptDebugger_Closed(object sender, EventArgs e)\r
+        {\r
+            if (mDontShowWindow)\r
+            {\r
+                mWindows.Clear();\r
+                return;\r
+            }\r
+            if (mWindows.Count > 0)\r
+            {\r
+                mWindows.RemoveAt(0);\r
+                if (mWindows.Count > 0)\r
+                    mWindows[0].Show();\r
+            }\r
+        }\r
+\r
+        private void mChkDontShowWindow_Checked(object sender, RoutedEventArgs e)\r
+        {\r
+            mDontShowWindow = true;\r
+        }\r
+\r
+        private void mChkDontShowWindow_Unchecked(object sender, RoutedEventArgs e)\r
+        {\r
+\r
+        }\r
+\r
+        private void mBtnClose_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            Close();\r
+        }\r
+        private void mBtnShowWatchWindow_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            List < DebugMemory> list;\r
+            if (FuncContext.getMemoryList(out list))\r
+            {\r
+                NTMemoryInspectionWindow win = new NTMemoryInspectionWindow();\r
+                win.initParam(list);\r
+                win.ShowWindow();\r
+            }\r
+        }        \r
+    }\r
+}\r
diff --git a/NT2chCtrl45/Properties/AssemblyInfo.cs b/NT2chCtrl45/Properties/AssemblyInfo.cs
new file mode 100755 (executable)
index 0000000..2a84b12
--- /dev/null
@@ -0,0 +1,55 @@
+using System.Reflection;\r
+using System.Resources;\r
+using System.Runtime.CompilerServices;\r
+using System.Runtime.InteropServices;\r
+using System.Windows;\r
+\r
+// アセンブリに関する一般情報は以下の属性セットをとおして制御されます。\r
+// アセンブリに関連付けられている情報を変更するには、\r
+// これらの属性値を変更してください。\r
+[assembly: AssemblyTitle("NT2chCtrl45")]\r
+[assembly: AssemblyDescription("")]\r
+[assembly: AssemblyConfiguration("")]\r
+[assembly: AssemblyCompany("")]\r
+[assembly: AssemblyProduct("NT2chCtrl45")]\r
+[assembly: AssemblyCopyright("Copyright ©  2012")]\r
+[assembly: AssemblyTrademark("")]\r
+[assembly: AssemblyCulture("")]\r
+\r
+// ComVisible を false に設定すると、その型はこのアセンブリ内で COM コンポーネントから\r
+// 参照不可能になります。COM からこのアセンブリ内の型にアクセスする場合は、\r
+// その型の ComVisible 属性を true に設定してください。\r
+[assembly: ComVisible(false)]\r
+\r
+//ローカライズ可能なアプリケーションのビルドを開始するには、\r
+//.csproj ファイルの <UICulture>CultureYouAreCodingWith</UICulture> を\r
+//<PropertyGroup> 内部で設定します。たとえば、\r
+//ソース ファイルで英語を使用している場合、<UICulture> を en-US に設定します。次に、\r
+//下の NeutralResourceLanguage 属性のコメントを解除します。下の行の "en-US" を\r
+//プロジェクト ファイルの UICulture 設定と一致するよう更新します。\r
+\r
+//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]\r
+\r
+\r
+[assembly:ThemeInfo(\r
+    ResourceDictionaryLocation.None, //テーマ固有のリソース ディクショナリが置かれている場所\r
+                             //(リソースがページ、\r
+                             //またはアプリケーション リソース ディクショナリに見つからない場合に使用されます)\r
+    ResourceDictionaryLocation.SourceAssembly //汎用リソース ディクショナリが置かれている場所\r
+                                      //(リソースがページ、\r
+                                      //アプリケーション、またはいずれのテーマ固有のリソース ディクショナリにも見つからない場合に使用されます)\r
+)]\r
+\r
+\r
+// アセンブリのバージョン情報は、以下の 4 つの値で構成されています:\r
+//\r
+//      Major Version\r
+//      Minor Version \r
+//      Build Number\r
+//      Revision\r
+//\r
+// すべての値を指定するか、下のように '*' を使ってビルドおよびリビジョン番号を \r
+// 既定値にすることができます:\r
+// [assembly: AssemblyVersion("1.0.*")]\r
+[assembly: AssemblyVersion("2.3.6.0")]\r
+[assembly: AssemblyFileVersion("2.3.6.0")]\r
diff --git a/NT2chCtrl45/Properties/Resources.Designer.cs b/NT2chCtrl45/Properties/Resources.Designer.cs
new file mode 100755 (executable)
index 0000000..a61296e
--- /dev/null
@@ -0,0 +1,62 @@
+//------------------------------------------------------------------------------\r
+// <auto-generated>\r
+//     このコードはツールによって生成されました。\r
+//     ランタイム バージョン:4.0.30319.17626\r
+//\r
+//     このファイルへの変更は、以下の状況下で不正な動作の原因になったり、\r
+//     コードが再生成されるときに損失したりします\r
+// </auto-generated>\r
+//------------------------------------------------------------------------------\r
+\r
+namespace NT2chCtrl45.Properties {\r
+    \r
+    \r
+    /// <summary>\r
+    ///   ローカライズされた文字列などを検索するための、厳密に型指定されたリソース クラスです。\r
+    /// </summary>\r
+    // このクラスは StronglyTypedResourceBuilder クラスによって ResGen\r
+    // または Visual Studio のようなツールを使用して自動生成されました。\r
+    // メンバーを追加または削除するには、.ResX ファイルを編集して、/str オプションと共に\r
+    // ResGen を実行し直すか、または VS プロジェクトをビルドし直します。\r
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]\r
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\r
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]\r
+    internal class Resources {\r
+        \r
+        private static global::System.Resources.ResourceManager resourceMan;\r
+        \r
+        private static global::System.Globalization.CultureInfo resourceCulture;\r
+        \r
+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]\r
+        internal Resources() {\r
+        }\r
+        \r
+        /// <summary>\r
+        ///   このクラスに使用される、キャッシュされた ResourceManager のインスタンスを返します。\r
+        /// </summary>\r
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]\r
+        internal static global::System.Resources.ResourceManager ResourceManager {\r
+            get {\r
+                if ((resourceMan == null)) {\r
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("NT2chCtrl45.Properties.Resources", typeof(Resources).Assembly);\r
+                    resourceMan = temp;\r
+                }\r
+                return resourceMan;\r
+            }\r
+        }\r
+        \r
+        /// <summary>\r
+        ///   厳密に型指定されたこのリソース クラスを使用して、すべての検索リソースに対し、\r
+        ///   現在のスレッドの CurrentUICulture プロパティをオーバーライドします。\r
+        /// </summary>\r
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]\r
+        internal static global::System.Globalization.CultureInfo Culture {\r
+            get {\r
+                return resourceCulture;\r
+            }\r
+            set {\r
+                resourceCulture = value;\r
+            }\r
+        }\r
+    }\r
+}\r
diff --git a/NT2chCtrl45/Properties/Resources.resx b/NT2chCtrl45/Properties/Resources.resx
new file mode 100755 (executable)
index 0000000..ffecec8
--- /dev/null
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<root>\r
+  <!-- \r
+    Microsoft ResX Schema \r
+    \r
+    Version 2.0\r
+    \r
+    The primary goals of this format is to allow a simple XML format \r
+    that is mostly human readable. The generation and parsing of the \r
+    various data types are done through the TypeConverter classes \r
+    associated with the data types.\r
+    \r
+    Example:\r
+    \r
+    ... ado.net/XML headers & schema ...\r
+    <resheader name="resmimetype">text/microsoft-resx</resheader>\r
+    <resheader name="version">2.0</resheader>\r
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\r
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\r
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>\r
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>\r
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">\r
+        <value>[base64 mime encoded serialized .NET Framework object]</value>\r
+    </data>\r
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">\r
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\r
+        <comment>This is a comment</comment>\r
+    </data>\r
+                \r
+    There are any number of "resheader" rows that contain simple \r
+    name/value pairs.\r
+    \r
+    Each data row contains a name, and value. The row also contains a \r
+    type or mimetype. Type corresponds to a .NET class that support \r
+    text/value conversion through the TypeConverter architecture. \r
+    Classes that don't support this are serialized and stored with the \r
+    mimetype set.\r
+    \r
+    The mimetype is used for serialized objects, and tells the \r
+    ResXResourceReader how to depersist the object. This is currently not \r
+    extensible. For a given mimetype the value must be set accordingly:\r
+    \r
+    Note - application/x-microsoft.net.object.binary.base64 is the format \r
+    that the ResXResourceWriter will generate, however the reader can \r
+    read any of the formats listed below.\r
+    \r
+    mimetype: application/x-microsoft.net.object.binary.base64\r
+    value   : The object must be serialized with \r
+            : System.Serialization.Formatters.Binary.BinaryFormatter\r
+            : and then encoded with base64 encoding.\r
+    \r
+    mimetype: application/x-microsoft.net.object.soap.base64\r
+    value   : The object must be serialized with \r
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\r
+            : and then encoded with base64 encoding.\r
+\r
+    mimetype: application/x-microsoft.net.object.bytearray.base64\r
+    value   : The object must be serialized into a byte array \r
+            : using a System.ComponentModel.TypeConverter\r
+            : and then encoded with base64 encoding.\r
+    -->\r
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">\r
+    <xsd:element name="root" msdata:IsDataSet="true">\r
+      <xsd:complexType>\r
+        <xsd:choice maxOccurs="unbounded">\r
+          <xsd:element name="metadata">\r
+            <xsd:complexType>\r
+              <xsd:sequence>\r
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />\r
+              </xsd:sequence>\r
+              <xsd:attribute name="name" type="xsd:string" />\r
+              <xsd:attribute name="type" type="xsd:string" />\r
+              <xsd:attribute name="mimetype" type="xsd:string" />\r
+            </xsd:complexType>\r
+          </xsd:element>\r
+          <xsd:element name="assembly">\r
+            <xsd:complexType>\r
+              <xsd:attribute name="alias" type="xsd:string" />\r
+              <xsd:attribute name="name" type="xsd:string" />\r
+            </xsd:complexType>\r
+          </xsd:element>\r
+          <xsd:element name="data">\r
+            <xsd:complexType>\r
+              <xsd:sequence>\r
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />\r
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />\r
+              </xsd:sequence>\r
+              <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />\r
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />\r
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />\r
+            </xsd:complexType>\r
+          </xsd:element>\r
+          <xsd:element name="resheader">\r
+            <xsd:complexType>\r
+              <xsd:sequence>\r
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />\r
+              </xsd:sequence>\r
+              <xsd:attribute name="name" type="xsd:string" use="required" />\r
+            </xsd:complexType>\r
+          </xsd:element>\r
+        </xsd:choice>\r
+      </xsd:complexType>\r
+    </xsd:element>\r
+  </xsd:schema>\r
+  <resheader name="resmimetype">\r
+    <value>text/microsoft-resx</value>\r
+  </resheader>\r
+  <resheader name="version">\r
+    <value>2.0</value>\r
+  </resheader>\r
+  <resheader name="reader">\r
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\r
+  </resheader>\r
+  <resheader name="writer">\r
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\r
+  </resheader>\r
+</root>
\ No newline at end of file
diff --git a/NT2chCtrl45/Properties/Settings.Designer.cs b/NT2chCtrl45/Properties/Settings.Designer.cs
new file mode 100755 (executable)
index 0000000..1ac0f4a
--- /dev/null
@@ -0,0 +1,30 @@
+//------------------------------------------------------------------------------\r
+// <auto-generated>\r
+//     This code was generated by a tool.\r
+//     Runtime Version:4.0.30319.17626\r
+//\r
+//     Changes to this file may cause incorrect behavior and will be lost if\r
+//     the code is regenerated.\r
+// </auto-generated>\r
+//------------------------------------------------------------------------------\r
+\r
+namespace NT2chCtrl45.Properties\r
+{\r
+    \r
+    \r
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]\r
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]\r
+    internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase\r
+    {\r
+        \r
+        private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));\r
+        \r
+        public static Settings Default\r
+        {\r
+            get\r
+            {\r
+                return defaultInstance;\r
+            }\r
+        }\r
+    }\r
+}\r
diff --git a/NT2chCtrl45/Properties/Settings.settings b/NT2chCtrl45/Properties/Settings.settings
new file mode 100755 (executable)
index 0000000..8f2fd95
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version='1.0' encoding='utf-8'?>\r
+<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">\r
+  <Profiles>\r
+    <Profile Name="(Default)" />\r
+  </Profiles>\r
+  <Settings />\r
+</SettingsFile>
\ No newline at end of file
diff --git a/NT2chCtrl45/ResListAdapter.cs b/NT2chCtrl45/ResListAdapter.cs
new file mode 100755 (executable)
index 0000000..8bdd6b4
--- /dev/null
@@ -0,0 +1,1312 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Windows;\r
+using System.Windows.Controls;\r
+using System.Windows.Documents;\r
+using System.Windows.Media;\r
+using System.Windows.Media.Imaging;\r
+using NT2chCtrl.html;\r
+using NT2chObject;\r
+\r
+namespace NT2chCtrl\r
+{\r
+    partial class ResListAdapter : UIElementListPanel.IUIElementListAdapter\r
+    {\r
+        IThread mCurrentThread = null;\r
+        List<IRes> mResList = null;\r
+        int mPrevReadCount;\r
+\r
+        IUtil mUtil;\r
+        ICommand mCommand;\r
+        NTResViewPanel mMainPanel;\r
+        ResViewCtrlState mState;\r
+\r
+        public ResListAdapter(NTResViewPanel mainPanel, IThread ithread, ICommand icmd, IUtil iutil)\r
+        {\r
+            mState = ResViewCtrlState.getInstance();\r
+            mMainPanel = mainPanel;\r
+            mCurrentThread = ithread;\r
+            mResList = ithread.getResList();\r
+            mPrevReadCount = ithread.getPrevReadCount();\r
+            mCommand = icmd;\r
+            mUtil = iutil;\r
+            initCashData(getCount());\r
+            if (!getZoomValue(out mZoomValue))\r
+                mZoomValue = 95;\r
+            if (mZoomValue < 50 || mZoomValue > 500)\r
+                mZoomValue = 95;\r
+\r
+        }\r
+\r
+        public int getCount()\r
+        {\r
+            return (mResList == null) ? 0 : mResList.Count;\r
+        }\r
+\r
+        public void updateTextSelMode(bool mode)\r
+        {\r
+            if(null == mResCashDataList)\r
+                return;\r
+\r
+            int count = mResCashDataList.Count;\r
+            for (int i = 0; i < count; i++)\r
+            {\r
+                FlowDocumentScrollViewer fdsv = mResCashDataList[i].element\r
+                    as FlowDocumentScrollViewer;\r
+                if (fdsv != null)\r
+                {\r
+                    fdsv.IsSelectionEnabled = mode;\r
+                }\r
+            }\r
+\r
+        }\r
+\r
+        public UIElement getElement(int pos, UIElement convertElement)\r
+        {\r
+            FlowDocumentScrollViewer fdsv;\r
+\r
+            if (pos < 0 || pos >= getCount())\r
+                return null;\r
+\r
+            if (getCount() != mResCashDataList.Count)\r
+            {\r
+                initCashData(getCount());\r
+            }\r
+\r
+            UIElement element = mResCashDataList[pos].element;\r
+            if (element != null)\r
+            {\r
+                fdsv = element as FlowDocumentScrollViewer;\r
+                if (fdsv != null)\r
+                {\r
+                    fdsv.Zoom = mZoomValue;\r
+                    fdsv.IsSelectionEnabled = mMainPanel.getTextSelMode();\r
+\r
+                }\r
+                return element;\r
+            }\r
+\r
+            fdsv = new FlowDocumentScrollViewer();\r
+            fdsv.HorizontalScrollBarVisibility = ScrollBarVisibility.Hidden;\r
+            fdsv.VerticalScrollBarVisibility = ScrollBarVisibility.Hidden;\r
+            fdsv.Margin = new Thickness(0);\r
+            fdsv.Padding = new Thickness(0);\r
+            fdsv.MaxZoom = 500;\r
+            fdsv.MinZoom = 50;\r
+            fdsv.Zoom = mZoomValue;\r
+\r
+            fdsv.IsSelectionEnabled = mMainPanel.getTextSelMode();\r
+\r
+            mUtil.CreateResViewContextMenu(fdsv);\r
+            bool newMsg;\r
+            //int prevReadCnt = mCurrentThread.getPrevReadCount();\r
+            if (mPrevReadCount > 0 && pos > (mPrevReadCount - 1))\r
+            {\r
+                newMsg = true;\r
+            }\r
+            else\r
+            {\r
+                newMsg = false;\r
+            }\r
+\r
+            ResViewCtrlState state = ResViewCtrlState.getInstance();\r
+            FontFamily font = null;\r
+            FontFamily aaFont = null;\r
+            string fontName = NTResViewPanel.getResFontTypeface();\r
+            if (fontName != null)\r
+                //font = new FontFamily(fontName);\r
+                font = html.wpf.FontCash.getFontFamily(fontName);\r
+            fontName = NTResViewPanel.getResAAFontTypeface();\r
+            if (fontName != null)\r
+                //aaFont = new FontFamily(fontName);\r
+                aaFont = html.wpf.FontCash.getFontFamily(fontName);\r
+            FlowDocument fd = new FlowDocument();\r
+\r
+            IRes ires = mResList[pos];\r
+            //ires.\r
+            Section sec;\r
+            if (state.EnableHtmlLayout)\r
+                sec = createResSection2(state, mCurrentThread, ires, newMsg, true, fd);\r
+            else\r
+                sec = createResSection(mCurrentThread, ires, newMsg, true);\r
+\r
+            sec.Margin = new Thickness(0);\r
+            sec.Padding = new Thickness(0);\r
+\r
+            if (aaFont != null && NTResViewPanel.testAsciiArt(ires.getMsg()))\r
+            {\r
+                sec.FontFamily = aaFont;\r
+            }\r
+            else if (font != null)\r
+            {\r
+                sec.FontFamily = font;\r
+            }\r
+\r
+            //document.Blocks.Add(sec);\r
+            //if (mainView)\r
+            ires.setExtra(sec);\r
+\r
+            if (ires.getAttribute(RES_ATTRIBUTE.BOOKMARK))\r
+            {\r
+                addBookmark(mCurrentThread, ires, false);\r
+            }\r
+\r
+            fdsv.Document = fd;\r
+            fd.Blocks.Add(sec);\r
+\r
+            fdsv.Margin = new Thickness(0);\r
+            fdsv.Padding = new Thickness(0);\r
+\r
+            mResCashDataList[pos].element = fdsv;\r
+            mResCashDataList[pos].section = sec;\r
+\r
+            return fdsv;\r
+        }\r
+\r
+        public FlowDocument createDocument(IThread ithread, List<IRes> rList, bool mainView)\r
+        {\r
+\r
+            FlowDocument document = new FlowDocument();\r
+\r
+            FontFamily font = null;\r
+            FontFamily aaFont = null;\r
+            string fontName = NTResViewPanel.getResFontTypeface();\r
+            if (fontName != null)\r
+                font = new FontFamily(fontName);\r
+            fontName = NTResViewPanel.getResAAFontTypeface();\r
+            if (fontName != null)\r
+                aaFont = new FontFamily(fontName);\r
+\r
+\r
+            mPrevReadCount = ithread.getPrevReadCount();\r
+\r
+            int prevMsg;\r
+            if (ithread.getPrevReadCount() <= 0)\r
+                prevMsg = 2000;\r
+            else\r
+                prevMsg = mPrevReadCount - 1;\r
+\r
+\r
+            for (int i = 0; i < rList.Count; i++)\r
+            {\r
+                IRes res = rList[i];\r
+                Section sec = createResSection(ithread, res, (i > prevMsg), false);\r
+                if (sec != null)\r
+                {\r
+                    if (aaFont != null && NTResViewPanel.testAsciiArt(res.getMsg()))\r
+                    {\r
+                        sec.FontFamily = aaFont;\r
+                    }\r
+                    else if (font != null)\r
+                    {\r
+                        sec.FontFamily = font;\r
+                    }\r
+\r
+                    document.Blocks.Add(sec);\r
+                    //if (mainView)\r
+                    //    res.setExtra(sec);\r
+\r
+                    if (res.getAttribute(RES_ATTRIBUTE.BOOKMARK))\r
+                    {\r
+                        addBookmark(ithread, res, false);\r
+                    }\r
+                }\r
+            }\r
+\r
+            return document;\r
+        }\r
+\r
+        Section createResSection2(ResViewCtrlState ctrlState, IThread thread,\r
+            IRes res, bool newMsg, bool topItem, FlowDocument fd)\r
+        {\r
+            Section sec = new Section();\r
+\r
+            sec.Margin = new Thickness(0);\r
+            sec.Padding = new Thickness(0);\r
+\r
+            HtmlParser parser = ctrlState.getResViewLayoutParser();\r
+\r
+            HtmlElement rootElement = parser.CloneHtmlElement();\r
+\r
+            bool mymsg = res.getAttribute(RES_ATTRIBUTE.MYMESSAGE);\r
+            bool reply = res.getAttribute(RES_ATTRIBUTE.REPRY);\r
+            bool bookmark = res.getAttribute(RES_ATTRIBUTE.BOOKMARK);\r
+            bool asciiart = NTResViewPanel.testAsciiArt(res.getMsg());\r
+\r
+            string ngword = null;\r
+            string ngname = null;\r
+            string ngid = null;\r
+            string[] ngWordList = mCommand.GetNgWordList();\r
+            string[] ngIdList = mCommand.GetNgIdList();\r
+            string[] ngNameList = mCommand.GetNgNameList();\r
+\r
+            foreach (string ng in ngNameList)\r
+            {\r
+                string s = ng.Trim();\r
+                if (s.Length == 0)\r
+                    continue;\r
+                if (0 <= res.getName().IndexOf(s))\r
+                {\r
+                    ngname = s;\r
+                    break;\r
+                }\r
+            }\r
+            foreach (string ng in ngIdList)\r
+            {\r
+                string s = ng.Trim();\r
+                if (s.Length == 0)\r
+                    continue;\r
+                if (0 <= res.getID().IndexOf(s))\r
+                {\r
+                    ngid = s;\r
+                    break;\r
+                }\r
+            }\r
+            foreach (string ng in ngWordList)\r
+            {\r
+                string s = ng.Trim();\r
+                if (s.Length == 0)\r
+                    continue;\r
+                if (0 <= res.getMsg().IndexOf(s))\r
+                {\r
+                    ngword = s;\r
+                    break;\r
+                }\r
+            }\r
+\r
+            if(!html.wpf.Html2FlowDoc.MargeResDataIntoHtml(rootElement, thread, res, \r
+                    newMsg, mymsg ,reply, bookmark, asciiart,\r
+                    ngword, ngname, ngid, mAmbisuousSearch))\r
+                return sec;\r
+            html.js.JsFunctionContext fCtx;\r
+            html.DebugContext dCtx = new DebugContext();\r
+            if (!parser.runJS(dCtx, rootElement, out fCtx))\r
+            {\r
+                //MessageBox.Show("Error");\r
+                string htmlSource = \r
+                    ResViewCtrlState.getInstance().\r
+                        getResViewLayoutParser().getHtmlSource();\r
+                NTScriptDebugger debugger = new NTScriptDebugger();\r
+                debugger.ErrorMessage = dCtx.mErrorMessage;//parser.getErrorMessage();\r
+                debugger.ErrorLine = dCtx.mCurrentLine;//parser.getErrorLine();\r
+                debugger.ErrorSrcIndex = dCtx.mCurentIndex;//parser.getErrorSrcIndex();\r
+                debugger.HtmlSource = htmlSource;\r
+                debugger.FuncContext = fCtx;\r
+                debugger.initParam();\r
+                NTScriptDebugger.ShowWindow(debugger);\r
+            }\r
+            parser.applyCSS(rootElement);\r
+\r
+            List<HtmlElement> rList = rootElement.getElements(null,\r
+                "body", null, null, null, false);\r
+            if (rList == null || rList.Count == 0)\r
+                return sec;\r
+\r
+            HtmlElement bodyElem = rList[0];\r
+\r
+            Color c;\r
+            if (bodyElem.tryGetBackgroundColor(out c))\r
+            {\r
+                fd.Background = new SolidColorBrush(c);\r
+            }\r
+            Brush brush;\r
+            if (bodyElem.tryGetBackgroundImage(out brush))\r
+            {\r
+                fd.Background = brush;\r
+            }\r
+\r
+            if (!html.wpf.Html2FlowDoc.DrawHtml(this, sec, thread, res, bodyElem))\r
+                return sec;\r
+            return sec;\r
+        }\r
+\r
+        Section createResSection(IThread thread, IRes res, bool newMsg, bool topItem)\r
+        {\r
+            Section sec = new Section();\r
+            //if (res.mIsDummy)\r
+            //    return sec;\r
+\r
+            Color c;\r
+            Paragraph paraHeader = new Paragraph();\r
+            if (newMsg)\r
+                c = Colors.LightPink;\r
+            else\r
+                c = Colors.LightGray;\r
+\r
+            paraHeader.Background = new LinearGradientBrush(Colors.White, c, 90.0);\r
+            paraHeader.Padding = new Thickness(3);\r
+\r
+            string[] ngWordList = mCommand.GetNgWordList();\r
+            string[] ngIdList = mCommand.GetNgIdList();\r
+            string[] ngNameList = mCommand.GetNgNameList();\r
+\r
+            foreach (string ng in ngNameList)\r
+            {\r
+                string s = ng.Trim();\r
+                if (s.Length == 0)\r
+                    continue;\r
+                if (0 <= res.getName().IndexOf(s))\r
+                {\r
+                    paraHeader.Inlines.Add(new Run("NG:NAME " + s));\r
+                    sec.Blocks.Add(paraHeader);\r
+                    return sec;\r
+                }\r
+            }\r
+            foreach (string ng in ngIdList)\r
+            {\r
+                string s = ng.Trim();\r
+                if (s.Length == 0)\r
+                    continue;\r
+                if (0 <= res.getID().IndexOf(s))\r
+                {\r
+                    paraHeader.Inlines.Add(new Run("NG:ID " + s));\r
+                    sec.Blocks.Add(paraHeader);\r
+                    return sec;\r
+                }\r
+            }\r
+            foreach (string ng in ngWordList)\r
+            {\r
+                string s = ng.Trim();\r
+                if (s.Length == 0)\r
+                    continue;\r
+                if (0 <= res.getMsg().IndexOf(s))\r
+                {\r
+                    paraHeader.Inlines.Add(new Run("NG:WORD " + s));\r
+                    sec.Blocks.Add(paraHeader);\r
+                    return sec;\r
+                }\r
+            }\r
+\r
+            Run r = new Run();\r
+            r.Text = res.getSequenceNo().ToString() + ":";\r
+            List<object> param = new List<object>();\r
+            param.Add(thread);\r
+            param.Add(res);\r
+            Hyperlink hlink = new Hyperlink();\r
+            hlink.Inlines.Add(r);\r
+            hlink.Tag = param;\r
+            if(topItem)\r
+                hlink.MouseEnter += ResSeqNo_MouseEnter;\r
+            else\r
+                hlink.MouseEnter += ResSeqNoSubItem_MouseEnter;\r
+            hlink.MouseLeftButtonDown += ResSeqNo_MouseLeftButtonDown;\r
+            hlink.PreviewMouseLeftButtonDown += hlink_PreviewMouseLeftButtonDown;\r
+            paraHeader.Inlines.Add(hlink);\r
+\r
+            r = new Run();\r
+            Hyperlink hl = null;\r
+            string name = res.getName();\r
+            try\r
+            {\r
+                int n = int.Parse(name);\r
+                List<int> arr = new List<int>();\r
+                arr.Add(n);\r
+\r
+                arr[0] = n;\r
+                param = new List<object>();\r
+                param.Add(thread);\r
+                param.Add(arr);\r
+                hl = new Hyperlink(new Run(" " + name + " "));\r
+                hl.Tag = param;\r
+                if (getEnablePopupMouseHover())\r
+                    hl.MouseEnter += resLink_MouseEnter;\r
+                else\r
+                    hl.Click += resLink_MouseEnter;\r
+                paraHeader.Inlines.Add(hl);\r
+            }\r
+            catch\r
+            {\r
+                //NTDebug.l(e.Message);\r
+            }\r
+            Span span;\r
+            if (hl == null)\r
+            {\r
+                span = new Span();\r
+                if (res.getAttribute(RES_ATTRIBUTE.MYMESSAGE))\r
+                {\r
+                    name = "<自分>";\r
+                    span.Foreground = Brushes.Red;\r
+                }\r
+                else if (res.getAttribute(RES_ATTRIBUTE.REPRY))\r
+                {\r
+                    name = "<返信>";\r
+                    span.Foreground = Brushes.Purple;\r
+                }\r
+                else\r
+                    span.Foreground = Brushes.Green;\r
+\r
+                r.Text = " " + name + " ";\r
+                span.Inlines.Add(r);\r
+                paraHeader.Inlines.Add(span);\r
+            }\r
+\r
+            r = new Run();\r
+            string mail = res.getMail();\r
+            if (0 < mail.Length)\r
+                r.Text = "(" + mail + ") ";\r
+            else\r
+                r.Text = " --- ";\r
+            span = new Span();\r
+            span.Foreground = Brushes.Blue;\r
+            span.Inlines.Add(r);\r
+            paraHeader.Inlines.Add(span);\r
+\r
+            r = new Run();\r
+            r.Text = res.getDate() + " ";\r
+            span = new Span();\r
+            span.Foreground = Brushes.Black;\r
+            span.Inlines.Add(r);\r
+            paraHeader.Inlines.Add(span);\r
+            string id = res.getID();\r
+            if (id != null && id.Length > 0)\r
+            {\r
+                int before = 0;\r
+                int after = 0;\r
+                bool chk = false;\r
+                List<IRes> rList = thread.getResList();\r
+                List<int> arrSeqNum = new List<int>();\r
+                if (rList != null)\r
+                {\r
+                    int rCnt = rList.Count;\r
+                    for (int i = 0; i < rCnt; i++)\r
+                    {\r
+                        if (!id.Equals(rList[i].getID()))\r
+                            continue;\r
+\r
+                        arrSeqNum.Add(rList[i].getSequenceNo());\r
+\r
+                        if (res.Equals(rList[i]))\r
+                        {\r
+                            chk = true;\r
+                            continue;\r
+                        }\r
+\r
+\r
+                        if (chk)\r
+                            after++;\r
+                        else\r
+                            before++;\r
+                    }\r
+                }\r
+                if (0 < (before + after))\r
+                {\r
+                    param = new List<object>();\r
+                    param.Add(thread);\r
+                    param.Add(arrSeqNum.ToArray());\r
+                    hl = new Hyperlink(new Run("ID:" + id + "(" + (before + 1) + "/" + (before + after + 1) + ")"));\r
+                    hl.Tag = param;\r
+                    if (topItem)\r
+                    {\r
+                        if (getEnablePopupMouseHover())\r
+                            hl.MouseEnter += resLink_MouseEnter;\r
+                        else\r
+                            hl.Click += resLink_MouseEnter;\r
+                    }\r
+                    else\r
+                    {\r
+                        if (getEnablePopupMouseHover())\r
+                            hl.MouseEnter += resLinkSubItem_MouseEnter;\r
+                        else\r
+                            hl.Click += resLinkSubItem_MouseEnter;\r
+                    }\r
+                    paraHeader.Inlines.Add(hl);\r
+                }\r
+                else\r
+                {\r
+                    r = new Run();\r
+                    r.Text = "ID:" + id;\r
+                    span = new Span();\r
+                    span.Foreground = Brushes.Black;\r
+                    span.Inlines.Add(r);\r
+                    paraHeader.Inlines.Add(span);\r
+                }\r
+            }\r
+\r
+            sec.Blocks.Add(paraHeader);\r
+\r
+            Paragraph paraBody = new Paragraph();\r
+\r
+            Thickness thick = paraBody.Padding;\r
+            thick.Left += 3;\r
+            thick.Top = 0;\r
+            parseResMsg(paraBody, thread, res, -1, -1, topItem);\r
+\r
+            sec.Blocks.Add(paraBody);\r
+\r
+            return sec;\r
+        }\r
+\r
+        public void parseResMsg(Paragraph paraBody, IThread thread, IRes res,\r
+    int emphStart, int emphEnd, bool topItem)\r
+        {\r
+            string source = res.getMsg();\r
+            int i = 0;\r
+            int start = 0;\r
+\r
+            int n;\r
+            start = 0;\r
+            i = 0;\r
+            for (; i < source.Length; i++)\r
+            {\r
+                //レス参照を判定します。\r
+                n = NTResViewPanel.getUtil().ParseResLinkReference(source, i);\r
+                if (n > 0)\r
+                {\r
+                    Hyperlink hl = new Hyperlink();\r
+                    Run r = new Run();\r
+                    string link = source.Substring(i, n);\r
+                    r.Text = link;\r
+                    hl.Inlines.Add(r);\r
+                    List<object> param = new List<object>();\r
+                    param.Add(thread);\r
+                    int[] arr = NTResViewPanel.getUtil().ParseResLinkReferenceNumber(link);\r
+                    param.Add(arr);\r
+                    hl.Tag = param;\r
+                    if (topItem)\r
+                    {\r
+                        if (getEnablePopupMouseHover())\r
+                            hl.MouseEnter += resLink_MouseEnter;\r
+                        else\r
+                            hl.Click += resLink_MouseEnter;\r
+                    }\r
+                    else\r
+                    {\r
+                        if (getEnablePopupMouseHover())\r
+                            hl.MouseEnter += resLinkSubItem_MouseEnter;\r
+                        else\r
+                            hl.Click += resLinkSubItem_MouseEnter;\r
+                    }\r
+                    paraBody.Inlines.Add(hl);\r
+                    i += (n - 1);\r
+                    start = i + 1;\r
+                    continue;\r
+                }\r
+                char c = source[i];\r
+\r
+                //datファイルのhtmlのリンクタグ<a href=>は、表示テキストと同じ内容なので(多分)\r
+                //単純にタグを削除します。<br>タグは改行エレメントにします。\r
+                //その他のタグは見たことが無いので考慮しません。\r
+                if (c == '<')\r
+                {\r
+                    //開始タグの前に未設定の文字列が有るときは、最初に表示エレメントを設定する。\r
+                    if (start < i)\r
+                    {\r
+                        Run r;\r
+                        if (start <= emphStart && i >= emphEnd)\r
+                        {\r
+                            if (start < emphStart)\r
+                            {\r
+                                r = new Run();\r
+                                r.Text = source.Substring(start, emphStart - start);\r
+                                paraBody.Inlines.Add(r);\r
+                            }\r
+                            r = new Run();\r
+                            r.Text = source.Substring(emphStart, emphEnd - emphStart);\r
+                            r.Background = new SolidColorBrush(Colors.Yellow);\r
+                            r.Foreground = new SolidColorBrush(Colors.Green);\r
+                            paraBody.Inlines.Add(r);\r
+                            if (emphEnd < i)\r
+                            {\r
+                                r = new Run();\r
+                                r.Text = source.Substring(emphEnd, i - emphEnd);\r
+                                paraBody.Inlines.Add(r);\r
+                            }\r
+                        }\r
+                        else\r
+                        {\r
+                            r = new Run();\r
+                            r.Text = source.Substring(start, i - start);\r
+                            paraBody.Inlines.Add(r);\r
+                        }\r
+                    }\r
+                    n = source.IndexOf('>', i + 1);\r
+                    if (n > -1)\r
+                    {\r
+                        string s1 = source.Substring(i + 1, n - (i + 1)).Trim();\r
+                        if (-1 < s1.IndexOf("A HREF", StringComparison.CurrentCultureIgnoreCase)\r
+                            || s1.Equals("/A", StringComparison.CurrentCultureIgnoreCase))\r
+                        {\r
+                            i = n;\r
+                            start = n + 1;\r
+                        }\r
+                        else if (s1.Equals("br", StringComparison.CurrentCultureIgnoreCase))\r
+                        {\r
+                            LineBreak rb = new LineBreak();\r
+                            paraBody.Inlines.Add(rb);\r
+                            i = n;\r
+                            start = n + 1;\r
+                        }\r
+                        else\r
+                        {\r
+                            start = i;\r
+                        }\r
+                    }\r
+                    else\r
+                    {\r
+                        start = i;\r
+                    }\r
+                }\r
+                else\r
+                {\r
+                    int urlLength = mUtil.ParseURLString(source, i);\r
+                    if (urlLength >= 0)\r
+                    {\r
+\r
+                        Run r;\r
+                        if (start > 0 && start < i)\r
+                        {\r
+                            r = new Run();\r
+                            r.Text = source.Substring(start, i - start);\r
+                            paraBody.Inlines.Add(r);\r
+                        }\r
+\r
+                        Hyperlink hl = new Hyperlink();\r
+                        r = new Run();\r
+                        string link = source.Substring(i, urlLength);\r
+                        r.Text = link;\r
+                        hl.Inlines.Add(r);\r
+                        if (c == 't' || c == 'T')\r
+                            link = "h" + link;\r
+\r
+                        if (chkGraphicLink(link))\r
+                        {\r
+                            ThumbnailImageHelper helper =\r
+                                ThumbnailImageHelper.CreateInstance(link);\r
+                            paraBody.Inlines.Add(helper.GetContainer());\r
+                            mCommand.SetThumbnailImage(helper, link);\r
+                        }\r
+\r
+                        try\r
+                        {\r
+                            hl.NavigateUri = new Uri(link);\r
+                            hl.Click += urlLink_Click;\r
+                        }\r
+                        catch// (Exception e)\r
+                        {\r
+                            //NTDebug.l(e.Message + ": " + link);\r
+                        }\r
+\r
+                        paraBody.Inlines.Add(hl);\r
+                        i += urlLength;// n1 + scheme_len + (n - i);\r
+                        start = i;\r
+                        i--;\r
+                    }\r
+                }\r
+            }//end of for\r
+\r
+            //処理が終わっていない文字列を表示エレメントに入れます。\r
+            if (start < source.Length)\r
+            {\r
+                Run r;\r
+                if (start <= emphStart && source.Length >= emphEnd)\r
+                {\r
+                    if (start < emphStart)\r
+                    {\r
+                        r = new Run();\r
+                        r.Text = source.Substring(start, emphStart - start);\r
+                        paraBody.Inlines.Add(r);\r
+                    }\r
+                    r = new Run();\r
+                    r.Text = source.Substring(emphStart, emphEnd - emphStart);\r
+                    r.Background = new SolidColorBrush(Colors.Yellow);\r
+                    r.Foreground = new SolidColorBrush(Colors.Green);\r
+                    paraBody.Inlines.Add(r);\r
+                    if (emphEnd < source.Length)\r
+                    {\r
+                        r = new Run();\r
+                        r.Text = source.Substring(emphEnd, source.Length - emphEnd);\r
+                        paraBody.Inlines.Add(r);\r
+                    }\r
+                }\r
+                else\r
+                {\r
+                    r = new Run();\r
+                    r.Text = source.Substring(start, source.Length - start);\r
+                    paraBody.Inlines.Add(r);\r
+                }\r
+            }\r
+            int[] refArray = res.getReferenceArray();\r
+            setFooter(thread, paraBody, refArray, topItem);\r
+        }\r
+\r
+        public void parseSequenceNo(InlineCollection inlines, IThread thread, IRes res)\r
+            //int emphStart, int emphEnd, bool topItem)\r
+        {\r
+            Run r = new Run();\r
+            r.Text = res.getSequenceNo().ToString();\r
+            List<object> param = new List<object>();\r
+            param.Add(thread);\r
+            param.Add(res);\r
+            Hyperlink hlink = new Hyperlink();\r
+            hlink.Inlines.Add(r);\r
+            hlink.Tag = param;\r
+            //if (topItem)\r
+            hlink.MouseEnter += ResSeqNo_MouseEnter;\r
+            //else\r
+            //    hlink.MouseEnter += ResSeqNoSubItem_MouseEnter;\r
+            hlink.MouseLeftButtonDown += ResSeqNo_MouseLeftButtonDown;\r
+            hlink.PreviewMouseLeftButtonDown += hlink_PreviewMouseLeftButtonDown;\r
+            inlines.Add(hlink);\r
+        }\r
+\r
+\r
+        public void parseBackwardReferences(InlineCollection inlines, IThread thread, IRes res)\r
+        {\r
+            int [] refArray = res.getReferenceArray();\r
+            string extraText = formatReferenceNumbers(refArray);\r
+            if (extraText != null)\r
+            {\r
+                //inlines.Add(new LineBreak());\r
+                Run r = new Run();\r
+                //r.Text = "-----------------------------";\r
+                //inlines.Add(r);\r
+                //inlines.Add(new LineBreak());\r
+                //r = new Run();\r
+                r.Text = extraText;\r
+                Hyperlink hl = new Hyperlink();\r
+\r
+                //if (topItem)\r
+                //{\r
+                    if (getEnablePopupMouseHover())\r
+                        hl.MouseEnter += resLink_MouseEnter;\r
+                    else\r
+                        hl.Click += resLink_MouseEnter;\r
+                /*}\r
+                else\r
+                {\r
+                    if (getEnablePopupMouseHover())\r
+                        hl.MouseEnter += resLinkSubItem_MouseEnter;\r
+                    else\r
+                        hl.Click += resLinkSubItem_MouseEnter;\r
+                }*/\r
+                List<object> param = new List<object>();\r
+                param.Add(thread);\r
+                param.Add(refArray);\r
+                hl.Tag = param;\r
+                hl.Inlines.Add(r);\r
+                inlines.Add(hl);\r
+            }\r
+        }\r
+\r
+\r
+        public void parseIdentifier(InlineCollection inlines, IThread thread, IRes res)\r
+        {\r
+            Span span;\r
+            Run r;\r
+            string id = res.getID();\r
+            if (id != null && id.Length > 0)\r
+            {\r
+                int before = 0;\r
+                int after = 0;\r
+                bool chk = false;\r
+                List<IRes> rList = thread.getResList();\r
+                List<int> arrSeqNum = new List<int>();\r
+                if (rList != null)\r
+                {\r
+                    int rCnt = rList.Count;\r
+                    for (int i = 0; i < rCnt; i++)\r
+                    {\r
+                        if (!id.Equals(rList[i].getID()))\r
+                            continue;\r
+\r
+                        arrSeqNum.Add(rList[i].getSequenceNo());\r
+\r
+                        if (res.Equals(rList[i]))\r
+                        {\r
+                            chk = true;\r
+                            continue;\r
+                        }\r
+\r
+\r
+                        if (chk)\r
+                            after++;\r
+                        else\r
+                            before++;\r
+                    }\r
+                }\r
+                if (0 < (before + after))\r
+                {\r
+                    List<object> param = new List<object>();\r
+                    param.Add(thread);\r
+                    param.Add(arrSeqNum.ToArray());\r
+                    Hyperlink hl = new Hyperlink(new Run(id + "(" + (before + 1) + "/" + (before + after + 1) + ")"));\r
+                    hl.Tag = param;\r
+                    //if (topItem)\r
+                    //{\r
+                        if (getEnablePopupMouseHover())\r
+                            hl.MouseEnter += resLink_MouseEnter;\r
+                        else\r
+                            hl.Click += resLink_MouseEnter;\r
+                    /*}\r
+                    else\r
+                    {\r
+                        if (getEnablePopupMouseHover())\r
+                            hl.MouseEnter += resLinkSubItem_MouseEnter;\r
+                        else\r
+                            hl.Click += resLinkSubItem_MouseEnter;\r
+                    }*/\r
+                    inlines.Add(hl);\r
+                }\r
+                else\r
+                {\r
+                    r = new Run();\r
+                    r.Text = id;\r
+                    span = new Span();\r
+                    span.Foreground = Brushes.Black;\r
+                    span.Inlines.Add(r);\r
+                    inlines.Add(span);\r
+                }\r
+            }\r
+        }\r
+#if false\r
+        public void parseResMsg(InlineCollection inlines, IThread thread, IRes res, \r
+            int emphStart, int emphEnd, bool topItem)\r
+        {\r
+            string source = res.getMsg();\r
+            int i = 0;\r
+            int start = 0;\r
+\r
+            int n;\r
+            start = 0;\r
+            i = 0;\r
+            for (; i < source.Length; i++)\r
+            {\r
+                //レス参照を判定します。\r
+                n = NTResViewPanel.getUtil().ParseResLinkReference(source, i);\r
+                if (n > 0)\r
+                {\r
+                    Hyperlink hl = new Hyperlink();\r
+                    Run r = new Run();\r
+                    string link = source.Substring(i, n);\r
+                    r.Text = link;\r
+                    hl.Inlines.Add(r);\r
+                    List<object> param = new List<object>();\r
+                    param.Add(thread);\r
+                    int[] arr = NTResViewPanel.getUtil().ParseResLinkReferenceNumber(link);\r
+                    param.Add(arr);\r
+                    hl.Tag = param;\r
+                    if (topItem)\r
+                    {\r
+                        if (getEnablePopupMouseHover())\r
+                            hl.MouseEnter += resLink_MouseEnter;\r
+                        else\r
+                            hl.Click += resLink_MouseEnter;\r
+                    }\r
+                    else\r
+                    {\r
+                        if (getEnablePopupMouseHover())\r
+                            hl.MouseEnter += resLinkSubItem_MouseEnter;\r
+                        else\r
+                            hl.Click += resLinkSubItem_MouseEnter;\r
+                    }\r
+                    inlines.Add(hl);\r
+                    i += (n - 1);\r
+                    start = i + 1;\r
+                    continue;\r
+                }\r
+                char c = source[i];\r
+\r
+                //datファイルのhtmlのリンクタグ<a href=>は、表示テキストと同じ内容なので(多分)\r
+                //単純にタグを削除します。<br>タグは改行エレメントにします。\r
+                //その他のタグは見たことが無いので考慮しません。\r
+                if (c == '<')\r
+                {\r
+                    //開始タグの前に未設定の文字列が有るときは、最初に表示エレメントを設定する。\r
+                    if (start < i)\r
+                    {\r
+                        Run r;\r
+                        if (start <= emphStart && i >= emphEnd)\r
+                        {\r
+                            if (start < emphStart)\r
+                            {\r
+                                r = new Run();\r
+                                r.Text = source.Substring(start, emphStart - start);\r
+                                inlines.Add(r);\r
+                            }\r
+                            r = new Run();\r
+                            r.Text = source.Substring(emphStart, emphEnd - emphStart);\r
+                            r.Background = new SolidColorBrush(Colors.Yellow);\r
+                            r.Foreground = new SolidColorBrush(Colors.Green);\r
+                            inlines.Add(r);\r
+                            if (emphEnd < i)\r
+                            {\r
+                                r = new Run();\r
+                                r.Text = source.Substring(emphEnd, i - emphEnd);\r
+                                inlines.Add(r);\r
+                            }\r
+                        }\r
+                        else\r
+                        {\r
+                            r = new Run();\r
+                            r.Text = source.Substring(start, i - start);\r
+                            inlines.Add(r);\r
+                        }\r
+                    }\r
+                    n = source.IndexOf('>', i + 1);\r
+                    if (n > -1)\r
+                    {\r
+                        string s1 = source.Substring(i + 1, n - (i + 1)).Trim();\r
+                        if (-1 < s1.IndexOf("A HREF", StringComparison.CurrentCultureIgnoreCase)\r
+                            || s1.Equals("/A", StringComparison.CurrentCultureIgnoreCase))\r
+                        {\r
+                            i = n;\r
+                            start = n + 1;\r
+                        }\r
+                        else if (s1.Equals("br", StringComparison.CurrentCultureIgnoreCase))\r
+                        {\r
+                            LineBreak rb = new LineBreak();\r
+                            inlines.Add(rb);\r
+                            i = n;\r
+                            start = n + 1;\r
+                        }\r
+                        else\r
+                        {\r
+                            start = i;\r
+                        }\r
+                    }\r
+                    else\r
+                    {\r
+                        start = i;\r
+                    }\r
+                }\r
+                else\r
+                {\r
+                    int urlLength = mUtil.ParseURLString(source, i);\r
+                    if (urlLength >= 0)\r
+                    {\r
+\r
+                        Run r;\r
+                        if (start > 0 && start < i)\r
+                        {\r
+                            r = new Run();\r
+                            r.Text = source.Substring(start, i - start);\r
+                            inlines.Add(r);\r
+                        }\r
+\r
+                        Hyperlink hl = new Hyperlink();\r
+                        r = new Run();\r
+                        string link = source.Substring(i, urlLength);\r
+                        r.Text = link;\r
+                        hl.Inlines.Add(r);\r
+                        if (c == 't' || c == 'T')\r
+                            link = "h" + link;\r
+\r
+                        if (chkGraphicLink(link))\r
+                        {\r
+                            ThumbnailImageHelper helper =\r
+                                ThumbnailImageHelper.CreateInstance(link);\r
+                            inlines.Add(helper.GetContainer());\r
+                            mCommand.SetThumbnailImage(helper, link);\r
+                        }\r
+\r
+                        try\r
+                        {\r
+                            hl.NavigateUri = new Uri(link);\r
+                            hl.Click += urlLink_Click;\r
+                        }\r
+                        catch// (Exception e)\r
+                        {\r
+                            //NTDebug.l(e.Message + ": " + link);\r
+                        }\r
+\r
+                        inlines.Add(hl);\r
+                        i += urlLength;// n1 + scheme_len + (n - i);\r
+                        start = i;\r
+                        i--;\r
+                    }\r
+                }\r
+            }//end of for\r
+\r
+            //処理が終わっていない文字列を表示エレメントに入れます。\r
+            if (start < source.Length)\r
+            {\r
+                Run r;\r
+                if (start <= emphStart && source.Length >= emphEnd)\r
+                {\r
+                    if (start < emphStart)\r
+                    {\r
+                        r = new Run();\r
+                        r.Text = source.Substring(start, emphStart - start);\r
+                        inlines.Add(r);\r
+                    }\r
+                    r = new Run();\r
+                    r.Text = source.Substring(emphStart, emphEnd - emphStart);\r
+                    r.Background = new SolidColorBrush(Colors.Yellow);\r
+                    r.Foreground = new SolidColorBrush(Colors.Green);\r
+                    inlines.Add(r);\r
+                    if (emphEnd < source.Length)\r
+                    {\r
+                        r = new Run();\r
+                        r.Text = source.Substring(emphEnd, source.Length - emphEnd);\r
+                        inlines.Add(r);\r
+                    }\r
+                }\r
+                else\r
+                {\r
+                    r = new Run();\r
+                    r.Text = source.Substring(start, source.Length - start);\r
+                    inlines.Add(r);\r
+                }\r
+            }\r
+            //int[] refArray = res.getReferenceArray();\r
+            //setFooter(thread, paraBody, refArray, topItem);\r
+        }\r
+#endif\r
+        public void setThumbnailImage(ThumbnailImageHelper helper, string link)\r
+        {\r
+            mCommand.SetThumbnailImage(helper, link);\r
+        }\r
+\r
+        bool chkGraphicLink(string src)\r
+        {\r
+            if (!chkShowThumbnail())\r
+                return false;\r
+\r
+            if (src == null || src.Length < 4)\r
+                return false;\r
+            int idx = src.LastIndexOf('.');\r
+            if (idx < 0)\r
+                return false;\r
+\r
+            string suffix = src.Substring(idx + 1).ToLower();\r
+            switch (suffix)\r
+            {\r
+                case "png":\r
+                case "jpg":\r
+                case "jpeg":\r
+                case "bmp":\r
+                case "gif":\r
+                    return true;\r
+                default:\r
+                    return false;\r
+            }\r
+        }\r
+        bool chkShowThumbnail()\r
+        {\r
+            object o;\r
+            Dictionary<PREF_PARAM, object> dict = mCommand.GetPreference();\r
+            if (!dict.TryGetValue(PREF_PARAM.RES_VIEW_SHOW_THUMBNAIL, out o))\r
+                return false;\r
+\r
+            string show = o as string;\r
+            if (show == null)\r
+                return false;\r
+\r
+            return show.Equals(bool.TrueString);\r
+        }\r
+        void setFooter(IThread thread, Paragraph para, int[] refArray , bool topItem)\r
+        {\r
+            string extraText = formatReferenceNumbers(refArray);\r
+            if (extraText != null)\r
+            {\r
+                para.Inlines.Add(new LineBreak());\r
+                Run r = new Run();\r
+                r.Text = "-----------------------------";\r
+                para.Inlines.Add(r);\r
+                para.Inlines.Add(new LineBreak());\r
+                r = new Run();\r
+                r.Text = extraText;\r
+                Hyperlink hl = new Hyperlink();\r
+\r
+                if (topItem)\r
+                {\r
+                    if (getEnablePopupMouseHover())\r
+                        hl.MouseEnter += resLink_MouseEnter;\r
+                    else\r
+                        hl.Click += resLink_MouseEnter;\r
+                }\r
+                else\r
+                {\r
+                    if (getEnablePopupMouseHover())\r
+                        hl.MouseEnter += resLinkSubItem_MouseEnter;\r
+                    else\r
+                        hl.Click += resLinkSubItem_MouseEnter;\r
+                }\r
+                List<object> param = new List<object>();\r
+                param.Add(thread);\r
+                param.Add(refArray);\r
+                hl.Tag = param;\r
+                hl.Inlines.Add(r);\r
+                para.Inlines.Add(hl);\r
+            }\r
+\r
+        }\r
+\r
+        public static string formatReferenceNumbers(int[] valList)\r
+        {\r
+            if (null == valList) { return null; }\r
+            if (0 >= valList.Length) { return null; }\r
+\r
+            StringBuilder buf = new StringBuilder();\r
+            buf.Append("<<");\r
+\r
+            bool flagFirst = true;\r
+\r
+            int prevVal = 0;\r
+            int i = 0;\r
+            for (; i < valList.Length - 1; i++)\r
+            {\r
+                int val1 = valList[i];\r
+                int val2 = valList[i + 1];\r
+                if (val1 == val2 - 1)\r
+                {\r
+                    if (0 == prevVal)\r
+                    {\r
+                        prevVal = val1;\r
+                    }\r
+                }\r
+                else\r
+                {\r
+                    if (!flagFirst)\r
+                    {\r
+                        buf.Append(',');\r
+                    }\r
+                    else\r
+                    {\r
+                        flagFirst = false;\r
+                    }\r
+                    if (0 != prevVal)\r
+                    {\r
+                        buf.Append(prevVal.ToString());\r
+                        buf.Append('-');\r
+                        buf.Append(val1.ToString());\r
+                        prevVal = 0;\r
+                    }\r
+                    else\r
+                    {\r
+                        buf.Append(val1.ToString());\r
+                    }\r
+                }\r
+            }\r
+\r
+            if (!flagFirst)\r
+            {\r
+                buf.Append(',');\r
+            }\r
+            if (0 != prevVal)\r
+            {\r
+                buf.Append(prevVal.ToString());\r
+                buf.Append('-');\r
+                buf.Append(valList[i].ToString());\r
+            }\r
+            else\r
+            {\r
+                buf.Append(valList[i].ToString());\r
+            }\r
+\r
+            return buf.ToString();\r
+        }\r
+        public void removeBookmark(IThread ithread, IRes ires, bool save)\r
+        {\r
+            if (save && !NTResViewPanel.getCommand().DeleteBookmark(ithread, ires))\r
+                return;\r
+\r
+            ResViewCtrlState state = ResViewCtrlState.getInstance();\r
+            if (state.EnableHtmlLayout)\r
+            {\r
+                if (save)\r
+                {\r
+                    mResCashDataList.Clear();\r
+                    mMainPanel.InvalidateItems();\r
+                }\r
+            }\r
+            else\r
+            {\r
+                Section sec = ires.getExtra() as Section;\r
+                if (sec == null)\r
+                    return;\r
+\r
+                if (2 > sec.Blocks.Count)\r
+                    return;\r
+\r
+                Paragraph paraBody = sec.Blocks.LastBlock as Paragraph;\r
+\r
+                if (paraBody == null)\r
+                    return;\r
+\r
+                Inline il = paraBody.Inlines.FirstInline;\r
+                if (il == null)\r
+                    return;\r
+                Span span = il as Span;\r
+                if (span == null)\r
+                    return;\r
+                Hyperlink hl = span as Hyperlink;\r
+                if (hl != null)\r
+                    return;\r
+                paraBody.Inlines.Remove(span);\r
+            }\r
+        }\r
+\r
+        public void addBookmark(IThread ithread, IRes ires, bool save)\r
+        {\r
+            if (save && !NTResViewPanel.getCommand().AddBookmark(ithread, ires))\r
+                return;\r
+\r
+            ResViewCtrlState state = ResViewCtrlState.getInstance();\r
+            if (state.EnableHtmlLayout)\r
+            {\r
+                if (save)\r
+                {\r
+                    mResCashDataList.Clear();\r
+                    mMainPanel.InvalidateItems();\r
+                }\r
+            }\r
+            else\r
+            {\r
+\r
+                Section sec = ires.getExtra() as Section;\r
+\r
+                if (sec == null)\r
+                    return;\r
+\r
+                if (2 > sec.Blocks.Count)\r
+                    return;\r
+\r
+                Paragraph paraBody = sec.Blocks.LastBlock as Paragraph;\r
+\r
+                if (paraBody == null)\r
+                    return;\r
+\r
+                Inline il = paraBody.Inlines.FirstInline;\r
+                if (il == null)\r
+                    return;\r
+\r
+                Span span = il as Span;\r
+                if (span != null)\r
+                {\r
+                    Hyperlink hl = span as Hyperlink;\r
+                    if (hl == null)\r
+                        return;\r
+                }\r
+\r
+                Image img = new Image();\r
+                img.Width = 12;\r
+                img.Height = 20;\r
+                Uri oUri = new Uri(\r
+                    "pack://application:,,,/NT2chStyle45;component/images/tag.png",\r
+                    UriKind.RelativeOrAbsolute);\r
+                BitmapImage bi = new BitmapImage();\r
+                bi.BeginInit();\r
+                bi.UriSource = oUri;\r
+\r
+                bi.EndInit();\r
+                img.Source = bi;\r
+                img.VerticalAlignment = System.Windows.VerticalAlignment.Center;\r
+                span = new Span();\r
+                span.Inlines.Add(img);\r
+                paraBody.Inlines.InsertBefore(il, span);\r
+            }\r
+        }\r
+\r
+        public void JumpTo(int newPosition)\r
+        {\r
+            newPosition--;\r
+            if (newPosition < 0 || newPosition >= mResList.Count)\r
+                return;\r
+\r
+            mMainPanel.JumpTo(newPosition);\r
+        }\r
+\r
+    }\r
+}\r
diff --git a/NT2chCtrl45/ResListAdapter_callback.cs b/NT2chCtrl45/ResListAdapter_callback.cs
new file mode 100755 (executable)
index 0000000..8bdc3b4
--- /dev/null
@@ -0,0 +1,195 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Windows;\r
+using System.Windows.Documents;\r
+using NT2chObject;\r
+\r
+namespace NT2chCtrl\r
+{\r
+    partial class ResListAdapter : UIElementListPanel.IUIElementListAdapter\r
+    {\r
+        class ResCashData\r
+        {\r
+            public UIElement element = null;\r
+            public Section section = null;\r
+            public bool hasMatchText = false;\r
+        }\r
+\r
+        List<ResCashData> mResCashDataList;\r
+        void initCashData(int size)\r
+        {\r
+            mResCashDataList = new List<ResCashData>(size);\r
+            for (int i = 0; i < size; i++)\r
+            {\r
+                mResCashDataList.Add(new ResCashData());\r
+            }\r
+        }\r
+        int mSearchResIndex = -1;\r
+        string mStrSearch = string.Empty;\r
+        IAmbiguousSearch mAmbisuousSearch = null;\r
+        //指定された検索文字列を選択状態にして下さい。\r
+\r
+        public void SetSearchWord(string searchWord, int startPostion)\r
+        {\r
+            if (mStrSearch.Equals(searchWord))\r
+                return;\r
+\r
+            \r
+            ResViewCtrlState state = ResViewCtrlState.getInstance();\r
+            bool htmlLayout = state.EnableHtmlLayout;\r
+\r
+            mSearchResIndex = startPostion;\r
+            //mSearchedRes.Clear();\r
+            mStrSearch = searchWord;\r
+\r
+            mAmbisuousSearch = mUtil.CreateAmbiguousSearchInstance(mStrSearch);\r
+\r
+            //foreach (IRes ires in rList)\r
+            //{\r
+            int num = getCount();\r
+            for (int i = 0; i < num; i++)\r
+            {\r
+                ResCashData cashData = mResCashDataList[i];\r
+                if (htmlLayout)\r
+                {\r
+                    cashData.element = null;\r
+                    cashData.section = null;\r
+                }\r
+                IRes ires = mResList[i];\r
+                string msg = ires.getMsg();\r
+                int firstIndex, length;\r
+                if (mAmbisuousSearch.match(ires.getMsg(), 0, out firstIndex, out length))\r
+                {\r
+                    cashData.hasMatchText = true;\r
+                    if (cashData.element == null)\r
+                    {\r
+                        getElement(i, null);\r
+                    }\r
+                    if (htmlLayout)\r
+                        continue;\r
+\r
+                    Section sec = cashData.section;\r
+                    if (sec == null)\r
+                        continue;\r
+\r
+                    if (sec.Blocks.Count != 2)\r
+                        continue;\r
+\r
+                    if (!sec.Blocks.Remove(sec.Blocks.LastBlock))\r
+                        continue;\r
+\r
+                    Paragraph para = new Paragraph();\r
+                    parseResMsg(para, mCurrentThread, ires, firstIndex, length, true);\r
+                    sec.Blocks.Add(para);\r
+                    //mSearchedRes.Add(ires);\r
+                }\r
+                else\r
+                {\r
+                    cashData.hasMatchText = false;\r
+                }\r
+                //}\r
+\r
+            }\r
+            //if (mResUI == null)\r
+            //    return;\r
+            //mResUI.SetSearchWord(mCurrentThread, searchWord);\r
+            if (htmlLayout)\r
+            {\r
+                mMainPanel.InvalidateItems();\r
+            }\r
+        }\r
+        //指定された検索文字列の後方にマッチする文字列を選択して下さい。\r
+        public int SearchNext()\r
+        {\r
+            int num = getCount();\r
+            mSearchResIndex++;\r
+            for (int i = mSearchResIndex; i < num; i++)\r
+            {\r
+                ResCashData cashData = mResCashDataList[i];\r
+                if (cashData.hasMatchText)\r
+                {\r
+                    mSearchResIndex = i;\r
+                    return i;\r
+                }\r
+            }\r
+            for (int i = 0; i < mSearchResIndex; i++)\r
+            {\r
+                ResCashData cashData = mResCashDataList[i];\r
+                if (cashData.hasMatchText)\r
+                {\r
+                    mSearchResIndex = i;\r
+                    return i;\r
+                }\r
+            }\r
+            return mSearchResIndex = -1;\r
+        }\r
+        //指定された検索文字列の前方にマッチする文字列を選択して下さい。\r
+        public int SearchPrev()\r
+        {\r
+            int num = getCount();\r
+            mSearchResIndex--;\r
+            if (mSearchResIndex < 0)\r
+                mSearchResIndex = num - 1;\r
+            for (int i = mSearchResIndex; i >= 0; i--)\r
+            {\r
+                ResCashData cashData = mResCashDataList[i];\r
+                if (cashData.hasMatchText)\r
+                {\r
+                    mSearchResIndex = i;\r
+                    return i;\r
+                }\r
+            }\r
+            for (int i = num - 1; i > mSearchResIndex; i--)\r
+            {\r
+                ResCashData cashData = mResCashDataList[i];\r
+                if (cashData.hasMatchText)\r
+                {\r
+                    mSearchResIndex = i;\r
+                    return i;\r
+                }\r
+            }\r
+            return mSearchResIndex = -1;\r
+        }\r
+\r
+\r
+        public int NextBookmark(int currentPosition)\r
+        {\r
+            currentPosition++;\r
+            int num = getCount();\r
+            if (currentPosition < 0\r
+                || currentPosition >= num)\r
+                currentPosition = 0;\r
+\r
+            for (int i = currentPosition; i < num; i++)\r
+            {\r
+                if (mResList[i].getAttribute(RES_ATTRIBUTE.BOOKMARK))\r
+                    return i;\r
+            }\r
+            for (int i = 0; i < currentPosition; i++)\r
+            {\r
+                if (mResList[i].getAttribute(RES_ATTRIBUTE.BOOKMARK))\r
+                    return i;\r
+            }\r
+            return -1;\r
+        }\r
+\r
+        public void ZoomIn()\r
+        {\r
+            mZoomValue += 5;\r
+            if (mZoomValue > 500)\r
+                mZoomValue = 500;\r
+            setZoomValue(mZoomValue);\r
+            mMainPanel.InvalidateItems();\r
+\r
+        }\r
+        public void ZoomOut()\r
+        {\r
+            mZoomValue -= 5;\r
+            if (mZoomValue < 50)\r
+                mZoomValue = 50;\r
+            setZoomValue(mZoomValue);\r
+            mMainPanel.InvalidateItems();\r
+        }\r
+    }\r
+}\r
diff --git a/NT2chCtrl45/ResListAdapter_event.cs b/NT2chCtrl45/ResListAdapter_event.cs
new file mode 100755 (executable)
index 0000000..ecf2219
--- /dev/null
@@ -0,0 +1,179 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Windows;\r
+using System.Windows.Documents;\r
+using System.Windows.Input;\r
+using NT2chObject;\r
+\r
+namespace NT2chCtrl\r
+{\r
+    partial class ResListAdapter : UIElementListPanel.IUIElementListAdapter\r
+    {\r
+        public void urlLink_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            Hyperlink hl = sender as Hyperlink;\r
+            if (hl == null)\r
+                return;\r
+\r
+            Uri uri = hl.NavigateUri;\r
+            if (uri == null)\r
+                return;\r
+\r
+            string url = uri.AbsoluteUri;\r
+\r
+            mCommand.ExecURL(url);\r
+        }\r
+\r
+\r
+        public void resLink_MouseEnter(object sender, RoutedEventArgs e)\r
+        {\r
+            ResViewPopup.ClearAll(ResViewPopup.CLEAR_POPUP.ALL);\r
+            resLinkSubItem_MouseEnter(sender, e);\r
+        }\r
+\r
+        void resLinkSubItem_MouseEnter(object sender, RoutedEventArgs e)\r
+        {\r
+            Hyperlink hl = sender as Hyperlink;\r
+            if (hl == null)\r
+                return;\r
+\r
+            List<object> param = hl.Tag as List<object>;\r
+\r
+            if (param == null || param.Count != 2)\r
+                return;\r
+\r
+            IThread thread = param[0] as IThread;\r
+            int[] arrNum = param[1] as int[];\r
+            resLinkDispalySubItem(thread, arrNum);\r
+\r
+        }\r
+\r
+        public void resLinkSubItem_MouseEnter2(object sender, RoutedEventArgs e)\r
+        {\r
+            Hyperlink hl = sender as Hyperlink;\r
+            if (hl == null)\r
+                return;\r
+\r
+            List<object> param = hl.Tag as List<object>;\r
+\r
+            if (param == null || param.Count != 2)\r
+                return;\r
+\r
+            IThread thread = param[0] as IThread;\r
+            string sArr = param[1] as string;\r
+            //int[] arrNum = param[1] as int[];\r
+            int[] arr = NTResViewPanel.getUtil().ParseResLinkReferenceNumber(sArr);\r
+            resLinkDispalySubItem(thread, arr);\r
+\r
+        }\r
+\r
+        public void resLinkDispalySubItem(IThread ithread, int[] arrNum)\r
+        {\r
+            if (ithread == null || arrNum == null)\r
+                return;\r
+\r
+            List<IRes> rList = ithread.getResList();\r
+            List<IRes> rListCopy = new List<IRes>(arrNum.Length);\r
+\r
+            int seq = 0;\r
+            foreach (IRes res in rList)\r
+            {\r
+                for (int i = seq; i < arrNum.Length; i++)\r
+                {\r
+                    if (res.getSequenceNo() == arrNum[i])\r
+                    {\r
+                        rListCopy.Add(res);\r
+                        seq = i + 1;\r
+                        break;\r
+                    }\r
+                }\r
+            }\r
+\r
+            FlowDocument doc = createDocument(ithread, rListCopy, false);\r
+\r
+            if (doc != null)\r
+            {\r
+                double zoom = 0;\r
+                if (!getZoomValue(out zoom))\r
+                    zoom = 90;\r
+                else\r
+                    zoom = (zoom > 90) ? 90 : zoom;\r
+                double scrHeight = System.Windows.SystemParameters.PrimaryScreenHeight;\r
+                ResViewPopup popup = new ResViewPopup(\r
+                    this, doc, scrHeight / 2, scrHeight * 2 / 3, zoom,\r
+                    mMainPanel.getTextSelMode());\r
+            }\r
+\r
+        }\r
+        private bool extractParam(object sender, out IThread ithread, out IRes ires)\r
+        {\r
+            ithread = null;\r
+            ires = null;\r
+\r
+            Hyperlink item = sender as Hyperlink;\r
+            if (item == null)\r
+                return false;\r
+\r
+            List<object> list = item.Tag as List<object>;\r
+            if (list == null || list.Count != 2)\r
+                return false;\r
+\r
+            ithread = list[0] as IThread;\r
+            ires = list[1] as IRes;\r
+\r
+            return (ithread != null && ires != null);\r
+        }\r
+\r
+        void hlink_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)\r
+        {\r
+            IThread thread;\r
+            IRes res;\r
+            if (!extractParam(sender, out thread, out res))\r
+                return;\r
+\r
+            ResViewPopup.ClearAll(ResViewPopup.CLEAR_POPUP.ALL);\r
+            JumpTo(res.getSequenceNo());\r
+        }\r
+\r
+\r
+        void ResSeqNo_MouseLeftButtonDown(object sender, MouseEventArgs e)\r
+        {\r
+            IThread thread;\r
+            IRes res;\r
+            if (!extractParam(sender, out thread, out res))\r
+                return;\r
+\r
+            //JumpTo(thread, res.getSequenceNo());\r
+        }\r
+\r
+        void ResSeqNo_MouseEnter(object sender, MouseEventArgs e)\r
+        {\r
+            IThread thread;\r
+            IRes res;\r
+            if (!extractParam(sender, out thread, out res))\r
+                return;\r
+\r
+            ResViewPopup.ClearAll(ResViewPopup.CLEAR_POPUP.ALL);\r
+\r
+            ResViewPopup popup = new ResViewPopup(this, thread, res);\r
+\r
+        }\r
+        void ResSeqNoSubItem_MouseEnter(object sender, MouseEventArgs e)\r
+        {\r
+            IThread thread;\r
+            IRes res;\r
+            if (!extractParam(sender, out thread, out res))\r
+                return;\r
+\r
+            ResViewPopup popup = new ResViewPopup(this, thread, res);\r
+\r
+        }\r
+\r
+\r
+        void document_MouseMove(object sender, RoutedEventArgs e)\r
+        {\r
+            ResViewPopup.ClearAll(ResViewPopup.CLEAR_POPUP.LEAVE_ONE);\r
+        }\r
+    }\r
+}\r
diff --git a/NT2chCtrl45/ResListAdapter_misc.cs b/NT2chCtrl45/ResListAdapter_misc.cs
new file mode 100755 (executable)
index 0000000..9f1a5ed
--- /dev/null
@@ -0,0 +1,74 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using NT2chObject;\r
+\r
+namespace NT2chCtrl\r
+{\r
+    partial class ResListAdapter : UIElementListPanel.IUIElementListAdapter\r
+    {\r
+        double mZoomValue;\r
+\r
+        bool? mPopupMouseHover = null;\r
+        public bool getEnablePopupMouseHover()\r
+        {\r
+            if (mPopupMouseHover.HasValue)\r
+                return (bool)mPopupMouseHover;\r
+\r
+            Dictionary<PREF_PARAM, object> dict =\r
+                mCommand.GetPreference();\r
+            if (dict == null)\r
+                return true;\r
+            object o;\r
+            if (dict.TryGetValue(PREF_PARAM.RES_VIEW_POPUP_MOUSEHOVER, out o))\r
+            {\r
+                string s = o as string;\r
+                if (s != null)\r
+                {\r
+                    bool hover;\r
+                    if (bool.TryParse(s, out hover))\r
+                    {\r
+                        mPopupMouseHover = hover;\r
+                        return hover;\r
+                    }\r
+                }\r
+            }\r
+            return true;\r
+        }\r
+\r
+        bool getZoomValue(out double zoom)\r
+        {\r
+            zoom = 0;\r
+            Dictionary<PREF_PARAM, object> dict =\r
+                mCommand.GetPreference();\r
+            if (dict == null)\r
+                return false;\r
+            object o;\r
+            if (dict.TryGetValue(PREF_PARAM.RES_VIEW_ZOOM_VALUE, out o))\r
+            {\r
+                string s = o as string;\r
+                if (s != null)\r
+                {\r
+                    if (double.TryParse(s, out zoom))\r
+                    {\r
+                        return true;\r
+                    }\r
+                }\r
+            }\r
+            return false;\r
+        }\r
+        bool setZoomValue(double zoom)\r
+        {\r
+            Dictionary<PREF_PARAM, object> dict =\r
+                mCommand.GetPreference();\r
+            if (dict == null)\r
+                return false;\r
+\r
+\r
+            dict.Remove(PREF_PARAM.RES_VIEW_ZOOM_VALUE);\r
+            dict.Add(PREF_PARAM.RES_VIEW_ZOOM_VALUE, zoom.ToString());\r
+            return true;\r
+        }\r
+    }\r
+\r
+}\r
diff --git a/NT2chCtrl45/ResViewCtrlState.cs b/NT2chCtrl45/ResViewCtrlState.cs
new file mode 100755 (executable)
index 0000000..47d64f4
--- /dev/null
@@ -0,0 +1,52 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using NT2chCtrl.html;\r
+using NT2chObject;\r
+\r
+namespace NT2chCtrl\r
+{\r
+    class ResViewCtrlState\r
+    {\r
+        static ResViewCtrlState mState;\r
+        //HtmlElement mResViewLayoutHtmlElement;\r
+        HtmlParser mParser;\r
+\r
+        public static ResViewCtrlState getInstance()\r
+        {\r
+            if (mState == null)\r
+                mState = new ResViewCtrlState();\r
+            return mState;\r
+        }\r
+\r
+        ResViewCtrlState()\r
+        {\r
+            EnableHtmlLayout = false;\r
+        }\r
+        public bool EnableHtmlLayout { set; get; }\r
+\r
+        //public HtmlElement getResViewLayoutElement() { return mResViewLayoutHtmlElement; }\r
+        public HtmlParser getResViewLayoutParser() { return mParser; }\r
+\r
+        public bool init(string htmlSource, ICommand iCommand, out HtmlParser parser)\r
+        {\r
+            parser = null;\r
+            if (htmlSource == null)\r
+            {\r
+                return false;\r
+            }\r
+            parser = new HtmlParser(iCommand.GetDataPath());\r
+\r
+            if (parser.Parse(htmlSource))\r
+            {\r
+                EnableHtmlLayout = true;\r
+                mParser = parser;\r
+                return true;\r
+            }\r
+            else\r
+            {\r
+                return false;\r
+            }\r
+        }\r
+    }\r
+}\r
diff --git a/NT2chCtrl45/ResViewPopup.cs b/NT2chCtrl45/ResViewPopup.cs
new file mode 100755 (executable)
index 0000000..a4f8ccf
--- /dev/null
@@ -0,0 +1,335 @@
+using NT2chObject;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Windows;\r
+using System.Windows.Controls;\r
+using System.Windows.Controls.Primitives;\r
+using System.Windows.Documents;\r
+using System.Windows.Media;\r
+\r
+namespace NT2chCtrl\r
+{\r
+    class ResViewPopup : Popup\r
+    {\r
+        public enum CLEAR_POPUP\r
+        {\r
+                ALL,\r
+                LEAVE_ONE\r
+        }\r
+        static Stack<ResViewPopup> mPopupStack = new Stack<ResViewPopup>();\r
+\r
+        //private ResViewUI mUI;\r
+        private ResListAdapter mAdapter;\r
+\r
+        public ResViewPopup(ResListAdapter adapter, \r
+        FlowDocument doc, double maxWidth, double maxHeight, double zoom, bool textSelMode)\r
+            : base()\r
+        {\r
+            //mUI = ui;\r
+            mAdapter = adapter;\r
+            Grid grid = new Grid();\r
+            grid.Background = new SolidColorBrush(Colors.Beige);\r
+            FlowDocumentScrollViewer fdsv = new FlowDocumentScrollViewer();\r
+            \r
+            fdsv.Document = doc;\r
+            fdsv.MaxHeight = maxHeight;\r
+            fdsv.MaxWidth = maxWidth;\r
+            fdsv.Zoom = zoom;\r
+            fdsv.IsSelectionEnabled = textSelMode;\r
+            this.Child = grid;\r
+            grid.Children.Add(fdsv);\r
+            addStack();\r
+\r
+        }\r
+\r
+\r
+\r
+\r
+        public ResViewPopup(ResListAdapter adapter, IThread ithread, IRes ires)\r
+            : base()\r
+        {\r
+           mAdapter = adapter;\r
+           List<object> param = new List<object>(2);\r
+           param.Add(ithread);\r
+           param.Add(ires);\r
+\r
+           StackPanel panel = new StackPanel();\r
+           panel.Background = new SolidColorBrush(Colors.White);\r
+           \r
+           ListBoxItem item1 = new ListBoxItem();\r
+           StackPanel sp = new StackPanel();\r
+           item1.Content = sp;\r
+           item1.Padding = new System.Windows.Thickness(10, 2, 10, 2);\r
+           if (!ires.getAttribute(RES_ATTRIBUTE.BOOKMARK))\r
+           {\r
+               sp.Children.Add(new TextBlock(new Run("ブックマークを追加")));\r
+               sp.MouseLeftButtonDown += addBookmark_MouseLeftButtonDown;\r
+           }\r
+           else\r
+           {\r
+               sp.Children.Add(new TextBlock(new Run("ブックマークを削除")));\r
+               sp.MouseLeftButtonDown += delBookmark_MouseLeftButtonDown;\r
+           }\r
+           \r
+           item1.MouseEnter += ResNumItem_MouseEnter;\r
+           item1.MouseLeave += ResNumItem_MouseLeave;\r
+           sp.Tag = param;\r
+           panel.Children.Add(item1);\r
+\r
+           sp = new StackPanel();\r
+           sp.Children.Add(new TextBlock(new Run("このレスに返信")));\r
+           item1 = new ListBoxItem();\r
+           item1.Content = sp;\r
+           item1.Padding = new System.Windows.Thickness(10, 2, 10, 2);\r
+           item1.MouseEnter += ResNumItem_MouseEnter;\r
+           item1.MouseLeave += ResNumItem_MouseLeave;\r
+           sp.MouseLeftButtonDown += replyMsg_MouseLeftButtonDown;\r
+           sp.Tag = param;\r
+           panel.Children.Add(item1);\r
+           sp = new StackPanel();\r
+           sp.Children.Add(new TextBlock(new Run("このレスに引用して返信")));\r
+           item1 = new ListBoxItem();\r
+           item1.Padding = new System.Windows.Thickness(10, 2, 10, 2);\r
+           item1.Content = sp;\r
+           item1.MouseEnter += ResNumItem_MouseEnter;\r
+           item1.MouseLeave += ResNumItem_MouseLeave;\r
+           sp.MouseLeftButtonDown += quoteMsg_MouseLeftButtonDown;\r
+           sp.Tag = param;\r
+           panel.Children.Add(item1);\r
+           sp = new StackPanel();\r
+           sp.Children.Add(new TextBlock(new Run("このレスからNGを抽出")));\r
+           item1 = new ListBoxItem();\r
+           item1.Padding = new System.Windows.Thickness(10, 2, 10, 2);\r
+           item1.Content = sp;\r
+           item1.MouseEnter += ResNumItem_MouseEnter;\r
+           item1.MouseLeave += ResNumItem_MouseLeave;\r
+           sp.MouseLeftButtonDown += extractNgword_MouseLeftButtonDown;\r
+           sp.Tag = param;\r
+           panel.Children.Add(item1);\r
+\r
+           Border border = new Border();\r
+           border.BorderThickness = new System.Windows.Thickness(1);\r
+           border.BorderBrush = new SolidColorBrush(Colors.DarkGray);\r
+           border.CornerRadius = new System.Windows.CornerRadius(2);\r
+           border.Child = panel;\r
+           this.Child = border;\r
+\r
+            addStack();\r
+       }\r
+\r
+\r
+\r
+       void ResViewPopup_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e)\r
+       {\r
+           try\r
+           {\r
+               ResViewPopup p = mPopupStack.Peek();\r
+               if (p.Equals(this))\r
+               {\r
+                   p = mPopupStack.Pop();\r
+                   p.IsOpen = false;\r
+                   //break;\r
+               }\r
+           }\r
+           catch// (Exception ex)\r
+           {\r
+               //NTDebug.l(ex.Message);\r
+           }\r
+       }\r
+\r
+       void ResViewPopup_MouseEnter(object sender, System.Windows.Input.MouseEventArgs e)\r
+       {\r
+           ClearTo(this);\r
+           //throw new NotImplementedException();\r
+       }\r
+\r
+       void ResViewPopup_LostFocus(object sender, System.Windows.RoutedEventArgs e)\r
+       {\r
+           //throw new NotImplementedException();\r
+           ClearTo2(this);\r
+       }\r
+\r
+       void ResViewPopup_GotFocus(object sender, System.Windows.RoutedEventArgs e)\r
+       {\r
+           ClearTo(this);\r
+\r
+           //throw new NotImplementedException();\r
+       }\r
+\r
+       public void addStack()\r
+       {\r
+           mPopupStack.Push(this);\r
+           StaysOpen = true;\r
+           Placement = PlacementMode.Mouse;\r
+           IsOpen = true;\r
+           this.GotFocus += ResViewPopup_GotFocus;\r
+           this.LostFocus += ResViewPopup_LostFocus;\r
+           this.MouseEnter += ResViewPopup_MouseEnter;\r
+           this.MouseLeave += ResViewPopup_MouseLeave;\r
+       }\r
+\r
+       public static void ClearAll(CLEAR_POPUP clear)\r
+       {\r
+           if ((clear == CLEAR_POPUP.LEAVE_ONE) && (mPopupStack.Count < 2))\r
+               return;\r
+\r
+           try\r
+           {\r
+               while (true)\r
+               {\r
+                   ResViewPopup p = mPopupStack.Pop();\r
+                   p.IsOpen = false;\r
+               }\r
+           }\r
+           catch// (InvalidOperationException e)\r
+           {\r
+               //NTDebug.l(e.Message);\r
+           }\r
+       }\r
+       public static void ClearTo2(ResViewPopup popup)\r
+       {\r
+           try\r
+           {\r
+               while (true)\r
+               {\r
+                   ResViewPopup p = mPopupStack.Peek();\r
+                   if (p.Equals(popup))\r
+                   {\r
+                       p = mPopupStack.Pop();\r
+                       p.IsOpen = false;\r
+                       break;\r
+                   }\r
+                   p = mPopupStack.Pop();\r
+                   p.IsOpen = false;\r
+               }\r
+               mPopupStack.Peek().Focus();\r
+           }\r
+           catch// (InvalidOperationException e)\r
+           {\r
+               //NTDebug.l(e.Message);\r
+           }\r
+       }\r
+\r
+       public static void ClearTo(ResViewPopup popup)\r
+       {\r
+\r
+           try\r
+           {\r
+               while (true)\r
+               {\r
+                   ResViewPopup p = mPopupStack.Peek();\r
+                   if (p.Equals(popup))\r
+                       break;\r
+                   p = mPopupStack.Pop();\r
+                   p.IsOpen = false;\r
+               }\r
+               mPopupStack.Peek().Focus();\r
+           }\r
+           catch// (InvalidOperationException e)\r
+           {\r
+               //NTDebug.l(e.Message);\r
+               return;\r
+           }\r
+\r
+       }\r
+\r
+       void ResNumItem_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e)\r
+       {\r
+           ListBoxItem item = sender as ListBoxItem;\r
+           if (item == null)\r
+               return;\r
+\r
+           item.Background = new SolidColorBrush(Colors.White);\r
+       }\r
+\r
+       void ResNumItem_MouseEnter(object sender, System.Windows.Input.MouseEventArgs e)\r
+       {\r
+           ListBoxItem item = sender as ListBoxItem;\r
+           if (item == null)\r
+               return;\r
+\r
+           item.Background = new SolidColorBrush(Colors.MistyRose);\r
+       }\r
+       void addBookmark_MouseLeftButtonDown(object sender, RoutedEventArgs e)\r
+       {\r
+           IThread ithread;\r
+           IRes ires;\r
+           if (!extractParam(sender, out ithread, out ires))\r
+               return;\r
+           mAdapter.addBookmark(ithread, ires, true);\r
+           \r
+       }\r
+       void delBookmark_MouseLeftButtonDown(object sender, RoutedEventArgs e)\r
+       {\r
+           IThread ithread;\r
+           IRes ires;\r
+           if (!extractParam(sender, out ithread, out ires))\r
+               return;\r
+           mAdapter.removeBookmark(ithread, ires, true);\r
+       }\r
+       void replyMsg_MouseLeftButtonDown(object sender, RoutedEventArgs e)\r
+       {\r
+           IThread ithread;\r
+           IRes ires;\r
+           if (!extractParam(sender, out ithread, out ires))\r
+               return;\r
+           int seqNo = ires.getSequenceNo();\r
+           string message = ">>" + seqNo.ToString() + "\n";\r
+           NTResViewPanel.getCommand().WriteMessage(ithread, message);\r
+       }\r
+       /*void jumpResMsg_MouseLeftButtonDown(object sender, RoutedEventArgs e)\r
+       {\r
+           IThread ithread;\r
+           IRes ires;\r
+           if (!extractParam(sender, out ithread, out ires))\r
+               return;\r
+           int seqNo = ires.getSequenceNo();\r
+           ClearAll(CLEAR_POPUP.ALL);\r
+           mAdapter.JumpTo(seqNo);\r
+       }*/\r
+\r
+       void quoteMsg_MouseLeftButtonDown(object sender, RoutedEventArgs e)\r
+       {\r
+           IThread ithread;\r
+           IRes ires;\r
+           if (!extractParam(sender, out ithread, out ires))\r
+               return;\r
+           int seqNo = ires.getSequenceNo();\r
+           StringBuilder sb = new StringBuilder(128);\r
+           sb.Append(">>").Append(seqNo.ToString()).Append('\n');\r
+\r
+\r
+           NTResViewPanel.getCommand().WriteMessage(ithread, sb.ToString());\r
+       }\r
+\r
+       void extractNgword_MouseLeftButtonDown(object sender, RoutedEventArgs e)\r
+       {\r
+           IThread ithread;\r
+           IRes ires;\r
+           if (!extractParam(sender, out ithread, out ires))\r
+               return;\r
+           NTResViewPanel.getCommand().ShowNgwordDialog(ires);\r
+       }\r
+\r
+       private bool extractParam(object sender, out IThread ithread, out IRes ires)\r
+       {\r
+           ithread = null;\r
+           ires = null;\r
+\r
+           StackPanel item = sender as StackPanel;\r
+           if (item == null)\r
+               return false;\r
+\r
+           List<object> list = item.Tag as List<object>;\r
+           if (list == null || list.Count != 2)\r
+               return false;\r
+\r
+           ithread = list[0] as IThread;\r
+           ires = list[1] as IRes;\r
+\r
+           return (ithread != null && ires != null);\r
+       }\r
+\r
+    }\r
+}\r
diff --git a/NT2chCtrl45/ThreadDescription.cs b/NT2chCtrl45/ThreadDescription.cs
new file mode 100755 (executable)
index 0000000..244fd3d
--- /dev/null
@@ -0,0 +1,56 @@
+using NT2chObject;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+\r
+namespace NT2chCtrl\r
+{\r
+    class ThreadDescriptionImple : IThreadDescription\r
+    {\r
+        IBoard mBoard;\r
+        string mDatName;\r
+        string mTitle;\r
+\r
+        public string getTitle() { return mTitle; }\r
+        public string getDatName() { return mDatName; }\r
+        public IBoard getBoard() { return mBoard; }\r
+        \r
+        public void setTitle(string title)\r
+        {\r
+            mTitle = title;\r
+        }\r
+\r
+        public bool Equals(IThreadDescription threadDecl)\r
+        {\r
+            return (mDatName.Equals(threadDecl.getDatName()) && \r
+                mBoard.getName().Equals(threadDecl.getBoard().getName()));\r
+        }\r
+\r
+        public static ThreadDescriptionImple\r
+            createThreadDescription(IThread thread)\r
+        {\r
+            ThreadDescriptionImple threadImpl = new ThreadDescriptionImple(\r
+                thread.getBoard(), thread.getDatName());\r
+            string title = thread.getTitle();\r
+            if(title != null && title.Length > 0)\r
+                threadImpl.setTitle(title);\r
+            return threadImpl;\r
+        }\r
+\r
+        public static ThreadDescriptionImple\r
+            createThreadDescription(IBoard board, string datName)\r
+        {\r
+            ThreadDescriptionImple thread = new ThreadDescriptionImple(\r
+                board, datName);\r
+            return thread;\r
+        }\r
+\r
+\r
+        private ThreadDescriptionImple(IBoard board, string datName)\r
+        {\r
+            mBoard = board;\r
+            mDatName = datName;\r
+        }\r
+\r
+    }\r
+}\r
diff --git a/NT2chCtrl45/ThreadHistoryUI.cs b/NT2chCtrl45/ThreadHistoryUI.cs
new file mode 100755 (executable)
index 0000000..a271455
--- /dev/null
@@ -0,0 +1,383 @@
+using NT2chObject;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Windows;\r
+using System.Windows.Controls;\r
+using System.Windows.Controls.Primitives;\r
+\r
+namespace NT2chCtrl\r
+{\r
+    class ThreadHistoryUI\r
+    {\r
+        List<IThreadDescription> mThreadList;\r
+        StackPanel mThreadHistoryPanel;\r
+        Style mThreadButtonStyle;\r
+        IUtil mUtil;\r
+        ICommand mCommand;\r
+\r
+        public ThreadHistoryUI(ICommand command, IUtil util, List<IThreadDescription> threadList,\r
+            StackPanel panel)\r
+        {\r
+            if (panel == null || threadList == null)\r
+                return;\r
+\r
+            mUtil = util;\r
+            mCommand = command;\r
+            \r
+            panel.Children.Clear();\r
+\r
+            mThreadList = new List<IThreadDescription>();\r
+            mThreadHistoryPanel = panel;\r
+\r
+            mThreadButtonStyle = (Style)panel.TryFindResource("ThreadButton");\r
+\r
+            int threadCount = threadList.Count;\r
+            for (int i = threadCount - 1; i >= 0; i--)\r
+            {\r
+                AddButton(threadList[i]);\r
+            }\r
+            if (threadCount > 0)\r
+                mCommand.OpenThread(threadList[0]);\r
+\r
+        }\r
+        public List<IThreadDescription> getCurrentList()\r
+        {\r
+            return mThreadList;\r
+        }\r
+\r
+        public void AddButton(IThread ithread)\r
+        {\r
+            ThreadDescriptionImple threadImpl = \r
+                ThreadDescriptionImple.createThreadDescription(ithread);\r
+            if (threadImpl == null)\r
+                return;\r
+\r
+            IBoard board = ithread.getBoard();\r
+            if (board != null)\r
+            {\r
+                string boardName = board.getName();\r
+                if (boardName != null && boardName.Length > 0)\r
+                    updateMenu(boardName);\r
+            }\r
+\r
+            AddButton(threadImpl);\r
+\r
+        }\r
+\r
+        public void UpdateButton(IBoard iboard)\r
+        {\r
+            //System.Diagnostics.Debug.WriteLine("AAA");\r
+            if (iboard == null)\r
+                return;\r
+            foreach (UIElement ui in mThreadHistoryPanel.Children)\r
+            {\r
+                Button btn = ui as Button;\r
+                if (btn == null)\r
+                    continue;\r
+                IThreadDescription desc =\r
+                    btn.Tag as IThreadDescription;\r
+                if (desc == null)\r
+                    continue;\r
+\r
+                IBoard ib = desc.getBoard();\r
+                if (!iboard.getName().Equals(ib.getName()))\r
+                    continue;\r
+\r
+                IThread ithread = getIThread(ib, desc.getDatName());\r
+                if (ithread == null)\r
+                    continue;\r
+                string title = ithread.getTitle();\r
+                if (title != null)\r
+                    btn.Content = title;\r
+                /*foreach (IThread ithread in iboard.getThreadList())\r
+                {\r
+                    if (desc.getDatName().Equals(ithread.getDatName()))\r
+                    {\r
+                        string title = ithread.getTitle();\r
+                        if (title != null)\r
+                        {\r
+                            //System.Diagnostics.Debug.WriteLine("Attached Title: "+ title);\r
+                            btn.Content = title;\r
+                        }\r
+                        break;\r
+                    }\r
+                }*/\r
+            }\r
+        }\r
+\r
+        private IThread getIThread(IBoard iboard, string datName)\r
+        {\r
+            foreach (IThread ithread in iboard.getThreadList())\r
+            {\r
+                if (datName.Equals(ithread.getDatName()))\r
+                    return ithread;\r
+            }\r
+            return null;\r
+        }\r
+\r
+        private void AddButton(IThreadDescription thread)\r
+        {\r
+            if (thread == null)\r
+                return;\r
+\r
+            deleteThreadFromMenu(thread);\r
+\r
+            string title =  thread.getTitle();\r
+\r
+            if (mThreadList.Count == 50)\r
+                mThreadList.RemoveAt(49);\r
+\r
+            mThreadList.Insert(0,thread);\r
+\r
+            Button button = new Button();\r
+            if (title != null)\r
+                button.Content = title;\r
+            else\r
+                button.Content = "Unknown thread title.";\r
+            if(mThreadButtonStyle != null)\r
+                button.Style = mThreadButtonStyle;\r
+\r
+            button.Click += threadButton_Click;\r
+            button.Tag = thread;\r
+            ContextMenu cm = createButtonContextMenu(thread);\r
+            if(cm != null)\r
+                button.ContextMenu = cm;\r
+\r
+            mThreadHistoryPanel.Children.Insert(0, button);\r
+\r
+        }\r
+\r
+        ContextMenu createButtonContextMenu(IThreadDescription thread)\r
+        {\r
+            ContextMenu cm = new ContextMenu();\r
+\r
+            string title = thread.getTitle();\r
+            if(title == null || title.Length == 0)\r
+                title = "Unknown thread ti...";\r
+\r
+            if (title.Length > 17)\r
+                title = title.Substring(0, 17-3) + "...";\r
+\r
+\r
+            MenuItem item = new MenuItem();\r
+            item = new MenuItem();\r
+            item.Header = title;\r
+            cm.Items.Add(item);\r
+            cm.Items.Add(new Separator());\r
+            item = new MenuItem();\r
+            item.Tag = thread;\r
+            item.Header = "お気に入りに追加";\r
+            item.Click += addThreadToFavorite_Click;\r
+            cm.Items.Add(item);\r
+            item = new MenuItem();\r
+            item.Tag = thread;\r
+            item.Header = "メニューから削除";\r
+            item.Click += deleteThreadFromMenu_Click;\r
+            cm.Items.Add(item);\r
+            item = new MenuItem();\r
+            item.Tag = thread;\r
+            item.Header = "類似スレを検索";\r
+            item.Click += searchSimularThreadMenu_Click;\r
+            cm.Items.Add(item);\r
+            item = new MenuItem();\r
+            item.Tag = thread;\r
+            item.Header = "アドレスを表示";\r
+            item.Click += showThreadInfoMenu_Click;\r
+            cm.Items.Add(item);\r
+            cm.Items.Add(new Separator());\r
+            item = new MenuItem();\r
+            item.Tag = thread;\r
+            item.Header = "このタブを閉じる";\r
+            //item.Click += boardTabHeaderMenu_CloseThis_Click;\r
+            cm.Items.Add(item);\r
+\r
+            return cm;\r
+        }\r
+\r
+        void searchSimularThreadMenu_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            MenuItem mi = sender as MenuItem;\r
+            if (mi == null)\r
+                return;\r
+\r
+            IThreadDescription thread = mi.Tag as IThreadDescription;\r
+            if (thread == null)\r
+                return;\r
+            IBoard iboard = thread.getBoard();\r
+            if (iboard == null)\r
+                return;\r
+\r
+            IThread2 ithread = getIThread(iboard, thread.getDatName()) as IThread2;\r
+            if (ithread != null)\r
+            {\r
+                ((ICommand2)mCommand).SearchSimilarTitle(ithread);\r
+            }\r
+            else\r
+            {\r
+                MessageBox.Show("スレッドの情報が見つかりません");\r
+            }\r
+        }\r
+\r
+        void showThreadInfoMenu_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            string title, address;\r
+\r
+            MenuItem mi = sender as MenuItem;\r
+            if (mi == null)\r
+                return;\r
+\r
+            IThreadDescription thread = mi.Tag as IThreadDescription;\r
+            if (thread == null)\r
+                return;\r
+            IBoard iboard = thread.getBoard();\r
+            if (iboard == null)\r
+                return;\r
+           \r
+            title =  thread.getTitle();\r
+            if (title == null || title.Length == 0)\r
+            {\r
+                IThread ithread = getIThread(iboard, thread.getDatName());\r
+                if(ithread != null)\r
+                    title = ithread.getTitle();\r
+            }\r
+\r
+            address = parse2chAddress(iboard.getAddress(), thread.getDatName());\r
+\r
+            mCommand.ShowThreadInfoWindow(title, address);\r
+        }\r
+        void deleteThreadFromMenu_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            MenuItem mi = sender as MenuItem;\r
+            if (mi == null)\r
+                return;\r
+\r
+            IThreadDescription thread = mi.Tag as IThreadDescription;\r
+            if (thread == null)\r
+                return;\r
+\r
+            deleteThreadFromMenu(thread);\r
+        }\r
+\r
+        void deleteThreadFromMenu(IThreadDescription thread)\r
+        {\r
+            int threadCnt = mThreadList.Count;\r
+\r
+            for (int i = 0; i < threadCnt; i++)\r
+            {\r
+                IThreadDescription ithreadDecl = mThreadList[i];\r
+\r
+                if (!(thread.getDatName().Equals(ithreadDecl.getDatName()) &&\r
+                    thread.getBoard().getName().Equals(ithreadDecl.getBoard().getName())))\r
+                    continue;\r
+                mThreadList.RemoveAt(i);\r
+                mThreadHistoryPanel.Children.RemoveAt(i);\r
+                break;\r
+            }\r
+\r
+\r
+        }\r
+\r
+        void updateMenu(string boardName)\r
+        {\r
+            if (boardName == null)\r
+                return;\r
+\r
+            int threadCnt = mThreadList.Count;\r
+\r
+            for (int i = 0; i < threadCnt; i++)\r
+            {\r
+                IThreadDescription ithreadDecl = mThreadList[i];\r
+\r
+                if (!boardName.Equals(ithreadDecl.getBoard().getName()))\r
+                    continue;\r
+\r
+                string title = ithreadDecl.getTitle();\r
+                if (title == null || title.Length == 0)\r
+                    continue;\r
+\r
+                Button btn = mThreadHistoryPanel.Children[i] as Button;\r
+                if(btn != null)\r
+                    btn.Content = title;\r
+             }\r
+\r
+\r
+        }\r
+\r
+        void addThreadToFavorite_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            MenuItem mi = sender as MenuItem;\r
+            if (mi == null)\r
+                return;\r
+\r
+            IThreadDescription thread = mi.Tag as IThreadDescription;\r
+            if (thread == null)\r
+                return;\r
+\r
+            if (!mCommand.AddThreadToFavorite(thread))\r
+                MessageBox.Show("追加できませんでした");\r
+        }\r
+\r
+        void threadButton_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            Button btn = sender as Button;\r
+            if (btn == null)\r
+                return;\r
+            IThreadDescription thread = btn.Tag as IThreadDescription;\r
+            if (thread == null)\r
+                return;\r
+\r
+            mCommand.OpenThread(thread);\r
+        }\r
+        string parse2chAddress(string address, string dat)\r
+        {\r
+            if (address == null)\r
+                return string.Empty;\r
+\r
+            int len = address.Length;\r
+            if (len == 0)\r
+                return string.Empty;\r
+\r
+            string address1;\r
+            string dat1;\r
+            if (dat == null)\r
+                dat1 = string.Empty;\r
+            else\r
+                dat1 = dat;\r
+\r
+\r
+            int idx = address.IndexOf("machi.to");\r
+            if (idx >= 0)\r
+            {\r
+                idx += "machi.to".Length;\r
+                address1 = address.Substring(0, idx);\r
+                address1 += "/bbs/read.cgi" + address.Substring(idx);\r
+                idx = dat1.IndexOf(".cgi");\r
+                if (idx >= 0)\r
+                {\r
+                    dat1 = dat.Substring(0, idx) + "/";\r
+                }\r
+            }\r
+            else\r
+            {\r
+                idx = address.LastIndexOf('/', len - 2);\r
+                if (idx <= 0)\r
+                    return string.Empty;\r
+\r
+                address1 = address.Substring(0, idx);\r
+                address1 += "/test/read.cgi" + address.Substring(idx);\r
+                idx = dat1.IndexOf(".dat");\r
+                if (idx >= 0)\r
+                {\r
+                    dat1 = dat.Substring(0, idx) + "/";\r
+                }\r
+            }\r
+\r
+            if (dat != null)\r
+                address1 += dat1;\r
+\r
+            return address1;\r
+        }\r
+\r
+    }\r
+}\r
diff --git a/NT2chCtrl45/TouchSupportScrollViewer.cs b/NT2chCtrl45/TouchSupportScrollViewer.cs
new file mode 100755 (executable)
index 0000000..13c1f4e
--- /dev/null
@@ -0,0 +1,67 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Windows;\r
+using System.Windows.Controls;\r
+using System.Windows.Input;\r
+\r
+\r
+namespace NT2chCtrl\r
+{\r
+    public class TouchSupportScrollViewer\r
+    {\r
+        ScrollViewer mSV;\r
+        UIElement mElement;\r
+        bool mTouch = false;\r
+        TouchPoint mPos;\r
+        double mVOffest;\r
+\r
+        public TouchSupportScrollViewer(\r
+            ScrollViewer sv, UIElement element)\r
+        {\r
+            mSV = sv;\r
+            mElement = element;\r
+            mElement.TouchDown += element_TouchDown;\r
+            mElement.TouchMove += element_TouchMove;\r
+            mElement.TouchUp += element_TouchUp;\r
+        }\r
+\r
+        void element_TouchUp(object sender, TouchEventArgs e)\r
+        {\r
+            mTouch = false;\r
+        }\r
+\r
+        void element_TouchMove(object sender, TouchEventArgs e)\r
+        {\r
+\r
+            if (!mTouch)\r
+                return;\r
+\r
+            TouchPoint pos = e.GetTouchPoint(mElement);\r
+            double y = mPos.Position.Y - pos.Position.Y;\r
+            double newOffset = mVOffest + y;\r
+            if (mSV != null)\r
+                mSV.ScrollToVerticalOffset(newOffset);\r
+        }\r
+\r
+\r
+        void element_TouchDown(object sender, TouchEventArgs e)\r
+        {\r
+            try\r
+            {\r
+                mPos = e.GetTouchPoint(mElement);\r
+                if (mSV == null)\r
+                {\r
+                    mTouch = false;\r
+                    return;\r
+                }\r
+                mVOffest = mSV.VerticalOffset;\r
+                mTouch = true;\r
+            }\r
+            catch (Exception ex)\r
+            {\r
+                MessageBox.Show(ex.Message);\r
+            }\r
+        }\r
+    }\r
+}\r
diff --git a/NT2chCtrl45/UIElementListAdapter.cs b/NT2chCtrl45/UIElementListAdapter.cs
new file mode 100755 (executable)
index 0000000..52643c3
--- /dev/null
@@ -0,0 +1,400 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Windows;\r
+using System.Windows.Controls;\r
+using System.Windows.Controls.Primitives;\r
+using System.Windows.Input;\r
+\r
+namespace NT2chCtrl\r
+{\r
+    public partial class UIElementListPanel : Panel\r
+    {\r
+        private static double DEFAULT_ITEM_HEIGHT = 200;\r
+        private static double SCRILL_CHANGE_VALUE = 10;\r
+\r
+        enum SCROLL_STATE\r
+        {\r
+            NONE, CURSOR_UP, \r
+            CURSOR_DOWN, EXPLICIT,\r
+            SKIP\r
+        }\r
+\r
+        SCROLL_STATE mScrollState = SCROLL_STATE.EXPLICIT;\r
+\r
+        IUIElementListAdapter mAdapter = null;\r
+        ScrollBar mScrollbar = null;\r
+        Size mSavedPanelSize;\r
+        double mCurrentScrollPos;\r
+        int mItemCount;\r
+\r
+        ScrollItemHeight mScrollHeight = new ScrollItemHeight();\r
+\r
+\r
+        public interface IUIElementListAdapter\r
+        {\r
+            int getCount();\r
+            UIElement getElement(int pos, UIElement convertElement);\r
+        }\r
+\r
+       \r
+        public void init()\r
+        {\r
+            this.PreviewMouseWheel += UIElementListPanel_PreviewMouseWheel;\r
+            this.PreviewKeyDown += UIElement_PreviewKeyDown;\r
+\r
+#if DOTNET45\r
+\r
+            this.TouchDown += UIElementListPanel_TouchDown;\r
+            this.TouchUp += UIElementListPanel_TouchUp;\r
+            this.TouchMove += UIElementListPanel_TouchMove;\r
+            this.TouchEnter += UIElementListPanel_TouchEnter;\r
+            this.TouchLeave += UIElementListPanel_TouchLeave;\r
+#endif\r
+        }\r
+\r
+\r
+        //int test = 0 ;\r
+\r
+\r
+        void UIElement_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e)\r
+        {\r
+\r
+            if (e.Key == System.Windows.Input.Key.Down)\r
+            {\r
+                setScrollValue(mCurrentScrollPos + mScrollbar.SmallChange);\r
+                e.Handled = true;\r
+                \r
+            }\r
+            else if (e.Key == System.Windows.Input.Key.Up)\r
+            {\r
+                setScrollValue(mCurrentScrollPos - mScrollbar.SmallChange);\r
+                e.Handled = true;\r
+               \r
+            }\r
+            else if (e.Key == System.Windows.Input.Key.PageUp)\r
+            {\r
+                setScrollValue(mCurrentScrollPos - mScrollbar.LargeChange);\r
+                e.Handled = true;\r
+            }\r
+            else if (e.Key == System.Windows.Input.Key.PageDown)\r
+            {\r
+                setScrollValue(mCurrentScrollPos + mScrollbar.LargeChange);\r
+                e.Handled = true;\r
+            }\r
+        }\r
+\r
+        void UIElementListPanel_PreviewMouseWheel(object sender, System.Windows.Input.MouseWheelEventArgs e)\r
+        {            \r
+            mCurrentScrollPos -= e.Delta;\r
+            setScrollValue(mCurrentScrollPos);\r
+        }\r
+\r
+        public void setAdapter(IUIElementListAdapter adapter, int scrollTo)\r
+        {\r
+            mAdapter = adapter;\r
+\r
+            initData(scrollTo);\r
+        }\r
+\r
+        public int getCurrentPosition()\r
+        {\r
+            int position;\r
+            double itemOffset;\r
+            if (!mScrollHeight.tryGetItemPosition(this.mCurrentScrollPos,\r
+                          out position, out itemOffset))\r
+                return -1;\r
+            return position;\r
+        }\r
+\r
+        public void InvalidateItems()\r
+        {\r
+            foreach (UIElement element in base.InternalChildren)\r
+            {\r
+                ScrollBar sb = element as ScrollBar;\r
+                if (sb != null)\r
+                {\r
+                    continue;\r
+                }\r
+                Grid grid = element as Grid;\r
+                if (grid != null && grid.Children.Count > 0)\r
+                {\r
+                    grid.Children.Clear();\r
+                }\r
+            }\r
+            setScrollItemPosition(-1);\r
+        }\r
+        \r
+        void initData(int scrollTo)\r
+        {\r
+            if (mAdapter == null)\r
+                return;\r
+\r
+            this.ClipToBounds = true;\r
+\r
+\r
+            int cnt = mAdapter.getCount();\r
+            mItemCount = cnt;\r
+            //mCurrentScrollPos = scrollTo * DEFAULT_ITEM_HEIGHT;\r
+\r
+            mScrollHeight.initHeightArray(cnt);\r
+\r
+            UIElementCollection col = base.InternalChildren;\r
+            col.Clear();\r
+\r
+            if (mScrollbar == null)\r
+            {\r
+                mScrollbar = new ScrollBar();\r
+                mScrollbar.Visibility = System.Windows.Visibility.Visible;\r
+                mScrollbar.ValueChanged += mScrollbar_ValueChanged;\r
+            }\r
+            \r
+            col.Add(mScrollbar);\r
+\r
+            for (int i = 0; i < cnt; i++)\r
+            {\r
+                UIElement element = new Grid();// mAdapter.getElement(i, null);\r
+                col.Add(element);\r
+            }\r
+            //mScrollState = SCROLL_STATE.EXPLICIT;\r
+            mScrollbar.Maximum = mScrollHeight.getTotalHeight();\r
+            mScrollbar.Minimum = 0;\r
+            mScrollbar.Value = mCurrentScrollPos;\r
+            mScrollbar.SmallChange = SCRILL_CHANGE_VALUE;\r
+            mScrollbar.LargeChange = DEFAULT_ITEM_HEIGHT;\r
+            //setScrollItemPosition(scrollTo);\r
+        }\r
+\r
+        public void setScrollItemPosition(int itemPosition)\r
+        {\r
+            mScrollState = SCROLL_STATE.EXPLICIT;\r
+            if (itemPosition >= 0)\r
+            {\r
+                mCurrentScrollPos = mScrollHeight.getScrollOffset(itemPosition);\r
+            }\r
+            this.MeasureOverride(mSavedPanelSize);\r
+            this.ArrangeOverride(mSavedPanelSize);\r
+            mScrollbar.Value = mCurrentScrollPos;\r
+            mScrollState = SCROLL_STATE.NONE;\r
+        }\r
+\r
+        void setScrollValuePreventEvent(double value)\r
+        {\r
+            if (value < mScrollbar.Minimum)\r
+                value = mScrollbar.Minimum;\r
+            if (value > mScrollbar.Maximum)\r
+                value = mScrollbar.Maximum;\r
+\r
+            if (mScrollbar != null)\r
+            {\r
+                SCROLL_STATE savedState = mScrollState;\r
+                mScrollState = SCROLL_STATE.SKIP;\r
+                mScrollbar.Value = value;\r
+                mScrollState = savedState;\r
+            }\r
+        }\r
+        void setScrollValue(double value)\r
+        {\r
+            if (value < mScrollbar.Minimum)\r
+                value = mScrollbar.Minimum;\r
+            if (value > mScrollbar.Maximum)\r
+                value = mScrollbar.Maximum;\r
+            mCurrentScrollPos = value;\r
+            if (mScrollbar != null)\r
+            {\r
+                 mScrollbar.Value = value;\r
+            }\r
+        }\r
+\r
+        void mScrollbar_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)\r
+        {\r
+            if (mScrollState == SCROLL_STATE.SKIP)\r
+                return;\r
+\r
+            bool restoreState = false;\r
+            \r
+            if (mScrollState == SCROLL_STATE.NONE)\r
+            {\r
+                if (mCurrentScrollPos < (int)e.NewValue)\r
+                    mScrollState = SCROLL_STATE.CURSOR_DOWN;\r
+                else\r
+                    mScrollState = SCROLL_STATE.CURSOR_UP;\r
+                restoreState = true;\r
+            }\r
+            mCurrentScrollPos = (int)e.NewValue;\r
+\r
+            this.MeasureOverride(mSavedPanelSize);\r
+            this.ArrangeOverride(mSavedPanelSize);\r
+            if(restoreState)\r
+                mScrollState = SCROLL_STATE.NONE;\r
+        }\r
+\r
+\r
+        protected override Size ArrangeOverride(Size finalSize)\r
+        {\r
+            Size panelSize = finalSize;\r
+            mSavedPanelSize = finalSize;\r
+\r
+            if (mScrollbar != null)\r
+            {\r
+                Size desiredSize = mScrollbar.DesiredSize;\r
+                desiredSize.Height = finalSize.Height;\r
+                panelSize.Width = finalSize.Width - desiredSize.Width;\r
+                mScrollbar.Arrange(new Rect(new Point(panelSize.Width, 0), desiredSize));\r
+            }\r
+\r
+            int position;\r
+            double itemOffsetY;\r
+            if (!mScrollHeight.tryGetItemPosition(mCurrentScrollPos, out position, out itemOffsetY))\r
+            {\r
+                position = 0;\r
+                itemOffsetY = 0;\r
+            }\r
+            else\r
+            {\r
+                itemOffsetY *= -1;\r
+            }\r
+\r
+            double y = itemOffsetY;\r
+            int num = 0;\r
+            bool complated = false;\r
+            foreach (UIElement element in base.InternalChildren)\r
+            {\r
+                ScrollBar sb = element as ScrollBar;\r
+                if (sb != null)\r
+                {\r
+                    continue;\r
+                }\r
+                if (num < position || complated)\r
+                {\r
+                    element.Arrange(new Rect(new Point(0, element.DesiredSize.Height * -1), element.DesiredSize));\r
+                    num++;\r
+                    continue;\r
+                }\r
+                element.Arrange(new Rect(new Point(0, y), element.DesiredSize));\r
+                y += element.DesiredSize.Height;\r
+                if (y > this.ActualHeight)\r
+                {\r
+                    complated = true;\r
+                }\r
+            }\r
+            if (mScrollbar != null)\r
+            {\r
+                mScrollbar.LargeChange = finalSize.Height;\r
+                mScrollbar.Maximum = mScrollHeight.getTotalHeight() - finalSize.Height;\r
+            }\r
+\r
+            return finalSize;\r
+        }\r
+\r
+\r
+        protected override Size MeasureOverride(Size constraint)\r
+        {\r
+            Size panelSize = constraint;\r
+\r
+            if (mScrollbar != null)\r
+            {\r
+                mScrollbar.Measure(constraint);\r
+                Size desiredSize = mScrollbar.DesiredSize;\r
+                panelSize.Width -= desiredSize.Width;\r
+            }\r
+\r
+            int position;\r
+            double itemOffsetY;\r
+            if (!mScrollHeight.tryGetItemPosition(mCurrentScrollPos, out position, out itemOffsetY))\r
+            {\r
+                position = 0;\r
+                itemOffsetY = 0;\r
+            }\r
+            else\r
+            {\r
+                itemOffsetY *= -1;\r
+            }\r
+\r
+            double y = itemOffsetY;\r
+            int num = 0;\r
+            double chgDelta = 0;\r
+            \r
+            panelSize.Height = double.PositiveInfinity;\r
+\r
+            foreach (UIElement element in base.InternalChildren)\r
+            {\r
+                ScrollBar sb = element as ScrollBar;\r
+                if (sb != null)\r
+                {\r
+                    continue;\r
+                }\r
+                if (num < position)\r
+                {\r
+                    num++;\r
+                    continue;\r
+                }\r
+                Grid grid = element as Grid;\r
+                if (grid != null && grid.Children.Count == 0)\r
+                {\r
+                    UIElement child = mAdapter.getElement(num, null);\r
+                    //child.PreviewKeyDown += UIElement_PreviewKeyDown;\r
+                    //child.PreviewKeyUp += UIElement_PreviewKeyUp;\r
+                    grid.Children.Add(child);\r
+                }\r
+                element.Visibility = System.Windows.Visibility.Visible;\r
+                element.Measure(panelSize);\r
+                Size desiredSize = element.DesiredSize;\r
+                double d = mScrollHeight.setHeight(num, desiredSize.Height);\r
+                if (d != 0 && num == position)\r
+                    chgDelta = d;\r
+                num++;\r
+                y += desiredSize.Height;\r
+                if (y > constraint.Height)\r
+                    break;\r
+            }//End Foreach\r
+\r
+            if (y < constraint.Height && num > 0)\r
+            {\r
+                double excessiveSpace = constraint.Height - y;\r
+                double panelHeight = constraint.Height;\r
+                do\r
+                {\r
+                    UIElement element = base.InternalChildren[num];\r
+                    Grid grid = element as Grid;\r
+                    if (grid != null && grid.Children.Count == 0)\r
+                    {\r
+                        UIElement child = mAdapter.getElement(num-1, null);\r
+                        //child.PreviewKeyDown += UIElement_PreviewKeyDown;\r
+                        //child.PreviewKeyUp += UIElement_PreviewKeyUp;\r
+                        grid.Children.Add(child);\r
+                        //grid.Children.Add(mAdapter.getElement(num - 1, null));\r
+                    }\r
+                    element.Visibility = System.Windows.Visibility.Visible;\r
+                    element.Measure(panelSize);\r
+                    Size desiredSize = element.DesiredSize;\r
+                    num--;\r
+                    panelHeight -= desiredSize.Height;\r
+                    mScrollHeight.setHeight(num, desiredSize.Height);\r
+                } while (panelHeight > 0 && num > 0);\r
+\r
+\r
+                double totalHeight = mScrollHeight.getTotalHeight();\r
+\r
+\r
+                if (mScrollbar != null)\r
+                {\r
+                    mCurrentScrollPos = totalHeight - constraint.Height;\r
+                    setScrollValuePreventEvent(mCurrentScrollPos);\r
+                }\r
+            }\r
+            else\r
+            {\r
+                if (mScrollbar != null)\r
+                {\r
+                    if (mScrollState == SCROLL_STATE.CURSOR_UP)\r
+                    {\r
+                        mCurrentScrollPos += chgDelta;\r
+                        setScrollValuePreventEvent(mCurrentScrollPos);\r
+                    }\r
+                }\r
+            }\r
+             return constraint;\r
+        }\r
+    }\r
+}\r
diff --git a/NT2chCtrl45/UIElementListAdapter_event.cs b/NT2chCtrl45/UIElementListAdapter_event.cs
new file mode 100755 (executable)
index 0000000..341b193
--- /dev/null
@@ -0,0 +1,95 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Windows;\r
+using System.Windows.Controls;\r
+using System.Windows.Input;\r
+\r
+namespace NT2chCtrl\r
+{\r
+    public partial class UIElementListPanel : Panel\r
+    {\r
+#if DOTNET45\r
+        bool mTouchDown = false;\r
+        Point mPos;\r
+        Point mDownPos;\r
+        int mTimeStamp;\r
+\r
+        void UIElementListPanel_TouchDown(object sender, System.Windows.Input.TouchEventArgs e)\r
+        {\r
+            mTouchDown = true;\r
+            mTimeStamp = e.Timestamp;\r
+            \r
+            TouchPoint point = e.GetTouchPoint(this);\r
+            mDownPos = mPos = point.Position;\r
+            e.Handled = true;\r
+            //System.Diagnostics.Debug.WriteLine(\r
+            /*string msg = "TouchDown 【" +\r
+                pos.Position.X + "-" + pos.Position.Y + "】";\r
+            if (test == 0)\r
+            {\r
+                MessageBox.Show(msg);\r
+                test = 1;\r
+            }*/\r
+        }\r
+        void UIElementListPanel_TouchMove(object sender, System.Windows.Input.TouchEventArgs e)\r
+        {\r
+            if (!mTouchDown)\r
+                return;\r
+            TouchPoint pos = e.GetTouchPoint(this);\r
+            double vOffset = pos.Position.Y - mPos.Y;\r
+            mPos = pos.Position;\r
+\r
+            setScrollValue(mCurrentScrollPos - vOffset);\r
+            //System.Diagnostics.Debug.WriteLine(\r
+            //string msg = "TouchMove (" + \r
+            //    pos.Position.X + "-" + pos.Position.Y + ")";\r
+            //throw new NotImplementedException();\r
+            //if (test == 1)\r
+            //{\r
+            //   MessageBox.Show(msg);\r
+            //   test = 0;\r
+            //}\r
+        }\r
+\r
+        void UIElementListPanel_TouchUp(object sender, System.Windows.Input.TouchEventArgs e)\r
+        {\r
+            if (!mTouchDown)\r
+                return;\r
+            mTouchDown = false;\r
+\r
+            int timestamp = e.Timestamp;\r
+\r
+            int timeElapse = timestamp - mTimeStamp;\r
+\r
+            //string msg = "Time elapse: " + timeElapse + "msec";\r
+\r
+            //MessageBox.Show(msg);\r
+\r
+            TouchPoint pos = e.GetTouchPoint(this);\r
+            double vOffset = pos.Position.Y - mDownPos.Y;\r
+            //mPos = pos.Position;\r
+            vOffset *= 1000;\r
+            vOffset /= timeElapse;\r
+\r
+            startScrollObserveTimer(vOffset);\r
+            //TouchPoint pos = e.GetTouchPoint(this);\r
+            //System.Diagnostics.Debug.WriteLine(\r
+            //string msg = "TouchUp 【" +\r
+            //    pos.Position.X + "-" + pos.Position.Y + "】";\r
+        }\r
+\r
+        void UIElementListPanel_TouchLeave(object sender, TouchEventArgs e)\r
+        {\r
+            mTouchDown = false;\r
+            //throw new NotImplementedException();\r
+        }\r
+\r
+        void UIElementListPanel_TouchEnter(object sender, TouchEventArgs e)\r
+        {\r
+            mTouchDown = false;\r
+            //throw new NotImplementedException();\r
+        }\r
+#endif\r
+    }\r
+}\r
diff --git a/NT2chCtrl45/UIElementListAdapter_timer.cs b/NT2chCtrl45/UIElementListAdapter_timer.cs
new file mode 100755 (executable)
index 0000000..66ed07c
--- /dev/null
@@ -0,0 +1,124 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Windows.Controls;\r
+using System.Windows.Threading;\r
+\r
+namespace NT2chCtrl\r
+{\r
+    public partial class UIElementListPanel : Panel\r
+    {\r
+        const int SCROLL_OBSERVE_TIMER_DURATION = 1000 / 15; //15 frames per second;\r
+        const double SCROLL_FRICTION_RATIO = 0.9;\r
+        const double MAX_SCROLL_SPEED_DELTA = 10000;\r
+\r
+        object mLockTimerObj = new object();\r
+        Timer mTimer;\r
+        double mSpeedDelta;\r
+        bool mAutoScroll;\r
+        double mAutoScrollDelta;\r
+        bool mPauseAutoScroll = false;\r
+\r
+        public void setAutoScroll(bool enable, double ratio)\r
+        {\r
+            mAutoScroll = enable;\r
+            if (enable)\r
+            {\r
+                mAutoScrollDelta = ratio * 100;\r
+                mSpeedDelta = 0;\r
+                startScrollObserveTimer(-mAutoScrollDelta);\r
+            }\r
+        }\r
+\r
+        public void toggleScrollDirection()\r
+        {\r
+            mSpeedDelta *= -1;\r
+        }\r
+\r
+        public void pauseAutoScroll()\r
+        {\r
+            mPauseAutoScroll = true;\r
+        }\r
+        public void resumeAutoScroll()\r
+        {\r
+            mPauseAutoScroll = false;\r
+        }\r
+        public void reverseAutoScroll()\r
+        {\r
+        }\r
+\r
+        private void startScrollObserveTimer(double delta)\r
+        {\r
+            lock (mLockTimerObj)\r
+            {\r
+                if (mTimer == null)\r
+                {\r
+                    mSpeedDelta = delta;\r
+                    mTimer = new System.Threading.Timer(\r
+                        scrollObserveTimerCallback,\r
+                        null,\r
+                        SCROLL_OBSERVE_TIMER_DURATION,\r
+                        SCROLL_OBSERVE_TIMER_DURATION);\r
+                }\r
+                else\r
+                {\r
+                    mSpeedDelta += delta;\r
+                    if (mSpeedDelta > MAX_SCROLL_SPEED_DELTA)\r
+                        mSpeedDelta = MAX_SCROLL_SPEED_DELTA;\r
+                    if (mSpeedDelta < -MAX_SCROLL_SPEED_DELTA)\r
+                        mSpeedDelta = -MAX_SCROLL_SPEED_DELTA;\r
+                    mTimer.Change(\r
+                        SCROLL_OBSERVE_TIMER_DURATION,\r
+                        SCROLL_OBSERVE_TIMER_DURATION);\r
+                }\r
+            }\r
+        }\r
+\r
+        private void scrollObserveTimerCallback(object param)\r
+        {\r
+            lock (mLockTimerObj)\r
+            {\r
+                double newOffset = mCurrentScrollPos - (mSpeedDelta/15);\r
+\r
+                mSpeedDelta *= SCROLL_FRICTION_RATIO;\r
+#if DOTNET45\r
+                if (mTouchDown)\r
+                {\r
+                    mSpeedDelta *= SCROLL_FRICTION_RATIO;\r
+                }\r
+#endif\r
+                if (mAutoScroll)\r
+                {\r
+                    if (mSpeedDelta < mAutoScrollDelta && mSpeedDelta > -mAutoScrollDelta)\r
+                    {\r
+                        if(mSpeedDelta > 0)\r
+                            mSpeedDelta = mAutoScrollDelta;                    \r
+                        else\r
+                            mSpeedDelta = -mAutoScrollDelta;\r
+                    }\r
+                    if (mPauseAutoScroll)\r
+                        return;\r
+                }\r
+                else\r
+                {\r
+                    if (mSpeedDelta < 10 && mSpeedDelta > -10)\r
+                    {\r
+                        mSpeedDelta = 0;\r
+                        if (mTimer != null)\r
+                        {\r
+                            mTimer.Dispose();\r
+                            mTimer = null;\r
+                        }\r
+                    }\r
+                }\r
+                this.Dispatcher.BeginInvoke(DispatcherPriority.Normal,\r
+                    (ThreadStart)delegate()\r
+                {\r
+                    setScrollValue(newOffset);\r
+                });         \r
+            }\r
+\r
+        }\r
+    }\r
+}\r
diff --git a/NT2chCtrl45/UIElementListAdapter_util.cs b/NT2chCtrl45/UIElementListAdapter_util.cs
new file mode 100755 (executable)
index 0000000..a7f3c57
--- /dev/null
@@ -0,0 +1,96 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading.Tasks;\r
+using System.Windows.Controls;\r
+\r
+namespace NT2chCtrl\r
+{\r
+    partial class UIElementListPanel : Panel\r
+    {\r
+        class ScrollItemHeight\r
+        {\r
+            double[] mHeightArray = new double[0];\r
+\r
+            public double setHeight(int position, double value)\r
+            {\r
+                if (position < 0 || position >= mHeightArray.Length)\r
+                    return 0;\r
+\r
+                double tmp = mHeightArray[position];\r
+                mHeightArray[position] = value;\r
+                return value - tmp;\r
+            }\r
+\r
+            public double getHeight(int position)\r
+            {\r
+                if (position < 0 || position >= mHeightArray.Length)\r
+                    return 0;\r
+                return mHeightArray[position];\r
+            }\r
+\r
+            public void initHeightArray(int num)\r
+            {\r
+                if (num < 0)\r
+                    num = 0;\r
+                mHeightArray = new double[num];\r
+                for (int i = 0; i < num; i++)\r
+                {\r
+                    mHeightArray[i] = DEFAULT_ITEM_HEIGHT;\r
+                }\r
+            }\r
+\r
+            public double getTotalHeight()\r
+            {\r
+                double total = 0;\r
+                foreach (double d in mHeightArray)\r
+                {\r
+                    total += d;\r
+                }\r
+                return total;\r
+            }\r
+\r
+            public bool tryGetItemPosition(double offset, out int position, out double itemOffset)\r
+            {\r
+                position = 0;\r
+                itemOffset = 0;\r
+\r
+                if (offset < 0)\r
+                    return false;\r
+\r
+                int num = mHeightArray.Length;\r
+                if (num == 0)\r
+                    return false;\r
+\r
+                double totalHeight = 0;\r
+                for (int i = 0; i < num; i++)\r
+                {\r
+                    totalHeight += mHeightArray[i];\r
+                    if (offset < totalHeight)\r
+                    {\r
+                        position = i;\r
+                        double tmp = totalHeight - offset;\r
+                        itemOffset = mHeightArray[i] - tmp;\r
+                        return (itemOffset < 0) ? false : true;\r
+                    }\r
+                }\r
+                return false;\r
+            }\r
+\r
+            public double getScrollOffset(int itemPosition)\r
+            {\r
+                int num = mHeightArray.Length;\r
+                if (num == 0 || num <= itemPosition)\r
+                    return 0;\r
+\r
+                double totalHeight = 0;\r
+                for (int i = 0; i < itemPosition; i++)\r
+                {\r
+                    totalHeight += mHeightArray[i];\r
+                }\r
+                return totalHeight;\r
+            }\r
+        }\r
+    }\r
+}\r
diff --git a/NT2chCtrl45/html/CommentElement.cs b/NT2chCtrl45/html/CommentElement.cs
new file mode 100755 (executable)
index 0000000..a7f649a
--- /dev/null
@@ -0,0 +1,16 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+\r
+namespace NT2chCtrl.html\r
+{\r
+    class CommentElement : HtmlElement\r
+    {\r
+        string mCommentString;\r
+        public CommentElement(HtmlElement parent, string comment)\r
+            : base(parent, string.Empty)\r
+        {\r
+            mCommentString = comment;\r
+        }\r
+    }\r
+}\r
diff --git a/NT2chCtrl45/html/DebugContext.cs b/NT2chCtrl45/html/DebugContext.cs
new file mode 100755 (executable)
index 0000000..d936566
--- /dev/null
@@ -0,0 +1,63 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+\r
+namespace NT2chCtrl.html\r
+{\r
+    public class DebugContext\r
+    {\r
+        public int mCurrentLine;\r
+        public int mCurentIndex;\r
+        public int mBaseIndex;\r
+        public string mErrorMessage;\r
+\r
+        public DebugContext()\r
+        {\r
+            mCurrentLine = 1;\r
+            mCurentIndex = 0;\r
+            mBaseIndex = 0;\r
+            mErrorMessage = null;\r
+        }\r
+        public void init()\r
+        {\r
+            mCurrentLine = 1;\r
+            mBaseIndex = 0;\r
+        }\r
+        /*public DebugContext(int currentLine)\r
+        {\r
+            mCurrentLine = currentLine;\r
+        }*/\r
+\r
+        public int getCurrentLine()\r
+        {\r
+            return mCurrentLine;\r
+        }\r
+\r
+        public int getCurrentIndex()\r
+        {\r
+            return mBaseIndex + mCurentIndex;\r
+        }\r
+\r
+        public string getErrorMessage()\r
+        {\r
+            return mErrorMessage;\r
+        }\r
+        public void setCurrentIdx(int idx)\r
+        {\r
+            mCurentIndex = idx;\r
+        }\r
+        public void setCurrentLine(int line)\r
+        {\r
+            mCurrentLine = line;\r
+        }\r
+        public void incrementLine()\r
+        {\r
+            mCurrentLine++;\r
+        }\r
+\r
+        public void setErrorMessage(string message)\r
+        {\r
+            mErrorMessage = message;\r
+        }\r
+    }\r
+}\r
diff --git a/NT2chCtrl45/html/HtmlAttribute.cs b/NT2chCtrl45/html/HtmlAttribute.cs
new file mode 100755 (executable)
index 0000000..0cbd161
--- /dev/null
@@ -0,0 +1,30 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+\r
+namespace NT2chCtrl.html\r
+{\r
+    public class HtmlAttribute\r
+    {\r
+        string mName;\r
+        string mValue;\r
+\r
+        public string getName() { return mName; }\r
+        public string getValue() { return mValue; }\r
+\r
+        public HtmlAttribute(string name, string value)\r
+        {\r
+            mName = name;\r
+            if (value == null || value.Length == 0)\r
+                mValue = name;\r
+            else\r
+                mValue = value;\r
+        }\r
+\r
+        public HtmlAttribute(string name)\r
+        {\r
+            mName = name;\r
+            mValue = name;\r
+        }\r
+    }\r
+}\r
diff --git a/NT2chCtrl45/html/HtmlColors.cs b/NT2chCtrl45/html/HtmlColors.cs
new file mode 100755 (executable)
index 0000000..ef9c793
--- /dev/null
@@ -0,0 +1,349 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Windows.Media;\r
+\r
+namespace NT2chCtrl.html\r
+{\r
+#if false\r
+    class HtmlColor\r
+    {\r
+        string mColorName;\r
+        int mColorValue;\r
+\r
+        HtmlColor(string colorName, int colorValue)\r
+        {\r
+            mColorName = colorName;\r
+            mColorValue = colorValue;\r
+        }\r
+\r
+        public static Color getColor(string colorText)\r
+        {\r
+            colorText = colorText.Trim();\r
+            int idx;\r
+\r
+            idx = colorText.IndexOf("rgb(");\r
+            if (idx == 0)\r
+            {\r
+                int endIdx;\r
+                return getColorFromRgbString(colorText, 4, out endIdx);\r
+            }\r
+            idx = colorText.IndexOf('#');\r
+            if (idx == 0)\r
+            {\r
+                return getColorFromHexString(colorText, 1);\r
+            }\r
+            foreach (HtmlColor c in mColorList)\r
+            {\r
+                if (colorText.Equals(c.mColorName, StringComparison.OrdinalIgnoreCase))\r
+                    return getColor(c.mColorValue);\r
+            }\r
+            return Colors.Transparent;\r
+        }\r
+\r
+\r
+        private static Color getColorFromRgbString(string rgbString, int startIdx, out int endIdx)\r
+        {\r
+\r
+            int length = rgbString.Length;\r
+            int digits = 0;\r
+            int value = 0;\r
+            int colorIdx = 0;\r
+            int r = 0, g = 0;//, b = 0;\r
+\r
+            endIdx = 0;\r
+\r
+            for (int i = startIdx; i < length; i++)\r
+            {\r
+                char c = rgbString[i];\r
+                if (c >= '0' && c <= '9')\r
+                {\r
+                    if (digits == 0)\r
+                        value = c - '0';\r
+                    else if (digits == 1)\r
+                        value = (c - '0') + (value * 10);\r
+                    else if (digits == 2)\r
+                        value = (c - '0') + (value * 10);\r
+                    else\r
+                        return Colors.Transparent;\r
+                    digits++;\r
+                }\r
+                else if (c == ',')\r
+                {\r
+                    if (digits == 0)\r
+                        return Colors.Transparent;\r
+\r
+                    if (colorIdx == 0)\r
+                        r = value;\r
+                    else if (colorIdx == 1)\r
+                        g = value;\r
+                    //else if (colorIdx == 2)\r
+                    //    b = value;\r
+                    else\r
+                        return Colors.Transparent;\r
+                    colorIdx++;\r
+                    digits = 0;\r
+                }\r
+                else if (c == ' ' || c == '\t' || c == 'r' || c == '\n')\r
+                {\r
+                }\r
+                else if (c == ')')\r
+                {\r
+                    if (colorIdx != 2)\r
+                        return Colors.Transparent;\r
+                    endIdx = i;\r
+                    return Color.FromRgb((byte)r, (byte)g, (byte)value);\r
+                }\r
+                else\r
+                {\r
+                    return Colors.Transparent;\r
+                }\r
+            }\r
+            return Colors.Transparent;\r
+        }\r
+\r
+        private static Color getColorFromHexString(string hexString, int startIdx)\r
+        {\r
+            int[] by = new int[8];\r
+            int length = Math.Min(hexString.Length, 8);\r
+            int idx = 0;\r
+            for (int i = startIdx; i < length; i++)\r
+            {\r
+                char c = hexString[i];\r
+                if (c >= '0' && c <= '9')\r
+                {\r
+                    by[idx] = (c - '0');\r
+                }else if(c >= 'a' && c <= 'f'){\r
+                    by[idx] = (c - 'a' + 10);\r
+                }\r
+                else if (c >= 'A' && c <= 'F')\r
+                {\r
+                    by[idx] = (c - 'A' + 10);\r
+                }\r
+                else\r
+                {\r
+                    idx++;\r
+                    break;\r
+                }\r
+                idx++;\r
+            }\r
+            if (idx < 0 || idx > 6)\r
+                return Colors.Transparent;\r
+\r
+            int r = 0, g = 0, b = 0;\r
+            idx--;\r
+            if (idx < 3)\r
+            {\r
+                for (int i = 0; idx >= 0; i++)\r
+                {\r
+                    switch (i)\r
+                    {\r
+                        case 0:\r
+                            b = by[idx];\r
+                            break;\r
+                        case 1:\r
+                            g = by[idx];\r
+                            break;\r
+                        case 2:\r
+                            r = by[idx];\r
+                            break;\r
+                    }\r
+\r
+                    idx--;\r
+                }\r
+            }\r
+            else\r
+            {\r
+                for (int i = 0; idx >= 0; i++)\r
+                {\r
+                    switch (i)\r
+                    {\r
+                        case 0:\r
+                            b = by[idx];\r
+                            break;\r
+                        case 1:\r
+                            b += (by[idx] << 4);\r
+                            break;\r
+                        case 2:\r
+                            g = by[idx];\r
+                            break;\r
+                        case 3:\r
+                            g += (by[idx] << 4);\r
+                            break;\r
+                        case 4:\r
+                            r = by[idx];\r
+                            break;\r
+                        case 5:\r
+                            r += (by[idx] << 4);\r
+                            break;\r
+                    }\r
+\r
+                    idx--;\r
+                }\r
+            }\r
+\r
+            return Color.FromRgb((byte)r, (byte)g, (byte)b);\r
+\r
+        }\r
+\r
+        private static Color getColor(int value)\r
+        {\r
+            int r = (value & 0xff0000) >> 16;\r
+            int g = (value & 0xff00) >> 8;\r
+            int b = (value & 0xff);\r
+            return Color.FromRgb((byte)r, (byte)g, (byte)b);\r
+        }\r
+\r
+        static HtmlColor [] mColorList = \r
+        {\r
+            new HtmlColor("aliceblue", 0xF0F8FF),      // 240,248,255\r
+            new HtmlColor("antiquewhite", 0xFAEBD7),   //250,235,215\r
+            new HtmlColor("aqua", 0x00FFFF),   //0,255,255\r
+            new HtmlColor("aquamarine", 0x7FFFD4),     //127,255,212\r
+            new HtmlColor("azure", 0xF0FFFF),  //240,255,255\r
+            new HtmlColor("beige", 0xF5F5DC),  //245,245,220\r
+            new HtmlColor("bisque", 0xFFE4C4), //255,228,196\r
+            new HtmlColor("black", 0x000000),  //0,0,0\r
+            new HtmlColor("blanchedalmond", 0xFFEBCD), //255,235,205\r
+            new HtmlColor("blue", 0x0000FF),   //0,0,255\r
+            new HtmlColor("blueviolet", 0x8A2BE2),     //138,43,226\r
+            new HtmlColor("brown", 0xA52A2A),  //165,42,42\r
+            new HtmlColor("burlywood", 0xDEB887),      //222,184,135\r
+            new HtmlColor("cadetblue", 0x5F9EA0),      //95,158,160\r
+            new HtmlColor("chartreuse", 0x7FFF00),     //127,255,0\r
+            new HtmlColor("chocolate", 0xD2691E),      //210,105,30\r
+            new HtmlColor("coral", 0xFF7F50),  //255,127,80\r
+            new HtmlColor("cornflowerblue", 0x6495ED), //100,149,237\r
+            new HtmlColor("cornsilk", 0xFFF8DC),       //255,248,220\r
+            new HtmlColor("crimson", 0xDC143C),        //220,20,60\r
+            new HtmlColor("cyan", 0x00FFFF),   //0,255,255\r
+            new HtmlColor("darkblue", 0x00008B),       //0,0,139\r
+            new HtmlColor("darkcyan", 0x008B8B),       //0,139,139\r
+            new HtmlColor("darkgoldenrod", 0xB8860B),  //184,134,11\r
+            new HtmlColor("darkgray", 0xA9A9A9),       //169,169,169\r
+            new HtmlColor("darkgreen", 0x006400),      //0,100,0\r
+            new HtmlColor("darkgrey", 0xA9A9A9),       //169,169,169\r
+            new HtmlColor("darkkhaki", 0xBDB76B),      //189,183,107\r
+            new HtmlColor("darkmagenta", 0x8B008B),    //139,0,139\r
+            new HtmlColor("darkolivegreen", 0x556B2F), //85,107,47\r
+            new HtmlColor("darkorange", 0xFF8C00),     //255,140,0\r
+            new HtmlColor("darkorchid", 0x9932CC),     //153,50,204\r
+            new HtmlColor("darkred", 0x8B0000),        //139,0,0\r
+            new HtmlColor("darksalmon", 0xE9967A),     //233,150,122\r
+            new HtmlColor("darkseagreen", 0x8FBC8F),   //143,188,143\r
+            new HtmlColor("darkslateblue", 0x483D8B),  //72,61,139\r
+            new HtmlColor("darkslategray", 0x2F4F4F),  //47,79,79\r
+            new HtmlColor("darkslategrey", 0x2F4F4F),  //47,79,79\r
+            new HtmlColor("darkturquoise", 0x00CED1),  //0,206,209\r
+            new HtmlColor("darkviolet", 0x9400D3),     //148,0,211\r
+            new HtmlColor("deeppink", 0xFF1493),       //255,20,147\r
+            new HtmlColor("deepskyblue", 0x00BFFF),    //0,191,255\r
+            new HtmlColor("dimgray", 0x696969),        //105,105,105\r
+            new HtmlColor("dimgrey", 0x696969),        //105,105,105\r
+            new HtmlColor("dodgerblue", 0x1E90FF),     //30,144,255\r
+            new HtmlColor("firebrick", 0xB22222),      //178,34,34\r
+            new HtmlColor("floralwhite", 0xFFFAF0),    //255,250,240\r
+            new HtmlColor("forestgreen", 0x228B22),    //34,139,34\r
+            new HtmlColor("fuchsia", 0xFF00FF),        //255,0,255\r
+            new HtmlColor("gainsboro", 0xDCDCDC),      //220,220,220\r
+            new HtmlColor("ghostwhite", 0xF8F8FF),     //248,248,255\r
+            new HtmlColor("gold", 0xFFD700),   //255,215,0\r
+            new HtmlColor("goldenrod", 0xDAA520),      //218,165,32\r
+            new HtmlColor("gray", 0x808080),   //128,128,128\r
+            new HtmlColor("green", 0x008000),  //0,128,0\r
+            new HtmlColor("greenyellow", 0xADFF2F),    //173,255,47\r
+            new HtmlColor("grey", 0x808080),   //128,128,128\r
+            new HtmlColor("honeydew", 0xF0FFF0),       //240,255,240\r
+            new HtmlColor("hotpink", 0xFF69B4),        //255,105,180\r
+            new HtmlColor("indianred", 0xCD5C5C),      //205,92,92\r
+            new HtmlColor("indigo", 0x4B0082), //75,0,130\r
+            new HtmlColor("ivory", 0xFFFFF0),  //255,255,240\r
+            new HtmlColor("khaki", 0xF0E68C),  //240,230,140\r
+            new HtmlColor("lavender", 0xE6E6FA),       //230,230,250\r
+            new HtmlColor("lavenderblush", 0xFFF0F5),  //255,240,245\r
+            new HtmlColor("lawngreen", 0x7CFC00),      //124,252,0\r
+            new HtmlColor("lemonchiffon", 0xFFFACD),   //255,250,205\r
+            new HtmlColor("lightblue", 0xADD8E6),      //173,216,230\r
+            new HtmlColor("lightcoral", 0xF08080),     //240,128,128\r
+            new HtmlColor("lightcyan", 0xE0FFFF),      //224,255,255\r
+            new HtmlColor("lightgoldenrodyellow", 0xFAFAD2),   //250,250,210\r
+            new HtmlColor("lightgray", 0xD3D3D3),      //211,211,211\r
+            new HtmlColor("lightgreen", 0x90EE90),     //144,238,144\r
+            new HtmlColor("lightgrey", 0xD3D3D3),      //211,211,211\r
+            new HtmlColor("lightpink", 0xFFB6C1),      //255,182,193\r
+            new HtmlColor("lightsalmon", 0xFFA07A),    //255,160,122\r
+            new HtmlColor("lightseagreen", 0x20B2AA),  //32,178,170\r
+            new HtmlColor("lightskyblue", 0x87CEFA),   //135,206,250\r
+            new HtmlColor("lightslategray", 0x778899), //119,136,153\r
+            new HtmlColor("lightslategrey", 0x778899), //119,136,153\r
+            new HtmlColor("lightsteelblue", 0xB0C4DE), //176,196,222\r
+            new HtmlColor("lightyellow", 0xFFFFE0),    //255,255,224\r
+            new HtmlColor("lime", 0x00FF00),   //0,255,0\r
+            new HtmlColor("limegreen", 0x32CD32),      //50,205,50\r
+            new HtmlColor("linen", 0xFAF0E6),  //250,240,230\r
+            new HtmlColor("magenta", 0xFF00FF),        //255,0,255\r
+            new HtmlColor("maroon", 0x800000), //128,0,0\r
+            new HtmlColor("mediumaquamarine", 0x66CDAA),       //102,205,170\r
+            new HtmlColor("mediumblue", 0x0000CD),     //0,0,205\r
+            new HtmlColor("mediumorchid", 0xBA55D3),   //186,85,211\r
+            new HtmlColor("mediumpurple", 0x9370DB),   //147,112,219\r
+            new HtmlColor("mediumseagreen", 0x3CB371), //60,179,113\r
+            new HtmlColor("mediumslateblue", 0x7B68EE),        //123,104,238\r
+            new HtmlColor("mediumspringgreen", 0x00FA9A),      //0,250,154\r
+            new HtmlColor("mediumturquoise", 0x48D1CC),        //72,209,204\r
+            new HtmlColor("mediumvioletred", 0xC71585),        //199,21,133\r
+            new HtmlColor("midnightblue", 0x191970),   //25,25,112\r
+            new HtmlColor("mintcream", 0xF5FFFA),      //245,255,250\r
+            new HtmlColor("mistyrose", 0xFFE4E1),      //255,228,225\r
+            new HtmlColor("moccasin", 0xFFE4B5),       //255,228,181\r
+            new HtmlColor("navajowhite", 0xFFDEAD),    //255,222,173\r
+            new HtmlColor("navy", 0x000080),   //0,0,128\r
+            new HtmlColor("oldlace", 0xFDF5E6),        //253,245,230\r
+            new HtmlColor("olive", 0x808000),  //128,128,0\r
+            new HtmlColor("olivedrab", 0x6B8E23),      //107,142,35\r
+            new HtmlColor("orange", 0xFFA500), //255,165,0\r
+            new HtmlColor("orangered", 0xFF4500),      //255,69,0\r
+            new HtmlColor("orchid", 0xDA70D6), //218,112,214\r
+            new HtmlColor("palegoldenrod", 0xEEE8AA),  //238,232,170\r
+            new HtmlColor("palegreen", 0x98FB98),      //152,251,152\r
+            new HtmlColor("paleturquoise", 0xAFEEEE),  //175,238,238\r
+            new HtmlColor("palevioletred", 0xDB7093),  //219,112,147\r
+            new HtmlColor("papayawhip", 0xFFEFD5),     //255,239,213\r
+            new HtmlColor("peachpuff", 0xFFDAB9),      //255,218,185\r
+            new HtmlColor("peru", 0xCD853F),   //205,133,63\r
+            new HtmlColor("pink", 0xFFC0CB),   //255,192,203\r
+            new HtmlColor("plum", 0xDDA0DD),   //221,160,221\r
+            new HtmlColor("powderblue", 0xB0E0E6),     //176,224,230\r
+            new HtmlColor("purple", 0x800080), //128,0,128\r
+            new HtmlColor("red", 0xFF0000),    //255,0,0\r
+            new HtmlColor("rosybrown", 0xBC8F8F),      //188,143,143\r
+            new HtmlColor("royalblue", 0x4169E1),      //65,105,225\r
+            new HtmlColor("saddlebrown", 0x8B4513),    //139,69,19\r
+            new HtmlColor("salmon", 0xFA8072), //250,128,114\r
+            new HtmlColor("sandybrown", 0xF4A460),     //244,164,96\r
+            new HtmlColor("seagreen", 0x2E8B57),       //46,139,87\r
+            new HtmlColor("seashell", 0xFFF5EE),       //255,245,238\r
+            new HtmlColor("sienna", 0xA0522D), //160,82,45\r
+            new HtmlColor("silver", 0xC0C0C0), //192,192,192\r
+            new HtmlColor("skyblue", 0x87CEEB),        //135,206,235\r
+            new HtmlColor("slateblue", 0x6A5ACD),      //106,90,205\r
+            new HtmlColor("slategray", 0x708090),      //112,128,144\r
+            new HtmlColor("slategrey", 0x708090),      //112,128,144\r
+            new HtmlColor("snow", 0xFFFAFA),   //255,250,250\r
+            new HtmlColor("springgreen", 0x00FF7F),    //0,255,127\r
+            new HtmlColor("steelblue", 0x4682B4),      //70,130,180\r
+            new HtmlColor("tan", 0xD2B48C),    //210,180,140\r
+            new HtmlColor("teal", 0x008080),   //0,128,128\r
+            new HtmlColor("thistle", 0xD8BFD8),        //216,191,216\r
+            new HtmlColor("tomato", 0xFF6347), //255,99,71\r
+            new HtmlColor("turquoise", 0x40E0D0),      //64,224,208\r
+            new HtmlColor("violet", 0xEE82EE), //238,130,238\r
+            new HtmlColor("wheat", 0xF5DEB3),  //245,222,179\r
+            new HtmlColor("white", 0xFFFFFF),  //255,255,255\r
+            new HtmlColor("whitesmoke", 0xF5F5F5),     //245,245,245\r
+            new HtmlColor("yellow", 0xFFFF00), //255,255,0\r
+            new HtmlColor("yellowgreen", 0x9ACD32),    //154,205,50\r
+        };\r
+    }\r
+#endif\r
+}\r
diff --git a/NT2chCtrl45/html/HtmlElement.cs b/NT2chCtrl45/html/HtmlElement.cs
new file mode 100755 (executable)
index 0000000..a177e34
--- /dev/null
@@ -0,0 +1,332 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using NT2chCtrl.html.css;\r
+using NT2chObject;\r
+\r
+namespace NT2chCtrl.html\r
+{\r
+    public partial class HtmlElement\r
+    {\r
+        HtmlElement mParent;\r
+        List<HtmlElement> mChildren;\r
+        List<HtmlAttribute> mAttributes;\r
+        List<string> mClassList = null;\r
+        List<Selector> mMatchedSelector;\r
+        string mTagName;\r
+        protected bool mClosed;\r
+\r
+        public int mDebugLine;\r
+        public int mDebugSourceIndex;\r
+        public void setDebugInfo(int line, int sourceIndex)\r
+        {\r
+            mDebugLine = line;\r
+            mDebugSourceIndex = sourceIndex;\r
+        }\r
+\r
+        public HtmlElement getParent() { return mParent; }\r
+        public List<HtmlElement> getChildren() { return mChildren; }\r
+        public void setChildren(List<HtmlElement>  children) { mChildren = children; }\r
+        public bool Closed() { return mClosed; }\r
+        public void setClosed(bool value) { mClosed = value; }\r
+        public string getTagName() { return mTagName; }\r
+        public void addAttribute(HtmlAttribute item)\r
+        {\r
+            mAttributes.Add(item);\r
+        }\r
+        public void clearChildren()\r
+        {\r
+            mChildren.Clear();\r
+        }\r
+\r
+        public string getInnerHtml()\r
+        {\r
+            StringBuilder sb = new StringBuilder();\r
+            foreach (HtmlElement elem in mChildren)\r
+            {\r
+                elem.getOuterHtml(sb);\r
+            }\r
+            return sb.ToString();\r
+        }\r
+        public string getOuterHtml()\r
+        {\r
+            StringBuilder sb = new StringBuilder();\r
+            if(!Tag2String(sb))\r
+                return sb.ToString();\r
+            if (mChildren.Count == 0)\r
+            {\r
+                sb.Append("/>");\r
+                return sb.ToString();\r
+            }\r
+            sb.Append(">");\r
+            foreach (HtmlElement elem in mChildren)\r
+            {\r
+                elem.getOuterHtml(sb);\r
+            }\r
+            sb.Append("</").Append(mTagName).Append('>');\r
+            return sb.ToString();\r
+        }\r
+\r
+        private void getOuterHtml(StringBuilder sb)\r
+        {\r
+            if(!Tag2String(sb))\r
+                return;\r
+            if (mChildren.Count == 0)\r
+            {\r
+                sb.Append("/>");\r
+                return;\r
+            }\r
+            sb.Append(">");\r
+            foreach (HtmlElement elem in mChildren)\r
+            {\r
+                elem.getOuterHtml(sb);\r
+            }\r
+            sb.Append("</").Append(mTagName).Append('>');\r
+        }\r
+\r
+        protected virtual bool Tag2String(StringBuilder sb)\r
+        {\r
+            int nVal;\r
+            sb.Append('<').Append(mTagName).Append(' ');\r
+\r
+            foreach (HtmlAttribute attr in mAttributes)\r
+            {\r
+                string name = attr.getName();\r
+                string value = attr.getValue();\r
+                if (name.Equals(value))\r
+                {\r
+                    sb.Append(name);\r
+                }\r
+                else\r
+                {\r
+                    sb.Append(name).Append('=');\r
+                    if (int.TryParse(value, out nVal))\r
+                    {\r
+                        sb.Append(value);\r
+                    }\r
+                    else\r
+                    {\r
+                        sb.Append('\"').Append(value).Append('\"');\r
+                    }\r
+                }\r
+                sb.Append(' ');\r
+            }\r
+            return true;\r
+        }\r
+\r
+        public string getAttributeValue(string attrName)\r
+        {\r
+            int count = mAttributes.Count;\r
+            for (int i = 0; i < count; i++)\r
+            {\r
+                if (mAttributes[i].getName().Equals(attrName))\r
+                {\r
+                    return mAttributes[i].getValue();\r
+                }\r
+            }\r
+            return null;\r
+        }\r
+\r
+        public void addSelector(Selector stor)\r
+        {\r
+            mMatchedSelector.Add(stor);\r
+        }\r
+\r
+        public HtmlElement(HtmlElement parent, string tagName)\r
+        {\r
+            mParent = parent;\r
+            if (mParent != null)\r
+                parent.mChildren.Add(this);\r
+            mTagName = tagName;\r
+            mChildren = new List<HtmlElement>();\r
+            mAttributes = new List<HtmlAttribute>();\r
+            mMatchedSelector = new List<Selector>();\r
+            mClosed = false;\r
+            mDebugLine = -1;\r
+            mDebugSourceIndex = -1;\r
+        }\r
+\r
+        public virtual HtmlElement Clone(HtmlElement parent)\r
+        {\r
+            HtmlElement elem = new HtmlElement(parent, mTagName);\r
+\r
+            elem.mAttributes.AddRange(mAttributes);\r
+            elem.mClosed = mClosed;\r
+            if(mClassList != null)\r
+                elem.mClassList.AddRange(mClassList);\r
+\r
+            foreach (HtmlElement e in mChildren)\r
+            {\r
+                e.Clone(elem);\r
+            }\r
+            return elem;\r
+        }\r
+\r
+        public void setInnerResHtml(string text, IAmbiguousSearch search)\r
+        {\r
+            mChildren.Clear();\r
+            //setInnerText(text);\r
+            parse2chRes(text, search);\r
+        }\r
+        public void setInnerText(string text)\r
+        {\r
+            mChildren.Clear();\r
+            StringElement elem = new StringElement(this, text);\r
+        }\r
+\r
+        public List<HtmlElement> getChildren(//HtmlElement parant, \r
+            string tagName, List<string> classList, string id,\r
+            string attrName)\r
+        {\r
+            List<HtmlElement> rList = new List<HtmlElement>();\r
+            if (mChildren == null || mChildren.Count == 0)\r
+                return rList;\r
+\r
+            foreach (HtmlElement elem in mChildren)\r
+            {\r
+                if (matchSelector(elem, tagName, classList, id, attrName))\r
+                    rList.Add(this);\r
+            }\r
+            return rList;\r
+        }\r
+\r
+        public List<HtmlElement> getElements(List<HtmlElement>rList, \r
+                    string tagName, List<string> classList, string id,\r
+                    string attrName, bool skipParent)\r
+        {\r
+            bool addList = !skipParent;\r
+            if(rList == null)\r
+                rList = new List<HtmlElement>();\r
+\r
+            if (!skipParent)\r
+            {\r
+                if (matchSelector(this, tagName, classList, id, attrName))\r
+                    rList.Add(this);\r
+            }\r
+\r
+            if (mChildren == null || mChildren.Count == 0)\r
+                return rList;\r
+\r
+            foreach (HtmlElement child in mChildren)\r
+            {\r
+                rList = child.getElements(rList,\r
+                     tagName, classList, id, attrName, false);\r
+            }\r
+            return rList;\r
+        }\r
+\r
+        private bool matchSelector(HtmlElement element,\r
+            string tagName, List<string> classList, \r
+            string id, string attrName)\r
+        {\r
+            if (tagName != null)\r
+            {\r
+                if (!tagName.Equals(element.getTagName()))\r
+                    return false;\r
+            }\r
+            if (classList != null)\r
+            {\r
+                if (!ContainClasses(classList))\r
+                    return false;\r
+            }\r
+            if (id != null)\r
+            {\r
+                if (!id.Equals(getAttributeValue("id")))\r
+                    return false;\r
+            }\r
+            if (attrName != null)\r
+            {\r
+                if (null == getAttributeValue(attrName))\r
+                    return false;\r
+            }\r
+            return true;\r
+        }\r
+\r
+\r
+        public string[] getStringContent()\r
+        {\r
+            List<string> result = new List<string>();\r
+            int count = mChildren.Count;\r
+            for (int i = 0; i < count; i++)\r
+            {\r
+                StringElement elem = mChildren[i] as StringElement;\r
+                if (elem == null)\r
+                    continue;\r
+                result.Add(elem.getString());\r
+            }\r
+            return result.ToArray();\r
+        }\r
+\r
+        public bool ContainClasses(List<string> classNames)\r
+        {\r
+            if (mClassList == null)\r
+            {\r
+                mClassList = getClasses();\r
+            }\r
+            if (mClassList.Count == 0)\r
+                return false;\r
+            bool contain = true;\r
+            foreach (string s1 in classNames)\r
+            {\r
+                bool found = false;\r
+                foreach (string s2 in mClassList)\r
+                {\r
+                    if (s1.Equals(s2))\r
+                    {\r
+                        found = true;\r
+                        break;\r
+                    }\r
+                }\r
+                if (!found)\r
+                {\r
+                    contain = false;\r
+                    break;\r
+                }\r
+            }\r
+            return contain;\r
+        }\r
+\r
+        public List<string> getClasses()\r
+        {\r
+            List<string> resultList = new List<string>();\r
+            string classes = getAttributeValue("class");\r
+            if (classes == null)\r
+                return resultList;\r
+\r
+            int length = classes.Length;\r
+            int state = 0;\r
+            int textStart = 0;\r
+            for (int i = 0; i < length; i++)\r
+            {\r
+                switch (HtmlParser.getCharToken(classes[i]))\r
+                {\r
+                    case HtmlParser.CHAR_TOKEN.WHITESPACE:\r
+                    case HtmlParser.CHAR_TOKEN.NL:\r
+                        if (state == 1)\r
+                        {\r
+                            string clsName = classes.Substring(textStart, i - textStart);\r
+                            resultList.Add(clsName);\r
+                            state = 0;\r
+                        }\r
+                        break;\r
+                    default:\r
+                        if (state == 0)\r
+                        {\r
+                            state = 1;\r
+                            textStart = i;\r
+                        }\r
+                        break;\r
+                }\r
+            }\r
+            if (state == 1)\r
+            {\r
+                string clsName = classes.Substring(textStart,\r
+                    length - textStart);\r
+                resultList.Add(clsName);\r
+            }\r
+            return resultList;\r
+        }\r
+\r
+\r
+    }\r
+}\r
diff --git a/NT2chCtrl45/html/HtmlElement_2chparser.cs b/NT2chCtrl45/html/HtmlElement_2chparser.cs
new file mode 100755 (executable)
index 0000000..b07ea63
--- /dev/null
@@ -0,0 +1,597 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using NT2chObject;\r
+\r
+namespace NT2chCtrl.html\r
+{\r
+    public partial class HtmlElement\r
+    {\r
+        private bool parse2chRes(string source, IAmbiguousSearch search)\r
+        {\r
+            //int idx1 = 0;\r
+            int idx2 = 0;\r
+            int idx3, idx4;\r
+            int length = source.Length;\r
+            int textStart = 0;\r
+            //StringElement sElem = null;\r
+            HtmlElement hElem = null;\r
+\r
+            //StringBuilder sb = new StringBuilder(source.Length);\r
+\r
+            for (int idx1 = 0; idx1 < length; idx1++)\r
+            {\r
+                idx2 = source.IndexOf('<', idx1);\r
+                if (idx2 < 0)\r
+                    break;\r
+                if (idx2 < length - 1)\r
+                {\r
+\r
+                    switch (source[idx2 + 1])\r
+                    {\r
+                        case 'a':\r
+                        case 'A':\r
+                            idx3 = source.IndexOf(" href=", idx2 + 2, StringComparison.OrdinalIgnoreCase);\r
+                            if (idx3 == idx2 + 2)\r
+                            {\r
+                                idx4 = source.IndexOf(">", idx3 + 6, StringComparison.OrdinalIgnoreCase);\r
+                                if (idx4 > 0)\r
+                                {\r
+                                    //sElem = new StringElement(this, source.Substring(textStart, idx2 - textStart));\r
+                                    parse2chRes2(this, source, textStart, idx2, search);\r
+                                    textStart = idx4 + 1;\r
+                                    idx1 = textStart - 1;\r
+                                }\r
+                            }\r
+                            break;\r
+                        case 'b':\r
+                        case 'B':\r
+                            idx3 = source.IndexOf("r", idx2 + 2, StringComparison.OrdinalIgnoreCase);\r
+                            if (idx3 == idx2 + 2)\r
+                            {\r
+                                idx4 = source.IndexOf(">", idx3 + 1, StringComparison.OrdinalIgnoreCase);\r
+                                if (idx4 > 0)\r
+                                {\r
+                                    //sElem = new StringElement(this, source.Substring(textStart, idx2 - textStart));\r
+                                    parse2chRes2(this, source, textStart, idx2, search);\r
+                                    hElem = new HtmlElement(this, "br");\r
+                                    hElem.setClosed(true);\r
+                                    textStart = idx4 + 1;\r
+                                    idx1 = textStart - 1;\r
+                                }\r
+                            }\r
+                            break;\r
+                        case '/':\r
+                            idx3 = source.IndexOf("a>", idx2 + 2, StringComparison.OrdinalIgnoreCase);\r
+                            if (idx3 == idx2 + 2)\r
+                            {\r
+                                    //sElem = new StringElement(this, source.Substring(textStart, idx2 - textStart));\r
+                                    parse2chRes2(this, source, textStart, idx2, search);\r
+                                    textStart = idx3 + 2;\r
+                                    idx1 = textStart - 1;\r
+                             }\r
+                            break;\r
+                        default:\r
+                            break;\r
+                    }\r
+                }\r
+                else\r
+                {\r
+                    break;\r
+                }\r
+\r
+            } //while (textStart < length);\r
+\r
+            if (textStart < length)\r
+            {\r
+                //sElem = new StringElement(this, source.Substring(textStart, length - textStart));\r
+                parse2chRes2(this, source, textStart, length, search);\r
+            }\r
+            return true;\r
+        }\r
+\r
+        private static int findNonDisplayAscii(string source, int start, int end)\r
+        {\r
+            int length = source.Length;\r
+            length = Math.Min(length, end);\r
+            for (int i = start; i < length; i++)\r
+            {\r
+                char c = source[i];\r
+                if(c <= ' ' || c >= 0x7f){\r
+                    return i;\r
+                }\r
+            }\r
+            return length;\r
+        }\r
+\r
+        private bool parseEmphasisText(HtmlElement pElem, string source, int start, int end, IAmbiguousSearch search)\r
+        {\r
+            HtmlElement hElem;\r
+            HtmlAttribute hAttr;\r
+            StringElement sElem;\r
+\r
+            int textLength = end - start;\r
+\r
+            string text = source.Substring(start, textLength);\r
+\r
+            if (search == null)\r
+            {\r
+                sElem = new StringElement(pElem, text);\r
+                return true;\r
+            }\r
+            int idx = 0;\r
+            int findIdx, endIdx;\r
+            do{\r
+                if (!search.match(text, idx, out findIdx, out endIdx))\r
+                    break;\r
+                if (idx < findIdx)\r
+                {\r
+                    sElem = new StringElement(pElem,\r
+                                    text.Substring(idx, findIdx - idx));\r
+                }\r
+                hElem = new HtmlElement(pElem, "span");\r
+                hAttr = new HtmlAttribute("emphasis");\r
+                hElem.addAttribute(hAttr);\r
+                sElem = new StringElement(hElem,\r
+                                text.Substring(findIdx, endIdx - findIdx));\r
+                hElem.setClosed(true);\r
+                idx = endIdx;\r
+            }while(idx < textLength);\r
+\r
+            if (idx < textLength)\r
+            {\r
+                sElem = new StringElement(pElem,\r
+                                text.Substring(idx, textLength - idx));\r
+            }\r
+            return true;\r
+        }\r
+\r
+        private bool parse2chRes2(HtmlElement pElem, string source, int start, int end, IAmbiguousSearch search)\r
+        {\r
+            bool bRet = false;\r
+            int textStart = start;\r
+            int textEnd = 0;\r
+            int state = 0;\r
+            int idx1, idx2;\r
+            StringElement sElem;\r
+            HtmlElement hElem;\r
+            HtmlAttribute hAttr;\r
+            string sLink;\r
+            string prefix;\r
+\r
+            for (int i = start; i < end; i++)\r
+            {\r
+                switch (source[i])\r
+                {\r
+                    case '>':\r
+                    case '>':\r
+                        if (state == 0)\r
+                        {\r
+                            textEnd = i;\r
+                            state = 1;\r
+                        }\r
+                        else if (state == 1)\r
+                        {\r
+                            textEnd = i - 1;\r
+                        }\r
+                        break;\r
+                    case '0':\r
+                    case '1':\r
+                    case '2':\r
+                    case '3':\r
+                    case '4':\r
+                    case '5':\r
+                    case '6':\r
+                    case '7':\r
+                    case '8':\r
+                    case '9':\r
+                        if (state == 1 || state == 2 || state == 3)\r
+                            state = 2;\r
+                        break;\r
+                    case '-':\r
+                    case ',':\r
+                        if (state == 2)\r
+                            state = 3;\r
+                        else\r
+                            state = 0;\r
+                        break;\r
+                    case 'h':\r
+                    case 'H':\r
+                    case 't':\r
+                    case 'T':\r
+                        if (state == 2 || state == 3)\r
+                        {\r
+\r
+                            //sElem = new StringElement(this,\r
+                            //    source.Substring(textStart, textEnd - textStart));\r
+                            parseEmphasisText(this, source, textStart, textEnd, search);\r
+                            hElem = new HtmlElement(this, "span");\r
+                            hAttr = new HtmlAttribute("res-link");\r
+                            hElem.addAttribute(hAttr);\r
+                            hElem.setClosed(true);\r
+                            if (state == 3)\r
+                                textStart = i - 2;\r
+                            else if (state == 2)\r
+                                textStart = i - 1;\r
+                            sElem = new StringElement(hElem, source.Substring(textEnd, textStart - textEnd));\r
+                        }\r
+                        idx1 = source.IndexOf("ttp://", i, StringComparison.OrdinalIgnoreCase);\r
+                        if (idx1 == i || idx1 == (i + 1))\r
+                        {\r
+                            if (idx1 == i)\r
+                                prefix = "h";\r
+                            else\r
+                                prefix = string.Empty;\r
+                            idx2 = findNonDisplayAscii(source, idx1 + 6, end);\r
+                            sLink = source.Substring(i, idx2 - i);\r
+                            if (chkGraphicLink(sLink))\r
+                            {\r
+                                hElem = new HtmlElement(this, "img");\r
+                                hAttr = new HtmlAttribute("src", sLink);\r
+                                hElem.addAttribute(hAttr);\r
+                                hElem.setClosed(true);\r
+                            }\r
+                            hElem = new HtmlElement(this, "a");\r
+                            hAttr = new HtmlAttribute("href", prefix+sLink);\r
+                            hElem.addAttribute(hAttr);\r
+                            hElem.setClosed(true);\r
+                            sElem = new StringElement(hElem, sLink);\r
+                            textStart = idx2;\r
+                            i = idx2 - 1;\r
+                        }\r
+                        else\r
+                        {\r
+                            idx1 = source.IndexOf("ttps://", i, StringComparison.OrdinalIgnoreCase);\r
+                            if (idx1 == i || idx1 == (i + 1))\r
+                            {\r
+                                if (idx1 == i)\r
+                                    prefix = "h";\r
+                                else\r
+                                    prefix = string.Empty;\r
+                                idx2 = findNonDisplayAscii(source, idx1 + 7, end);\r
+                                sLink = source.Substring(i, idx2 - i);\r
+                                if (chkGraphicLink(sLink))\r
+                                {\r
+                                    hElem = new HtmlElement(this, "img");\r
+                                    hAttr = new HtmlAttribute("src", sLink);\r
+                                    hElem.addAttribute(hAttr);\r
+                                    hElem.setClosed(true);\r
+                                }\r
+                                hElem = new HtmlElement(this, "a");\r
+                                hAttr = new HtmlAttribute("href", prefix+sLink);\r
+                                hElem.addAttribute(hAttr);\r
+                                hElem.setClosed(true);\r
+                                sElem = new StringElement(hElem, sLink);\r
+                                textStart = idx2;\r
+                                i = idx2 - 1;\r
+                            }\r
+                            else\r
+                            {\r
+                            }\r
+                        }\r
+                        state = 0;\r
+                        break;\r
+                    case 's':\r
+                        if (state == 2 || state == 3)\r
+                        {\r
+\r
+                            //sElem = new StringElement(this,\r
+                            //    source.Substring(textStart, textEnd - textStart));\r
+                            parseEmphasisText(this, source, textStart, textEnd, search);\r
+                            hElem = new HtmlElement(this, "span");\r
+                            hAttr = new HtmlAttribute("res-link");\r
+                            hElem.addAttribute(hAttr);\r
+                            hElem.setClosed(true);\r
+                            if (state == 3)\r
+                                textStart = i - 2;\r
+                            else if (state == 2)\r
+                                textStart = i - 1;\r
+                            sElem = new StringElement(hElem, source.Substring(textEnd, textStart - textEnd));\r
+                            state = 0;\r
+                        }\r
+                        idx1 = source.IndexOf("sssp://", i, StringComparison.OrdinalIgnoreCase);\r
+                        if (idx1 == i || idx1 == (i + 1))\r
+                        {\r
+                            idx2 = findNonDisplayAscii(source, idx1 + 7, end);\r
+                            sLink = "http" + source.Substring(i+4, idx2 - i - 4);\r
+                            if (chkGraphicLink(sLink))\r
+                            {\r
+                                hElem = new HtmlElement(this, "img");\r
+                                hAttr = new HtmlAttribute("src", sLink);\r
+                                hElem.addAttribute(hAttr);\r
+                                hAttr = new HtmlAttribute("sssp");\r
+                                hElem.addAttribute(hAttr);\r
+                                hElem.setClosed(true);\r
+                                textStart = idx2;\r
+                                i = idx2 - 1;\r
+                            }\r
+                        }\r
+                        break;\r
+                    default:\r
+                        if (state == 2 || state == 3)\r
+                        {\r
+                            //sElem = new StringElement(this,\r
+                            //    source.Substring(textStart, textEnd - textStart));\r
+                            parseEmphasisText(this, source, textStart, textEnd, search);\r
+                            hElem = new HtmlElement(this, "span");\r
+                            hAttr = new HtmlAttribute("res-link");\r
+                            hElem.addAttribute(hAttr);\r
+                            hElem.setClosed(true);\r
+                            if (state == 3)\r
+                                textStart = i - 2;\r
+                            else if (state == 2)\r
+                                textStart = i - 1;\r
+                            sElem = new StringElement(hElem, source.Substring(textEnd, textStart - textEnd));\r
+                            state = 0;\r
+                        }\r
+                        break;\r
+                }\r
+            }\r
+            if (textStart < end)\r
+            {\r
+                if (state == 2 || state == 3)\r
+                {\r
+                    //sElem = new StringElement(this,\r
+                    //    source.Substring(textStart, textEnd - textStart));\r
+                    parseEmphasisText(this, source, textStart, textEnd, search);\r
+                    hElem = new HtmlElement(this, "span");\r
+                    hAttr = new HtmlAttribute("res-link");\r
+                    hElem.addAttribute(hAttr);\r
+                    hElem.setClosed(true);\r
+                    if (state == 3)\r
+                        textStart = end - 1;\r
+                    else if (state == 2)\r
+                        textStart = end;\r
+                    sElem = new StringElement(hElem, source.Substring(textEnd, textStart - textEnd));\r
+                    if (state == 3)\r
+                    {\r
+                        sElem = new StringElement(this, source.Substring(end -1, 1));\r
+                    }\r
+                }\r
+                else\r
+                {\r
+                    //sElem = new StringElement(this, source.Substring(textStart, end - textStart));\r
+                    parseEmphasisText(this, source, textStart, end, search);\r
+                }\r
+            }\r
+            return bRet;\r
+        }\r
+\r
+        bool chkGraphicLink(string src)\r
+        {\r
+            //if (!chkShowThumbnail())\r
+            //    return false;\r
+\r
+            if (src == null || src.Length < 4)\r
+                return false;\r
+            int idx = src.LastIndexOf('.');\r
+            if (idx < 0)\r
+                return false;\r
+\r
+            string suffix = src.Substring(idx + 1).ToLower();\r
+            switch (suffix)\r
+            {\r
+                case "png":\r
+                case "jpg":\r
+                case "jpeg":\r
+                case "bmp":\r
+                case "gif":\r
+                    return true;\r
+                default:\r
+                    return false;\r
+            }\r
+        }\r
+\r
+        private bool parse2chRes_old(string source)\r
+        {\r
+\r
+            if (source == null || source.Length == 0)\r
+                return false;\r
+\r
+            int textStart = 0;\r
+            int state = 0;\r
+            string tagName, attrName=null, attrVal;\r
+            StringElement sElem;\r
+            HtmlAttribute hAttr;\r
+            HtmlElement hElem = null;\r
+            bool dquote = false;\r
+            bool squote = false;\r
+\r
+\r
+            int length = source.Length;\r
+            for (int i = 0; i < length; i++)\r
+            {\r
+                switch (HtmlParser.getCharToken(source[i]))\r
+                {\r
+                    case  HtmlParser.CHAR_TOKEN.LT:\r
+                        if (state == 0 && textStart < i)\r
+                        {\r
+                            sElem = new StringElement(\r
+                                this, source.Substring(textStart, i - textStart));\r
+                        }\r
+                        state = 1;\r
+                        textStart = length;\r
+                        break;\r
+                    case HtmlParser.CHAR_TOKEN.SLASH:\r
+                        if (state == 0)\r
+                            break;\r
+                        else if (state == 6 && (dquote || squote))\r
+                        {\r
+                            break;\r
+                        }\r
+                        else if (state == 1)\r
+                        {\r
+                            state = 8;\r
+                        }\r
+                        else\r
+                        {                            \r
+                            state = 7;\r
+                        }\r
+                        break;\r
+                    case HtmlParser.CHAR_TOKEN.GT:\r
+                        if (state == 0){\r
+                            break;\r
+                        }if (state == 1 || state == 8){\r
+                            return false;\r
+                        }\r
+                        else if (state == 2)\r
+                        {\r
+                            tagName = source.Substring(textStart, i - textStart);\r
+                            hElem = new HtmlElement(this, tagName);\r
+                        }\r
+                        else if (state == 7)\r
+                        {\r
+                            hElem.setClosed(true);\r
+                        }\r
+                        else if (state == 9)\r
+                        {\r
+                            tagName = source.Substring(textStart, i - textStart);\r
+                            int count = mChildren.Count;\r
+                            for (int j = count - 1; j >= 0; j--)\r
+                            {\r
+                                HtmlElement child = mChildren[j];\r
+                                if (child.Closed())\r
+                                    continue;\r
+\r
+                                if (tagName.Equals(child.getTagName()))\r
+                                {\r
+                                    child.setClosed(true);\r
+                                    if (j < (count-1))\r
+                                    {\r
+                                        child.mChildren.AddRange(\r
+                                            mChildren.GetRange(j+1, count - 1 - j));\r
+                                        mChildren.RemoveRange(j+1, count - 1 - j);\r
+                                    }\r
+                                    break;\r
+                                }\r
+                            }\r
+                        }\r
+                        hElem = null;\r
+                        state = 0;\r
+                        textStart = i + 1;\r
+                        break;\r
+                    case  HtmlParser.CHAR_TOKEN.WHITESPACE:\r
+                    case  HtmlParser.CHAR_TOKEN.NL:\r
+                        if (state == 1)\r
+                            return false;\r
+                        else if (state == 2)\r
+                        {\r
+                            tagName = source.Substring(textStart, i - textStart);\r
+                            hElem = new HtmlElement(this, tagName);\r
+                            state = 3;\r
+                        }\r
+                        else if (state == 4)\r
+                        {\r
+                            attrName = source.Substring(textStart, i - textStart);\r
+                            state = 5;\r
+                        }\r
+                        else if (state == 5)\r
+                        {\r
+                            hAttr = new HtmlAttribute(attrName);\r
+                            hElem.addAttribute(hAttr);\r
+                            state = 3;\r
+                            dquote = squote = false;\r
+                        }\r
+                        else if (state == 6)\r
+                        {\r
+                            attrVal = source.Substring(textStart, i - textStart);\r
+                            hAttr = new HtmlAttribute(attrName, attrVal);\r
+                            hElem.addAttribute(hAttr);\r
+                            state = 3;\r
+                            dquote = squote = false;\r
+                        }\r
+                        break;\r
+                    case HtmlParser.CHAR_TOKEN.EQUAL:\r
+                        if (state != 0 && state != 4 && state != 5)\r
+                            return false;\r
+                        if (state == 0)\r
+                            break;\r
+                        if (state == 4)\r
+                        {\r
+                            attrName = source.Substring(textStart, i - textStart);\r
+                        }\r
+                        textStart = i + 1;\r
+                        state = 6;\r
+                        break;\r
+                    case HtmlParser.CHAR_TOKEN.DQUOTE:\r
+                        if (state == 0)\r
+                            break;\r
+                        if(state != 6)\r
+                            return false;\r
+                        if (squote)\r
+                            break;\r
+                        if (dquote)\r
+                        {\r
+                            attrVal = source.Substring(textStart, i - textStart);\r
+                            hAttr = new HtmlAttribute(attrName, attrVal);\r
+                            hElem.addAttribute(hAttr);\r
+                            state = 3;\r
+                            dquote = false;\r
+                        }\r
+                        else\r
+                        {\r
+                            dquote = true;\r
+                            textStart = i + 1;\r
+                        }\r
+                        break;\r
+                    case HtmlParser.CHAR_TOKEN.SQUOTE:\r
+                        if (state == 0)\r
+                            break;\r
+                        if(state != 6)\r
+                            return false;\r
+                        if (dquote)\r
+                            break;\r
+                        if (squote)\r
+                        {\r
+                            attrVal = source.Substring(textStart, i - textStart);\r
+                            hAttr = new HtmlAttribute(attrName, attrVal);\r
+                            hElem.addAttribute(hAttr);\r
+                            state = 3;\r
+                            squote = false;\r
+                        }\r
+                        else\r
+                        {\r
+                            squote = true;\r
+                            textStart = i + 1;\r
+                        }\r
+                        break;\r
+                    case HtmlParser.CHAR_TOKEN.ALPHA:\r
+                        if(state == 0)\r
+                            break;\r
+                        else if (state == 1)\r
+                        {\r
+                            state = 2;\r
+                            textStart = i;\r
+                        }\r
+                        else if (state == 3)\r
+                        {\r
+                            textStart = i;\r
+                            state = 4;\r
+                        }\r
+                        else if (state == 8)\r
+                        {\r
+                            textStart = i;\r
+                            state = 9;\r
+                        }\r
+                        else if(state == 7)\r
+                        {\r
+                            return false;\r
+                        }\r
+                        break;\r
+                    default:\r
+                        if(state == 7)\r
+                        {\r
+                            return false;\r
+                        }\r
+                        break;\r
+                }\r
+            }\r
+            if (state == 0 && textStart < length)\r
+            {\r
+                sElem = new StringElement(\r
+                    this, source.Substring(textStart, length - textStart));\r
+            }\r
+            return false;\r
+        }\r
+    }\r
+}\r
diff --git a/NT2chCtrl45/html/HtmlElement_css.cs b/NT2chCtrl45/html/HtmlElement_css.cs
new file mode 100755 (executable)
index 0000000..e975943
--- /dev/null
@@ -0,0 +1,827 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Windows;\r
+using System.Windows.Controls;\r
+using System.Windows.Media;\r
+using System.Windows.Media.Imaging;\r
+\r
+namespace NT2chCtrl.html\r
+{\r
+    public partial class HtmlElement\r
+    {\r
+        bool mInitSelector = false;\r
+\r
+        private void initSelector()\r
+        {\r
+            if (!mInitSelector)\r
+            {\r
+                mMatchedSelector.Sort(CompareSelector);\r
+                mInitSelector = true;\r
+            }\r
+        }\r
+\r
+        static int CompareSelector(css.Selector lhs, css.Selector rhs)\r
+        {\r
+            return lhs.getSpecificity() - rhs.getSpecificity();\r
+        }\r
+\r
+        public bool tryGetBackgroundColor(out Color color)\r
+        {\r
+            initSelector();\r
+\r
+\r
+            bool bRet = false;\r
+            color = Colors.Transparent;\r
+            int count = mMatchedSelector.Count;\r
+            for (int i = count - 1; i >= 0; i--)\r
+            {\r
+                css.Selector stor = mMatchedSelector[i];\r
+                css.Property p = stor.getProperty("background-color");\r
+                if (null == p)\r
+                    continue;\r
+                color = p.getColor();\r
+                bRet = true;\r
+                break;\r
+            }\r
+            return bRet;\r
+        }\r
+\r
+\r
+        public bool tryGetImage(out Image img, string path)\r
+        {\r
+            initSelector();\r
+\r
+            css.Property widthProperty = null;\r
+            css.Property heightProperty = null;\r
+\r
+            img = null;\r
+\r
+            bool bRet = false;\r
+            BitmapImage bImg = null;\r
+            int nWidth = -1;\r
+            int  nHeight = -1;\r
+            int count;\r
+\r
+            string sWidth = this.getAttributeValue("width");\r
+            string sHeight = this.getAttributeValue("height");\r
+            if (sWidth != null)\r
+            {\r
+                int.TryParse(sWidth, out nWidth);\r
+            }\r
+            if (sHeight != null)\r
+            {\r
+                int.TryParse(sHeight, out nHeight);\r
+            }\r
+\r
+            if (nWidth == -1 || nHeight == -1)\r
+            {\r
+                count = mMatchedSelector.Count;\r
+                for (int i = count - 1; i >= 0; i--)\r
+                {\r
+                    css.Selector stor = mMatchedSelector[i];\r
+                    if (widthProperty == null && nWidth == -1)\r
+                    {\r
+                        widthProperty = stor.getProperty("width");\r
+                    }\r
+                    if (heightProperty == null && nHeight == -1)\r
+                    {\r
+                        heightProperty = stor.getProperty("height");\r
+                    }\r
+                    if (null != widthProperty && null != heightProperty)\r
+                        break;\r
+                }\r
+                if (nWidth == -1 && widthProperty != null)\r
+                {\r
+                    double d = widthProperty.getLength();\r
+                    if (d != double.NaN)\r
+                        nWidth = (int)d;\r
+                }\r
+                if (nHeight == -1 && heightProperty != null)\r
+                {\r
+                    double d = heightProperty.getLength();\r
+                    if (d != double.NaN)\r
+                        nHeight = (int)d;\r
+                }\r
+            }\r
+\r
+            bImg = wpf.ImageCash.getBitmapImage(path);\r
+            if (bImg != null)\r
+            {\r
+                img = new Image();\r
+                img.Stretch = System.Windows.Media.Stretch.Uniform;\r
+                if(nWidth > -1)\r
+                    img.Width = nWidth;\r
+                if(nHeight > -1)\r
+                    img.Height = nHeight;\r
+                img.Source = bImg;\r
+                bRet = true;\r
+            }\r
+            return bRet;\r
+        }\r
+\r
+        public bool tryGetBackgroundImage(out Brush brush)// BitmapImage bImage)\r
+        {\r
+            initSelector();\r
+\r
+            css.Property imgProperty = null;\r
+            css.Property szProperty = null;\r
+\r
+            brush = null;\r
+\r
+            //bool bRet = false;\r
+            BitmapImage bImg = null;\r
+            int count = mMatchedSelector.Count;\r
+            for (int i = count - 1; i >= 0; i--)\r
+            {\r
+                css.Selector stor = mMatchedSelector[i];\r
+                if (imgProperty == null)\r
+                {\r
+                    imgProperty = stor.getProperty("background-image");\r
+                }\r
+                if (szProperty == null)\r
+                {\r
+                    szProperty = stor.getProperty("background-size");\r
+                }\r
+                if (null != szProperty && null != imgProperty)\r
+                    break;\r
+            }\r
+            if (imgProperty != null)\r
+            {\r
+                string url = imgProperty.getUrlPath();\r
+                if (url != null)\r
+                {\r
+                    bImg = wpf.ImageCash.getBitmapImage(url);\r
+                    if (bImg != null)\r
+                    {\r
+                        brush = setImageBrushSize(bImg, szProperty);\r
+                        return true;\r
+                    }\r
+                    else\r
+                    {\r
+                        return false;\r
+                    }\r
+                }\r
+                else\r
+                {\r
+                    string gradient = imgProperty.getLinearGradientValue();\r
+                    if (gradient != null)\r
+                    {\r
+                        brush = getLinearGradientBrush(gradient);\r
+                        return (brush != null);\r
+                    }\r
+                    gradient = imgProperty.getRadialGradientValue();\r
+                    if (gradient != null)\r
+                    {\r
+                        brush = getRadialGradientBrush(gradient);\r
+                        return (brush != null);\r
+                    }                    \r
+                }\r
+            }\r
+            return false;\r
+        }\r
+\r
+        private static Brush getLinearGradientBrush(string source)\r
+        {\r
+            //Color colStart = Colors.Transparent;\r
+            //Color colEnd = Colors.Transparent;\r
+            double angle = 90;\r
+            string strColor;\r
+            bool corner2corner = false;\r
+            Point[] points = null;\r
+\r
+            List<Color> cStops = new List<Color>();\r
+            List<double> dStops = new List<double>();\r
+\r
+            int state = 0;\r
+            int textStart = 0;\r
+            int idx;\r
+            int nVal;\r
+            //Color color;\r
+            int bracket = 0;\r
+\r
+            int length = source.Length;\r
+            for (int i = 0; i < length; i++)\r
+            {\r
+                switch (HtmlParser.getCharToken(source[i]))\r
+                {\r
+                    case HtmlParser.CHAR_TOKEN.HYPHIEN:\r
+                        if (state != 0)\r
+                            return null;\r
+                        state = 1;\r
+                        textStart = i;\r
+                        break;\r
+                    case HtmlParser.CHAR_TOKEN.NUMBER:\r
+                        if (state == 0 || state == 1)\r
+                        {\r
+                            if (state == 0)\r
+                                textStart = i;\r
+                            idx = source.IndexOf("deg", textStart);\r
+                            if (idx < 0)\r
+                                return null;\r
+                            if (!int.TryParse(source.Substring(textStart, idx - textStart), out nVal))\r
+                            {\r
+                                return null;\r
+                            }\r
+                            angle = nVal;\r
+                            state = 2;\r
+                            i = idx + 2;\r
+                        }\r
+                        else if (state == 4)\r
+                        {\r
+                            break;\r
+                        }\r
+                        else if (state == 5)\r
+                        {\r
+                            textStart = i;\r
+                            state = 6;\r
+                        }\r
+                        else if (state == 6)\r
+                        {\r
+                            break;\r
+                        }\r
+                        else\r
+                        {\r
+                            return null;\r
+                        }\r
+                        break;\r
+                    case HtmlParser.CHAR_TOKEN.PERCENT:\r
+                        if (state != 6)\r
+                            return null;\r
+                        if (!int.TryParse(source.Substring(textStart, i- textStart), out nVal))\r
+                            return null;\r
+                        dStops.Add(((double)nVal) / 100);\r
+                        state = 7;\r
+                        break;\r
+                    case HtmlParser.CHAR_TOKEN.COMMA:\r
+                        if (state == 0 || state == 1)\r
+                            return null;\r
+                        else if (state == 2)\r
+                        {\r
+                            state = 3;\r
+                        }\r
+                        else if (state == 4)\r
+                        {\r
+                            if (bracket > 0)\r
+                                break;\r
+                            strColor = source.Substring(textStart, i - textStart);\r
+                            cStops.Add(css.cssColor.getColor(strColor));\r
+                            dStops.Add(double.NaN);\r
+                        }\r
+                        else if (state == 5)\r
+                        {\r
+                            dStops.Add(double.NaN);\r
+                        }\r
+                        else if (state == 7)\r
+                        {\r
+                        }\r
+                        else\r
+                        {\r
+                            return null;\r
+                        }\r
+                        state = 3;\r
+                        break;\r
+                    case HtmlParser.CHAR_TOKEN.ALPHA:\r
+                        if (state == 0)\r
+                        {\r
+                            idx = source.IndexOf("to ", i);\r
+                            if (idx == i)\r
+                            {\r
+                                int end;\r
+                                if(!tryGetCornerDirection(source, idx + 3, out points, out end))\r
+                                    return null;\r
+                                corner2corner = true;\r
+                                i = end;\r
+                                state = 3;\r
+                            }\r
+                            else\r
+                            {\r
+                                textStart = i;\r
+                                state = 4;\r
+                            }\r
+                        }\r
+                        else if (state == 3)\r
+                        {\r
+                            textStart = i;\r
+                            state = 4;\r
+                        }\r
+                        break;\r
+                    case HtmlParser.CHAR_TOKEN.SHARP:\r
+                        if (state == 0 || state == 3)\r
+                        {\r
+                            textStart = i;\r
+                            state = 4;\r
+                        }\r
+                        else\r
+                        {\r
+                            return null;\r
+                        }\r
+                        break;\r
+                    case HtmlParser.CHAR_TOKEN.L_BRACKET:\r
+                        if (state != 4)\r
+                            return null;\r
+                        bracket++;\r
+                        break;\r
+                    case HtmlParser.CHAR_TOKEN.R_BRACKET:\r
+                        if (state != 4)\r
+                            return null;\r
+                        bracket--;\r
+                        break;\r
+                    case HtmlParser.CHAR_TOKEN.NL:\r
+                    case HtmlParser.CHAR_TOKEN.WHITESPACE:\r
+                        if (state == 4)\r
+                        {\r
+                            strColor = source.Substring(textStart, i - textStart);\r
+                            cStops.Add(css.cssColor.getColor(strColor));\r
+                            state = 5;\r
+                        }\r
+                        break;\r
+                }\r
+            }\r
+            if (state == 4)\r
+            {\r
+                strColor = source.Substring(textStart, length - textStart);\r
+                cStops.Add(css.cssColor.getColor(strColor));\r
+                dStops.Add(double.NaN);\r
+            }\r
+            else if(state == 5){\r
+                dStops.Add(double.NaN);\r
+            }else if(state ==6){\r
+                return null;\r
+            }\r
+\r
+            int count = cStops.Count;\r
+\r
+            if (count == 0 || dStops.Count != count)\r
+                return null;\r
+            if (count == 1)\r
+            {\r
+                return new SolidColorBrush(cStops[0]);\r
+            }\r
+\r
+            double delta = ((double)1) / (count - 1);\r
+\r
+            GradientStopCollection collection  = new GradientStopCollection(count);\r
+\r
+            for (int i = 0; i < count; i++)\r
+            {\r
+                if (double.IsNaN(dStops[i]))\r
+                    collection.Add(new GradientStop(cStops[i], delta * i));\r
+                else\r
+                    collection.Add(new GradientStop(cStops[i], dStops[i]));\r
+            }\r
+            if (!corner2corner)\r
+                return new LinearGradientBrush(collection, angle);\r
+            else\r
+                return new LinearGradientBrush(collection, points[0], points[1]);\r
+        }\r
+\r
+\r
+        private static Brush getRadialGradientBrush(string source)\r
+        {\r
+\r
+            string sVal;\r
+\r
+            List<Color> cStops = new List<Color>();\r
+            List<double> dStops = new List<double>();\r
+\r
+            int state = 0;\r
+            int textStart = 0;\r
+            int nVal;\r
+            Color color;\r
+            int bracket = 0;\r
+\r
+            //int nShape = -1;//-1 not specify, 1. circle, 2. ellipse\r
+\r
+            int length = source.Length;\r
+            for (int i = 0; i < length; i++)\r
+            {\r
+                HtmlParser.CHAR_TOKEN token =\r
+                    HtmlParser.getCharToken(source[i]);\r
+                switch (token)\r
+                {\r
+                    case HtmlParser.CHAR_TOKEN.ALPHA:\r
+                        if (state == 0)\r
+                        {\r
+                            textStart = i;\r
+                            state = 1;\r
+                        }\r
+                        else if (state == 2)\r
+                        {\r
+                            textStart = i;\r
+                            state = 3;\r
+                        }\r
+                        else if (state == 4 || state == 5)\r
+                        {\r
+                            return null;\r
+                        }\r
+                        else if (state == 7)\r
+                        {\r
+                            break;\r
+                        }\r
+                        break;\r
+                    case HtmlParser.CHAR_TOKEN.SHARP:\r
+                        if (state != 2)\r
+                            return null;\r
+                        textStart = i;\r
+                        state = 7;\r
+                        break;\r
+                    case HtmlParser.CHAR_TOKEN.COMMA:\r
+                    case HtmlParser.CHAR_TOKEN.NL:\r
+                    case HtmlParser.CHAR_TOKEN.WHITESPACE:\r
+                        if (bracket > 0)\r
+                        {\r
+                            if (state != 1 && state != 3)\r
+                                return null;\r
+                            break;\r
+                        }\r
+                        if (state == 4)\r
+                        {\r
+                            if (token == HtmlParser.CHAR_TOKEN.COMMA)\r
+                            {\r
+                                state = 2;\r
+                                dStops.Add(double.NaN);\r
+                                break;\r
+                            }\r
+                        }\r
+                        else if (state == 5)\r
+                        {\r
+                            return null;\r
+                        }\r
+                        else if (state == 6)\r
+                        {\r
+                            if (token == HtmlParser.CHAR_TOKEN.COMMA)\r
+                                state = 2;\r
+                            break;\r
+                        }\r
+                        sVal = source.Substring(textStart, i - textStart);\r
+                        if (state == 1)\r
+                        {\r
+                            if (sVal.Equals("circle"))\r
+                            {\r
+                                //nShape = 1;\r
+                                if (token == HtmlParser.CHAR_TOKEN.COMMA)\r
+                                    state = 2;\r
+                                else\r
+                                    state = 6;\r
+                                break;\r
+                            }\r
+                            else if (sVal.Equals("ellipse"))\r
+                            {\r
+                                //nShape = 2;\r
+                                if (token == HtmlParser.CHAR_TOKEN.COMMA)\r
+                                    state = 2;\r
+                                else\r
+                                    state = 6;\r
+                                break;\r
+                            }\r
+                            else\r
+                            {\r
+                                state = 3;\r
+                            }\r
+                        }\r
+                        if (state == 3 || state == 7)\r
+                        {\r
+                            color = css.cssColor.getColor(sVal);\r
+                            if (color == Colors.Transparent)\r
+                                return null;\r
+                            cStops.Add(color);\r
+                        }\r
+                        if (token == HtmlParser.CHAR_TOKEN.COMMA)\r
+                        {\r
+                            state = 2;\r
+                            dStops.Add(double.NaN);\r
+                        }\r
+                        else\r
+                        {\r
+                            state = 4;\r
+                        }\r
+                        break;\r
+                    case HtmlParser.CHAR_TOKEN.NUMBER:\r
+                        if (state == 4){\r
+                            state = 5;\r
+                            textStart = i;\r
+                        }\r
+                        else if (state == 5)\r
+                        {\r
+                        }\r
+                        else if (state == 1 || state == 3)\r
+                        {\r
+                            if (bracket == 0)\r
+                                return null;\r
+                        }\r
+                        else if (state == 7)\r
+                        {\r
+                            break;\r
+                        }\r
+                        else\r
+                        {\r
+                            return null;\r
+                        }\r
+                        break;\r
+                    case HtmlParser.CHAR_TOKEN.PERCENT:\r
+                        if (state != 5)\r
+                            return null;\r
+                        sVal = source.Substring(textStart, i - textStart);\r
+                        if (!int.TryParse(sVal, out nVal))\r
+                        {\r
+                            return null;\r
+                        }\r
+                        dStops.Add(((double)nVal) / 100);\r
+                        state = 6;\r
+                        break;\r
+                    case HtmlParser.CHAR_TOKEN.L_BRACKET:\r
+                        if (state != 1 && state != 3)\r
+                            return null;\r
+                        bracket++;\r
+                        break;\r
+                    case HtmlParser.CHAR_TOKEN.R_BRACKET:\r
+                        if (state != 1 && state != 3)\r
+                            return null;\r
+                        bracket--;\r
+                        break;\r
+                }\r
+            }\r
+            if (state == 1 || state == 3)\r
+            {\r
+                sVal = source.Substring(textStart, length - textStart);\r
+                color = css.cssColor.getColor(sVal);\r
+                if (color == Colors.Transparent)\r
+                    return null;\r
+                cStops.Add(color);\r
+                dStops.Add(double.NaN);\r
+            }\r
+            else if (state == 4)\r
+            {\r
+                dStops.Add(double.NaN);\r
+            }\r
+            else if (state == 5)\r
+            {\r
+                return null;\r
+            }\r
+\r
+            int count = cStops.Count;\r
+\r
+            if (count == 0 || dStops.Count != count)\r
+                return null;\r
+            if (count == 1)\r
+            {\r
+                return new SolidColorBrush(cStops[0]);\r
+            }\r
+\r
+            double delta = ((double)1) / (count - 1);\r
+\r
+            GradientStopCollection collection = new GradientStopCollection(count);\r
+\r
+            for (int i = 0; i < count; i++)\r
+            {\r
+                if (double.IsNaN(dStops[i]))\r
+                    collection.Add(new GradientStop(cStops[i], delta * i));\r
+                else\r
+                    collection.Add(new GradientStop(cStops[i], dStops[i]));\r
+            }\r
+            return new RadialGradientBrush(collection);            \r
+        }\r
+\r
+        private static bool tryGetCornerDirection(string source, int startIdx, out Point[] points, out int end)\r
+        {\r
+            end = 0;\r
+            points = new Point[2];\r
+            points[0].X = 0.5;\r
+            points[1].X = 0.5;\r
+            points[0].Y = 0.5;\r
+            points[1].Y = 0.5;\r
+            HtmlParser.CHAR_TOKEN token;\r
+\r
+\r
+            int textStart = startIdx;\r
+            int state = 0;\r
+\r
+            int length = source.Length;\r
+            for (int i = startIdx; i < length; i++)\r
+            {\r
+                token = HtmlParser.getCharToken(source[i]);\r
+                switch (token)\r
+                {\r
+                    case HtmlParser.CHAR_TOKEN.ALPHA:\r
+                        if (state == 0)\r
+                        {\r
+                            textStart = i;\r
+                            state = 1;\r
+                        }\r
+                        break;\r
+                    case HtmlParser.CHAR_TOKEN.COMMA:\r
+                    case HtmlParser.CHAR_TOKEN.NL:\r
+                    case HtmlParser.CHAR_TOKEN.WHITESPACE:\r
+                        if (state == 1)\r
+                        {\r
+                            switch (source.Substring(textStart, i-textStart))\r
+                            {\r
+                                case "top":\r
+                                    points[0].Y = 1;\r
+                                    points[1].Y = 0;\r
+                                    break;\r
+                                case "bottom":\r
+                                    points[0].Y = 0;\r
+                                    points[1].Y = 1;\r
+                                    break;\r
+                                case "left":\r
+                                    points[0].X = 1;\r
+                                    points[1].X = 0;\r
+                                    break;\r
+                                case "right":\r
+                                    points[0].X = 0;\r
+                                    points[1].X = 1;\r
+                                    break;\r
+                            }\r
+                        }\r
+                        if (token == HtmlParser.CHAR_TOKEN.COMMA)\r
+                        {\r
+                            end = i;\r
+                            return true;\r
+                        }\r
+                        state = 0;\r
+                        break;    \r
+                }\r
+            }\r
+            return false;\r
+        }\r
+\r
+        private ImageBrush setImageBrushSize(BitmapImage bImg, css.Property property)\r
+        {\r
+            string param = null;\r
+            ImageBrush iBrush = new ImageBrush(bImg);\r
+            if (property != null)\r
+                param = property.getValue();\r
+            switch (param)\r
+            {\r
+                case "auto":\r
+                case null:\r
+                    iBrush.Stretch = Stretch.Fill;\r
+                    iBrush.ViewportUnits = BrushMappingMode.Absolute;\r
+                    Rect rc = new Rect();\r
+                    rc.X = rc.Y = 0;\r
+                    rc.Width = bImg.Width;\r
+                    rc.Height = bImg.Height;\r
+                    iBrush.TileMode = TileMode.Tile;\r
+                    iBrush.Viewport = rc;\r
+                    break;\r
+                case "contain":\r
+                    iBrush.Stretch = Stretch.Uniform;\r
+                    break;\r
+                case "cover":\r
+                    iBrush.Stretch = Stretch.UniformToFill;\r
+                    break;\r
+                default:\r
+                    iBrush.Stretch = Stretch.Fill;\r
+                    break;\r
+            }\r
+            return iBrush;\r
+\r
+        }\r
+        public bool tryGetColor(out Color color)\r
+        {\r
+            initSelector();\r
+\r
+\r
+            bool bRet = false;\r
+            color = Colors.Transparent;\r
+            int count = mMatchedSelector.Count;\r
+            for (int i = count - 1; i >= 0; i--)\r
+            {\r
+                css.Selector stor = mMatchedSelector[i];\r
+                css.Property p = stor.getProperty("color");\r
+                if (null == p)\r
+                    continue;\r
+                color = p.getColor();\r
+                bRet = true;\r
+                break;\r
+            }\r
+            return bRet;\r
+        }\r
+\r
+        public bool tryGetFontWeight(out int weight)\r
+        {\r
+            initSelector();\r
+\r
+            weight = 400;\r
+            bool bRet = false;\r
+            int count = mMatchedSelector.Count;\r
+            for (int i = count - 1; i >= 0; i--)\r
+            {\r
+                css.Selector stor = mMatchedSelector[i];\r
+                css.Property p = stor.getProperty("font-weight");\r
+                if (null == p)\r
+                    continue;\r
+                if (p.getFontWeight(out weight))\r
+                    bRet = true;\r
+                break;\r
+            }\r
+            return bRet;\r
+        }\r
+        public bool tryGetFontFamily(out string fontNames)\r
+        {\r
+            initSelector();\r
+\r
+            fontNames = null;\r
+            bool bRet = false;\r
+            int count = mMatchedSelector.Count;\r
+            for (int i = count - 1; i >= 0; i--)\r
+            {\r
+                css.Selector stor = mMatchedSelector[i];\r
+                css.Property p = stor.getProperty("font-family");\r
+                if (null == p)\r
+                    continue;\r
+                if (p.getFontFamily(out fontNames))\r
+                    bRet = true;\r
+                break;\r
+            }\r
+            return bRet;\r
+        }\r
+\r
+        public bool tryGetFontStyle(out css.Property.FontStyle style)\r
+        {\r
+            initSelector();\r
+\r
+            style = css.Property.FontStyle.Normal;\r
+            bool bRet = false;\r
+            int count = mMatchedSelector.Count;\r
+            for (int i = count - 1; i >= 0; i--)\r
+            {\r
+                css.Selector stor = mMatchedSelector[i];\r
+                css.Property p = stor.getProperty("font-style");\r
+                if (null == p)\r
+                    continue;\r
+                if (p.getFontStyle(out style))\r
+                    bRet = true;\r
+                break;\r
+            }\r
+            return bRet;\r
+        }\r
+\r
+        public bool tryGetLength(string propertyName, out double outLength, double? fontSize)\r
+        {\r
+            initSelector();\r
+\r
+            bool bRet = false;\r
+            outLength = double.NaN;\r
+            int count = mMatchedSelector.Count;\r
+            for (int i = count - 1; i >= 0; i--)\r
+            {\r
+                css.Selector stor = mMatchedSelector[i];\r
+                css.Property p = stor.getProperty(propertyName);\r
+                if (null == p)\r
+                    continue;\r
+                outLength = p.getLength(fontSize);\r
+                if (outLength != double.NaN)\r
+                    bRet = true;\r
+                break;\r
+            }\r
+            return bRet;\r
+        }\r
+\r
+\r
+        public bool tryGetPropertyValue(string propertyName, out string pValue)\r
+        {\r
+            initSelector();\r
+\r
+            bool bRet = false;\r
+            pValue = null;\r
+            int count = mMatchedSelector.Count;\r
+            for (int i = count - 1; i >= 0; i--)\r
+            {\r
+                css.Selector stor = mMatchedSelector[i];\r
+                css.Property p = stor.getProperty(propertyName);\r
+                if (null == p)\r
+                    continue;\r
+                pValue = p.getValue();\r
+                bRet = true;\r
+                break;\r
+            }\r
+            return bRet;\r
+        }\r
+\r
+\r
+        public bool tryGetVisibility(out css.Property.Visibility visibility)\r
+        {\r
+            initSelector();\r
+\r
+\r
+            bool bRet = false;\r
+            visibility = css.Property.Visibility.Other;\r
+            int count = mMatchedSelector.Count;\r
+            for (int i = count - 1; i >= 0; i--)\r
+            {\r
+                css.Selector stor = mMatchedSelector[i];\r
+                css.Property p = stor.getProperty("visibility");\r
+                if (null == p)\r
+                    continue;                \r
+                visibility = p.getVisibility();\r
+                bRet = true;\r
+                break;\r
+            }\r
+            return bRet;\r
+        }\r
+\r
+    }\r
+}\r
diff --git a/NT2chCtrl45/html/HtmlEscape.cs b/NT2chCtrl45/html/HtmlEscape.cs
new file mode 100755 (executable)
index 0000000..1ba1ff3
--- /dev/null
@@ -0,0 +1,468 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Globalization;\r
+using System.IO;\r
+using System.Text;\r
+\r
+namespace NT2chCtrl.html\r
+{\r
+    class HtmlEscape\r
+    {\r
+        static bool mInit = false;\r
+        public static void init()\r
+        {\r
+            if (mInit)\r
+                return;\r
+            HTMLEscapeTable.init();\r
+            mInit = true;\r
+        }\r
+\r
+        public static char parseHTMLDecimalHexEscape(String source, int offset, out int retVal)\r
+        {\r
+            StringBuilder wrk = new StringBuilder(16);\r
+            bool fHEX = false;\r
+            retVal = 0;\r
+            char c;\r
+            //int nVal;\r
+            byte[] bVal = new byte[2];\r
+            bool loop = true;\r
+            for (int j = offset; j < source.Length; j++)\r
+            {\r
+                c = source[j];\r
+                if (';' == c)\r
+                {\r
+                    if (wrk.Length > 0 && ((fHEX && wrk.Length <= 4) || !fHEX && wrk.Length <= 5))\r
+                    {\r
+                        //DebugUtil.log("convert hex escape: 0x" + wrk);\r
+                        //c = (char)Integer.parseInt(wrk, 16);\r
+                        retVal = j + 1;\r
+                        try\r
+                        {\r
+                            int nVal = int.Parse(wrk.ToString(), fHEX ? NumberStyles.HexNumber : NumberStyles.Integer);\r
+                            bVal[0] = (byte)(nVal & 0x000000ff);\r
+                            bVal[1] = (byte)((nVal >> 8) & 0x000000ff);\r
+                            MemoryStream ms = new MemoryStream(bVal, false);\r
+                            //Encoding enc = Encoding.GetEncoding(NTAppState.HOST_2CH_ENCODING);\r
+                            StreamReader sr = new StreamReader(ms);\r
+                            c = (char)sr.Read();\r
+                            sr.Close();\r
+                            ms.Close();\r
+                            return c;\r
+                        }\r
+                        catch (Exception e)\r
+                        {\r
+                            return '\0';\r
+                        }\r
+                    }\r
+                    break;\r
+                }\r
+                else if ('x' == c || 'X' == c)\r
+                {\r
+                    if (j != offset)\r
+                    {\r
+                        break;\r
+                    }\r
+                    fHEX = true;\r
+                }\r
+                else\r
+                {\r
+                    switch (HtmlParser.getCharToken(c))\r
+                    {\r
+                        case HtmlParser.CHAR_TOKEN.NUMBER:\r
+                            wrk.Append(c);// = wrk + c;\r
+                            break;\r
+                        case HtmlParser.CHAR_TOKEN.ALPHA:\r
+                            if (!fHEX)\r
+                            {\r
+                                loop = false;\r
+                                break;\r
+                            }\r
+                            wrk.Append(c);// = wrk + c;\r
+                            break;\r
+                        default:\r
+                            loop = false;\r
+                            break;\r
+                    }\r
+                    if (!loop)\r
+                        break;\r
+                }\r
+            }// End of the for\r
+            return '\0';\r
+        }\r
+\r
+\r
+        class HttpEscapeTree\r
+        {\r
+            public char mC;\r
+            public char mCode;\r
+            public List<HttpEscapeTree> mTree = new List<HttpEscapeTree>();\r
+            public HttpEscapeTree(char c) { mC = c; mCode = '\0'; }\r
+        }\r
+\r
+\r
+\r
+        public class HTMLEscapeTable\r
+        {\r
+            static HttpEscapeTree mTopTree = null;\r
+            //private static ArrayList<HTMLEscape> mHtmlEscape = new ArrayList<HTMLEscape>();\r
+            private String mEscape;\r
+            private char mCode;\r
+            //private ArrayList<HTMLEscapeTable> mTree = new ArrayList<HTMLEscapeTable>();\r
+\r
+            HTMLEscapeTable(String escape, char code)\r
+            {\r
+                mEscape = escape;\r
+                mCode = code;\r
+            }\r
+\r
+            //static int counter = 0;\r
+\r
+            public static char getCodeFromEscape(String escape, int index, out int returnLength)\r
+            {\r
+                return findTree(mTopTree, escape, index, out returnLength);\r
+            }\r
+\r
+            static char findTree(HttpEscapeTree parent, String escape, int index, out int returnLength)\r
+            {\r
+\r
+                if (escape.Length == index)\r
+                {\r
+                    returnLength = -1;\r
+                    return '\0';\r
+                }\r
+\r
+                char c = escape[index];\r
+\r
+                for (int i = 0; i < parent.mTree.Count; i++)\r
+                {\r
+                    HttpEscapeTree current = parent.mTree[i];\r
+                    if (current.mC == c)\r
+                    {\r
+                        index++;\r
+                        if (';' == c)\r
+                        {\r
+                            returnLength = index;\r
+                            return current.mCode;\r
+                        }\r
+                        return findTree(current, escape, index, out returnLength);\r
+                    }\r
+                }\r
+                returnLength = -1;\r
+                return '\0';// No match code available\r
+            }\r
+\r
+\r
+            public static void init()\r
+            {\r
+                //Making escape-code tree\r
+                mTopTree = new HttpEscapeTree((char)0x00);\r
+                //DebugUtil.log("HTMLEscape.length: " + htmlEscape.length);\r
+                for (int i = 0; i < htmlEscape.Length; i++)\r
+                {\r
+                    parseTree(mTopTree, htmlEscape[i].mEscape, 0, htmlEscape[i].mCode);\r
+                }\r
+            }\r
+\r
+\r
+            static void parseTree(HttpEscapeTree tree, String source, int index, char code)\r
+            {\r
+                try\r
+                {\r
+                    List<HttpEscapeTree> parentTree = tree.mTree;\r
+                    HttpEscapeTree newTree;\r
+                    char c = source[index];\r
+                    int i;\r
+                    for (i = 0; i < parentTree.Count; i++)\r
+                    {\r
+                        if (parentTree[i].mC == c)\r
+                        {\r
+                            break;\r
+                        }\r
+                    }\r
+                    if (i == parentTree.Count)\r
+                    {\r
+                        newTree = new HttpEscapeTree(c);\r
+                        parentTree.Add(newTree);\r
+                        //    NTDebug.l("HTMLEscape.parseTree(): err occured. #1");\r
+                        //    return;\r
+                        //}\r
+                    }\r
+                    else\r
+                    {\r
+                        newTree = parentTree[i];//.get(i);\r
+                    }\r
+                    index++;\r
+                    if (source.Length == index)\r
+                    {\r
+                        newTree.mCode = code;\r
+                        //DebugUtil.log("EscapeCode setup:" + source + ":" + String.format("0x%04X", (int)code) + ":" + ++counter);\r
+                        //DebugUtil.log("EscapeCode setup:" + source + ":" + String.format("0x%04X", 10));\r
+                    }\r
+                    else\r
+                    {\r
+                        parseTree(newTree, source, index, code);\r
+                    }\r
+                }\r
+                catch (Exception e)\r
+                {\r
+                    //NTDebug.l(e.Message);\r
+                }\r
+            }\r
+\r
+            static HTMLEscapeTable[] htmlEscape = {\r
+                       new HTMLEscapeTable("quot;", (char)0x22),//quotation mark = APL quote\r
+                       new HTMLEscapeTable("amp;", (char)0x26),//ampersand\r
+                       new HTMLEscapeTable("lt;", (char)0x3C),//less-than sign\r
+                       new HTMLEscapeTable("gt;", (char)0x3E),//greater-than sign\r
+                       new HTMLEscapeTable("nbsp;", (char)0xA0),//no-break space = non-breaking space\r
+                       new HTMLEscapeTable("iexcl;", (char)0xA1),//inverted exclamation mark\r
+                       new HTMLEscapeTable("cent;", (char)0xA2),//cent sign\r
+                       new HTMLEscapeTable("pound;", (char)0xA3),//pound sign\r
+                       new HTMLEscapeTable("curren;", (char)0xA4),//currency sign\r
+                       new HTMLEscapeTable("yen;", (char)0xA5),//yen sign = yuan sign\r
+                       new HTMLEscapeTable("brvbar;", (char)0xA6),//broken bar = broken vertical bar\r
+                       new HTMLEscapeTable("sect;", (char)0xA7),//section sign\r
+                       new HTMLEscapeTable("uml;", (char)0xA8),//diaeresis = spacing diaeresis\r
+                       new HTMLEscapeTable("copy;", (char)0xA9),//copyright sign\r
+                       new HTMLEscapeTable("ordf;", (char)0xAA),//feminine ordinal indicator\r
+                       new HTMLEscapeTable("laquo;", (char)0xAB),//left-pointing double angle quotation mark = left pointing guillemet\r
+                       new HTMLEscapeTable("not;", (char)0xAC),//not sign\r
+                       new HTMLEscapeTable("shy;", (char)0xAD),//soft hyphen = discretionary hyphen\r
+                       new HTMLEscapeTable("reg;", (char)0xAE),//registered sign = registered trade mark sign\r
+                       new HTMLEscapeTable("macr;", (char)0xAF),//macron = spacing macron = overline = APL overbar\r
+                       new HTMLEscapeTable("deg;", (char)0xB0),//degree sign\r
+                       new HTMLEscapeTable("plusmn;", (char)0xB1),//plus-minus sign = plus-or-minus sign\r
+                       new HTMLEscapeTable("sup2;", (char)0xB2),//superscript two = superscript digit two = squared\r
+                       new HTMLEscapeTable("sup3;", (char)0xB3),//superscript three = superscript digit three = cubed\r
+                       new HTMLEscapeTable("acute;",(char)0xB4),//acute accent = spacing acute\r
+                       new HTMLEscapeTable("micro;",(char) 0xB5),//micro sign\r
+                       new HTMLEscapeTable("para;", (char)0xB6),//pilcrow sign = paragraph sign\r
+                       new HTMLEscapeTable("middot;", (char)0xB7),//middle dot = Georgian comma = Greek middle dot\r
+                       new HTMLEscapeTable("cedil;", (char)0xB8),//cedilla = spacing cedilla\r
+                       new HTMLEscapeTable("sup1;", (char)0xB9),//superscript one = superscript digit one\r
+                       new HTMLEscapeTable("ordm;", (char)0xBA),//masculine ordinal indicator\r
+                       new HTMLEscapeTable("raquo;", (char)0xBB),//right-pointing double angle quotation mark = right pointing guillemet\r
+                       new HTMLEscapeTable("frac14;", (char)0xBC),//vulgar fraction one quarter = fraction one quarter\r
+                       new HTMLEscapeTable("frac12;", (char)0xBD),//vulgar fraction one half = fraction one half\r
+                       new HTMLEscapeTable("frac34;", (char)0xBE),//vulgar fraction three quarters = fraction three quarters\r
+                       new HTMLEscapeTable("iquest;", (char)0xBF),//inverted question mark = turned question mark\r
+                       new HTMLEscapeTable("Agrave;", (char)0xC0),//latin capital letter A with grave = latin capital letter A grave\r
+                       new HTMLEscapeTable("Aacute;", (char)0xC1),//latin capital letter A with acute\r
+                       new HTMLEscapeTable("Acirc;", (char)0xC2),//latin capital letter A with circumflex\r
+                       new HTMLEscapeTable("Atilde;", (char)0xC3),//latin capital letter A with tilde\r
+                       new HTMLEscapeTable("Auml;", (char)0xC4),//latin capital letter A with diaeresis\r
+                       new HTMLEscapeTable("Aring;", (char)0xC5),//latin capital letter A with ring above = latin capital letter A ring\r
+                       new HTMLEscapeTable("AElig;", (char)0xC6),//latin capital letter AE = latin capital ligature AE\r
+                       new HTMLEscapeTable("Ccedil;", (char)0xC7),//latin capital letter C with cedilla\r
+                       new HTMLEscapeTable("Egrave;", (char)0xC8),//latin capital letter E with grave\r
+                       new HTMLEscapeTable("Eacute;", (char)0xC9),//latin capital letter E with acute\r
+                       new HTMLEscapeTable("Ecirc;", (char)0xCA),//latin capital letter E with circumflex\r
+                       new HTMLEscapeTable("Euml;",(char) 0xCB),//latin capital letter E with diaeresis\r
+                       new HTMLEscapeTable("Igrave;", (char)0xCC),//latin capital letter I with grave\r
+                       new HTMLEscapeTable("Iacute;", (char)0xCD),//latin capital letter I with acute\r
+                       new HTMLEscapeTable("Icirc;", (char)0xCE),//latin capital letter I with circumflex\r
+                       new HTMLEscapeTable("Iuml;",(char) 0xCF),//latin capital letter I with diaeresis\r
+                       new HTMLEscapeTable("ETH;", (char)0xD0),//latin capital letter ETH\r
+                       new HTMLEscapeTable("Ntilde;", (char)0xD1),//latin capital letter N with tilde\r
+                       new HTMLEscapeTable("Ograve;", (char)0xD2),//latin capital letter O with grave\r
+                       new HTMLEscapeTable("Oacute;",(char) 0xD3),//latin capital letter O with acute\r
+                       new HTMLEscapeTable("Ocirc;", (char)0xD4),//latin capital letter O with circumflex\r
+                       new HTMLEscapeTable("Otilde;", (char)0xD5),//latin capital letter O with tilde\r
+                       new HTMLEscapeTable("Ouml;", (char)0xD6),//latin capital letter O with diaeresis\r
+                       new HTMLEscapeTable("times;", (char)0xD7),//multiplication sign\r
+                       new HTMLEscapeTable("Oslash;", (char)0xD8),//latin capital letter O with stroke = latin capital letter O slash\r
+                       new HTMLEscapeTable("Ugrave;", (char)0xD90),//latin capital letter U with grave\r
+                       new HTMLEscapeTable("Uacute;", (char)0xDA),//latin capital letter U with acute\r
+                       new HTMLEscapeTable("Ucirc;", (char)0xDB),//latin capital letter U with circumflex\r
+                       new HTMLEscapeTable("Uuml;", (char)0xDC),//latin capital letter U with diaeresis\r
+                       new HTMLEscapeTable("Yacute", (char)0xDD),//latin capital letter Y with acute\r
+                       new HTMLEscapeTable("THORN;", (char)0xDE),//latin capital letter THORN\r
+                       new HTMLEscapeTable("szlig;", (char)0xDF),//latin small letter sharp s = ess-zed\r
+                       new HTMLEscapeTable("agrave;", (char)0xE0),//latin small letter a with grave = latin small letter a grave\r
+                       new HTMLEscapeTable("aacute;", (char)0xE1),//latin small letter a with acute\r
+                       new HTMLEscapeTable("acirc;", (char)0xE2),//latin small letter a with circumflex\r
+                       new HTMLEscapeTable("atilde;", (char)0xE3),//latin small letter a with tilde\r
+                       new HTMLEscapeTable("auml;", (char)0xE4),//latin small letter a with diaeresis\r
+                       new HTMLEscapeTable("aring;", (char)0xE5),//latin small letter a with ring above = latin small letter a ring\r
+                       new HTMLEscapeTable("aelig;", (char)0xE6),//latin small letter ae = latin small ligature ae\r
+                       new HTMLEscapeTable("ccedil;", (char)0xE7),//latin small letter c with cedilla\r
+                       new HTMLEscapeTable("egrave;", (char)0xE8),//latin small letter e with grave\r
+                       new HTMLEscapeTable("eacute;", (char)0xE9),//latin small letter e with acute\r
+                       new HTMLEscapeTable("ecirc;", (char)0xEA),//latin small letter e with circumflex\r
+                       new HTMLEscapeTable("euml;", (char)0xEB),//latin small letter e with diaeresis\r
+                       new HTMLEscapeTable("igrave;", (char)0xEC),//latin small letter i with grave\r
+                       new HTMLEscapeTable("iacute;", (char)0xED),//latin small letter i with acute\r
+                       new HTMLEscapeTable("icirc;", (char)0xEE),//latin small letter i with circumflex\r
+                       new HTMLEscapeTable("iuml;", (char)0xEF),//latin small letter i with diaeresis\r
+                       new HTMLEscapeTable("eth;", (char)0xF0),//latin small letter eth\r
+                       new HTMLEscapeTable("ntilde;", (char)0xF1),//latin small letter n with tilde\r
+                       new HTMLEscapeTable("ograve;", (char)0xF2),//latin small letter o with grave\r
+                       new HTMLEscapeTable("oacute;", (char)0xF3),//latin small letter o with acute\r
+                       new HTMLEscapeTable("ocirc;",(char) 0xF4),//latin small letter o with circumflex\r
+                       new HTMLEscapeTable("otilde;", (char)0xF5),//latin small letter o with tilde\r
+                       new HTMLEscapeTable("ouml;", (char)0xF6),//latin small letter o with diaeresis\r
+                       new HTMLEscapeTable("divide;", (char)0xF7),//division sign\r
+                       new HTMLEscapeTable("oslash;", (char)0xF8),//latin small letter o with stroke, = latin small letter o slash\r
+                       new HTMLEscapeTable("ugrave;", (char)0xF9),//latin small letter u with grave\r
+                       new HTMLEscapeTable("uacute;", (char)0xFA),//latin small letter u with acute\r
+                       new HTMLEscapeTable("ucirc;", (char)0xFB),//latin small letter u with circumflex\r
+                       new HTMLEscapeTable("uuml;", (char)0xFC),//latin small letter u with diaeresis\r
+                       new HTMLEscapeTable("yacute;", (char)0xFD),//latin small letter y with acute\r
+                       new HTMLEscapeTable("thorn;",(char) 0xFE),//latin small letter thorn with\r
+                       new HTMLEscapeTable("yuml;", (char)0xFF),//latin small letter y with diaeresis\r
+       \r
+       \r
+                       new HTMLEscapeTable("OElig;", (char)0x0152),//latin capital ligature OE\r
+                       new HTMLEscapeTable("oelig;", (char)0x0153),//latin small ligature oe\r
+                       new HTMLEscapeTable("Scaron;", (char)0x0160),//latin capital letter S with caron\r
+                       new HTMLEscapeTable("scaron;", (char)0x0161),//latin small letter s with caron\r
+                       new HTMLEscapeTable("Yuml;", (char)0x0178),//latin capital letter Y with diaeresis\r
+                       new HTMLEscapeTable("fnof;", (char)0x0192),//latin small f with hook = function = florin\r
+                       new HTMLEscapeTable("circ;", (char)0x02C6),//modifier letter circumflex accent\r
+                       new HTMLEscapeTable("tilde;", (char)0x02DC),//small tilde\r
+                       new HTMLEscapeTable("Alpha;", (char)0x391),//greek capital letter alpha\r
+                       new HTMLEscapeTable("Beta;", (char)0x392),//greek capital letter beta\r
+                       new HTMLEscapeTable("Gamma;", (char)0x393),//greek capital letter gamma\r
+                       new HTMLEscapeTable("Delta;", (char)0x394),//greek capital letter delta\r
+                       new HTMLEscapeTable("Epsilon;", (char)0x395),//greek capital letter epsilon\r
+                       new HTMLEscapeTable("Zeta;", (char)0x396),//greek capital letter zeta\r
+                       new HTMLEscapeTable("Eta;", (char)0x397),//greek capital letter eta\r
+                       new HTMLEscapeTable("Theta;", (char)0x398),//greek capital letter theta\r
+                       new HTMLEscapeTable("Iota;", (char)0x399),//greek capital letter iota\r
+                       new HTMLEscapeTable("Kappa;", (char)0x39A),//greek capital letter kappa\r
+                       new HTMLEscapeTable("Lambda;", (char)0x39B),//greek capital letter lambda\r
+                       new HTMLEscapeTable("Mu;", (char)0x39C),//greek capital letter mu\r
+                       new HTMLEscapeTable("Nu;", (char)0x39D),//greek capital letter nu\r
+                       new HTMLEscapeTable("Xi;", (char)0x39E),//greek capital letter xi\r
+                       new HTMLEscapeTable("Omicron;", (char)0x39F),//greek capital letter omicron\r
+                       new HTMLEscapeTable("Pi;", (char)0x3A0),//greek capital letter pi\r
+                       new HTMLEscapeTable("Rho;", (char)0x3A1),//greek capital letter rho\r
+                       new HTMLEscapeTable("Sigma;", (char)0x3A3),//greek capital letter sigma\r
+                       new HTMLEscapeTable("Tau;", (char)0x3A4),//greek capital letter tau\r
+                       new HTMLEscapeTable("Upsilon;", (char)0x3A5),//greek capital letter upsilon\r
+                       new HTMLEscapeTable("Phi;", (char)0x3A6),//greek capital letter phi\r
+                       new HTMLEscapeTable("Chi;", (char)0x3A7),//greek capital letter chi\r
+                       new HTMLEscapeTable("Psi;", (char)0x3A8),//greek capital letter psi\r
+                       new HTMLEscapeTable("Omega;", (char)0x3A9),//greek capital letter omega\r
+                       new HTMLEscapeTable("alpha;", (char)0x3B1),//greek small letter alpha\r
+                       new HTMLEscapeTable("beta;", (char)0x3B2),//greek small letter beta\r
+                       new HTMLEscapeTable("gamma;", (char)0x3B3),//greek small letter gamma\r
+                       new HTMLEscapeTable("delta;", (char)0x3B4),//greek small letter delta\r
+                       new HTMLEscapeTable("epsilon;", (char)0x3B5),//greek small letter epsilon\r
+                       new HTMLEscapeTable("zeta;", (char)0x3B6),//greek small letter zeta\r
+                       new HTMLEscapeTable("eta;", (char)0x3B7),//greek small letter eta\r
+                       new HTMLEscapeTable("theta;", (char)0x3B8),//greek small letter theta\r
+                       new HTMLEscapeTable("iota;", (char)0x3B9),//greek small letter iota\r
+                       new HTMLEscapeTable("kappa;", (char)0x3BA),//greek small letter kappa\r
+                       new HTMLEscapeTable("lambda;", (char)0x3BB),//greek small letter lambda\r
+                       new HTMLEscapeTable("mu;", (char)0x3BC),//greek small letter mu\r
+                       new HTMLEscapeTable("nu;", (char)0x3BD),//greek small letter nu\r
+                       new HTMLEscapeTable("xi;", (char)0x3BE),//greek small letter xi\r
+                       new HTMLEscapeTable("omicron;", (char)0x3BF),//greek small letter omicron\r
+                       new HTMLEscapeTable("pi;", (char)0x3C0),//greek small letter pi\r
+                       new HTMLEscapeTable("rho;", (char)0x3C1),//greek small letter rho\r
+                       new HTMLEscapeTable("sigmaf;", (char)0x3C2),//greek small letter final sigma\r
+                       new HTMLEscapeTable("sigma;", (char)0x3C3),//greek small letter sigma\r
+                       new HTMLEscapeTable("tau;", (char)0x3C4),//greek small letter tau\r
+                       new HTMLEscapeTable("upsilon;", (char)0x3C5),//greek small letter upsilon\r
+                       new HTMLEscapeTable("phi;", (char)0x3C6),//greek small letter phi\r
+                       new HTMLEscapeTable("chi;", (char)0x3C7),//greek small letter chi\r
+                       new HTMLEscapeTable("psi;", (char)0x3C8),//greek small letter psi\r
+                       new HTMLEscapeTable("omega;", (char)0x3C9),//greek small letter omega\r
+                       new HTMLEscapeTable("thetasym;", (char)0x3D1),//greek small letter theta symbol\r
+                       new HTMLEscapeTable("upsih;", (char)0x3D2),//greek upsilon with hook symbol\r
+                       new HTMLEscapeTable("piv;", (char)0x3D3),//greek pi symbol\r
+                       new HTMLEscapeTable("bull;", (char)0x2022),//bullet = black small circle\r
+                       new HTMLEscapeTable("hellip;", (char)0x2026),//horizontal ellipsis = three dot leader\r
+                       new HTMLEscapeTable("prime;", (char)0x2032),//prime = minutes = feet\r
+                       new HTMLEscapeTable("Prime;", (char)0x2033),//double prime = seconds = inches\r
+                       new HTMLEscapeTable("oline;", (char)0x203E),//overline = spacing overscore\r
+                       new HTMLEscapeTable("frasl;", (char)0x2044),//fraction slash\r
+                       new HTMLEscapeTable("weierp;", (char)0x2118),//script capital P = power set = Weierstrass p\r
+                       new HTMLEscapeTable("image;", (char)0x2111),//blackletter capital I = imaginary part\r
+                       new HTMLEscapeTable("real;", (char)0x211C),//blackletter capital R = real part symbol\r
+                       new HTMLEscapeTable("trade;", (char)0x2122),//trade mark sign\r
+                       new HTMLEscapeTable("alefsym;", (char)0x2135),//alef symbol = first transfinite cardinal\r
+                       new HTMLEscapeTable("larr;", (char)0x2190),//leftwards arrow\r
+                       new HTMLEscapeTable("uarr;", (char)0x2191),//upwards arrow\r
+                       new HTMLEscapeTable("rarr;", (char)0x2192),//rightwards arrow\r
+                       new HTMLEscapeTable("darr;", (char)0x2193),//downwards arrow\r
+                       new HTMLEscapeTable("harr;", (char)0x2194),//left right arrow\r
+                       new HTMLEscapeTable("crarr;", (char)0x21B5),//downwards arrow with corner leftwards = carriage return\r
+                       new HTMLEscapeTable("lArr;", (char)0x21D0),//leftwards double arrow\r
+                       new HTMLEscapeTable("uArr;", (char)0x21D1),//upwards double arrow\r
+                       new HTMLEscapeTable("rArr;", (char)0x21D2),//rightwards double arrow\r
+                       new HTMLEscapeTable("dArr;", (char)0x21D3),//downwards double arrow\r
+                       new HTMLEscapeTable("hArr;", (char)0x21D4),//left right double arrow\r
+                       new HTMLEscapeTable("forall;", (char)0x2200),//for all\r
+                       new HTMLEscapeTable("part;", (char)0x2202),//partial differential\r
+                       new HTMLEscapeTable("exist;", (char)0x2203),//there exists\r
+                       new HTMLEscapeTable("empty;", (char)0x2205),//empty set = null set = diameter\r
+                       new HTMLEscapeTable("nabla;", (char)0x2207),//nabla = backward difference\r
+                       new HTMLEscapeTable("isin;", (char)0x2208),//element of\r
+                       new HTMLEscapeTable("notin;", (char)0x2209),//not an element of\r
+                       new HTMLEscapeTable("ni;", (char)0x220B),//contains as member\r
+                       new HTMLEscapeTable("prod;", (char)0x220F),//n-ary product = product sign\r
+                       new HTMLEscapeTable("sum;", (char)0x2211),//n-ary sumation\r
+                       new HTMLEscapeTable("minus;", (char)0x2212),//minus sign\r
+                       new HTMLEscapeTable("lowast;", (char)0x2217),//asterisk operator\r
+                       new HTMLEscapeTable("radic;", (char)0x221A),//square root = radical sign\r
+                       new HTMLEscapeTable("prop;", (char)0x221D),//proportional to\r
+                       new HTMLEscapeTable("infin;", (char)0x221E),//infinity\r
+                       new HTMLEscapeTable("ang;", (char)0x2220),//angle\r
+                       new HTMLEscapeTable("and;", (char)0x2227),//logical and = wedge\r
+                       new HTMLEscapeTable("or;", (char)0x2228),//logical or = vee\r
+                       new HTMLEscapeTable("cap;", (char)0x2229),//intersection = cap\r
+                       new HTMLEscapeTable("cup;", (char)0x222A),//union = cup\r
+                       new HTMLEscapeTable("int;", (char)0x222B),//integral\r
+                       new HTMLEscapeTable("there4;", (char)0x2234),//therefore\r
+                       new HTMLEscapeTable("sim;", (char)0x223C),//tilde operator = varies with = similar to\r
+                       new HTMLEscapeTable("cong;", (char)0x2245),//approximately equal to\r
+                       new HTMLEscapeTable("asymp;", (char)0x2248),//almost equal to = asymptotic to\r
+                       new HTMLEscapeTable("ne;", (char)0x2260),//not equal to\r
+                       new HTMLEscapeTable("equiv;", (char)0x2261),//identical to\r
+                       new HTMLEscapeTable("le;", (char)0x2264),//less-than or equal to\r
+                       new HTMLEscapeTable("ge;", (char)0x2265),//greater-than or equal to\r
+                       new HTMLEscapeTable("sub;", (char)0x2282),//subset of\r
+                       new HTMLEscapeTable("sup;", (char)0x2283),//superset of\r
+                       new HTMLEscapeTable("nsub;", (char)0x2284),//not a subset of\r
+                       new HTMLEscapeTable("sube;", (char)0x2286),//subset of or equal to\r
+                       new HTMLEscapeTable("supe;", (char)0x2287),//superset of or equal to\r
+                       new HTMLEscapeTable("oplus;", (char)0x2295),//circled plus = direct sum\r
+                       new HTMLEscapeTable("otimes;", (char)0x2297),//circled times = vector product\r
+                       new HTMLEscapeTable("perp;", (char)0x22A5),//up tack = orthogonal to = perpendicular\r
+                       new HTMLEscapeTable("sdot;", (char)0x22C5),//dot operator\r
+                       new HTMLEscapeTable("lceil;", (char)0x2308),//left ceiling = apl upstile\r
+                       new HTMLEscapeTable("rceil;", (char)0x2309),//right ceiling\r
+                       new HTMLEscapeTable("lfloor;", (char)0x230A),//left floor = apl downstile\r
+                       new HTMLEscapeTable("rfloor;", (char)0x230B),//right floor\r
+                       new HTMLEscapeTable("lang;", (char)0x2329),//left-pointing angle bracket = bra\r
+                       new HTMLEscapeTable("rang;", (char)0x232A),//right-pointing angle bracket = ket\r
+                       new HTMLEscapeTable("loz;", (char)0x25CA),//lozenge\r
+                       new HTMLEscapeTable("spades;", (char)0x2660),//black spade suit\r
+                       new HTMLEscapeTable("clubs;", (char)0x2663),//black club suit = shamrock\r
+                       new HTMLEscapeTable("hearts;", (char)0x2665),//black heart suit = valentine\r
+                       new HTMLEscapeTable("diams;", (char)0x2666),//black diamond suit\r
+                       new HTMLEscapeTable("ensp;", (char)0x2002),//en space\r
+                       new HTMLEscapeTable("emsp;", (char)0x2003),//em space\r
+                       new HTMLEscapeTable("thinsp;", (char)0x2009),//thin space\r
+                       new HTMLEscapeTable("zwnj;", (char)0x200C),//zero width non-joiner\r
+                       new HTMLEscapeTable("zwj;", (char)0x200D),//zero width joiner\r
+                       new HTMLEscapeTable("lrm;", (char)0x200E),//left-to-right mark\r
+                       new HTMLEscapeTable("rlm;", (char)0x200F),//right-to-left mark\r
+                       new HTMLEscapeTable("ndash;", (char)0x2013),//en dash\r
+                       new HTMLEscapeTable("mdash;", (char)0x2014),//em dash\r
+                       new HTMLEscapeTable("lsquo;", (char)0x2018),//left single quotation mark\r
+                       new HTMLEscapeTable("rsquo;", (char)0x2019),//right single quotation mark\r
+                       new HTMLEscapeTable("sbquo;", (char)0x201A),//single low-9 quotation mark\r
+                       new HTMLEscapeTable("ldquo;", (char)0x201C),//left double quotation mark\r
+                       new HTMLEscapeTable("rdquo;", (char)0x201D),//right double quotation mark\r
+                       new HTMLEscapeTable("bdquo;", (char)0x201E),//double low-9 quotation mark\r
+                       new HTMLEscapeTable("dagger;", (char)0x2020),//dagger\r
+                       new HTMLEscapeTable("Dagger;", (char)0x2021),//double dagger\r
+                       new HTMLEscapeTable("permil;", (char)0x2030),//per mille sign\r
+                       new HTMLEscapeTable("lsaquo;", (char)0x2039),//single left-pointing angle quotation mark\r
+               };\r
+        }// end of class HTMLEscape\r
+    }\r
+}\r
diff --git a/NT2chCtrl45/html/HtmlParser.cs b/NT2chCtrl45/html/HtmlParser.cs
new file mode 100755 (executable)
index 0000000..ba06ff9
--- /dev/null
@@ -0,0 +1,949 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Windows.Media;\r
+using NT2chCtrl.html.css;\r
+\r
+namespace NT2chCtrl.html\r
+{\r
+    partial class HtmlParser\r
+    {\r
+\r
+        const string ERROR_INVALIE_TAG_FORMAT = "タグの書式が不正です";\r
+        const string ERROR_UNMACHED_TAG_PAIR = "開始タグと終了タグが一致しません";\r
+\r
+        //int mCurrentLine;\r
+        //int mErrorIdx;\r
+        //string mErrorMessage;\r
+        DebugContext mDbgCtx = new DebugContext();\r
+        string mHtmlSource;\r
+        bool mHasError;\r
+        public bool hasError() { return mHasError; }\r
+        public int getErrorLine() { return mDbgCtx.mCurrentLine; }\r
+        public int getErrorSrcIndex() { return mDbgCtx.mCurentIndex; }\r
+        public string getErrorMessage() { return mDbgCtx.mErrorMessage; }\r
+\r
+        HtmlElement mRootElement;\r
+        List<Selector> mCSSSelectors;\r
+        js.JsParser mJsParser;\r
+\r
+        public string getHtmlSource() { return mHtmlSource; }\r
+\r
+        public HtmlParser(string basePath)\r
+        {\r
+            HtmlEscape.init();\r
+            wpf.ImageCash.init(basePath);\r
+            mDbgCtx.mCurrentLine = 1;\r
+            mHasError = false;\r
+        }\r
+\r
+        public string getError()\r
+        {\r
+            string line = "(" + mDbgCtx.mCurrentLine + ") " +\r
+                mDbgCtx.mErrorMessage;\r
+            return line;\r
+        }\r
+\r
+        public HtmlElement CloneHtmlElement()\r
+        {\r
+            if (mRootElement == null)\r
+                return null;\r
+\r
+            return mRootElement.Clone(null);\r
+\r
+        }\r
+\r
+        public bool Parse(string htmlSource)\r
+        {            \r
+\r
+            mRootElement = null;\r
+\r
+            mHtmlSource = htmlSource;\r
+            if (htmlSource == null)\r
+                return false;\r
+            \r
+            //DebugContext ctx = new DebugContext();\r
+            mDbgCtx.init();\r
+            //HtmlParser parser = new HtmlParser();\r
+\r
+            HtmlElement rootElement = new HtmlElement(null, string.Empty);\r
+\r
+            if (0 > parseElement(mDbgCtx, rootElement, htmlSource, 0))\r
+            {\r
+                mHasError = true;\r
+                return false;\r
+            }\r
+\r
+            mCSSSelectors = new List<Selector>();\r
+            if (!parseCSS(mDbgCtx, rootElement, mCSSSelectors))\r
+            {\r
+                mHasError = true;\r
+                //mDbgCtx.mCurentIndex = ctx.getCurrentIndex();\r
+                //mDbgCtx.mCurrentLine = ctx.getCurrentLine();\r
+                //mDbgCtx.mErrorMessage = ctx.getErrorMessage();\r
+                return false;\r
+            }\r
+            if (!parseJS(mDbgCtx, rootElement, out mJsParser))\r
+            {\r
+                mHasError = true;\r
+                //mDbgCtx.mCurrentIndex = ctx.getCurrentIndex();\r
+                //mDbgCtx.mCurrentLine = ctx.getCurrentLine();\r
+                //mDbgCtx.mErrorMessage = ctx.getErrorMessage();\r
+                return false;\r
+            }\r
+            mRootElement = rootElement;\r
+            return true;\r
+        }\r
+\r
+        private bool parseJS(DebugContext ctx, HtmlElement parent, out js.JsParser parser)\r
+        {\r
+            parser = new js.JsParser();\r
+\r
+            List<HtmlElement> list = parent.getElements(null, "script", null, null, "type", true);\r
+            foreach (HtmlElement hElem in list)\r
+            {\r
+                string attrVal = hElem.getAttributeValue("type");\r
+                if (attrVal == null)\r
+                    continue;\r
+                if (!attrVal.Equals("text/javascript"))\r
+                    continue;\r
+\r
+                ctx.setCurrentLine(hElem.mDebugLine);\r
+                ctx.mBaseIndex = hElem.mDebugSourceIndex;\r
+                if (!parser.PreCompile(ctx, hElem))\r
+                {\r
+                    return false;\r
+                }\r
+            }\r
+            return true;\r
+        }\r
+\r
+        public bool runJS(DebugContext dCtx, HtmlElement rootElement, out js.JsFunctionContext fCtx)\r
+        {\r
+            return mJsParser.run(dCtx, rootElement, out fCtx);\r
+        }\r
+\r
+        private bool parseCSS(DebugContext ctx, HtmlElement parent, List<Selector> cssList)\r
+        {\r
+            List<HtmlElement> children = parent.getChildren();\r
+            int len = children.Count;\r
+            for (int i = 0; i < len; i++)\r
+            {\r
+                if ("style".Equals(children[i].getTagName()))\r
+                {\r
+                    string attrVal = children[i].getAttributeValue("type");\r
+                    if (attrVal == null)\r
+                        continue;\r
+                    if (!attrVal.Equals("text/css"))\r
+                        continue;\r
+\r
+                    ctx.setCurrentLine(children[i].mDebugLine);\r
+                    ctx.mBaseIndex = children[i].mDebugSourceIndex;\r
+                    string[] contents = children[i].getStringContent();\r
+                    if (contents.Length > 0)\r
+                        if(!Selector.Parse(ctx, contents[0], cssList))\r
+                            return false;\r
+                }\r
+                else\r
+                {\r
+                    if(!parseCSS(ctx, children[i], cssList))\r
+                        return false;\r
+                }\r
+            }\r
+            return true;\r
+\r
+        }\r
+\r
+        public bool applyCSS(HtmlElement rootElement)\r
+        {\r
+            List<HtmlElement> eList = rootElement.getElements(null,\r
+                "body", null, null, null, true);\r
+\r
+            if (eList == null || eList.Count != 1)\r
+                return false;\r
+\r
+\r
+\r
+            List<Select> sList;\r
+            int count = mCSSSelectors.Count;\r
+            for(int i = 0; i < count; i++)\r
+            {\r
+                Selector stor = mCSSSelectors[i];\r
+                //List<Property> properties = stor.getProperties();\r
+                sList = stor.getList();\r
+\r
+                if(!applyCSS(eList[0], sList, 0, stor, false))\r
+                    continue;\r
+            }\r
+            return true;\r
+        }\r
+\r
+        private bool applyCSS(HtmlElement baseElement,\r
+                List<Select> sList, int currListIdx, Selector stor, bool skipParent)\r
+        {\r
+            List<HtmlElement> eList;\r
+\r
+            if (baseElement == null)\r
+                return false;\r
+\r
+            int sCnt = sList.Count;\r
+            if (sCnt == currListIdx)\r
+                return false;\r
+\r
+            Select select = sList[currListIdx];\r
+\r
+\r
+            List<string> cList = null;\r
+            string className = select.getClassName();\r
+            if (className != null && className.Length > 0 && !"*".Equals(className))\r
+            {\r
+                cList = new List<string>();\r
+                cList.Add(className);\r
+            }\r
+\r
+            string tagName = select.getTagName();\r
+            string idName = select.getIdName();\r
+            string attrName = select.getAttrName();\r
+            if (tagName != null && "*".Equals(tagName))\r
+                tagName = null;\r
+            if (idName != null && "*".Equals(idName))\r
+                idName = null;\r
+            if (attrName != null && "*".Equals(attrName))\r
+                attrName = null;\r
+\r
+            if (select.isImmidiateChild())\r
+            {\r
+                eList = baseElement.getChildren(\r
+                    tagName, cList, idName, attrName);\r
+            }\r
+            else\r
+            {\r
+                eList = baseElement.getElements(null,\r
+                    tagName, cList, idName, attrName, skipParent);\r
+            }\r
+            if (eList == null)\r
+                return false;\r
+            if (eList.Count == 0)\r
+                return true;\r
+            \r
+            currListIdx++;\r
+            if (sCnt == currListIdx)\r
+            {\r
+                foreach (HtmlElement elem in eList)\r
+                {\r
+                    elem.addSelector(stor);\r
+                }\r
+            }\r
+            else\r
+            {\r
+                foreach (HtmlElement elem in eList)\r
+                {\r
+                    applyCSS(elem, sList, currListIdx, stor, true);                    \r
+                }\r
+            }\r
+            return true;\r
+        }\r
+\r
+\r
+\r
+        public static int parseElement(DebugContext ctx, HtmlElement parent, string source, int startIdx)\r
+        {\r
+            int n;\r
+            string tagName;\r
+\r
+            int state = 0;//out of tag\r
+            //1. after <\r
+            //2. after !\r
+            //3. processing tagName\r
+\r
+            int tagTextStart = startIdx;\r
+\r
+            int textStart = startIdx;\r
+            int textEnd = 0;\r
+\r
+            int srcLen = source.Length;\r
+            for (int i = startIdx; i < srcLen; i++)\r
+            {\r
+                switch (getCharToken(source[i]))\r
+                {\r
+                    case CHAR_TOKEN.LT:\r
+                        state = 1;\r
+                        textEnd = i;\r
+                        break;\r
+                    case CHAR_TOKEN.EXCLAMATION:\r
+                        if (state == 0)\r
+                        {\r
+                            break;\r
+                        }\r
+                        else if (state == 1)\r
+                        {\r
+                            state = 2;\r
+                            break;\r
+                        }\r
+                        else\r
+                        {\r
+                            ctx.mCurentIndex = i;\r
+                            return -1;\r
+                        }\r
+                    case CHAR_TOKEN.HYPHIEN:\r
+                        if(state == 2)\r
+                        {\r
+                            if (i + 1 < srcLen)\r
+                            {\r
+                                if (source[i + 1] == '-')\r
+                                {\r
+                                    setStringElement(ctx, parent, source, textStart, textEnd);\r
+                                    n = parseComment(ctx, parent, source, i + 2);\r
+                                    if (n < 0)\r
+                                        return n;\r
+                                    i = n;\r
+                                    textStart = i + 1;\r
+                                }\r
+                            }\r
+                        }\r
+                        state = 0;\r
+                        break;\r
+                    case CHAR_TOKEN.NL:\r
+                        if (state == 3)\r
+                        {\r
+                            setStringElement(ctx, parent, source, textStart, textEnd);\r
+                            tagName = source.Substring(tagTextStart, i);\r
+                            n = parseTag(ctx, parent, tagName, source, i + 1);\r
+                            if (n < 0)\r
+                            {\r
+                                 return -1;\r
+                            }\r
+                            i = n;\r
+                            textStart = i + 1;\r
+                        }\r
+                        ctx.mCurrentLine++;\r
+                        state = 0;\r
+                        break;\r
+                    case CHAR_TOKEN.SLASH:\r
+                        if (state == 1)\r
+                        {\r
+                            setStringElement(ctx, parent, source, textStart, textEnd);\r
+                            n = closeTag(ctx, parent, source, i + 1);\r
+                            if (n < 0)\r
+                            {\r
+                                return -1;\r
+                            }\r
+                            i = n;\r
+                            textStart = i + 1;\r
+                        }\r
+                        else if (state == 3)\r
+                        {\r
+                            setStringElement(ctx, parent, source, textStart, textEnd);\r
+                            tagName = source.Substring(tagTextStart, i - tagTextStart);\r
+                            n = parseTag(ctx, parent, tagName, source, i);\r
+                            if (n < 0)\r
+                            {\r
+                                return -1;\r
+                            }\r
+                            i = n;\r
+                            textStart = i + 1;\r
+                        }\r
+                        state = 0;\r
+                        break;\r
+                    case CHAR_TOKEN.WHITESPACE:\r
+                    case CHAR_TOKEN.GT:\r
+                        if (state == 3)\r
+                        {\r
+                            setStringElement(ctx, parent, source, textStart, textEnd);\r
+                            tagName = source.Substring(tagTextStart, i - tagTextStart);\r
+                            n = parseTag(ctx, parent, tagName, source, i);\r
+                            if (n < 0)\r
+                            {\r
+                                return -1;\r
+                            }\r
+                            i = n;\r
+                            textStart = i + 1;\r
+                        }\r
+                        state = 0;\r
+                        break;\r
+                    case CHAR_TOKEN.ALPHA:\r
+                        if (state == 1 || state == 2)\r
+                        {\r
+                            state = 3;\r
+                            tagTextStart = i;\r
+                        }\r
+                        break;\r
+                    case CHAR_TOKEN.NUMBER:\r
+                        if (state != 3)\r
+                        {\r
+                            state = 0;\r
+                        }\r
+                        break;\r
+                }\r
+            }\r
+            if(textStart < srcLen)\r
+                setStringElement(ctx, parent, source, textStart, srcLen);\r
+\r
+            return 0;\r
+        }\r
+\r
+        private static int parseTag(DebugContext ctx, HtmlElement parent, string tagName, string source, int startIdx)\r
+        {\r
+            int length = source.Length;\r
+            string attrName;\r
+            string attrValue;\r
+            int n;\r
+            int state = 0;\r
+            int textStart = startIdx;\r
+            int textEnd = -1;\r
+            \r
+            HtmlElement element = new HtmlElement(parent, tagName);\r
+            element.setDebugInfo(ctx.mCurrentLine, startIdx);\r
+\r
+            for (int i = startIdx; i < length; i++)\r
+            {\r
+                switch (getCharToken(source[i]))\r
+                {\r
+                    case CHAR_TOKEN.NL:\r
+                        ctx.mCurrentLine++;\r
+                        if (state == 0)\r
+                        {\r
+                            state = 1;\r
+                        }\r
+                        else if (state == 2)\r
+                        {\r
+                            state = 3;\r
+                            textEnd = i;\r
+                        }\r
+                        break;\r
+                    case CHAR_TOKEN.WHITESPACE:\r
+                        if (state == 0)\r
+                        {\r
+                            state = 1;\r
+                        }\r
+                        else if (state == 2)\r
+                        {\r
+                            state = 3;\r
+                            textEnd = i;\r
+                        }\r
+                        break;\r
+                    case CHAR_TOKEN.EQUAL:\r
+                        if (state == 2)\r
+                        {\r
+                            attrName = source.Substring(textStart, i - textStart);\r
+                        }\r
+                        else if (state == 3)\r
+                        {\r
+                            attrName = source.Substring(textStart, textEnd - textStart);\r
+                        }\r
+                        else\r
+                        {\r
+                            ctx.mCurentIndex = i;\r
+                            ctx.mErrorMessage = ERROR_INVALIE_TAG_FORMAT;\r
+                            return -1;\r
+                        }\r
+                        n = parseAttrValue(ctx, source, i + 1, out attrValue);\r
+                        if (n < 0)\r
+                        {\r
+                            return n;\r
+                        }\r
+                        element.addAttribute(new HtmlAttribute(attrName, attrValue));\r
+                        i = n;\r
+                        state = 0;\r
+                        break;\r
+                    /*case CHAR_TOKEN.DQUOTE:\r
+                    case CHAR_TOKEN.SQUOTE:\r
+                        if (state == 2)\r
+                        {\r
+                            attrName = source.Substring(textStart, i - textStart);\r
+                        }\r
+                        else if (state == 3)\r
+                        {\r
+                            attrName = source.Substring(textStart, textEnd - textStart);\r
+                        }\r
+                        else\r
+                        {\r
+                            mErrorIdx = i;\r
+                            mErrorMessage = ERROR_INVALIE_TAG_FORMAT;\r
+                            return -1;\r
+                        }\r
+                        n = parseAttrValue(source, i, out attrValue);\r
+                        if (n < 0)\r
+                        {\r
+                            return n;\r
+                        }\r
+                        element.addAttribute(new HtmlAttribute(attrName, attrValue));\r
+                        i = n;\r
+                        state = 0;\r
+                        break;*/\r
+                    case CHAR_TOKEN.GT:\r
+                        bool closeTag = false;\r
+                        if (i > 0)\r
+                        {\r
+                            if ('/' == source[i - 1])\r
+                            {\r
+                                element.setClosed(true);\r
+                                closeTag = true;\r
+                            }\r
+                        }\r
+                        if (state == 2 || state == 3)\r
+                        {\r
+                            if (state == 2)\r
+                                textEnd = (closeTag) ? i - 1 : i;\r
+                            attrName = source.Substring(textStart, textEnd - textStart);\r
+                            element.addAttribute(new HtmlAttribute(attrName));\r
+                        }\r
+                        if(!closeTag)\r
+                        {\r
+                            if(tagName.Equals("style") ||\r
+                                tagName.Equals("script"))\r
+                            {\r
+                                if(!parseScriptElement(ctx, element, tagName, source, i + 1, out n))\r
+                                {\r
+                                    return -1;\r
+                                }\r
+                                i = n;\r
+                            }\r
+                        }\r
+                        return i;\r
+                    case CHAR_TOKEN.ALPHA:\r
+                        if (state == 1)\r
+                        {\r
+                            textStart = i;\r
+                            state = 2;\r
+                        }\r
+                        else if (state == 2)\r
+                        {\r
+                            break;\r
+                        }\r
+                        else if (state == 3)\r
+                        {\r
+                            //single attribute\r
+                            attrName = source.Substring(textStart, textEnd - textStart);\r
+                            element.addAttribute(new HtmlAttribute(attrName));\r
+                            break;\r
+                        }\r
+                        else\r
+                        {\r
+                            ctx.mCurentIndex = i;\r
+                            ctx.mErrorMessage = ERROR_INVALIE_TAG_FORMAT;\r
+                            return -1;\r
+                        }\r
+                        break;\r
+                    case CHAR_TOKEN.NUMBER:\r
+                    case CHAR_TOKEN.HYPHIEN:\r
+                        if (state != 2)\r
+                        {\r
+                            ctx.mCurentIndex = i;\r
+                            ctx.mErrorMessage = ERROR_INVALIE_TAG_FORMAT;\r
+                            return -1;\r
+                        }\r
+                        break;\r
+                }\r
+            }\r
+            return - 1;\r
+            /*\r
+            int idx = source.IndexOf('>', startIdx);\r
+            if (idx < 0)\r
+                return source.Length - 1;\r
+\r
+            HtmlElement element = new HtmlElement(parent, tagName);\r
+\r
+            if (idx > 1)\r
+            {\r
+                if (source[idx - 1] == '/')\r
+                {\r
+                    element.setClosed(true);\r
+                }\r
+            }\r
+            return idx;*/\r
+        }\r
+\r
+        private static bool parseScriptElement(DebugContext ctx, HtmlElement pElem,\r
+            string tagName, string source, int startIdx, out int endIdx)\r
+        {\r
+            int textEnd;\r
+            StringElement sElem;\r
+            endIdx = 0;\r
+            int comment = 0;\r
+            int length = source.Length;\r
+            for (int i = startIdx; i < length; i++)\r
+            {\r
+                char c = source[i];\r
+                switch (c)\r
+                {\r
+                    case '/':\r
+                        if (comment > 0)\r
+                            break;\r
+                        if (i >= (length - 1))\r
+                            break;\r
+                        switch(source[i+1]){\r
+                            case '/':\r
+                                comment = 1;\r
+                                i++;\r
+                                break;\r
+                            case '*':\r
+                                comment = 2;\r
+                                i++;\r
+                                break;\r
+                        }\r
+                        break;\r
+                    case '\'':\r
+                        if (comment > 0)\r
+                            break;\r
+                        while(true)\r
+                        {\r
+                            i = source.IndexOf('\'', i + 1);\r
+                            if (i < 0)\r
+                                return false;\r
+                            if (source[i - 1] == '\\')\r
+                                continue;\r
+                            break;\r
+                        }\r
+                        //i++;\r
+                        break;\r
+                    case '\"':\r
+                        if (comment > 0)\r
+                            break;\r
+                        while(true)\r
+                        {\r
+                            i = source.IndexOf('\"', i + 1);\r
+                            if (i < 0)\r
+                                return false;\r
+                            if (source[i - 1] == '\\')\r
+                                continue;\r
+                            break;\r
+                        }\r
+                        //i++;\r
+                        break;\r
+                    case '\n':\r
+                        ctx.incrementLine();\r
+                        if (comment == 1)\r
+                            comment = 0;\r
+                        break;\r
+                    case '*':\r
+                        if (comment < 2)\r
+                            break;\r
+                        if (i >= (length - 1))\r
+                            break;\r
+                        if (source[i + 1] == '/')\r
+                        {\r
+                            i++;\r
+                            comment = 0;\r
+                        }\r
+                        break;\r
+                    case '<':\r
+                        if (comment > 0)\r
+                            break;\r
+                        if (i >= (length - 1) || source[i + 1] != '/')\r
+                            break;\r
+                        textEnd = i;\r
+                        i += 2;\r
+                        if (i == source.IndexOf(tagName, i))\r
+                        {\r
+                            int tagLength = tagName.Length;\r
+                            if (i + tagLength >= length)\r
+                                return false;\r
+                            if ('>' == source[i + tagLength])\r
+                            {\r
+                                sElem = new StringElement(\r
+                                    pElem, source.Substring(startIdx, textEnd-startIdx));\r
+                                pElem.setClosed(true);\r
+                                endIdx = i + tagLength;\r
+                                return true;\r
+                            }\r
+                        }\r
+                        break;\r
+                }\r
+\r
+            }\r
+            return false;\r
+        }\r
+\r
+        private  static int parseAttrValue(DebugContext ctx, string source, int startIdx, out string attrValue)\r
+        {\r
+            attrValue = string.Empty;\r
+\r
+            int length = source.Length;\r
+            bool dquote = false;\r
+            bool squote = false;\r
+            int state = 0;\r
+            int textStart = startIdx;\r
+            for (int i = startIdx; i < length; i++)\r
+            {\r
+                switch (getCharToken(source[i]))\r
+                {\r
+                    case CHAR_TOKEN.DQUOTE:\r
+                        if (squote)\r
+                        {\r
+                            if (state == 0)\r
+                            {\r
+                                textStart = i;\r
+                                state = 1;\r
+                            }\r
+                            break;\r
+                        }\r
+                        if (state == 0 && !dquote)\r
+                        {\r
+                            dquote = true;\r
+                        }\r
+                        else if (state == 1 && dquote)\r
+                        {\r
+                            attrValue = source.Substring(textStart, i - textStart);\r
+                            return i;\r
+                        }\r
+                        else\r
+                        {\r
+                            ctx.mCurentIndex = i;\r
+                            ctx.mErrorMessage = ERROR_INVALIE_TAG_FORMAT;\r
+                            return -1;\r
+                        }                        \r
+                        break;\r
+                    case CHAR_TOKEN.SQUOTE:\r
+                        if (dquote)\r
+                        {\r
+                            if (state == 0)\r
+                            {\r
+                                textStart = i;\r
+                                state = 1;\r
+                            }\r
+                            break;\r
+                        }\r
+                        if (state == 0 && !squote)\r
+                        {\r
+                            squote = true;\r
+                        }\r
+                        else if (state == 1 && squote)\r
+                        {\r
+                            attrValue = source.Substring(textStart, i - textStart);\r
+                            return i;\r
+                        }\r
+                        else\r
+                        {\r
+                            ctx.mCurentIndex = i;\r
+                            ctx.mErrorMessage = ERROR_INVALIE_TAG_FORMAT;\r
+                            return -1;\r
+                        }                        \r
+                        break;\r
+                    case CHAR_TOKEN.ESCAPE:\r
+                        if (i < length - 1)\r
+                        {\r
+                            i++;\r
+                        }\r
+                        else\r
+                        {\r
+                            ctx.mCurentIndex = i;\r
+                            ctx.mErrorMessage = ERROR_INVALIE_TAG_FORMAT;\r
+                            return - 1;\r
+                        }\r
+                        break;\r
+                    case CHAR_TOKEN.NL:\r
+                        if (state == 1)\r
+                        {\r
+                            ctx.mCurrentLine++;\r
+                            if (dquote || squote)\r
+                                break;\r
+                            attrValue = source.Substring(textStart, i - textStart);\r
+                            return i;\r
+                        }\r
+                        else\r
+                        {\r
+                            ctx.mErrorMessage = ERROR_INVALIE_TAG_FORMAT;\r
+                            ctx.mCurentIndex = i;\r
+                            return -1;\r
+                        }\r
+                    case CHAR_TOKEN.WHITESPACE:\r
+                        if (state == 1)\r
+                        {\r
+                            if (dquote || squote)\r
+                                break;\r
+                            attrValue = source.Substring(textStart, i - textStart);\r
+                            return i;\r
+                        }\r
+                        else\r
+                        {\r
+                            ctx.mErrorMessage = ERROR_INVALIE_TAG_FORMAT;\r
+                            ctx.mCurentIndex = i;\r
+                            return -1;\r
+                        }\r
+                    case CHAR_TOKEN.ALPHA:\r
+                    case CHAR_TOKEN.NUMBER:\r
+                    case CHAR_TOKEN.OTHER:\r
+                    default:\r
+                        if (state == 0)\r
+                        {\r
+                            textStart = i;\r
+                            state = 1;\r
+                        }\r
+                        break;\r
+                }\r
+            }\r
+            return -1;\r
+        }\r
+\r
+        private static  int closeTag(DebugContext ctx, HtmlElement parent, string source, int startIdx)\r
+        {\r
+            int length = source.Length;\r
+            int endIdx = 0;\r
+            string tagName = string.Empty;\r
+            int state = 0;\r
+            int tagTextStart = startIdx;\r
+            \r
+            for (int i = startIdx; i < length; i++)\r
+            {\r
+                switch(getCharToken(source[i]))\r
+                {\r
+                    case CHAR_TOKEN.NL:\r
+                    case CHAR_TOKEN.WHITESPACE:\r
+                        if (state == 0 || state == 2)\r
+                            break;\r
+                        if(state == 1)\r
+                        {\r
+                            tagName = source.Substring(tagTextStart, i - tagTextStart);\r
+                            state = 2;\r
+                        }\r
+                        break;\r
+                    case CHAR_TOKEN.GT:\r
+                        if (state == 1)\r
+                        {\r
+                            tagName = source.Substring(tagTextStart, i - tagTextStart);\r
+                        }\r
+                        else if (state != 2)\r
+                        {\r
+                            ctx.mCurentIndex = i;\r
+                            ctx.mErrorMessage = ERROR_INVALIE_TAG_FORMAT;\r
+                            return -1;\r
+                        }\r
+                        endIdx = i;\r
+                        goto LABEL1;\r
+                    case CHAR_TOKEN.ALPHA:\r
+                        if (state == 0)\r
+                        {\r
+                            tagTextStart = i;\r
+                            state = 1;\r
+                        }\r
+                        else if (state == 1)\r
+                        {\r
+                            break;\r
+                        }\r
+                        else\r
+                        {\r
+                            ctx.mCurentIndex = i;\r
+                            ctx.mErrorMessage = ERROR_INVALIE_TAG_FORMAT;\r
+                            return -1;\r
+                        }\r
+                        break;\r
+                    case CHAR_TOKEN.NUMBER:\r
+                        if (state != 1)\r
+                        {\r
+                            ctx.mCurentIndex = i;\r
+                            ctx.mErrorMessage = ERROR_INVALIE_TAG_FORMAT;\r
+                            return -1;\r
+                        }\r
+                        break;\r
+                }\r
+            }\r
+        LABEL1:\r
+\r
+            if (tagName == null || tagName.Length == 0 || endIdx == 0)\r
+            {\r
+                ctx.mCurentIndex = startIdx;\r
+                ctx.mErrorMessage = ERROR_INVALIE_TAG_FORMAT;\r
+                return -1;\r
+            }\r
+            List<HtmlElement> children = parent.getChildren();\r
+\r
+            length = children.Count;\r
+            int childCnt = 0;\r
+            for (int i = length - 1; i >= 0; i--)\r
+            {\r
+                HtmlElement element = children[i];\r
+                if (!element.Closed())\r
+                {\r
+                    if (tagName.Equals(element.getTagName()))\r
+                    {\r
+                        if (childCnt > 0)\r
+                        {\r
+                            List<HtmlElement> children2 = children.GetRange(i + 1, childCnt);\r
+                            children.RemoveRange(i+1, childCnt);\r
+                            element.setChildren(children2);\r
+                            element.setClosed(true);\r
+                        }\r
+                        return endIdx;\r
+                    }\r
+                }\r
+                childCnt ++;\r
+            }\r
+\r
+            ctx.mCurentIndex = startIdx;\r
+            ctx.mErrorMessage = ERROR_UNMACHED_TAG_PAIR;\r
+            return -1;\r
+        }\r
+\r
+        static void setStringElement(DebugContext ctx, HtmlElement parent, string source, int start, int end)\r
+        {\r
+            int length = end - start;\r
+            if (0 >= length)\r
+                return;\r
+\r
+            string value = source.Substring(start, length);\r
+            StringElement element = \r
+                new StringElement(parent, value);\r
+            element.setDebugInfo(ctx.mCurrentLine, start);\r
+        }\r
+\r
+        private static int parseComment(DebugContext ctx, HtmlElement parent, string source, int startIdx)\r
+        {\r
+            //int n;\r
+\r
+            int state = 0;\r
+\r
+            int start = startIdx;\r
+\r
+            int srcLen = source.Length;\r
+            for (int i = startIdx; i < srcLen; i++)\r
+            {\r
+                switch (getCharToken(source[i]))\r
+                {\r
+                    case CHAR_TOKEN.HYPHIEN:\r
+                        if (state == 0)\r
+                        {\r
+                            state = 1;\r
+                        }\r
+                        else if (state == 1 || state == 2)\r
+                        {\r
+                            state = 2;\r
+                        }\r
+                        else if (state == 3)\r
+                        {\r
+                            state = 0;\r
+                        }\r
+                        break;\r
+                    case CHAR_TOKEN.ESCAPE:\r
+                        if (state == 3)\r
+                            state = 0;\r
+                        else\r
+                            state = 3;\r
+                        break;\r
+                    case CHAR_TOKEN.GT:\r
+                        if (state == 2)\r
+                        {\r
+\r
+                            string comment =\r
+                                source.Substring(startIdx, i - 2 - startIdx); \r
+                            CommentElement element = \r
+                                new CommentElement(parent, comment);\r
+                            element.setDebugInfo(ctx.mCurrentLine, startIdx);\r
+                            return i;\r
+                        }\r
+                        state = 0;\r
+                        break;\r
+                    case CHAR_TOKEN.NL:\r
+                        state = 0;\r
+                        ctx.mCurrentLine++;\r
+                        break;\r
+                    default :\r
+                        state = 0;\r
+                        break;\r
+                }\r
+            }\r
+            return srcLen - 1;\r
+        }\r
+\r
+    }\r
+}\r
diff --git a/NT2chCtrl45/html/HtmlToken.cs b/NT2chCtrl45/html/HtmlToken.cs
new file mode 100755 (executable)
index 0000000..7ae63e6
--- /dev/null
@@ -0,0 +1,157 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+\r
+namespace NT2chCtrl.html\r
+{\r
+    partial class HtmlParser\r
+    {\r
+        public enum CHAR_TOKEN\r
+        {\r
+            LT, GT, NL, NUMBER, ALPHA,\r
+            SQUOTE, DQUOTE, WHITESPACE,\r
+            EXCLAMATION, HYPHIEN,PLUS,SLASH,\r
+            ESCAPE, AMP, COLON, SEMICOLON, EQUAL,\r
+            SHARP, ASTOR, UNDERBAR,\r
+            COMMA, PERIOD,DOLLAR,\r
+            L_CURLY_BRACKET, R_CURLY_BRACKET,\r
+            L_BRACKET, R_BRACKET,PERCENT,\r
+            L_SQUARE_BRACKET, R_SQUARE_BRACKET,\r
+            OTHER, ERROR \r
+        }\r
+\r
+\r
+        public static CHAR_TOKEN getCharToken(char c)\r
+        {\r
+            switch (c)\r
+            {\r
+                case '0':\r
+                case '1':\r
+                case '2':\r
+                case '3':\r
+                case '4':\r
+                case '5':\r
+                case '6':\r
+                case '7':\r
+                case '8':\r
+                case '9':\r
+                    return CHAR_TOKEN.NUMBER;\r
+                case 'a':\r
+                case 'b':\r
+                case 'c':\r
+                case 'd':\r
+                case 'e':\r
+                case 'f':\r
+                case 'g':\r
+                case 'h':\r
+                case 'i':\r
+                case 'j':\r
+                case 'k':\r
+                case 'l':\r
+                case 'm':\r
+                case 'n':\r
+                case 'o':\r
+                case 'p':\r
+                case 'q':\r
+                case 'r':\r
+                case 's':\r
+                case 't':\r
+                case 'u':\r
+                case 'v':\r
+                case 'w':\r
+                case 'x':\r
+                case 'y':\r
+                case 'z':\r
+                case 'A':\r
+                case 'B':\r
+                case 'C':\r
+                case 'D':\r
+                case 'E':\r
+                case 'F':\r
+                case 'G':\r
+                case 'H':\r
+                case 'I':\r
+                case 'J':\r
+                case 'K':\r
+                case 'L':\r
+                case 'M':\r
+                case 'N':\r
+                case 'O':\r
+                case 'P':\r
+                case 'Q':\r
+                case 'R':\r
+                case 'S':\r
+                case 'T':\r
+                case 'U':\r
+                case 'V':\r
+                case 'W':\r
+                case 'X':\r
+                case 'Y':\r
+                case 'Z':\r
+                    return CHAR_TOKEN.ALPHA;\r
+                case '\t':\r
+                case '\r':\r
+                case ' ':\r
+                    return CHAR_TOKEN.WHITESPACE;\r
+                case '\n':\r
+                    return CHAR_TOKEN.NL;\r
+                case '<':\r
+                    return CHAR_TOKEN.LT;\r
+                case '>':\r
+                    return CHAR_TOKEN.GT;\r
+                case '"':\r
+                    return CHAR_TOKEN.DQUOTE;\r
+                case '\'':\r
+                    return CHAR_TOKEN.SQUOTE;\r
+                case '!':\r
+                    return CHAR_TOKEN.EXCLAMATION;\r
+                case '-':\r
+                    return CHAR_TOKEN.HYPHIEN;\r
+                case '+':\r
+                    return CHAR_TOKEN.PLUS;\r
+                case '\\':\r
+                    return CHAR_TOKEN.ESCAPE;\r
+                case '/':\r
+                    return CHAR_TOKEN.SLASH;\r
+                case '&':\r
+                    return CHAR_TOKEN.AMP;\r
+                case ':':\r
+                    return CHAR_TOKEN.COLON;\r
+                case ';':\r
+                    return CHAR_TOKEN.SEMICOLON;\r
+                case '=':\r
+                    return CHAR_TOKEN.EQUAL;\r
+                case '_':\r
+                    return CHAR_TOKEN.UNDERBAR;\r
+                case '*':\r
+                    return CHAR_TOKEN.ASTOR;\r
+                case '#':\r
+                    return CHAR_TOKEN.SHARP;\r
+                case '.':\r
+                    return CHAR_TOKEN.PERIOD;\r
+                case ',':\r
+                    return CHAR_TOKEN.COMMA;\r
+                case '(':\r
+                    return CHAR_TOKEN.L_BRACKET;\r
+                case ')':\r
+                    return CHAR_TOKEN.R_BRACKET;\r
+                case '[':\r
+                    return CHAR_TOKEN.L_SQUARE_BRACKET;\r
+                case ']':\r
+                    return CHAR_TOKEN.R_SQUARE_BRACKET;\r
+                case '{':\r
+                    return CHAR_TOKEN.L_CURLY_BRACKET;\r
+                case '}':\r
+                    return CHAR_TOKEN.R_CURLY_BRACKET;\r
+                case '%':\r
+                    return CHAR_TOKEN.PERCENT;    \r
+                case '$':\r
+                    return CHAR_TOKEN.DOLLAR;\r
+                default:\r
+                    return CHAR_TOKEN.OTHER;\r
+            }           \r
+        }\r
+\r
+\r
+    }\r
+}\r
diff --git a/NT2chCtrl45/html/StringElement.cs b/NT2chCtrl45/html/StringElement.cs
new file mode 100755 (executable)
index 0000000..d4bd1e6
--- /dev/null
@@ -0,0 +1,41 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+\r
+namespace NT2chCtrl.html\r
+{\r
+    class StringElement : HtmlElement\r
+    {\r
+        string mDisplayString;\r
+        //int mDebugSourceIdx;\r
+        public string getString()\r
+        {\r
+            return mDisplayString;\r
+        }\r
+        public StringElement(HtmlElement parent, string dispString)\r
+            : base(parent, string.Empty)\r
+        {\r
+            mDisplayString = dispString;\r
+            mClosed = true;\r
+            //mDebugSourceIdx = -1;\r
+        }\r
+        protected override bool Tag2String(StringBuilder sb)\r
+        {\r
+            sb.Append(mDisplayString);\r
+            return false;\r
+        }\r
+\r
+        /*public StringElement(HtmlElement parent, string dispString, int debugIndex)\r
+            : base(parent, string.Empty)\r
+        {\r
+            mDisplayString = dispString;\r
+            mClosed = true;\r
+            //mDebugSourceIdx = debugIndex;\r
+        }*/\r
+\r
+        public override HtmlElement Clone(HtmlElement parent)\r
+        {\r
+            return new StringElement(parent, mDisplayString);\r
+        }\r
+    }\r
+}\r
diff --git a/NT2chCtrl45/html/css/Property.cs b/NT2chCtrl45/html/css/Property.cs
new file mode 100755 (executable)
index 0000000..3ad2cda
--- /dev/null
@@ -0,0 +1,433 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Windows.Media;\r
+\r
+namespace NT2chCtrl.html.css\r
+{\r
+    public class Property\r
+    {\r
+        public enum Visibility\r
+        {\r
+            Collapse, Visible, Hidden, Other\r
+        }\r
+        public enum FontStyle\r
+        {\r
+            Normal, Italic, Oblique\r
+        }\r
+\r
+        string mName;\r
+        string mValue;\r
+        Color mColor;\r
+        bool mInitColor;\r
+        Visibility mVisibility;\r
+        bool mInitVisibility;\r
+        \r
+        Property(string name, string value)\r
+        {\r
+            mName = name;\r
+            mValue = value;\r
+\r
+            mInitColor = false;\r
+            mInitVisibility = false;\r
+        }\r
+\r
+        public string getName()\r
+        {\r
+            return mName;\r
+        }\r
+        public string getValue()\r
+        {\r
+            return mValue;\r
+        }\r
+\r
+\r
+        public Color getColor()\r
+        {\r
+            if (mInitColor)\r
+                return mColor;\r
+            mInitColor = true;\r
+            mColor = css.cssColor.getColor(mValue);\r
+            return mColor;\r
+        }\r
+\r
+\r
+        private static string retrieveTextFromBrackets(string source, int startIdx)\r
+        {\r
+            //int state = 0;\r
+            int length = source.Length;\r
+            int textStart = 0;\r
+            int indent = 0;\r
+            for (int i = startIdx/* + 15*/; i < length; i++)\r
+            {\r
+                switch (source[i])\r
+                {\r
+                    case '(':\r
+                        //if (state != 0)\r
+                        //    return null;\r
+                        //state = 1;\r
+                        if(indent == 0)\r
+                            textStart = i + 1;\r
+                        indent++;\r
+                        break;\r
+                    case ')':\r
+                        //if (state != 1)\r
+                        //    return null;\r
+                        indent--;\r
+                        if(indent == 0)\r
+                            return source.Substring(textStart, i - textStart);\r
+                        break;\r
+                }\r
+            }\r
+            return null;\r
+        }\r
+        public string getLinearGradientValue()\r
+        {\r
+            int idx = mValue.IndexOf("linear-gradient");\r
+            if (idx < 0)\r
+                return null;\r
+            return retrieveTextFromBrackets(mValue, idx + 15);\r
+        }\r
+\r
+        public string getRadialGradientValue()\r
+        {\r
+            int idx = mValue.IndexOf("radial-gradient");\r
+            if (idx < 0)\r
+                return null;\r
+            return retrieveTextFromBrackets(mValue, idx + 15);\r
+        }\r
+\r
+        public string getUrlPath()\r
+        {\r
+            int idx = mValue.IndexOf("url(", 0);\r
+            if (idx < 0)\r
+            {\r
+                idx = mValue.IndexOf("URL(", 0);\r
+                if (idx < 0)\r
+                    return null;\r
+            }\r
+            int length = mValue.Length;\r
+            int state = 0;\r
+            int textStart = 0;\r
+            int textEnd = 0;\r
+            bool dquote = false;\r
+            bool squote = false;\r
+            string resultStr = null;\r
+            for (int i = idx + 4; i < length; i++)\r
+            {\r
+                char c = mValue[i];\r
+                switch (c)\r
+                {\r
+                    case ' ':\r
+                    case '\n':\r
+                    case '\t':\r
+                    case '\r':\r
+                        break;\r
+                    case '"':\r
+                        if (!dquote)\r
+                        {\r
+                            if (squote)\r
+                            {\r
+                                if (state == 0)\r
+                                {\r
+                                    textStart = i;\r
+                                    state = 1;\r
+                                }\r
+                                textEnd = i + 1;\r
+                            }\r
+                            else\r
+                            {\r
+                                if (state != 0)\r
+                                    return null;\r
+                                dquote = true;\r
+                            }\r
+                        }\r
+                        else\r
+                        {\r
+                            if (state != 1)\r
+                                return null;\r
+                            state = 2;\r
+                            resultStr = mValue.Substring(textStart, textEnd - textStart);\r
+                        }\r
+                        break;\r
+                    case '\'':\r
+                        if (!squote)\r
+                        {\r
+                            if (dquote)\r
+                            {\r
+                                if (state == 0)\r
+                                {\r
+                                    textStart = i;\r
+                                    state = 1;\r
+                                }\r
+                                textEnd = i + 1;\r
+                            }\r
+                            else\r
+                            {\r
+                                if (state != 0)\r
+                                    return null;\r
+                                squote = true;\r
+                            }\r
+                        }\r
+                        else\r
+                        {\r
+                            if (state != 1)\r
+                                return null;\r
+                            state = 3;\r
+                            resultStr = mValue.Substring(textStart, textEnd - textStart);\r
+                        }\r
+                        break;\r
+                    case ')':\r
+                        switch (state)\r
+                        {\r
+                            case 1:\r
+                                return mValue.Substring(textStart, textEnd - textStart);\r
+                            case 2:\r
+                            case 3:\r
+                                return resultStr;\r
+                            default:\r
+                                return null;\r
+                        }\r
+                    default:\r
+                        if (state == 0)\r
+                        {\r
+                            textStart = i;\r
+                            state = 1;\r
+                        }\r
+                        textEnd = i + 1;\r
+                        break;\r
+                }\r
+            }\r
+            return null;\r
+        }\r
+\r
+        public double getLength(double? fontSize)\r
+        {\r
+            return cssLength.getLength(mValue, fontSize);\r
+        }\r
+\r
+        public double getLength()\r
+        {\r
+            return cssLength.getLength(mValue);\r
+        }\r
+\r
+        public bool getFontFamily(out string fontNames)\r
+        {\r
+            return cssFont.tryGetFontFamily(mValue, out fontNames);\r
+        }\r
+        public bool getFontWeight(out int weight)\r
+        {\r
+            return cssFont.tryGetFontWeight(mValue, out weight);\r
+        }\r
+        public bool getFontStyle(out FontStyle style)\r
+        {\r
+            return cssFont.tryGetFontStyle(mValue, out style);\r
+        }\r
+\r
+        \r
+\r
+        public Visibility getVisibility()\r
+        {\r
+            if (mInitVisibility)\r
+                return mVisibility;\r
+\r
+            if (mValue.Equals("collapse", StringComparison.OrdinalIgnoreCase))\r
+                mVisibility = Visibility.Collapse;\r
+            else if (mValue.Equals("hidden", StringComparison.OrdinalIgnoreCase))\r
+                mVisibility = Visibility.Hidden;\r
+            else if (mValue.Equals("visible", StringComparison.OrdinalIgnoreCase))\r
+                mVisibility =  Visibility.Visible;\r
+            else\r
+                mVisibility = Visibility.Other;\r
+\r
+            mInitVisibility = true;\r
+            return mVisibility;\r
+        }\r
+\r
+        private static string concat2pices(string source, int start, int end, int excludeS, int excludeE, bool exclude)\r
+        {\r
+            if (!exclude || excludeS == excludeE)\r
+                return source.Substring(start, end - start);\r
+            if (excludeS < excludeE)\r
+            {\r
+                if (excludeE <= start || excludeS >= end)\r
+                    return source.Substring(start, end - start);\r
+            }\r
+            if (start > excludeS || end < excludeE)\r
+                return string.Empty;\r
+\r
+            string s1 = source.Substring(start, excludeS - start);\r
+            return s1 + source.Substring(excludeE, end - excludeE);\r
+        }\r
+\r
+        public static int Parse(DebugContext ctx, string source, int startIdx, List<Property> list)\r
+        {\r
+            int state = 0;\r
+            int textStart = startIdx;\r
+            int length = source.Length;\r
+            string name = null;\r
+            Property property;\r
+            bool dquote = false;\r
+            bool squote = false;\r
+\r
+            bool comment = false;\r
+            int commentS = 0, commentE = -1;\r
+            string s;\r
+\r
+\r
+            for (int i = startIdx; i < length; i++)\r
+            {\r
+                char c = source[i];\r
+                HtmlParser.CHAR_TOKEN token = \r
+                    HtmlParser.getCharToken(c);\r
+\r
+                switch (token)\r
+                {\r
+                    case HtmlParser.CHAR_TOKEN.L_CURLY_BRACKET:\r
+                        if (startIdx != i)\r
+                        {\r
+                            ctx.setCurrentIdx(i);\r
+                            return -1;\r
+                        }\r
+                        break;\r
+                    case HtmlParser.CHAR_TOKEN.ALPHA:\r
+                        if (state == 0)\r
+                        {\r
+                            state = 1;\r
+                            textStart = i;\r
+                        }\r
+                        else if(state == 3){\r
+                            state = 4;\r
+                            textStart = i;\r
+                        }\r
+                        break;\r
+                    case HtmlParser.CHAR_TOKEN.NUMBER:\r
+                    case HtmlParser.CHAR_TOKEN.HYPHIEN:\r
+                    case HtmlParser.CHAR_TOKEN.UNDERBAR:\r
+                        if (state == 3)\r
+                        {\r
+                            state = 4;\r
+                            textStart = i;\r
+                        }\r
+                        else if (state != 1 && state != 4)\r
+                        {\r
+                            ctx.setCurrentIdx(i);\r
+                            return -1;\r
+                        }\r
+                        break;\r
+                    case HtmlParser.CHAR_TOKEN.DQUOTE:\r
+                        if (state == 3 && !dquote)\r
+                        {\r
+                            state = 4;\r
+                            textStart = i;\r
+                        }\r
+                        else if (state != 4)\r
+                        {\r
+                            ctx.setCurrentIdx(i);\r
+                            return -1;\r
+                        }\r
+                        if(!squote)\r
+                            dquote = !dquote;\r
+                        break;\r
+                    case HtmlParser.CHAR_TOKEN.SQUOTE:\r
+                        if (state == 3 && !squote)\r
+                        {\r
+                            state = 4;\r
+                            textStart = i;\r
+                        }\r
+                        else if (state != 4)\r
+                        {\r
+                            ctx.setCurrentIdx(i);\r
+                            return -1;\r
+                        }\r
+                        if(!dquote)\r
+                            squote = !squote;\r
+                        break;\r
+                    case HtmlParser.CHAR_TOKEN.COLON:\r
+                        if (state == 1)\r
+                        {\r
+                            name = concat2pices(source, textStart, i, commentS, commentE, comment);\r
+                            comment = false;\r
+                            //name = source.Substring(textStart, i - textStart);\r
+                        }\r
+                        else if (state != 2)\r
+                        {\r
+                            ctx.setCurrentIdx(i);\r
+                            return -1;\r
+                        }\r
+                        state = 3;\r
+                        break;\r
+                    case HtmlParser.CHAR_TOKEN.SEMICOLON:\r
+                        if (state == 4 && !dquote && !squote)\r
+                        {\r
+                            s = concat2pices(source, textStart, i, commentS, commentE, comment);\r
+                            comment = false;\r
+                            property = new Property(name, s);//ource.Substring(textStart, i - textStart));\r
+                            list.Add(property);\r
+                        }\r
+                        else\r
+                        {\r
+                            ctx.setCurrentIdx(i);\r
+                            return -1;\r
+                        }\r
+                        state = 0;\r
+                        break;\r
+                    case HtmlParser.CHAR_TOKEN.NL:\r
+                        ctx.incrementLine();\r
+                        if (state == 1)\r
+                        {\r
+                            state = 2;\r
+                            name = concat2pices(source, textStart, i, commentS, commentE, comment);\r
+                            comment = false;\r
+                            //name = source.Substring(textStart, i - textStart);\r
+                        }\r
+                        break;\r
+                    case HtmlParser.CHAR_TOKEN.WHITESPACE:\r
+                        if (state == 1)\r
+                        {\r
+                            state = 2;\r
+                            name = concat2pices(source, textStart, i, commentS, commentE, comment);\r
+                            comment = false;\r
+                            //name = source.Substring(textStart, i - textStart);\r
+                        }\r
+                        break;\r
+                    case HtmlParser.CHAR_TOKEN.SLASH:\r
+                        if (i < length - 1 && source[i+1] == '*')\r
+                        {\r
+                            int idx = source.IndexOf("*/", i + 2);\r
+                            if (idx >= 0)\r
+                            {\r
+                                comment = true;\r
+                                commentS = i;\r
+                                commentE = idx + 2;                                \r
+                                i = idx + 1;\r
+                            }\r
+                        }\r
+                        break;\r
+                    case HtmlParser.CHAR_TOKEN.R_CURLY_BRACKET:\r
+                        if (state == 4 && !dquote && !squote)\r
+                        {\r
+                            s = concat2pices(source, textStart, i, commentS, commentE, comment);\r
+                            comment = false;\r
+                            property = new Property(name, s);//ource.Substring(textStart, i - textStart));\r
+                            list.Add(property);\r
+                        }\r
+                        else if(state != 0)\r
+                        {\r
+                            ctx.setCurrentIdx(i);\r
+                            return -1;\r
+                        }\r
+                        return i;\r
+                    case HtmlParser.CHAR_TOKEN.OTHER:\r
+                        if (state != 4)\r
+                        {\r
+                            ctx.setCurrentIdx(i);\r
+                            return -1;\r
+                        }\r
+                        break;\r
+                }\r
+            }\r
+            return length;\r
+        }\r
+    }\r
+}\r
diff --git a/NT2chCtrl45/html/css/Select.cs b/NT2chCtrl45/html/css/Select.cs
new file mode 100755 (executable)
index 0000000..8ed53d1
--- /dev/null
@@ -0,0 +1,513 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+\r
+namespace NT2chCtrl.html.css\r
+{\r
+    public class Select\r
+    {\r
+        string mTag;\r
+        string mClass;\r
+        string mId;\r
+        string mAttrName;\r
+        string mAttrValue;\r
+        bool mImmidiate;\r
+\r
+        public string getTagName() { return mTag; }\r
+        public string getClassName() { return mClass; }\r
+        public string getIdName() { return mId; }\r
+        public string getAttrName() { return mAttrName; }\r
+        public string getAttrValue() { return mAttrValue; }\r
+        public bool isImmidiateChild() { return mImmidiate; }\r
+\r
+        public static  int Parse(DebugContext ctx, string source, int startIdx,\r
+            List<Selector> resultList)\r
+        {\r
+            //List<List<Select>> resultList = new List<List<Select>>();\r
+            Selector list = new Selector();\r
+            \r
+            int state = 0;\r
+\r
+            string tagName = null;\r
+            string className = null;\r
+            string idName = null;\r
+            string attrName = null;\r
+            string attrVal = null;\r
+            Select sel;\r
+            bool immidiate = false;\r
+\r
+\r
+            int textStart = startIdx;\r
+\r
+\r
+\r
+            int length = source.Length;\r
+            for (int i = startIdx; i < length; i++)\r
+            {\r
+                char c = source[i];\r
+                HtmlParser.CHAR_TOKEN token = \r
+                    HtmlParser.getCharToken(c);\r
+\r
+                switch (token)\r
+                {\r
+                    case HtmlParser.CHAR_TOKEN.ALPHA:\r
+                        if (state == 0)\r
+                        {\r
+                            state = 1;\r
+                            textStart = i;\r
+                        }\r
+                        else if(state == 2){\r
+                            state = 4;\r
+                            textStart = i;\r
+                        }\r
+                        else if (state == 3)\r
+                        {\r
+                            state = 5;\r
+                            textStart = i;\r
+                        }\r
+                        else if (state == 7)\r
+                        {\r
+                            state = 8;\r
+                            textStart = i;\r
+                        }\r
+                        else if (state == 9)\r
+                        {\r
+                            state = 10;\r
+                            textStart = i;\r
+                        }\r
+                        break;\r
+                    case HtmlParser.CHAR_TOKEN.NUMBER:\r
+                    case HtmlParser.CHAR_TOKEN.HYPHIEN:\r
+                    case HtmlParser.CHAR_TOKEN.UNDERBAR:\r
+                        if (state == 0 || state == 2 || state == 3 || state == 7)\r
+                        {\r
+                            ctx.setCurrentIdx(i);\r
+                            return -1;\r
+                        }\r
+                        else if (state == 9)\r
+                        {\r
+                            state = 10;\r
+                            textStart = i;\r
+\r
+                        }\r
+                        break;\r
+                    case HtmlParser.CHAR_TOKEN.ASTOR:\r
+                        if (state != 0)\r
+                        {\r
+                            ctx.setCurrentIdx(i);\r
+                            return -1;\r
+                        }\r
+                        state = 6;\r
+                        break;\r
+                    case HtmlParser.CHAR_TOKEN.PERIOD:\r
+                        if (state == 1)\r
+                        {\r
+                            tagName = source.Substring(textStart, i - textStart);\r
+                        }\r
+                        else if (state == 6 || state == 0)\r
+                        {\r
+                            tagName = null;\r
+                        }\r
+                        else\r
+                        {\r
+                            ctx.setCurrentIdx(i);\r
+                            return -1;\r
+                        }\r
+                        state = 2;\r
+                        break;\r
+                    case HtmlParser.CHAR_TOKEN.L_SQUARE_BRACKET:\r
+                        if (state == 0 || state == 6)\r
+                        {\r
+                            state = 7;\r
+                            tagName = className = idName = null;\r
+                        }\r
+                        else if (state == 1)\r
+                        {\r
+                            tagName = source.Substring(textStart, i - textStart);\r
+                        }\r
+                        else if (state == 4)\r
+                        {\r
+                            className = source.Substring(textStart, i - textStart);\r
+                        }\r
+                        else if (state == 5)\r
+                        {\r
+                            idName = source.Substring(textStart, i - textStart);\r
+                        }\r
+                        else\r
+                        {\r
+                            ctx.setCurrentIdx(i);\r
+                            return -1;\r
+                        }\r
+                        state = 7;\r
+                        break;\r
+                    case HtmlParser.CHAR_TOKEN.R_SQUARE_BRACKET:\r
+                        if (state == 8)\r
+                        {\r
+                            attrName = source.Substring(textStart, i - textStart);\r
+                        }\r
+                        else if (state == 10)\r
+                        {\r
+                            attrVal = source.Substring(textStart, i - textStart);\r
+                        }\r
+                        else\r
+                        {\r
+                            ctx.setCurrentIdx(i);\r
+                            return -1;\r
+                        }\r
+                        state = 11;\r
+                        break;\r
+                    case HtmlParser.CHAR_TOKEN.EQUAL:\r
+                        if (state != 8)\r
+                        {\r
+                            ctx.setCurrentIdx(i);\r
+                            return -1;\r
+                        }\r
+                        attrName = source.Substring(textStart, i - textStart);\r
+                        state = 9;\r
+                        break;\r
+                    case HtmlParser.CHAR_TOKEN.SHARP:\r
+                        if (state == 0 || state == 6)\r
+                        {\r
+                        }\r
+                        else if (state == 1)\r
+                        {\r
+                            tagName = source.Substring(textStart, i - textStart);\r
+                        }\r
+                        else if (state == 4)\r
+                        {\r
+                            className = source.Substring(textStart, i - textStart);\r
+                        }\r
+                        else\r
+                        {\r
+                            ctx.setCurrentIdx(i);\r
+                            return -1;\r
+                        }\r
+                        state = 3;\r
+                        break;\r
+                    case HtmlParser.CHAR_TOKEN.GT:\r
+                        if (state != 0)\r
+                        {\r
+                            ctx.setCurrentIdx(i);\r
+                            return -1;\r
+                        }\r
+                        immidiate = true;\r
+                        break;\r
+                    case HtmlParser.CHAR_TOKEN.COMMA:\r
+                        if (state == 0)\r
+                        {\r
+                            sel = null;\r
+                        }\r
+                        else if (state == 1)\r
+                        {\r
+                            sel = new Select(\r
+                                source.Substring(textStart, i - textStart),\r
+                                        null, null, null, null, immidiate);\r
+                            immidiate = false;\r
+                        }\r
+                        else if (state == 4)\r
+                        {\r
+                            sel = new Select(tagName,\r
+                                source.Substring(textStart, i - textStart),\r
+                                        null, null, null, immidiate);\r
+                            immidiate = false;\r
+                        }\r
+                        else if (state == 5)\r
+                        {\r
+                            sel = new Select(tagName, className,\r
+                                source.Substring(textStart, i - textStart),\r
+                                null, null, \r
+                                immidiate);\r
+                            immidiate = false;\r
+                        }\r
+                        else if (state == 6)\r
+                        {\r
+                            sel = new Select(null, null, null, null, null, immidiate);\r
+                            immidiate = false;\r
+                        }\r
+                        else if (state == 11)\r
+                        {\r
+                            sel = new Select(tagName, className, idName, attrName, attrVal, immidiate);\r
+                            immidiate = false;\r
+                        }\r
+                        else\r
+                        {\r
+                            ctx.setCurrentIdx(i);\r
+                            return -1;\r
+                        }\r
+                        state = 0;\r
+                        if(sel != null)\r
+                            list.addSelect(sel);\r
+                        resultList.Add(list);\r
+                        list = new Selector();\r
+\r
+                        tagName = null;\r
+                        className = null;\r
+                        idName = null;\r
+                        attrName = null;\r
+                        attrVal = null;\r
+                        break;\r
+                    case HtmlParser.CHAR_TOKEN.WHITESPACE:\r
+                        if (state == 0)\r
+                        {\r
+                            break;\r
+                        }\r
+                        else if (state == 1)\r
+                        {\r
+                            sel = new Select(\r
+                                source.Substring(textStart, i - textStart),\r
+                                        null, null, null, null, immidiate);\r
+                            immidiate = false;\r
+                        }\r
+                        else if (state == 4)\r
+                        {\r
+                            sel = new Select(tagName,\r
+                                source.Substring(textStart, i - textStart),\r
+                                        null, null, null, immidiate);\r
+                            immidiate = false;\r
+                        }\r
+                        else if (state == 5)\r
+                        {\r
+                            sel = new Select(tagName, className,\r
+                                source.Substring(textStart, i - textStart),\r
+                                null, null, immidiate);\r
+                            immidiate = false;\r
+                        }\r
+                        else if (state == 6)\r
+                        {\r
+                            sel = new Select(null, null, null, null, null, immidiate);\r
+                            immidiate = false;\r
+                        }\r
+                        else if (state == 11)\r
+                        {\r
+                            sel = new Select(tagName, className, idName, attrName, attrVal, immidiate);\r
+                            immidiate = false;\r
+                        }\r
+                        else\r
+                        {\r
+                            ctx.setCurrentIdx(i);\r
+                            return -1;\r
+                        }\r
+                        state = 0;\r
+                        list.addSelect(sel);\r
+                        tagName = null;\r
+                        className = null;\r
+                        idName = null;\r
+                        attrName = null;\r
+                        attrVal = null;\r
+                        break;\r
+                    case HtmlParser.CHAR_TOKEN.NL:\r
+                        ctx.incrementLine();\r
+                        if(state == 0)\r
+                        {\r
+                            break;\r
+                        }\r
+                        else if (state == 1)\r
+                        {\r
+                            sel = new Select(\r
+                                source.Substring(textStart, i - textStart),\r
+                                        null, null, null, null, immidiate);\r
+                            immidiate = false;\r
+                        }\r
+                        else if (state == 4)\r
+                        {\r
+                            sel = new Select(tagName,\r
+                                source.Substring(textStart, i - textStart),\r
+                                        null, null, null, immidiate);\r
+                            immidiate = false;\r
+                        }\r
+                        else if (state == 5)\r
+                        {\r
+                            sel = new Select(tagName, className,\r
+                                source.Substring(textStart, i - textStart),\r
+                                 null, null, immidiate);\r
+                            immidiate = false;\r
+                        }\r
+                        else if (state == 6)\r
+                        {\r
+                            sel = new Select(null, null, null, null, null, immidiate);\r
+                            immidiate = false;\r
+                        }\r
+                        else if (state == 11)\r
+                        {\r
+                            sel = new Select(tagName, className, idName, attrName, attrVal, immidiate);\r
+                            immidiate = false;\r
+                        }\r
+                        else\r
+                        {\r
+                            ctx.setCurrentIdx(i);\r
+                            return -1;\r
+                        }\r
+                        state = 0;\r
+                        list.addSelect(sel);\r
+                        tagName = null;\r
+                        className = null;\r
+                        idName = null;\r
+                        attrName = null;\r
+                        attrVal = null;\r
+                        break;\r
+                    case HtmlParser.CHAR_TOKEN.L_CURLY_BRACKET:\r
+                        if(state == 0)\r
+                        {\r
+                            sel = null;\r
+                        }\r
+                        else if (state == 1)\r
+                        {\r
+                            sel = new Select(\r
+                                source.Substring(textStart, i - textStart),\r
+                                        null, null, null, null, immidiate);\r
+                            immidiate = false;\r
+                        }\r
+                        else if (state == 4)\r
+                        {\r
+                            sel = new Select(tagName,\r
+                                source.Substring(textStart, i - textStart),\r
+                                        null, null, null, immidiate);\r
+                            immidiate = false;\r
+                        }\r
+                        else if (state == 5)\r
+                        {\r
+                            sel = new Select(tagName, className,\r
+                                source.Substring(textStart, i - textStart),\r
+                                 null, null, immidiate);\r
+                            immidiate = false;\r
+                        }\r
+                        else if (state == 6)\r
+                        {\r
+                            sel = new Select(null, null, null, null, null, immidiate);\r
+                            immidiate = false;\r
+                        }\r
+                        else if (state == 11)\r
+                        {\r
+                            sel = new Select(tagName, className, idName, attrName, attrVal, immidiate);\r
+                            immidiate = false;\r
+                        }\r
+                        else\r
+                        {\r
+                            ctx.setCurrentIdx(i);\r
+                            return -1;\r
+                        }\r
+                        if(sel != null)\r
+                            list.addSelect(sel);\r
+                        resultList.Add(list);\r
+                        return i;\r
+                    case HtmlParser.CHAR_TOKEN.SLASH:\r
+                        if (i < length - 1 && source[i+1] == '*')\r
+                        {\r
+                            int idx = source.IndexOf("*/", i + 2);\r
+                            if (idx >= 0)\r
+                            {\r
+                                for (int j = i + 2; j < idx; j++)\r
+                                {\r
+                                    if (source[j] == '\n')\r
+                                    {\r
+                                        ctx.incrementLine();\r
+                                    }\r
+                                }\r
+                                if (state == 0)\r
+                                {\r
+                                    //break;\r
+                                    sel = null;\r
+                                }\r
+                                else if (state == 1)\r
+                                {\r
+                                    sel = new Select(\r
+                                        source.Substring(textStart, i - textStart),\r
+                                                null, null, null, null, immidiate);\r
+                                    immidiate = false;\r
+                                }\r
+                                else if (state == 4)\r
+                                {\r
+                                    sel = new Select(tagName,\r
+                                        source.Substring(textStart, i - textStart),\r
+                                                null, null, null, immidiate);\r
+                                    immidiate = false;\r
+                                }\r
+                                else if (state == 5)\r
+                                {\r
+                                    sel = new Select(tagName, className,\r
+                                        source.Substring(textStart, i - textStart),\r
+                                         null, null, immidiate);\r
+                                    immidiate = false;\r
+                                }\r
+                                else if (state == 6)\r
+                                {\r
+                                    sel = new Select(null, null, null, null, null, immidiate);\r
+                                    immidiate = false;\r
+                                }\r
+                                else if (state == 11)\r
+                                {\r
+                                    sel = new Select(tagName, className, idName, attrName, attrVal, immidiate);\r
+                                    immidiate = false;\r
+                                }\r
+                                else\r
+                                {\r
+                                    ctx.setCurrentIdx(i);\r
+                                    return -1;\r
+                                }\r
+                                if (state != 0)\r
+                                {\r
+                                    state = 0;\r
+                                    list.addSelect(sel);\r
+                                    tagName = null;\r
+                                    className = null;\r
+                                    idName = null;\r
+                                    attrName = null;\r
+                                    attrVal = null;\r
+                                }\r
+                                i = idx + 1;\r
+                            }\r
+                        }\r
+                        break;\r
+                    case HtmlParser.CHAR_TOKEN.OTHER:\r
+                        //if (state != 0)\r
+                        //{\r
+                        ctx.setCurrentIdx(i);\r
+                        return -1;\r
+                        //}\r
+                        //break;\r
+                }\r
+\r
+            }\r
+            return length;\r
+        }\r
+\r
+        public int getSpecificity()\r
+        {\r
+            int specificity = 0;\r
+            if (mId != null && mId.Length > 0 && !mId.Equals("*"))\r
+                specificity += 100;\r
+\r
+            if (mClass != null && mClass.Length > 0 && !mClass.Equals("*"))\r
+                specificity += 10;\r
+\r
+            if (mAttrName != null && mAttrName.Length > 0)\r
+                specificity += 10;\r
+\r
+            if (mTag != null && mTag.Length > 0 && !mTag.Equals("*"))\r
+                specificity += 1;\r
+            return specificity;\r
+        }\r
+\r
+        public Select(string tag, string className, string id, \r
+            string attrName, string attrVal, bool immidiate)\r
+        {\r
+            mTag = (tag != null && tag.Length > 0) ? tag : "*";\r
+            mClass = (className != null && className.Length > 0) ? className : "*";\r
+            mId = (id != null && id.Length > 0) ? id : "*";\r
+            if (attrName != null)\r
+            {\r
+                if (attrVal == null)\r
+                    mAttrValue = attrName;\r
+                else\r
+                    mAttrValue = attrVal;\r
+                mAttrName = attrName;\r
+            }\r
+            else\r
+            {\r
+                mAttrName = null;\r
+            }\r
+            mImmidiate = immidiate;\r
+        }\r
+\r
+    }\r
+}\r
diff --git a/NT2chCtrl45/html/css/Selector.cs b/NT2chCtrl45/html/css/Selector.cs
new file mode 100755 (executable)
index 0000000..f8d9113
--- /dev/null
@@ -0,0 +1,82 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+\r
+namespace NT2chCtrl.html.css\r
+{\r
+    public class Selector\r
+    {\r
+        List<Select> mSelector = new List<Select>();\r
+        List<Property> mProperties ;//= new List<Property>();\r
+\r
+        public List<Select> getList() { return mSelector; }\r
+        public List<Property> getProperties() { return mProperties; }\r
+\r
+        public void addSelect(Select select)\r
+        {\r
+            mSelector.Add(select);\r
+        }\r
+\r
+        public int getSpecificity()\r
+        {\r
+            int specificity= 0;\r
+            foreach (Select s in mSelector)\r
+            {\r
+                specificity += s.getSpecificity();\r
+            }\r
+            return specificity;\r
+        }\r
+\r
+        public Property getProperty(string key)\r
+        {\r
+            foreach (Property p in mProperties)\r
+            {\r
+                if(key.Equals(p.getName()))\r
+                    return p;\r
+            }\r
+            return null;\r
+        }\r
+\r
+\r
+        public static bool Parse(DebugContext ctx, string selector, List<Selector>  cssList)\r
+        {\r
+\r
+            int length = selector.Length;\r
+\r
+            int idx = 0;\r
+\r
+            int endIdx;\r
+            do\r
+            {\r
+                List<Selector> list = new List<Selector>();\r
+                endIdx = Select.Parse(ctx, selector, idx, list);\r
+                if (endIdx < 0)\r
+                {\r
+                    ctx.setErrorMessage("セレクターの書式が不正です");\r
+                    return false;\r
+                }\r
+                if (endIdx == length)\r
+                    break;\r
+                List<Property> pList = new List<Property>();\r
+                idx = Property.Parse(ctx, selector, endIdx, pList);\r
+                //idx = selector.IndexOf('}', endIdx);\r
+                if (idx < 0)\r
+                {\r
+                    ctx.setErrorMessage("CSSプロパティの書式が不正です");\r
+                    return false;\r
+                }\r
+\r
+                foreach (Selector s in list)\r
+                {\r
+                    s.mProperties = pList;\r
+                }\r
+                idx++;\r
+                cssList.AddRange(list);\r
+            } while (idx < length);\r
+\r
+            return true;\r
+        }\r
+\r
+\r
+    }\r
+}\r
diff --git a/NT2chCtrl45/html/css/cssColor.cs b/NT2chCtrl45/html/css/cssColor.cs
new file mode 100755 (executable)
index 0000000..5053b9b
--- /dev/null
@@ -0,0 +1,347 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Windows.Media;\r
+\r
+namespace NT2chCtrl.html.css\r
+{\r
+    public class cssColor\r
+    {\r
+        string mColorName;\r
+        int mColorValue;\r
+\r
+        cssColor(string colorName, int colorValue)\r
+        {\r
+            mColorName = colorName;\r
+            mColorValue = colorValue;\r
+        }\r
+\r
+        public static Color getColor(string colorText)\r
+        {\r
+            colorText = colorText.Trim();\r
+            int idx;\r
+\r
+            idx = colorText.IndexOf("rgb(");\r
+            if (idx == 0)\r
+            {\r
+                int endIdx;\r
+                return getColorFromRgbString(colorText, 4, out endIdx);\r
+            }\r
+            idx = colorText.IndexOf('#');\r
+            if (idx == 0)\r
+            {\r
+                return getColorFromHexString(colorText, 1);\r
+            }\r
+            foreach (cssColor c in mColorList)\r
+            {\r
+                if (colorText.Equals(c.mColorName, StringComparison.OrdinalIgnoreCase))\r
+                    return getColor(c.mColorValue);\r
+            }\r
+            return Colors.Transparent;\r
+        }\r
+\r
+\r
+        private static Color getColorFromRgbString(string rgbString, int startIdx, out int endIdx)\r
+        {\r
+\r
+            int length = rgbString.Length;\r
+            int digits = 0;\r
+            int value = 0;\r
+            int colorIdx = 0;\r
+            int r = 0, g = 0;//, b = 0;\r
+\r
+            endIdx = 0;\r
+\r
+            for (int i = startIdx; i < length; i++)\r
+            {\r
+                char c = rgbString[i];\r
+                if (c >= '0' && c <= '9')\r
+                {\r
+                    if (digits == 0)\r
+                        value = c - '0';\r
+                    else if (digits == 1)\r
+                        value = (c - '0') + (value * 10);\r
+                    else if (digits == 2)\r
+                        value = (c - '0') + (value * 10);\r
+                    else\r
+                        return Colors.Transparent;\r
+                    digits++;\r
+                }\r
+                else if (c == ',')\r
+                {\r
+                    if (digits == 0)\r
+                        return Colors.Transparent;\r
+\r
+                    if (colorIdx == 0)\r
+                        r = value;\r
+                    else if (colorIdx == 1)\r
+                        g = value;\r
+                    //else if (colorIdx == 2)\r
+                    //    b = value;\r
+                    else\r
+                        return Colors.Transparent;\r
+                    colorIdx++;\r
+                    digits = 0;\r
+                }\r
+                else if (c == ' ' || c == '\t' || c == 'r' || c == '\n')\r
+                {\r
+                }\r
+                else if (c == ')')\r
+                {\r
+                    if (colorIdx != 2)\r
+                        return Colors.Transparent;\r
+                    endIdx = i;\r
+                    return Color.FromRgb((byte)r, (byte)g, (byte)value);\r
+                }\r
+                else\r
+                {\r
+                    return Colors.Transparent;\r
+                }\r
+            }\r
+            return Colors.Transparent;\r
+        }\r
+\r
+        private static Color getColorFromHexString(string hexString, int startIdx)\r
+        {\r
+            int[] by = new int[8];\r
+            int length = Math.Min(hexString.Length, 8);\r
+            int idx = 0;\r
+            for (int i = startIdx; i < length; i++)\r
+            {\r
+                char c = hexString[i];\r
+                if (c >= '0' && c <= '9')\r
+                {\r
+                    by[idx] = (c - '0');\r
+                }else if(c >= 'a' && c <= 'f'){\r
+                    by[idx] = (c - 'a' + 10);\r
+                }\r
+                else if (c >= 'A' && c <= 'F')\r
+                {\r
+                    by[idx] = (c - 'A' + 10);\r
+                }\r
+                else\r
+                {\r
+                    idx++;\r
+                    break;\r
+                }\r
+                idx++;\r
+            }\r
+            if (idx < 0 || idx > 6)\r
+                return Colors.Transparent;\r
+\r
+            int r = 0, g = 0, b = 0;\r
+            idx--;\r
+            if (idx < 3)\r
+            {\r
+                for (int i = 0; idx >= 0; i++)\r
+                {\r
+                    switch (i)\r
+                    {\r
+                        case 0:\r
+                            b = by[idx]<<4;\r
+                            break;\r
+                        case 1:\r
+                            g = by[idx]<<4;\r
+                            break;\r
+                        case 2:\r
+                            r = by[idx]<<4;\r
+                            break;\r
+                    }\r
+\r
+                    idx--;\r
+                }\r
+            }\r
+            else\r
+            {\r
+                for (int i = 0; idx >= 0; i++)\r
+                {\r
+                    switch (i)\r
+                    {\r
+                        case 0:\r
+                            b = by[idx];\r
+                            break;\r
+                        case 1:\r
+                            b += (by[idx] << 4);\r
+                            break;\r
+                        case 2:\r
+                            g = by[idx];\r
+                            break;\r
+                        case 3:\r
+                            g += (by[idx] << 4);\r
+                            break;\r
+                        case 4:\r
+                            r = by[idx];\r
+                            break;\r
+                        case 5:\r
+                            r += (by[idx] << 4);\r
+                            break;\r
+                    }\r
+\r
+                    idx--;\r
+                }\r
+            }\r
+\r
+            return Color.FromRgb((byte)r, (byte)g, (byte)b);\r
+\r
+        }\r
+\r
+        private static Color getColor(int value)\r
+        {\r
+            int r = (value & 0xff0000) >> 16;\r
+            int g = (value & 0xff00) >> 8;\r
+            int b = (value & 0xff);\r
+            return Color.FromRgb((byte)r, (byte)g, (byte)b);\r
+        }\r
+\r
+        static cssColor [] mColorList = \r
+        {\r
+            new cssColor("aliceblue", 0xF0F8FF),       // 240,248,255\r
+            new cssColor("antiquewhite", 0xFAEBD7),    //250,235,215\r
+            new cssColor("aqua", 0x00FFFF),    //0,255,255\r
+            new cssColor("aquamarine", 0x7FFFD4),      //127,255,212\r
+            new cssColor("azure", 0xF0FFFF),   //240,255,255\r
+            new cssColor("beige", 0xF5F5DC),   //245,245,220\r
+            new cssColor("bisque", 0xFFE4C4),  //255,228,196\r
+            new cssColor("black", 0x000000),   //0,0,0\r
+            new cssColor("blanchedalmond", 0xFFEBCD),  //255,235,205\r
+            new cssColor("blue", 0x0000FF),    //0,0,255\r
+            new cssColor("blueviolet", 0x8A2BE2),      //138,43,226\r
+            new cssColor("brown", 0xA52A2A),   //165,42,42\r
+            new cssColor("burlywood", 0xDEB887),       //222,184,135\r
+            new cssColor("cadetblue", 0x5F9EA0),       //95,158,160\r
+            new cssColor("chartreuse", 0x7FFF00),      //127,255,0\r
+            new cssColor("chocolate", 0xD2691E),       //210,105,30\r
+            new cssColor("coral", 0xFF7F50),   //255,127,80\r
+            new cssColor("cornflowerblue", 0x6495ED),  //100,149,237\r
+            new cssColor("cornsilk", 0xFFF8DC),        //255,248,220\r
+            new cssColor("crimson", 0xDC143C), //220,20,60\r
+            new cssColor("cyan", 0x00FFFF),    //0,255,255\r
+            new cssColor("darkblue", 0x00008B),        //0,0,139\r
+            new cssColor("darkcyan", 0x008B8B),        //0,139,139\r
+            new cssColor("darkgoldenrod", 0xB8860B),   //184,134,11\r
+            new cssColor("darkgray", 0xA9A9A9),        //169,169,169\r
+            new cssColor("darkgreen", 0x006400),       //0,100,0\r
+            new cssColor("darkgrey", 0xA9A9A9),        //169,169,169\r
+            new cssColor("darkkhaki", 0xBDB76B),       //189,183,107\r
+            new cssColor("darkmagenta", 0x8B008B),     //139,0,139\r
+            new cssColor("darkolivegreen", 0x556B2F),  //85,107,47\r
+            new cssColor("darkorange", 0xFF8C00),      //255,140,0\r
+            new cssColor("darkorchid", 0x9932CC),      //153,50,204\r
+            new cssColor("darkred", 0x8B0000), //139,0,0\r
+            new cssColor("darksalmon", 0xE9967A),      //233,150,122\r
+            new cssColor("darkseagreen", 0x8FBC8F),    //143,188,143\r
+            new cssColor("darkslateblue", 0x483D8B),   //72,61,139\r
+            new cssColor("darkslategray", 0x2F4F4F),   //47,79,79\r
+            new cssColor("darkslategrey", 0x2F4F4F),   //47,79,79\r
+            new cssColor("darkturquoise", 0x00CED1),   //0,206,209\r
+            new cssColor("darkviolet", 0x9400D3),      //148,0,211\r
+            new cssColor("deeppink", 0xFF1493),        //255,20,147\r
+            new cssColor("deepskyblue", 0x00BFFF),     //0,191,255\r
+            new cssColor("dimgray", 0x696969), //105,105,105\r
+            new cssColor("dimgrey", 0x696969), //105,105,105\r
+            new cssColor("dodgerblue", 0x1E90FF),      //30,144,255\r
+            new cssColor("firebrick", 0xB22222),       //178,34,34\r
+            new cssColor("floralwhite", 0xFFFAF0),     //255,250,240\r
+            new cssColor("forestgreen", 0x228B22),     //34,139,34\r
+            new cssColor("fuchsia", 0xFF00FF), //255,0,255\r
+            new cssColor("gainsboro", 0xDCDCDC),       //220,220,220\r
+            new cssColor("ghostwhite", 0xF8F8FF),      //248,248,255\r
+            new cssColor("gold", 0xFFD700),    //255,215,0\r
+            new cssColor("goldenrod", 0xDAA520),       //218,165,32\r
+            new cssColor("gray", 0x808080),    //128,128,128\r
+            new cssColor("green", 0x008000),   //0,128,0\r
+            new cssColor("greenyellow", 0xADFF2F),     //173,255,47\r
+            new cssColor("grey", 0x808080),    //128,128,128\r
+            new cssColor("honeydew", 0xF0FFF0),        //240,255,240\r
+            new cssColor("hotpink", 0xFF69B4), //255,105,180\r
+            new cssColor("indianred", 0xCD5C5C),       //205,92,92\r
+            new cssColor("indigo", 0x4B0082),  //75,0,130\r
+            new cssColor("ivory", 0xFFFFF0),   //255,255,240\r
+            new cssColor("khaki", 0xF0E68C),   //240,230,140\r
+            new cssColor("lavender", 0xE6E6FA),        //230,230,250\r
+            new cssColor("lavenderblush", 0xFFF0F5),   //255,240,245\r
+            new cssColor("lawngreen", 0x7CFC00),       //124,252,0\r
+            new cssColor("lemonchiffon", 0xFFFACD),    //255,250,205\r
+            new cssColor("lightblue", 0xADD8E6),       //173,216,230\r
+            new cssColor("lightcoral", 0xF08080),      //240,128,128\r
+            new cssColor("lightcyan", 0xE0FFFF),       //224,255,255\r
+            new cssColor("lightgoldenrodyellow", 0xFAFAD2),    //250,250,210\r
+            new cssColor("lightgray", 0xD3D3D3),       //211,211,211\r
+            new cssColor("lightgreen", 0x90EE90),      //144,238,144\r
+            new cssColor("lightgrey", 0xD3D3D3),       //211,211,211\r
+            new cssColor("lightpink", 0xFFB6C1),       //255,182,193\r
+            new cssColor("lightsalmon", 0xFFA07A),     //255,160,122\r
+            new cssColor("lightseagreen", 0x20B2AA),   //32,178,170\r
+            new cssColor("lightskyblue", 0x87CEFA),    //135,206,250\r
+            new cssColor("lightslategray", 0x778899),  //119,136,153\r
+            new cssColor("lightslategrey", 0x778899),  //119,136,153\r
+            new cssColor("lightsteelblue", 0xB0C4DE),  //176,196,222\r
+            new cssColor("lightyellow", 0xFFFFE0),     //255,255,224\r
+            new cssColor("lime", 0x00FF00),    //0,255,0\r
+            new cssColor("limegreen", 0x32CD32),       //50,205,50\r
+            new cssColor("linen", 0xFAF0E6),   //250,240,230\r
+            new cssColor("magenta", 0xFF00FF), //255,0,255\r
+            new cssColor("maroon", 0x800000),  //128,0,0\r
+            new cssColor("mediumaquamarine", 0x66CDAA),        //102,205,170\r
+            new cssColor("mediumblue", 0x0000CD),      //0,0,205\r
+            new cssColor("mediumorchid", 0xBA55D3),    //186,85,211\r
+            new cssColor("mediumpurple", 0x9370DB),    //147,112,219\r
+            new cssColor("mediumseagreen", 0x3CB371),  //60,179,113\r
+            new cssColor("mediumslateblue", 0x7B68EE), //123,104,238\r
+            new cssColor("mediumspringgreen", 0x00FA9A),       //0,250,154\r
+            new cssColor("mediumturquoise", 0x48D1CC), //72,209,204\r
+            new cssColor("mediumvioletred", 0xC71585), //199,21,133\r
+            new cssColor("midnightblue", 0x191970),    //25,25,112\r
+            new cssColor("mintcream", 0xF5FFFA),       //245,255,250\r
+            new cssColor("mistyrose", 0xFFE4E1),       //255,228,225\r
+            new cssColor("moccasin", 0xFFE4B5),        //255,228,181\r
+            new cssColor("navajowhite", 0xFFDEAD),     //255,222,173\r
+            new cssColor("navy", 0x000080),    //0,0,128\r
+            new cssColor("oldlace", 0xFDF5E6), //253,245,230\r
+            new cssColor("olive", 0x808000),   //128,128,0\r
+            new cssColor("olivedrab", 0x6B8E23),       //107,142,35\r
+            new cssColor("orange", 0xFFA500),  //255,165,0\r
+            new cssColor("orangered", 0xFF4500),       //255,69,0\r
+            new cssColor("orchid", 0xDA70D6),  //218,112,214\r
+            new cssColor("palegoldenrod", 0xEEE8AA),   //238,232,170\r
+            new cssColor("palegreen", 0x98FB98),       //152,251,152\r
+            new cssColor("paleturquoise", 0xAFEEEE),   //175,238,238\r
+            new cssColor("palevioletred", 0xDB7093),   //219,112,147\r
+            new cssColor("papayawhip", 0xFFEFD5),      //255,239,213\r
+            new cssColor("peachpuff", 0xFFDAB9),       //255,218,185\r
+            new cssColor("peru", 0xCD853F),    //205,133,63\r
+            new cssColor("pink", 0xFFC0CB),    //255,192,203\r
+            new cssColor("plum", 0xDDA0DD),    //221,160,221\r
+            new cssColor("powderblue", 0xB0E0E6),      //176,224,230\r
+            new cssColor("purple", 0x800080),  //128,0,128\r
+            new cssColor("red", 0xFF0000),     //255,0,0\r
+            new cssColor("rosybrown", 0xBC8F8F),       //188,143,143\r
+            new cssColor("royalblue", 0x4169E1),       //65,105,225\r
+            new cssColor("saddlebrown", 0x8B4513),     //139,69,19\r
+            new cssColor("salmon", 0xFA8072),  //250,128,114\r
+            new cssColor("sandybrown", 0xF4A460),      //244,164,96\r
+            new cssColor("seagreen", 0x2E8B57),        //46,139,87\r
+            new cssColor("seashell", 0xFFF5EE),        //255,245,238\r
+            new cssColor("sienna", 0xA0522D),  //160,82,45\r
+            new cssColor("silver", 0xC0C0C0),  //192,192,192\r
+            new cssColor("skyblue", 0x87CEEB), //135,206,235\r
+            new cssColor("slateblue", 0x6A5ACD),       //106,90,205\r
+            new cssColor("slategray", 0x708090),       //112,128,144\r
+            new cssColor("slategrey", 0x708090),       //112,128,144\r
+            new cssColor("snow", 0xFFFAFA),    //255,250,250\r
+            new cssColor("springgreen", 0x00FF7F),     //0,255,127\r
+            new cssColor("steelblue", 0x4682B4),       //70,130,180\r
+            new cssColor("tan", 0xD2B48C),     //210,180,140\r
+            new cssColor("teal", 0x008080),    //0,128,128\r
+            new cssColor("thistle", 0xD8BFD8), //216,191,216\r
+            new cssColor("tomato", 0xFF6347),  //255,99,71\r
+            new cssColor("turquoise", 0x40E0D0),       //64,224,208\r
+            new cssColor("violet", 0xEE82EE),  //238,130,238\r
+            new cssColor("wheat", 0xF5DEB3),   //245,222,179\r
+            new cssColor("white", 0xFFFFFF),   //255,255,255\r
+            new cssColor("whitesmoke", 0xF5F5F5),      //245,245,245\r
+            new cssColor("yellow", 0xFFFF00),  //255,255,0\r
+            new cssColor("yellowgreen", 0x9ACD32),     //154,205,50\r
+        };\r
+    }\r
+}\r
diff --git a/NT2chCtrl45/html/css/cssFont.cs b/NT2chCtrl45/html/css/cssFont.cs
new file mode 100755 (executable)
index 0000000..564142d
--- /dev/null
@@ -0,0 +1,205 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+\r
+namespace NT2chCtrl.html.css\r
+{\r
+    public class cssFont\r
+    {\r
+\r
+\r
+        public static bool tryGetFontStyle(string source, out Property.FontStyle style)\r
+        {\r
+            int state = 0;\r
+            int length = source.Length;\r
+            //string s;\r
+            style = Property.FontStyle.Normal;\r
+\r
+            for (int i = 0; i < length; i++)\r
+            {\r
+                switch (HtmlParser.getCharToken(source[i]))\r
+                {\r
+                    case HtmlParser.CHAR_TOKEN.ALPHA:\r
+                        if (state != 0)\r
+                            return false;\r
+                        if (i == source.IndexOf("italic", i))\r
+                        {\r
+                            style  = Property.FontStyle.Italic;\r
+                            state = 1;\r
+                            i += 5;\r
+                        }\r
+                        else if (i == source.IndexOf("oblique", i))\r
+                        {\r
+                            style = Property.FontStyle.Oblique;\r
+                            state = 1;\r
+                            i += 6;\r
+                        }\r
+                        else if (i == source.IndexOf("normal", i))\r
+                        {\r
+                            state = 1;\r
+                            i += 5;\r
+                        }\r
+                        else\r
+                        {\r
+                            return false;\r
+                        }\r
+                        break;\r
+                    case HtmlParser.CHAR_TOKEN.NUMBER:\r
+                        return false;\r
+                    case HtmlParser.CHAR_TOKEN.NL:\r
+                    case HtmlParser.CHAR_TOKEN.WHITESPACE:\r
+                        switch (state)\r
+                        {\r
+                            case 0:\r
+                                break;\r
+                            case 1:\r
+                                 return true;\r
+                            default:\r
+                                return false;\r
+                        }\r
+                        break;\r
+                }\r
+            }\r
+            if (state == 1)\r
+            {\r
+                return true;\r
+            }\r
+            return false;\r
+        }\r
+\r
+        public static bool tryGetFontFamily(string source, out string fontFamily)\r
+        {\r
+            int state = 0;\r
+            int length = source.Length;\r
+            //string s;\r
+            fontFamily = null;\r
+            bool dquote = false;\r
+            bool squote = false;\r
+            StringBuilder sb = new StringBuilder();\r
+\r
+            for (int i = 0; i < length; i++)\r
+            {\r
+                char c = source[i];\r
+                switch (HtmlParser.getCharToken(c))\r
+                {\r
+                    case HtmlParser.CHAR_TOKEN.DQUOTE :\r
+                        if (!squote)\r
+                            dquote = !dquote;\r
+                        else\r
+                            sb.Append(c);\r
+                        break;\r
+                    case HtmlParser.CHAR_TOKEN.SQUOTE:\r
+                        if(!dquote)\r
+                            squote = !squote;\r
+                        else\r
+                            sb.Append(c);\r
+                        break;\r
+                    case HtmlParser.CHAR_TOKEN.ALPHA:\r
+                    case HtmlParser.CHAR_TOKEN.NUMBER:\r
+                    case HtmlParser.CHAR_TOKEN.OTHER:\r
+                        if (state == 0)\r
+                            state = 1;\r
+                        sb.Append(c);\r
+                        break;\r
+                    case HtmlParser.CHAR_TOKEN.COMMA:\r
+                        if (state != 1)\r
+                            return false;\r
+                        sb.Append(c);\r
+                        break;\r
+                    case HtmlParser.CHAR_TOKEN.WHITESPACE:\r
+                    case HtmlParser.CHAR_TOKEN.NL:\r
+                        if (state == 1)// && (dquote || squote))\r
+                            sb.Append(c);\r
+                        break;\r
+                }\r
+            }\r
+            if (state == 1)\r
+            {\r
+                fontFamily = sb.ToString();\r
+                return true;\r
+            }\r
+            return false;\r
+        }\r
+\r
+        public static bool tryGetFontWeight(string source, out int weight)\r
+        {\r
+            int state = 0;\r
+            int length = source.Length;\r
+            int textStart = 0;\r
+            string s;\r
+            int nVal;\r
+            weight = 400;\r
+            for (int i = 0; i < length; i++)\r
+            {\r
+                switch (HtmlParser.getCharToken(source[i]))\r
+                {\r
+                    case HtmlParser.CHAR_TOKEN.ALPHA:\r
+                        if (state != 0)\r
+                            return false;\r
+                        if (i == source.IndexOf("bold", i))\r
+                        {\r
+                            weight = 700;\r
+                            state = 2;\r
+                            i += 3;\r
+                        }\r
+                        else if (i == source.IndexOf("normal", i))\r
+                        {\r
+                            state = 2;\r
+                            i += 5;\r
+                        }\r
+                        else\r
+                        {\r
+                            return false;\r
+                        }\r
+                        break;\r
+\r
+                    case HtmlParser.CHAR_TOKEN.NUMBER:\r
+                        if (state == 0)\r
+                        {\r
+                            textStart = i;\r
+                            state = 1;\r
+                        }\r
+                        else if (state != 1)\r
+                        {\r
+                            return false;\r
+                        }\r
+                        break;\r
+                    case HtmlParser.CHAR_TOKEN.NL:\r
+                    case HtmlParser.CHAR_TOKEN.WHITESPACE:\r
+                        switch (state)\r
+                        {\r
+                            case 0:\r
+                                break;\r
+                            case 1:\r
+                                s = source.Substring(textStart, i - textStart);\r
+                                if (int.TryParse(s, out nVal))\r
+                                {\r
+                                    weight = nVal;\r
+                                    return true;\r
+                                }\r
+                                return false;\r
+                            case 2:\r
+                                return true;\r
+                            default:\r
+                                return false;\r
+                        }\r
+                        break;\r
+                }\r
+            }\r
+            if (state == 1)\r
+            {\r
+                s = source.Substring(textStart, length - textStart);\r
+                if (int.TryParse(s, out nVal))\r
+                {\r
+                    weight = nVal;\r
+                    return true;\r
+                }\r
+            }\r
+            else if (state == 2)\r
+            {\r
+                return true;\r
+            }\r
+            return false;\r
+        }\r
+    }\r
+}\r
diff --git a/NT2chCtrl45/html/css/cssLength.cs b/NT2chCtrl45/html/css/cssLength.cs
new file mode 100755 (executable)
index 0000000..83d4928
--- /dev/null
@@ -0,0 +1,175 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+\r
+namespace NT2chCtrl.html.css\r
+{\r
+    public class cssLength\r
+    {\r
+        const double ONE_INCH_CM = 2.54;\r
+        const double ONE_INCH_MM = 25.4;\r
+        const double SCREEN_DPI = 96;\r
\r
+        private static double mBaseLength = 14; \r
+        //public static void init(double baseFontLength)\r
+        //{\r
+        //    mBaseLength = baseFontLength;\r
+        //}\r
+\r
+        public static double getLength(string source)\r
+        {\r
+            return getLength(source, null);\r
+        }\r
+\r
+        public static double getLength(string source, double? fontSize)\r
+        {\r
+            int state = 0;\r
+            int numberStartIdx = 0;\r
+            int length = source.Length;\r
+            double resultLength;\r
+            bool fraction = false;\r
+            bool zeroSuppress = false;\r
+            int nVal;\r
+            double dVal;\r
+            string numberStr;\r
+\r
+            if (source == null)\r
+                return double.NaN;\r
+\r
+            for (int i = 0; i < length; i++)            \r
+            {\r
+                char c = source[i];\r
+                switch (HtmlParser.getCharToken(c))\r
+                {\r
+                    case HtmlParser.CHAR_TOKEN.NUMBER:\r
+                        if (state == 0)\r
+                        {\r
+                            state = 1;\r
+                            numberStartIdx = i;\r
+                        }\r
+                        else if (state != 1)\r
+                        {\r
+                            return double.NaN;\r
+                        }\r
+                        break;\r
+                    case HtmlParser.CHAR_TOKEN.PERIOD:\r
+                        if (state == 0)\r
+                        {\r
+                            state = 1;\r
+                            numberStartIdx = i;\r
+                            zeroSuppress = true;\r
+                        }\r
+                        else if (state != 1)\r
+                        {\r
+                            return double.NaN;\r
+                        }\r
+                        fraction = true;\r
+                        break;\r
+                    case HtmlParser.CHAR_TOKEN.WHITESPACE:\r
+                    case HtmlParser.CHAR_TOKEN.NL:\r
+                        if (state != 0)\r
+                            return double.NaN;\r
+                        break;\r
+                    //case HtmlParser.CHAR_TOKEN.OTHER:\r
+                    default:\r
+                        if (state != 1)\r
+                            return double.NaN;\r
+                        numberStr = source.Substring(numberStartIdx, i - numberStartIdx);\r
+                        if (fraction)\r
+                        {\r
+                            if (zeroSuppress)\r
+                                numberStr = "0" + numberStr;\r
+                            if (!double.TryParse(numberStr, out dVal))\r
+                                return double.NaN;\r
+                        }\r
+                        else\r
+                        {\r
+                            if (!int.TryParse(numberStr, out nVal))\r
+                                return double.NaN;\r
+                            else\r
+                                dVal = nVal;\r
+\r
+                        }\r
+                        if (tryParseCSSLength(dVal, source, i, out resultLength, fontSize))\r
+                            return resultLength;\r
+                        else\r
+                            return double.NaN;\r
+                }\r
+            }\r
+            return double.NaN;\r
+        }\r
+\r
+        public static bool tryParseCSSLength(double length , string source,\r
+            int startIdx, out double outLength, double? fontSize)\r
+        {\r
+            outLength = double.NaN;\r
+            bool bRet = true;\r
+\r
+            double baseLength;\r
+            if (!fontSize.HasValue || fontSize == double.NaN)\r
+            {\r
+                baseLength = mBaseLength;\r
+            }\r
+            else\r
+            {\r
+                baseLength = (double)fontSize;\r
+            }\r
+\r
+            if (startIdx == source.IndexOf("in", startIdx))\r
+            {\r
+                //in (inches)\r
+                outLength = length / SCREEN_DPI;\r
+            }\r
+            else if (startIdx == source.IndexOf("cm", startIdx))\r
+            {\r
+                //cm (centimeters)\r
+                outLength = length * SCREEN_DPI / ONE_INCH_CM;                \r
+            }\r
+            else if (startIdx == source.IndexOf("mm", startIdx))\r
+            {\r
+                //mm (millimeters)\r
+                outLength = length * SCREEN_DPI / ONE_INCH_MM;\r
+            }\r
+            else if (startIdx == source.IndexOf("pt", startIdx))\r
+            {\r
+                //pt (point 1/72 of an inch)\r
+                outLength = length * SCREEN_DPI / 72;\r
+            }\r
+            else if (startIdx == source.IndexOf("pc", startIdx))\r
+            {\r
+                //pc (picas 12 points)\r
+                outLength = length * SCREEN_DPI / 72 / 12;\r
+            }\r
+            else if (startIdx == source.IndexOf("em", startIdx))\r
+            {\r
+                //em font size\r
+                outLength = baseLength * length;\r
+            }\r
+            else if (startIdx == source.IndexOf("ex", startIdx))\r
+            {\r
+                //ex x-height of font (approximately 0.5em)\r
+                outLength = baseLength * length / 2;\r
+            }\r
+            else if (startIdx == source.IndexOf("rem", startIdx))\r
+            {\r
+                //rem root elements font size\r
+                outLength = mBaseLength * length;\r
+            }\r
+            else if (startIdx == source.IndexOf("px", startIdx))\r
+            {\r
+                //px (96dpi)\r
+                outLength = length;\r
+            }\r
+            else if (startIdx == source.IndexOf("%", startIdx))\r
+            {\r
+                //% percentage of another property\r
+                outLength = baseLength * length / 100;\r
+            }\r
+            else\r
+            {\r
+                bRet = false;\r
+            }\r
+            return bRet;\r
+        }\r
+    }\r
+}\r
diff --git a/NT2chCtrl45/html/js/JsArrayValue.cs b/NT2chCtrl45/html/js/JsArrayValue.cs
new file mode 100755 (executable)
index 0000000..4382426
--- /dev/null
@@ -0,0 +1,29 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading.Tasks;\r
+\r
+namespace NT2chCtrl.html.js\r
+{\r
+    class JsArrayValue : JsVariant\r
+    {\r
+        List<JsVariant> mArray = new List<JsVariant>();\r
+\r
+        public JsArrayValue()\r
+        {\r
+        }\r
+        public JsArrayValue(JsVariant val)\r
+        {\r
+            mArray.Add(val);\r
+        }\r
+        public void AddValue(JsVariant val)\r
+        {\r
+            mArray.Add(val);\r
+        }\r
+        public List<JsVariant> getList()\r
+        {\r
+            return mArray;\r
+        }\r
+    }\r
+}\r
diff --git a/NT2chCtrl45/html/js/JsCmpFunction.cs b/NT2chCtrl45/html/js/JsCmpFunction.cs
new file mode 100755 (executable)
index 0000000..c3089e1
--- /dev/null
@@ -0,0 +1,273 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading.Tasks;\r
+\r
+namespace NT2chCtrl.html.js\r
+{\r
+    class JsCmpFunction : JsFunction\r
+    {\r
+        JsVariant mLhsValue;\r
+        JsVariant mRhsValue;\r
+        JsToken mOpToken;\r
+\r
+        public JsCmpFunction(int lineNo, int srcIdx, JsToken opToken)\r
+            : base(lineNo, srcIdx)\r
+        {\r
+            mOpToken = opToken;\r
+        }\r
+        public override int getPriority()\r
+        {\r
+            return FUNC_PRIORITY_COMPARE;\r
+        }\r
+\r
+        public override bool rearegeSquence(List<JsVariant> insList, int currIdx)\r
+        {\r
+            int count = insList.Count;\r
+            if (count < 3 || count <= (currIdx + 1))\r
+                return false;\r
+\r
+            mRhsValue = insList[currIdx + 1];\r
+            mLhsValue = insList[currIdx - 1];\r
+            insList.RemoveAt(currIdx + 1);\r
+            insList.RemoveAt(currIdx - 1);\r
+            mArranged = true;\r
+            return true;\r
+        }\r
+\r
+        public override JsVariant Execute(JsFunctionContext ctx, HtmlElement rootElement)\r
+        {\r
+            base.Execute(ctx, rootElement);\r
+\r
+            JsVariant lhs = ctx.getParamValue(rootElement, mLhsValue);\r
+            JsVariant rhs = ctx.getParamValue(rootElement, mRhsValue);\r
+\r
+            switch (mOpToken)\r
+            {\r
+                case JsToken.KEY_OP_CMP_EQUAL:\r
+                    return cmpEqual(lhs, rhs);\r
+                case JsToken.KEY_OP_CMP_STRICT_EQUAL:\r
+                    return cmpStrictEqual(lhs, rhs);\r
+                case JsToken.KEY_OP_CMP_NOT_EQUAL:\r
+                    return cmpNotEqual(lhs, rhs);\r
+                case JsToken.KEY_OP_CMP_STRICT_NOT_EQUAL:\r
+                    return cmpStrictNotEqual(lhs, rhs);\r
+                case JsToken.KEY_OP_CMP_LT:\r
+                case JsToken.KEY_OP_CMP_GT:\r
+                case JsToken.KEY_OP_CMP_LT_EQUAL:\r
+                case JsToken.KEY_OP_CMP_GT_EQUAL:\r
+                    return cmpValues(mOpToken, lhs, rhs);\r
+            }\r
+            return null;\r
+        }\r
+\r
+        private JsVariant cmpValues(JsToken token, JsVariant lhs, JsVariant rhs)\r
+        {\r
+            JsNumberValue nVal1 = lhs.getNumberValue();\r
+            if (nVal1 == null)\r
+                return null;\r
+\r
+            JsNumberValue nVal2 = rhs.getNumberValue();\r
+            if (nVal2 == null)\r
+                return null;\r
+            double d1 = nVal1.getValue();\r
+            double d2 = nVal2.getValue();\r
+            switch (mOpToken)\r
+            {\r
+                case JsToken.KEY_OP_CMP_LT:\r
+                    return JsBooleanValue.getConstantValue(d1 < d2);\r
+                case JsToken.KEY_OP_CMP_GT:\r
+                    return JsBooleanValue.getConstantValue(d1 > d2);\r
+                case JsToken.KEY_OP_CMP_LT_EQUAL:\r
+                    return JsBooleanValue.getConstantValue(d1 <= d2);\r
+                case JsToken.KEY_OP_CMP_GT_EQUAL:\r
+                    return JsBooleanValue.getConstantValue(d1 >= d2);\r
+            }\r
+            return null;\r
+        }\r
+\r
+        private JsVariant cmpStrictNotEqual(JsVariant lhs, JsVariant rhs)\r
+        {\r
+            JsBooleanValue bVal = cmpStrictEqual(lhs, rhs) as JsBooleanValue;\r
+            if (bVal != null)\r
+            {\r
+                if (bVal.getValue())\r
+                    return JsBooleanValue.getFalseValue();\r
+                else\r
+                    return JsBooleanValue.getTrueValue();\r
+            }\r
+            return null;\r
+        }\r
+\r
+        private JsVariant cmpStrictEqual(JsVariant lhs, JsVariant rhs)\r
+        {\r
+            JsNumberValue nVal1, nVal2;\r
+            JsStringValue sVal1, sVal2;\r
+            string s1, s2;\r
+\r
+            if (lhs == null || rhs == null)\r
+                return null;\r
+\r
+            if (lhs is JsNullValue)\r
+            {\r
+                return JsBooleanValue.getConstantValue(rhs is JsNullValue);\r
+            }\r
+            if (rhs is JsNullValue)\r
+            {\r
+                return JsBooleanValue.getConstantValue(lhs is JsNullValue);\r
+            }\r
+            if (lhs is JsUndefValue)\r
+            {\r
+                return JsBooleanValue.getConstantValue(rhs is JsNullValue);\r
+            }\r
+            if (rhs is JsUndefValue)\r
+            {\r
+                return JsBooleanValue.getConstantValue(lhs is JsUndefValue);\r
+            }\r
+\r
+            nVal1 = lhs as JsNumberValue;\r
+            if (nVal1 != null)\r
+            {\r
+                if (!(rhs is JsNumberValue))\r
+                    return JsBooleanValue.getFalseValue();\r
+                nVal2 = rhs.getNumberValue();\r
+                if (nVal2 == null)\r
+                    return JsBooleanValue.getFalseValue();\r
+                return JsBooleanValue.getConstantValue(nVal1.getValue() == nVal2.getValue());\r
+            }\r
+            nVal1 = rhs as JsNumberValue;\r
+            if (nVal1 != null)\r
+            {\r
+                if (!(lhs is JsNumberValue))\r
+                    return JsBooleanValue.getFalseValue();\r
+                nVal2 = lhs.getNumberValue();\r
+                if (nVal2 == null)\r
+                    return JsBooleanValue.getFalseValue();\r
+                return JsBooleanValue.getConstantValue(nVal1.getValue() == nVal2.getValue());\r
+            }\r
+            sVal1 = lhs as JsStringValue;\r
+            if (sVal1 != null)\r
+            {\r
+                if (!(rhs is JsStringValue))\r
+                    return JsBooleanValue.getFalseValue();\r
+                sVal2 = rhs.getStringValue();\r
+                if (sVal2 == null)\r
+                    return JsBooleanValue.getFalseValue();\r
+                s1 = sVal1.getValue();\r
+                s2 = sVal2.getValue();\r
+                if (s1 == null || s2 == null)\r
+                    return JsBooleanValue.getFalseValue();\r
+                return JsBooleanValue.getConstantValue(s1.Equals(s2));\r
+            }\r
+            sVal1 = rhs as JsStringValue;\r
+            if (sVal1 != null)\r
+            {\r
+                if (!(lhs is JsStringValue))\r
+                    return JsBooleanValue.getFalseValue();\r
+                sVal2 = lhs.getStringValue();\r
+                if (sVal2 == null)\r
+                    return JsBooleanValue.getFalseValue();\r
+                s1 = sVal1.getValue();\r
+                s2 = sVal2.getValue();\r
+                if (s1 == null || s2 == null)\r
+                    return JsBooleanValue.getFalseValue();\r
+                return JsBooleanValue.getConstantValue(s1.Equals(s2));\r
+            }\r
+            return null;\r
+        }\r
+        private JsVariant cmpNotEqual(JsVariant lhs, JsVariant rhs)\r
+        {\r
+            JsBooleanValue bVal = cmpEqual(lhs, rhs) as JsBooleanValue;\r
+            if (bVal != null)\r
+            {\r
+                if (bVal.getValue())\r
+                    return JsBooleanValue.getFalseValue();\r
+                else\r
+                    return JsBooleanValue.getTrueValue();\r
+            }\r
+            return null;\r
+        }\r
+\r
+        private JsVariant cmpEqual(JsVariant lhs, JsVariant rhs)\r
+        {\r
+            JsNumberValue nVal1, nVal2;\r
+            JsStringValue sVal1, sVal2;\r
+            string s1, s2;\r
+\r
+            if (lhs == null || rhs == null)\r
+                return null;\r
+\r
+            if (lhs is JsNullValue || lhs is JsUndefValue)\r
+            {\r
+                if (rhs is JsNullValue || rhs is JsUndefValue)\r
+                    return JsBooleanValue.getTrueValue();\r
+                if (rhs is JsNumberValue)\r
+                {\r
+                    double d = ((JsNumberValue)rhs).getValue();\r
+                    return JsBooleanValue.getConstantValue(d == 0);\r
+                }\r
+                return JsBooleanValue.getFalseValue();\r
+            }\r
+            if (rhs is JsNullValue || rhs is JsUndefValue)\r
+            {\r
+                if (lhs is JsNullValue || lhs is JsUndefValue)\r
+                    return JsBooleanValue.getTrueValue();\r
+                if (lhs is JsNumberValue)\r
+                {\r
+                    double d = ((JsNumberValue)lhs).getValue();\r
+                    return JsBooleanValue.getConstantValue(d == 0);\r
+                }\r
+                return JsBooleanValue.getFalseValue();\r
+            }\r
+\r
+            nVal1 = lhs as JsNumberValue;\r
+            if (nVal1 != null)\r
+            {\r
+                nVal2 = rhs.getNumberValue();\r
+                if (nVal2 == null)\r
+                    return JsBooleanValue.getFalseValue();\r
+                return JsBooleanValue.getConstantValue(nVal1.getValue() == nVal2.getValue());\r
+            }\r
+            nVal1 = rhs as JsNumberValue;\r
+            if (nVal1 != null)\r
+            {\r
+                nVal2 = lhs.getNumberValue();\r
+                if (nVal2 == null)\r
+                    return JsBooleanValue.getFalseValue();\r
+                return JsBooleanValue.getConstantValue(nVal1.getValue() == nVal2.getValue());\r
+            }\r
+            sVal1 = lhs as JsStringValue;\r
+            if (sVal1 != null)\r
+            {\r
+                sVal2 = rhs.getStringValue();\r
+                if (sVal2 == null)\r
+                    return JsBooleanValue.getFalseValue();\r
+                s1 = sVal1.getValue();\r
+                s2 = sVal2.getValue();\r
+                if (s1 == null || s2 == null)\r
+                    return JsBooleanValue.getFalseValue();\r
+                return JsBooleanValue.getConstantValue(s1.Equals(s2));\r
+            }\r
+            sVal1 = rhs as JsStringValue;\r
+            if (sVal1 != null)\r
+            {\r
+                sVal2 = lhs.getStringValue();\r
+                if (sVal2 == null)\r
+                    return JsBooleanValue.getFalseValue();\r
+                s1 = sVal1.getValue();\r
+                s2 = sVal2.getValue();\r
+                if (s1 == null || s2 == null)\r
+                    return JsBooleanValue.getFalseValue();\r
+                return JsBooleanValue.getConstantValue(s1.Equals(s2));\r
+            }\r
+            return null;\r
+        }\r
+\r
+\r
+\r
+\r
+\r
+\r
+    }\r
+}\r
diff --git a/NT2chCtrl45/html/js/JsDOMValue.cs b/NT2chCtrl45/html/js/JsDOMValue.cs
new file mode 100755 (executable)
index 0000000..011682f
--- /dev/null
@@ -0,0 +1,74 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading.Tasks;\r
+\r
+namespace NT2chCtrl.html.js\r
+{\r
+    public class JsDOMValue : JsVariant\r
+    {\r
+        List<HtmlElement> mThisElem;// = new List<HtmlElement>();\r
+\r
+        public JsDOMValue()\r
+        {\r
+            mThisElem = new List<HtmlElement>();\r
+        }\r
+        public JsDOMValue(HtmlElement elem)\r
+        {\r
+            mThisElem = new List<HtmlElement>(1);\r
+            mThisElem.Add(elem);\r
+        }\r
+        public JsDOMValue(List<HtmlElement> elems)\r
+        {\r
+            mThisElem = elems;\r
+        }\r
+\r
+        public override JsBooleanValue getBooleanValue()\r
+        {\r
+            return JsBooleanValue.getConstantValue(\r
+                (mThisElem != null && mThisElem.Count > 0));\r
+        }\r
+\r
+        public override JsStringValue getStringValue()\r
+        {\r
+            string s;\r
+            if (getInnerHTML(out s))\r
+            {\r
+                return new JsStringValue(s);\r
+            }\r
+            else\r
+            {\r
+                return JsStringValue.getEmpty();\r
+            }\r
+        }\r
+\r
+        public bool setInnerHTML(string source)\r
+        {\r
+            DebugContext ctx = new DebugContext();\r
+            foreach (HtmlElement elem in mThisElem)\r
+            {\r
+                elem.clearChildren();\r
+                if(0 > HtmlParser.parseElement(ctx, elem, source, 0))\r
+                    return false;\r
+\r
+            }\r
+            return true;\r
+        }\r
+\r
+        public bool getInnerHTML(out string htmlStr)\r
+        {\r
+            htmlStr = null;\r
+            DebugContext ctx = new DebugContext();\r
+            foreach (HtmlElement elem in mThisElem)\r
+            {\r
+                if(htmlStr == null)\r
+                    htmlStr = elem.getInnerHtml();\r
+                else\r
+                    htmlStr += elem.getInnerHtml();\r
+            }\r
+            return true;\r
+        }\r
+\r
+    }\r
+}\r
diff --git a/NT2chCtrl45/html/js/JsDomFunction.cs b/NT2chCtrl45/html/js/JsDomFunction.cs
new file mode 100755 (executable)
index 0000000..373d317
--- /dev/null
@@ -0,0 +1,212 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading.Tasks;\r
+\r
+namespace NT2chCtrl.html.js\r
+{\r
+    class JsDomFunction : JsFunction\r
+    {\r
+        JsToken mFuncNameKey;\r
+        JsFunction mThis;\r
+\r
+        public override bool IsArranged()\r
+        {\r
+            return mThis.IsArranged();\r
+        }\r
+        public override int getPriority()\r
+        {\r
+            return FUNC_PRIORITY_FUNCTION;\r
+        }\r
+        public override bool IsAssignable()\r
+        {\r
+            switch (mFuncNameKey)\r
+            {\r
+                //case JsToken.KEY_DOM_getElementById:\r
+                //    return false;\r
+                case JsToken.KEY_DOM_innerHTML:\r
+                    return true;\r
+            }\r
+            return false;\r
+        }\r
+\r
+        public JsDomFunction(JsToken funcNameKey, int lineNo, int srcIdx)\r
+            : base(lineNo, srcIdx)\r
+        {\r
+            mFuncNameKey = funcNameKey;\r
+            switch (mFuncNameKey)\r
+            {\r
+                case JsToken.KEY_DOM_getElementById:\r
+                    mThis = new JsDOMFunc_getElementById(lineNo, srcIdx);\r
+                    break;\r
+                case JsToken.KEY_DOM_innerHTML:\r
+                    mThis = new JsDOMFunc_innerHTML(lineNo, srcIdx);\r
+                    break;\r
+            }\r
+        }\r
+        public override bool rearegeSquence(List<JsVariant> insList, int currIdx)\r
+        {\r
+            return mThis.rearegeSquence(insList, currIdx);\r
+        }\r
+        public override JsVariant Execute(JsFunctionContext ctx, HtmlElement rootElement)\r
+        {\r
+            return mThis.Execute(ctx, rootElement);\r
+        }\r
+        public override JsVariant Execute(JsFunctionContext ctx, HtmlElement rootElement, JsVariant assignVal)\r
+        {\r
+            return mThis.Execute(ctx, rootElement, assignVal);\r
+        }\r
+    }\r
+\r
+    class JsDOMFunc_getElementById : JsFunction\r
+    {\r
+        List<JsVariant> mParams = null;\r
+        public override int getPriority()\r
+        {\r
+            return FUNC_PRIORITY_FUNCTION;\r
+        }\r
+\r
+        public JsDOMFunc_getElementById(int lineNo, int srcIdx)\r
+            : base(lineNo, srcIdx)\r
+        {\r
+        }\r
+\r
+        public override bool rearegeSquence(List<JsVariant> insList, int currIdx)\r
+        {\r
+            JsRBracket rBraket = null;\r
+            int count = insList.Count;\r
+            \r
+            if (currIdx + 1 >= count)\r
+                return false;\r
+            rBraket = insList[currIdx+1] as JsRBracket;\r
+            if (rBraket == null)\r
+                return false;\r
+\r
+            mParams = rBraket.mArgs;\r
+            if (mParams.Count != 1)\r
+                return false;\r
+\r
+            insList.RemoveAt(currIdx + 1);\r
+\r
+            mArranged = true;\r
+            return true;\r
+        }\r
+\r
+        public override JsVariant Execute(JsFunctionContext ctx, HtmlElement rootElement)\r
+        {\r
+            base.Execute(ctx,rootElement);\r
+            /*DebugContext dCtx = ctx.getDbgCtx();\r
+            if (dCtx != null)\r
+            {\r
+                dCtx.mCurrentLine = mSourceLine;\r
+                dCtx.mCurentIndex = mSourceIdx;\r
+            }*/\r
+\r
+            if (mParams == null || mParams.Count != 1)\r
+                return null;\r
+\r
+            JsVariant param = ctx.getParamValue(rootElement, mParams[0]);\r
+            JsStringValue sVal =  param as JsStringValue;\r
+            if (sVal == null)\r
+                return null;                \r
+\r
+            List<HtmlElement> elems = \r
+                rootElement.getElements(null, null, null,\r
+                        sVal.getValue(), null, true);\r
+            if (elems == null)\r
+                return JsNullValue.getConstant();\r
+\r
+            return new JsDOMValue(elems);\r
+        }\r
+    }\r
+\r
+    class JsDOMFunc_innerHTML : JsFunction\r
+    {\r
+        // This must be JsHTMLVariable;\r
+        JsVariant mElem = null;\r
+        public override int getPriority()\r
+        {\r
+            return FUNC_PRIORITY_FUNCTION;\r
+        }\r
+\r
+        public JsDOMFunc_innerHTML(int lineNo, int srcIdx)\r
+            : base(lineNo, srcIdx)\r
+        {\r
+        }\r
+\r
+        public override bool rearegeSquence(List<JsVariant> insList, int currIdx)\r
+        {\r
+            int count = insList.Count;\r
+            if (currIdx < 1 || count <= currIdx)\r
+                return false;\r
+\r
+            mElem = insList[currIdx - 1];\r
+            insList.RemoveAt(currIdx - 1);\r
+\r
+            mArranged = true;\r
+            return true;\r
+        }\r
+\r
+        public override JsVariant Execute(JsFunctionContext ctx, HtmlElement rootElement)\r
+        {\r
+            base.Execute(ctx, rootElement);\r
+            string htmlStr;\r
+            JsIdentifier idVal = mElem as JsIdentifier;\r
+            if (idVal == null)\r
+            {\r
+                return null;\r
+            }\r
+            JsDOMValue domVal = ctx.getValue(idVal) as JsDOMValue;\r
+            if (domVal == null)\r
+                return null;\r
+\r
+            if (domVal.getInnerHTML(out htmlStr))\r
+            {\r
+                return new JsStringValue(htmlStr);\r
+            }\r
+            else\r
+            {\r
+                return null;\r
+            }\r
+        }\r
+        public override JsVariant Execute(JsFunctionContext ctx, HtmlElement rootElement, JsVariant assignVal)\r
+        {\r
+            DebugContext dCtx = ctx.getDbgCtx();\r
+            if (dCtx != null)\r
+            {\r
+                dCtx.mCurrentLine = mSourceLine;\r
+                dCtx.mCurentIndex = mSourceIdx;\r
+            }\r
+\r
+            JsIdentifier idVal = mElem as JsIdentifier;\r
+            if(idVal == null){\r
+                return null;\r
+            }\r
+            JsDOMValue domVal = ctx.getValue(idVal) as JsDOMValue;\r
+            if (domVal == null)\r
+                return null;\r
+\r
+\r
+            JsVariant var = ctx.getParamValue(rootElement, assignVal);\r
+\r
+            JsStringValue sVal = var.getStringValue();\r
+            if (sVal == null)\r
+                return null;\r
+\r
+            /*JsStringValue sVal = assignVal as JsStringValue;\r
+            if (sVal == null)\r
+            {\r
+                idVal = assignVal as JsIdentifier;\r
+                if (idVal == null)\r
+                    return null;\r
+                sVal = ctx.getValue(idVal) as JsStringValue;\r
+                if (sVal == null)\r
+                    return null;\r
+            }*/\r
+            domVal.setInnerHTML(sVal.getValue());\r
+            return domVal;\r
+        }\r
+\r
+    }\r
+}\r
diff --git a/NT2chCtrl45/html/js/JsDomStrFunction.cs b/NT2chCtrl45/html/js/JsDomStrFunction.cs
new file mode 100755 (executable)
index 0000000..769bfa9
--- /dev/null
@@ -0,0 +1,402 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading.Tasks;\r
+\r
+namespace NT2chCtrl.html.js\r
+{\r
+    class JsDomStrFunc_indexOf : JsFunction\r
+    {\r
+        JsVariant mObj = null;\r
+        List<JsVariant> mParams = null;\r
+        public JsDomStrFunc_indexOf(int lineNo, int srcIdx)\r
+            : base(lineNo, srcIdx)\r
+        {\r
+        }\r
+        public override int getPriority()\r
+        {\r
+            return FUNC_PRIORITY_FUNCTION;\r
+        }\r
+        public override bool rearegeSquence(List<JsVariant> insList, int currIdx)\r
+        {\r
+            int count = insList.Count;\r
+            if (currIdx < 1 || count <= (currIdx+1))\r
+                return false;\r
+\r
+            mObj = insList[currIdx - 1];\r
+\r
+            JsRBracket rBraket = null;\r
+\r
+            if (currIdx + 1 >= count)\r
+                return false;\r
+            rBraket = insList[currIdx + 1] as JsRBracket;\r
+            if (rBraket == null)\r
+                return false;\r
+\r
+            mParams = rBraket.mArgs;\r
+\r
+            insList.RemoveAt(currIdx + 1);\r
+            insList.RemoveAt(currIdx - 1);\r
+\r
+            mArranged = true;\r
+            return true;\r
+        }\r
+        public override JsVariant Execute(JsFunctionContext ctx, HtmlElement rootElement)\r
+        {\r
+            base.Execute(ctx, rootElement);\r
+\r
+\r
+            if (mParams == null || mObj == null)\r
+                return null;\r
+\r
+            if (mParams.Count != 1)\r
+            {\r
+                ctx.getDbgCtx().mErrorMessage = JsError.INVALID_ARGMENT;\r
+                return null;\r
+            }\r
+\r
+            JsVariant var = ctx.getParamValue(rootElement, mObj);\r
+            if (var == null)\r
+                return null;\r
+\r
+            JsStringValue sVal = var.getStringValue();\r
+            if (sVal == null)\r
+                return null;\r
+\r
+            string orgStr = sVal.getValue();\r
+\r
+            List<JsVariant> args = mParams;\r
+\r
+            JsCommaFunction comma = args[0] as JsCommaFunction;\r
+            if (comma != null)\r
+            {\r
+                args = comma.getArgs();\r
+                if (args.Count != 1 && args.Count != 2)\r
+                {\r
+                    ctx.getDbgCtx().mErrorMessage = JsError.INVALID_ARGMENT;\r
+                    return null;\r
+                }\r
+            }\r
+\r
+            var = ctx.getParamValue(rootElement, args[0]);\r
+            if (var == null)\r
+                return null;\r
+\r
+            sVal = var.getStringValue();\r
+            if (sVal == null)\r
+                return null;\r
+\r
+            string findStr = sVal.getValue();\r
+\r
+            if (args.Count == 1)\r
+            {\r
+                return new JsNumberValue(orgStr.IndexOf(findStr));\r
+            }\r
+\r
+            var = ctx.getParamValue(rootElement, args[1]);\r
+            JsNumberValue nVal = var.getNumberValue();\r
+            if (nVal == null)\r
+            {\r
+                ctx.getDbgCtx().mErrorMessage = JsError.INVALID_NUMBER_TYPE;\r
+                return null;\r
+            }\r
+            if (nVal.IsNaN())\r
+            {\r
+                ctx.getDbgCtx().mErrorMessage = JsError.INVALID_NUMBER;\r
+                return null;\r
+            }\r
+\r
+            int num = (int)nVal.getValue();\r
+\r
+            if (num < 0 || num >= orgStr.Length)\r
+            {\r
+                ctx.getDbgCtx().mErrorMessage = JsError.INDEX_OUT_OF_RANGE;\r
+                return null;\r
+            }\r
+            return new JsNumberValue(orgStr.IndexOf(findStr, num));\r
+        }\r
+    }\r
+\r
+    class JsDomStrFunc_substring : JsFunction\r
+    {\r
+        JsVariant mObj;\r
+        List<JsVariant> mParams;\r
+        public JsDomStrFunc_substring(int lineNo, int srcIdx)\r
+            : base(lineNo, srcIdx)\r
+        {\r
+        }\r
+        public override int getPriority()\r
+        {\r
+            return FUNC_PRIORITY_FUNCTION;\r
+        }\r
+        public override bool rearegeSquence(List<JsVariant> insList, int currIdx)\r
+        {\r
+            int count = insList.Count;\r
+            if (currIdx < 1 || count <= (currIdx+1))\r
+                return false;\r
+\r
+            mObj = insList[currIdx - 1];\r
+\r
+            JsRBracket rBraket = null;\r
+\r
+            if (currIdx + 1 >= count)\r
+                return false;\r
+            rBraket = insList[currIdx + 1] as JsRBracket;\r
+            if (rBraket == null)\r
+                return false;\r
+\r
+            mParams = rBraket.mArgs;\r
+\r
+            insList.RemoveAt(currIdx + 1);\r
+            insList.RemoveAt(currIdx - 1);\r
+\r
+            mArranged = true;\r
+            return true;\r
+        }\r
+        public override JsVariant Execute(JsFunctionContext ctx, HtmlElement rootElement)\r
+        {\r
+            base.Execute(ctx, rootElement);\r
+\r
+\r
+            if (mParams == null || mObj == null)\r
+                return null;\r
+\r
+            if (mParams.Count != 1)\r
+            {\r
+                ctx.getDbgCtx().mErrorMessage = JsError.INVALID_ARGMENT;\r
+                return null;\r
+            }\r
+\r
+            JsVariant var = ctx.getParamValue(rootElement, mObj);\r
+            if (var == null)\r
+                return null;\r
+\r
+            JsStringValue sVal = var.getStringValue();\r
+            if (sVal == null)\r
+                return null;\r
+\r
+            string orgStr = sVal.getValue();\r
+\r
+            List<JsVariant> args = mParams;\r
+\r
+            JsCommaFunction comma = args[0] as JsCommaFunction;\r
+            if (comma != null)\r
+            {\r
+                args = comma.getArgs();\r
+                if (args.Count != 1 && args.Count != 2)\r
+                {\r
+                    ctx.getDbgCtx().mErrorMessage = JsError.INVALID_ARGMENT;\r
+                    return null;\r
+                }\r
+            }\r
+\r
+            var = ctx.getParamValue(rootElement, args[0]);\r
+            if (var == null)\r
+            {\r
+                ctx.getDbgCtx().mErrorMessage = JsError.INVALID_NUMBER_TYPE;\r
+                return null;\r
+            }\r
+\r
+            JsNumberValue nVal = var.getNumberValue();\r
+            if (nVal == null)\r
+            {\r
+                ctx.getDbgCtx().mErrorMessage = JsError.INVALID_NUMBER_TYPE;\r
+                return null;\r
+            }\r
+            if (nVal.IsNaN())\r
+            {\r
+                ctx.getDbgCtx().mErrorMessage = JsError.INVALID_NUMBER;\r
+                return null;\r
+            }\r
+\r
+            int startIdx = (int)nVal.getValue();\r
+\r
+            if (args.Count == 1)\r
+            {\r
+                return new JsStringValue(orgStr.Substring(startIdx));\r
+            }\r
+\r
+            var = ctx.getParamValue(rootElement, args[1]);\r
+            nVal = var.getNumberValue();\r
+            if (nVal == null)\r
+            {\r
+                ctx.getDbgCtx().mErrorMessage = JsError.INVALID_NUMBER_TYPE;\r
+                return null;\r
+            }\r
+            if (nVal.IsNaN())\r
+            {\r
+                ctx.getDbgCtx().mErrorMessage = JsError.INVALID_NUMBER;\r
+                return null;\r
+            }\r
+\r
+            int num = (int)nVal.getValue();\r
+\r
+            if (num < 0 || num >= orgStr.Length || startIdx > num)\r
+            {\r
+                ctx.getDbgCtx().mErrorMessage = JsError.INDEX_OUT_OF_RANGE;\r
+                return null;\r
+            }\r
+            return new JsStringValue(orgStr.Substring(startIdx, num - startIdx));\r
+        }\r
+    }\r
+\r
+    class JsDomStrFunc_replace : JsFunction\r
+    {\r
+        JsVariant mObj = null;\r
+        List<JsVariant> mParams = null;\r
+        public JsDomStrFunc_replace(int lineNo, int srcIdx)\r
+            : base(lineNo, srcIdx)\r
+        {\r
+        }\r
+        public override int getPriority()\r
+        {\r
+            return FUNC_PRIORITY_FUNCTION;\r
+        }\r
+        public override bool rearegeSquence(List<JsVariant> insList, int currIdx)\r
+        {\r
+            int count = insList.Count;\r
+            if (currIdx < 1 || count <= (currIdx + 1))\r
+                return false;\r
+\r
+            mObj = insList[currIdx - 1];\r
+\r
+            JsRBracket rBraket = null;\r
+\r
+            if (currIdx + 1 >= count)\r
+                return false;\r
+            rBraket = insList[currIdx + 1] as JsRBracket;\r
+            if (rBraket == null)\r
+                return false;\r
+\r
+            mParams = rBraket.mArgs;\r
+\r
+            insList.RemoveAt(currIdx + 1);\r
+            insList.RemoveAt(currIdx - 1);\r
+\r
+            mArranged = true;\r
+            return true;\r
+        }\r
+        public override JsVariant Execute(JsFunctionContext ctx, HtmlElement rootElement)\r
+        {\r
+            base.Execute(ctx, rootElement);\r
+\r
+\r
+            if (mParams == null || mObj == null)\r
+                return null;\r
+\r
+            if (mParams.Count != 1)\r
+            {\r
+                ctx.getDbgCtx().mErrorMessage = JsError.INVALID_ARGMENT;\r
+                return null;\r
+            }\r
+\r
+            JsVariant var = ctx.getParamValue(rootElement, mObj);\r
+            if (var == null)\r
+                return null;\r
+\r
+            JsStringValue sVal = var.getStringValue();\r
+            if (sVal == null)\r
+                return null;\r
+\r
+            string orgStr = sVal.getValue();\r
+\r
+            List<JsVariant> args = mParams;\r
+\r
+            JsCommaFunction comma = args[0] as JsCommaFunction;\r
+            if (comma != null)\r
+            {\r
+                args = comma.getArgs();\r
+                if (args.Count != 2)\r
+                {\r
+                    ctx.getDbgCtx().mErrorMessage = JsError.INVALID_ARGMENT;\r
+                    return null;\r
+                }\r
+            }\r
+\r
+            var = ctx.getParamValue(rootElement, args[0]);\r
+            if (var == null)\r
+                return null;\r
+\r
+            sVal = var.getStringValue();\r
+            if (sVal == null)\r
+                return null;\r
+\r
+            string targetStr = sVal.getValue();\r
+\r
+\r
+            var = ctx.getParamValue(rootElement, args[1]);\r
+            sVal = var.getStringValue();\r
+            if (sVal == null)\r
+            {\r
+                ctx.getDbgCtx().mErrorMessage = JsError.INVALID_STRING_TYPE;\r
+                return null;\r
+            }\r
+\r
+            return new JsStringValue(orgStr.Replace(targetStr, sVal.getValue()));\r
+        }\r
+    }\r
+\r
+    class JsDomStrFunc_length : JsFunction\r
+    {\r
+        JsVariant mObj = null;\r
+        public JsDomStrFunc_length(int lineNo, int srcIdx)\r
+            : base(lineNo, srcIdx)\r
+        {\r
+        }\r
+        public override int getPriority()\r
+        {\r
+            return FUNC_PRIORITY_FUNCTION;\r
+        }\r
+        public override bool rearegeSquence(List<JsVariant> insList, int currIdx)\r
+        {\r
+            int count = insList.Count;\r
+            if (currIdx < 1 || count < 2)\r
+                return false;\r
+\r
+            mObj = insList[currIdx - 1];\r
+            insList.RemoveAt(currIdx - 1);\r
+\r
+            mArranged = true;\r
+            return true;\r
+        }\r
+        public override JsVariant Execute(JsFunctionContext ctx, HtmlElement rootElement)\r
+        {\r
+            base.Execute(ctx, rootElement);\r
+\r
+\r
+            if (mObj == null)\r
+                return null;\r
+\r
+\r
+            JsVariant var = ctx.getParamValue(rootElement, mObj);\r
+            if (var == null)\r
+            {\r
+                ctx.getDbgCtx().mErrorMessage = JsError.INVALID_STRING_TYPE;\r
+                return null;\r
+            }\r
+\r
+            JsStringValue sVal = var.getStringValue();\r
+            if (sVal == null)\r
+                return null;\r
+\r
+            string orgStr = sVal.getValue();\r
+\r
+\r
+            return new JsNumberValue(orgStr.Length);\r
+        }\r
+    }\r
+#if false\r
+    class JsDomStrFunc_concat : JsFunction\r
+    {\r
+        public JsDomStrFunc_concat(int lineNo, int srcIdx)\r
+            : base(lineNo, srcIdx)\r
+        {\r
+        }\r
+        public override int getPriority()\r
+        {\r
+            return FUNC_PRIORITY_FUNCTION;\r
+        }\r
+    }\r
+#endif\r
+}\r
diff --git a/NT2chCtrl45/html/js/JsError.cs b/NT2chCtrl45/html/js/JsError.cs
new file mode 100755 (executable)
index 0000000..bc001a6
--- /dev/null
@@ -0,0 +1,21 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading.Tasks;\r
+\r
+namespace NT2chCtrl.html.js\r
+{\r
+    class JsError\r
+    {\r
+        public const string INDEX_OUT_OF_RANGE = "添字が配列の範囲外です";\r
+        public const string DIVIDED_BY_ZERO = "ゼロで除算しました";\r
+        public const string INVALID_ARGMENT = "引数の値が不正です";\r
+        public const string INVALID_1ST_ARGMENT = "第1引数の値が不正です";\r
+        public const string INVALID_2ND_ARGMENT = "第2引数の値が不正です";\r
+        public const string INVALID_NUMBER = "無効な数値です";\r
+        public const string INVALID_NUMBER_TYPE = "数値型に変換できません";\r
+        public const string INVALID_STRING_TYPE = "文字列に変換できません";\r
+        public const string INVALID_OPERAND_TYPE = "演算子のオペランドの型が不正です";\r
+    }\r
+}\r
diff --git a/NT2chCtrl45/html/js/JsFunction.cs b/NT2chCtrl45/html/js/JsFunction.cs
new file mode 100755 (executable)
index 0000000..872d94b
--- /dev/null
@@ -0,0 +1,884 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+\r
+namespace NT2chCtrl.html.js\r
+{\r
+\r
+\r
+    abstract class JsFunction : JsVariant\r
+    {\r
+        public const int FUNC_PRIORITY_INVALID = -2;\r
+        public const int FUNC_PRIORITY_ROOT = -1;\r
+        public const int FUNC_PRIORITY_LOAD = 1;\r
+\r
+        public const int FUNC_PRIORITY_COMMA = 10;\r
+        public const int FUNC_PRIORITY_SEMICOLON = 11;\r
+        \r
+        public const int FUNC_PRIORITY_COMPARE = 100;\r
+\r
+        public const int FUNC_PRIORITY_ADD = 1000;\r
+        public const int FUNC_PRIORITY_SUB = 1000;\r
+        public const int FUNC_PRIORITY_DIV = 1001;\r
+        public const int FUNC_PRIORITY_MUL = 1001;\r
+        public const int FUNC_PRIORITY_MINUS = 1002;\r
+        public const int FUNC_PRIORITY_PLUS = 1002;\r
+\r
+        public const int FUNC_PRIORITY_NOT = 1002;\r
+        public const int FUNC_PRIORITY_INC = 1003;\r
+        public const int FUNC_PRIORITY_DEC = 1003;\r
+\r
+        public const int FUNC_PRIORITY_FUNCTION = int.MaxValue - 2;\r
+        public const int FUNC_PRIORITY_L_BRACKET = int.MaxValue - 1;\r
+        public const int FUNC_PRIORITY_R_BRACKET = int.MaxValue;\r
+\r
+        protected static JsUndefValue JS_UNDEF_VALUE = new JsUndefValue();\r
+        protected static JsNullValue JS_NULL_VALUE = new JsNullValue();\r
+\r
+        protected bool mArranged = false;\r
+        public virtual bool IsArranged() { return mArranged; }\r
+        public virtual bool IsAssignable() { return false; }\r
+\r
+        protected List<List<JsVariant>> mInstructions = new List<List<JsVariant>>();\r
+\r
+        public abstract int getPriority();\r
+        public virtual bool rearegeSquence(List<JsVariant> insList, int currIdx) { return false; }\r
+\r
+        protected int mSourceLine;\r
+        protected int mSourceIdx;\r
+\r
+        public JsFunction(int lineNo, int srcIdx)\r
+        {\r
+            mSourceIdx = srcIdx;\r
+            mSourceLine = lineNo;\r
+        }\r
+\r
+        public void setDebugContext(DebugContext dCtx)\r
+        {\r
+            dCtx.mCurentIndex = mSourceIdx;\r
+            dCtx.mCurrentLine = mSourceLine;\r
+        }\r
+\r
+        public virtual JsVariant Execute(JsFunctionContext ctx, HtmlElement rootElement)\r
+        {  \r
+            DebugContext dCtx = ctx.getDbgCtx();\r
+            if (dCtx != null)\r
+            {\r
+                dCtx.mCurrentLine = mSourceLine;\r
+                dCtx.mCurentIndex = mSourceIdx;\r
+            }\r
+            return null;\r
+        }\r
+\r
+        public virtual JsVariant Execute(JsFunctionContext ctx, HtmlElement rootElement, JsVariant assignVal){return null;}\r
+\r
+        protected static bool rearangeInstructions(List<JsVariant> instructions)\r
+        {\r
+            JsFunction func;\r
+            int maxPriority = -1;\r
+            int maxIdx = -1;\r
+            int count = instructions.Count;\r
+            for (int i = 0; i < count; i++)\r
+            {\r
+                func = instructions[i] as JsFunction;\r
+                if (func == null)\r
+                    continue;\r
+                if (func.IsArranged())\r
+                    continue;\r
+\r
+                int priority = func.getPriority();\r
+                if (maxPriority < priority)\r
+                {\r
+                    maxPriority = priority;\r
+                    maxIdx = i;\r
+                }\r
+            }\r
+            if (maxIdx < 0)\r
+                return true;\r
+            func = instructions[maxIdx] as JsFunction;\r
+            if (func == null)\r
+                return false;\r
+            if (!func.rearegeSquence(instructions, maxIdx))\r
+                return false;\r
+\r
+            return rearangeInstructions(instructions);\r
+        }\r
+\r
+    }\r
+\r
+    class JsEmptyFunction : JsFunction\r
+    {\r
+        public JsEmptyFunction(int lineNo, int srcIdx)\r
+            : base(lineNo, srcIdx)\r
+        {\r
+            mArranged = true;\r
+        }\r
+        public override int getPriority()\r
+        {\r
+            return FUNC_PRIORITY_INVALID;\r
+        }\r
+        public override JsVariant Execute(JsFunctionContext ctx, HtmlElement rootElement)\r
+        {\r
+            base.Execute(ctx, rootElement);\r
+            return JsUndefValue.getConstant();\r
+        }\r
+\r
+    }\r
+\r
+    class JsDebuggerFunction : JsFunction\r
+    {\r
+        public JsDebuggerFunction(int lineNo, int srcIdx)\r
+            : base(lineNo, srcIdx)\r
+        {\r
+            mArranged = true;\r
+        }\r
+        public override int getPriority()\r
+        {\r
+            return FUNC_PRIORITY_INVALID;\r
+        }\r
+\r
+    }\r
+\r
+    class JsLoopBreak : JsFunction\r
+    {\r
+        public JsLoopBreak(int lineNo, int srcIdx)\r
+            : base(lineNo, srcIdx)\r
+        {\r
+            mArranged = true;\r
+        }\r
+        public override int getPriority()\r
+        {\r
+            return FUNC_PRIORITY_INVALID;\r
+        }\r
+    }\r
+    class JsLoopContinue : JsFunction\r
+    {\r
+        public JsLoopContinue(int lineNo, int srcIdx)\r
+            : base(lineNo, srcIdx)\r
+        {\r
+            mArranged = true;\r
+        }\r
+        public override int getPriority()\r
+        {\r
+            return FUNC_PRIORITY_INVALID;\r
+        }\r
+    }\r
+\r
+\r
+    partial class JsRootFunction : JsFunction\r
+    {\r
+\r
+        public JsRootFunction(int lineNo, int srcIdx)\r
+            : base(lineNo, srcIdx)\r
+        {\r
+        }\r
+\r
+        public override int getPriority()\r
+        {\r
+            return FUNC_PRIORITY_ROOT;\r
+        }\r
+\r
+\r
+        public bool Parse(DebugContext ctx, string source)\r
+        {\r
+            int startIdx = 0;\r
+            JsTokenStruct sToken;\r
+            int length = source.Length;\r
+            int endIdx;\r
+            int bracket = 0;\r
+            bool inside_if = false;\r
+            bool inside_for = false;\r
+            \r
+            List<JsVariant> instruction = new List<JsVariant>();\r
+\r
+            int state = 0;\r
+\r
+            do\r
+            {\r
+                endIdx = JsParser.getJsToken(ctx, source, startIdx, out sToken);\r
+                if (endIdx < 0)\r
+                    break;\r
+                startIdx = endIdx;\r
+\r
+\r
+                switch (sToken.type)\r
+                {\r
+                    case JsToken.TYPE_ERROR:\r
+                        return false;\r
+                    case JsToken.TYPE_KEYWORD:\r
+                        switch (sToken.keyword)\r
+                        {\r
+                            case JsToken.KEY_VAR:\r
+                                if (state != 0 && state != 9 && state != 11)\r
+                                {\r
+                                    ctx.setCurrentIdx(startIdx);\r
+                                    return false;\r
+                                }\r
+                                state = 1;\r
+                                break;\r
+                            case JsToken.KEY_TRUE:\r
+                                if (state == 9 || state == 4)\r
+                                {\r
+                                    instruction.Add(new JsBooleanValue(true));\r
+                                    state = 5;\r
+                                }\r
+                                else\r
+                                {\r
+                                    ctx.setCurrentIdx(startIdx);\r
+                                    return false;\r
+                                }\r
+                                break;\r
+                            case JsToken.KEY_FALSE:\r
+                                if (state == 9 || state == 4)\r
+                                {\r
+                                    instruction.Add(new JsBooleanValue(false));\r
+                                    state = 5;\r
+                                }\r
+                                else\r
+                                {\r
+                                    ctx.setCurrentIdx(startIdx);\r
+                                    return false;\r
+                                }\r
+                                break;\r
+                            case JsToken.KEY_NULL:\r
+                                if (state == 9 || state == 4)\r
+                                {\r
+                                    instruction.Add(new JsNullValue());\r
+                                    state = 5;\r
+                                }\r
+                                else\r
+                                {\r
+                                    ctx.setCurrentIdx(startIdx);\r
+                                    return false;\r
+                                }\r
+                                break;\r
+                            case JsToken.KEY_UNDEFINED:\r
+                                if (state == 9 || state == 4)\r
+                                {\r
+                                    instruction.Add(new JsUndefValue());\r
+                                    state = 5;\r
+                                }\r
+                                else\r
+                                {\r
+                                    ctx.setCurrentIdx(startIdx);\r
+                                    return false;\r
+                                }\r
+                                break;\r
+                            default:\r
+                                ctx.setCurrentIdx(startIdx);\r
+                                return false;\r
+\r
+                        }\r
+                        break;\r
+                    case JsToken.TYPE_OP_KEYWORD:\r
+                        switch (sToken.keyword)\r
+                        {\r
+                            case JsToken.KEY_OP_FOR:\r
+                                if (state != 0 && state != 11)\r
+                                {\r
+                                    ctx.setCurrentIdx(startIdx);\r
+                                    return false;\r
+                                }\r
+                                if (state == 0 && instruction.Count > 0)\r
+                                {\r
+                                    if (!rearangeInstructions(instruction))\r
+                                    {\r
+                                        ctx.setCurrentIdx(startIdx);\r
+                                        return false;\r
+                                    }\r
+                                    mInstructions.Add(instruction);\r
+                                    instruction = new List<JsVariant>();\r
+                                }\r
+                                instruction.Add(new JsOpFunction_for(ctx.mCurrentLine, startIdx));\r
+                                state = 8;\r
+                                inside_for = true;\r
+                                break;\r
+                            case JsToken.KEY_OP_IF:\r
+                                if (state != 0 && state != 11)\r
+                                {\r
+                                    ctx.setCurrentIdx(startIdx);\r
+                                    return false;\r
+                                }\r
+                                if (state == 0 && instruction.Count > 0)\r
+                                {\r
+                                    if (!rearangeInstructions(instruction))\r
+                                    {\r
+                                        ctx.setCurrentIdx(startIdx);\r
+                                        return false;\r
+                                    }\r
+                                    mInstructions.Add(instruction);\r
+                                    instruction = new List<JsVariant>();\r
+                                }\r
+                                instruction.Add(new JsOpFunction_if(ctx.mCurrentLine, startIdx));\r
+                                state = 8;\r
+                                inside_if = true;\r
+                                break;\r
+                            case JsToken.KEY_OP_ELSE:\r
+                                if (state != 0)\r
+                                {\r
+                                    ctx.setCurrentIdx(startIdx);\r
+                                    return false;\r
+                                }\r
+                                if (instruction.Count > 0)\r
+                                {\r
+                                    if (!rearangeInstructions(instruction))\r
+                                    {\r
+                                        ctx.setCurrentIdx(startIdx);\r
+                                        return false;\r
+                                    } \r
+                                    mInstructions.Add(instruction);\r
+                                    instruction = new List<JsVariant>();\r
+                                }\r
+                                instruction.Add(new JsOpFunction_else(ctx.mCurrentLine, startIdx));\r
+                                mInstructions.Add(instruction);\r
+                                instruction = new List<JsVariant>();\r
+                                state = 11;\r
+                                inside_if = true;\r
+                                break;\r
+                            case JsToken.KEY_OP_LOOP_BREAK:\r
+                                if (state != 0 && state != 11 && state != 15)\r
+                                {\r
+                                    ctx.setCurrentIdx(startIdx);\r
+                                    return false;\r
+                                }\r
+                                if (instruction.Count > 0)\r
+                                {\r
+                                    if (!rearangeInstructions(instruction))\r
+                                    {\r
+                                        ctx.setCurrentIdx(startIdx);\r
+                                        return false;\r
+                                    } \r
+                                    mInstructions.Add(instruction);\r
+                                    instruction = new List<JsVariant>();\r
+                                }\r
+                                instruction.Add(new JsLoopBreak(ctx.mCurrentLine, startIdx));\r
+                                mInstructions.Add(instruction);\r
+                                instruction = new List<JsVariant>();\r
+                                state = 16;\r
+                                break;\r
+                            case JsToken.KEY_OP_LOOP_CONTINUE:\r
+                                if (state != 0 && state != 11 && state != 15)\r
+                                {\r
+                                    ctx.setCurrentIdx(startIdx);\r
+                                    return false;\r
+                                }\r
+                                if (instruction.Count > 0)\r
+                                {\r
+                                    if (!rearangeInstructions(instruction))\r
+                                    {\r
+                                        ctx.setCurrentIdx(startIdx);\r
+                                        return false;\r
+                                    }\r
+                                    mInstructions.Add(instruction);\r
+                                    instruction = new List<JsVariant>();\r
+                                }\r
+                                instruction.Add(new JsLoopContinue(ctx.mCurrentLine, startIdx));\r
+                                mInstructions.Add(instruction);\r
+                                instruction = new List<JsVariant>();\r
+                                state = 16;\r
+                                break;\r
+                            case JsToken.KEY_OP_DEBUGGER:\r
+                                if (state != 0 && state != 11 && state != 15)\r
+                                {\r
+                                    ctx.setCurrentIdx(startIdx);\r
+                                    return false;\r
+                                }\r
+                                if (instruction.Count > 0)\r
+                                {\r
+                                    if (!rearangeInstructions(instruction))\r
+                                    {\r
+                                        ctx.setCurrentIdx(startIdx);\r
+                                        return false;\r
+                                    }\r
+                                    mInstructions.Add(instruction);\r
+                                    instruction = new List<JsVariant>();\r
+                                }\r
+                                instruction.Add(new JsDebuggerFunction(ctx.mCurrentLine, startIdx));\r
+                                mInstructions.Add(instruction);\r
+                                instruction = new List<JsVariant>();\r
+                                state = 16;\r
+                                break;\r
+                            default:\r
+                                ctx.setCurrentIdx(startIdx);\r
+                                return false;\r
+                        }\r
+                        break;\r
+                    case JsToken.TYPE_DOM_KEYWORD:\r
+                        switch (sToken.keyword)\r
+                        {\r
+                            case JsToken.KEY_DOM_DOCUMENT:\r
+                                if (state == 0 || state == 4 || state ==8 || state == 10 || state == 11)\r
+                                {\r
+                                    state = 6;\r
+                                }\r
+                                else\r
+                                {\r
+                                    ctx.setCurrentIdx(startIdx);\r
+                                    return false;\r
+                                }\r
+                                break;\r
+                            case JsToken.KEY_DOM_getElementById:\r
+                                if (state != 7)\r
+                                {\r
+                                    ctx.setCurrentIdx(startIdx);\r
+                                    return false;\r
+                                }\r
+                                instruction.Add(new JsDomFunction(sToken.keyword, ctx.mCurrentLine, startIdx));\r
+                                state = 8;\r
+                                break;\r
+                            case JsToken.KEY_DOM_innerHTML:\r
+                                if (state != 7)\r
+                                {\r
+                                    ctx.setCurrentIdx(startIdx);\r
+                                    return false;\r
+                                }\r
+                                instruction.Add(new JsDomFunction(sToken.keyword, ctx.mCurrentLine, startIdx));\r
+                                state = 2;\r
+                                break;\r
+                            default:\r
+                                ctx.setCurrentIdx(startIdx);\r
+                                return false;\r
+                        }\r
+                        break;\r
+                    case JsToken.TYPE_DOM_STR_KEYWORD:\r
+                        switch (sToken.keyword)\r
+                        {\r
+                            case JsToken.KEY_DOM_STR_indexOf:\r
+                                if (state != 7)\r
+                                {\r
+                                    ctx.setCurrentIdx(startIdx);\r
+                                    return false;\r
+                                }\r
+                                instruction.Add(new JsDomStrFunc_indexOf(ctx.mCurrentLine, startIdx));\r
+                                state = 8;\r
+                                break;\r
+                            case JsToken.KEY_DOM_STR_substring:\r
+                                if (state != 7)\r
+                                {\r
+                                    ctx.setCurrentIdx(startIdx);\r
+                                    return false;\r
+                                }\r
+                                instruction.Add(new JsDomStrFunc_substring(ctx.mCurrentLine, startIdx));\r
+                                state = 8;\r
+                                break;\r
+                            case JsToken.KEY_DOM_STR_replace:\r
+                                if (state != 7)\r
+                                {\r
+                                    ctx.setCurrentIdx(startIdx);\r
+                                    return false;\r
+                                }\r
+                                instruction.Add(new JsDomStrFunc_replace(ctx.mCurrentLine, startIdx));\r
+                                state = 8;\r
+                                break;\r
+                            case JsToken.KEY_DOM_STR_length:\r
+                                if (state != 7)\r
+                                {\r
+                                    ctx.setCurrentIdx(startIdx);\r
+                                    return false;\r
+                                }\r
+                                instruction.Add(new JsDomStrFunc_length(ctx.mCurrentLine, startIdx));\r
+                                state = 5;\r
+                                break;\r
+                            default:\r
+                                ctx.setCurrentIdx(startIdx);\r
+                                return false;\r
+                        }\r
+                        break;\r
+                    case JsToken.TYPE_VARIABLENAME:\r
+                        switch (state)\r
+                        {\r
+                            case 0:\r
+                            case 4:\r
+                            //case 8:\r
+                            case 9:\r
+                            case 10:\r
+                            case 11:\r
+                            case 12:\r
+                            case 13:\r
+                            case 15:\r
+                                instruction.Add(new JsIdentifier(sToken.sValue, false));\r
+                                break;\r
+                            case 1:\r
+                                instruction.Add(new JsIdentifier(sToken.sValue, true));\r
+                                break;\r
+                            default:\r
+                                ctx.setCurrentIdx(startIdx);\r
+                                return false;\r
+                        }\r
+                        state = 2;\r
+                        break;\r
+                    case JsToken.TYPE_PUNCTUATOR:\r
+                        switch (sToken.keyword)\r
+                        {\r
+                            case JsToken.KEY_OP_CMP_LT:\r
+                            case JsToken.KEY_OP_CMP_GT:\r
+                            case JsToken.KEY_OP_CMP_LT_EQUAL:\r
+                            case JsToken.KEY_OP_CMP_GT_EQUAL:\r
+                            case JsToken.KEY_OP_CMP_EQUAL:\r
+                            case JsToken.KEY_OP_CMP_STRICT_EQUAL:\r
+                            case JsToken.KEY_OP_CMP_NOT_EQUAL:\r
+                            case JsToken.KEY_OP_CMP_STRICT_NOT_EQUAL:\r
+                                if ((state != 0 && state != 2 && state != 5) || instruction.Count == 0)\r
+                                {\r
+                                    ctx.setCurrentIdx(startIdx);\r
+                                    return false;\r
+                                }\r
+                                instruction.Add(new JsCmpFunction(ctx.mCurrentLine, startIdx,\r
+                                                            sToken.keyword));\r
+                                state = 10;\r
+                                break;\r
+                            case JsToken.PUNC_L_CURLY_BRACKET:\r
+                                if (state == 4 || state == 5 || state == 6 || state == 7 || state == 8)\r
+                                {\r
+                                    ctx.setCurrentIdx(startIdx);\r
+                                    return false;\r
+                                }\r
+                                else if (!rearangeInstructions(instruction))\r
+                                {\r
+                                    ctx.setCurrentIdx(startIdx);\r
+                                    return false;\r
+                                }\r
+                                if (instruction.Count > 0)\r
+                                {\r
+                                    mInstructions.Add(instruction);\r
+                                    instruction = new List<JsVariant>();\r
+                                }\r
+                                instruction.Add(new JsL_CURLY_Bracket(ctx.mCurrentLine, startIdx));\r
+                                mInstructions.Add(instruction);\r
+                                instruction = new List<JsVariant>();\r
+                                state = 0;\r
+                                break;\r
+                            case JsToken.PUNC_R_CURLY_BRACKET:\r
+                                if (state == 4 || state == 6 || state == 7)\r
+                                {\r
+                                    ctx.setCurrentIdx(startIdx);\r
+                                    return false;\r
+                                }\r
+                                else if (!rearangeInstructions(instruction))\r
+                                {\r
+                                    ctx.setCurrentIdx(startIdx);\r
+                                    return false;\r
+                                }\r
+                                if (instruction.Count > 0)\r
+                                {\r
+                                    mInstructions.Add(instruction);\r
+                                    instruction = new List<JsVariant>();\r
+                                }\r
+                                instruction.Add(new JsR_CURLY_Bracket(ctx.mCurrentLine, startIdx));\r
+                                mInstructions.Add(instruction);\r
+                                instruction = new List<JsVariant>();\r
+                                state = 0;\r
+                                break;\r
+                            case JsToken.PUNC_SEMICOL0N:\r
+                                if (bracket > 0)\r
+                                {\r
+                                    if (state != 2 && state != 5 && state != 9 && state != 15)\r
+                                    {\r
+                                        ctx.setCurrentIdx(startIdx);\r
+                                        return false;\r
+                                    }\r
+                                    instruction.Add(new JsSemiColonFunction(ctx.mCurrentLine, startIdx));\r
+                                    state = 9;\r
+                                }\r
+                                else\r
+                                {\r
+                                    if (state == 4 || state == 6 || state == 7)\r
+                                    {\r
+                                        ctx.setCurrentIdx(startIdx);\r
+                                        return false;\r
+                                    }\r
+                                    else if (!rearangeInstructions(instruction))\r
+                                    {\r
+                                        ctx.setCurrentIdx(startIdx);\r
+                                        return false;\r
+                                    }\r
+                                    if (instruction.Count > 0)\r
+                                    {\r
+                                        mInstructions.Add(instruction);\r
+                                        instruction = new List<JsVariant>();\r
+                                    }\r
+                                    state = 0;\r
+                                }\r
+                                break;\r
+                            case JsToken.PUNC_EQUAL:\r
+                                switch (state)\r
+                                {\r
+                                    case 0:\r
+                                    case 1:\r
+                                    case 5:\r
+                                    case 6:\r
+                                    case 7:\r
+                                    //case 8: document.\r
+                                    case 9:\r
+                                    case 10:\r
+                                        ctx.setCurrentIdx(startIdx);\r
+                                        return false;\r
+                                    case 2:\r
+                                        instruction.Add(new JsLoadFunction(ctx.mCurrentLine, startIdx));\r
+                                        state = 4;\r
+                                        break;\r
+                                }\r
+                                break;\r
+                            case JsToken.PUNC_PERIOD:\r
+                                if (state != 2 && state != 6)\r
+                                {\r
+                                    ctx.setCurrentIdx(startIdx);\r
+                                    return false;\r
+                                }\r
+                                state = 7;\r
+                                break;\r
+                            case JsToken.PUNC_COMMA:\r
+                                if (state != 2 && state != 5)\r
+                                {\r
+                                    ctx.setCurrentIdx(startIdx);\r
+                                    return false;\r
+                                }\r
+                                instruction.Add(new JsCommaFunction(ctx.mCurrentLine, startIdx));\r
+                                state = 9;\r
+                                break;\r
+                            case JsToken.PUNC_L_BRACKET:\r
+                                if (state != 4 && state != 8 && state != 12)\r
+                                {\r
+                                    ctx.setCurrentIdx(startIdx);\r
+                                    return false;\r
+                                }\r
+                                instruction.Add(new JsLBracket(ctx.mCurrentLine, startIdx));\r
+                                bracket++;\r
+                                state = 9;\r
+                                break;\r
+                            case JsToken.PUNC_R_BRACKET:\r
+                                bracket--;\r
+                                if (bracket < 0)\r
+                                {\r
+                                    ctx.setCurrentIdx(startIdx);\r
+                                    return false;\r
+                                }\r
+                                if (state == 4)\r
+                                {\r
+                                    ctx.setCurrentIdx(startIdx);\r
+                                    return false;\r
+                                }\r
+                                instruction.Add(new JsRBracket(ctx.mCurrentLine, startIdx));\r
+                                if ((inside_if || inside_for) && bracket == 0)\r
+                                {\r
+                                    if (!rearangeInstructions(instruction))\r
+                                    {\r
+                                        ctx.setCurrentIdx(startIdx);\r
+                                        return false;\r
+                                    }\r
+                                    mInstructions.Add(instruction);\r
+                                    instruction = new List<JsVariant>();\r
+                                    inside_if = false;\r
+                                    inside_for = false;\r
+                                }\r
+                                state = 15;\r
+                                break;\r
+                            case JsToken.PUNC_INC:\r
+                                switch (state)\r
+                                {\r
+                                    case 0:\r
+                                    case 4:\r
+                                    case 9:\r
+                                    case 10:\r
+                                    case 12:\r
+                                        instruction.Add(new JsIncrementFunction(ctx.mCurrentLine, startIdx));\r
+                                        state = 14;\r
+                                        break;\r
+                                    case 2:\r
+                                        instruction.Add(new JsIncrementFunction(ctx.mCurrentLine, startIdx));\r
+                                        state = 2;\r
+                                        break;\r
+                                    default:\r
+                                        ctx.setCurrentIdx(startIdx);\r
+                                        return false;\r
+                                }\r
+                                break;\r
+                            case JsToken.PUNC_DEC:\r
+                                switch (state)\r
+                                {\r
+                                    case 0:\r
+                                    case 4:\r
+                                    case 9:\r
+                                    case 10:\r
+                                    case 12:\r
+                                        instruction.Add(new JsDecrementFunction(ctx.mCurrentLine, startIdx));\r
+                                        state = 14;\r
+                                        break;\r
+                                    case 2:\r
+                                        instruction.Add(new JsDecrementFunction(ctx.mCurrentLine, startIdx));\r
+                                        state = 2;\r
+                                        break;\r
+                                    default:\r
+                                        ctx.setCurrentIdx(startIdx);\r
+                                        return false;\r
+                                }\r
+                                break;\r
+                            case JsToken.PUNC_OP_NOT:\r
+                                switch (state)\r
+                                {\r
+                                    case 0:\r
+                                    case 4:\r
+                                    case 9:\r
+                                    case 10:\r
+                                    case 12:\r
+                                        instruction.Add(new JsNotFunction(ctx.mCurrentLine, startIdx));\r
+                                        state = 14;\r
+                                        break;\r
+                                    default:\r
+                                        ctx.setCurrentIdx(startIdx);\r
+                                        return false;\r
+                                }\r
+                                break;\r
+                            case JsToken.PUNC_ADD:\r
+                                switch (state)\r
+                                {\r
+                                    case 0:\r
+                                    case 4:\r
+                                    case 9:\r
+                                    case 10:\r
+                                    case 12:\r
+                                        instruction.Add(new JsPlusFunction(ctx.mCurrentLine, startIdx));\r
+                                        state = 13;\r
+                                        break;\r
+                                    case 2:\r
+                                    case 5:\r
+                                    case 15:\r
+                                        instruction.Add(new JsAddFunction(ctx.mCurrentLine, startIdx));\r
+                                        state = 12;\r
+                                        break;\r
+                                    default:\r
+                                        ctx.setCurrentIdx(startIdx);\r
+                                        return false;\r
+                                }\r
+                                break;\r
+                            case JsToken.PUNC_SUB:\r
+                                switch (state)\r
+                                {\r
+                                    case 0:\r
+                                    case 4:\r
+                                    case 9:\r
+                                    case 10:\r
+                                    case 12:\r
+                                        instruction.Add(new JsMinusFunction(ctx.mCurrentLine, startIdx));\r
+                                        state = 13;\r
+                                        break;\r
+                                    case 2:\r
+                                    case 5:\r
+                                    case 15:\r
+                                        instruction.Add(new JsSubFunction(ctx.mCurrentLine, startIdx));\r
+                                        state = 12;\r
+                                        break;\r
+                                    default:\r
+                                        ctx.setCurrentIdx(startIdx);\r
+                                        return false;\r
+                                }\r
+                                break;\r
+                            case JsToken.PUNC_MUL:\r
+                                switch (state)\r
+                                {\r
+                                    case 2:\r
+                                    case 5:\r
+                                    case 15:\r
+                                        instruction.Add(new JsMultipleFunction(ctx.mCurrentLine, startIdx));\r
+                                        state = 12;\r
+                                        break;\r
+                                    default:\r
+                                        ctx.setCurrentIdx(startIdx);\r
+                                        return false;\r
+                                }\r
+                                break;\r
+                            case JsToken.PUNC_DIV:\r
+                                switch (state)\r
+                                {\r
+                                    case 2:\r
+                                    case 5:\r
+                                    case 15:\r
+                                        instruction.Add(new JsDivideFunction(ctx.mCurrentLine, startIdx));\r
+                                        state = 12;\r
+                                        break;\r
+                                    default:\r
+                                        ctx.setCurrentIdx(startIdx);\r
+                                        return false;\r
+                                }\r
+                                break;\r
+                        }\r
+                        break;\r
+                    case JsToken.TYPE_NUMBER_LITERAL:\r
+                        switch (state)\r
+                        {\r
+                            case 4:\r
+                            case 9:\r
+                            case 10:\r
+                            case 12:\r
+                            case 13:\r
+                                instruction.Add(new JsNumberValue(sToken.dValue));\r
+                                state = 5;\r
+                                break;\r
+                            default:\r
+                                ctx.setCurrentIdx(startIdx);\r
+                                return false;\r
+                        }\r
+                        break;\r
+                    case JsToken.TYPE_STRING_LITERAL:\r
+                        switch (state)\r
+                        {\r
+                            case 4:\r
+                            case 9:\r
+                            case 10:\r
+                            case 12:\r
+                            case 13:\r
+                                instruction.Add(new JsStringValue(sToken.sValue));\r
+                                state = 5;\r
+                                break;\r
+                            default:\r
+                                ctx.setCurrentIdx(startIdx);\r
+                                return false;\r
+                        }\r
+                        break;\r
+                    case JsToken.TYPE_END_SRC:\r
+                        endIdx = length; \r
+                        break;\r
+                }\r
+            } while (length > endIdx);\r
+\r
+\r
+            switch (state)\r
+            {\r
+                case 1:\r
+                case 4:\r
+                case 6:\r
+                case 7:\r
+                case 8:\r
+                case 9:\r
+                case 10:\r
+                case 11:\r
+                    ctx.setCurrentIdx(startIdx);\r
+                    return false;\r
+            }\r
+            if (bracket > 0)\r
+            {\r
+                ctx.setCurrentIdx(startIdx);\r
+                return false;\r
+            }\r
+            if (instruction.Count > 0)\r
+            {\r
+                if (!rearangeInstructions(instruction))\r
+                {\r
+                    ctx.setCurrentIdx(startIdx);\r
+                    return false;\r
+                }\r
+                mInstructions.Add(instruction);\r
+            }\r
+            return true;\r
+        }\r
+\r
+        public int getInstaructionCount()\r
+        {\r
+            return mInstructions.Count;\r
+        }\r
+\r
+\r
+    }\r
\r
+\r
+}\r
diff --git a/NT2chCtrl45/html/js/JsFunctionContext.cs b/NT2chCtrl45/html/js/JsFunctionContext.cs
new file mode 100755 (executable)
index 0000000..3b8493b
--- /dev/null
@@ -0,0 +1,131 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading.Tasks;\r
+\r
+namespace NT2chCtrl.html.js\r
+{\r
+    public class JsFunctionContext\r
+    {\r
+        protected static Dictionary<string, JsVariant>\r
+            mGlobalVariables = new Dictionary<string, JsVariant>();\r
+        protected Dictionary<string, JsVariant>\r
+            mLocalVariables = new Dictionary<string, JsVariant>();\r
+\r
+        private DebugContext mDbgCtx;\r
+        public void setDbgCtx(DebugContext dbgCtx)\r
+        {\r
+            mDbgCtx = dbgCtx;\r
+        }\r
+        public DebugContext getDbgCtx() { return mDbgCtx; }\r
+\r
+        public JsFunctionContext(DebugContext dCtx)\r
+        {\r
+            setDbgCtx(dCtx);\r
+        }\r
+\r
+        public bool getMemoryList(out List<DebugMemory> list)\r
+        {\r
+            list = new List<DebugMemory>();\r
+            foreach (string key in mGlobalVariables.Keys)\r
+            {\r
+                JsVariant var;\r
+                if (mGlobalVariables.TryGetValue(key, out var))\r
+                {\r
+                    list.Add(DebugMemory.createInstance(key, var, false));\r
+                }\r
+            }\r
+            foreach (string key in mLocalVariables.Keys)\r
+            {\r
+                JsVariant var;\r
+                if (mLocalVariables.TryGetValue(key, out var))\r
+                {\r
+                    list.Add(DebugMemory.createInstance(key, var, true));\r
+                }\r
+            }\r
+\r
+            return true;\r
+        }\r
+        public JsFunctionContext() { }\r
+\r
+        public JsVariant getValue(JsIdentifier id)\r
+        {\r
+            return getValue(id.getName(), id.isLocal());\r
+        }\r
+\r
+        public JsVariant getValue(string name, bool local)\r
+        {\r
+            JsVariant value;\r
+            if (mLocalVariables.TryGetValue(name, out value))\r
+            {\r
+                return value;\r
+            }\r
+\r
+            if (local)\r
+            {\r
+                value = new JsUndefValue();\r
+                mLocalVariables.Add(name, value);\r
+                return value;\r
+            }\r
+            if (mGlobalVariables.TryGetValue(name, out value))\r
+            {\r
+                return value;\r
+            }\r
+            value = new JsUndefValue();\r
+            mGlobalVariables.Add(name, value);\r
+            return value;\r
+        }\r
+        public void setValue(JsIdentifier id, JsVariant value)\r
+        {\r
+            setValue(id.getName(), id.isLocal(), value);\r
+        }\r
+\r
+        public void setValue(string name, bool local, JsVariant inValue)\r
+        {\r
+            if (mLocalVariables.ContainsKey(name))\r
+            {\r
+                mLocalVariables.Remove(name);\r
+                mLocalVariables.Add(name, inValue);\r
+                return;\r
+            }\r
+            if (local)\r
+            {\r
+                mLocalVariables.Add(name, inValue);\r
+                return;\r
+            }\r
+            if (mGlobalVariables.ContainsKey(name))\r
+            {\r
+                mGlobalVariables.Remove(name);\r
+                mGlobalVariables.Add(name, inValue);\r
+                return;\r
+            }\r
+            mGlobalVariables.Add(name, inValue);\r
+        }\r
+\r
+        public JsVariant getParamValue(HtmlElement elem, JsVariant val)\r
+        {\r
+            if (val == null)\r
+                return null;\r
+            JsFunction func = val as JsFunction;\r
+            if (func != null)\r
+            {\r
+                val = func.Execute(this, elem);\r
+                if (val == null)\r
+                    return null;\r
+            }\r
+            JsIdentifier id = val as JsIdentifier;\r
+            if (id != null)\r
+            {\r
+                val = getValue(id);\r
+            }\r
+            func = val as JsFunction;\r
+            if (func != null)\r
+            {\r
+                return getParamValue(elem, val);\r
+            }\r
+            return val;\r
+\r
+        }\r
+    }\r
+}\r
diff --git a/NT2chCtrl45/html/js/JsOpFunction.cs b/NT2chCtrl45/html/js/JsOpFunction.cs
new file mode 100755 (executable)
index 0000000..2ffd704
--- /dev/null
@@ -0,0 +1,325 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading.Tasks;\r
+\r
+namespace NT2chCtrl.html.js\r
+{\r
+    class JsLoadFunction : JsFunction\r
+    {\r
+        JsVariant mRetVal;\r
+        JsVariant mLoadVal;\r
+\r
+        public JsLoadFunction(int lineNo, int srcIdx)\r
+            : base(lineNo, srcIdx)\r
+        {\r
+        }\r
+        public override int getPriority()\r
+        {\r
+            return FUNC_PRIORITY_LOAD;\r
+        }\r
+\r
+        public override bool rearegeSquence(List<JsVariant> insList, int currIdx)\r
+        {\r
+            int count = insList.Count;\r
+            if (count < 3 || count <= (currIdx + 1))\r
+                return false;\r
+\r
+            mLoadVal = insList[currIdx + 1];\r
+            mRetVal = insList[currIdx - 1];\r
+            insList.RemoveAt(currIdx + 1);\r
+            insList.RemoveAt(currIdx - 1);\r
+            mArranged = true;\r
+            return true;\r
+        }\r
+\r
+\r
+        public override JsVariant Execute(JsFunctionContext ctx, HtmlElement rootElement)\r
+        {\r
+            //if (ctx == null)\r
+            //    ctx = new JsFunctionContext();\r
+            DebugContext dCtx = ctx.getDbgCtx();\r
+            base.Execute(ctx, rootElement);\r
+            /*if (dCtx != null)\r
+            {\r
+                dCtx.mCurrentLine = mSourceLine;\r
+                dCtx.mCurentIndex = mSourceIdx;\r
+            }*/\r
+\r
+            JsVariant loadVal = mLoadVal;\r
+            JsFunction func = mLoadVal as JsFunction;\r
+            if (func != null)\r
+            {\r
+                loadVal = func.Execute(ctx, rootElement);\r
+                if (loadVal == null)\r
+                    return null;\r
+            }\r
+            JsIdentifier idVal2 = loadVal as JsIdentifier;\r
+            if (idVal2 != null)\r
+            {\r
+                loadVal = ctx.getValue(idVal2);\r
+            }\r
+            if(loadVal is JsFunction)\r
+                return null;\r
+\r
+            JsVariant retVal = mRetVal;\r
+            func = retVal as JsFunction;\r
+            if (func != null)\r
+            {\r
+                if (func.IsAssignable())\r
+                {\r
+                    return func.Execute(ctx, rootElement, loadVal); \r
+                }\r
+                retVal = func.Execute(ctx, rootElement);\r
+            }\r
+            JsIdentifier idVal1 = retVal as JsIdentifier;\r
+            if (idVal1 == null)\r
+                return null;\r
+\r
+            ctx.setValue(idVal1, loadVal);\r
+            return idVal1;\r
+        }\r
+    }\r
+\r
+    class JsLBracket : JsFunction\r
+    {\r
+        public JsLBracket(int lineNo, int srcIdx)\r
+            : base(lineNo, srcIdx)\r
+        {\r
+        }\r
+        public override int getPriority()\r
+        {\r
+            return FUNC_PRIORITY_L_BRACKET;\r
+        }\r
+\r
+        //public override JsVariant Execute(JsFunctionContext ctx, HtmlElement rootElement)\r
+        //{\r
+            //if (ctx == null)\r
+            //    ctx = new JsFunctionContext();\r
+        //    return null;\r
+        //}\r
+    }\r
+    class JsRBracket : JsFunction\r
+    {\r
+        public List<JsVariant> mArgs = null;\r
+\r
+        public JsRBracket(int lineNo, int srcIdx)\r
+            : base(lineNo, srcIdx)\r
+        {\r
+        }\r
+\r
+        public override bool rearegeSquence(List<JsVariant> insList, int currIdx)\r
+        {\r
+            JsLBracket lBracket = null;\r
+            int count = insList.Count;\r
+\r
+            int i = currIdx - 1;\r
+            for (; i >= 0; i--)\r
+            {\r
+                lBracket = insList[i] as JsLBracket;\r
+                if (lBracket != null)\r
+                    break;\r
+            }\r
+            if (lBracket == null)\r
+                return false;\r
+            \r
+            mArgs= insList.GetRange(i + 1, currIdx - i - 1);\r
+            insList.RemoveRange(i, currIdx - i);\r
+\r
+            if (!JsFunction.rearangeInstructions(mArgs))\r
+                return false;\r
+\r
+            mArranged = true;\r
+            return true;\r
+        }\r
+\r
+        public override int getPriority()\r
+        {\r
+            return FUNC_PRIORITY_R_BRACKET;\r
+        }\r
+\r
+        public override JsVariant Execute(JsFunctionContext ctx, HtmlElement rootElement)\r
+        {\r
+            if (mArgs == null || mArgs.Count != 1)\r
+                return null;\r
+\r
+            return ctx.getParamValue(rootElement, mArgs[0]);\r
+        }\r
+    }\r
+\r
+    class JsCommaFunction : JsFunction\r
+    {\r
+        public List<JsVariant> mArgs = new List<JsVariant>();\r
+\r
+        public JsCommaFunction(int lineNo, int srcIdx)\r
+            : base(lineNo, srcIdx)\r
+        {\r
+        }\r
+\r
+        public List<JsVariant> getArgs()\r
+        {\r
+            return mArgs;\r
+        }\r
+\r
+        public override bool rearegeSquence(List<JsVariant> insList, int currIdx)\r
+        {\r
+            mArgs.Clear();\r
+\r
+            int count = insList.Count;\r
+\r
+            List<JsVariant> arg = new List<JsVariant>();\r
+            int startIdx = 0;\r
+            int endIdx = count;\r
+            for (int i = 0; i < count; i++)\r
+            {\r
+                JsFunction func = insList[i] as JsFunction;\r
+                if (func == null)\r
+                    continue;\r
+                if (func.IsArranged())\r
+                    continue;\r
+                if (i < currIdx)\r
+                {\r
+                    if (func.getPriority() > FUNC_PRIORITY_COMMA)\r
+                        startIdx = i + 1;\r
+                }\r
+                else if (i > currIdx)\r
+                {\r
+                    if (func.getPriority() > FUNC_PRIORITY_COMMA)\r
+                    {\r
+                        endIdx = i - 1;\r
+                    }\r
+                }\r
+            }\r
+\r
+            for (int i = startIdx; i < endIdx; i++)\r
+            {\r
+                JsVariant var = insList[i];\r
+                if (var is JsCommaFunction)\r
+                {\r
+                    if (arg.Count == 0)\r
+                        return false;\r
+                    if (!JsFunction.rearangeInstructions(arg))\r
+                        return false;\r
+                    if (arg.Count != 1)\r
+                        return false;\r
+                    mArgs.Add(arg[0]);\r
+                    arg = new List<JsVariant>();\r
+                }\r
+                else\r
+                {\r
+                    arg.Add(var);\r
+                }\r
+            }\r
+            if (arg.Count > 0)\r
+            {\r
+                if (!JsFunction.rearangeInstructions(arg))\r
+                    return false;\r
+                if (arg.Count != 1)\r
+                    return false;\r
+                mArgs.Add(arg[0]);\r
+            }\r
+            if (mArgs.Count < 2)\r
+                return false;\r
+            insList.Clear();\r
+            insList.Add(this);\r
+            mArranged = true;\r
+            return true;\r
+        }\r
+\r
+        public override int getPriority()\r
+        {\r
+            return FUNC_PRIORITY_COMMA;\r
+        }\r
+\r
+        public override JsVariant Execute(JsFunctionContext ctx, HtmlElement rootElement)\r
+        {\r
+            if (mArgs == null)\r
+                return JsUndefValue.getConstant();\r
+            foreach(JsVariant var in mArgs){\r
+                JsFunction func = var as JsFunction;\r
+                if (func == null)\r
+                    continue;\r
+                if(null == func.Execute(ctx, rootElement))\r
+                    return null;;\r
+            }\r
+            return JsUndefValue.getConstant();\r
+        }\r
+    }\r
+    class JsSemiColonFunction : JsFunction\r
+    {\r
+        public List<JsVariant> mArgs = new List<JsVariant>();\r
+\r
+        public JsSemiColonFunction(int lineNo, int srcIdx)\r
+            : base(lineNo, srcIdx)\r
+        {\r
+        }\r
+\r
+        public List<JsVariant> getArgs()\r
+        {\r
+            return mArgs;\r
+        }\r
+\r
+        public override bool rearegeSquence(List<JsVariant> insList, int currIdx)\r
+        {\r
+            mArgs.Clear();\r
+\r
+            int count = insList.Count;\r
+\r
+            List<JsVariant> arg = new List<JsVariant>();\r
+\r
+            for (int i = 0; i < count; i++)\r
+            {\r
+                JsVariant var = insList[i];\r
+                if (var is JsSemiColonFunction)\r
+                {\r
+                    if (arg.Count > 0)\r
+                    {\r
+                        if (!JsFunction.rearangeInstructions(arg))\r
+                            return false;\r
+                        if (arg.Count != 1)\r
+                            return false;\r
+                        mArgs.Add(arg[0]);\r
+                        arg = new List<JsVariant>();\r
+                    }\r
+                    else\r
+                    {\r
+                        mArgs.Add(new JsEmptyFunction(mSourceLine, mSourceIdx));\r
+                    }\r
+                }\r
+                else\r
+                {\r
+                    arg.Add(var);\r
+                }\r
+            }\r
+            if (arg.Count > 0)\r
+            {\r
+                if (!JsFunction.rearangeInstructions(arg))\r
+                    return false;\r
+                if (arg.Count != 1)\r
+                    return false;\r
+                mArgs.Add(arg[0]);\r
+            }\r
+            if (mArgs.Count < 2)\r
+                return false;\r
+            insList.Clear();\r
+            insList.Add(this);\r
+            mArranged = true;\r
+            return true;\r
+        }\r
+\r
+        public override int getPriority()\r
+        {\r
+            return FUNC_PRIORITY_SEMICOLON;\r
+        }\r
+\r
+        //public override JsVariant Execute(JsFunctionContext ctx, HtmlElement rootElement)\r
+        //{\r
+        //if (mArgs == null || mArgs.Count != 1)\r
+        //    return null;\r
+\r
+        //return ctx.getParamValue(rootElement, mArgs[0]);\r
+        // }\r
+    }\r
+}\r
+\r
diff --git a/NT2chCtrl45/html/js/JsOpFunction2.cs b/NT2chCtrl45/html/js/JsOpFunction2.cs
new file mode 100755 (executable)
index 0000000..e53089f
--- /dev/null
@@ -0,0 +1,201 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading.Tasks;\r
+\r
+namespace NT2chCtrl.html.js\r
+{\r
+    class JsOpFunction_for : JsFunction\r
+    {\r
+\r
+        JsFunction mInitializeFunc;\r
+        JsFunction mEvaluateFunc;\r
+        JsFunction mRepeatFunc;\r
+\r
+        public JsVariant initialize(JsFunctionContext fCtx, HtmlElement hElem)\r
+        {\r
+            return mInitializeFunc.Execute(fCtx, hElem);\r
+        }\r
+        public JsVariant evaluate(JsFunctionContext fCtx, HtmlElement hElem)\r
+        {\r
+            return mEvaluateFunc.Execute(fCtx, hElem);\r
+        }\r
+        public JsVariant repeat(JsFunctionContext fCtx, HtmlElement hElem)\r
+        {\r
+            return mRepeatFunc.Execute(fCtx, hElem);\r
+        }\r
+\r
+\r
+        public JsOpFunction_for(int lineNo, int srcIdx)\r
+            : base(lineNo, srcIdx)\r
+        {\r
+        }\r
+\r
+        public override bool rearegeSquence(List<JsVariant> insList, int currIdx)\r
+        {\r
+            List<JsVariant> para;\r
+            JsRBracket rBraket = null;\r
+            int count = insList.Count;\r
+\r
+            if (currIdx + 1 >= count)\r
+                return false;\r
+            rBraket = insList[currIdx + 1] as JsRBracket;\r
+            if (rBraket == null)\r
+                return false;\r
+\r
+            para = rBraket.mArgs;\r
+            if (para.Count != 1)\r
+                return false;\r
+\r
+            JsSemiColonFunction semicolon = para[0] as JsSemiColonFunction;\r
+            if (semicolon == null)\r
+                return false;\r
+\r
+            List<JsVariant> args = semicolon.mArgs;\r
+\r
+            if(args.Count != 3)\r
+                return false;\r
+\r
+            mInitializeFunc = args[0] as JsFunction;\r
+            mEvaluateFunc = args[1] as JsFunction;\r
+            mRepeatFunc = args[2] as JsFunction; \r
+\r
+            insList.RemoveAt(currIdx + 1);\r
+\r
+            mArranged = true;\r
+            return true;\r
+        }\r
+\r
+        public override int getPriority()\r
+        {\r
+            return FUNC_PRIORITY_FUNCTION;\r
+        }\r
+\r
+        public override JsVariant Execute(JsFunctionContext ctx, HtmlElement rootElement)\r
+        {\r
+            DebugContext dCtx = ctx.getDbgCtx();\r
+            if (dCtx != null)\r
+            {\r
+                dCtx.mCurrentLine = mSourceLine;\r
+                dCtx.mCurentIndex = mSourceIdx;\r
+            }\r
+            return null;\r
+            /*\r
+            if (mParams == null || mParams.Count != 1)\r
+                return null;\r
+\r
+\r
+            JsVariant param = ctx.getParamValue(rootElement, mParams[0]);\r
+\r
+            if (param == null)\r
+                return null;\r
+\r
+            return param.getBooleanValue();*/\r
+        }\r
+    }\r
+    class JsOpFunction_if : JsFunction\r
+    {\r
+        public List<JsVariant> mParams = null;\r
+\r
+        public JsOpFunction_if(int lineNo, int srcIdx)\r
+            : base(lineNo, srcIdx)\r
+        {\r
+        }\r
+\r
+        public override bool rearegeSquence(List<JsVariant> insList, int currIdx)\r
+        {\r
+            JsRBracket rBraket = null;\r
+            int count = insList.Count;\r
+\r
+            if (currIdx + 1 >= count)\r
+                return false;\r
+            rBraket = insList[currIdx + 1] as JsRBracket;\r
+            if (rBraket == null)\r
+                return false;\r
+\r
+            mParams = rBraket.mArgs;\r
+            if (mParams.Count != 1)\r
+                return false;\r
+\r
+            insList.RemoveAt(currIdx + 1);\r
+\r
+            mArranged = true;\r
+            return true;\r
+        }\r
+\r
+        public override int getPriority()\r
+        {\r
+            return FUNC_PRIORITY_FUNCTION;\r
+        }\r
+\r
+        public override JsVariant Execute(JsFunctionContext ctx, HtmlElement rootElement)\r
+        {\r
+            DebugContext dCtx = ctx.getDbgCtx();\r
+            if (dCtx != null)\r
+            {\r
+                dCtx.mCurrentLine = mSourceLine;\r
+                dCtx.mCurentIndex = mSourceIdx;\r
+            }\r
+\r
+            if (mParams == null || mParams.Count != 1)\r
+                return null;\r
+\r
+\r
+            JsVariant param = ctx.getParamValue(rootElement, mParams[0]);\r
+\r
+            if (param == null)\r
+                return null;\r
+\r
+            return param.getBooleanValue();\r
+        }\r
+    }\r
+    class JsOpFunction_else : JsFunction\r
+    {\r
+\r
+        public JsOpFunction_else(int lineNo, int srcIdx)\r
+            : base(lineNo, srcIdx)\r
+        {\r
+        }\r
+        public override int getPriority()\r
+        {\r
+            return FUNC_PRIORITY_FUNCTION;\r
+        }\r
+\r
+    }\r
+    class JsL_CURLY_Bracket : JsFunction\r
+    {\r
+\r
+        public JsL_CURLY_Bracket(int lineNo, int srcIdx)\r
+            : base(lineNo, srcIdx)\r
+        {\r
+        }\r
+        public override int getPriority()\r
+        {\r
+            return FUNC_PRIORITY_FUNCTION;\r
+        }\r
+\r
+        public override JsVariant Execute(JsFunctionContext ctx, HtmlElement rootElement)\r
+        {\r
+            return null;\r
+        }\r
+    }\r
+    class JsR_CURLY_Bracket : JsFunction\r
+    {\r
+\r
+        public JsR_CURLY_Bracket(int lineNo, int srcIdx)\r
+            : base(lineNo, srcIdx)\r
+        {\r
+        }\r
+        public override int getPriority()\r
+        {\r
+            return FUNC_PRIORITY_FUNCTION;\r
+        }\r
+\r
+        public override JsVariant Execute(JsFunctionContext ctx, HtmlElement rootElement)\r
+        {\r
+            return null;\r
+        }\r
+    }\r
+\r
+}\r
diff --git a/NT2chCtrl45/html/js/JsOpFunction3.cs b/NT2chCtrl45/html/js/JsOpFunction3.cs
new file mode 100755 (executable)
index 0000000..b150b8f
--- /dev/null
@@ -0,0 +1,307 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading.Tasks;\r
+\r
+namespace NT2chCtrl.html.js\r
+{\r
+    class JsPlusFunction : JsFunction\r
+    {\r
+        JsVariant mOperand;\r
+        public JsPlusFunction(int lineNo, int srcIdx)\r
+            : base(lineNo, srcIdx)\r
+        {\r
+        }\r
+        public override int getPriority()\r
+        {\r
+            return FUNC_PRIORITY_PLUS;\r
+        }\r
+        public override bool rearegeSquence(List<JsVariant> insList, int currIdx)\r
+        {\r
+            int count = insList.Count;\r
+            if (count < 2 || currIdx + 1 >= count)\r
+                return false;\r
+\r
+            mOperand = insList[currIdx + 1];\r
+            insList.RemoveAt(currIdx + 1);\r
+            mArranged = true;\r
+            return true;\r
+        }\r
+        public override JsVariant Execute(JsFunctionContext ctx, HtmlElement rootElement)\r
+        {\r
+            base.Execute(ctx, rootElement);\r
+            JsNumberValue nVal = mOperand.getNumberValue();\r
+            if (nVal == null)\r
+                return null;\r
+            return nVal;\r
+        }\r
+    }\r
+    class JsMinusFunction : JsFunction\r
+    {\r
+        JsVariant mOperand;\r
+        public JsMinusFunction(int lineNo, int srcIdx)\r
+            : base(lineNo, srcIdx)\r
+        {\r
+        }\r
+        public override int getPriority()\r
+        {\r
+            return FUNC_PRIORITY_MINUS;\r
+        }\r
+        public override bool rearegeSquence(List<JsVariant> insList, int currIdx)\r
+        {\r
+            int count = insList.Count;\r
+            if (count < 2 || currIdx + 1 >= count)\r
+                return false;\r
+\r
+            mOperand = insList[currIdx + 1];\r
+            insList.RemoveAt(currIdx + 1);\r
+            mArranged = true;\r
+            return true;\r
+        }\r
+        public override JsVariant Execute(JsFunctionContext ctx, HtmlElement rootElement)\r
+        {\r
+            base.Execute(ctx, rootElement);\r
+            JsNumberValue nVal = mOperand.getNumberValue();\r
+            if (nVal == null)\r
+                return null;\r
+            double d = nVal.getValue();\r
+            return new JsNumberValue(d * -1);\r
+        }\r
+    }\r
+    class JsAddFunction : JsFunction\r
+    {\r
+        JsVariant mLHS;\r
+        JsVariant mRHS;\r
+\r
+        public JsAddFunction(int lineNo, int srcIdx)\r
+            : base(lineNo, srcIdx)\r
+        {\r
+        }\r
+        public override int getPriority()\r
+        {\r
+            return FUNC_PRIORITY_ADD;\r
+        }\r
+        public override bool rearegeSquence(List<JsVariant> insList, int currIdx)\r
+        {\r
+            int count = insList.Count;\r
+            if (count < 3 || currIdx + 1 >= count)\r
+                return false;\r
+\r
+            mLHS = insList[currIdx - 1];\r
+            mRHS = insList[currIdx + 1];\r
+            insList.RemoveAt(currIdx + 1);\r
+            insList.RemoveAt(currIdx - 1);\r
+            mArranged = true;\r
+            return true;\r
+        }\r
+        public override JsVariant Execute(JsFunctionContext ctx, HtmlElement rootElement)\r
+        {\r
+            base.Execute(ctx, rootElement);\r
+\r
+            JsVariant lhs = ctx.getParamValue(rootElement, mLHS);\r
+            JsVariant rhs = ctx.getParamValue(rootElement, mRHS);\r
+\r
+\r
+            if (lhs is JsNumberValue && rhs is JsNumberValue)\r
+            {\r
+                double d1 = ((JsNumberValue)lhs).getValue();\r
+                double d2 = ((JsNumberValue)rhs).getValue();\r
+                return new JsNumberValue(d1+d2);\r
+            }\r
+\r
+            JsStringValue sVal1 = lhs.getStringValue();\r
+            JsStringValue sVal2 = rhs.getStringValue();\r
+            if (sVal1 == null || sVal2 == null)\r
+                return null;\r
+\r
+            return new JsStringValue(sVal1.getValue() + sVal2.getValue());\r
+        }\r
+    }\r
+    class JsSubFunction : JsFunction\r
+    {\r
+        JsVariant mLHS;\r
+        JsVariant mRHS;\r
+\r
+        public JsSubFunction(int lineNo, int srcIdx)\r
+            : base(lineNo, srcIdx)\r
+        {\r
+        }\r
+        public override int getPriority()\r
+        {\r
+            return FUNC_PRIORITY_SUB;\r
+        }\r
+        public override bool rearegeSquence(List<JsVariant> insList, int currIdx)\r
+        {\r
+            int count = insList.Count;\r
+            if (count < 3 || currIdx + 1 >= count)\r
+                return false;\r
+\r
+            mLHS = insList[currIdx - 1];\r
+            mRHS = insList[currIdx + 1];\r
+            insList.RemoveAt(currIdx + 1);\r
+            insList.RemoveAt(currIdx - 1);\r
+            mArranged = true;\r
+            return true;\r
+        }\r
+        public override JsVariant Execute(JsFunctionContext ctx, HtmlElement rootElement)\r
+        {\r
+            base.Execute(ctx, rootElement);\r
+\r
+            JsVariant lhs = ctx.getParamValue(rootElement, mLHS);\r
+            JsVariant rhs = ctx.getParamValue(rootElement, mRHS);\r
+\r
+            if (lhs == null || rhs == null)\r
+            {\r
+                ctx.getDbgCtx().mErrorMessage = JsError.INVALID_NUMBER_TYPE;\r
+                return null;\r
+            }\r
+\r
+            JsNumberValue nVal1 = lhs.getNumberValue();\r
+            JsNumberValue nVal2 = rhs.getNumberValue();\r
+\r
+            if (nVal1 == null || nVal2 == null)\r
+            {\r
+                ctx.getDbgCtx().mErrorMessage = JsError.INVALID_NUMBER_TYPE;\r
+                return null;\r
+            }\r
+            if (nVal1.IsNaN() || nVal2.IsNaN())\r
+            {\r
+                ctx.getDbgCtx().mErrorMessage = JsError.INVALID_NUMBER;\r
+                return null;\r
+            }\r
+\r
+\r
+\r
+            double d1 = nVal1.getValue();\r
+            double d2 = nVal2.getValue();\r
+            \r
+            return new JsNumberValue(d1 - d2);\r
+        }\r
+    }\r
+    class JsMultipleFunction : JsFunction\r
+    {\r
+        JsVariant mLHS;\r
+        JsVariant mRHS;\r
+        public JsMultipleFunction(int lineNo, int srcIdx)\r
+            : base(lineNo, srcIdx)\r
+        {\r
+        }\r
+        public override int getPriority()\r
+        {\r
+            return FUNC_PRIORITY_MUL;\r
+        }\r
+        public override bool rearegeSquence(List<JsVariant> insList, int currIdx)\r
+        {\r
+            int count = insList.Count;\r
+            if (count < 3 || currIdx + 1 >= count)\r
+                return false;\r
+\r
+            mLHS = insList[currIdx - 1];\r
+            mRHS = insList[currIdx + 1];\r
+            insList.RemoveAt(currIdx + 1);\r
+            insList.RemoveAt(currIdx - 1);\r
+            mArranged = true;\r
+            return true;\r
+        }\r
+        public override JsVariant Execute(JsFunctionContext ctx, HtmlElement rootElement)\r
+        {\r
+            base.Execute(ctx, rootElement);\r
+\r
+            JsVariant lhs = ctx.getParamValue(rootElement, mLHS);\r
+            JsVariant rhs = ctx.getParamValue(rootElement, mRHS);\r
+\r
+            if (lhs == null || rhs == null)\r
+            {\r
+                ctx.getDbgCtx().mErrorMessage = JsError.INVALID_NUMBER_TYPE;\r
+                return null;\r
+            }\r
+\r
+            JsNumberValue nVal1 = lhs.getNumberValue();\r
+            JsNumberValue nVal2 = rhs.getNumberValue();\r
+\r
+            if (nVal1 == null || nVal2 == null)\r
+            {\r
+                ctx.getDbgCtx().mErrorMessage = JsError.INVALID_NUMBER_TYPE;\r
+                return null;\r
+            }\r
+            if (nVal1.IsNaN() || nVal2.IsNaN())\r
+            {\r
+                ctx.getDbgCtx().mErrorMessage = JsError.INVALID_NUMBER;\r
+                return null;\r
+            }\r
+\r
+\r
+\r
+            double d1 = nVal1.getValue();\r
+            double d2 = nVal2.getValue();\r
+\r
+            return new JsNumberValue(d1 * d2);\r
+        }\r
+    }\r
+    class JsDivideFunction : JsFunction\r
+    {\r
+        JsVariant mLHS;\r
+        JsVariant mRHS;\r
+        public JsDivideFunction(int lineNo, int srcIdx)\r
+            : base(lineNo, srcIdx)\r
+        {\r
+        }\r
+        public override int getPriority()\r
+        {\r
+            return FUNC_PRIORITY_DIV;\r
+        }\r
+        public override bool rearegeSquence(List<JsVariant> insList, int currIdx)\r
+        {\r
+            int count = insList.Count;\r
+            if (count < 3 || currIdx + 1 >= count)\r
+                return false;\r
+\r
+            mLHS = insList[currIdx - 1];\r
+            mRHS = insList[currIdx + 1];\r
+            insList.RemoveAt(currIdx + 1);\r
+            insList.RemoveAt(currIdx - 1);\r
+            mArranged = true;\r
+            return true;\r
+        }\r
+        public override JsVariant Execute(JsFunctionContext ctx, HtmlElement rootElement)\r
+        {\r
+            base.Execute(ctx, rootElement);\r
+\r
+            JsVariant lhs = ctx.getParamValue(rootElement, mLHS);\r
+            JsVariant rhs = ctx.getParamValue(rootElement, mRHS);\r
+\r
+            if (lhs == null || rhs == null)\r
+            {\r
+                ctx.getDbgCtx().mErrorMessage = JsError.INVALID_NUMBER_TYPE;\r
+                return null;\r
+            }\r
+\r
+            JsNumberValue nVal1 = lhs.getNumberValue();\r
+            JsNumberValue nVal2 = rhs.getNumberValue();\r
+\r
+            if (nVal1 == null || nVal2 == null)\r
+            {\r
+                ctx.getDbgCtx().mErrorMessage = JsError.INVALID_NUMBER_TYPE;\r
+                return null;\r
+            }\r
+            if (nVal1.IsNaN() || nVal2.IsNaN())\r
+            {\r
+                ctx.getDbgCtx().mErrorMessage = JsError.INVALID_NUMBER;\r
+                return null;\r
+            }\r
+\r
+\r
+\r
+            double d1 = nVal1.getValue();\r
+            double d2 = nVal2.getValue();\r
+            if (d2 == 0)\r
+            {\r
+                ctx.getDbgCtx().mErrorMessage = JsError.DIVIDED_BY_ZERO;\r
+                return null;\r
+            }\r
+\r
+            return new JsNumberValue(d1 / d2);\r
+        }\r
+    }\r
+}\r
diff --git a/NT2chCtrl45/html/js/JsOpFunction4.cs b/NT2chCtrl45/html/js/JsOpFunction4.cs
new file mode 100755 (executable)
index 0000000..1151c23
--- /dev/null
@@ -0,0 +1,164 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading.Tasks;\r
+\r
+namespace NT2chCtrl.html.js\r
+{\r
+    class JsIncrementFunction : JsFunction\r
+    {\r
+        JsIdentifier mOperand;\r
+        public JsIncrementFunction(int lineNo, int srcIdx)\r
+            : base(lineNo, srcIdx)\r
+        {\r
+        }\r
+        public override int getPriority()\r
+        {\r
+            return FUNC_PRIORITY_INC;\r
+        }\r
+        public override bool rearegeSquence(List<JsVariant> insList, int currIdx)\r
+        {\r
+            JsVariant var;\r
+            int count = insList.Count;\r
+            if (currIdx >= count || count < 2)\r
+                return false;\r
+\r
+            if (currIdx > 0)\r
+            {\r
+                var = insList[currIdx - 1];\r
+                if (var is JsIdentifier)\r
+                {\r
+                    mOperand = (JsIdentifier)var;\r
+                    insList.RemoveAt(currIdx - 1);\r
+                    mArranged = true;\r
+                    return true;\r
+                }\r
+            }\r
+            if (currIdx + 1 < count)\r
+            {\r
+                var = insList[currIdx + 1];\r
+                if (var is JsIdentifier)\r
+                {\r
+                    mOperand = (JsIdentifier)var;\r
+                    insList.RemoveAt(currIdx + 1);\r
+                    mArranged = true;\r
+                    return true;\r
+                }\r
+            }\r
+            return false;\r
+        }\r
+        public override JsVariant Execute(JsFunctionContext ctx, HtmlElement rootElement)\r
+        {\r
+            base.Execute(ctx, rootElement);\r
+\r
+            JsNumberValue nVal = ctx.getParamValue(rootElement, mOperand) as JsNumberValue;\r
+            if (nVal == null)\r
+            {\r
+                ctx.getDbgCtx().mErrorMessage = JsError.INVALID_OPERAND_TYPE;\r
+                return null;\r
+            }\r
+            ctx.setValue(mOperand, new JsNumberValue(nVal.getValue() + 1));\r
+\r
+            return mOperand;\r
+        }\r
+    }\r
+    class JsDecrementFunction : JsFunction\r
+    {\r
+        JsIdentifier mOperand;\r
+        public JsDecrementFunction(int lineNo, int srcIdx)\r
+            : base(lineNo, srcIdx)\r
+        {\r
+        }\r
+        public override int getPriority()\r
+        {\r
+            return FUNC_PRIORITY_DEC;\r
+        }\r
+        public override bool rearegeSquence(List<JsVariant> insList, int currIdx)\r
+        {\r
+            JsVariant var;\r
+            int count = insList.Count;\r
+            if (currIdx >= count || count < 2)\r
+                return false;\r
+\r
+            if (currIdx > 0)\r
+            {\r
+                var = insList[currIdx - 1];\r
+                if (var is JsIdentifier)\r
+                {\r
+                    mOperand = (JsIdentifier)var;\r
+                    insList.RemoveAt(currIdx - 1);\r
+                    mArranged = true;\r
+                    return true;\r
+                }\r
+            }\r
+            if (currIdx + 1 < count)\r
+            {\r
+                var = insList[currIdx + 1];\r
+                if (var is JsIdentifier)\r
+                {\r
+                    mOperand = (JsIdentifier)var;\r
+                    insList.RemoveAt(currIdx + 1);\r
+                    mArranged = true;\r
+                    return true;\r
+                }\r
+            }\r
+            return false;\r
+        }\r
+        public override JsVariant Execute(JsFunctionContext ctx, HtmlElement rootElement)\r
+        {\r
+            base.Execute(ctx, rootElement);\r
+\r
+            JsNumberValue nVal = ctx.getParamValue(rootElement, mOperand) as JsNumberValue;\r
+            if (nVal == null)\r
+            {\r
+                ctx.getDbgCtx().mErrorMessage = JsError.INVALID_OPERAND_TYPE;\r
+                return null;\r
+            }\r
+            ctx.setValue(mOperand, new JsNumberValue(nVal.getValue() - 1));\r
+\r
+            return mOperand;\r
+        }\r
+    }\r
+    class JsNotFunction : JsFunction\r
+    {\r
+        JsVariant mOperand;\r
+        public JsNotFunction(int lineNo, int srcIdx)\r
+            : base(lineNo, srcIdx)\r
+        {\r
+        }\r
+        public override int getPriority()\r
+        {\r
+            return FUNC_PRIORITY_NOT;\r
+        }\r
+        public override bool rearegeSquence(List<JsVariant> insList, int currIdx)\r
+        {\r
+            JsVariant var;\r
+            int count = insList.Count;\r
+            if (currIdx >= count || count < 2)\r
+                return false;\r
+\r
+            if (currIdx + 1 < count)\r
+            {\r
+                var = insList[currIdx + 1];\r
+                mOperand = var;\r
+                insList.RemoveAt(currIdx + 1);\r
+                mArranged = true;\r
+                return true;\r
+\r
+            }\r
+            return false;\r
+        }\r
+        public override JsVariant Execute(JsFunctionContext ctx, HtmlElement rootElement)\r
+        {\r
+            base.Execute(ctx, rootElement);\r
+            JsVariant var = ctx.getParamValue(rootElement, mOperand);\r
+            if (var == null)\r
+                return null;\r
+            JsBooleanValue bVal = var.getBooleanValue();\r
+            if (bVal == null)\r
+                return null;\r
+            return JsBooleanValue.getConstantValue(!bVal.getValue());\r
+        }\r
+    }\r
+}\r
diff --git a/NT2chCtrl45/html/js/JsParser.cs b/NT2chCtrl45/html/js/JsParser.cs
new file mode 100755 (executable)
index 0000000..418bbdd
--- /dev/null
@@ -0,0 +1,48 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+\r
+namespace NT2chCtrl.html.js\r
+{\r
+    partial class JsParser\r
+    {\r
+        //List<JsFunction> mBodyLvlFunc = new List<JsFunction>();\r
+        List<JsRootFunction> mFuncList = new List<JsRootFunction>();\r
+        //HtmlElement mRootElement;\r
+        public bool PreCompile(DebugContext ctx , HtmlElement jsElem)\r
+        {\r
+            string[] contents = jsElem.getStringContent();\r
+            if (contents == null || contents.Length != 1)\r
+                return false;\r
+\r
+            JsRootFunction rootFunc = new JsRootFunction(ctx.mCurrentLine, 0);\r
+            if (rootFunc.Parse(ctx, contents[0]))\r
+            {\r
+                mFuncList.Add(rootFunc);\r
+                return true;\r
+            }\r
+            else\r
+            {\r
+                return false;\r
+            }\r
+        }\r
+\r
+        public bool run(DebugContext dCtx, HtmlElement rootElement, out JsFunctionContext fCtx)\r
+        {\r
+            fCtx = null;\r
+            if (mFuncList.Count == 0)\r
+                return true;\r
+\r
+            foreach (JsRootFunction func in mFuncList)\r
+            {\r
+                fCtx = new JsFunctionContext(dCtx);\r
+                if (func.getInstaructionCount() > 0 && \r
+                    null == func.Execute(fCtx, rootElement))\r
+                {\r
+                    return false;\r
+                }\r
+            }\r
+            return true;\r
+        }\r
+    }\r
+}\r
diff --git a/NT2chCtrl45/html/js/JsRootFunction.cs b/NT2chCtrl45/html/js/JsRootFunction.cs
new file mode 100755 (executable)
index 0000000..6417cd8
--- /dev/null
@@ -0,0 +1,528 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading.Tasks;\r
+\r
+namespace NT2chCtrl.html.js\r
+{\r
+    enum LOOP_EXIT_TYPE\r
+    {\r
+        BREAK, CONTINUE,NONE\r
+    }\r
+\r
+    partial class JsRootFunction : JsFunction\r
+    {\r
+        public override JsVariant Execute(JsFunctionContext ctx, HtmlElement rootElement)\r
+        {\r
+            LOOP_EXIT_TYPE exitType;\r
+            int nVal;\r
+\r
+            //DebugContext dCtx = ctx.getDbgCtx();\r
+            JsVariant result = null;\r
+            if (ctx == null)\r
+                ctx = new JsFunctionContext();\r
+\r
+            int iCount = mInstructions.Count;\r
+            for (int i = 0; i < iCount; i++)\r
+            {\r
+                List<JsVariant> list = mInstructions[i];\r
+\r
+                int count = list.Count;\r
+                for (int j = 0; j < count; j++)\r
+                {\r
+                    JsVariant var = list[j];\r
+\r
+                    JsIdentifier idVal = var as JsIdentifier;\r
+                    if (idVal != null)\r
+                    {\r
+                        ctx.setValue(idVal, new JsUndefValue());\r
+                        continue;\r
+                    }\r
+                    JsFunction func = var as JsFunction;\r
+                    if (func == null)\r
+                        continue;\r
+                    //JsOpFunction_else funcelse = func as JsOpFunction_else;\r
+\r
+\r
+                    JsOpFunction_if funcIf = func as JsOpFunction_if;\r
+                    JsOpFunction_for funcFor = func as JsOpFunction_for;\r
+                    if (funcIf != null)\r
+                    {\r
+                        result = Execute_if(ctx, rootElement, mInstructions, i, j, out nVal, out exitType);\r
+                        if (result == null || exitType != LOOP_EXIT_TYPE.NONE)\r
+                            goto LOOP_END;\r
+                        i = nVal;\r
+                        break;\r
+                    }\r
+                    else if (funcFor != null)\r
+                    {\r
+                        result = Execute_for(ctx, rootElement, mInstructions, i, j, out nVal);\r
+                        if (result == null)\r
+                            goto LOOP_END;\r
+                        i = nVal;\r
+                        break;\r
+                    }\r
+                    else\r
+                    {\r
+                        result = func.Execute(ctx, rootElement);\r
+                    }\r
+                    if (result == null)\r
+                    {\r
+                        goto LOOP_END;\r
+                    }\r
+                }\r
+            }\r
+        LOOP_END:\r
+            return result;\r
+        }\r
+\r
+        private JsVariant Execute_if(JsFunctionContext ctx, HtmlElement rootElement,\r
+            List<List<JsVariant>> instructions, int curIdx, int j, out int endIdx, out  LOOP_EXIT_TYPE exitType)\r
+        {\r
+            exitType = LOOP_EXIT_TYPE.NONE;\r
+            // int trueCount = 0;\r
+            bool firstTrue = false;\r
+            bool TrueFinish = false;\r
+            DebugContext dCtx = ctx.getDbgCtx();\r
+            //bool bExec = false;\r
+            JsOpFunction_else funcelse;\r
+            endIdx = 0;\r
+            JsOpFunction_if funcIf = instructions[curIdx][j] as JsOpFunction_if;\r
+            if (funcIf == null)\r
+                return null;\r
+            funcIf.setDebugContext(dCtx);\r
+            JsBooleanValue bVal = funcIf.Execute(ctx, rootElement) as JsBooleanValue;\r
+            if (bVal == null)\r
+                return null;\r
+            if (bVal.getValue())\r
+                firstTrue = true;\r
+\r
+            bool finalElse = false;\r
+\r
+            int length = instructions.Count;\r
+            int state = 0;\r
+            for (int i = curIdx + 1; i < length; i++)\r
+            {\r
+                List<JsVariant> val1 = instructions[i];\r
+                if (val1.Count == 0)\r
+                    continue;\r
+\r
+                JsVariant val = val1[0];\r
+\r
+                if (state == 2)\r
+                {\r
+                    if (finalElse)\r
+                        return null;\r
+                    funcelse = val as JsOpFunction_else;\r
+                    if (funcelse == null)\r
+                    {\r
+                        return JsUndefValue.getConstant();\r
+                    }\r
+                    funcelse.setDebugContext(dCtx);\r
+                    state = 3;\r
+                    /*if (firstTrue)\r
+                    {\r
+                        TrueFinish = true;\r
+                    }\r
+                    else\r
+                    {\r
+                        firstTrue = true;\r
+                    }*/\r
+                    continue;\r
+                }\r
+\r
+                if (val is JsOpFunction_if)\r
+                {\r
+                    if (firstTrue)\r
+                    {\r
+                        TrueFinish = true;\r
+                    }\r
+                    switch (state)\r
+                    {\r
+                        case 0:\r
+                            if (null == Execute_if(ctx, rootElement,\r
+                                instructions, i, 0, out endIdx, out exitType))\r
+                                return null;\r
+                            if (exitType != LOOP_EXIT_TYPE.NONE)\r
+                            {\r
+                                TrueFinish = true;\r
+                            }\r
+                            i = endIdx;\r
+                            state = 2;\r
+                            break;\r
+                        case 1:\r
+                            if (null == Execute_if(ctx, rootElement,\r
+                                instructions, i, 0, out endIdx, out exitType))\r
+                                return null;\r
+                            if (exitType != LOOP_EXIT_TYPE.NONE)\r
+                            {\r
+                                TrueFinish = true;\r
+                            }\r
+                            i = endIdx;\r
+                            break;\r
+                        case 2:\r
+                            return null;\r
+                        case 3:\r
+                            funcIf = val as JsOpFunction_if;\r
+                            if (funcIf == null)\r
+                                return null;\r
+                            funcIf.setDebugContext(dCtx);\r
+                            if (!TrueFinish)\r
+                            {\r
+                                bVal = funcIf.Execute(ctx, rootElement) as JsBooleanValue;\r
+                                if (bVal.getValue())\r
+                                    firstTrue = true;\r
+                            }\r
+                            state = 0;\r
+                            break;\r
+                    }\r
+                }\r
+                else if (val is JsOpFunction_for)\r
+                {\r
+                    switch (state)\r
+                    {\r
+                        case 0:\r
+                            if (null == Execute_for(ctx, rootElement,\r
+                                instructions, i, 0, out endIdx))\r
+                                return null;\r
+                            i = endIdx;\r
+                            state = 2;\r
+                            break;\r
+                        case 1:\r
+                            if (null == Execute_for(ctx, rootElement,\r
+                                instructions, i, 0, out endIdx))\r
+                                return null;\r
+                            i = endIdx;\r
+                            break;\r
+                        default:\r
+                            return null;\r
+                    }\r
+                }\r
+                else if (val is JsLoopBreak)\r
+                {\r
+                    if (state == 0)\r
+                    {\r
+                        if (firstTrue && !TrueFinish)\r
+                        {\r
+                            exitType = LOOP_EXIT_TYPE.BREAK;\r
+                            TrueFinish = true;\r
+                        }\r
+                        state = 2;\r
+                        endIdx = i;\r
+                    }\r
+                    else if (state == 1)\r
+                    {\r
+                        if (firstTrue && !TrueFinish)\r
+                        {\r
+                            exitType = LOOP_EXIT_TYPE.BREAK;\r
+                            TrueFinish = true;\r
+                        }\r
+                    }\r
+                    else if (state == 3)\r
+                    {\r
+                        if (/*firstTrue &&*/ !TrueFinish)\r
+                        {\r
+                            exitType = LOOP_EXIT_TYPE.BREAK;\r
+                        }\r
+                        endIdx = i;\r
+                        return JsUndefValue.getConstant();\r
+                    }\r
+                    else\r
+                    {\r
+                        return null;\r
+                    }\r
+                }\r
+                else if (val is JsLoopContinue)\r
+                {\r
+                    if (state == 0)\r
+                    {\r
+                        if (firstTrue && !TrueFinish)\r
+                        {\r
+                            exitType = LOOP_EXIT_TYPE.CONTINUE;\r
+                            TrueFinish = true;\r
+                        }\r
+                        state = 2;\r
+                        endIdx = i;\r
+                    }\r
+                    else if (state == 1)\r
+                    {\r
+                        if (firstTrue && !TrueFinish)\r
+                        {\r
+                            exitType = LOOP_EXIT_TYPE.CONTINUE;\r
+                            TrueFinish = true;\r
+                        }\r
+                    }\r
+                    else if (state == 3)\r
+                    {\r
+                        if (/*firstTrue &&*/ !TrueFinish)\r
+                        {\r
+                            exitType = LOOP_EXIT_TYPE.CONTINUE;\r
+                        }\r
+                        endIdx = i;\r
+                        return JsUndefValue.getConstant();\r
+                    }\r
+                    else\r
+                    {\r
+                        return null;\r
+                    }\r
+                }\r
+                else if (val is JsL_CURLY_Bracket)\r
+                {\r
+                    ((JsL_CURLY_Bracket)val).setDebugContext(dCtx);\r
+                    if (state != 0 && state != 3)\r
+                        return null;\r
+                    if (state == 3)\r
+                        finalElse = true;\r
+                    state = 1;\r
+                }\r
+                else if (val is JsR_CURLY_Bracket)\r
+                {\r
+                    ((JsR_CURLY_Bracket)val).setDebugContext(dCtx);\r
+                    if (state == 0 && state == 3)\r
+                        return null;\r
+                    endIdx = i;\r
+                    if (finalElse)\r
+                        return JsUndefValue.getConstant();\r
+                    state = 2;\r
+                }\r
+                else if (val is JsFunction)\r
+                {\r
+                    JsFunction func = (JsFunction)val;\r
+                    switch (state)\r
+                    {\r
+                        case 0://if () single line\r
+                            endIdx = i;\r
+                            if (firstTrue && !TrueFinish)\r
+                            {\r
+                                func.Execute(ctx, rootElement);\r
+                            }\r
+                            state = 2;\r
+                            break;\r
+                        //else\r
+                        //    return JsUndefValue.getConstant();\r
+                        case 1://if(){ multi lines}\r
+                            if (finalElse)\r
+                            {\r
+                                if (!firstTrue && !TrueFinish)\r
+                                {\r
+                                    if (null == func.Execute(ctx, rootElement))\r
+                                        return null;\r
+                                }\r
+                            }\r
+                            else if (firstTrue && !TrueFinish)\r
+                            {\r
+                                if (null == func.Execute(ctx, rootElement))\r
+                                    return null;\r
+                            }\r
+                            break;\r
+                        case 2://just after right curly bracket\r
+                            return JsUndefValue.getConstant();\r
+                        case 3:// just after else\r
+                            if (!firstTrue && !TrueFinish)\r
+                            {\r
+                                if (null == func.Execute(ctx, rootElement))\r
+                                    return null;\r
+                            }\r
+                            endIdx = i;\r
+                            return JsUndefValue.getConstant();\r
+                        default:\r
+                            return null;\r
+\r
+                    }\r
+                }\r
+                else\r
+                {\r
+                    return null;\r
+                }\r
+            }\r
+            endIdx = length;\r
+            return JsUndefValue.getConstant();\r
+        }\r
+\r
+        private JsVariant Execute_for(JsFunctionContext ctx, HtmlElement rootElement,\r
+            List<List<JsVariant>> instructions, int curIdx, int j, out int endIdx)\r
+        {\r
+            LOOP_EXIT_TYPE exitType;\r
+            JsBooleanValue bVal;\r
+            bool first = true;\r
+            bool fBreak = false;\r
+            DebugContext dCtx = ctx.getDbgCtx();\r
+            endIdx = curIdx + 1;\r
+\r
+            JsOpFunction_for funcFor = instructions[curIdx][j] as JsOpFunction_for;\r
+            if (funcFor == null)\r
+                return null;\r
+            funcFor.setDebugContext(dCtx);\r
+            if (null == funcFor.initialize(ctx, rootElement))\r
+                return null;\r
+\r
+            int state = 0;\r
+            int length = instructions.Count;\r
+\r
+            while (true)\r
+            {\r
+                if (!first)\r
+                {\r
+                    if (null == funcFor.repeat(ctx, rootElement))\r
+                        return null;\r
+                }\r
+                first = false;\r
+                bVal = funcFor.evaluate(ctx, rootElement) as JsBooleanValue;\r
+                if (bVal == null)\r
+                    return null;\r
+                if (!bVal.getValue())\r
+                    break;\r
+\r
+                state = 0;\r
+                for (int i = curIdx + 1; i < length; i++)\r
+                {\r
+\r
+                    List<JsVariant> val1 = instructions[i];\r
+                    if (val1.Count == 0)\r
+                        continue;\r
+\r
+                    JsVariant val = val1[0];\r
+\r
+                    if (val is JsOpFunction_if)\r
+                    {\r
+                        switch (state)\r
+                        {\r
+                            case 0:\r
+                                if (null == Execute_if(ctx, rootElement,\r
+                                    instructions, i, 0, out endIdx, out exitType))\r
+                                    return null;\r
+                                i = endIdx;\r
+                                state = 2;\r
+                                if (exitType == LOOP_EXIT_TYPE.BREAK)\r
+                                {\r
+                                    fBreak = true;\r
+                                    curIdx = endIdx;\r
+                                    goto LABEL_END_WHILE;\r
+                                }\r
+                                else if (exitType == LOOP_EXIT_TYPE.CONTINUE)\r
+                                {\r
+                                    goto LABEL_END_FOR;\r
+                                }\r
+                                break;\r
+                            case 1:\r
+                                if (null == Execute_if(ctx, rootElement,\r
+                                    instructions, i, 0, out endIdx, out exitType))\r
+                                    return null;\r
+                                i = endIdx;\r
+                                if (exitType == LOOP_EXIT_TYPE.BREAK)\r
+                                {\r
+                                    fBreak = true;\r
+                                    curIdx = endIdx;\r
+                                    goto LABEL_END_WHILE;\r
+                                }\r
+                                else if (exitType == LOOP_EXIT_TYPE.CONTINUE)\r
+                                {\r
+                                    goto LABEL_END_FOR;\r
+                                }\r
+                                break;\r
+                            default:\r
+                                return null;\r
+                        }\r
+                    }\r
+                    else if (val is JsOpFunction_for)\r
+                    {\r
+                        switch (state)\r
+                        {\r
+                            case 0:\r
+                                if (null == Execute_for(ctx, rootElement,\r
+                                    instructions, i, 0, out endIdx))\r
+                                    return null;\r
+                                i = endIdx;\r
+                                state = 2;\r
+                                break;\r
+                            case 1:\r
+                                if (null == Execute_for(ctx, rootElement,\r
+                                    instructions, i, 0, out endIdx))\r
+                                    return null;\r
+                                i = endIdx;\r
+                                break;\r
+                            default:\r
+                                return null;\r
+                        }\r
+                    }\r
+                    else if (val is JsLoopBreak)\r
+                    {\r
+                        fBreak = true;\r
+                        curIdx = i;\r
+                        goto LABEL_END_WHILE;\r
+                    }\r
+                    else if (val is JsLoopContinue)\r
+                    {\r
+                        goto LABEL_END_FOR;\r
+                    }\r
+                    else if (val is JsL_CURLY_Bracket)\r
+                    {\r
+                        ((JsL_CURLY_Bracket)val).setDebugContext(dCtx);\r
+                        if (state != 0)\r
+                            return null;\r
+                        state = 1;\r
+                    }\r
+                    else if (val is JsR_CURLY_Bracket)\r
+                    {\r
+                        ((JsR_CURLY_Bracket)val).setDebugContext(dCtx);\r
+                        if (state == 0)\r
+                            return null;\r
+                        endIdx = i;\r
+                        state = 0;\r
+                        goto LABEL_END_FOR;\r
+                    }\r
+                    else if (val is JsFunction)\r
+                    {\r
+                        JsFunction func = (JsFunction)val;\r
+                        switch (state)\r
+                        {\r
+                            case 0://if () single line\r
+                                if (null == func.Execute(ctx, rootElement))\r
+                                    return null;\r
+                                endIdx = i;\r
+                                goto LABEL_END_FOR;\r
+                            case 1://if(){ multi lines}\r
+                                if (null == func.Execute(ctx, rootElement))\r
+                                    return null;\r
+                                break;\r
+                            default:\r
+                                return null;\r
+                        }\r
+                    }\r
+                    else\r
+                    {\r
+                        return null;\r
+                    }\r
+                }\r
+    LABEL_END_FOR: ;\r
+            }\r
+    LABEL_END_WHILE:\r
+            if (fBreak)\r
+            {\r
+                if (state == 0)\r
+                {\r
+                    endIdx = curIdx + 1;\r
+                }\r
+                else\r
+                {\r
+                    for (int i = curIdx + 1; i < length; i++)\r
+                    {\r
+\r
+                        List<JsVariant> val1 = instructions[i];\r
+                        if (val1.Count == 0)\r
+                            continue;\r
+\r
+                        JsR_CURLY_Bracket rCurrly = val1[0] as JsR_CURLY_Bracket;\r
+                        if (rCurrly != null)\r
+                        {\r
+                            endIdx = i;\r
+                            break;\r
+                        }\r
+                    }\r
+                }\r
+            }\r
+            return JsUndefValue.getConstant();\r
+        }\r
+    }\r
+}\r
diff --git a/NT2chCtrl45/html/js/JsToken.cs b/NT2chCtrl45/html/js/JsToken.cs
new file mode 100755 (executable)
index 0000000..d21b73e
--- /dev/null
@@ -0,0 +1,865 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading.Tasks;\r
+\r
+\r
+namespace NT2chCtrl.html.js\r
+{\r
+    public enum JsToken\r
+    {\r
+        TYPE_ERROR ,\r
+        TYPE_END_SRC,\r
+        TYPE_KEYWORD,\r
+        TYPE_DOM_KEYWORD,\r
+        TYPE_DOM_STR_KEYWORD,\r
+        TYPE_OP_KEYWORD,\r
+        TYPE_NULL,\r
+        TYPE_BOOLEAN,\r
+        TYPE_NUMBER_LITERAL ,\r
+        TYPE_PUNCTUATOR ,\r
+        TYPE_STRING_LITERAL,\r
+        TYPE_VARIABLENAME ,\r
+        TYPE_ARRAY_SUBSCRIPT ,\r
+\r
+\r
+        KEY_NOT_KEY ,\r
+        KEY_NAN ,\r
+        KEY_TRUE,\r
+        KEY_FALSE ,\r
+        KEY_NULL ,\r
+        KEY_THIS,\r
+        KEY_UNDEFINED,\r
+        KEY_FUNCTION,\r
+        KEY_VAR,\r
+\r
+        KEY_DOM_DOCUMENT,\r
+        KEY_DOM_getElementById,\r
+        KEY_DOM_innerHTML,\r
+        KEY_DOM_STR_substring,\r
+        KEY_DOM_STR_substr,\r
+        KEY_DOM_STR_length,\r
+        KEY_DOM_STR_indexOf,\r
+        KEY_DOM_STR_replace,\r
+\r
+        KEY_OP_IF,\r
+        KEY_OP_ELSE,\r
+        KEY_OP_FOR,\r
+        KEY_OP_WHILE,\r
+        KEY_OP_LOOP_BREAK,\r
+        KEY_OP_LOOP_CONTINUE,\r
+        KEY_OP_CMP_LT,\r
+        KEY_OP_CMP_GT,\r
+        KEY_OP_CMP_LT_EQUAL,\r
+        KEY_OP_CMP_GT_EQUAL,\r
+        KEY_OP_CMP_EQUAL,\r
+        KEY_OP_CMP_STRICT_EQUAL,\r
+        KEY_OP_CMP_NOT_EQUAL,\r
+        KEY_OP_CMP_STRICT_NOT_EQUAL,\r
+\r
+        KEY_OP_DEBUGGER,\r
+\r
+\r
+        PUNC_OP_NOT,\r
+        PUNC_NO_PUNC,\r
+        PUNC_EQUAL,\r
+        PUNC_ADD,\r
+        PUNC_SUB,\r
+        PUNC_MUL,\r
+        PUNC_DIV,\r
+        PUNC_INC,\r
+        PUNC_DEC,\r
+        PUNC_SEMICOL0N,\r
+        PUNC_COMMA,\r
+        PUNC_PERIOD,\r
+        PUNC_L_BRACKET,\r
+        PUNC_R_BRACKET,\r
+        PUNC_L_CURLY_BRACKET,\r
+        PUNC_R_CURLY_BRACKET,\r
+\r
+\r
+    }\r
+\r
+    public struct JsTokenStruct\r
+    {\r
+        public JsToken type;\r
+        public JsToken keyword;\r
+        public double dValue;\r
+        public string sValue;\r
+\r
+        /*public void init()\r
+        {\r
+            this.type = JsToken.TYPE_ERROR;\r
+            this.keyword = 0;\r
+            this.dValue = 0;\r
+            this.sValue = null;\r
+        }*/\r
+\r
+        public void setToken(JsToken type, JsToken key)\r
+        {\r
+            this.type = type;\r
+            this.keyword = key;\r
+            this.dValue = 0;\r
+            this.sValue = null;\r
+        }\r
+        public void setToken(JsToken type, JsToken key, double value)\r
+        {\r
+            this.type = type;\r
+            this.keyword = 0;\r
+            this.dValue = value;\r
+            this.sValue = null;\r
+        }\r
+        public void setToken(JsToken type, JsToken key, string value)\r
+        {\r
+            this.type = type;\r
+            this.keyword = 0;\r
+            this.dValue = 0;\r
+            this.sValue = value;\r
+        }\r
+    }\r
+\r
+    partial class JsParser\r
+    {\r
+        /*private int setToken(JsToken typeCode, JsToken keyCode)\r
+        {\r
+            \r
+            return (int)typeCode + (int)keyCode;\r
+        }\r
+        //HIGH BYTE\r
+        const int TYPE_MASK = 0xFF00;\r
+        //public enum JsTYPE\r
+        //{\r
+        //LOW BYTE\r
+        const int KEY_MASK = 0xFF;\r
+\r
+        public JsToken getTypeToken(int value)\r
+        {\r
+            return (JsToken)(value & TYPE_MASK);\r
+        }\r
+        public JsToken getKeyToken(int value)\r
+        {\r
+            return (JsToken)(value & KEY_MASK);\r
+        }*/\r
+\r
\r
+        public static int getJsToken(DebugContext ctx, string source, int startIdx, out JsTokenStruct outToken)\r
+        {\r
+            string sVal;\r
+            double dVal;\r
+            int nVal;\r
+            outToken.type = JsToken.TYPE_ERROR;\r
+            outToken.keyword = JsToken.KEY_NOT_KEY;\r
+            outToken.dValue = 0;\r
+            outToken.sValue = null;\r
+\r
+\r
+            JsToken key;\r
+            JsToken type;\r
+\r
+            int comma = 0;\r
+            \r
+            if (source == null)\r
+                return -1;// setToken(JsToken.TYPE_ERROR, 0);\r
+            int length = source.Length;\r
+            if(length < startIdx)\r
+                return -1;// setToken(JsToken.TYPE_ERROR, 0);\r
+            \r
+            int state = 0;\r
+            int textStart = 0;\r
+            int textEnd = 0;\r
+            for (int i = startIdx; i < length; i++)\r
+            {\r
+                char c = source[i];\r
+                HtmlParser.CHAR_TOKEN token =\r
+                    HtmlParser.getCharToken(c);\r
+                switch (token)\r
+                {\r
+                    case HtmlParser.CHAR_TOKEN.NL:\r
+                        ctx.incrementLine();\r
+                        goto FALLTHROUGH_WHITESPACE;\r
+                    case HtmlParser.CHAR_TOKEN.WHITESPACE:\r
+                FALLTHROUGH_WHITESPACE:\r
+                        if (state == 0)\r
+                        {\r
+                            break;\r
+                        }\r
+                        else if (state == 1)\r
+                        {\r
+                            sVal = source.Substring(textStart, i - textStart);\r
+                            type = findKeyword(sVal, out key);\r
+                            if (JsToken.TYPE_ERROR != type)\r
+                                outToken.setToken(type, key);\r
+                            else\r
+                            {\r
+                                 outToken.setToken(JsToken.TYPE_VARIABLENAME, 0, sVal);\r
+                            }\r
+                            return i;\r
+                        }\r
+                        else if (state == 2)\r
+                        {\r
+                            sVal = source.Substring(textStart, i - textStart);\r
+                            if (!double.TryParse(sVal, out dVal))\r
+                            {\r
+                                ctx.setCurrentIdx(i);\r
+                                return -1;\r
+                            }\r
+                            outToken.setToken(JsToken.TYPE_NUMBER_LITERAL, 0, dVal);\r
+                            return i;\r
+                        }\r
+                        else if (state == 3)\r
+                        {\r
+                            //endIdx = textEnd;\r
+                            outToken.setToken(JsToken.TYPE_NUMBER_LITERAL, 0);\r
+                            return textEnd;\r
+                        }\r
+                        else if (state == 4)\r
+                        {\r
+                            sVal = source.Substring(textStart, i - textStart);\r
+                            key = validatePunctuation(sVal);\r
+                            if (key == JsToken.PUNC_NO_PUNC)\r
+                            {\r
+                                ctx.setCurrentIdx(i);\r
+                                return -1;\r
+                            }\r
+                            outToken.setToken(JsToken.TYPE_PUNCTUATOR, key);\r
+                            return i;\r
+                        }\r
+                      break;\r
+                    case HtmlParser.CHAR_TOKEN.DQUOTE:\r
+                        if (state == 0)\r
+                        {\r
+                            textEnd = getDquote(source, i + 1, out sVal);\r
+                            if (textEnd < 0)\r
+                            {\r
+                                ctx.setCurrentIdx(i);\r
+                                return -1;\r
+                            }\r
+                            outToken.setToken(JsToken.TYPE_STRING_LITERAL,\r
+                                JsToken.KEY_NOT_KEY, sVal);//source.Substring(i+1, textEnd - (i+1)));\r
+                            return textEnd + 1;\r
+                        }\r
+                        goto FALLTHROUGH_WHITESPACE;\r
+#if false\r
+                        else if (state == 1)\r
+                        {\r
+                            sVal = source.Substring(textStart, i - textStart);\r
+                            type = findKeyword(sVal, out key);\r
+                            if (JsToken.TYPE_ERROR != type)\r
+                                outToken.setToken(type, key);\r
+                            else\r
+                            {\r
+                                //key = findDomKeyword(sVal);\r
+                                //if (JsToken.KEY_NOT_KEY != key)\r
+                                //    outToken.setToken(JsToken.TYPE_DOM_KEYWORD, key);\r
+                                //else\r
+                                outToken.setToken(JsToken.TYPE_VARIABLENAME, 0, sVal);\r
+\r
+                            }\r
+                            return i;\r
+                        }\r
+                        else if (state == 2)\r
+                        {\r
+                            sVal = source.Substring(textStart, i - textStart);\r
+                            if (!double.TryParse(sVal, out dVal))\r
+                            {\r
+                                ctx.setCurrentIdx(i);\r
+                                return -1;\r
+                            }\r
+                            outToken.setToken(JsToken.TYPE_NUMBER_LITERAL, 0, dVal);\r
+                            return i;\r
+                        }\r
+                        else if (state == 3)\r
+                        {\r
+                            //endIdx = textEnd;\r
+                            outToken.setToken(JsToken.TYPE_NUMBER_LITERAL, 0);\r
+                            return textEnd;\r
+                        }\r
+                        else if (state == 4)\r
+                        {\r
+                            sVal = source.Substring(textStart, i - textStart);\r
+                            key = validatePunctuation(sVal);\r
+                            if (key == JsToken.PUNC_NO_PUNC)\r
+                            {\r
+                                ctx.setCurrentIdx(i);\r
+                                return -1;\r
+                            }\r
+                            outToken.setToken(JsToken.TYPE_PUNCTUATOR, key);\r
+                            return i;\r
+                        }\r
+                        break;\r
+#endif\r
+                    case HtmlParser.CHAR_TOKEN.SQUOTE:\r
+                        if (state == 0)\r
+                        {\r
+                            textEnd = getSquote(source, i + 1, out sVal);\r
+                            if (textEnd < 0)\r
+                            {\r
+                                ctx.setCurrentIdx(i);\r
+                                return -1;\r
+                            }\r
+                            outToken.setToken(JsToken.TYPE_STRING_LITERAL,\r
+                                JsToken.KEY_NOT_KEY, sVal);//source.Substring(i + 1, textEnd - (i + 1)));\r
+                            return textEnd + 1;\r
+                        }\r
+                        goto FALLTHROUGH_WHITESPACE;\r
+#if false\r
+                        else if (state == 1)\r
+                        {\r
+                            sVal = source.Substring(textStart, i - textStart);\r
+                            type = findKeyword(sVal, out key);\r
+                            if (JsToken.TYPE_ERROR != type)\r
+                                outToken.setToken(type, key);\r
+                            else\r
+                            {\r
+                                //key = findDomKeyword(sVal);\r
+                                //if (JsToken.KEY_NOT_KEY != key)\r
+                                //    outToken.setToken(JsToken.TYPE_DOM_KEYWORD, key);\r
+                                //else\r
+                                outToken.setToken(JsToken.TYPE_VARIABLENAME, 0, sVal);\r
+\r
+                            }\r
+                            return i;\r
+                        }\r
+                        else if (state == 2)\r
+                        {\r
+                            sVal = source.Substring(textStart, i - textStart);\r
+                            if (!double.TryParse(sVal, out dVal))\r
+                            {\r
+                                ctx.setCurrentIdx(i);\r
+                                return -1;\r
+                            }\r
+                            outToken.setToken(JsToken.TYPE_NUMBER_LITERAL, 0, dVal);\r
+                            return i;\r
+                        }\r
+                        else if (state == 3)\r
+                        {\r
+                            //endIdx = textEnd;\r
+                            outToken.setToken(JsToken.TYPE_NUMBER_LITERAL, 0);\r
+                            return textEnd;\r
+                        }\r
+                        else if (state == 4)\r
+                        {\r
+                            sVal = source.Substring(textStart, i - textStart);\r
+                            key = validatePunctuation(sVal);\r
+                            if (key == JsToken.PUNC_NO_PUNC)\r
+                            {\r
+                                ctx.setCurrentIdx(i);\r
+                                return -1;\r
+                            }\r
+                            outToken.setToken(JsToken.TYPE_PUNCTUATOR, key);\r
+                            return i;\r
+                        }\r
+                        break;\r
+#endif\r
+                    case HtmlParser.CHAR_TOKEN.ALPHA:\r
+                    case HtmlParser.CHAR_TOKEN.DOLLAR:\r
+                    case HtmlParser.CHAR_TOKEN.UNDERBAR:\r
+                        if (state == 0)\r
+                        {\r
+                            state = 1;\r
+                            textStart = i;\r
+                        }\r
+                        else if (state == 1)\r
+                        {\r
+                            break;\r
+                        }\r
+                        else if (state == 2)\r
+                        {\r
+                            ctx.setCurrentIdx(i);\r
+                            //return setToken(JsToken.TYPE_ERROR, 0);\r
+                            return -1;\r
+                        }\r
+                        else if (state == 3)\r
+                        {\r
+                            //endIdx = textEnd;\r
+                            outToken.setToken(JsToken.TYPE_NUMBER_LITERAL, 0);\r
+                            return textEnd;\r
+                        }\r
+                        else if (state == 4)\r
+                        {\r
+                            sVal = source.Substring(textStart, i - textStart);\r
+                            key = validatePunctuation(sVal);\r
+                            if (key == JsToken.PUNC_NO_PUNC)\r
+                            {\r
+                                ctx.setCurrentIdx(i);\r
+                                return -1;\r
+                            }\r
+                            outToken.setToken(JsToken.TYPE_PUNCTUATOR, key);\r
+                            return i;\r
+                        }\r
+                        break;\r
+                    case HtmlParser.CHAR_TOKEN.NUMBER:\r
+                        if (state == 0)\r
+                        {\r
+                            comma = 0;\r
+                            state = 2;\r
+                            textStart = i;\r
+                        }\r
+                        else if (state == 1 || state == 2)\r
+                        {\r
+                            break;\r
+                        }\r
+                        else if (state == 3)\r
+                        {\r
+                            state = 2;\r
+                        }\r
+                        else if (state == 4)\r
+                        {\r
+                            sVal = source.Substring(textStart, i - textStart);\r
+                            key = validatePunctuation(sVal);\r
+                            if (key == JsToken.PUNC_NO_PUNC)\r
+                            {\r
+                                ctx.setCurrentIdx(i);\r
+                                return -1;\r
+                            }\r
+                            outToken.setToken(JsToken.TYPE_PUNCTUATOR, key);\r
+                            return i;\r
+                        }\r
+                        break;\r
+                    case HtmlParser.CHAR_TOKEN.PERIOD:\r
+                        if (state == 0)\r
+                        {\r
+                            outToken.setToken(JsToken.TYPE_PUNCTUATOR, JsToken.PUNC_PERIOD);\r
+                            return i + 1;\r
+                        }\r
+                        else if (state == 1)\r
+                        {\r
+                            sVal = source.Substring(textStart, i - textStart);\r
+                            type = findKeyword(sVal, out key);\r
+                            if (JsToken.TYPE_ERROR != type)\r
+                                outToken.setToken(type, key);\r
+                            else\r
+                            {\r
+                                outToken.setToken(JsToken.TYPE_VARIABLENAME, 0, sVal);\r
+\r
+                            }\r
+                            return i;\r
+                        }\r
+                        else if (state == 2)\r
+                        {\r
+                            if (comma == 0)\r
+                            {\r
+                                comma++;\r
+                                textEnd = i;\r
+                                state = 3;\r
+                                break;\r
+                            }\r
+                            else\r
+                            {\r
+                                ctx.setCurrentIdx(i);\r
+                                return -1;\r
+                            }\r
+                        }\r
+                        else if (state == 3)\r
+                        {\r
+                            //endIdx = textEnd;\r
+                            outToken.setToken(JsToken.TYPE_NUMBER_LITERAL, 0);\r
+                            return textEnd;\r
+                        }\r
+                        break;\r
+\r
+                    case HtmlParser.CHAR_TOKEN.SEMICOLON:\r
+                    case HtmlParser.CHAR_TOKEN.COMMA:\r
+                    case HtmlParser.CHAR_TOKEN.L_BRACKET:\r
+                    case HtmlParser.CHAR_TOKEN.R_BRACKET:\r
+                    case HtmlParser.CHAR_TOKEN.L_CURLY_BRACKET:\r
+                    case HtmlParser.CHAR_TOKEN.R_CURLY_BRACKET:\r
+                        if (state == 0)\r
+                        {\r
+                            outToken.setToken(JsToken.TYPE_PUNCTUATOR, validatePunctuation(source.Substring(i, 1)));\r
+                            return i + 1;\r
+                        }\r
+                        goto FALLTHROUGH_WHITESPACE;\r
+#if false\r
+                        else if (state == 1)\r
+                        {\r
+                            sVal = source.Substring(textStart, i - textStart);\r
+                            type = findKeyword(sVal, out key);\r
+                            if (JsToken.TYPE_ERROR != type)\r
+                                outToken.setToken(type, key);\r
+                            else\r
+                            {\r
+                                //key = findDomKeyword(sVal);\r
+                                //if (JsToken.KEY_NOT_KEY != key)\r
+                                //    outToken.setToken(JsToken.TYPE_DOM_KEYWORD, key);\r
+                                //else\r
+                                outToken.setToken(JsToken.TYPE_VARIABLENAME, 0, sVal);\r
+\r
+                            }\r
+                            return i;\r
+                        }\r
+                        else if (state == 2)\r
+                        {\r
+                            sVal = source.Substring(textStart, i - textStart);\r
+                            if (!double.TryParse(sVal, out dVal))\r
+                            {\r
+                                ctx.setCurrentIdx(i);\r
+                                return -1;\r
+                            }\r
+                            outToken.setToken(JsToken.TYPE_NUMBER_LITERAL, 0, dVal);\r
+                            return i;\r
+                        }\r
+                        else if (state == 3)\r
+                        {\r
+                            outToken.setToken(JsToken.TYPE_NUMBER_LITERAL, 0);\r
+                            return textEnd;\r
+                        }\r
+                        else if(state == 4)\r
+                        {\r
+                            sVal = source.Substring(textStart, i - textStart);\r
+                            key = validatePunctuation(sVal);\r
+                            if (key == JsToken.PUNC_NO_PUNC)\r
+                            {\r
+                                ctx.setCurrentIdx(i);\r
+                                return -1;\r
+                            }\r
+                            outToken.setToken(JsToken.TYPE_PUNCTUATOR, key);\r
+                            return i;\r
+                        }\r
+                        break;\r
+#endif\r
+                    case HtmlParser.CHAR_TOKEN.SLASH:\r
+                        if (parseComment(ctx, source, i+1, out nVal))\r
+                        {\r
+                            if (state != 0)\r
+                                goto FALLTHROUGH_WHITESPACE;\r
+                            i = nVal;\r
+                            break;\r
+                        }\r
+                        goto FALLTHROUGH1;\r
+                    case HtmlParser.CHAR_TOKEN.EQUAL:\r
+                    case HtmlParser.CHAR_TOKEN.HYPHIEN:\r
+                    case HtmlParser.CHAR_TOKEN.PLUS:\r
+                    case HtmlParser.CHAR_TOKEN.ASTOR:\r
+                    case HtmlParser.CHAR_TOKEN.LT:\r
+                    case HtmlParser.CHAR_TOKEN.GT:\r
+                    case HtmlParser.CHAR_TOKEN.EXCLAMATION:\r
+                FALLTHROUGH1:\r
+                        if (state == 0)\r
+                        {\r
+                            state = 4;\r
+                            textStart = i;\r
+                        }\r
+                        else if (state == 1)\r
+                        {\r
+                            sVal = source.Substring(textStart, i - textStart);\r
+                            type = findKeyword(sVal, out key);\r
+                            if (JsToken.TYPE_ERROR != type)\r
+                                outToken.setToken(type, key);\r
+                            else\r
+                            {\r
+                                //key = findDomKeyword(sVal);\r
+                                //if (JsToken.KEY_NOT_KEY != key)\r
+                                //    outToken.setToken(JsToken.TYPE_DOM_KEYWORD, key);\r
+                               // else\r
+                                outToken.setToken(JsToken.TYPE_VARIABLENAME, 0, sVal);\r
+\r
+                            }\r
+                            return i;\r
+                        }\r
+                        else if (state == 2)\r
+                        {\r
+                            sVal = source.Substring(textStart, i - textStart);\r
+                            if (!double.TryParse(sVal, out dVal))\r
+                            {\r
+                                ctx.setCurrentIdx(i);\r
+                                return -1;\r
+                            }\r
+                            outToken.setToken(JsToken.TYPE_NUMBER_LITERAL, 0, dVal);\r
+                            return i;\r
+                        }\r
+                        else if (state == 3)\r
+                        {\r
+                            //endIdx = textEnd;\r
+                            outToken.setToken(JsToken.TYPE_NUMBER_LITERAL, 0);\r
+                            return textEnd;\r
+                        }\r
+                        else if(state == 4)\r
+                        {\r
+                            break;\r
+                        }\r
+                        break;\r
+                }\r
+            }\r
+            outToken.setToken(JsToken.TYPE_END_SRC, 0);\r
+            return length;\r
+        }\r
+        private static bool parseComment(DebugContext ctx, string source, int startIdx, out int endIdx)\r
+        {\r
+            int nVal;\r
+            int length = source.Length;\r
+            char c;\r
+            endIdx = length;\r
+            if (startIdx >= length)\r
+                return false;\r
+            char cNext = source[startIdx];\r
+            if (cNext == '/')\r
+            {\r
+                nVal = source.IndexOf('\n', startIdx+1);\r
+                if (nVal >= 0)\r
+                {\r
+                    ctx.incrementLine();\r
+                    endIdx = nVal;\r
+                }\r
+            }\r
+            else if (cNext == '*')\r
+            {\r
+                for (int i = startIdx+1; i < length; i++)\r
+                {\r
+                    c = source[i];\r
+                    if (c == '\n')\r
+                    {\r
+                        ctx.incrementLine();\r
+                    }\r
+                    else if (c == '*')\r
+                    {\r
+                        if (i + 1 < length)\r
+                        {\r
+                            if (source[i + 1] == '/')\r
+                            {\r
+                                endIdx = i + 1;\r
+                                break;\r
+                            }\r
+                        }\r
+                    }\r
+                }\r
+            }\r
+            else\r
+            {\r
+                return false;\r
+            }\r
+            return true;\r
+        }\r
+\r
+        private static JsToken findKeyword(string source, out JsToken keyToken)\r
+        {\r
+            switch (source)\r
+            {\r
+                case "NaN":\r
+                    keyToken = JsToken.KEY_NAN;\r
+                    return JsToken.TYPE_KEYWORD;\r
+                case "true":\r
+                    keyToken = JsToken.KEY_TRUE;\r
+                    return JsToken.TYPE_KEYWORD;\r
+                case "false":\r
+                    keyToken = JsToken.KEY_FALSE;\r
+                    return JsToken.TYPE_KEYWORD;\r
+                case "null":\r
+                    keyToken = JsToken.KEY_NULL;\r
+                    return JsToken.TYPE_KEYWORD;\r
+                case "this":\r
+                    keyToken = JsToken.KEY_THIS;\r
+                    return JsToken.TYPE_KEYWORD;\r
+                case "undefined":\r
+                    keyToken = JsToken.KEY_UNDEFINED;\r
+                    return JsToken.TYPE_KEYWORD;\r
+                case "function":\r
+                    keyToken = JsToken.KEY_FUNCTION;\r
+                    return JsToken.TYPE_KEYWORD;\r
+                case "var":\r
+                    keyToken = JsToken.KEY_VAR;\r
+                    return JsToken.TYPE_KEYWORD;\r
+                case "document":\r
+                    keyToken = JsToken.KEY_DOM_DOCUMENT;\r
+                    return JsToken.TYPE_DOM_KEYWORD;\r
+                case "getElementById":\r
+                    keyToken = JsToken.KEY_DOM_getElementById;\r
+                    return JsToken.TYPE_DOM_KEYWORD;\r
+                case "innerHTML":\r
+                    keyToken = JsToken.KEY_DOM_innerHTML;\r
+                    return JsToken.TYPE_DOM_KEYWORD;\r
+                case "substring":\r
+                    keyToken = JsToken.KEY_DOM_STR_substring;\r
+                    return JsToken.TYPE_DOM_STR_KEYWORD;\r
+                case "length":\r
+                    keyToken = JsToken.KEY_DOM_STR_length;\r
+                    return JsToken.TYPE_DOM_STR_KEYWORD;\r
+                case "indexOf":\r
+                    keyToken = JsToken.KEY_DOM_STR_indexOf;\r
+                    return JsToken.TYPE_DOM_STR_KEYWORD;\r
+                case "replace":\r
+                    keyToken = JsToken.KEY_DOM_STR_replace;\r
+                    return JsToken.TYPE_DOM_STR_KEYWORD;\r
+                case "if":\r
+                    keyToken = JsToken.KEY_OP_IF;\r
+                    return JsToken.TYPE_OP_KEYWORD;\r
+                case "else":\r
+                    keyToken = JsToken.KEY_OP_ELSE;\r
+                    return JsToken.TYPE_OP_KEYWORD;\r
+                case "for":\r
+                    keyToken = JsToken.KEY_OP_FOR;\r
+                    return JsToken.TYPE_OP_KEYWORD;\r
+                case "while":\r
+                    keyToken = JsToken.KEY_OP_WHILE;\r
+                    return JsToken.TYPE_OP_KEYWORD;\r
+                case "break":\r
+                    keyToken = JsToken.KEY_OP_LOOP_BREAK;\r
+                    return JsToken.TYPE_OP_KEYWORD;\r
+                case "continue":\r
+                    keyToken = JsToken.KEY_OP_LOOP_CONTINUE;\r
+                    return JsToken.TYPE_OP_KEYWORD;\r
+                case "debugger":\r
+                    keyToken = JsToken.KEY_OP_DEBUGGER;\r
+                    return JsToken.TYPE_OP_KEYWORD;\r
+                default:\r
+                    keyToken = JsToken.KEY_NOT_KEY;\r
+                    return JsToken.TYPE_ERROR;\r
+            }\r
+        }\r
+\r
+/*        private static JsToken findDomKeyword(string source)\r
+        {\r
+            switch (source)\r
+            {\r
+                case "document":\r
+                    return JsToken.KEY_DOM_DOCUMENT;\r
+                case "getElementById":\r
+                    return JsToken.KEY_DOM_getElementById;\r
+                case "innerHTML":\r
+                    return JsToken.KEY_DOM_innerHTML;\r
+            }\r
+            return JsToken.KEY_NOT_KEY;\r
+        }\r
+        */\r
+        private static int getDquote(string source, int startIdx , out string retSrc)\r
+        {\r
+            bool dquoteEscape = false;\r
+            bool squoteEscape = false;\r
+            retSrc = source;\r
+            int length = source.Length;\r
+            for (int i = startIdx; i < length; i++)\r
+            {\r
+                switch (source[i])\r
+                {\r
+                    case '\"':\r
+                        if (source[i - 1] != '\\')\r
+                        {\r
+                            retSrc = source.Substring(startIdx, i - startIdx);\r
+                            if (dquoteEscape)\r
+                            {\r
+                                retSrc = retSrc.Replace("\\\"", "\"");\r
+                            }\r
+                            if (squoteEscape)\r
+                            {\r
+                                retSrc = retSrc.Replace("\\\'", "\'");\r
+                            }\r
+                            return i;\r
+                        }\r
+                        dquoteEscape = true;\r
+                        break;\r
+                    case '\'':\r
+                        if (source[i - 1] == '\\')\r
+                        {\r
+                            squoteEscape = true;\r
+                        }\r
+                        break;\r
+                }\r
+            }\r
+            return -1;\r
+        }\r
+        private static int getSquote(string source, int startIdx, out string retSrc)\r
+        {\r
+            bool dquoteEscape = false;\r
+            bool squoteEscape = false;\r
+            retSrc = source;\r
+            int length = source.Length;\r
+            for (int i = startIdx; i < length; i++)\r
+            {\r
+                switch (source[i])\r
+                {\r
+                    case '\'':\r
+                        if (source[i - 1] != '\\')\r
+                        {\r
+                            retSrc = source.Substring(startIdx, i - startIdx);\r
+                            if (dquoteEscape)\r
+                            {\r
+                                retSrc = retSrc.Replace("\\\"", "\"");\r
+                            }\r
+                            if (squoteEscape)\r
+                            {\r
+                                retSrc = retSrc.Replace("\\\'", "\'");\r
+                            }\r
+                            return i;\r
+                        }\r
+                        squoteEscape = true;\r
+                        break;\r
+                    case '\"':\r
+                        if (source[i - 1] == '\\')\r
+                        {\r
+                            dquoteEscape = true;\r
+                        }\r
+                        break;\r
+                }\r
+            }\r
+            return -1;\r
+#if false\r
+            int length = source.Length;\r
+            for (int i = startIdx; i < length; i++)\r
+            {\r
+                char c1 = source[i-1];\r
+                char c2 = source[i];\r
+                if (c1 != '\\' && c2 == '\'')\r
+                    return i;\r
+            }\r
+            return -1;\r
+#endif\r
+        }\r
+\r
+        private static JsToken validatePunctuation(string source)\r
+        {\r
+            switch (source)\r
+            {\r
+                case "!":\r
+                    return JsToken.PUNC_OP_NOT;\r
+                case ",":\r
+                    return JsToken.PUNC_COMMA;\r
+                case ";":\r
+                    return JsToken.PUNC_SEMICOL0N;\r
+                case "(":\r
+                    return JsToken.PUNC_L_BRACKET;\r
+                case ")":\r
+                    return JsToken.PUNC_R_BRACKET;\r
+                case "{":\r
+                    return JsToken.PUNC_L_CURLY_BRACKET;\r
+                case "}":\r
+                    return JsToken.PUNC_R_CURLY_BRACKET;\r
+                case "+":\r
+                    return JsToken.PUNC_ADD;\r
+                case "-":\r
+                    return JsToken.PUNC_SUB;\r
+                case "*":\r
+                    return JsToken.PUNC_MUL;\r
+                case "/":\r
+                    return JsToken.PUNC_DIV;\r
+                case "++":\r
+                    return JsToken.PUNC_INC;\r
+                case "--":\r
+                    return JsToken.PUNC_DEC;\r
+                case "=":\r
+                    return JsToken.PUNC_EQUAL;\r
+                case "==":\r
+                    return JsToken.KEY_OP_CMP_EQUAL;\r
+                case "===":\r
+                    return JsToken.KEY_OP_CMP_STRICT_EQUAL;\r
+                case "!=":\r
+                    return JsToken.KEY_OP_CMP_NOT_EQUAL;\r
+                case "!==":\r
+                    return JsToken.KEY_OP_CMP_STRICT_NOT_EQUAL;\r
+                case "<":\r
+                    return JsToken.KEY_OP_CMP_LT;\r
+                case ">":\r
+                    return JsToken.KEY_OP_CMP_GT;\r
+                case "<=":\r
+                    return JsToken.KEY_OP_CMP_LT_EQUAL;\r
+                case ">=":\r
+                    return JsToken.KEY_OP_CMP_GT_EQUAL;\r
+\r
+                default:\r
+                    return JsToken.PUNC_NO_PUNC;\r
+            }\r
+        }\r
+\r
+\r
+    }\r
+}\r
diff --git a/NT2chCtrl45/html/js/JsVariable.cs b/NT2chCtrl45/html/js/JsVariable.cs
new file mode 100755 (executable)
index 0000000..761e0b5
--- /dev/null
@@ -0,0 +1,138 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading.Tasks;\r
+\r
+namespace NT2chCtrl.html.js\r
+{\r
+    public class JsIdentifier : JsVariant\r
+    {\r
+        string mName;\r
+        bool mLocal;\r
+        public JsIdentifier(string name, bool local)\r
+        {\r
+            mName = name;\r
+            mLocal = local;\r
+        }\r
+        public string getName() { return mName; }\r
+        public bool isLocal() { return mLocal; }\r
+\r
+    }\r
+\r
+    public class JsStringValue : JsVariant\r
+    {\r
+        static JsStringValue mStrEmpty = new JsStringValue("");\r
+        string mVal;\r
+        public JsStringValue(string sVal)\r
+        {\r
+            mVal = sVal;\r
+        }\r
+        public string getValue() { return mVal; }\r
+        public override JsStringValue getStringValue() { return this; }\r
+        public override JsBooleanValue getBooleanValue()\r
+        {\r
+            if (mVal == null || mVal.Length == 0)\r
+                return new JsBooleanValue(false);\r
+            else\r
+                return new JsBooleanValue(true);\r
+        }\r
+        public override JsNumberValue getNumberValue()\r
+        {\r
+            double dVal;\r
+            if (double.TryParse(mVal, out dVal))\r
+                return new JsNumberValue(dVal);\r
+            return new JsNumberValue(double.NaN);\r
+            //return base.getNumberValue();\r
+        }\r
+\r
+        public static JsStringValue getEmpty()\r
+        {\r
+            return mStrEmpty;\r
+        }\r
+    }\r
+    public class JsNumberValue : JsVariant\r
+    {\r
+        double mVal;\r
+        public JsNumberValue(double dVal)\r
+        {\r
+            mVal = dVal;\r
+        }\r
+        public override JsStringValue getStringValue()\r
+        {\r
+            return new JsStringValue(mVal.ToString());\r
+        }\r
+\r
+        public bool IsNaN()\r
+        {\r
+            return double.IsNaN(mVal);\r
+        }\r
+\r
+        public override JsBooleanValue getBooleanValue()\r
+        {\r
+            if (double.IsNaN(mVal))\r
+                return new JsBooleanValue(false);\r
+\r
+            if (mVal == 0)\r
+                return new JsBooleanValue(false);\r
+\r
+            return new JsBooleanValue(true);\r
+        }\r
+        public double getValue() { return mVal; }\r
+        public override JsNumberValue getNumberValue()\r
+        {\r
+            return this;\r
+        }\r
+\r
+    }\r
+    public class JsBooleanValue : JsVariant\r
+    {\r
+        static JsBooleanValue gFalseValue = new JsBooleanValue(false);\r
+        static JsBooleanValue gTrueValue = new JsBooleanValue(true);\r
+\r
+        public static JsBooleanValue getFalseValue() { return gFalseValue; }\r
+        public static JsBooleanValue getTrueValue() { return gTrueValue; }\r
+        public static JsBooleanValue getConstantValue(bool value) { return value ?  gTrueValue : gFalseValue; }\r
+\r
+        bool? mVal;\r
+        public JsBooleanValue()\r
+        {\r
+            mVal = null;\r
+        }\r
+        public JsBooleanValue(bool dVal)\r
+        {\r
+            mVal = dVal;\r
+        }\r
+        public override JsStringValue getStringValue()\r
+        {\r
+            string str;\r
+            if (mVal.HasValue && (bool)mVal)\r
+                str = "true";\r
+            else\r
+                str = "false";\r
+            return new JsStringValue(str);\r
+        }\r
+        public override JsNumberValue getNumberValue()\r
+        {\r
+            \r
+            if (mVal.HasValue && (bool)mVal)\r
+                return new JsNumberValue(1);\r
+            else\r
+                return new JsNumberValue(0);\r
+        }\r
+\r
+\r
+        public override JsBooleanValue getBooleanValue()\r
+        {\r
+            return this;\r
+        }\r
+        public bool getValue()\r
+        {\r
+            if (mVal.HasValue)\r
+                return (bool)mVal;\r
+            return false;\r
+        }\r
+\r
+    }\r
+\r
+}\r
diff --git a/NT2chCtrl45/html/js/JsVariant.cs b/NT2chCtrl45/html/js/JsVariant.cs
new file mode 100755 (executable)
index 0000000..bef780b
--- /dev/null
@@ -0,0 +1,42 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading.Tasks;\r
+\r
+namespace NT2chCtrl.html.js\r
+{\r
+    public abstract class JsVariant\r
+    {\r
+        public virtual JsBooleanValue getBooleanValue()\r
+        {\r
+            return JsBooleanValue.getFalseValue();\r
+        }\r
+        public virtual JsStringValue getStringValue() { return null; }\r
+        public virtual JsNumberValue getNumberValue() { return null; }\r
+    }\r
+\r
+    public class JsUndefValue : JsVariant\r
+    {\r
+        static JsUndefValue gThis = new JsUndefValue();\r
+\r
+        public static JsUndefValue getConstant(){return gThis;}\r
+\r
+        public override JsBooleanValue getBooleanValue()\r
+        {\r
+            return JsBooleanValue.getFalseValue();\r
+        } \r
+    }\r
+\r
+    public class JsNullValue : JsVariant\r
+    {\r
+        static JsNullValue gThis = new JsNullValue();\r
+\r
+        public static JsNullValue getConstant() { return gThis; }\r
+\r
+        public override JsBooleanValue getBooleanValue()\r
+        {\r
+            return JsBooleanValue.getFalseValue();\r
+        }\r
+    }\r
+}\r
diff --git a/NT2chCtrl45/html/wpf/FontCash.cs b/NT2chCtrl45/html/wpf/FontCash.cs
new file mode 100755 (executable)
index 0000000..844d568
--- /dev/null
@@ -0,0 +1,28 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Windows.Media;\r
+\r
+namespace NT2chCtrl.html.wpf\r
+{\r
+    class FontCash\r
+    {\r
+        private static Dictionary<string, FontFamily>\r
+            mFontCash = new Dictionary<string, FontFamily>();\r
+\r
+        public static FontFamily getFontFamily(string fontName)\r
+        {\r
+            FontFamily ff;\r
+            if (fontName == null)\r
+                return null;\r
+\r
+            if (mFontCash.TryGetValue(fontName, out ff))\r
+            {\r
+                return ff;\r
+            }            \r
+            ff = new FontFamily(fontName);\r
+            mFontCash.Add(fontName, ff);\r
+            return ff;\r
+        }\r
+    }\r
+}\r
diff --git a/NT2chCtrl45/html/wpf/Html2FlowDoc.cs b/NT2chCtrl45/html/wpf/Html2FlowDoc.cs
new file mode 100755 (executable)
index 0000000..8cc0f52
--- /dev/null
@@ -0,0 +1,1442 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Windows;\r
+using System.Windows.Controls;\r
+using System.Windows.Documents;\r
+using System.Windows.Media;\r
+using System.Windows.Media.Imaging;\r
+using System.Windows.Shapes;\r
+using NT2chCtrl;\r
+using NT2chCtrl.html.css;\r
+using NT2chObject;\r
+\r
+namespace NT2chCtrl.html.wpf\r
+{\r
+    class Html2FlowDoc\r
+    {\r
+        static Dictionary<string, FontFamily> mFontList = new Dictionary<string, FontFamily>();\r
+\r
+        static FontFamily getFontFamily(string familyName)\r
+        {\r
+            FontFamily font;\r
+            if (mFontList.TryGetValue(familyName, out font))\r
+                return font;\r
+\r
+            font = new FontFamily(familyName);\r
+            mFontList.Add(familyName, font);\r
+            return font;\r
+        }\r
+\r
+        public static bool DrawHtml(ResListAdapter adapter, Section rootSection,\r
+            IThread thread, IRes res, HtmlElement bodyElem)\r
+        {\r
+            return drawHtmlForBlocks(adapter, rootSection.Blocks,thread , res,  bodyElem);\r
+        }\r
+\r
+\r
+        public static void applyCSSProperiesForElement(HtmlElement hElem, TextElement tElem)\r
+        {\r
+            Brush brush;\r
+            //BitmapImage bImg;\r
+            Color c;\r
+            double d;\r
+            int nVal;\r
+            string sVal;\r
+            Property.FontStyle fontStyle;\r
+            if (hElem.tryGetColor(out c))\r
+            {\r
+                tElem.Foreground = new SolidColorBrush(c);\r
+            }\r
+            if (hElem.tryGetBackgroundColor(out c))\r
+            {\r
+                tElem.Background = new SolidColorBrush(c);\r
+            }\r
+            if (hElem.tryGetBackgroundImage(out brush))\r
+            {\r
+               // iBrush = new ImageBrush(bImg);\r
+                //iBrush.Stretch = Stretch.UniformToFill;\r
+               // iBrush.TileMode = TileMode.Tile;\r
+                tElem.Background = brush;\r
+            }\r
+\r
+            if (hElem.tryGetFontFamily(out sVal))\r
+            {\r
+                FontFamily font = getFontFamily(sVal);\r
+                tElem.FontFamily = font;\r
+            }\r
+            if (hElem.tryGetLength("font-size", out d, null))\r
+            {\r
+                if (d != double.NaN)\r
+                    tElem.FontSize = d;\r
+            }\r
+            if (hElem.tryGetFontWeight(out nVal))\r
+            {\r
+                tElem.FontWeight = parseFontWeight(nVal);\r
+            }\r
+            if (hElem.tryGetFontStyle(out fontStyle))\r
+            {\r
+                switch (fontStyle)\r
+                {\r
+                    case Property.FontStyle.Normal:\r
+                        tElem.FontStyle = FontStyles.Normal;\r
+                        break;\r
+                    case Property.FontStyle.Italic:\r
+                        tElem.FontStyle = FontStyles.Italic;\r
+                        break;\r
+                    case Property.FontStyle.Oblique:\r
+                        tElem.FontStyle = FontStyles.Oblique;\r
+                        break;\r
+                }\r
+            }\r
+        }\r
+        public static void applyCSSProperiesForElement(HtmlElement hElem, TextBlock tElem)\r
+        {\r
+            Brush brush;\r
+            //BitmapImage bImg;\r
+            Color c;\r
+            double d;\r
+            int nVal;\r
+            string sVal;\r
+            if (hElem.tryGetColor(out c))\r
+            {\r
+                tElem.Foreground = new SolidColorBrush(c);\r
+            }\r
+            if (hElem.tryGetBackgroundColor(out c))\r
+            {\r
+                tElem.Background = new SolidColorBrush(c);\r
+            }\r
+            if (hElem.tryGetBackgroundImage(out brush))\r
+            {\r
+\r
+                //iBrush = new ImageBrush(bImg);\r
+                //iBrush.Stretch = Stretch.UniformToFill;\r
+                //iBrush.TileMode = TileMode.Tile;\r
+                //iBrush.Viewport\r
+                tElem.Background = brush;\r
+\r
+            }\r
+            if (hElem.tryGetPropertyValue("font-family", out sVal))\r
+            {\r
+                FontFamily font = getFontFamily(sVal);\r
+                tElem.FontFamily = font;\r
+            }\r
+            if (hElem.tryGetLength("font-size", out d, null))\r
+            {\r
+                if(d != double.NaN)\r
+                    tElem.FontSize = d;\r
+            }\r
+            if (hElem.tryGetFontWeight(out nVal))\r
+            {\r
+                tElem.FontWeight = parseFontWeight(nVal);\r
+            }\r
+            if (hElem.tryGetLength("height", out d, null))\r
+            {\r
+                if (d != double.NaN)\r
+                    tElem.Height = d;\r
+            }\r
+            if (hElem.tryGetLength("min-height", out d, null))\r
+            {\r
+                if (d != double.NaN)\r
+                    tElem.MinHeight = d;\r
+            }\r
+            if (hElem.tryGetLength("max-height", out d, null))\r
+            {\r
+                if (d != double.NaN)\r
+                    tElem.MaxHeight = d;\r
+            }\r
+            if (hElem.tryGetLength("width", out d, null))\r
+            {\r
+                if (d != double.NaN)\r
+                    tElem.Width = d;\r
+            }\r
+            if (hElem.tryGetLength("min-width", out d, null))\r
+            {\r
+                if (d != double.NaN)\r
+                    tElem.MinWidth = d;\r
+            }\r
+            if (hElem.tryGetLength("max-width", out d, null))\r
+            {\r
+                if (d != double.NaN)\r
+                    tElem.MaxWidth = d;\r
+            }\r
+        }\r
+\r
+        private static FontWeight parseFontWeight(int value)\r
+        {\r
+            if (value <= 100)\r
+                return FontWeights.Thin;\r
+            else if (value <= 200)\r
+                return FontWeights.ExtraLight;\r
+            else if (value <= 300)\r
+                return FontWeights.Light;\r
+            else if (value <= 400)\r
+                return FontWeights.Normal;\r
+            else if (value <= 500)\r
+                return FontWeights.Medium;\r
+            else if (value <= 600)\r
+                return FontWeights.SemiBold;\r
+            else if (value <= 700)\r
+                return FontWeights.Bold;\r
+            else if (value <= 800)\r
+                return FontWeights.ExtraBold;\r
+            else if (value <= 900)\r
+                return FontWeights.Black;\r
+            else\r
+                return FontWeights.ExtraBlack;\r
+        }\r
+\r
+        \r
\r
+\r
+        private static bool drawHtmlForBlocks(ResListAdapter adapter, \r
+            BlockCollection blocks, IThread thread, IRes res, HtmlElement parent)\r
+        {\r
+            StringBuilder sb = new StringBuilder();\r
+            string[] sArr;\r
+            StringElement sElem;\r
+            Paragraph paraBase = null;\r
+            Paragraph para;\r
+            Span span;\r
+            Section sec;\r
+            Hyperlink hLink;\r
+            Run run;\r
+            string attrName;\r
+            css.Property.Visibility visibility;\r
+            List<HtmlElement> children = parent.getChildren();\r
+            int count = children.Count;\r
+            foreach (HtmlElement elem in children)\r
+            {\r
+                bool bHandled = false;\r
+                para = null;\r
+                string attrVal = elem.getAttributeValue("id");\r
+                switch (attrVal)\r
+                {\r
+                    /*case "msg":\r
+                        if(paraBase == null)\r
+                            paraBase = new Paragraph();\r
+                        if (sb.Length > 0)\r
+                        {\r
+                            setStringAvoidEmpty(paraBase.Inlines, sb.ToString());\r
+                            sb.Clear();\r
+                        }\r
+                        adapter.parseResMsg(paraBase.Inlines, thread, res, -1, -1, true);\r
+                        bHandled = true;\r
+                        break;*/\r
+                    case "sequence":\r
+                        if(paraBase == null)\r
+                            paraBase = new Paragraph();\r
+                        adapter.parseSequenceNo(paraBase.Inlines, thread, res);\r
+                        if (sb.Length > 0)\r
+                        {\r
+                            setStringAvoidEmpty(paraBase.Inlines, sb.ToString());\r
+                            sb.Clear();\r
+                        }\r
+                        bHandled = true;\r
+                        break;\r
+                    /*case "identifier":\r
+                        if(paraBase == null)\r
+                            paraBase = new Paragraph();\r
+                        if (sb.Length > 0)\r
+                        {\r
+                            setStringAvoidEmpty(paraBase.Inlines, sb.ToString());\r
+                            sb.Clear();\r
+                        }\r
+                        adapter.parseIdentifier(paraBase.Inlines, thread, res);\r
+                        bHandled = true;\r
+                        break;*/\r
+                    /*case "backwardreferences":\r
+                        if(paraBase == null)\r
+                            paraBase = new Paragraph();\r
+                        if (sb.Length > 0)\r
+                        {\r
+                            setStringAvoidEmpty(paraBase.Inlines, sb.ToString());\r
+                            sb.Clear();\r
+                        }\r
+                        adapter.parseBackwardReferences(paraBase.Inlines, thread, res);\r
+                        bHandled = true;\r
+                        break;*/\r
+                }\r
+                if (bHandled)\r
+                {\r
+                    blocks.Add(paraBase);\r
+                    continue;\r
+                }\r
+                attrName = elem.getAttributeValue("res-link");\r
+                if (attrName != null)\r
+                {\r
+                    if (paraBase == null)\r
+                    {\r
+                        paraBase = new Paragraph();\r
+                        blocks.Add(paraBase);\r
+                    }\r
+                    if (sb.Length > 0)\r
+                    {\r
+                        setStringAvoidEmpty(paraBase.Inlines, sb.ToString());\r
+                        sb.Clear();\r
+                    }\r
+                    if (elem.tryGetVisibility(out visibility))\r
+                    {\r
+                        if (visibility == css.Property.Visibility.Collapse ||\r
+                            visibility == css.Property.Visibility.Hidden)\r
+                        {\r
+                            continue;\r
+                        }\r
+                    }\r
+                    hLink = new Hyperlink();\r
+                    //span = new Span();\r
+                    Html2FlowDoc.applyCSSProperiesForElement(elem, hLink);\r
+                    paraBase.Inlines.Add(hLink);\r
+                    drawHtmlForInlines(adapter, hLink.Inlines, thread, res, elem);\r
+                    sArr = elem.getStringContent();\r
+                    if (sArr != null && sArr.Length > 0)\r
+                    {\r
+                        string s = sArr[0].Replace("<<", ">>");\r
+                        List<object> param = new List<object>(2);\r
+                        param.Add(thread);\r
+                        param.Add(s);\r
+                        hLink.Tag = param;\r
+                        hLink.Click += adapter.resLinkSubItem_MouseEnter2;\r
+                    }\r
+                    continue;\r
+                }\r
+                attrName = elem.getAttributeValue("id-link");\r
+                if (attrName != null)\r
+                {\r
+                    if (paraBase == null)\r
+                    {\r
+                        paraBase = new Paragraph();\r
+                        blocks.Add(paraBase);\r
+                    }\r
+                    if (sb.Length > 0)\r
+                    {\r
+                        setStringAvoidEmpty(paraBase.Inlines, sb.ToString());\r
+                        sb.Clear();\r
+                    }\r
+                    if (elem.tryGetVisibility(out visibility))\r
+                    {\r
+                        if (visibility == css.Property.Visibility.Collapse ||\r
+                            visibility == css.Property.Visibility.Hidden)\r
+                        {\r
+                            continue;\r
+                        }\r
+                    }\r
+                    List<int> numArr = collectResId(thread, attrName);\r
+                    if (numArr != null && numArr.Count > 1)\r
+                    {\r
+                        hLink = new Hyperlink();\r
+                        Html2FlowDoc.applyCSSProperiesForElement(elem, hLink);\r
+                        paraBase.Inlines.Add(hLink);\r
+                        drawHtmlForInlines(adapter, hLink.Inlines, thread, res, elem);\r
+                        List<object> param = new List<object>(2);\r
+                        param.Add(thread);\r
+                        param.Add(numArr.ToArray());\r
+                        hLink.Tag = param;\r
+                        if(adapter.getEnablePopupMouseHover())\r
+                            hLink.MouseEnter += adapter.resLink_MouseEnter;\r
+                        else\r
+                            hLink.Click += adapter.resLink_MouseEnter;\r
+                    }\r
+                    else\r
+                    {\r
+                        span = new Span();\r
+                        Html2FlowDoc.applyCSSProperiesForElement(elem, span);\r
+                        paraBase.Inlines.Add(span);\r
+                        drawHtmlForInlines(adapter, span.Inlines, thread, res, elem);\r
+                    }\r
+                    continue;\r
+                }\r
+                string tagName = elem.getTagName();\r
+                switch (tagName)\r
+                {\r
+                    case "":\r
+                        sElem = elem as StringElement;\r
+                        if (sElem != null)\r
+                        {\r
+                            sb.Append(sElem.getString());\r
+                        }\r
+                        break;\r
+                    case "hr":\r
+                        if (paraBase == null)\r
+                        {\r
+                            paraBase = new Paragraph();\r
+                            paraBase.Margin = new System.Windows.Thickness(10, 0, 10, 0);\r
+                            blocks.Add(paraBase);\r
+                        }\r
+                        if (sb.Length > 0)\r
+                        {\r
+                            setStringAvoidEmpty(paraBase.Inlines, sb.ToString());\r
+                            sb.Clear();\r
+                        }\r
+                        paraBase.Inlines.Add(new LineBreak());\r
+                        paraBase.Inlines.Add(new LineBreak());\r
+                        System.Windows.Shapes.Rectangle rectangle = new Rectangle();\r
+                        rectangle.HorizontalAlignment = System.Windows.HorizontalAlignment.Center;\r
+                        rectangle.Width = 800;\r
+                        rectangle.Height = 4;\r
+                        rectangle.StrokeThickness = 1;\r
+                        rectangle.Stroke = new SolidColorBrush(Colors.White);\r
+                        rectangle.Fill = new SolidColorBrush(Colors.Black);\r
+                        InlineUIContainer ui = new InlineUIContainer(rectangle);\r
+                        rectangle.Margin = new System.Windows.Thickness(20, 0, 20, 0);\r
+\r
+\r
+                        paraBase.Inlines.Add(ui);\r
+                        paraBase.Inlines.Add(new LineBreak());\r
+                        paraBase.Inlines.Add(new LineBreak());\r
+                        break;\r
+                    case "br":\r
+                        if (paraBase == null)\r
+                        {\r
+                            paraBase = new Paragraph();\r
+                            paraBase.Margin = new System.Windows.Thickness(10, 0, 10, 0);\r
+                            blocks.Add(paraBase);\r
+                        }\r
+                        if (sb.Length > 0)\r
+                        {\r
+                            setStringAvoidEmpty(paraBase.Inlines, sb.ToString());\r
+                            sb.Clear();\r
+                        }\r
+                        paraBase.Inlines.Add(new LineBreak());\r
+                        break;\r
+                    case "p":\r
+                        if (sb.Length > 0)\r
+                        {\r
+                            string s = convertHtmlString(sb.ToString());\r
+                            if (s.Length > 0)\r
+                            {\r
+                                if (paraBase == null && !" ".Equals(s))\r
+                                {\r
+                                    paraBase = new Paragraph();\r
+                                    paraBase.Margin = new System.Windows.Thickness(10, 0, 10, 0);\r
+                                    blocks.Add(paraBase);\r
+                                }\r
+                                if (paraBase != null)\r
+                                {\r
+                                    run = new Run(convertHtmlString(sb.ToString()));\r
+                                    paraBase.Inlines.Add(run);\r
+                                }\r
+                            }\r
+                            sb.Clear();\r
+                        }\r
+                        paraBase = null;\r
+                        if (elem.tryGetVisibility(out visibility))\r
+                        {\r
+                            if (visibility == css.Property.Visibility.Collapse ||\r
+                                visibility == css.Property.Visibility.Hidden)\r
+                            {\r
+                                break;\r
+                            }\r
+                        }\r
+                        para = new Paragraph();\r
+                        //para.Margin = new System.Windows.Thickness(10, 0, 10, 0);\r
+                        //blocks.Add(para);\r
+                        //sec = new Section();\r
+                        Html2FlowDoc.applyCSSProperiesForElement(elem, para);\r
+                        drawHtmlForInlines(adapter, para.Inlines, thread, res, elem);\r
+                        blocks.Add(para);\r
+                        break;\r
+                    case "div":\r
+                        if (sb.Length > 0)\r
+                        {\r
+                            string s = convertHtmlString(sb.ToString());\r
+                            if (s.Length > 0)\r
+                            {\r
+                                if (paraBase == null && !" ".Equals(s))\r
+                                {\r
+                                    paraBase = new Paragraph();\r
+                                    paraBase.Margin = new System.Windows.Thickness(10, 0, 10, 0);\r
+                                    blocks.Add(paraBase);\r
+                                }\r
+                                if (paraBase != null)\r
+                                {\r
+                                    run = new Run(convertHtmlString(sb.ToString()));\r
+                                    paraBase.Inlines.Add(run);\r
+                                }\r
+                            }\r
+                            sb.Clear();\r
+                        }\r
+                        paraBase = null;\r
+                        if (elem.tryGetVisibility(out visibility))\r
+                        {\r
+                            if (visibility == css.Property.Visibility.Collapse ||\r
+                                visibility == css.Property.Visibility.Hidden)\r
+                            {\r
+                                break;\r
+                            }\r
+                        }\r
+                        //Paragraph para = new Paragraph();\r
+                       // para.Margin = new System.Windows.Thickness(10, 0, 10, 0);\r
+                        //blocks.Add(para);\r
+                        sec = new Section();\r
+                        Html2FlowDoc.applyCSSProperiesForElement(elem, sec);\r
+                        drawHtmlForBlocks(adapter, sec.Blocks, thread, res, elem);\r
+                        blocks.Add(sec);\r
+                        break;\r
+                    case "span":\r
+                        if (paraBase == null)\r
+                        {\r
+                            paraBase = new Paragraph();\r
+                            paraBase.Margin = new System.Windows.Thickness(10, 0, 10, 0);\r
+                            blocks.Add(paraBase);\r
+                        }\r
+                        if (sb.Length > 0)\r
+                        {\r
+                            setStringAvoidEmpty(paraBase.Inlines, sb.ToString());\r
+                            sb.Clear();\r
+                        }\r
+                        if (elem.tryGetVisibility(out visibility))\r
+                        {\r
+                            if (visibility == css.Property.Visibility.Collapse ||\r
+                                visibility == css.Property.Visibility.Hidden)\r
+                            {\r
+                                break;\r
+                            }\r
+                        }\r
+                        span = new Span();\r
+                        Html2FlowDoc.applyCSSProperiesForElement(elem, span);\r
+                        paraBase.Inlines.Add(span);\r
+                        drawHtmlForInlines(adapter, span.Inlines, thread, res, elem);\r
+                        break;\r
+                    case "a":\r
+                        if (paraBase == null)\r
+                        {\r
+                            paraBase = new Paragraph();\r
+                            paraBase.Margin = new System.Windows.Thickness(10, 0, 10, 0);\r
+                            blocks.Add(paraBase);\r
+                        }\r
+                        if (sb.Length > 0)\r
+                        {\r
+                            setStringAvoidEmpty(paraBase.Inlines, sb.ToString());\r
+                            sb.Clear();\r
+                        }\r
+                        if (elem.tryGetVisibility(out visibility))\r
+                        {\r
+                            if (visibility == css.Property.Visibility.Collapse ||\r
+                                visibility == css.Property.Visibility.Hidden)\r
+                            {\r
+                                break;\r
+                            }\r
+                        }\r
+                        string url = elem.getAttributeValue("href");\r
+                        hLink = new Hyperlink();\r
+                        if (url != null)\r
+                        {\r
+                            /*if (adapter.chkGraphicLink(url))\r
+                            {\r
+                                ThumbnailImageHelper helper =\r
+                                    ThumbnailImageHelper.CreateInstance(url);\r
+                                paraBase.Inlines.Add(helper.GetContainer());\r
+                                adapter.setThumbnailImage(helper, url);\r
+                            }*/\r
+                            hLink.NavigateUri = new Uri(url);\r
+                            hLink.Click += adapter.urlLink_Click;\r
+                        }\r
+                        Html2FlowDoc.applyCSSProperiesForElement(elem, hLink);\r
+                        paraBase.Inlines.Add(hLink);\r
+                        drawHtmlForInlines(adapter, hLink.Inlines, thread, res, elem);\r
+                        break;\r
+                    case "img":\r
+                        if (paraBase == null)\r
+                        {\r
+                            paraBase = new Paragraph();\r
+                            paraBase.Margin = new System.Windows.Thickness(10, 0, 10, 0);\r
+                            blocks.Add(paraBase);\r
+                        }\r
+                        if (sb.Length > 0)\r
+                        {\r
+                            setStringAvoidEmpty(paraBase.Inlines, sb.ToString());\r
+                            sb.Clear();\r
+                        }\r
+                        if (elem.tryGetVisibility(out visibility))\r
+                        {\r
+                            if (visibility == css.Property.Visibility.Collapse ||\r
+                                visibility == css.Property.Visibility.Hidden)\r
+                            {\r
+                                break;\r
+                            }\r
+                        }\r
+                        url = elem.getAttributeValue("src");\r
+                        hLink = new Hyperlink();\r
+                        if (url != null)\r
+                        {\r
+                            if (chkLocalPath(url))\r
+                            {\r
+                                Image img;\r
+                                if (elem.tryGetImage(out img, url))\r
+                                {\r
+                                    paraBase.Inlines.Add(new InlineUIContainer(img));\r
+                                }\r
+                            }\r
+                            else\r
+                            {\r
+                                ThumbnailImageHelper helper =\r
+                                     ThumbnailImageHelper.CreateInstance(url);\r
+                                paraBase.Inlines.Add(helper.GetContainer());\r
+                                adapter.setThumbnailImage(helper, url);\r
+                                hLink.NavigateUri = new Uri(url);\r
+                                hLink.Click += adapter.urlLink_Click;\r
+                            }\r
+                        }\r
+                        Html2FlowDoc.applyCSSProperiesForElement(elem, hLink);\r
+                        paraBase.Inlines.Add(hLink);\r
+                        //drawHtmlForInlines(adapter, hLink.Inlines, thread, res, elem);\r
+                        break;\r
+                }\r
+\r
+\r
+            }\r
+            if (sb.Length > 0)\r
+            {\r
+                string s = convertHtmlString(sb.ToString());\r
+                if (s.Length > 0 && !" ".Equals(s))\r
+                {\r
+                    if (paraBase == null)\r
+                    {\r
+                        paraBase = new Paragraph();\r
+                        \r
+                        blocks.Add(paraBase);\r
+                    }\r
+                    run = new Run(convertHtmlString(sb.ToString()));\r
+                    paraBase.Inlines.Add(run);\r
+                }\r
+                sb.Clear();\r
+            }\r
+            return true;\r
+        }\r
+\r
+        private static bool chkLocalPath(string path)\r
+        {\r
+            if (path != null && path.Length > 0)\r
+            {\r
+                int idx = path.IndexOf("://");\r
+                if (idx > 0)\r
+                    return false;\r
+            }\r
+            return true;\r
+        }\r
+\r
+        private static bool drawHtmlForInlines(ResListAdapter adapter, InlineCollection inlines, \r
+            IThread thread, IRes res, HtmlElement parent)\r
+        {\r
+            StringBuilder sb = new StringBuilder();\r
+            StringElement sElem;\r
+            //Run run;\r
+            Span span;\r
+            Hyperlink hLink;\r
+            //TextBlock tb;\r
+            Paragraph para;\r
+            Floater fl;\r
+            css.Property.Visibility visibility;\r
+            string[] sArr;\r
+\r
+\r
+            List<HtmlElement> children = parent.getChildren();\r
+            int count = children.Count;\r
+            foreach (HtmlElement elem in children)\r
+            {\r
+                bool bHandled = false;\r
+                string attrVal = elem.getAttributeValue("id");\r
+                switch (attrVal)\r
+                {\r
+                    /*case "msg":\r
+                        if (sb.Length > 0)\r
+                        {\r
+                            setStringAvoidEmpty(inlines, sb.ToString());\r
+                            sb.Clear();\r
+                        }\r
+                        adapter.parseResMsg(inlines, thread, res, -1, -1, true);\r
+                        bHandled = true;\r
+                        break;*/\r
+                    case "sequence":\r
+                        adapter.parseSequenceNo(inlines, thread, res);\r
+                        if (sb.Length > 0)\r
+                        {\r
+                            setStringAvoidEmpty(inlines, sb.ToString());\r
+                            sb.Clear();\r
+                        }\r
+                        bHandled = true;\r
+                        break;\r
+                    /*case "identifier":\r
+                        if (sb.Length > 0)\r
+                        {\r
+                            setStringAvoidEmpty(inlines, sb.ToString());\r
+                            sb.Clear();\r
+                        }\r
+                        adapter.parseIdentifier(inlines, thread, res);\r
+                        bHandled = true;\r
+                        break;*/\r
+                    /*case "backwardreferences":\r
+                        if (sb.Length > 0)\r
+                        {\r
+                            setStringAvoidEmpty(inlines, sb.ToString());\r
+                            sb.Clear();\r
+                        }\r
+                        adapter.parseBackwardReferences(inlines,thread, res);\r
+                        bHandled = true;\r
+                        break;*/\r
+                }\r
+                if (bHandled)\r
+                {\r
+                    continue;\r
+                }\r
+\r
+                string attrName = elem.getAttributeValue("res-link");\r
+                if (attrName != null)\r
+                {\r
+                    if (sb.Length > 0)\r
+                    {\r
+                        setStringAvoidEmpty(inlines, sb.ToString());\r
+                        sb.Clear();\r
+                    }\r
+                    if (elem.tryGetVisibility(out visibility))\r
+                    {\r
+                        if (visibility == css.Property.Visibility.Collapse ||\r
+                            visibility == css.Property.Visibility.Hidden)\r
+                        {\r
+                            continue;\r
+                        }\r
+                    }\r
+                    hLink = new Hyperlink();\r
+                    //span = new Span();\r
+                    Html2FlowDoc.applyCSSProperiesForElement(elem, hLink);\r
+                    inlines.Add(hLink);\r
+                    drawHtmlForInlines(adapter, hLink.Inlines, thread, res, elem);\r
+                    sArr = elem.getStringContent();\r
+                    if (sArr != null && sArr.Length > 0)\r
+                    {\r
+                        string s = sArr[0].Replace("<<", ">>");\r
+                        List<object> param = new List<object>(2);\r
+                        param.Add(thread);\r
+                        param.Add(s);\r
+                        hLink.Tag = param;\r
+                        if (adapter.getEnablePopupMouseHover())\r
+                            hLink.MouseEnter += adapter.resLinkSubItem_MouseEnter2;\r
+                        else\r
+                            hLink.Click += adapter.resLinkSubItem_MouseEnter2;\r
+                    }\r
+                    continue;\r
+                }\r
+                attrName = elem.getAttributeValue("id-link");\r
+                if (attrName != null)\r
+                {\r
+                    if (sb.Length > 0)\r
+                    {\r
+                        setStringAvoidEmpty(inlines, sb.ToString());\r
+                        sb.Clear();\r
+                    }\r
+                    if (elem.tryGetVisibility(out visibility))\r
+                    {\r
+                        if (visibility == css.Property.Visibility.Collapse ||\r
+                            visibility == css.Property.Visibility.Hidden)\r
+                        {\r
+                            continue;\r
+                        }\r
+                    }\r
+                    List<int> numArr = collectResId(thread, attrName);\r
+                    if (numArr != null && numArr.Count > 1)\r
+                    {\r
+                        hLink = new Hyperlink();\r
+                        Html2FlowDoc.applyCSSProperiesForElement(elem, hLink);\r
+                        inlines.Add(hLink);\r
+                        drawHtmlForInlines(adapter, hLink.Inlines, thread, res, elem);\r
+\r
+                        List<object> param = new List<object>(2);\r
+                        param.Add(thread);\r
+                        param.Add(numArr.ToArray());\r
+                        hLink.Tag = param;\r
+                        if (adapter.getEnablePopupMouseHover())\r
+                            hLink.MouseEnter += adapter.resLink_MouseEnter;\r
+                        else\r
+                            hLink.Click += adapter.resLink_MouseEnter;\r
+                    }\r
+                    else\r
+                    {\r
+                        span = new Span();\r
+                        Html2FlowDoc.applyCSSProperiesForElement(elem, span);\r
+                        inlines.Add(span);\r
+                        drawHtmlForInlines(adapter, span.Inlines, thread, res, elem);\r
+                    }\r
+                    continue;\r
+                }\r
+                string tagName = elem.getTagName();\r
+                switch (tagName)\r
+                {\r
+                    case "":\r
+                        sElem = elem as StringElement;\r
+                        if (sElem != null)\r
+                        {\r
+                            sb.Append(sElem.getString());\r
+                        }\r
+                        break;\r
+                    case "hr":\r
+                        if (sb.Length > 0)\r
+                        {\r
+                            setStringAvoidEmpty(inlines, sb.ToString());\r
+                            sb.Clear();\r
+                        }\r
+                        inlines.Add(new LineBreak());\r
+                        inlines.Add(new LineBreak());\r
+                        System.Windows.Shapes.Rectangle rectangle = new Rectangle();\r
+                        rectangle.HorizontalAlignment = System.Windows.HorizontalAlignment.Center;\r
+                        rectangle.Width = 800;\r
+                        rectangle.Height = 4;\r
+                        rectangle.StrokeThickness = 1;\r
+                        rectangle.Stroke = new SolidColorBrush(Colors.White);\r
+                        rectangle.Fill = new SolidColorBrush(Colors.Black);\r
+                        InlineUIContainer ui = new InlineUIContainer(rectangle);\r
+                        rectangle.Margin = new System.Windows.Thickness(20, 0, 20, 0);\r
+                        \r
+                        \r
+                        inlines.Add(ui);\r
+                        inlines.Add(new LineBreak());\r
+                        inlines.Add(new LineBreak());\r
+                        break;\r
+                    case "br":\r
+                       if (sb.Length > 0)\r
+                        {\r
+                            setStringAvoidEmpty(inlines, sb.ToString());\r
+                            sb.Clear();\r
+                        }\r
+                        inlines.Add(new LineBreak());\r
+                        break;\r
+                    case "p":\r
+                        if (sb.Length > 0)\r
+                        {\r
+                            setStringAvoidEmpty(inlines, sb.ToString());\r
+                            sb.Clear();\r
+                        }\r
+                        if (elem.getChildren().Count == 0)\r
+                            break;\r
+                        if (elem.tryGetVisibility(out visibility))\r
+                        {\r
+                            if (visibility == css.Property.Visibility.Collapse ||\r
+                                visibility == css.Property.Visibility.Hidden)\r
+                            {\r
+                                break;\r
+                            }\r
+                        }\r
+                        //span = new Span();\r
+                        //tb = new TextBlock();\r
+                        //tb.Margin = new System.Windows.Thickness(0);\r
+                        //tb.Padding = new System.Windows.Thickness(0);\r
+                        para = new Paragraph();\r
+                        fl = new Floater(para);\r
+                        fl.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;\r
+                        //fl.Width = double.NaN;\r
+                        //tb.TextWrapping = System.Windows.TextWrapping.Wrap;\r
+                        //tb.TextAlignment = System.Windows.TextAlignment.Left;\r
+                        //tb.HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch;\r
+                        //span.Inlines.Add(tb);\r
+                        Html2FlowDoc.applyCSSProperiesForElement(elem, para);\r
+                        //inlines.Add(new LineBreak());\r
+                        inlines.Add(fl);\r
+                        drawHtmlForInlines(adapter, para.Inlines, thread, res, elem);\r
+                        //if (!findLastLineBreak(inlines))\r
+                        //{                            \r
+                        //inlines.Add(new LineBreak());\r
+                        //}\r
+                        break;\r
+                    case "div":\r
+                        if (sb.Length > 0)\r
+                        {\r
+                            setStringAvoidEmpty(inlines, sb.ToString());\r
+                            sb.Clear();\r
+                        }\r
+                        if (elem.getChildren().Count == 0)\r
+                            break;\r
+                        if (elem.tryGetVisibility(out visibility))\r
+                        {\r
+                            if (visibility == css.Property.Visibility.Collapse ||\r
+                                visibility == css.Property.Visibility.Hidden)\r
+                            {\r
+                                break;\r
+                            }\r
+                        }\r
+                        //span = new Span();\r
+                        //tb = new TextBlock();\r
+                        //tb.Margin = new System.Windows.Thickness(0);\r
+                        //tb.Padding = new System.Windows.Thickness(0);\r
+                        //para = new Paragraph();\r
+                        Section sec = new Section();\r
+                        fl = new Floater(sec);\r
+                        fl.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;\r
+                        //fl.Width = double.NaN;\r
+                        //tb.TextWrapping = System.Windows.TextWrapping.Wrap;\r
+                        //tb.TextAlignment = System.Windows.TextAlignment.Left;\r
+                        //tb.HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch;\r
+                        //span.Inlines.Add(tb);\r
+                        Html2FlowDoc.applyCSSProperiesForElement(elem, sec);\r
+                        //inlines.Add(new LineBreak());\r
+                        inlines.Add(fl);\r
+                        drawHtmlForBlocks(adapter, sec.Blocks, thread, res, elem);\r
+                        //if (!findLastLineBreak(inlines))\r
+                        //{                            \r
+                        //inlines.Add(new LineBreak());\r
+                        //}\r
+                        break;\r
+                    case "span":\r
+                         if (sb.Length > 0)\r
+                        {\r
+                            setStringAvoidEmpty(inlines, sb.ToString());\r
+                            sb.Clear();\r
+                        }\r
+                        if (elem.tryGetVisibility(out visibility))\r
+                        {\r
+                            if (visibility == css.Property.Visibility.Collapse ||\r
+                                visibility == css.Property.Visibility.Hidden)\r
+                            {\r
+                                break;\r
+                            }\r
+                        }\r
+                        span = new Span();\r
+                        Html2FlowDoc.applyCSSProperiesForElement(elem, span);\r
+                        inlines.Add(span);\r
+                        drawHtmlForInlines(adapter, span.Inlines, thread, res, elem);\r
+                       break;\r
+                    case "a":\r
+                       if (sb.Length > 0)\r
+                       {\r
+                           setStringAvoidEmpty(inlines, sb.ToString());\r
+                           sb.Clear();\r
+                       }\r
+                       if (elem.tryGetVisibility(out visibility))\r
+                       {\r
+                           if (visibility == css.Property.Visibility.Collapse ||\r
+                               visibility == css.Property.Visibility.Hidden)\r
+                           {\r
+                               break;\r
+                           }\r
+                       }\r
+                       string url = elem.getAttributeValue("href");\r
+                       hLink = new Hyperlink();\r
+                       if (url != null)\r
+                       {\r
+                           /*if (adapter.chkGraphicLink(url))\r
+                           {\r
+                               ThumbnailImageHelper helper =\r
+                                   ThumbnailImageHelper.CreateInstance(url);\r
+                               inlines.Add(helper.GetContainer());\r
+                               adapter.setThumbnailImage(helper, url);\r
+                           }*/\r
+                           try\r
+                           {\r
+                               hLink.NavigateUri = new Uri(url);\r
+                               hLink.Click += adapter.urlLink_Click;\r
+                           }\r
+                           catch (UriFormatException e)\r
+                           {\r
+                           }\r
+                       }\r
+                       Html2FlowDoc.applyCSSProperiesForElement(elem, hLink);\r
+                       inlines.Add(hLink);\r
+                       drawHtmlForInlines(adapter, hLink.Inlines, thread, res, elem);\r
+                       break;\r
+                    case "img":\r
+                       if (sb.Length > 0)\r
+                       {\r
+                           setStringAvoidEmpty(inlines, sb.ToString());\r
+                           sb.Clear();\r
+                       }\r
+                       if (elem.tryGetVisibility(out visibility))\r
+                       {\r
+                           if (visibility == css.Property.Visibility.Collapse ||\r
+                               visibility == css.Property.Visibility.Hidden)\r
+                           {\r
+                               break;\r
+                           }\r
+                       }\r
+                       url = elem.getAttributeValue("src");\r
+                       hLink = new Hyperlink();\r
+                       if (url != null)\r
+                       {\r
+                           if (chkLocalPath(url))\r
+                           {\r
+                               Image img;\r
+                               if (elem.tryGetImage(out img, url))\r
+                               {\r
+                                   inlines.Add(new InlineUIContainer(img));\r
+                               }\r
+                           }\r
+                           else\r
+                           {\r
+                               ThumbnailImageHelper helper =\r
+                                    ThumbnailImageHelper.CreateInstance(url);\r
+                               inlines.Add(helper.GetContainer());\r
+                               adapter.setThumbnailImage(helper, url);\r
+                               hLink.NavigateUri = new Uri(url);\r
+                               hLink.Click += adapter.urlLink_Click;\r
+                           }\r
+                       }\r
+                       Html2FlowDoc.applyCSSProperiesForElement(elem, hLink);\r
+                       inlines.Add(hLink);\r
+                       //drawHtmlForInlines(adapter, hLink.Inlines, thread, res, elem);\r
+                       break;\r
+                }\r
+            }\r
+            if (sb.Length > 0)\r
+            {\r
+                setStringAvoidEmpty(inlines, sb.ToString());\r
+                sb.Clear();\r
+            }\r
+            return true;\r
+        }\r
+#if false\r
+        private static  bool aaafindLastLineBreak(InlineCollection inlines)\r
+        {\r
+            int n = findLastLineBreak_sub(inlines);\r
+            if (n == 1 || n == 2)\r
+                return true;\r
+            else\r
+                return false;\r
+        }\r
+\r
+        private static int findLastLineBreak_sub(InlineCollection inlines)\r
+        {\r
+            int state = 0;\r
+            foreach (Inline i1 in inlines)\r
+            {\r
+                LineBreak lb = i1 as LineBreak;\r
+                if (lb != null)\r
+                    state = 1;\r
+                else\r
+                {\r
+                    Run run = i1 as Run;\r
+                    if (run != null)\r
+                    {\r
+                        string s = run.Text;\r
+                        if (s.Length == 0 || " ".Equals(s))\r
+                        {\r
+                            if (state == 1)\r
+                                state = 2;\r
+                        }\r
+                        else\r
+                        {\r
+                            state = 3;\r
+                        }\r
+                    }\r
+                    else\r
+                    {\r
+                        Span span = i1 as Span;\r
+                        if (span != null)\r
+                        {\r
+                            if (span.Inlines.FirstInline != null)\r
+                            {\r
+                                int n = findLastLineBreak_sub(span.Inlines);\r
+                                if (n == 1)\r
+                                    state = 1;\r
+                                else if (n == 2)\r
+                                    state = 2;\r
+                                else if (n == 3)\r
+                                    state = 3;\r
+                            }\r
+                            else\r
+                            {\r
+                                if (state == 1 || state == 2)\r
+                                    state = 2;\r
+                                else\r
+                                    state = 0;\r
+                            }\r
+                        }\r
+                        else\r
+                        {\r
+                            state = 3;\r
+                        }\r
+                    }\r
+                }\r
+            }\r
+            return state;\r
+        }\r
+#endif\r
+        private static void setStringAvoidEmpty(InlineCollection inlines, string source)\r
+        {\r
+            string s = convertHtmlString(source);\r
+            if (s.Length == 0)\r
+                return;\r
+            inlines.Add(s);\r
+        }\r
+        private static string convertHtmlString(string source)\r
+        {\r
+            int state = 0;\r
+            int length = source.Length;\r
+            StringBuilder sb = new StringBuilder(length);\r
+            for (int i = 0; i < length; i++)\r
+            {\r
+                char c = source[i];\r
+                switch(c){\r
+                    case ' ':\r
+                    case '\t':\r
+                    case '\r':\r
+                    case '\n':\r
+                        state = 1;\r
+                        break; \r
+                    case '&':\r
+                        int retLen;\r
+                        if ((i + 1 < source.Length) && source[i + 1] == '#')\r
+                        {\r
+                            c = HtmlEscape.parseHTMLDecimalHexEscape(source, i + 2, out retLen);\r
+                            if (c != '\0')\r
+                            {\r
+                                //if (start < i)\r
+                                //    sb.Append(source.Substring(start, i - start));\r
+                                sb.Append(c);\r
+                                //start = retLen;\r
+                                i = retLen - 1;\r
+\r
+                            }\r
+                        }\r
+                        else\r
+                        {\r
+                            c = HtmlEscape.HTMLEscapeTable.getCodeFromEscape(source, i + 1, out retLen);\r
+                            if (c != '\0')\r
+                            {\r
+                                //if (start < i)\r
+                                //    sb.Append(source.Substring(start, i - start));\r
+                                sb.Append(c);\r
+                                //start = retLen;\r
+                                i = retLen - 1;\r
+                            }\r
+                        }\r
+\r
+                        break;\r
+                    default:\r
+                        if(state == 1)\r
+                            sb.Append(' ');\r
+                        sb.Append(c);\r
+                        state = 0;\r
+                        break;\r
+                }\r
+            }\r
+            if(state == 1)\r
+                sb.Append(' ');\r
+\r
+            return sb.ToString();\r
+        }\r
+        public static bool MargeResDataIntoHtml(HtmlElement rootElement,\r
+            IThread ithread, IRes res, \r
+            bool newMsg,  bool msgOwner, bool reply,\r
+            bool bookmark, bool asciiart,\r
+            string ngword, string ngname, string ngid, IAmbiguousSearch search)\r
+        {\r
+            HtmlElement hElem;\r
+            HtmlAttribute hAttr;\r
+            StringElement sElem;\r
+            string backRefText;\r
+\r
+            string msg = res.getMsg();\r
+            string id = res.getID();\r
+            string name = res.getName();\r
+            string email = res.getMail();\r
+            string date = res.getDate();\r
+\r
+            int[] refArray = res.getReferenceArray();\r
+\r
+            List<HtmlElement> rList = rootElement.getElements(\r
+                null, "body", null, null, null, false);\r
+            if (rList == null || rList.Count != 1)\r
+                return false;\r
+\r
+            List<HtmlElement> elems =\r
+                rList[0].getElements(null, null, null, "sequence", null, true);\r
+            if (elems != null && elems.Count > 0)\r
+            {\r
+                foreach (HtmlElement elem in elems)\r
+                {\r
+                    elem.setInnerText(res.getSequenceNo().ToString());\r
+                }\r
+            }\r
+\r
+            elems = rList[0].getElements(null, null, null, "uname", null, true);\r
+            if (elems != null && elems.Count > 0)\r
+            {\r
+                foreach (HtmlElement elem in elems)\r
+                {\r
+                    elem.setInnerText(res.getName());\r
+                }\r
+            }\r
+\r
+            elems = rList[0].getElements(null, null, null, "email", null, true);\r
+            if (elems != null && elems.Count > 0)\r
+            {\r
+                foreach (HtmlElement elem in elems)\r
+                {\r
+                    elem.setInnerText(res.getMail());\r
+                }\r
+            }\r
+\r
+            elems = rList[0].getElements(null, null, null, "datetime", null, true);\r
+            if (elems != null && elems.Count > 0)\r
+            {\r
+                foreach (HtmlElement elem in elems)\r
+                {\r
+                    elem.setInnerText(res.getDate());\r
+                }\r
+            }\r
+\r
+            elems = rList[0].getElements(null, null, null, "identifier", null, true);\r
+            if (elems != null && elems.Count > 0)\r
+            {\r
+                DebugContext ctx = new DebugContext();\r
+                foreach (HtmlElement elem in elems)\r
+                {\r
+                    string innerHtml = getResIdHtml(ithread, res);\r
+                    elem.setInnerText(innerHtml);\r
+                    //elem.clearChildren();\r
+                    //if (0 > HtmlParser.parseElement(ctx, elem, innerHtml, 0))\r
+                    //    continue;\r
+                    elem.addAttribute(new HtmlAttribute("id-link", res.getID()));\r
+                }\r
+            }\r
+\r
+            elems = rList[0].getElements(null, null, null, "msg", null, true);\r
+            if (elems != null && elems.Count > 0)\r
+            {\r
+                foreach (HtmlElement elem in elems)\r
+                {\r
+                    elem.setInnerResHtml(res.getMsg(), search);\r
+                }\r
+            }\r
+\r
+            if (ngword != null)\r
+            {\r
+                elems = rList[0].getElements(null, null, null, "ngword", null, true);\r
+                if (elems != null && elems.Count > 0)\r
+                {\r
+                    foreach (HtmlElement elem in elems)\r
+                    {\r
+                        elem.setInnerText(ngword);\r
+                    }\r
+                }\r
+            }\r
+            if (ngname != null)\r
+            {\r
+                elems = rList[0].getElements(null, null, null, "ngname", null, true);\r
+                if (elems != null && elems.Count > 0)\r
+                {\r
+                    foreach (HtmlElement elem in elems)\r
+                    {\r
+                        elem.setInnerText(ngname);\r
+                    }\r
+                }\r
+            }\r
+            if (ngid != null)\r
+            {\r
+                elems = rList[0].getElements(null, null, null, "ngid", null, true);\r
+                if (elems != null && elems.Count > 0)\r
+                {\r
+                    foreach (HtmlElement elem in elems)\r
+                    {\r
+                        elem.setInnerText(ngid);\r
+                    }\r
+                }\r
+            }\r
+\r
+            if (refArray != null && refArray.Length > 0)\r
+            {\r
+                backRefText = formatReferenceNumbers(refArray);\r
+                if (backRefText != null)\r
+                {\r
+                    backRefText = "<<" + backRefText;\r
+                    elems = rList[0].getElements(null, null, null, "backwardreferences", null, true);\r
+                    if (elems != null && elems.Count > 0)\r
+                    {\r
+                        foreach (HtmlElement elem in elems)\r
+                        {\r
+                            hElem = new HtmlElement(elem, "span");\r
+                            hAttr = new HtmlAttribute("res-link");\r
+                            hElem.addAttribute(hAttr);\r
+                            sElem = new StringElement(hElem, backRefText);\r
+                        }\r
+                    }\r
+                }\r
+            }\r
+\r
+\r
+            List<string> cList = new List<string>(1);\r
+            cList.Add("resparam");\r
+            elems = rList[0].getElements(null, null, cList, null,  null, true);\r
+            if (elems != null && elems.Count > 0)\r
+            {\r
+                foreach (HtmlElement elem in elems)\r
+                {\r
+                    //List<string> cList2 = elem.getClasses();\r
+                    if (newMsg)\r
+                        elem.addAttribute(new HtmlAttribute("new-message"));\r
+                    if (msgOwner)\r
+                        elem.addAttribute(new HtmlAttribute("message-owner"));\r
+                    if (reply)\r
+                        elem.addAttribute(new HtmlAttribute("reply-message"));\r
+                    if (bookmark)\r
+                        elem.addAttribute(new HtmlAttribute("bookmark"));\r
+                    if (asciiart)\r
+                        elem.addAttribute(new HtmlAttribute("ascii-art"));\r
+                    if (refArray != null && refArray.Length > 0)\r
+                        elem.addAttribute(new HtmlAttribute("backwardreferences"));\r
+                    if(ngword != null)\r
+                        elem.addAttribute(new HtmlAttribute("ngword"));\r
+                    if(ngname != null)\r
+                        elem.addAttribute(new HtmlAttribute("ngname"));\r
+                    if(ngid != null)\r
+                        elem.addAttribute(new HtmlAttribute("ngid"));\r
+                }\r
+            }\r
+            return true;\r
+        }\r
+        private static string formatReferenceNumbers(int[] valList)\r
+        {\r
+            if (null == valList) { return null; }\r
+            if (0 >= valList.Length) { return null; }\r
+\r
+            StringBuilder buf = new StringBuilder();\r
+            //buf.Append("<<");\r
+\r
+            bool flagFirst = true;\r
+\r
+            int prevVal = 0;\r
+            int i = 0;\r
+            for (; i < valList.Length - 1; i++)\r
+            {\r
+                int val1 = valList[i];\r
+                int val2 = valList[i + 1];\r
+                if (val1 == val2 - 1)\r
+                {\r
+                    if (0 == prevVal)\r
+                    {\r
+                        prevVal = val1;\r
+                    }\r
+                }\r
+                else\r
+                {\r
+                    if (!flagFirst)\r
+                    {\r
+                        buf.Append(',');\r
+                    }\r
+                    else\r
+                    {\r
+                        flagFirst = false;\r
+                    }\r
+                    if (0 != prevVal)\r
+                    {\r
+                        buf.Append(prevVal.ToString());\r
+                        buf.Append('-');\r
+                        buf.Append(val1.ToString());\r
+                        prevVal = 0;\r
+                    }\r
+                    else\r
+                    {\r
+                        buf.Append(val1.ToString());\r
+                    }\r
+                }\r
+            }\r
+\r
+            if (!flagFirst)\r
+            {\r
+                buf.Append(',');\r
+            }\r
+            if (0 != prevVal)\r
+            {\r
+                buf.Append(prevVal.ToString());\r
+                buf.Append('-');\r
+                buf.Append(valList[i].ToString());\r
+            }\r
+            else\r
+            {\r
+                buf.Append(valList[i].ToString());\r
+            }\r
+\r
+            return buf.ToString();\r
+        }\r
+\r
+        private static string getResIdHtml(IThread ithread, IRes ires)\r
+        {\r
+            StringBuilder sb = new StringBuilder();\r
+            //Span span;\r
+            //Run r;\r
+            string id = ires.getID();\r
+            if (id != null && id.Length > 0)\r
+            {\r
+                int before = 0;\r
+                int after = 0;\r
+                bool chk = false;\r
+                List<IRes> rList = ithread.getResList();\r
+                List<int> arrSeqNum = new List<int>();\r
+                if (rList != null)\r
+                {\r
+                    int rCnt = rList.Count;\r
+                    for (int i = 0; i < rCnt; i++)\r
+                    {\r
+                        if (!id.Equals(rList[i].getID()))\r
+                            continue;\r
+\r
+                        arrSeqNum.Add(rList[i].getSequenceNo());\r
+                        if (ires.Equals(rList[i]))\r
+                        {\r
+                            chk = true;\r
+                            continue;\r
+                        }\r
+\r
+\r
+                        if (chk)\r
+                            after++;\r
+                        else\r
+                            before++;\r
+                    }\r
+                }\r
+                if (0 < (before + after))\r
+                {\r
+                    //List<object> param = new List<object>();\r
+                    //param.Add(thread);\r
+                    //param.Add(arrSeqNum.ToArray());\r
+                    sb.Append("ID:").Append(id).Append('(').Append(before + 1).Append('/').Append(before + after + 1).Append(')');\r
+                    //Hyperlink hl = new Hyperlink(new Run(id + "(" + (before + 1) + "/" + (before + after + 1) + ")"));\r
+                    //hl.Tag = param;\r
+                    //if (topItem)\r
+                    //{\r
+                    //if (getEnablePopupMouseHover())\r
+                    //    hl.MouseEnter += resLink_MouseEnter;\r
+                    //else\r
+                    //    hl.Click += resLink_MouseEnter;\r
+                    /*}\r
+                    else\r
+                    {\r
+                        if (getEnablePopupMouseHover())\r
+                            hl.MouseEnter += resLinkSubItem_MouseEnter;\r
+                        else\r
+                            hl.Click += resLinkSubItem_MouseEnter;\r
+                    }*/\r
+                    //inlines.Add(hl);\r
+                }\r
+                else\r
+                {\r
+                    sb.Append("ID:").Append(id);\r
+                    //r = new Run();\r
+                    //r.Text = id;\r
+                    //span = new Span();\r
+                    //span.Foreground = Brushes.Black;\r
+                    //span.Inlines.Add(r);\r
+                    //inlines.Add(span);\r
+                }\r
+            }\r
+            return sb.ToString();\r
+        }\r
+\r
+        private static List<int> collectResId(IThread ithread, string id)\r
+        {\r
+            List<IRes> rList = ithread.getResList();\r
+            List<int> arrSeqNum = new List<int>();\r
+            if (rList != null)\r
+            {\r
+                int rCnt = rList.Count;\r
+                for (int i = 0; i < rCnt; i++)\r
+                {\r
+                    if (!id.Equals(rList[i].getID()))\r
+                        continue;\r
+\r
+                    arrSeqNum.Add(rList[i].getSequenceNo());\r
+\r
+                }\r
+            }\r
+            return arrSeqNum; \r
+        }\r
+    }\r
+}\r
diff --git a/NT2chCtrl45/html/wpf/ImageCash.cs b/NT2chCtrl45/html/wpf/ImageCash.cs
new file mode 100755 (executable)
index 0000000..ff811ce
--- /dev/null
@@ -0,0 +1,75 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.IO;\r
+using System.Text;\r
+using System.Windows.Controls;\r
+using System.Windows.Media.Imaging;\r
+\r
+namespace NT2chCtrl.html.wpf\r
+{\r
+    class ImageCash\r
+    {\r
+        private static string mBasePath;\r
+        private static Dictionary<string, BitmapImage> mImageCash = new Dictionary<string, BitmapImage>();\r
+        public static void init(string basePath)\r
+        {\r
+            mBasePath = basePath;\r
+        }\r
+\r
+        public static BitmapImage getBitmapImage(string path)\r
+        {\r
+            string imagePath = parseImagePath(path);\r
+            if (imagePath == null)\r
+                return null;\r
+            BitmapImage bImg;\r
+\r
+            if (mImageCash.TryGetValue(imagePath, out bImg))\r
+                return bImg;\r
+\r
+            if (!File.Exists(imagePath))\r
+                return null;\r
+            try\r
+            {\r
+                bImg = new BitmapImage();\r
+\r
+                bImg.BeginInit();\r
+\r
+                bImg.CacheOption = BitmapCacheOption.OnDemand;\r
+                bImg.CreateOptions = BitmapCreateOptions.DelayCreation;\r
+                bImg.UriSource = new Uri(imagePath, UriKind.Absolute);\r
+\r
+                bImg.EndInit();\r
+            }\r
+            catch (Exception)\r
+            {\r
+                return null;\r
+            }\r
+            mImageCash.Add(imagePath, bImg);\r
+            return bImg;\r
+        }\r
+        private static string parseImagePath(string path)\r
+        {\r
+            int idx = path.IndexOf(":\\");\r
+            if (idx >= 0)\r
+            {\r
+                if (idx == 1)\r
+                {\r
+                    char c = path[0];\r
+                    if((c >= 'a' && c <= 'z')||(c >= 'A' && c <= 'Z'))\r
+                        return path;\r
+                }\r
+                return null;\r
+            }\r
+            idx = path.IndexOf("://");\r
+            if (idx >= 0)\r
+                return null;\r
+            path = path.Trim();\r
+            if (path.Length == 0)\r
+                return null;\r
+            if (path[0] == '\\')\r
+                return mBasePath + path;\r
+            else\r
+                return mBasePath + "\\" + path;\r
+        }\r
+    }\r
+}\r
diff --git a/NT2chObject45/NT2chObject45.csproj b/NT2chObject45/NT2chObject45.csproj
new file mode 100755 (executable)
index 0000000..d5d00e0
--- /dev/null
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />\r
+  <PropertyGroup>\r
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>\r
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>\r
+    <ProjectGuid>{4E9CECF8-7DEA-45DB-9B25-D3F768A10C4B}</ProjectGuid>\r
+    <OutputType>Library</OutputType>\r
+    <AppDesignerFolder>Properties</AppDesignerFolder>\r
+    <RootNamespace>NT2chObject45</RootNamespace>\r
+    <AssemblyName>NT2chObject45</AssemblyName>\r
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>\r
+    <FileAlignment>512</FileAlignment>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">\r
+    <DebugSymbols>true</DebugSymbols>\r
+    <DebugType>full</DebugType>\r
+    <Optimize>false</Optimize>\r
+    <OutputPath>bin\Debug\</OutputPath>\r
+    <DefineConstants>TRACE;DEBUG;DOTNET45</DefineConstants>\r
+    <ErrorReport>prompt</ErrorReport>\r
+    <WarningLevel>4</WarningLevel>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">\r
+    <DebugType>pdbonly</DebugType>\r
+    <Optimize>true</Optimize>\r
+    <OutputPath>bin\Release\</OutputPath>\r
+    <DefineConstants>TRACE;DOTNET45</DefineConstants>\r
+    <ErrorReport>prompt</ErrorReport>\r
+    <WarningLevel>4</WarningLevel>\r
+  </PropertyGroup>\r
+  <PropertyGroup>\r
+    <SignAssembly>false</SignAssembly>\r
+  </PropertyGroup>\r
+  <PropertyGroup>\r
+    <AssemblyOriginatorKeyFile>\r
+    </AssemblyOriginatorKeyFile>\r
+  </PropertyGroup>\r
+  <ItemGroup>\r
+    <Reference Include="PresentationCore" />\r
+    <Reference Include="PresentationFramework" />\r
+    <Reference Include="System" />\r
+    <Reference Include="System.Core" />\r
+    <Reference Include="System.Xaml" />\r
+    <Reference Include="System.Xml.Linq" />\r
+    <Reference Include="System.Data.DataSetExtensions" />\r
+    <Reference Include="Microsoft.CSharp" />\r
+    <Reference Include="System.Data" />\r
+    <Reference Include="System.Xml" />\r
+    <Reference Include="WindowsBase" />\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <Compile Include="NTConstants.cs" />\r
+    <Compile Include="NTInterfaceDecl.cs" />\r
+    <Compile Include="NTThread.cs" />\r
+    <Compile Include="Properties\AssemblyInfo.cs" />\r
+    <Compile Include="ThumbnailImageHelper.cs" />\r
+  </ItemGroup>\r
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />\r
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. \r
+       Other similar extension points exist, see Microsoft.Common.targets.\r
+  <Target Name="BeforeBuild">\r
+  </Target>\r
+  <Target Name="AfterBuild">\r
+  </Target>\r
+  -->\r
+</Project>
\ No newline at end of file
diff --git a/NT2chObject45/NTConstants.cs b/NT2chObject45/NTConstants.cs
new file mode 100755 (executable)
index 0000000..82a8fdd
--- /dev/null
@@ -0,0 +1,54 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+\r
+namespace NT2chObject\r
+{\r
+    //IUtil.getPreference()で取得した辞書オブジェクトから値を取り出す検索キー\r
+    public enum PREF_PARAM\r
+    {\r
+        //レス表示に指定されたフォントタイプフェイス \r
+        //型 string 入出力[out]\r
+        RES_VIEW_FONT_TYPEFACE,\r
+        //レス表示に指定されたAA判定時のフォントタイプフェイス\r
+        //型 string 入出力[out]\r
+        //未指定時はnull\r
+        RES_VIEW_AA_FONT_TYPEFACE,\r
+        //AA判定に使用する文字列の配列 \r
+        //型 string[] 入出力[out]\r
+        RES_VIEW_AA_STRING_LIST,\r
+        //レス表示に使用するZOOM値の設定 (オブジェクト double型の文字列表現) \r
+        //型string 入出力[in, out]\r
+        RES_VIEW_ZOOM_VALUE,\r
+        //マウスホーバーでポップアップを表示する \r
+        //型string 入出力[out]\r
+        RES_VIEW_POPUP_MOUSEHOVER,\r
+      \r
+        //レスビューでサムネイル画像を表示する\r
+        RES_VIEW_SHOW_THUMBNAIL,\r
+\r
+        //サムネイル画像のサイズ(横幅)\r
+        RES_VIEW_THUMBNAIL_WIDTH,\r
+\r
+        //サムネイル画像のサイズ(高さ)\r
+        RES_VIEW_THUMBNAIL_HEIGHT,\r
+\r
+        //レス画面のテキスト選択モード\r
+        RES_VIEW_TEXTSEL_MODE,\r
+\r
+        //スレタイ表示リストビューのフォントサイズ\r
+        THREADTITLE_LIST_FONT_SIZE,\r
+\r
+        //デバッグモード(True / False)\r
+        DEGUB_MODE\r
+    }\r
+    /*\r
+     * レスオブジェクトが特定の属性を持つかを判定する時に使用します。 \r
+     */\r
+    public enum RES_ATTRIBUTE\r
+    {\r
+        MYMESSAGE,//自分の書込\r
+        REPRY,//自分への返信\r
+        BOOKMARK//しおりを付けたレス\r
+    }\r
+}\r
diff --git a/NT2chObject45/NTInterfaceDecl.cs b/NT2chObject45/NTInterfaceDecl.cs
new file mode 100755 (executable)
index 0000000..5f88a5a
--- /dev/null
@@ -0,0 +1,336 @@
+using NT2chObject;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Windows.Controls;\r
+\r
+\r
+namespace NT2chObject\r
+{\r
+    /*\r
+     * アプリケーションフレームワークとの通信に使用します。\r
+     * コントロール初期化時に設定されます。\r
+     */\r
+    public interface ICommand\r
+    {\r
+        //アプリケーションでサポートしているAPIのバージョンを取得します。\r
+        int GetApplicationApiVersion();\r
+        //このコントロールの永続的なデータを保存する為のフォルダーのパスを取得します。\r
+        string GetDataPath();\r
+\r
+        //アプリケーションの設定画面でユーザーが指定した値を取得します。\r
+        //取得した値はプロセスの生存期間中有効で有り、ユーザーが設定画面で\r
+        //編集すると、この値も反映されます。\r
+        //この動作が適さない場合、取得したデータをコピーして下さい。\r
+        //※NTConstants.csのPREF_PARAMも参照して下さい\r
+        Dictionary<PREF_PARAM, object> GetPreference();\r
+\r
+        //スレッドディスクリプターを指定して、フレームワークに\r
+        //スレッドを開くように要求します\r
+        void OpenThread(IThreadDescription threaDesc);\r
+\r
+        //スレッドディスクリプターを指定して、フレームワークに\r
+        //スレッドをお気に入りに追加するように要求します\r
+        bool AddThreadToFavorite(IThreadDescription threaDesc);\r
+        //スレッドディスクリプターを指定して、フレームワークに        \r
+        //レスにブックマークをつけるように要求します\r
+        bool AddBookmark(IThread ithread, IRes ires);\r
+        //レスにブックマークをつけるように要求します\r
+        bool DeleteBookmark(IThread ithread, IRes ires);\r
+        //スレッドを指定して、書き込み用のダイアログを開きます。\r
+        //メッセージの初期値を指定できます。\r
+        //指定する値がない場合、nullを指定できます。\r
+        bool WriteMessage(IThread ithread, string message);\r
+\r
+        bool CreateThread(IBoard iboard, string title, string message);\r
+        void ShowThreadInfoWindow(string title, string address);\r
+\r
+        //板オブジェクトを指定して、板を開きます。\r
+        void TryToOpenBoard(IBoard board);\r
+\r
+        //URLを指定して、外部プログラムを実行します。\r
+        void ExecURL(string url);\r
+\r
+        //NGワード編集ダイアログを開きます。\r
+        //iresを指定すると、そのレスからNGに指定する各項目の文字列を\r
+        //抽出して初期設定します。\r
+        void ShowNgwordDialog(IRes ires);\r
+\r
+        //設定されているNGワード文字列のリストを取得します\r
+        //返される値はプレーンな複数行テキストで、現時点で\r
+        //オリジナル実装では行毎に一つのNGワードとして判定することを想定しています。\r
+        //将来的な拡張の為に推奨する書式は以下になります\r
+        // [板名!dat番号]ngワード\r
+        // 例:[ニュース速報!1311837176]あああ\r
+        //先頭に角カッコがあるNGワードを指定する場合、先頭に空の角カッコを付加します[]\r
+        //上記は、板ごと、スレッド毎のNGワードを指定する為の書式です。\r
+        //板毎のNGワードを指定するときはdat番号を省略します。\r
+        string[] GetNgWordList();\r
+\r
+        //設定されているNG-ID文字列のリストを取得します\r
+        string[] GetNgIdList();\r
+\r
+        //設定されているNG-NAME文字列のリストを取得します\r
+        string[] GetNgNameList();\r
+\r
+        void SetThumbnailImage(ThumbnailImageHelper helper, string url);\r
+\r
+    }\r
+\r
+    public interface ICommand2 :  ICommand\r
+    {\r
+        //スレッドディスクリプターを指定して、フレームワークに\r
+        //スレッドをお気に入りに追加するように要求します\r
+        void AddBoardToFavorite(IBoard iboard);\r
+       \r
+        //スレッドディスクリプターを指定して、フレームワークに\r
+        //スレッドをお気に入りから削除するように要求します\r
+        bool RemoveThreadFromFavorite(IThreadDescription threaDesc);\r
+\r
+        //指定したスレッドの取得済ログを消去します\r
+        //クラウド同期が有効な場合、クラウドの同期情報も削除されます。\r
+        void DeleteLog(IThread ithread);\r
+\r
+        //指定した板に含まれるスレッドの全ての取得済ログを消去します\r
+        //クラウド同期が有効な場合、クラウドの同期情報も削除されます。\r
+        void DeleteLog(IBoard iboard);\r
+\r
+        //板オブジェクトを指定して、板を更新します。\r
+        void UpdateBoard(IBoard board);\r
+\r
+        //指定したスレッドと類似したタイトルを持つ\r
+        //スレッドを検索します。表示方法はフレームワークが\r
+        //決定するので、呼び出し側ではコールバックを受け取りません\r
+        void SearchSimilarTitle(IThread2 ithread);\r
+    }  \r
+    /*\r
+     * 汎用的に使えるように用意したユーティリティメソッドです。\r
+     * コントロール初期化時にアプリケーションフレームワークから\r
+     * 設定されます。\r
+     */\r
+    public interface IUtil\r
+    {\r
+        //2チャンネルのレス参照フォーマットを判定し、\r
+        //有効フォーマットと判定された文字数を返します。\r
+        //例:>>1-10    >12,14,21 など。一つ目は6を返します。二つ目は9を返します。\r
+        //文字列が有効なフォーマットで始まっていない場合、-1を返します。\r
+        //source 判定する文字列 \r
+        //startPosition 判定を開始する位置を指定します。\r
+        int ParseResLinkReference(string source, int startPosition);\r
+\r
+        //上記のフォーマットから、参照しているレス番号の整数値の配列を取得します。\r
+        int[] ParseResLinkReferenceNumber(string source);\r
+\r
+        //startIndexから始まる文字列sourceが有効なURLで有るかを判定します。\r
+        //戻り値 -1. 有効なURLでは無い 0以上.URLとして認識した最後の文字の次のインデックスを返します。\r
+        int ParseURLString(string source, int startIndex);\r
+\r
+        //曖昧検索オブジェクトを取得します。\r
+        //word 検索の元になる文字列。\r
+        //指定されたwordを使って、字句検索オブジェクトが生成されます。\r
+        IAmbiguousSearch CreateAmbiguousSearchInstance(string word);\r
+        //ユーザーの設定ファイルから\r
+        //レス画面用のコンテキストメニューを生成します。\r
+        void CreateResViewContextMenu(FlowDocumentScrollViewer sv);\r
+\r
+    }\r
+\r
+    /*\r
+     * ボードメニューから読み込んで生成された板オブジェクトを表します。\r
+     */\r
+    public interface IBoard : IBase\r
+    {\r
+        //板の名前を取得します。\r
+        string getName();\r
+        //板のアドレスを取得します\r
+        string getAddress();\r
+        //この板のスレッド一覧を取得します。\r
+        //※スレッドが読み込まれていない場合があります。\r
+        //その場合、NULLが返ります。\r
+        List<IThread> getThreadList();\r
+    }\r
+\r
+\r
+    /*\r
+     * Subjectファイルから読み込んで生成されたスレッドオブジェクトを表します  \r
+     */\r
+    public interface IThread : IBase\r
+    {\r
+        //このスレッドのタイトルを取得します。\r
+        string getTitle();\r
+        //このスレッドが配置されている板オブジェクトを取得します。\r
+        IBoard getBoard();\r
+        //このスレッドのDATファイル名を取得します。\r
+        string getDatName();\r
+        //このスレッドのメッセージが格納された配列\r
+        List<IRes> getResList();\r
+        //更新される前に読み込んでいたスレッドのレス数。\r
+        int getPrevReadCount();\r
+    }\r
+\r
+    public interface IThread2 : IThread\r
+    {\r
+        NTThread getDependencyObject();\r
+    }\r
+    /*\r
+     * IRes datファイルから読み込んで生成されたメッセージオブジェクトを表します\r
+     */\r
+    public interface IRes : IBase\r
+    {\r
+        //スレッド内のシーケンス番号(1を基点とする)\r
+        int getSequenceNo();\r
+        //名前欄に指定された文字列\r
+        string getName();\r
+        //メール欄に指定された文字列\r
+        string getMail();\r
+        //メッセージ本文\r
+        string getMsg();\r
+        //その他の文字列\r
+        string getMisc();\r
+        //書き込まれた日時を示す文字列\r
+        string getDate();\r
+        // IDを示す文字列\r
+        string getID();\r
+        //当該レスオブジェクトに設定されている属性を取得します。\r
+        //RES_ATTRUBUTE列挙子の値を参照して下さい。\r
+        bool getAttribute(RES_ATTRIBUTE attr);\r
+        //同じスレッド内でこのレスを参照している番号のリスト\r
+        int[] getReferenceArray();\r
+\r
+    }\r
+\r
+    public interface IBase\r
+    {\r
+        //オブジェクトに設定した追加情報を取得します。\r
+        object getExtra();\r
+        //オブジェクトのインスタンスに追加情報を設定します。\r
+        void setExtra(object o);\r
+    }\r
+\r
+    public interface ISubjectView\r
+    {\r
+        bool OpenBoard(IBoard iboard);\r
+        bool InitBoardList(List<IBoard> boardList);\r
+        void OnInitApplicationInterface(ICommand2 command, IUtil util);\r
+        IBoard GetCurrentBoard();\r
+        //このコントロールで管理している表示状態の板リストを取得する為に呼ばれます。\r
+        List<IBoard> QueryOpenedBoardList();\r
+    }\r
+    public interface ISubjectViewJump\r
+    {\r
+        //フレームワークから呼ばれます。先頭のレスにジャンプしてください。\r
+        void JumpToTop();\r
+        //フレームワークから呼ばれます。最後のレスにジャンプしてください。\r
+        void JumpToBottom();\r
+    }\r
+\r
+    /*\r
+     * レスデータをGUI画面上に表示する為にアプリケーションフレームワークから\r
+     * 呼び出す、メソッドを定義しています。\r
+     * このインターフェースを実装したコントロールを作成して\r
+     * 2ぃとちゃんの実行ファイル(NT2chView.exe)と同じフォルダーに配置します。\r
+     * \r
+     */\r
+    public interface IResView\r
+    {\r
+\r
+        //フレームワークで、スレッドが開かれた時に呼ばれます。\r
+        //渡された情報を使って、スレッドを表示して下さい。\r
+        bool OpenThread(IThread ithread);\r
+        //コントロール初期化時に、これまでに閲覧したスレッドの履歴リストが渡されます。\r
+        //呼び出し側では履歴リストを管理していません。\r
+        //アプリケーション終了時にQueryThreadReadHistoryが呼び出されて、\r
+        //コントロールが管理している履歴リストが取得されます。\r
+        bool SetThreadReadHistory(List<IThreadDescription> threadDescriptionList);\r
+        //\r
+        void OnNotifyThreadUpdated(IBoard iboard);\r
+\r
+        //このコントロールで管理しているスレッドの履歴リストを取得する為に呼ばれます。\r
+        List<IThreadDescription> QueryThreadReadHistory();\r
+        //ユーティリティ関数のポインターが設定されます。\r
+        //渡されたポインターをコピーしておきます。\r
+        //(NTResViewPanel_util.csファイルで実装されています。)\r
+        void OnInitApplicationInterface(ICommand command, IUtil util);\r
+        //現在アクティブなスレッドを確認する為に呼ばれます。\r
+        //OpenThreadで渡された識別子を返して下さい。\r
+        IThread getCurrentThread();\r
+        //オブジェクトがアンロードされる前に呼ばれます。\r
+        //ここで、オブジェクトの永続データーを保存して下さい。\r
+        void SaveCurrentState();\r
+        //レス画面でのフォントサイズ設定ツールの表示/非表示を切り替えます\r
+        void ToggleFontSetupTool();\r
+    }\r
+\r
+    //フレームワークからのジャンプコマンドをサポートする\r
+    //コントロールはこのインターフェースをサポートして下さい。\r
+    public interface IResViewJump\r
+    {\r
+        //フレームワークから呼ばれます。先頭のレスにジャンプしてください。\r
+        void JumpToTop();\r
+        //フレームワークから呼ばれます。最後のレスにジャンプしてください。\r
+        void JumpToBottom();\r
+        //フレームワークから呼ばれます。新着のレスにジャンプしてください。\r
+        void JumpToNew();\r
+        //フレームワークから呼ばれます。ブックマークの付いたレスに順番に\r
+        //ジャンプしてください。\r
+        void JumpToNextBookmark();\r
+    }\r
+    //アプリケーションのコマンドからユーザーが検索操作を行ったときに\r
+    //コントロールで検索を実行する場合に、このインターフェースをコントロールに\r
+    //実装します\r
+    public interface IResViewSearch\r
+    {\r
+        //指定された検索文字列を選択状態にして下さい。\r
+        void SetSearchWord(string searchWord);\r
+        //指定された検索文字列の後方にマッチする文字列を選択して下さい。\r
+        void SearchNext();\r
+        //指定された検索文字列の前方にマッチする文字列を選択して下さい。\r
+        void SearchPrev();\r
+    }\r
+\r
+    /*\r
+     * スレッドを特定する為の情報が記述されます。\r
+     * クラウドで同期した既読スレッドのリストを受け取ったり、\r
+     * スレッドをお気に入りに追加したり、ドラッグドロップの\r
+     * オブジェクトとして利用する事を想定しています。\r
+     * 【注意】このインターフェースを実装したオブジェクトの\r
+     * インスタンスは、必ずしも、実際に読み込んだメモリー上の\r
+     * スレッドに対応している訳では有りません。つまり、\r
+     * このインターフェースのメソッドで、必ず有効な値が\r
+     * 取得できることは(正常系であっても)保証されないと言うことです。\r
+     * \r
+     * スレッドオブジェクトの実態ではなく、単なる注文書のようなもので\r
+     * あると考えて下さい。\r
+     * コントロールの呼び出し側では、このオブジェクトの特定の実装には依存しない為、\r
+     * ユーザーコントロールがこのインターフェースを実装したインスタンスを作成して\r
+     * APIに渡すことが出来ます。\r
+     * \r
+     */\r
+    public interface IThreadDescription\r
+    {\r
+        //スレッドのタイトルを取得します。\r
+        //【注意】クラウド同期されたデータなどを取得した時に\r
+        //空の値を返す場合が有ります。\r
+        string getTitle();\r
+        //ダットファイルの名前を取得します。\r
+        //この値とIBoardオブジェクトを使って、アプリケーションフレームワークに\r
+        //スレッドを取得させることが出来ます。\r
+        string getDatName();\r
+        //このスレッドが設定されている板オブジェクトを取得します。\r
+        IBoard getBoard();\r
+    }\r
+\r
+    /**\r
+     * 曖昧検索インターフェース\r
+     * IUtil.GetIAmbiguousSearchを参照して下さい。\r
+     */\r
+    public interface IAmbiguousSearch\r
+    {\r
+        //source 検索される文字列\r
+        //startIndex sourceの検索開始基点インデックス\r
+        //out firstIndex 検索が成功したときに、\r
+        //見つかった単語のsource内の位置インデックスが返ります。\r
+        // out length 検索が成功したときにfirstIndexからの文字数が返ります\r
+        bool match(string source, int startIndex, out int firstIndex, out int length);\r
+    }\r
+ }\r
diff --git a/NT2chObject45/NTThread.cs b/NT2chObject45/NTThread.cs
new file mode 100755 (executable)
index 0000000..4422c99
--- /dev/null
@@ -0,0 +1,102 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Windows;\r
+\r
+namespace NT2chObject\r
+{\r
+    public abstract class NTThread : DependencyObject\r
+    {\r
+\r
+        public static readonly DependencyProperty SeqNoProperty;\r
+        public static readonly DependencyProperty TitleProperty;\r
+        public static readonly DependencyProperty ResCntProperty;\r
+        public static readonly DependencyProperty ReadCntProperty;\r
+        public static readonly DependencyProperty RemainCntProperty;\r
+        public static readonly DependencyProperty LastModProperty;\r
+        public static readonly DependencyProperty LastWriteProperty;\r
+        public static readonly DependencyProperty IsFavoriteProperty;\r
+\r
+        static NTThread()\r
+        {\r
+\r
+            PropertyMetadata pm1 = new PropertyMetadata(0);\r
+            PropertyMetadata pm3 = new PropertyMetadata(0, new PropertyChangedCallback(OnResCntChanged));\r
+            PropertyMetadata pm4 = new PropertyMetadata(0, new PropertyChangedCallback(OnReadCntChanged));\r
+            PropertyMetadata pm5 = new PropertyMetadata(0);\r
+            PropertyMetadata pm2 = new PropertyMetadata(string.Empty);\r
+            PropertyMetadata pm6 = new PropertyMetadata(string.Empty);\r
+            PropertyMetadata pm7 = new PropertyMetadata(string.Empty);\r
+            PropertyMetadata pm8 = new PropertyMetadata(false);\r
+\r
+            SeqNoProperty = DependencyProperty.Register("SeqNo", typeof(int), typeof(NTThread), pm1);\r
+            TitleProperty = DependencyProperty.Register("Title", typeof(string), typeof(NTThread), pm2);\r
+            ResCntProperty = DependencyProperty.Register("ResCnt", typeof(int), typeof(NTThread), pm3);\r
+            ReadCntProperty = DependencyProperty.Register("ReadCnt", typeof(int), typeof(NTThread), pm4);\r
+            RemainCntProperty = DependencyProperty.Register("RemainCnt", typeof(int), typeof(NTThread), pm5);\r
+            LastModProperty = DependencyProperty.Register("LastMod", typeof(string), typeof(NTThread), pm6);\r
+            LastWriteProperty = DependencyProperty.Register("LastWrite", typeof(string), typeof(NTThread), pm7);\r
+            IsFavoriteProperty = DependencyProperty.Register("IsFavorite", typeof(bool), typeof(NTThread), pm8);\r
+\r
+        }\r
+\r
+        public int SeqNo\r
+        {\r
+            set { SetValue(SeqNoProperty, value); }\r
+            get { return (int)GetValue(SeqNoProperty); }\r
+        }\r
+        public string Title\r
+        {\r
+            set { SetValue(TitleProperty, value); }\r
+            get { return (string)GetValue(TitleProperty); }\r
+        }\r
+        public int ResCnt\r
+        {\r
+            set { SetValue(ResCntProperty, value); }\r
+            get { return (int)GetValue(ResCntProperty); }\r
+        }\r
+        public int ReadCnt\r
+        {\r
+            set { SetValue(ReadCntProperty, value); }\r
+            get { return (int)GetValue(ReadCntProperty); }\r
+        }\r
+        public int RemainCnt\r
+        {\r
+            set { SetValue(RemainCntProperty, value); }\r
+            get { return (int)GetValue(RemainCntProperty); }\r
+        }\r
+        public string LastMod\r
+        {\r
+            set { SetValue(LastModProperty, value); }\r
+            get { return (string)GetValue(LastModProperty); }\r
+        }\r
+        public string LastWrite\r
+        {\r
+            set { SetValue(LastWriteProperty, value); }\r
+            get { return (string)GetValue(LastWriteProperty); }\r
+        }\r
+        public bool IsFavorite\r
+        {\r
+            set { SetValue(IsFavoriteProperty, value); }\r
+            get { return (bool)GetValue(IsFavoriteProperty); }\r
+        }\r
+\r
+        static void OnResCntChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)\r
+        {\r
+            NTThread t = (NTThread)d;\r
+            t.RemainCnt = (int)e.NewValue - t.ReadCnt;\r
+        }\r
+\r
+        static void OnReadCntChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)\r
+        {\r
+            NTThread t = (NTThread)d;\r
+            if (t.ResCnt < (int)e.NewValue)\r
+                t.ResCnt = (int)e.NewValue;\r
+            else\r
+                t.RemainCnt = t.ResCnt - (int)e.NewValue;\r
+        }\r
+\r
+        public abstract string getDatName();\r
+\r
+    }\r
+}\r
diff --git a/NT2chObject45/Properties/AssemblyInfo.cs b/NT2chObject45/Properties/AssemblyInfo.cs
new file mode 100755 (executable)
index 0000000..49eb0db
--- /dev/null
@@ -0,0 +1,36 @@
+using System.Reflection;\r
+using System.Runtime.CompilerServices;\r
+using System.Runtime.InteropServices;\r
+\r
+// アセンブリに関する一般情報は以下の属性セットをとおして制御されます。\r
+// アセンブリに関連付けられている情報を変更するには、\r
+// これらの属性値を変更してください。\r
+[assembly: AssemblyTitle("NT2chObject45")]\r
+[assembly: AssemblyDescription("")]\r
+[assembly: AssemblyConfiguration("")]\r
+[assembly: AssemblyCompany("")]\r
+[assembly: AssemblyProduct("NT2chObject45")]\r
+[assembly: AssemblyCopyright("Copyright ©  2013")]\r
+[assembly: AssemblyTrademark("")]\r
+[assembly: AssemblyCulture("")]\r
+\r
+// ComVisible を false に設定すると、その型はこのアセンブリ内で COM コンポーネントから \r
+// 参照不可能になります。COM からこのアセンブリ内の型にアクセスする場合は、\r
+// その型の ComVisible 属性を true に設定してください。\r
+[assembly: ComVisible(false)]\r
+\r
+// 次の GUID は、このプロジェクトが COM に公開される場合の、typelib の ID です\r
+[assembly: Guid("914ecc9d-28c8-4e63-ab59-6447f6bd830d")]\r
+\r
+// アセンブリのバージョン情報は、以下の 4 つの値で構成されています:\r
+//\r
+//      Major Version\r
+//      Minor Version \r
+//      Build Number\r
+//      Revision\r
+//\r
+// すべての値を指定するか、下のように '*' を使ってビルドおよびリビジョン番号を \r
+// 既定値にすることができます:\r
+// [assembly: AssemblyVersion("1.0.*")]\r
+[assembly: AssemblyVersion("2.3.6.0")]\r
+[assembly: AssemblyFileVersion("2.3.6.0")]\r
diff --git a/NT2chObject45/ThumbnailImageHelper.cs b/NT2chObject45/ThumbnailImageHelper.cs
new file mode 100755 (executable)
index 0000000..3b193aa
--- /dev/null
@@ -0,0 +1,154 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.ComponentModel;\r
+using System.IO;\r
+using System.Net;\r
+using System.Net.Cache;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Windows;\r
+using System.Windows.Controls;\r
+using System.Windows.Documents;\r
+using System.Windows.Media;\r
+using System.Windows.Media.Animation;\r
+using System.Windows.Media.Imaging;\r
+using System.Windows.Shapes;\r
+\r
+namespace NT2chObject\r
+{\r
+    public class ThumbnailImageHelper\r
+    {\r
+        static LineGeometry[] mLg;\r
+        static Brush mRed;\r
+        static Brush mBlue;\r
+        static Brush mBlack;\r
+        static Brush mAqua;\r
+        static Thickness mThick2;\r
+        static Thickness mThick4;\r
+\r
+        static ThumbnailImageHelper()\r
+        {\r
+            mLg = new LineGeometry[4];\r
+\r
+            mLg[0] = new LineGeometry(\r
+                 new Point(0, 0), new Point(0, 20));\r
+\r
+            mLg[1] = new LineGeometry(\r
+                new Point(0, 0), new Point(20, 0));\r
+\r
+            mLg[2] = new LineGeometry(\r
+                new Point(20, 0), new Point(20, 20));\r
+\r
+            mLg[3] = new LineGeometry(\r
+                new Point(0, 20), new Point(20, 20));\r
+\r
+            mRed = new SolidColorBrush(Colors.Red);\r
+            mBlue = new SolidColorBrush(Colors.Blue);\r
+            mBlack = new SolidColorBrush(Colors.Black);\r
+            mAqua = new SolidColorBrush(Colors.Aqua);\r
+\r
+            mThick2 = new Thickness(2);\r
+            mThick4 = new Thickness(4);\r
+\r
+        }\r
+\r
+        InlineUIContainer mContainer;\r
+        //Image mImage;\r
+\r
+        ThumbnailImageHelper(InlineUIContainer container)\r
+        {\r
+            mContainer = container;\r
+            //mImage = null;\r
+        }\r
+\r
+        public InlineUIContainer GetContainer()\r
+        {\r
+            return mContainer;\r
+        }\r
+\r
+\r
+        public static ThumbnailImageHelper\r
+            CreateInstance(string url)\r
+        {\r
+            InlineUIContainer uiContainer = new InlineUIContainer();\r
+\r
+            System.Windows.Shapes.Path path = new System.Windows.Shapes.Path();\r
+            path.Fill = mRed;\r
+            path.Opacity = 1;\r
+            path.Stroke = mBlack;\r
+            path.Margin = new Thickness(5, 0, 5, 0);\r
+            Rect rect = new Rect(9, 2, 2, 16);\r
+\r
+            GeometryGroup gg = new GeometryGroup();\r
+            //gg.FillRule = FillRule.Nonzero;\r
+\r
+            DoubleAnimation animation = new DoubleAnimation();\r
+            animation.From = 0;\r
+            animation.To = 360;\r
+            animation.Duration = TimeSpan.FromSeconds(1);\r
+            animation.RepeatBehavior = RepeatBehavior.Forever;\r
+\r
+            RotateTransform rotate = new RotateTransform(\r
+                0, 10, 10);\r
+            RectangleGeometry rg = new RectangleGeometry(rect, 0, 0, rotate);\r
+            gg.Children.Add(rg);\r
+\r
+            gg.Children.Add(mLg[0]);\r
+            gg.Children.Add(mLg[1]);\r
+            gg.Children.Add(mLg[2]);\r
+            gg.Children.Add(mLg[3]);\r
+\r
+            path.Data = gg;\r
+            uiContainer.Child = path;\r
+\r
+            ThumbnailImageHelper helper = new ThumbnailImageHelper(uiContainer);\r
+            \r
+            rotate.BeginAnimation(RotateTransform.AngleProperty, animation);\r
+\r
+            return helper;\r
+        }\r
+\r
+        public void SetImage(Image image)\r
+        {\r
+            if (image == null)\r
+                return;\r
+\r
+            Border border = new Border();\r
+            border.BorderBrush = mBlue;\r
+            border.BorderThickness = mThick2;\r
+            border.Child = image;\r
+\r
+            image.MouseEnter += image_MouseEnter;\r
+            image.MouseLeave += image_MouseLeave;\r
+\r
+            mContainer.Child = border;\r
+\r
+        }\r
+\r
+        void image_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e)\r
+        {\r
+            Image img = sender as Image;\r
+            if (img == null)\r
+                return;\r
+            Border border = img.Parent as Border;\r
+            if (border == null)\r
+                return;\r
+\r
+            border.BorderBrush = new SolidColorBrush(Colors.Blue);\r
+            //border.BorderThickness = new Thickness(2);\r
+        }\r
+\r
+        void image_MouseEnter(object sender, System.Windows.Input.MouseEventArgs e)\r
+        {\r
+            Image img = sender as Image;\r
+            if (img == null)\r
+                return;\r
+            Border border = img.Parent as Border;\r
+            if (border == null)\r
+                return;\r
+\r
+            border.BorderBrush = new SolidColorBrush(Colors.Red);\r
+            //border.BorderThickness = mThick4;\r
+        }\r
+     }\r
+}\r
diff --git a/NT2chStyle45/CustomControl1.cs b/NT2chStyle45/CustomControl1.cs
new file mode 100755 (executable)
index 0000000..57a3016
--- /dev/null
@@ -0,0 +1,54 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading.Tasks;\r
+using System.Windows;\r
+using System.Windows.Controls;\r
+using System.Windows.Data;\r
+using System.Windows.Documents;\r
+using System.Windows.Input;\r
+using System.Windows.Media;\r
+using System.Windows.Media.Imaging;\r
+using System.Windows.Navigation;\r
+using System.Windows.Shapes;\r
+\r
+namespace NT2chStyle45\r
+{\r
+    /// <summary>\r
+    /// このカスタム コントロールを XAML ファイルで使用するには、手順 1a または 1b の後、手順 2 に従います。\r
+    ///\r
+    /// 手順 1a) 現在のプロジェクトに存在する XAML ファイルでこのカスタム コントロールを使用する場合\r
+    /// この XmlNamespace 属性を使用場所であるマークアップ ファイルのルート要素に\r
+    /// 追加します:\r
+    ///\r
+    ///     xmlns:MyNamespace="clr-namespace:NT2chStyle45"\r
+    ///\r
+    ///\r
+    /// 手順 1b) 異なるプロジェクトに存在する XAML ファイルでこのカスタム コントロールを使用する場合\r
+    /// この XmlNamespace 属性を使用場所であるマークアップ ファイルのルート要素に\r
+    /// 追加します:\r
+    ///\r
+    ///     xmlns:MyNamespace="clr-namespace:NT2chStyle45;assembly=NT2chStyle45"\r
+    ///\r
+    /// また、XAML ファイルのあるプロジェクトからこのプロジェクトへのプロジェクト参照を追加し、\r
+    /// リビルドして、コンパイル エラーを防ぐ必要があります:\r
+    ///\r
+    ///     ソリューション エクスプローラーで対象のプロジェクトを右クリックし、\r
+    ///     [参照の追加] の [プロジェクト] を選択してから、このプロジェクトを選択します。\r
+    ///\r
+    ///\r
+    /// 手順 2)\r
+    /// コントロールを XAML ファイルで使用します。\r
+    ///\r
+    ///     <MyNamespace:CustomControl1/>\r
+    ///\r
+    /// </summary>\r
+    public class CustomControl1 : Control\r
+    {\r
+        static CustomControl1()\r
+        {\r
+            DefaultStyleKeyProperty.OverrideMetadata(typeof(CustomControl1), new FrameworkPropertyMetadata(typeof(CustomControl1)));\r
+        }\r
+    }\r
+}\r
diff --git a/NT2chStyle45/MainDictionary-black.xaml b/NT2chStyle45/MainDictionary-black.xaml
new file mode 100755 (executable)
index 0000000..22a38d0
--- /dev/null
@@ -0,0 +1,608 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"\r
+                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">\r
+    <!-- アプリケーションの基本背景色-->\r
+    <Brush x:Key="BasicBkBrush">\r
+        Black\r
+    </Brush>\r
+    <!-- アプリケーションの基本文字色-->\r
+    <Brush x:Key="BasicForeBrush">\r
+        LightGray\r
+    </Brush>\r
+    <!-- 選択されているタブの背景色-->\r
+    <Brush x:Key="SelectedTabBkBrush">\r
+        DimGray\r
+    </Brush>\r
+    <!-- お気に入りパネルの背景色-->\r
+    <Brush x:Key="FavoritePanelBKBrush">\r
+        DimGray\r
+    </Brush>\r
+    <!-- お気に入りに表示されるスレットの背景色-->\r
+    <Brush x:Key="FavoriteThreadBKBrush">\r
+        DimGray\r
+    </Brush>\r
+    <!-- お気に入りに表示されるスレットの文字色-->\r
+    <Brush x:Key="FavoriteThreadForeBrush">\r
+        LightGray\r
+    </Brush>\r
+    <!-- お気に入りに表示されるスレットの「登録板」の文字色-->\r
+    <Brush x:Key="FavoriteThreadBoardForeBrush">\r
+        Orange\r
+    </Brush>\r
+    <!-- お気に入りに表示されるスレット未読数強調時の背景色-->\r
+    <LinearGradientBrush x:Key="FavoriteThreadEmphasizedBKBrush">\r
+            <GradientStop Color="DimGray" Offset="0"/>\r
+            <GradientStop Color="Red" Offset="0.5"/>\r
+            <GradientStop Color="DimGray" Offset="1.0"/>\r
+       <!-- Green-->\r
+    </LinearGradientBrush>\r
+    <!-- お気に入りに表示されるスレット未読数強調時の文字色-->\r
+    <Brush x:Key="FavoriteThreadEmphasizedForeBrush">\r
+        LightGray\r
+    </Brush>\r
+    <!-- お気に入りに表示されるスレットのマウスオーバー時の背景色-->    \r
+    <LinearGradientBrush x:Key="FavoriteThreadMouseOverBKBrush">\r
+        <LinearGradientBrush.RelativeTransform>\r
+            <TransformGroup>\r
+                <ScaleTransform CenterY="0.5" CenterX="0.5"/>\r
+                <SkewTransform CenterY="0.5" CenterX="0.5"/>\r
+                <RotateTransform Angle="90" CenterY="0.5" CenterX="0.5"/>\r
+                <TranslateTransform/>\r
+            </TransformGroup>\r
+        </LinearGradientBrush.RelativeTransform>\r
+        <GradientStop Color="DarkGray" Offset="0" />\r
+        <GradientStop Color="Blue" Offset="0.1" />\r
+        <GradientStop Color="DarkGray" Offset="1" />\r
+    </LinearGradientBrush>\r
+    \r
+    <!-- お気に入りに表示されるスレットのドラッグオブジェクトオーバー時の背景色-->\r
+    <LinearGradientBrush x:Key="FavoriteThreadDragOverBKBrush">\r
+        <LinearGradientBrush.RelativeTransform>\r
+            <TransformGroup>\r
+                <ScaleTransform CenterY="0.5" CenterX="0.5"/>\r
+                <SkewTransform CenterY="0.5" CenterX="0.5"/>\r
+                <RotateTransform Angle="90" CenterY="0.5" CenterX="0.5"/>\r
+                <TranslateTransform/>\r
+            </TransformGroup>\r
+        </LinearGradientBrush.RelativeTransform>\r
+        <GradientStop  Color="DimGray" Offset="0.7"/>\r
+        <GradientStop Color="LightBlue" Offset="0.9" />\r
+        <GradientStop  Color="DimGray" Offset="1"/>\r
+    </LinearGradientBrush>\r
+    \r
+    <!-- お気に入りに表示される板のドラッグオブジェクトオーバー時の背景色-->\r
+    <LinearGradientBrush x:Key="FavoriteBoardDragOverBKBrush">\r
+        <GradientStop  Color="DimGray" Offset="0.7"/>\r
+        <GradientStop Color="Blue" Offset="0.9" />\r
+        <GradientStop  Color="DimGray" Offset="1"/>\r
+    </LinearGradientBrush>\r
+    \r
+    <LinearGradientBrush x:Key="MyBrush2">\r
+        <GradientStop Color="Black" Offset="0" />\r
+        <GradientStop Color="Blue" Offset="1" />\r
+    </LinearGradientBrush>\r
+    <!-- ステータースバーの背景ブラシ-->\r
+    <LinearGradientBrush x:Key="HorizontalToolBKBrush">\r
+        <LinearGradientBrush.RelativeTransform>\r
+            <TransformGroup>\r
+                <ScaleTransform CenterY="0.5" CenterX="0.5"/>\r
+                <SkewTransform CenterY="0.5" CenterX="0.5"/>\r
+                <RotateTransform Angle="90" CenterY="0.5" CenterX="0.5"/>\r
+                <TranslateTransform/>\r
+            </TransformGroup>\r
+        </LinearGradientBrush.RelativeTransform>\r
+        <GradientStop Color="DarkGray" Offset="0" />\r
+        <GradientStop Color="LightGray" Offset="0.5" />\r
+        <GradientStop Color="LightGray" Offset="1" />\r
+    </LinearGradientBrush>\r
+    <!---->\r
+    <Brush x:Key="SubjectViewBkBrush">\r
+        DimGray\r
+    </Brush>\r
+    <Brush x:Key="SubjectViewForeBrush">\r
+        LightGray\r
+    </Brush>\r
+    <Brush x:Key="SubjectViewSelectedItemBkBrush">\r
+       Black \r
+    </Brush>\r
+    <Brush x:Key="SubjectViewSelectedItemForeBrush">\r
+        Aqua\r
+    </Brush>\r
+    <!-- カテゴリー一覧パネルの選択ラベルを定義します-->\r
+    <Style x:Key="CategoryDisplayButton" TargetType="ToggleButton">\r
+        <Setter Property="Foreground" Value="{StaticResource BasicForeBrush}"/>\r
+        <Setter Property="FontSize" Value="12"/>\r
+        <Setter Property="FontWeight" Value="Bold" />\r
+        <Setter Property="Width" Value="120" />\r
+        <Setter Property="Height" Value="30" />\r
+        <Setter Property="Margin" Value="5,0,5,5" />\r
+        <Setter Property="Template">\r
+            <Setter.Value>\r
+                <ControlTemplate TargetType="ToggleButton">\r
+                    <Border BorderThickness="1,0,0,1" BorderBrush="{StaticResource BasicForeBrush}">\r
+                        <Grid x:Name="controlLayout">\r
+                            <Rectangle x:Name="buttonSurface"\r
+                                 Fill="{StaticResource BasicBkBrush}"/>\r
+                            <Label x:Name="buttonCaption" Content="{TemplateBinding Content}"\r
+                                   Foreground="{StaticResource BasicForeBrush}"\r
+                               HorizontalAlignment="Center"\r
+                               VerticalAlignment="Center"/>\r
+                        </Grid>\r
+                    </Border>\r
+                    <ControlTemplate.Triggers>\r
+                        <Trigger Property="IsMouseOver" Value="True">\r
+                            <Setter TargetName="buttonSurface" Property="Fill" Value="{StaticResource MyBrush2}">\r
+                            </Setter>\r
+                            <Setter TargetName="buttonCaption" Property="Foreground"\r
+                                   Value="LightGray"/>\r
+                        </Trigger>\r
+                        <Trigger Property="IsChecked" Value="True">\r
+                            <Setter TargetName="buttonCaption" Property="Foreground"\r
+                                   Value="DarkGray"/>\r
+                            <Setter TargetName="buttonSurface" Property="Fill" Value="White"/>\r
+                            <Setter TargetName="controlLayout"\r
+                                    Property="RenderTransformOrigin"\r
+                                    Value="0.5, 0.5" />\r
+                            <Setter TargetName="controlLayout"\r
+                                    Property="RenderTransform">\r
+                                <Setter.Value>\r
+                                    <ScaleTransform ScaleX="0.8" ScaleY="0.8"/>\r
+                                </Setter.Value>\r
+                            </Setter>\r
+                        </Trigger>\r
+                    </ControlTemplate.Triggers>\r
+                </ControlTemplate>\r
+            </Setter.Value>\r
+        </Setter>\r
+    </Style>\r
+    <!-- 板一覧パネルの選択ラベルを定義します-->\r
+    <Style x:Key="BoardDisplayButton" TargetType="Button">\r
+        <Setter Property="Background" Value="Transparent"/>\r
+        <!--Setter Property="Foreground" Value="LightGray"/-->\r
+        <!---Setter Property="Background" Value="White"/-->\r
+        <Setter Property="FontSize" Value="12"/>\r
+        <Setter Property="Height" Value="22" />\r
+        <Setter Property="Margin" Value="5" />\r
+        <Setter Property="AllowDrop" Value="True" />\r
+        <Setter Property="Template">\r
+            <Setter.Value>\r
+                <ControlTemplate TargetType="Button">\r
+                    <Grid x:Name="controlLayout2">\r
+                        <Grid.RowDefinitions>\r
+                            <RowDefinition Height="Auto"/>\r
+                            <RowDefinition Height="1"/>\r
+                        </Grid.RowDefinitions>\r
+                        <Label x:Name="buttonCaption2" Content="{TemplateBinding Content}"\r
+                                Foreground="LightGray"  Margin="0" Padding="0"\r
+                            HorizontalAlignment="Center"\r
+                            VerticalAlignment="Center"/>\r
+                        <Rectangle x:Name="buttonUnderline2" Height="1" Margin="0"\r
+                              Fill="LightGray" Grid.Row="1"/>\r
+                    </Grid>\r
+                    <ControlTemplate.Triggers>\r
+                        <Trigger Property="IsMouseOver" Value="True">\r
+                            <Setter TargetName="buttonCaption2" Property="FontWeight"\r
+                                   Value="Bold"/>\r
+                            <Setter TargetName="buttonCaption2" Property="Foreground"\r
+                                   Value="White"/>\r
+                            <Setter TargetName="buttonUnderline2" Property="Fill"\r
+                                   Value="White"/>\r
+                        </Trigger>\r
+                        <Trigger Property="IsPressed"  Value="True">\r
+                            <Setter TargetName="buttonCaption2" Property="Foreground"\r
+                                   Value="Red"/>\r
+                            <Setter TargetName="buttonUnderline2" Property="Fill"\r
+                                   Value="Red"/>\r
+                        </Trigger>\r
+                    </ControlTemplate.Triggers>\r
+                </ControlTemplate>\r
+            </Setter.Value>\r
+        </Setter>\r
+    </Style>\r
+    <!-- お気に入り「板」一覧パネルの選択ラベルを定義します-->\r
+    <Style x:Key="FavoriteBoardDisplayButton" TargetType="Button">\r
+        <!-- Setter Property="Background" Value="{StaticResource BasicBkBrush}"/ -->\r
+        <Setter Property="Foreground" Value="LightGray"/>\r
+        <Setter Property="Background" Value="Transparent"/>\r
+        <Setter Property="FontSize" Value="12"/>\r
+        <Setter Property="Height" Value="22" />\r
+        <Setter Property="Margin" Value="5" />\r
+        <Setter Property="Template">\r
+            <Setter.Value>\r
+                <ControlTemplate TargetType="Button">\r
+                    <Grid x:Name="controlLayout2" Background="{TemplateBinding Background}">\r
+                        <Grid.RowDefinitions>\r
+                            <RowDefinition Height="Auto"/>\r
+                            <RowDefinition Height="1"/>\r
+                        </Grid.RowDefinitions>\r
+                        <Label x:Name="buttonCaption2" Content="{TemplateBinding Content}"\r
+                                Foreground="LightGray"  Margin="0" Padding="0"\r
+                            HorizontalAlignment="Center"\r
+                            VerticalAlignment="Center"/>\r
+                        <Rectangle x:Name="buttonUnderline2" Height="1" Margin="0"\r
+                              Fill="LightGray" Grid.Row="1"/>\r
+                    </Grid>\r
+                    <ControlTemplate.Triggers>\r
+                        <Trigger Property="IsMouseOver" Value="True">\r
+                            <Setter TargetName="buttonCaption2" Property="FontWeight"\r
+                                   Value="Bold"/>\r
+                            <Setter TargetName="buttonCaption2" Property="Foreground"\r
+                                   Value="White"/>\r
+                            <Setter TargetName="buttonUnderline2" Property="Fill"\r
+                                   Value="White"/>\r
+                        </Trigger>\r
+                        <Trigger Property="IsPressed"  Value="True">\r
+                            <Setter TargetName="buttonCaption2" Property="Foreground"\r
+                                   Value="Red"/>\r
+                            <Setter TargetName="buttonUnderline2" Property="Fill"\r
+                                   Value="Red"/>\r
+                        </Trigger>\r
+                    </ControlTemplate.Triggers>\r
+                </ControlTemplate>\r
+            </Setter.Value>\r
+        </Setter>\r
+    </Style>\r
+    <!-- 終了ボタン-->\r
+    <Style x:Key="ToolButtonExit" TargetType="Button">\r
+        <Setter Property="Template">\r
+            <Setter.Value>\r
+                <ControlTemplate TargetType="Button">\r
+                    <Grid x:Name="ToolButtonPanel" Width="50">\r
+                        <Grid.RowDefinitions>\r
+                            <RowDefinition Height="Auto"/>\r
+                            <RowDefinition Height="Auto"/>\r
+                        </Grid.RowDefinitions>\r
+                        <Rectangle x:Name="ToolButtonPanelFill" RadiusX="3" RadiusY="3" \r
+                                   Grid.RowSpan="2"></Rectangle>\r
+                        <Image Source="images/exit_btn_light.png" Stretch="None" />\r
+                        <TextBlock  Grid.Row="1" Text="Exit" Foreground="Aqua"\r
+                                   HorizontalAlignment="Center"/>\r
+                    </Grid>\r
+                    <ControlTemplate.Triggers>\r
+                        <Trigger Property="IsMouseOver" Value="True">\r
+                            <Setter TargetName="ToolButtonPanel" Property="Background"\r
+                                   Value="LightBlue"/>\r
+                            <Setter TargetName="ToolButtonPanelFill" Property="Fill"\r
+                                   Value="LightBlue"/>\r
+                        </Trigger>\r
+                    </ControlTemplate.Triggers>\r
+                </ControlTemplate>\r
+            </Setter.Value>\r
+        </Setter>\r
+    </Style>\r
+    <Style x:Key="ToolButtonMaxWindow" TargetType="Button">\r
+        <Setter Property="Template">\r
+            <Setter.Value>\r
+                <ControlTemplate TargetType="Button">\r
+                    <StackPanel x:Name="ToolButtonPanel">\r
+                        <Image Source="images/max_window2.png" Stretch="None" />\r
+                        <TextBlock Text="Maximz" Foreground="{StaticResource BasicForeBrush}"/>\r
+                    </StackPanel>\r
+                    <ControlTemplate.Triggers>\r
+                        <Trigger Property="IsMouseOver" Value="True">\r
+                            <Setter TargetName="ToolButtonPanel" Property="Background"\r
+                                   Value="LightBlue"/>\r
+                        </Trigger>\r
+                    </ControlTemplate.Triggers>\r
+                </ControlTemplate>\r
+            </Setter.Value>\r
+        </Setter>\r
+    </Style>\r
+    <Style x:Key="ToolButtonRestoreWindow" TargetType="Button">\r
+        <Setter Property="Template">\r
+            <Setter.Value>\r
+                <ControlTemplate TargetType="Button">\r
+                    <StackPanel x:Name="ToolButtonPanel">\r
+                        <Image Source="images/restore_window2.png" Stretch="None" />\r
+                        <TextBlock Text="Restre" Foreground="{StaticResource BasicForeBrush}"/>\r
+                    </StackPanel>\r
+                    <ControlTemplate.Triggers>\r
+                        <Trigger Property="IsMouseOver" Value="True">\r
+                            <Setter TargetName="ToolButtonPanel" Property="Background"\r
+                                   Value="LightBlue"/>\r
+                        </Trigger>\r
+                    </ControlTemplate.Triggers>\r
+                </ControlTemplate>\r
+            </Setter.Value>\r
+        </Setter>\r
+    </Style>\r
+    <!-- 設定ボタン-->\r
+    <Style x:Key="ToolButtonSetup" TargetType="Button">\r
+        <Setter Property="Template">\r
+            <Setter.Value>\r
+                <ControlTemplate TargetType="Button">\r
+                    <StackPanel x:Name="ToolButtonPanel" Width="50">\r
+                        <Image Source="images/setup_btn.png" Stretch="None" />\r
+                        <TextBlock Text="Setup" Foreground="{StaticResource BasicForeBrush}"\r
+                                   HorizontalAlignment="Center"/>\r
+                    </StackPanel>\r
+                    <ControlTemplate.Triggers>\r
+                        <Trigger Property="IsMouseOver" Value="True">\r
+                            <Setter TargetName="ToolButtonPanel" Property="Background"\r
+                                   Value="LightBlue"/>\r
+                        </Trigger>\r
+                    </ControlTemplate.Triggers>\r
+                </ControlTemplate>\r
+            </Setter.Value>\r
+        </Setter>\r
+    </Style>\r
+    <!-- 更新ボタン-->\r
+    <Style x:Key="ToolButtonUpdate" TargetType="Button">\r
+        <Setter Property="Template">\r
+            <Setter.Value>\r
+                <ControlTemplate TargetType="Button">\r
+                    <StackPanel x:Name="ToolButtonPanel" Background="Red" Width="50" Margin="2">\r
+                        <Image Source="images/update_btn_light.png" Stretch="None" />\r
+                        <TextBlock Text="Update" Foreground="{StaticResource BasicForeBrush}"\r
+                                   HorizontalAlignment="Center" />\r
+                    </StackPanel>\r
+                    <ControlTemplate.Triggers>\r
+                        <Trigger Property="IsMouseOver" Value="True">\r
+                            <Setter TargetName="ToolButtonPanel" Property="Background"\r
+                                   Value="LightBlue"/>\r
+                        </Trigger>\r
+                    </ControlTemplate.Triggers>\r
+                </ControlTemplate>\r
+            </Setter.Value>\r
+        </Setter>\r
+    </Style>\r
+    <!-- 一番上にジャンプボタン-->\r
+    <Style x:Key="ToolButtonJumpToTop" TargetType="Button">\r
+        <Setter Property="Template">\r
+            <Setter.Value>\r
+                <ControlTemplate TargetType="Button">\r
+                    <StackPanel x:Name="ToolButtonPanel" Background="Orange"  Width="50" Margin="2">\r
+                        <Image Source="images/to_the_top_light.png" Stretch="None" />\r
+                        <TextBlock Text="ToTop" Foreground="{StaticResource BasicForeBrush}"\r
+                                   HorizontalAlignment="Center" />\r
+                    </StackPanel>\r
+                    <ControlTemplate.Triggers>\r
+                        <Trigger Property="IsMouseOver" Value="True">\r
+                            <Setter TargetName="ToolButtonPanel" Property="Background"\r
+                                   Value="LightBlue"/>\r
+                        </Trigger>\r
+                    </ControlTemplate.Triggers>\r
+                </ControlTemplate>\r
+            </Setter.Value>\r
+        </Setter>\r
+    </Style>\r
+    <!-- 一番下にジャンプボタン-->\r
+    <Style x:Key="ToolButtonJumpToBottom" TargetType="Button">\r
+        <Setter Property="Template">\r
+            <Setter.Value>\r
+                <ControlTemplate TargetType="Button">\r
+                    <StackPanel x:Name="ToolButtonPanel" Background="OliveDrab"  Width="50" Margin="2">\r
+                        <Image Source="images/to_the_bottom_light.png" Stretch="None" />\r
+                        <TextBlock Text="ToBottom" Foreground="{StaticResource BasicForeBrush}"\r
+                                   HorizontalAlignment="Center" />\r
+                    </StackPanel>\r
+                    <ControlTemplate.Triggers>\r
+                        <Trigger Property="IsMouseOver" Value="True">\r
+                            <Setter TargetName="ToolButtonPanel" Property="Background"\r
+                                   Value="LightBlue"/>\r
+                        </Trigger>\r
+                    </ControlTemplate.Triggers>\r
+                </ControlTemplate>\r
+            </Setter.Value>\r
+        </Setter>\r
+    </Style>\r
+    <!-- スレタイ検索ボタン-->\r
+    <Style x:Key="ToolButtonThreadTitleSearch" TargetType="Button">\r
+        <Setter Property="Template">\r
+            <Setter.Value>\r
+                <ControlTemplate TargetType="Button">\r
+                    <StackPanel x:Name="ToolButtonPanel" Background="SteelBlue"  Width="50" Margin="2">\r
+                        <Image Source="images/search_btn_light.png" Stretch="None" />\r
+                        <TextBlock Text="Search" Foreground="{StaticResource BasicForeBrush}"\r
+                                   HorizontalAlignment="Center" />\r
+                    </StackPanel>\r
+                    <ControlTemplate.Triggers>\r
+                        <Trigger Property="IsMouseOver" Value="True">\r
+                            <Setter TargetName="ToolButtonPanel" Property="Background"\r
+                                   Value="LightBlue"/>\r
+                        </Trigger>\r
+                    </ControlTemplate.Triggers>\r
+                </ControlTemplate>\r
+            </Setter.Value>\r
+        </Setter>\r
+    </Style>\r
+    <!-- スレ作成ボタン-->\r
+    <Style x:Key="ToolButtonCreateThread" TargetType="Button">\r
+        <Setter Property="Template">\r
+            <Setter.Value>\r
+                <ControlTemplate TargetType="Button">\r
+                    <StackPanel x:Name="ToolButtonPanel"  Background="DimGray" Width="50" Margin="2">\r
+                        <Image Source="images/write_btn.png" Stretch="None" />\r
+                        <TextBlock Text="Create" Foreground="{StaticResource BasicForeBrush}"\r
+                                   HorizontalAlignment="Center"/>\r
+                    </StackPanel>\r
+                    <ControlTemplate.Triggers>\r
+                        <Trigger Property="IsMouseOver" Value="True">\r
+                            <Setter TargetName="ToolButtonPanel" Property="Background"\r
+                                   Value="LightBlue"/>\r
+                        </Trigger>\r
+                    </ControlTemplate.Triggers>\r
+                </ControlTemplate>\r
+            </Setter.Value>\r
+        </Setter>\r
+    </Style>\r
+    <!-- レス検索ボタン-->\r
+    <Style x:Key="ToolButtonResSearch" TargetType="Button">\r
+        <Setter Property="Template">\r
+            <Setter.Value>\r
+                <ControlTemplate TargetType="Button">\r
+                    <StackPanel x:Name="ToolButtonPanel" Background="SlateBlue" Width="50"  Margin="2">\r
+                        <Image Source="images/search_btn_light.png" Stretch="None" />\r
+                        <TextBlock Text="Search" Foreground="{StaticResource BasicForeBrush}"\r
+                                   HorizontalAlignment="Center" />\r
+                    </StackPanel>\r
+                    <ControlTemplate.Triggers>\r
+                        <Trigger Property="IsMouseOver" Value="True">\r
+                            <Setter TargetName="ToolButtonPanel" Property="Background"\r
+                                   Value="LightBlue"/>\r
+                        </Trigger>\r
+                    </ControlTemplate.Triggers>\r
+                </ControlTemplate>\r
+            </Setter.Value>\r
+        </Setter>\r
+    </Style>\r
+    <!-- 新着スレへジャンプボタン-->\r
+    <Style x:Key="ToolButtonJumpToNew" TargetType="Button">\r
+        <Setter Property="Template">\r
+            <Setter.Value>\r
+                <ControlTemplate TargetType="Button">\r
+                    <StackPanel x:Name="ToolButtonPanel" Background="DimGray"  Width="50" Margin="2">\r
+                        <Image Source="images/jmp_to_new.png" Stretch="None" />\r
+                        <TextBlock Text="New☆" Foreground="{StaticResource BasicForeBrush}"\r
+                                   HorizontalAlignment="Center"/>\r
+                    </StackPanel>\r
+                    <ControlTemplate.Triggers>\r
+                        <Trigger Property="IsMouseOver" Value="True">\r
+                            <Setter TargetName="ToolButtonPanel" Property="Background"\r
+                                   Value="LightBlue"/>\r
+                        </Trigger>\r
+                    </ControlTemplate.Triggers>\r
+                </ControlTemplate>\r
+            </Setter.Value>\r
+        </Setter>\r
+    </Style>\r
+    <!-- ブックマークへジャンプボタン-->\r
+    <Style x:Key="ToolButtonJumpToBookmark" TargetType="Button">\r
+        <Setter Property="Template">\r
+            <Setter.Value>\r
+                <ControlTemplate TargetType="Button">\r
+                    <StackPanel x:Name="ToolButtonPanel" Background="DimGray"  Width="50" Margin="2">\r
+                        <Image Source="images/tag_btn.png" Stretch="None" />\r
+                        <TextBlock Text="B-Mark" Foreground="{StaticResource BasicForeBrush}"\r
+                                   HorizontalAlignment="Center"/>\r
+                    </StackPanel>\r
+                    <ControlTemplate.Triggers>\r
+                        <Trigger Property="IsMouseOver" Value="True">\r
+                            <Setter TargetName="ToolButtonPanel" Property="Background"\r
+                                   Value="LightBlue"/>\r
+                        </Trigger>\r
+                    </ControlTemplate.Triggers>\r
+                </ControlTemplate>\r
+            </Setter.Value>\r
+        </Setter>\r
+    </Style>\r
+    <!-- レス書込ボタン-->\r
+    <Style x:Key="ToolButtonWriteRes" TargetType="Button">\r
+        <Setter Property="Template">\r
+            <Setter.Value>\r
+                <ControlTemplate TargetType="Button">\r
+                    <StackPanel x:Name="ToolButtonPanel"  Background="DimGray" Width="50" Margin="2">\r
+                        <Image Source="images/write_btn.png" Stretch="None" />\r
+                        <TextBlock Text="Write" Foreground="{StaticResource BasicForeBrush}"\r
+                                   HorizontalAlignment="Center"/>\r
+                    </StackPanel>\r
+                    <ControlTemplate.Triggers>\r
+                        <Trigger Property="IsMouseOver" Value="True">\r
+                            <Setter TargetName="ToolButtonPanel" Property="Background"\r
+                                   Value="LightBlue"/>\r
+                        </Trigger>\r
+                    </ControlTemplate.Triggers>\r
+                </ControlTemplate>\r
+            </Setter.Value>\r
+        </Setter>\r
+    </Style>\r
+    <!-- レス文字サイズ設定ボタン-->\r
+    <Style x:Key="ToolButtonSetupFont" TargetType="Button">\r
+        <Setter Property="Template">\r
+            <Setter.Value>\r
+                <ControlTemplate TargetType="Button">\r
+                    <StackPanel x:Name="ToolButtonPanel"  Background="DimGray" Width="50" Margin="2">\r
+                        <Image Source="images/font_btn_ics.png" Stretch="None" />\r
+                        <TextBlock Text=" Font " Foreground="{StaticResource BasicForeBrush}"\r
+                                   HorizontalAlignment="Center"/>\r
+                    </StackPanel>\r
+                    <ControlTemplate.Triggers>\r
+                        <Trigger Property="IsMouseOver" Value="True">\r
+                            <Setter TargetName="ToolButtonPanel" Property="Background"\r
+                                   Value="LightBlue"/>\r
+                        </Trigger>\r
+                    </ControlTemplate.Triggers>\r
+                </ControlTemplate>\r
+            </Setter.Value>\r
+        </Setter>\r
+    </Style>\r
+    <!-- レスビュースクロール開始ボタン-->\r
+    <Style x:Key="ToolButtonPlayAutoScroll" TargetType="Button">\r
+        <Setter Property="Template">\r
+            <Setter.Value>\r
+                <ControlTemplate TargetType="Button">\r
+                    <StackPanel x:Name="ToolButtonPanel"  Background="DimGray" Width="50" Margin="2">\r
+                        <Image Source="images/play_btn.png" Stretch="None" />\r
+                        <TextBlock Text="AutoRun" Foreground="{StaticResource BasicForeBrush}"\r
+                                   HorizontalAlignment="Center"/>\r
+                    </StackPanel>\r
+                    <ControlTemplate.Triggers>\r
+                        <Trigger Property="IsMouseOver" Value="True">\r
+                            <Setter TargetName="ToolButtonPanel" Property="Background"\r
+                                   Value="LightBlue"/>\r
+                        </Trigger>\r
+                    </ControlTemplate.Triggers>\r
+                </ControlTemplate>\r
+            </Setter.Value>\r
+        </Setter>\r
+    </Style>\r
+    <!-- レスビュースクロール終了ボタン-->\r
+    <Style x:Key="ToolButtonStopAutoScroll" TargetType="Button">\r
+        <Setter Property="Template">\r
+            <Setter.Value>\r
+                <ControlTemplate TargetType="Button">\r
+                    <StackPanel x:Name="ToolButtonPanel"  Background="DimGray" Width="50" Margin="2">\r
+                        <Image Source="images/stop_btn.png" Stretch="None" />\r
+                        <TextBlock Text="StopRun" Foreground="{StaticResource BasicForeBrush}"\r
+                                   HorizontalAlignment="Center"/>\r
+                    </StackPanel>\r
+                    <ControlTemplate.Triggers>\r
+                        <Trigger Property="IsMouseOver" Value="True">\r
+                            <Setter TargetName="ToolButtonPanel" Property="Background"\r
+                                   Value="LightBlue"/>\r
+                        </Trigger>\r
+                    </ControlTemplate.Triggers>\r
+                </ControlTemplate>\r
+            </Setter.Value>\r
+        </Setter>\r
+    </Style>\r
+    <!-- レスビューテキスト選択モードボタン-->\r
+    <Style x:Key="ToolButtonTextTool" TargetType="Button">\r
+        <Setter Property="Template">\r
+            <Setter.Value>\r
+                <ControlTemplate TargetType="Button">\r
+                    <StackPanel x:Name="ToolButtonPanel"  Background="DimGray" Width="50" Margin="2">\r
+                        <Image Source="images/texttools_btn.png" Stretch="None" />\r
+                        <TextBlock Text="TextSel" Foreground="{StaticResource BasicForeBrush}"\r
+                                   HorizontalAlignment="Center"/>\r
+                    </StackPanel>\r
+                    <ControlTemplate.Triggers>\r
+                        <Trigger Property="IsMouseOver" Value="True">\r
+                            <Setter TargetName="ToolButtonPanel" Property="Background"\r
+                                   Value="LightBlue"/>\r
+                        </Trigger>\r
+                    </ControlTemplate.Triggers>\r
+                </ControlTemplate>\r
+            </Setter.Value>\r
+        </Setter>\r
+    </Style>\r
+    <!-- レスビュータッチモードボタン-->\r
+    <Style x:Key="ToolButtonTouchMode" TargetType="Button">\r
+        <Setter Property="Template">\r
+            <Setter.Value>\r
+                <ControlTemplate TargetType="Button">\r
+                    <StackPanel x:Name="ToolButtonPanel"  Background="DimGray" Width="50" Margin="2">\r
+                        <Image Source="images/hand_btn.png" Stretch="None" />\r
+                        <TextBlock Text="Touch" Foreground="{StaticResource BasicForeBrush}"\r
+                                   HorizontalAlignment="Center"/>\r
+                    </StackPanel>\r
+                    <ControlTemplate.Triggers>\r
+                        <Trigger Property="IsMouseOver" Value="True">\r
+                            <Setter TargetName="ToolButtonPanel" Property="Background"\r
+                                   Value="LightBlue"/>\r
+                        </Trigger>\r
+                    </ControlTemplate.Triggers>\r
+                </ControlTemplate>\r
+            </Setter.Value>\r
+        </Setter>\r
+    </Style>\r
+</ResourceDictionary>
\ No newline at end of file
diff --git a/NT2chStyle45/MainDictionary.xaml b/NT2chStyle45/MainDictionary.xaml
new file mode 100755 (executable)
index 0000000..876460b
--- /dev/null
@@ -0,0 +1,594 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"\r
+                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">\r
+    <!-- アプリケーションの基本背景色-->\r
+    <Brush x:Key="BasicBkBrush">\r
+        DodgerBlue\r
+        <!--#ffd700-->\r
+        <!--White-->\r
+    </Brush>\r
+    <!-- アプリケーションの基本文字色-->\r
+    <Brush x:Key="BasicForeBrush">\r
+        <!--DodgerBlue-->\r
+        LightGray\r
+        <!--Black-->\r
+    </Brush>\r
+    <!-- 選択されているタブの背景色-->\r
+    <Brush x:Key="SelectedTabBkBrush">\r
+        <!--DodgerBlue-->\r
+        <!--LightGray-->\r
+        White\r
+    </Brush>\r
+    <!-- お気に入りパネルの背景色-->\r
+    <Brush x:Key="FavoritePanelBKBrush">\r
+        White\r
+    </Brush>\r
+    <!-- お気に入りに表示されるスレットの背景色-->\r
+    <Brush x:Key="FavoriteThreadBKBrush">\r
+        White\r
+    </Brush>\r
+    <!-- お気に入りに表示されるスレットの文字色-->\r
+    <Brush x:Key="FavoriteThreadForeBrush">\r
+        Black\r
+    </Brush>\r
+    <!-- お気に入りに表示されるスレットの「登録板」の文字色-->\r
+    <Brush x:Key="FavoriteThreadBoardForeBrush">\r
+        Orange\r
+    </Brush>\r
+    <!-- お気に入りに表示されるスレット未読数強調時の背景色-->\r
+    <Brush x:Key="FavoriteThreadEmphasizedBKBrush">\r
+        Red\r
+    </Brush>\r
+    <!-- お気に入りに表示されるスレット未読数強調時の文字色-->\r
+    <Brush x:Key="FavoriteThreadEmphasizedForeBrush">\r
+        White\r
+    </Brush>\r
+    <!-- お気に入りに表示されるスレットのマウスオーバー時の背景色-->    \r
+    <LinearGradientBrush x:Key="FavoriteThreadMouseOverBKBrush">\r
+        <LinearGradientBrush.RelativeTransform>\r
+            <TransformGroup>\r
+                <ScaleTransform CenterY="0.5" CenterX="0.5"/>\r
+                <SkewTransform CenterY="0.5" CenterX="0.5"/>\r
+                <RotateTransform Angle="90" CenterY="0.5" CenterX="0.5"/>\r
+                <TranslateTransform/>\r
+            </TransformGroup>\r
+        </LinearGradientBrush.RelativeTransform>\r
+        <GradientStop Color="White" Offset="0" />\r
+        <GradientStop Color="Yellow" Offset="0.1" />\r
+        <GradientStop Color="White" Offset="1" />\r
+    </LinearGradientBrush>\r
+    \r
+    <!-- お気に入りに表示されるスレットのドラッグオブジェクトオーバー時の背景色-->\r
+    <LinearGradientBrush x:Key="FavoriteThreadDragOverBKBrush">\r
+        <LinearGradientBrush.RelativeTransform>\r
+            <TransformGroup>\r
+                <ScaleTransform CenterY="0.5" CenterX="0.5"/>\r
+                <SkewTransform CenterY="0.5" CenterX="0.5"/>\r
+                <RotateTransform Angle="90" CenterY="0.5" CenterX="0.5"/>\r
+                <TranslateTransform/>\r
+            </TransformGroup>\r
+        </LinearGradientBrush.RelativeTransform>\r
+        <GradientStop  Color="White" Offset="0.7"/>\r
+        <GradientStop Color="LightBlue" Offset="0.9" />\r
+        <GradientStop  Color="White" Offset="1"/>\r
+    </LinearGradientBrush>\r
+    \r
+    <!-- お気に入りに表示される板のドラッグオブジェクトオーバー時の背景色-->\r
+    <LinearGradientBrush x:Key="FavoriteBoardDragOverBKBrush">\r
+        <GradientStop  Color="White" Offset="0.7"/>\r
+        <GradientStop Color="Blue" Offset="0.9" />\r
+        <GradientStop  Color="White" Offset="1"/>\r
+    </LinearGradientBrush>\r
+    \r
+    <LinearGradientBrush x:Key="MyBrush2">\r
+        <GradientStop Color="White" Offset="0" />\r
+        <GradientStop Color="DodgerBlue" Offset="1" />\r
+    </LinearGradientBrush>\r
+    <!-- ステータースバーの背景ブラシ-->\r
+    <LinearGradientBrush x:Key="HorizontalToolBKBrush">\r
+        <LinearGradientBrush.RelativeTransform>\r
+            <TransformGroup>\r
+                <ScaleTransform CenterY="0.5" CenterX="0.5"/>\r
+                <SkewTransform CenterY="0.5" CenterX="0.5"/>\r
+                <RotateTransform Angle="90" CenterY="0.5" CenterX="0.5"/>\r
+                <TranslateTransform/>\r
+            </TransformGroup>\r
+        </LinearGradientBrush.RelativeTransform>\r
+        <GradientStop Color="White" Offset="0" />\r
+        <GradientStop Color="LightGray" Offset="0.5" />\r
+        <GradientStop Color="LightGray" Offset="1" />\r
+    </LinearGradientBrush>\r
+    <!---->\r
+    <Brush x:Key="SubjectViewBkBrush">\r
+        White\r
+    </Brush>\r
+    <Brush x:Key="SubjectViewForeBrush">\r
+        Black\r
+    </Brush>\r
+    <Brush x:Key="SubjectViewSelectedItemBkBrush">\r
+       DodgerBlue \r
+    </Brush>\r
+    <Brush x:Key="SubjectViewSelectedItemForeBrush">\r
+        White\r
+    </Brush>\r
+    <!-- カテゴリー一覧パネルの選択ラベルを定義します-->\r
+    <Style x:Key="CategoryDisplayButton" TargetType="ToggleButton">\r
+        <Setter Property="Foreground" Value="{StaticResource BasicForeBrush}"/>\r
+        <Setter Property="FontSize" Value="12"/>\r
+        <Setter Property="FontWeight" Value="Bold" />\r
+        <Setter Property="Width" Value="120" />\r
+        <Setter Property="Height" Value="30" />\r
+        <Setter Property="Margin" Value="5,0,5,5" />\r
+        <Setter Property="Template">\r
+            <Setter.Value>\r
+                <ControlTemplate TargetType="ToggleButton">\r
+                    <Border BorderThickness="1,0,0,1" BorderBrush="{StaticResource BasicForeBrush}">\r
+                        <Grid x:Name="controlLayout">\r
+                            <Rectangle x:Name="buttonSurface"\r
+                                 Fill="{StaticResource BasicBkBrush}"/>\r
+                            <Label x:Name="buttonCaption" Content="{TemplateBinding Content}"\r
+                                   Foreground="{StaticResource BasicForeBrush}"\r
+                               HorizontalAlignment="Center"\r
+                               VerticalAlignment="Center"/>\r
+                        </Grid>\r
+                    </Border>\r
+                    <ControlTemplate.Triggers>\r
+                        <Trigger Property="IsMouseOver" Value="True">\r
+                            <Setter TargetName="buttonSurface" Property="Fill" Value="{StaticResource MyBrush2}">\r
+                            </Setter>\r
+                            <Setter TargetName="buttonCaption" Property="Foreground"\r
+                                   Value="Green"/>\r
+                        </Trigger>\r
+                        <Trigger Property="IsChecked" Value="True">\r
+                            <Setter TargetName="buttonCaption" Property="Foreground"\r
+                                   Value="Green"/>\r
+                            <Setter TargetName="buttonSurface" Property="Fill" Value="White"/>\r
+                            <Setter TargetName="controlLayout"\r
+                                    Property="RenderTransformOrigin"\r
+                                    Value="0.5, 0.5" />\r
+                            <Setter TargetName="controlLayout"\r
+                                    Property="RenderTransform">\r
+                                <Setter.Value>\r
+                                    <ScaleTransform ScaleX="0.8" ScaleY="0.8"/>\r
+                                </Setter.Value>\r
+                            </Setter>\r
+                        </Trigger>\r
+                    </ControlTemplate.Triggers>\r
+                </ControlTemplate>\r
+            </Setter.Value>\r
+        </Setter>\r
+    </Style>\r
+    <!-- 板一覧パネルの選択ラベルを定義します-->\r
+    <Style x:Key="BoardDisplayButton" TargetType="Button">\r
+        <Setter Property="Background" Value="Transparent"/>\r
+        <!--Setter Property="Foreground" Value="LightGray"/-->\r
+        <!---Setter Property="Background" Value="White"/-->\r
+        <Setter Property="FontSize" Value="12"/>\r
+        <Setter Property="Height" Value="22" />\r
+        <Setter Property="Margin" Value="5" />\r
+        <Setter Property="AllowDrop" Value="True" />\r
+        <Setter Property="Template">\r
+            <Setter.Value>\r
+                <ControlTemplate TargetType="Button">\r
+                    <Grid x:Name="controlLayout2">\r
+                        <Grid.RowDefinitions>\r
+                            <RowDefinition Height="Auto"/>\r
+                            <RowDefinition Height="1"/>\r
+                        </Grid.RowDefinitions>\r
+                        <Label x:Name="buttonCaption2" Content="{TemplateBinding Content}"\r
+                                Foreground="Blue"  Margin="0" Padding="0"\r
+                            HorizontalAlignment="Center"\r
+                            VerticalAlignment="Center"/>\r
+                        <Rectangle x:Name="buttonUnderline2" Height="1" Margin="0"\r
+                              Fill="Blue" Grid.Row="1"/>\r
+                    </Grid>\r
+                    <ControlTemplate.Triggers>\r
+                        <Trigger Property="IsMouseOver" Value="True">\r
+                            <Setter TargetName="buttonCaption2" Property="FontWeight"\r
+                                   Value="Bold"/>\r
+                        </Trigger>\r
+                        <Trigger Property="IsPressed"  Value="True">\r
+                            <Setter TargetName="buttonCaption2" Property="Foreground"\r
+                                   Value="Red"/>\r
+                            <Setter TargetName="buttonUnderline2" Property="Fill"\r
+                                   Value="Red"/>\r
+                        </Trigger>\r
+                    </ControlTemplate.Triggers>\r
+                </ControlTemplate>\r
+            </Setter.Value>\r
+        </Setter>\r
+    </Style>\r
+    <!-- お気に入り「板」一覧パネルの選択ラベルを定義します-->\r
+    <Style x:Key="FavoriteBoardDisplayButton" TargetType="Button">\r
+        <!-- Setter Property="Background" Value="{StaticResource BasicBkBrush}"/ -->\r
+        <Setter Property="Foreground" Value="LightGray"/>\r
+        <Setter Property="Background" Value="Transparent"/>\r
+        <Setter Property="FontSize" Value="12"/>\r
+        <Setter Property="Height" Value="22" />\r
+        <Setter Property="Margin" Value="5" />\r
+        <Setter Property="Template">\r
+            <Setter.Value>\r
+                <ControlTemplate TargetType="Button">\r
+                    <Grid x:Name="controlLayout2" Background="{TemplateBinding Background}">\r
+                        <Grid.RowDefinitions>\r
+                            <RowDefinition Height="Auto"/>\r
+                            <RowDefinition Height="1"/>\r
+                        </Grid.RowDefinitions>\r
+                        <Label x:Name="buttonCaption2" Content="{TemplateBinding Content}"\r
+                                Foreground="Blue"  Margin="0" Padding="0"\r
+                            HorizontalAlignment="Center"\r
+                            VerticalAlignment="Center"/>\r
+                        <Rectangle x:Name="buttonUnderline2" Height="1" Margin="0"\r
+                              Fill="Blue" Grid.Row="1"/>\r
+                    </Grid>\r
+                    <ControlTemplate.Triggers>\r
+                        <Trigger Property="IsMouseOver" Value="True">\r
+                            <Setter TargetName="buttonCaption2" Property="FontWeight"\r
+                                   Value="Bold"/>\r
+                        </Trigger>\r
+                        <Trigger Property="IsPressed"  Value="True">\r
+                            <Setter TargetName="buttonCaption2" Property="Foreground"\r
+                                   Value="Red"/>\r
+                            <Setter TargetName="buttonUnderline2" Property="Fill"\r
+                                   Value="Red"/>\r
+                        </Trigger>\r
+                    </ControlTemplate.Triggers>\r
+                </ControlTemplate>\r
+            </Setter.Value>\r
+        </Setter>\r
+    </Style>\r
+    <!-- 終了ボタン-->\r
+    <Style x:Key="ToolButtonExit" TargetType="Button">\r
+        <Setter Property="Template">\r
+            <Setter.Value>\r
+                <ControlTemplate TargetType="Button">\r
+                    <StackPanel x:Name="ToolButtonPanel">\r
+                        <Image Source="images/exit_btn_light.png" Stretch="None" />\r
+                        <TextBlock Text=" Exit " Foreground="{StaticResource BasicForeBrush}"/>\r
+                    </StackPanel>\r
+                    <ControlTemplate.Triggers>\r
+                        <Trigger Property="IsMouseOver" Value="True">\r
+                            <Setter TargetName="ToolButtonPanel" Property="Background"\r
+                                   Value="LightBlue"/>\r
+                        </Trigger>\r
+                    </ControlTemplate.Triggers>\r
+                </ControlTemplate>\r
+            </Setter.Value>\r
+        </Setter>\r
+    </Style>\r
+    <Style x:Key="ToolButtonMaxWindow" TargetType="Button">\r
+        <Setter Property="Template">\r
+            <Setter.Value>\r
+                <ControlTemplate TargetType="Button">\r
+                    <StackPanel x:Name="ToolButtonPanel">\r
+                        <Image Source="images/max_window2.png" Stretch="None" />\r
+                        <TextBlock Text="Maximz" Foreground="{StaticResource BasicForeBrush}"/>\r
+                    </StackPanel>\r
+                    <ControlTemplate.Triggers>\r
+                        <Trigger Property="IsMouseOver" Value="True">\r
+                            <Setter TargetName="ToolButtonPanel" Property="Background"\r
+                                   Value="LightBlue"/>\r
+                        </Trigger>\r
+                    </ControlTemplate.Triggers>\r
+                </ControlTemplate>\r
+            </Setter.Value>\r
+        </Setter>\r
+    </Style>\r
+    <Style x:Key="ToolButtonRestoreWindow" TargetType="Button">\r
+        <Setter Property="Template">\r
+            <Setter.Value>\r
+                <ControlTemplate TargetType="Button">\r
+                    <StackPanel x:Name="ToolButtonPanel">\r
+                        <Image Source="images/restore_window2.png" Stretch="None" />\r
+                        <TextBlock Text="Restre" Foreground="{StaticResource BasicForeBrush}"/>\r
+                    </StackPanel>\r
+                    <ControlTemplate.Triggers>\r
+                        <Trigger Property="IsMouseOver" Value="True">\r
+                            <Setter TargetName="ToolButtonPanel" Property="Background"\r
+                                   Value="LightBlue"/>\r
+                        </Trigger>\r
+                    </ControlTemplate.Triggers>\r
+                </ControlTemplate>\r
+            </Setter.Value>\r
+        </Setter>\r
+    </Style>\r
+    <!-- 設定ボタン-->\r
+    <Style x:Key="ToolButtonSetup" TargetType="Button">\r
+        <Setter Property="Template">\r
+            <Setter.Value>\r
+                <ControlTemplate TargetType="Button">\r
+                    <StackPanel x:Name="ToolButtonPanel" Width="50">\r
+                        <Image Source="images/setup_btn.png" Stretch="None" />\r
+                        <TextBlock Text="Setup" Foreground="{StaticResource BasicForeBrush}"\r
+                                   HorizontalAlignment="Center"/>\r
+                    </StackPanel>\r
+                    <ControlTemplate.Triggers>\r
+                        <Trigger Property="IsMouseOver" Value="True">\r
+                            <Setter TargetName="ToolButtonPanel" Property="Background"\r
+                                   Value="LightBlue"/>\r
+                        </Trigger>\r
+                    </ControlTemplate.Triggers>\r
+                </ControlTemplate>\r
+            </Setter.Value>\r
+        </Setter>\r
+    </Style>\r
+    <!-- 更新ボタン-->\r
+    <Style x:Key="ToolButtonUpdate" TargetType="Button">\r
+        <Setter Property="Template">\r
+            <Setter.Value>\r
+                <ControlTemplate TargetType="Button">\r
+                    <StackPanel x:Name="ToolButtonPanel" Width="50" Margin="2">\r
+                        <Image Source="images/update_btn_light.png" Stretch="None" />\r
+                        <TextBlock Text="Update" Foreground="{StaticResource BasicForeBrush}"\r
+                                   HorizontalAlignment="Center" />\r
+                    </StackPanel>\r
+                    <ControlTemplate.Triggers>\r
+                        <Trigger Property="IsMouseOver" Value="True">\r
+                            <Setter TargetName="ToolButtonPanel" Property="Background"\r
+                                   Value="LightBlue"/>\r
+                        </Trigger>\r
+                    </ControlTemplate.Triggers>\r
+                </ControlTemplate>\r
+            </Setter.Value>\r
+        </Setter>\r
+    </Style>\r
+    <!-- 一番上にジャンプボタン-->\r
+    <Style x:Key="ToolButtonJumpToTop" TargetType="Button">\r
+        <Setter Property="Template">\r
+            <Setter.Value>\r
+                <ControlTemplate TargetType="Button">\r
+                    <StackPanel x:Name="ToolButtonPanel" Width="50" Margin="2">\r
+                        <Image Source="images/to_the_top_light.png" Stretch="None" />\r
+                        <TextBlock Text="ToTop" Foreground="{StaticResource BasicForeBrush}"\r
+                                   HorizontalAlignment="Center" />\r
+                    </StackPanel>\r
+                    <ControlTemplate.Triggers>\r
+                        <Trigger Property="IsMouseOver" Value="True">\r
+                            <Setter TargetName="ToolButtonPanel" Property="Background"\r
+                                   Value="LightBlue"/>\r
+                        </Trigger>\r
+                    </ControlTemplate.Triggers>\r
+                </ControlTemplate>\r
+            </Setter.Value>\r
+        </Setter>\r
+    </Style>\r
+    <!-- 一番下にジャンプボタン-->\r
+    <Style x:Key="ToolButtonJumpToBottom" TargetType="Button">\r
+        <Setter Property="Template">\r
+            <Setter.Value>\r
+                <ControlTemplate TargetType="Button">\r
+                    <StackPanel x:Name="ToolButtonPanel" Width="50" Margin="2">\r
+                        <Image Source="images/to_the_bottom_light.png" Stretch="None" />\r
+                        <TextBlock Text="ToBottom" Foreground="{StaticResource BasicForeBrush}"\r
+                                   HorizontalAlignment="Center" />\r
+                    </StackPanel>\r
+                    <ControlTemplate.Triggers>\r
+                        <Trigger Property="IsMouseOver" Value="True">\r
+                            <Setter TargetName="ToolButtonPanel" Property="Background"\r
+                                   Value="LightBlue"/>\r
+                        </Trigger>\r
+                    </ControlTemplate.Triggers>\r
+                </ControlTemplate>\r
+            </Setter.Value>\r
+        </Setter>\r
+    </Style>\r
+    <!-- スレタイ検索ボタン-->\r
+    <Style x:Key="ToolButtonThreadTitleSearch" TargetType="Button">\r
+        <Setter Property="Template">\r
+            <Setter.Value>\r
+                <ControlTemplate TargetType="Button">\r
+                    <StackPanel x:Name="ToolButtonPanel" Width="50" Margin="2">\r
+                        <Image Source="images/search_btn_light.png" Stretch="None" />\r
+                        <TextBlock Text="Search" Foreground="{StaticResource BasicForeBrush}"\r
+                                   HorizontalAlignment="Center" />\r
+                    </StackPanel>\r
+                    <ControlTemplate.Triggers>\r
+                        <Trigger Property="IsMouseOver" Value="True">\r
+                            <Setter TargetName="ToolButtonPanel" Property="Background"\r
+                                   Value="LightBlue"/>\r
+                        </Trigger>\r
+                    </ControlTemplate.Triggers>\r
+                </ControlTemplate>\r
+            </Setter.Value>\r
+        </Setter>\r
+    </Style>\r
+    <!-- スレ作成ボタン-->\r
+    <Style x:Key="ToolButtonCreateThread" TargetType="Button">\r
+        <Setter Property="Template">\r
+            <Setter.Value>\r
+                <ControlTemplate TargetType="Button">\r
+                    <StackPanel x:Name="ToolButtonPanel" Width="50" Margin="2">\r
+                        <Image Source="images/write_btn.png" Stretch="None" />\r
+                        <TextBlock Text="Create" Foreground="{StaticResource BasicForeBrush}"\r
+                                   HorizontalAlignment="Center"/>\r
+                    </StackPanel>\r
+                    <ControlTemplate.Triggers>\r
+                        <Trigger Property="IsMouseOver" Value="True">\r
+                            <Setter TargetName="ToolButtonPanel" Property="Background"\r
+                                   Value="LightBlue"/>\r
+                        </Trigger>\r
+                    </ControlTemplate.Triggers>\r
+                </ControlTemplate>\r
+            </Setter.Value>\r
+        </Setter>\r
+    </Style>\r
+    <!-- レス検索ボタン-->\r
+    <Style x:Key="ToolButtonResSearch" TargetType="Button">\r
+        <Setter Property="Template">\r
+            <Setter.Value>\r
+                <ControlTemplate TargetType="Button">\r
+                    <StackPanel x:Name="ToolButtonPanel" Width="50"  Margin="2">\r
+                        <Image Source="images/search_btn_light.png" Stretch="None" />\r
+                        <TextBlock Text="Search" Foreground="{StaticResource BasicForeBrush}"\r
+                                   HorizontalAlignment="Center" />\r
+                    </StackPanel>\r
+                    <ControlTemplate.Triggers>\r
+                        <Trigger Property="IsMouseOver" Value="True">\r
+                            <Setter TargetName="ToolButtonPanel" Property="Background"\r
+                                   Value="LightBlue"/>\r
+                        </Trigger>\r
+                    </ControlTemplate.Triggers>\r
+                </ControlTemplate>\r
+            </Setter.Value>\r
+        </Setter>\r
+    </Style>\r
+    <!-- 新着スレへジャンプボタン-->\r
+    <Style x:Key="ToolButtonJumpToNew" TargetType="Button">\r
+        <Setter Property="Template">\r
+            <Setter.Value>\r
+                <ControlTemplate TargetType="Button">\r
+                    <StackPanel x:Name="ToolButtonPanel" Width="50" Margin="2">\r
+                        <Image Source="images/jmp_to_new.png" Stretch="None" />\r
+                        <TextBlock Text="New☆" Foreground="{StaticResource BasicForeBrush}"\r
+                                   HorizontalAlignment="Center"/>\r
+                    </StackPanel>\r
+                    <ControlTemplate.Triggers>\r
+                        <Trigger Property="IsMouseOver" Value="True">\r
+                            <Setter TargetName="ToolButtonPanel" Property="Background"\r
+                                   Value="LightBlue"/>\r
+                        </Trigger>\r
+                    </ControlTemplate.Triggers>\r
+                </ControlTemplate>\r
+            </Setter.Value>\r
+        </Setter>\r
+    </Style>\r
+    <!-- ブックマークへジャンプボタン-->\r
+    <Style x:Key="ToolButtonJumpToBookmark" TargetType="Button">\r
+        <Setter Property="Template">\r
+            <Setter.Value>\r
+                <ControlTemplate TargetType="Button">\r
+                    <StackPanel x:Name="ToolButtonPanel" Width="50" Margin="2">\r
+                        <Image Source="images/tag_btn.png" Stretch="None" />\r
+                        <TextBlock Text="B-Mark" Foreground="{StaticResource BasicForeBrush}"\r
+                                   HorizontalAlignment="Center"/>\r
+                    </StackPanel>\r
+                    <ControlTemplate.Triggers>\r
+                        <Trigger Property="IsMouseOver" Value="True">\r
+                            <Setter TargetName="ToolButtonPanel" Property="Background"\r
+                                   Value="LightBlue"/>\r
+                        </Trigger>\r
+                    </ControlTemplate.Triggers>\r
+                </ControlTemplate>\r
+            </Setter.Value>\r
+        </Setter>\r
+    </Style>\r
+    <!-- レス書込ボタン-->\r
+    <Style x:Key="ToolButtonWriteRes" TargetType="Button">\r
+        <Setter Property="Template">\r
+            <Setter.Value>\r
+                <ControlTemplate TargetType="Button">\r
+                    <StackPanel x:Name="ToolButtonPanel" Width="50" Margin="2">\r
+                        <Image Source="images/write_btn.png" Stretch="None" />\r
+                        <TextBlock Text="Write" Foreground="{StaticResource BasicForeBrush}"\r
+                                   HorizontalAlignment="Center"/>\r
+                    </StackPanel>\r
+                    <ControlTemplate.Triggers>\r
+                        <Trigger Property="IsMouseOver" Value="True">\r
+                            <Setter TargetName="ToolButtonPanel" Property="Background"\r
+                                   Value="LightBlue"/>\r
+                        </Trigger>\r
+                    </ControlTemplate.Triggers>\r
+                </ControlTemplate>\r
+            </Setter.Value>\r
+        </Setter>\r
+    </Style>\r
+    <!-- レス文字サイズ設定ボタン-->\r
+    <Style x:Key="ToolButtonSetupFont" TargetType="Button">\r
+        <Setter Property="Template">\r
+            <Setter.Value>\r
+                <ControlTemplate TargetType="Button">\r
+                    <StackPanel x:Name="ToolButtonPanel" Width="50" Margin="2">\r
+                        <Image Source="images/font_btn_ics.png" Stretch="None" />\r
+                        <TextBlock Text=" Font " Foreground="{StaticResource BasicForeBrush}"\r
+                                   HorizontalAlignment="Center"/>\r
+                    </StackPanel>\r
+                    <ControlTemplate.Triggers>\r
+                        <Trigger Property="IsMouseOver" Value="True">\r
+                            <Setter TargetName="ToolButtonPanel" Property="Background"\r
+                                   Value="LightBlue"/>\r
+                        </Trigger>\r
+                    </ControlTemplate.Triggers>\r
+                </ControlTemplate>\r
+            </Setter.Value>\r
+        </Setter>\r
+    </Style>\r
+    <!-- レスビュースクロール開始ボタン-->\r
+    <Style x:Key="ToolButtonPlayAutoScroll" TargetType="Button">\r
+        <Setter Property="Template">\r
+            <Setter.Value>\r
+                <ControlTemplate TargetType="Button">\r
+                    <StackPanel x:Name="ToolButtonPanel" Width="50" Margin="2">\r
+                        <Image Source="images/play_btn.png" Stretch="None" />\r
+                        <TextBlock Text="AutoRun" Foreground="{StaticResource BasicForeBrush}"\r
+                                   HorizontalAlignment="Center"/>\r
+                    </StackPanel>\r
+                    <ControlTemplate.Triggers>\r
+                        <Trigger Property="IsMouseOver" Value="True">\r
+                            <Setter TargetName="ToolButtonPanel" Property="Background"\r
+                                   Value="LightBlue"/>\r
+                        </Trigger>\r
+                    </ControlTemplate.Triggers>\r
+                </ControlTemplate>\r
+            </Setter.Value>\r
+        </Setter>\r
+    </Style>\r
+    <!-- レスビュースクロール終了ボタン-->\r
+    <Style x:Key="ToolButtonStopAutoScroll" TargetType="Button">\r
+        <Setter Property="Template">\r
+            <Setter.Value>\r
+                <ControlTemplate TargetType="Button">\r
+                    <StackPanel x:Name="ToolButtonPanel"  Width="50" Margin="2">\r
+                        <Image Source="images/stop_btn.png" Stretch="None" />\r
+                        <TextBlock Text="StopRun" Foreground="{StaticResource BasicForeBrush}"\r
+                                   HorizontalAlignment="Center"/>\r
+                    </StackPanel>\r
+                    <ControlTemplate.Triggers>\r
+                        <Trigger Property="IsMouseOver" Value="True">\r
+                            <Setter TargetName="ToolButtonPanel" Property="Background"\r
+                                   Value="LightBlue"/>\r
+                        </Trigger>\r
+                    </ControlTemplate.Triggers>\r
+                </ControlTemplate>\r
+            </Setter.Value>\r
+        </Setter>\r
+    </Style>\r
+    <!-- レスビューテキスト選択モードボタン-->\r
+    <Style x:Key="ToolButtonTextTool" TargetType="Button">\r
+        <Setter Property="Template">\r
+            <Setter.Value>\r
+                <ControlTemplate TargetType="Button">\r
+                    <StackPanel x:Name="ToolButtonPanel"  Width="50" Margin="2">\r
+                        <Image Source="images/texttools_btn.png" Stretch="None" />\r
+                        <TextBlock Text="TextSel" Foreground="{StaticResource BasicForeBrush}"\r
+                                   HorizontalAlignment="Center"/>\r
+                    </StackPanel>\r
+                    <ControlTemplate.Triggers>\r
+                        <Trigger Property="IsMouseOver" Value="True">\r
+                            <Setter TargetName="ToolButtonPanel" Property="Background"\r
+                                   Value="LightBlue"/>\r
+                        </Trigger>\r
+                    </ControlTemplate.Triggers>\r
+                </ControlTemplate>\r
+            </Setter.Value>\r
+        </Setter>\r
+    </Style>\r
+    <!-- レスビュータッチモードボタン-->\r
+    <Style x:Key="ToolButtonTouchMode" TargetType="Button">\r
+        <Setter Property="Template">\r
+            <Setter.Value>\r
+                <ControlTemplate TargetType="Button">\r
+                    <StackPanel x:Name="ToolButtonPanel"  Width="50" Margin="2">\r
+                        <Image Source="images/hand_btn.png" Stretch="None" />\r
+                        <TextBlock Text="Touch" Foreground="{StaticResource BasicForeBrush}"\r
+                                   HorizontalAlignment="Center"/>\r
+                    </StackPanel>\r
+                    <ControlTemplate.Triggers>\r
+                        <Trigger Property="IsMouseOver" Value="True">\r
+                            <Setter TargetName="ToolButtonPanel" Property="Background"\r
+                                   Value="LightBlue"/>\r
+                        </Trigger>\r
+                    </ControlTemplate.Triggers>\r
+                </ControlTemplate>\r
+            </Setter.Value>\r
+        </Setter>\r
+    </Style>\r
+</ResourceDictionary>
\ No newline at end of file
diff --git a/NT2chStyle45/NT2chStyle45.csproj b/NT2chStyle45/NT2chStyle45.csproj
new file mode 100755 (executable)
index 0000000..26731e9
--- /dev/null
@@ -0,0 +1,163 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />\r
+  <PropertyGroup>\r
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>\r
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>\r
+    <ProjectGuid>{D9D1B7B7-3E6E-4CED-B16A-1677BA957F73}</ProjectGuid>\r
+    <OutputType>library</OutputType>\r
+    <AppDesignerFolder>Properties</AppDesignerFolder>\r
+    <RootNamespace>NT2chStyle45</RootNamespace>\r
+    <AssemblyName>NT2chStyle45</AssemblyName>\r
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>\r
+    <FileAlignment>512</FileAlignment>\r
+    <ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>\r
+    <WarningLevel>4</WarningLevel>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">\r
+    <DebugSymbols>true</DebugSymbols>\r
+    <DebugType>full</DebugType>\r
+    <Optimize>false</Optimize>\r
+    <OutputPath>bin\Debug\</OutputPath>\r
+    <DefineConstants>TRACE;DEBUG;DOTNET45</DefineConstants>\r
+    <ErrorReport>prompt</ErrorReport>\r
+    <WarningLevel>4</WarningLevel>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">\r
+    <DebugType>pdbonly</DebugType>\r
+    <Optimize>true</Optimize>\r
+    <OutputPath>bin\Release\</OutputPath>\r
+    <DefineConstants>TRACE;DOTNET45</DefineConstants>\r
+    <ErrorReport>prompt</ErrorReport>\r
+    <WarningLevel>4</WarningLevel>\r
+  </PropertyGroup>\r
+  <PropertyGroup>\r
+    <SignAssembly>false</SignAssembly>\r
+  </PropertyGroup>\r
+  <PropertyGroup>\r
+    <AssemblyOriginatorKeyFile>\r
+    </AssemblyOriginatorKeyFile>\r
+  </PropertyGroup>\r
+  <ItemGroup>\r
+    <Reference Include="System" />\r
+    <Reference Include="System.Data" />\r
+    <Reference Include="System.Xml" />\r
+    <Reference Include="Microsoft.CSharp" />\r
+    <Reference Include="System.Core" />\r
+    <Reference Include="System.Xml.Linq" />\r
+    <Reference Include="System.Data.DataSetExtensions" />\r
+    <Reference Include="System.Xaml">\r
+      <RequiredTargetFramework>4.0</RequiredTargetFramework>\r
+    </Reference>\r
+    <Reference Include="WindowsBase" />\r
+    <Reference Include="PresentationCore" />\r
+    <Reference Include="PresentationFramework" />\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <Page Include="MainDictionary.xaml">\r
+      <SubType>Designer</SubType>\r
+      <Generator>MSBuild:Compile</Generator>\r
+    </Page>\r
+    <Page Include="Themes\Generic.xaml">\r
+      <Generator>MSBuild:Compile</Generator>\r
+      <SubType>Designer</SubType>\r
+    </Page>\r
+    <Compile Include="CustomControl1.cs">\r
+      <SubType>Code</SubType>\r
+    </Compile>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <Compile Include="Properties\AssemblyInfo.cs">\r
+      <SubType>Code</SubType>\r
+    </Compile>\r
+    <Compile Include="Properties\Resources.Designer.cs">\r
+      <AutoGen>True</AutoGen>\r
+      <DesignTime>True</DesignTime>\r
+      <DependentUpon>Resources.resx</DependentUpon>\r
+    </Compile>\r
+    <Compile Include="Properties\Settings.Designer.cs">\r
+      <AutoGen>True</AutoGen>\r
+      <DependentUpon>Settings.settings</DependentUpon>\r
+      <DesignTimeSharedInput>True</DesignTimeSharedInput>\r
+    </Compile>\r
+    <EmbeddedResource Include="Properties\Resources.resx">\r
+      <Generator>ResXFileCodeGenerator</Generator>\r
+      <LastGenOutput>Resources.Designer.cs</LastGenOutput>\r
+    </EmbeddedResource>\r
+    <None Include="Properties\Settings.settings">\r
+      <Generator>SettingsSingleFileGenerator</Generator>\r
+      <LastGenOutput>Settings.Designer.cs</LastGenOutput>\r
+    </None>\r
+    <AppDesigner Include="Properties\" />\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <Resource Include="images\back_btn.png" />\r
+    <Resource Include="images\back_btn_light.png" />\r
+    <Resource Include="images\close_tab.png" />\r
+    <Resource Include="images\down.png" />\r
+    <Resource Include="images\exit_btn.png" />\r
+    <Resource Include="images\exit_btn_light.png" />\r
+    <Resource Include="images\home_btn.png" />\r
+    <Resource Include="images\home_btn_light.png" />\r
+    <Resource Include="images\jmp_to_new.png" />\r
+    <Resource Include="images\search_btn.png" />\r
+    <Resource Include="images\search_btn_light.png" />\r
+    <Resource Include="images\setup_btn.png" />\r
+    <Resource Include="images\tag.png" />\r
+    <Resource Include="images\to_the_bottom.png" />\r
+    <Resource Include="images\to_the_bottom_light.png" />\r
+    <Resource Include="images\to_the_top.png" />\r
+    <Resource Include="images\to_the_top_light.png" />\r
+    <Resource Include="images\up.png" />\r
+    <Resource Include="images\update_btn.png" />\r
+    <Resource Include="images\update_btn_light.png" />\r
+    <Resource Include="images\write_btn.png" />\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <WCFMetadata Include="Service References\" />\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <Resource Include="images\history_btn.png" />\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <Resource Include="images\favo_off.png" />\r
+    <Resource Include="images\favo_on.png" />\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <Resource Include="images\max_window2.png" />\r
+    <Resource Include="images\restore_window2.png" />\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <Resource Include="images\font_btn.png" />\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <Resource Include="images\font_btn_ics.png" />\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <Resource Include="images\enlarge_font.png" />\r
+    <Resource Include="images\reduce_font.png" />\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <Resource Include="images\autoplay_btn.png" />\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <Resource Include="images\timer_btn.png" />\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <Resource Include="images\hand_btn.png" />\r
+    <Resource Include="images\pause_btn.png" />\r
+    <Resource Include="images\play_btn.png" />\r
+    <Resource Include="images\reverse.png" />\r
+    <Resource Include="images\stop_btn.png" />\r
+    <Resource Include="images\tag_btn.png" />\r
+    <Resource Include="images\texttools_btn.png" />\r
+  </ItemGroup>\r
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />\r
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. \r
+       Other similar extension points exist, see Microsoft.Common.targets.\r
+  <Target Name="BeforeBuild">\r
+  </Target>\r
+  <Target Name="AfterBuild">\r
+  </Target>\r
+  -->\r
+</Project>
\ No newline at end of file
diff --git a/NT2chStyle45/Properties/AssemblyInfo.cs b/NT2chStyle45/Properties/AssemblyInfo.cs
new file mode 100755 (executable)
index 0000000..42bfb4c
--- /dev/null
@@ -0,0 +1,55 @@
+using System.Reflection;\r
+using System.Resources;\r
+using System.Runtime.CompilerServices;\r
+using System.Runtime.InteropServices;\r
+using System.Windows;\r
+\r
+// アセンブリに関する一般情報は以下の属性セットをとおして制御されます。\r
+// アセンブリに関連付けられている情報を変更するには、\r
+// これらの属性値を変更してください。\r
+[assembly: AssemblyTitle("NT2chStyle45")]\r
+[assembly: AssemblyDescription("")]\r
+[assembly: AssemblyConfiguration("")]\r
+[assembly: AssemblyCompany("")]\r
+[assembly: AssemblyProduct("NT2chStyle45")]\r
+[assembly: AssemblyCopyright("Copyright ©  2012")]\r
+[assembly: AssemblyTrademark("")]\r
+[assembly: AssemblyCulture("")]\r
+\r
+// ComVisible を false に設定すると、その型はこのアセンブリ内で COM コンポーネントから\r
+// 参照不可能になります。COM からこのアセンブリ内の型にアクセスする場合は、\r
+// その型の ComVisible 属性を true に設定してください。\r
+[assembly: ComVisible(false)]\r
+\r
+//ローカライズ可能なアプリケーションのビルドを開始するには、\r
+//.csproj ファイルの <UICulture>CultureYouAreCodingWith</UICulture> を\r
+//<PropertyGroup> 内部で設定します。たとえば、\r
+//ソース ファイルで英語を使用している場合、<UICulture> を en-US に設定します。次に、\r
+//下の NeutralResourceLanguage 属性のコメントを解除します。下の行の "en-US" を\r
+//プロジェクト ファイルの UICulture 設定と一致するよう更新します。\r
+\r
+//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]\r
+\r
+\r
+[assembly:ThemeInfo(\r
+    ResourceDictionaryLocation.None, //テーマ固有のリソース ディクショナリが置かれている場所\r
+                             //(リソースがページ、\r
+                             // またはアプリケーション リソース ディクショナリに見つからない場合に使用されます)\r
+    ResourceDictionaryLocation.SourceAssembly //汎用リソース ディクショナリが置かれている場所\r
+                                      //(リソースがページ、\r
+                                      // アプリケーション、またはいずれのテーマ固有のリソース ディクショナリにも見つからない場合に使用されます)\r
+)]\r
+\r
+\r
+// アセンブリのバージョン情報は、以下の 4 つの値で構成されています:\r
+//\r
+//      Major Version\r
+//      Minor Version \r
+//      Build Number\r
+//      Revision\r
+//\r
+// すべての値を指定するか、下のように '*' を使ってビルドおよびリビジョン番号を \r
+// 既定値にすることができます:\r
+// [assembly: AssemblyVersion("1.0.*")]\r
+[assembly: AssemblyVersion("2.3.6.0")]\r
+[assembly: AssemblyFileVersion("2.3.6.0")]\r
diff --git a/NT2chStyle45/Properties/Resources.Designer.cs b/NT2chStyle45/Properties/Resources.Designer.cs
new file mode 100755 (executable)
index 0000000..c242428
--- /dev/null
@@ -0,0 +1,62 @@
+//------------------------------------------------------------------------------\r
+// <auto-generated>\r
+//     このコードはツールによって生成されました。\r
+//     ランタイム バージョン:4.0.30319.17626\r
+//\r
+//     このファイルへの変更は、以下の状況下で不正な動作の原因になったり、\r
+//     コードが再生成されるときに損失したりします\r
+// </auto-generated>\r
+//------------------------------------------------------------------------------\r
+\r
+namespace NT2chStyle45.Properties {\r
+    \r
+    \r
+    /// <summary>\r
+    ///   ローカライズされた文字列などを検索するための、厳密に型指定されたリソース クラスです。\r
+    /// </summary>\r
+    // このクラスは StronglyTypedResourceBuilder クラスによって ResGen\r
+    // または Visual Studio のようなツールを使用して自動生成されました。\r
+    // メンバーを追加または削除するには、.ResX ファイルを編集して、/str オプションと共に\r
+    // ResGen を実行し直すか、または VS プロジェクトをビルドし直します。\r
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]\r
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\r
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]\r
+    internal class Resources {\r
+        \r
+        private static global::System.Resources.ResourceManager resourceMan;\r
+        \r
+        private static global::System.Globalization.CultureInfo resourceCulture;\r
+        \r
+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]\r
+        internal Resources() {\r
+        }\r
+        \r
+        /// <summary>\r
+        ///   このクラスに使用される、キャッシュされた ResourceManager のインスタンスを返します。\r
+        /// </summary>\r
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]\r
+        internal static global::System.Resources.ResourceManager ResourceManager {\r
+            get {\r
+                if ((resourceMan == null)) {\r
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("NT2chStyle45.Properties.Resources", typeof(Resources).Assembly);\r
+                    resourceMan = temp;\r
+                }\r
+                return resourceMan;\r
+            }\r
+        }\r
+        \r
+        /// <summary>\r
+        ///   厳密に型指定されたこのリソース クラスを使用して、すべての検索リソースに対し、\r
+        ///   現在のスレッドの CurrentUICulture プロパティをオーバーライドします。\r
+        /// </summary>\r
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]\r
+        internal static global::System.Globalization.CultureInfo Culture {\r
+            get {\r
+                return resourceCulture;\r
+            }\r
+            set {\r
+                resourceCulture = value;\r
+            }\r
+        }\r
+    }\r
+}\r
diff --git a/NT2chStyle45/Properties/Resources.resx b/NT2chStyle45/Properties/Resources.resx
new file mode 100755 (executable)
index 0000000..ffecec8
--- /dev/null
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<root>\r
+  <!-- \r
+    Microsoft ResX Schema \r
+    \r
+    Version 2.0\r
+    \r
+    The primary goals of this format is to allow a simple XML format \r
+    that is mostly human readable. The generation and parsing of the \r
+    various data types are done through the TypeConverter classes \r
+    associated with the data types.\r
+    \r
+    Example:\r
+    \r
+    ... ado.net/XML headers & schema ...\r
+    <resheader name="resmimetype">text/microsoft-resx</resheader>\r
+    <resheader name="version">2.0</resheader>\r
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\r
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\r
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>\r
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>\r
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">\r
+        <value>[base64 mime encoded serialized .NET Framework object]</value>\r
+    </data>\r
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">\r
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\r
+        <comment>This is a comment</comment>\r
+    </data>\r
+                \r
+    There are any number of "resheader" rows that contain simple \r
+    name/value pairs.\r
+    \r
+    Each data row contains a name, and value. The row also contains a \r
+    type or mimetype. Type corresponds to a .NET class that support \r
+    text/value conversion through the TypeConverter architecture. \r
+    Classes that don't support this are serialized and stored with the \r
+    mimetype set.\r
+    \r
+    The mimetype is used for serialized objects, and tells the \r
+    ResXResourceReader how to depersist the object. This is currently not \r
+    extensible. For a given mimetype the value must be set accordingly:\r
+    \r
+    Note - application/x-microsoft.net.object.binary.base64 is the format \r
+    that the ResXResourceWriter will generate, however the reader can \r
+    read any of the formats listed below.\r
+    \r
+    mimetype: application/x-microsoft.net.object.binary.base64\r
+    value   : The object must be serialized with \r
+            : System.Serialization.Formatters.Binary.BinaryFormatter\r
+            : and then encoded with base64 encoding.\r
+    \r
+    mimetype: application/x-microsoft.net.object.soap.base64\r
+    value   : The object must be serialized with \r
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\r
+            : and then encoded with base64 encoding.\r
+\r
+    mimetype: application/x-microsoft.net.object.bytearray.base64\r
+    value   : The object must be serialized into a byte array \r
+            : using a System.ComponentModel.TypeConverter\r
+            : and then encoded with base64 encoding.\r
+    -->\r
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">\r
+    <xsd:element name="root" msdata:IsDataSet="true">\r
+      <xsd:complexType>\r
+        <xsd:choice maxOccurs="unbounded">\r
+          <xsd:element name="metadata">\r
+            <xsd:complexType>\r
+              <xsd:sequence>\r
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />\r
+              </xsd:sequence>\r
+              <xsd:attribute name="name" type="xsd:string" />\r
+              <xsd:attribute name="type" type="xsd:string" />\r
+              <xsd:attribute name="mimetype" type="xsd:string" />\r
+            </xsd:complexType>\r
+          </xsd:element>\r
+          <xsd:element name="assembly">\r
+            <xsd:complexType>\r
+              <xsd:attribute name="alias" type="xsd:string" />\r
+              <xsd:attribute name="name" type="xsd:string" />\r
+            </xsd:complexType>\r
+          </xsd:element>\r
+          <xsd:element name="data">\r
+            <xsd:complexType>\r
+              <xsd:sequence>\r
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />\r
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />\r
+              </xsd:sequence>\r
+              <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />\r
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />\r
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />\r
+            </xsd:complexType>\r
+          </xsd:element>\r
+          <xsd:element name="resheader">\r
+            <xsd:complexType>\r
+              <xsd:sequence>\r
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />\r
+              </xsd:sequence>\r
+              <xsd:attribute name="name" type="xsd:string" use="required" />\r
+            </xsd:complexType>\r
+          </xsd:element>\r
+        </xsd:choice>\r
+      </xsd:complexType>\r
+    </xsd:element>\r
+  </xsd:schema>\r
+  <resheader name="resmimetype">\r
+    <value>text/microsoft-resx</value>\r
+  </resheader>\r
+  <resheader name="version">\r
+    <value>2.0</value>\r
+  </resheader>\r
+  <resheader name="reader">\r
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\r
+  </resheader>\r
+  <resheader name="writer">\r
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\r
+  </resheader>\r
+</root>
\ No newline at end of file
diff --git a/NT2chStyle45/Properties/Settings.Designer.cs b/NT2chStyle45/Properties/Settings.Designer.cs
new file mode 100755 (executable)
index 0000000..fef4ad7
--- /dev/null
@@ -0,0 +1,30 @@
+//------------------------------------------------------------------------------\r
+// <auto-generated>\r
+//     This code was generated by a tool.\r
+//     Runtime Version:4.0.30319.17626\r
+//\r
+//     Changes to this file may cause incorrect behavior and will be lost if\r
+//     the code is regenerated.\r
+// </auto-generated>\r
+//------------------------------------------------------------------------------\r
+\r
+namespace NT2chStyle45.Properties\r
+{\r
+    \r
+    \r
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]\r
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]\r
+    internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase\r
+    {\r
+        \r
+        private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));\r
+        \r
+        public static Settings Default\r
+        {\r
+            get\r
+            {\r
+                return defaultInstance;\r
+            }\r
+        }\r
+    }\r
+}\r
diff --git a/NT2chStyle45/Properties/Settings.settings b/NT2chStyle45/Properties/Settings.settings
new file mode 100755 (executable)
index 0000000..8f2fd95
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version='1.0' encoding='utf-8'?>\r
+<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">\r
+  <Profiles>\r
+    <Profile Name="(Default)" />\r
+  </Profiles>\r
+  <Settings />\r
+</SettingsFile>
\ No newline at end of file
diff --git a/NT2chStyle45/Themes/Generic.xaml b/NT2chStyle45/Themes/Generic.xaml
new file mode 100755 (executable)
index 0000000..76dad04
--- /dev/null
@@ -0,0 +1,18 @@
+<ResourceDictionary\r
+    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"\r
+    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"\r
+    xmlns:local="clr-namespace:NT2chStyle45">\r
+    <Style TargetType="{x:Type local:CustomControl1}">\r
+        <Setter Property="Template">\r
+            <Setter.Value>\r
+                <ControlTemplate TargetType="{x:Type local:CustomControl1}">\r
+                    <Border Background="{TemplateBinding Background}"\r
+                            BorderBrush="{TemplateBinding BorderBrush}"\r
+                            BorderThickness="{TemplateBinding BorderThickness}">\r
+\r
+                    </Border>\r
+                </ControlTemplate>\r
+            </Setter.Value>\r
+        </Setter>\r
+    </Style>\r
+</ResourceDictionary>\r
diff --git a/NT2chStyle45/images/autoplay_btn.png b/NT2chStyle45/images/autoplay_btn.png
new file mode 100755 (executable)
index 0000000..177a48e
Binary files /dev/null and b/NT2chStyle45/images/autoplay_btn.png differ
diff --git a/NT2chStyle45/images/back_btn.png b/NT2chStyle45/images/back_btn.png
new file mode 100755 (executable)
index 0000000..8ade39a
Binary files /dev/null and b/NT2chStyle45/images/back_btn.png differ
diff --git a/NT2chStyle45/images/back_btn_light.png b/NT2chStyle45/images/back_btn_light.png
new file mode 100755 (executable)
index 0000000..3bc2104
Binary files /dev/null and b/NT2chStyle45/images/back_btn_light.png differ
diff --git a/NT2chStyle45/images/close_tab.png b/NT2chStyle45/images/close_tab.png
new file mode 100755 (executable)
index 0000000..6be645e
Binary files /dev/null and b/NT2chStyle45/images/close_tab.png differ
diff --git a/NT2chStyle45/images/down.png b/NT2chStyle45/images/down.png
new file mode 100755 (executable)
index 0000000..1a663f3
Binary files /dev/null and b/NT2chStyle45/images/down.png differ
diff --git a/NT2chStyle45/images/enlarge_font.png b/NT2chStyle45/images/enlarge_font.png
new file mode 100755 (executable)
index 0000000..c3bbbe8
Binary files /dev/null and b/NT2chStyle45/images/enlarge_font.png differ
diff --git a/NT2chStyle45/images/exit_btn.png b/NT2chStyle45/images/exit_btn.png
new file mode 100755 (executable)
index 0000000..3100538
Binary files /dev/null and b/NT2chStyle45/images/exit_btn.png differ
diff --git a/NT2chStyle45/images/exit_btn_light.png b/NT2chStyle45/images/exit_btn_light.png
new file mode 100755 (executable)
index 0000000..3bd4582
Binary files /dev/null and b/NT2chStyle45/images/exit_btn_light.png differ
diff --git a/NT2chStyle45/images/favo_off.png b/NT2chStyle45/images/favo_off.png
new file mode 100755 (executable)
index 0000000..b6c8e39
Binary files /dev/null and b/NT2chStyle45/images/favo_off.png differ
diff --git a/NT2chStyle45/images/favo_on.png b/NT2chStyle45/images/favo_on.png
new file mode 100755 (executable)
index 0000000..f82b2e0
Binary files /dev/null and b/NT2chStyle45/images/favo_on.png differ
diff --git a/NT2chStyle45/images/font_btn.png b/NT2chStyle45/images/font_btn.png
new file mode 100755 (executable)
index 0000000..073ac49
Binary files /dev/null and b/NT2chStyle45/images/font_btn.png differ
diff --git a/NT2chStyle45/images/font_btn_ics.png b/NT2chStyle45/images/font_btn_ics.png
new file mode 100755 (executable)
index 0000000..9fdb2c0
Binary files /dev/null and b/NT2chStyle45/images/font_btn_ics.png differ
diff --git a/NT2chStyle45/images/hand_btn.png b/NT2chStyle45/images/hand_btn.png
new file mode 100755 (executable)
index 0000000..7f4ddca
Binary files /dev/null and b/NT2chStyle45/images/hand_btn.png differ
diff --git a/NT2chStyle45/images/history_btn.png b/NT2chStyle45/images/history_btn.png
new file mode 100755 (executable)
index 0000000..6f40e44
Binary files /dev/null and b/NT2chStyle45/images/history_btn.png differ
diff --git a/NT2chStyle45/images/home_btn.png b/NT2chStyle45/images/home_btn.png
new file mode 100755 (executable)
index 0000000..7777ea4
Binary files /dev/null and b/NT2chStyle45/images/home_btn.png differ
diff --git a/NT2chStyle45/images/home_btn_light.png b/NT2chStyle45/images/home_btn_light.png
new file mode 100755 (executable)
index 0000000..0e15138
Binary files /dev/null and b/NT2chStyle45/images/home_btn_light.png differ
diff --git a/NT2chStyle45/images/jmp_to_new.png b/NT2chStyle45/images/jmp_to_new.png
new file mode 100755 (executable)
index 0000000..5cb9e77
Binary files /dev/null and b/NT2chStyle45/images/jmp_to_new.png differ
diff --git a/NT2chStyle45/images/max_window2.png b/NT2chStyle45/images/max_window2.png
new file mode 100755 (executable)
index 0000000..81e8f23
Binary files /dev/null and b/NT2chStyle45/images/max_window2.png differ
diff --git a/NT2chStyle45/images/pause_btn.png b/NT2chStyle45/images/pause_btn.png
new file mode 100755 (executable)
index 0000000..51ed34b
Binary files /dev/null and b/NT2chStyle45/images/pause_btn.png differ
diff --git a/NT2chStyle45/images/play_btn.png b/NT2chStyle45/images/play_btn.png
new file mode 100755 (executable)
index 0000000..13cf17a
Binary files /dev/null and b/NT2chStyle45/images/play_btn.png differ
diff --git a/NT2chStyle45/images/reduce_font.png b/NT2chStyle45/images/reduce_font.png
new file mode 100755 (executable)
index 0000000..2477f3f
Binary files /dev/null and b/NT2chStyle45/images/reduce_font.png differ
diff --git a/NT2chStyle45/images/restore_window2.png b/NT2chStyle45/images/restore_window2.png
new file mode 100755 (executable)
index 0000000..8d45201
Binary files /dev/null and b/NT2chStyle45/images/restore_window2.png differ
diff --git a/NT2chStyle45/images/reverse.png b/NT2chStyle45/images/reverse.png
new file mode 100755 (executable)
index 0000000..4da2cde
Binary files /dev/null and b/NT2chStyle45/images/reverse.png differ
diff --git a/NT2chStyle45/images/search_btn.png b/NT2chStyle45/images/search_btn.png
new file mode 100755 (executable)
index 0000000..e3c419e
Binary files /dev/null and b/NT2chStyle45/images/search_btn.png differ
diff --git a/NT2chStyle45/images/search_btn_light.png b/NT2chStyle45/images/search_btn_light.png
new file mode 100755 (executable)
index 0000000..6021f38
Binary files /dev/null and b/NT2chStyle45/images/search_btn_light.png differ
diff --git a/NT2chStyle45/images/setup_btn.png b/NT2chStyle45/images/setup_btn.png
new file mode 100755 (executable)
index 0000000..a861a84
Binary files /dev/null and b/NT2chStyle45/images/setup_btn.png differ
diff --git a/NT2chStyle45/images/stop_btn.png b/NT2chStyle45/images/stop_btn.png
new file mode 100755 (executable)
index 0000000..005d447
Binary files /dev/null and b/NT2chStyle45/images/stop_btn.png differ
diff --git a/NT2chStyle45/images/tag.png b/NT2chStyle45/images/tag.png
new file mode 100755 (executable)
index 0000000..905d749
Binary files /dev/null and b/NT2chStyle45/images/tag.png differ
diff --git a/NT2chStyle45/images/tag_btn.png b/NT2chStyle45/images/tag_btn.png
new file mode 100755 (executable)
index 0000000..d6590b4
Binary files /dev/null and b/NT2chStyle45/images/tag_btn.png differ
diff --git a/NT2chStyle45/images/texttools_btn.png b/NT2chStyle45/images/texttools_btn.png
new file mode 100755 (executable)
index 0000000..416c776
Binary files /dev/null and b/NT2chStyle45/images/texttools_btn.png differ
diff --git a/NT2chStyle45/images/timer_btn.png b/NT2chStyle45/images/timer_btn.png
new file mode 100755 (executable)
index 0000000..fc2b166
Binary files /dev/null and b/NT2chStyle45/images/timer_btn.png differ
diff --git a/NT2chStyle45/images/to_the_bottom.png b/NT2chStyle45/images/to_the_bottom.png
new file mode 100755 (executable)
index 0000000..11bc2e1
Binary files /dev/null and b/NT2chStyle45/images/to_the_bottom.png differ
diff --git a/NT2chStyle45/images/to_the_bottom_light.png b/NT2chStyle45/images/to_the_bottom_light.png
new file mode 100755 (executable)
index 0000000..53cb939
Binary files /dev/null and b/NT2chStyle45/images/to_the_bottom_light.png differ
diff --git a/NT2chStyle45/images/to_the_top.png b/NT2chStyle45/images/to_the_top.png
new file mode 100755 (executable)
index 0000000..fbc3f81
Binary files /dev/null and b/NT2chStyle45/images/to_the_top.png differ
diff --git a/NT2chStyle45/images/to_the_top_light.png b/NT2chStyle45/images/to_the_top_light.png
new file mode 100755 (executable)
index 0000000..2f46c59
Binary files /dev/null and b/NT2chStyle45/images/to_the_top_light.png differ
diff --git a/NT2chStyle45/images/up.png b/NT2chStyle45/images/up.png
new file mode 100755 (executable)
index 0000000..73e1816
Binary files /dev/null and b/NT2chStyle45/images/up.png differ
diff --git a/NT2chStyle45/images/update_btn.png b/NT2chStyle45/images/update_btn.png
new file mode 100755 (executable)
index 0000000..8ef4ae4
Binary files /dev/null and b/NT2chStyle45/images/update_btn.png differ
diff --git a/NT2chStyle45/images/update_btn_light.png b/NT2chStyle45/images/update_btn_light.png
new file mode 100755 (executable)
index 0000000..777bf59
Binary files /dev/null and b/NT2chStyle45/images/update_btn_light.png differ
diff --git a/NT2chStyle45/images/write_btn.png b/NT2chStyle45/images/write_btn.png
new file mode 100755 (executable)
index 0000000..bf2aba3
Binary files /dev/null and b/NT2chStyle45/images/write_btn.png differ
diff --git a/NT2chView45.sln b/NT2chView45.sln
new file mode 100755 (executable)
index 0000000..4fabd38
--- /dev/null
@@ -0,0 +1,44 @@
+\r
+Microsoft Visual Studio Solution File, Format Version 12.00\r
+# Visual Studio Express 2012 for Windows Desktop\r
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NT2chView45", "NT2chView45\NT2chView45.csproj", "{197BD61C-EC0B-44AF-9531-01999F437EB2}"\r
+EndProject\r
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NT2chStyle45", "NT2chStyle45\NT2chStyle45.csproj", "{D9D1B7B7-3E6E-4CED-B16A-1677BA957F73}"\r
+EndProject\r
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NT2chCtrl45", "NT2chCtrl45\NT2chCtrl45.csproj", "{4873F294-5F91-4364-8E6B-2B539B76F495}"\r
+EndProject\r
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NT2chObject45", "NT2chObject45\NT2chObject45.csproj", "{4E9CECF8-7DEA-45DB-9B25-D3F768A10C4B}"\r
+EndProject\r
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NT2chCtrl245", "NT2chCtrl245\NT2chCtrl245.csproj", "{8AB65B58-6B41-47DC-AA6F-6CA444180556}"\r
+EndProject\r
+Global\r
+       GlobalSection(SolutionConfigurationPlatforms) = preSolution\r
+               Debug|Any CPU = Debug|Any CPU\r
+               Release|Any CPU = Release|Any CPU\r
+       EndGlobalSection\r
+       GlobalSection(ProjectConfigurationPlatforms) = postSolution\r
+               {197BD61C-EC0B-44AF-9531-01999F437EB2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r
+               {197BD61C-EC0B-44AF-9531-01999F437EB2}.Debug|Any CPU.Build.0 = Debug|Any CPU\r
+               {197BD61C-EC0B-44AF-9531-01999F437EB2}.Release|Any CPU.ActiveCfg = Release|Any CPU\r
+               {197BD61C-EC0B-44AF-9531-01999F437EB2}.Release|Any CPU.Build.0 = Release|Any CPU\r
+               {D9D1B7B7-3E6E-4CED-B16A-1677BA957F73}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r
+               {D9D1B7B7-3E6E-4CED-B16A-1677BA957F73}.Debug|Any CPU.Build.0 = Debug|Any CPU\r
+               {D9D1B7B7-3E6E-4CED-B16A-1677BA957F73}.Release|Any CPU.ActiveCfg = Release|Any CPU\r
+               {D9D1B7B7-3E6E-4CED-B16A-1677BA957F73}.Release|Any CPU.Build.0 = Release|Any CPU\r
+               {4873F294-5F91-4364-8E6B-2B539B76F495}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r
+               {4873F294-5F91-4364-8E6B-2B539B76F495}.Debug|Any CPU.Build.0 = Debug|Any CPU\r
+               {4873F294-5F91-4364-8E6B-2B539B76F495}.Release|Any CPU.ActiveCfg = Release|Any CPU\r
+               {4873F294-5F91-4364-8E6B-2B539B76F495}.Release|Any CPU.Build.0 = Release|Any CPU\r
+               {4E9CECF8-7DEA-45DB-9B25-D3F768A10C4B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r
+               {4E9CECF8-7DEA-45DB-9B25-D3F768A10C4B}.Debug|Any CPU.Build.0 = Debug|Any CPU\r
+               {4E9CECF8-7DEA-45DB-9B25-D3F768A10C4B}.Release|Any CPU.ActiveCfg = Release|Any CPU\r
+               {4E9CECF8-7DEA-45DB-9B25-D3F768A10C4B}.Release|Any CPU.Build.0 = Release|Any CPU\r
+               {8AB65B58-6B41-47DC-AA6F-6CA444180556}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r
+               {8AB65B58-6B41-47DC-AA6F-6CA444180556}.Debug|Any CPU.Build.0 = Debug|Any CPU\r
+               {8AB65B58-6B41-47DC-AA6F-6CA444180556}.Release|Any CPU.ActiveCfg = Release|Any CPU\r
+               {8AB65B58-6B41-47DC-AA6F-6CA444180556}.Release|Any CPU.Build.0 = Release|Any CPU\r
+       EndGlobalSection\r
+       GlobalSection(SolutionProperties) = preSolution\r
+               HideSolutionNode = FALSE\r
+       EndGlobalSection\r
+EndGlobal\r
diff --git a/NT2chView45/App.xaml b/NT2chView45/App.xaml
new file mode 100755 (executable)
index 0000000..8ba9dff
--- /dev/null
@@ -0,0 +1,15 @@
+<Application x:Class="NT2chView.App"\r
+             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"\r
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"\r
+             StartupUri="MainWindow.xaml">\r
+    <Application.Resources>\r
+        <ResourceDictionary>\r
+            <ResourceDictionary.MergedDictionaries>\r
+                <ResourceDictionary \r
+                    Source = "/NT2chStyle45;Component/MainDictionary.xaml"/>\r
+                <!--ResourceDictionary Source="Dictionary1.xaml" />\r
+                <ResourceDictionary Source="Dictionary2.xaml" /-->\r
+            </ResourceDictionary.MergedDictionaries>\r
+        </ResourceDictionary>         \r
+    </Application.Resources>\r
+</Application>\r
diff --git a/NT2chView45/App.xaml.cs b/NT2chView45/App.xaml.cs
new file mode 100755 (executable)
index 0000000..254ebdc
--- /dev/null
@@ -0,0 +1,15 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Configuration;\r
+using System.Data;\r
+using System.Windows;\r
+\r
+namespace NT2chView\r
+{\r
+    /// <summary>\r
+    /// App.xaml の相互作用ロジック\r
+    /// </summary>\r
+    public partial class App : Application\r
+    {\r
+    }\r
+}\r
diff --git a/NT2chView45/MainWindow.xaml b/NT2chView45/MainWindow.xaml
new file mode 100755 (executable)
index 0000000..557afd3
--- /dev/null
@@ -0,0 +1,397 @@
+<Window\r
+        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"\r
+        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"\r
+        xmlns:cm="clr-namespace:System.ComponentModel;assembly=System"\r
+        xmlns:d="http://schemas.microsoft.com/expression/blend/2008" \r
+        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" \r
+        mc:Ignorable="d" x:Class="NT2chView.MainWindow"\r
+        xmlns:custom="clr-namespace:NT2chView"\r
+        xmlns:lib="clr-namespace:NT2chCtrl;assembly=NT2chCtrl45" \r
+        xmlns:lib2="clr-namespace:NT2chCtrl2;assembly=NT2chCtrl245" \r
+        Title="2ぃとちゃん Blue" Height="800" Width="920" Icon="/NT2chView45;component/images/neetchan2.png"         Loaded="MainWindow_Loaded" Closing="MainWindow_Closing"\r
+        Background="{StaticResource BasicBkBrush}" PreviewKeyDown="MainWindow_PreviewKeyDown"\r
+    >\r
+    <Window.Resources>\r
+        <LinearGradientBrush x:Key="lhsDragOrgBrush" EndPoint="0.5,1" StartPoint="0.5,0">\r
+            <LinearGradientBrush.RelativeTransform>\r
+                <TransformGroup>\r
+                    <ScaleTransform CenterY="0.5" CenterX="0.5"/>\r
+                    <SkewTransform CenterY="0.5" CenterX="0.5"/>\r
+                    <RotateTransform Angle="84.806" CenterY="0.5" CenterX="0.5"/>\r
+                    <TranslateTransform/>\r
+                </TransformGroup>\r
+            </LinearGradientBrush.RelativeTransform>\r
+            <GradientStop Color="#19F2F7F1"/>\r
+            <GradientStop Color="#FF21F70C" Offset="1"/>\r
+        </LinearGradientBrush>\r
+        <LinearGradientBrush x:Key="rhsDragOrgBrush" EndPoint="0.5,0" StartPoint="0.5,1">\r
+            <LinearGradientBrush.RelativeTransform>\r
+                <TransformGroup>\r
+                    <ScaleTransform CenterY="0.5" CenterX="0.5"/>\r
+                    <SkewTransform CenterY="0.5" CenterX="0.5"/>\r
+                    <RotateTransform Angle="84.806" CenterY="0.5" CenterX="0.5"/>\r
+                    <TranslateTransform/>\r
+                </TransformGroup>\r
+            </LinearGradientBrush.RelativeTransform>\r
+            <GradientStop Color="#19F2F7F1"/>\r
+            <GradientStop Color="#FF21F70C" Offset="1"/>\r
+        </LinearGradientBrush>\r
+        <LinearGradientBrush x:Key="lhsDragBrush" EndPoint="0.5,1" StartPoint="0.5,0">\r
+            <LinearGradientBrush.RelativeTransform>\r
+                <TransformGroup>\r
+                    <ScaleTransform CenterY="0.5" CenterX="0.5"/>\r
+                    <SkewTransform CenterY="0.5" CenterX="0.5"/>\r
+                    <RotateTransform Angle="84.806" CenterY="0.5" CenterX="0.5"/>\r
+                    <TranslateTransform/>\r
+                </TransformGroup>\r
+            </LinearGradientBrush.RelativeTransform>\r
+            <GradientStop Color="#19F2F7F1"/>\r
+            <GradientStop Color="#FFFF1493" Offset="1"/>\r
+        </LinearGradientBrush>\r
+        <LinearGradientBrush x:Key="rhsDragBrush" EndPoint="0.5,0" StartPoint="0.5,1">\r
+            <LinearGradientBrush.RelativeTransform>\r
+                <TransformGroup>\r
+                    <ScaleTransform CenterY="0.5" CenterX="0.5"/>\r
+                    <SkewTransform CenterY="0.5" CenterX="0.5"/>\r
+                    <RotateTransform Angle="84.806" CenterY="0.5" CenterX="0.5"/>\r
+                    <TranslateTransform/>\r
+                </TransformGroup>\r
+            </LinearGradientBrush.RelativeTransform>\r
+            <GradientStop Color="#19F2F7F1"/>\r
+            <GradientStop Color="#FFFF1493" Offset="1"/>\r
+        </LinearGradientBrush>\r
+        <Brush x:Key="orgDragBrush">\r
+            #02000000\r
+        </Brush>\r
+        <GeometryGroup x:Key="ToolbarHandleGeometry">\r
+            <RectangleGeometry Rect="3,3,3,3" />\r
+            <RectangleGeometry Rect="3,9,3,3" />\r
+            <RectangleGeometry Rect="3,15,3,3" />\r
+            <RectangleGeometry Rect="9,3,3,3" />\r
+            <RectangleGeometry Rect="9,9,3,3" />\r
+            <RectangleGeometry Rect="9,15,3,3" />\r
+            <RectangleGeometry Rect="15,3,3,3" />\r
+            <RectangleGeometry Rect="15,9,3,3" />\r
+            <RectangleGeometry Rect="15,15,3,3" />\r
+            <RectangleGeometry Rect="21,3,3,3" />\r
+            <RectangleGeometry Rect="21,9,3,3" />\r
+            <RectangleGeometry Rect="21,15,3,3" />\r
+            <RectangleGeometry Rect="27,3,3,3" />\r
+            <RectangleGeometry Rect="27,9,3,3" />\r
+            <RectangleGeometry Rect="27,15,3,3" />\r
+            <RectangleGeometry Rect="33,3,3,3" />\r
+            <RectangleGeometry Rect="33,9,3,3" />\r
+            <RectangleGeometry Rect="33,15,3,3" />\r
+            <RectangleGeometry Rect="39,3,3,3" />\r
+            <RectangleGeometry Rect="39,9,3,3" />\r
+            <RectangleGeometry Rect="39,15,3,3" />\r
+            <RectangleGeometry Rect="45,3,3,3" />\r
+            <RectangleGeometry Rect="45,9,3,3" />\r
+            <RectangleGeometry Rect="45,15,3,3" />\r
+            <RectangleGeometry Rect="51,3,3,3" />\r
+            <RectangleGeometry Rect="51,9,3,3" />\r
+            <RectangleGeometry Rect="51,15,3,3" />\r
+        </GeometryGroup>\r
+    </Window.Resources>\r
+    <DockPanel LastChildFill="True" Background="{StaticResource BasicBkBrush}" >\r
+        <Grid UseLayoutRounding="True">\r
+            <Grid.RowDefinitions>\r
+                <RowDefinition x:Name="mMainRow1" Height="*" MinHeight="20" />\r
+                <RowDefinition Height="Auto" />\r
+                <RowDefinition Height="2*" MinHeight="20"/>\r
+            </Grid.RowDefinitions>\r
+            <Grid.ColumnDefinitions>\r
+                <ColumnDefinition x:Name="mMainColumn1" Width="*" MinWidth="20" />\r
+                <ColumnDefinition Width="Auto"/>\r
+                <ColumnDefinition Width="2*" MinWidth="20"/>\r
+            </Grid.ColumnDefinitions>\r
+            <DockPanel Grid.Column="0" Grid.Row="0" Grid.RowSpan="3" LastChildFill="True" Background="{StaticResource BasicBkBrush}">\r
+                <ToolBarTray IsLocked="True" DockPanel.Dock="Top"  Background="{StaticResource BasicBkBrush}">\r
+                    <ToolBar Band="0" Background="{StaticResource BasicBkBrush}" >\r
+                        <Button x:Name="btnExit" Click="btnExit_Click" Style="{DynamicResource ToolButtonExit}"/>\r
+                        <Button x:Name="btnMaximizeWindow" Click="btnMaximizeWindow_Click" Style="{DynamicResource ToolButtonMaxWindow}"/>\r
+                        <Button x:Name="btnRestoreWindow" Click="btnRestoreWindow_Click" Style="{DynamicResource ToolButtonRestoreWindow}"/>\r
+                        <!--StackPanel>\r
+                                <Image Source="/NT2chView;component/images/exit_btn.png" Stretch="None" />\r
+                                <TextBlock Foreground="{StaticResource BasicForeBrush}">\r
+                                    <Run Text="Exit" />\r
+                                </TextBlock>\r
+                            </StackPanel>\r
+                        </Button-->\r
+                        <Button x:Name="btnSetup" Click="btnSetup_Click" Style="{DynamicResource ToolButtonSetup}"/>\r
+                        <!--StackPanel>\r
+                                <Image Source="/NT2chView;component/images/setup_btn.png" Stretch="None" />\r
+                                <TextBlock Foreground="{StaticResource BasicForeBrush}"><Run Text="Setup"/></TextBlock>\r
+                            </StackPanel>\r
+                        </Button-->\r
+                    </ToolBar>\r
+                    <ToolBar Background="{StaticResource BasicBkBrush}">\r
+                        <StackPanel Orientation="Vertical" Background="{StaticResource BasicBkBrush}">\r
+                            <ProgressBar x:Name="progressCtrlCloud" VerticalAlignment="Bottom" Margin="5" Width="60" Height="10"  IsIndeterminate="True"/>\r
+                            <Label \r
+                                VerticalAlignment="Center" \r
+                                VerticalContentAlignment="Center" \r
+                                HorizontalAlignment="Center" \r
+                                 Foreground="{StaticResource BasicForeBrush}"\r
+                                Content="Cloud"/>\r
+                        </StackPanel>\r
+                    </ToolBar>\r
+                </ToolBarTray>\r
+\r
+                <StatusBar DockPanel.Dock="Bottom">\r
+                    <StatusBarItem Grid.Column="0" HorizontalAlignment="Stretch">\r
+                        <StackPanel Orientation="Horizontal" HorizontalAlignment="Stretch" Width="209.513">\r
+                            <Label x:Name="MainWindowLblStatusBar" Content="Processing..." Margin="3" Padding="1" />\r
+                            <ProgressBar  Height="13" x:Name="MainWindowProgressBar" HorizontalAlignment="Stretch" Margin="5" Width="117" />\r
+                        </StackPanel>\r
+                    </StatusBarItem>\r
+\r
+                </StatusBar>\r
+                <TabControl x:Name="tabCtrlMain"    Margin="5" TabStripPlacement="Top" SelectionChanged="tabCtrlMain_SelectionChanged" Background="{DynamicResource SelectedTabBkBrush}">\r
+                    <TabItem Header="Home" Background="{DynamicResource SelectedTabBkBrush}">\r
+                        <!-- TreeView x:Name="treeMainView"  SelectedItemChanged="treeBoardView_SelectedItemChanged"/ -->\r
+\r
+                        <Grid>\r
+                            <Grid.RowDefinitions>\r
+                                <RowDefinition x:Name="mLeftPanelRow1" Height="2*"/>\r
+                                <RowDefinition Height="Auto"/>\r
+                                <RowDefinition Height="3*"/>\r
+                            </Grid.RowDefinitions>\r
+                            <custom:NTCategoryPanel  x:Name="mCategoryPanel" Grid.Row="0"/>\r
+                            <GridSplitter Grid.Row="1" Height="8" \r
+                                VerticalAlignment="Center" HorizontalAlignment="Stretch"\r
+                                ShowsPreview="False" Background="LightGray" Cursor="SizeNS"\r
+                                          />\r
+                            <Border BorderBrush="LightGray" Margin="2" Padding="5" BorderThickness="2" Grid.Row="2">\r
+                                <Grid>\r
+                                    <custom:NTBoardPanel  x:Name="mBoardPanel"/>\r
+                                    <custom:NTFavoritePanel  x:Name="mFavoritePanel" />\r
+                                </Grid>\r
+                            </Border>\r
+                        </Grid>\r
+                    </TabItem>\r
+                    <TabItem x:Name="tabItemNgEdit" Header="NG">\r
+                        <Grid>\r
+                            <Grid.RowDefinitions>\r
+                                <RowDefinition Height="Auto"/>\r
+                                <RowDefinition Height="*"/>\r
+                            </Grid.RowDefinitions>\r
+                            <Border BorderThickness="2" Padding="5" Margin="2" BorderBrush="DarkGray" CornerRadius="10">\r
+                                <Grid>\r
+                                    <Grid.ColumnDefinitions>\r
+                                        <ColumnDefinition/>\r
+                                        <ColumnDefinition/>\r
+                                    </Grid.ColumnDefinitions>\r
+                                    <Grid.RowDefinitions>\r
+                                        <RowDefinition/>\r
+                                        <RowDefinition/>\r
+                                        <RowDefinition/>\r
+                                        <RowDefinition/>\r
+                                        <RowDefinition/>\r
+                                        <RowDefinition/>\r
+                                    </Grid.RowDefinitions>\r
+                                    <Label Content="NG:NAME"/>\r
+                                    <Button x:Name="btnAddNgName" Grid.Column="1" HorizontalAlignment="Right" Margin="0,0,10,0" Click="btnAddNgName_Click" Content="追加"/>\r
+                                    <TextBox x:Name="txtNgNameEdit" Grid.ColumnSpan="2"  Grid.Row="1" MaxLines="1" Margin="2"/>\r
+                                    <Label Grid.Row="2" Content="NG:ID"/>\r
+                                    <Button x:Name="btnAddNgId" Grid.Column="1" Grid.Row="2" HorizontalAlignment="Right" Margin="0,0,10,0" Click="btnAddNgId_Click" Content="追加"/>\r
+                                    <TextBox x:Name="txtNgIdEdit" Grid.Row="3" Grid.ColumnSpan="2" Margin="2" MaxLines="1"/>\r
+                                    <Label Grid.Row="4" Content="NG:WORD"/>\r
+                                    <Button x:Name="btnAddNgWord" Grid.Row="4" Grid.Column="2" HorizontalAlignment="Right" Margin="0,0,10,0" Click="btnAddNgWord_Click" Content="追加"/>\r
+                                    <ScrollViewer  Grid.Row="5" Grid.ColumnSpan="2" Height="100">\r
+                                        <TextBox x:Name="txtNgWordEdit" MinLines="5" Margin="2" AcceptsReturn="True"/>\r
+                                    </ScrollViewer>\r
+                                </Grid>\r
+                            </Border>\r
+                            <Grid Grid.Row="1">\r
+                                <Grid.RowDefinitions>\r
+                                    <RowDefinition Height="Auto"/>\r
+                                    <RowDefinition Height="*"/>\r
+                                    <RowDefinition Height="Auto"/>\r
+                                    <RowDefinition Height="Auto"/>\r
+                                </Grid.RowDefinitions>\r
+                                <ComboBox Margin="5" x:Name="cmbNgEditKind" SelectedIndex="0" SelectionChanged="cmbNgEditKind_SelectionChanged">\r
+                                    <ComboBoxItem Content="NG:WORD"/>\r
+                                    <ComboBoxItem Content="NG:NAME"/>\r
+                                    <ComboBoxItem Content="NG:ID"/>\r
+                                </ComboBox>\r
+                                <ScrollViewer Grid.Row="1" >\r
+                                    <TextBox x:Name="txtNgEdit" Margin="3" VerticalAlignment="Stretch"  AcceptsReturn="True" AutoWordSelection="True" TextChanged="txtNgEdit_TextChanged" />\r
+                                </ScrollViewer>\r
+                                <Button Grid.Row="2" x:Name="btnSaveNgEdit"  HorizontalAlignment="Right" Padding="10,2" Margin="5,2,20,2" Click="btnSaveNgEdit_Click" Content="保存"/>\r
+\r
+                                <TextBox Grid.Row="3" MinLines="3" TextWrapping="WrapWithOverflow" IsEnabled="False" BorderThickness="0" FontSize="10" Text="NGワードの指定は行単位です。 複数行の文章を指定すると各行毎に個別のNGワードとして認識します。" />\r
+\r
+                            </Grid>\r
+                        </Grid>\r
+                    </TabItem>\r
+                    <TabItem x:Name="tabItemSearch" Header="検索">\r
+                        <Grid>\r
+                            <Grid.RowDefinitions>\r
+                                <RowDefinition Height="Auto"/>\r
+                                <RowDefinition Height="Auto"/>\r
+                                <RowDefinition Height="Auto"/>\r
+                                <RowDefinition Height="Auto"/>\r
+                                <RowDefinition Height="*"/>\r
+                                <RowDefinition Height="Auto"/>\r
+                                <RowDefinition Height="Auto"/>\r
+                            </Grid.RowDefinitions>\r
+                            <Grid.ColumnDefinitions>\r
+                                <ColumnDefinition Width="*"/>\r
+                                <ColumnDefinition Width="Auto"/>\r
+                                <ColumnDefinition Width="Auto"/>\r
+                            </Grid.ColumnDefinitions>\r
+                            <Label Content="タイトル検索" />\r
+                            <TextBox Grid.Row="1" Grid.ColumnSpan="2" x:Name="txtTitleSearch" VerticalContentAlignment="Center" />\r
+                            <Button x:Name="btnTitleSearch" Click="btnTitleSearch_Click" Grid.Row="1"  Grid.Column="2"  HorizontalAlignment="Center" >\r
+                                <Image Source="/NT2chView45;component/images/search_btn.png" Stretch="None" VerticalAlignment="Center" />\r
+                            </Button>\r
+                            <Label Grid.Row="2" Content="全板検索" />\r
+                            <TextBox x:Name="txtAllBoardSeach" Grid.Row="3" Grid.ColumnSpan="2" VerticalContentAlignment="Center"/>\r
+                            <Button x:Name="btnAllBoardSearch" Click="btnAllBoardSearch_Click" Grid.Row="3" Grid.Column="2" VerticalContentAlignment="Center" HorizontalAlignment="Center" >\r
+                                <Image Source="/NT2chView45;component/images/search_btn.png" Stretch="None" VerticalAlignment="Center" />\r
+                            </Button>\r
+                            <ScrollViewer HorizontalScrollBarVisibility="Auto" Grid.Row="4" Grid.ColumnSpan="3" Margin="3,5,3,10" >\r
+                                <ListBox x:Name="lstSearchedThread" VerticalAlignment="Stretch" SelectionChanged="lstSearchedThread_SelectionChanged"/>\r
+                            </ScrollViewer>\r
+                            <Label Grid.Row="5" Content="メッセージ検索" />\r
+                            <TextBox x:Name="txtMsgSearch" Grid.Row="6" VerticalContentAlignment="Center" Margin="3,3,0,3"/>\r
+                            <Button x:Name="btnMsgSearchPrev" Grid.Row="6" Grid.Column="1" VerticalContentAlignment="Center" HorizontalAlignment="Center" Margin="0,3,3,3" Click="btnMsgSearchPrev_Click">\r
+                                <Image  Source="images/left.png" Stretch="None" VerticalAlignment="Center" />\r
+                            </Button>\r
+                            <Button x:Name="btnMsgSearchNext" Grid.Row="6" Grid.Column="2" VerticalContentAlignment="Center" HorizontalAlignment="Center" Margin="0,3,3,3" Click="btnMsgSearchNext_Click">\r
+                                <Image  Source="images/right.png" Stretch="None" VerticalAlignment="Center" />\r
+                            </Button>\r
+                        </Grid>\r
+                    </TabItem>\r
+                    <TabItem x:Name="tabItemHistory" Header="履歴">\r
+                        <Grid>\r
+                            <custom:NTHistoryPanel  x:Name="mHistoryPanel"/>\r
+                        </Grid>\r
+                    </TabItem>\r
+                    <TabItem x:Name="tabItemMovie" Header="動画">\r
+                        <Grid>\r
+                            <custom:NTMoviePanel  x:Name="mMoviePanel"/>\r
+                        </Grid>\r
+                    </TabItem>\r
+                    <TabItem x:Name="tabItemGraphics" Header="画像">\r
+                        <Grid>\r
+                            <custom:NTGraphicsPanel  x:Name="mGraphicsPanel"/>\r
+                        </Grid>\r
+                    </TabItem>\r
+                </TabControl>\r
+\r
+\r
+            </DockPanel>\r
+            <DockPanel Grid.Column="2" Grid.Row="0" LastChildFill="True">\r
+                <ToolBarTray IsLocked="True" DockPanel.Dock="Right" x:Name="mTooltrayThreadTitleView"\r
+                             Orientation="Vertical" Background="{StaticResource BasicBkBrush}">\r
+                    <ToolBar  Background="{StaticResource BasicBkBrush}" x:Name="mToolbarThreadTitleView">\r
+                        <Canvas x:Name="mThreadTitleViewToolHandle" Height="20" Margin="0,2,0,10" \r
+                                Background="{StaticResource BasicBkBrush}"\r
+                                MouseEnter="mThreadTitleViewToolHandle_MouseEnter" \r
+                                MouseLeave="mThreadTitleViewToolHandle_MouseLeave"\r
+                                MouseLeftButtonDown="mThreadTitleViewToolHandle_MouseLeftBouttnDown" \r
+                                MouseLeftButtonUp="mThreadTitleViewToolHandle_MouseLeftButtonUp" \r
+                                MouseMove="mThreadTitleViewToolHandle_MouseMove" Cursor="Hand">\r
+                            <Path Fill="Beige" Data="{StaticResource ToolbarHandleGeometry}">\r
+                            </Path>\r
+                        </Canvas>\r
+                        <Button x:Name="btnUpdateInSubject" Click="btnUpdateInSubject_Click" Style="{DynamicResource ToolButtonUpdate}">\r
+                        </Button>\r
+                        <Button x:Name="btnJumpToTopInSubject" Click="btnJumpToTopInSubject_Click" Style="{DynamicResource ToolButtonJumpToTop}"/>\r
+                        <Button x:Name="btnJumpToBottomInSubject" Click="btnJumpToBottomInSubject_Click" Style="{DynamicResource ToolButtonJumpToBottom}"/>\r
+                        <Button x:Name="btnThreadTitleSearch" Click="btnThreadTitleSearch_Click" Style="{DynamicResource ToolButtonThreadTitleSearch}"/>\r
+                        <Button x:Name="btnCreateThread" Click="btnCreateThread_Click" Style="{DynamicResource ToolButtonCreateThread}"/>\r
+                    </ToolBar>\r
+                </ToolBarTray>\r
+                <Grid>\r
+                    <!--TabControl x:Name="tabCtrlSubject" Margin="3"/ -->\r
+                    <lib2:NTSubjectViewPanel x:Name="mSubjectPanel" />\r
+                    <Canvas x:Name="mThreadTitleViewLHSDragCanvas"\r
+                            AllowDrop="True" Width="20" Height="Auto" \r
+                            Background="{StaticResource lhsDragOrgBrush}"\r
+                            HorizontalAlignment="Left" \r
+                            DragEnter="mThreadTitleViewLHSDragCanvas_DragEnter" \r
+                            DragLeave="mThreadTitleViewLHSDragCanvas_DragLeave" \r
+                            DragOver="mThreadTitleViewLHSDragCanvas_DragOver" \r
+                            Drop="mThreadTitleViewLHSDragCanvas_Drop">\r
+                    </Canvas>\r
+                    <Canvas x:Name="mThreadTitleViewRHSDragCanvas"\r
+                            AllowDrop="True" Width="20" Height="Auto" \r
+                            Background="{StaticResource rhsDragOrgBrush}"\r
+                            HorizontalAlignment="Right" \r
+                            DragEnter="mThreadTitleViewRHSDragCanvas_DragEnter" \r
+                            DragLeave="mThreadTitleViewRHSDragCanvas_DragLeave" \r
+                            DragOver="mThreadTitleViewRHSDragCanvas_DragOver" \r
+                            Drop="mThreadTitleViewRHSDragCanvas_Drop"/>\r
+                </Grid>\r
+            </DockPanel>\r
+            <DockPanel LastChildFill="True" Grid.Column="2" Grid.Row="2">\r
+                <ToolBarTray IsLocked="True"  x:Name="mTooltrayResView" DockPanel.Dock="Right" \r
+                             Orientation="Vertical" Background="{StaticResource BasicBkBrush}">\r
+                    <ToolBar x:Name="mToolbarResView" Background="{StaticResource BasicBkBrush}" VerticalAlignment="Top" >\r
+                        <Canvas x:Name="mResViewToolHandle" Height="20" Margin="0,2,0,10" \r
+                                Background="{StaticResource BasicBkBrush}" \r
+                                MouseEnter="mResViewToolHandle_MouseEnter" \r
+                                MouseLeave="mResViewToolHandle_MouseLeave"\r
+                                MouseLeftButtonDown="mResViewToolHandle_MouseLeftBouttnDown" \r
+                                MouseLeftButtonUp="mResViewToolHandle_MouseLeftButtonUp" \r
+                                MouseMove="mResViewToolHandle_MouseMove" Cursor="Hand">\r
+                            <Path Fill="Beige" Data="{StaticResource ToolbarHandleGeometry}">                                \r
+                            </Path>\r
+                        </Canvas>\r
+                        <Button x:Name="btnUpdate" Click="btnUpdate_Click" Style="{DynamicResource ToolButtonUpdate}"/>\r
+                        <Button Click="btnJumpToTop_Click" x:Name="btnJumpToTop" Style="{DynamicResource ToolButtonJumpToTop}"/>\r
+                        <Button Click="btnJumpToBottom_Click" x:Name="btnJumpToBottom"  Style="{DynamicResource ToolButtonJumpToBottom}"/>\r
+                        <Button Click="btnResSearch_Click" x:Name="btnResSeach"  Style="{DynamicResource ToolButtonResSearch}"/>\r
+                        <Button Click="btnJumpToNew_Click" x:Name="btnJumpToNew"  Style="{DynamicResource ToolButtonJumpToNew}"/>\r
+                        <Button x:Name="btnJmpNextBookmark" Click="btnJumpNextBookmark_Click"  Style="{DynamicResource ToolButtonJumpToBookmark}"/>\r
+                        <Button x:Name="btnWriteRes" Click="btnWriteRes_Click"  \r
+                                Style="{DynamicResource ToolButtonWriteRes}" />\r
+                        <Button x:Name="btnSetupFont" Click="btnFontSetup_Click"  \r
+                                Style="{DynamicResource ToolButtonSetupFont}" />\r
+                        <Button x:Name="btnPlayAutoScroll" Click="btnPlayAutoScroll_Click" \r
+                                Style="{DynamicResource ToolButtonPlayAutoScroll}" />\r
+                        <Button x:Name="btnStopAutoScroll" Click="btnStopAutoScroll_Click" \r
+                                Style="{DynamicResource ToolButtonStopAutoScroll}" />\r
+                        <Button x:Name="btnTextTool"   Click="btnTextTool_Click" \r
+                                Style="{DynamicResource ToolButtonTextTool}" />\r
+                        <Button x:Name="btnTouchMode"  Click="btnTouchMode_Click" \r
+                                Style="{DynamicResource ToolButtonTouchMode}" />\r
+                    </ToolBar>\r
+                </ToolBarTray>\r
+                <!--TabControl x:Name="tabCtrlDat"  Visibility="Collapsed" Margin="3" TabStripPlacement="Top" /-->\r
+                <Grid x:Name="gridResPanel" >\r
+                    <lib:NTResViewPanel x:Name="mResPanel"/>\r
+                    <Canvas x:Name="mLHSDragCanvas" \r
+                            AllowDrop="True" Width="20" Height="Auto"\r
+                            HorizontalAlignment="Left" \r
+                            Background="{StaticResource lhsDragOrgBrush}"\r
+                            DragEnter="mLHSDragCanvas_DragEnter" \r
+                            DragLeave="mLHSDragCanvas_DragLeave" \r
+                            DragOver="mLHSDragCanvas_DragOver" \r
+                            Drop="mLHSDragCanvas_Drop">\r
+                    </Canvas>\r
+                    <Canvas x:Name="mRHSDragCanvas" \r
+                            AllowDrop="True" Width="20" Height="Auto"\r
+                            HorizontalAlignment="Right" \r
+                            Background="{StaticResource rhsDragOrgBrush}"\r
+                            DragEnter="mRHSDragCanvas_DragEnter" \r
+                            DragLeave="mRHSDragCanvas_DragLeave" \r
+                            DragOver="mRHSDragCanvas_DragOver" \r
+                            Drop="mRHSDragCanvas_Drop"/>\r
+                </Grid>\r
+            </DockPanel>\r
+            <GridSplitter Grid.Column="1" Width="8" \r
+                          Grid.Row="0" Grid.RowSpan="3"\r
+                          VerticalAlignment="Stretch" HorizontalAlignment="Center"\r
+                          ShowsPreview="False" Background="LightGray" Cursor="SizeWE"/>\r
+            <GridSplitter Grid.Column="1" Height="8" \r
+                          Grid.Row="1" Grid.ColumnSpan="2"\r
+                          VerticalAlignment="Center" HorizontalAlignment="Stretch"\r
+                          ShowsPreview="False" Background="LightGray" Cursor="SizeNS"/>\r
+        </Grid>\r
+\r
+    </DockPanel>\r
+</Window>\r
diff --git a/NT2chView45/MainWindow.xaml.cs b/NT2chView45/MainWindow.xaml.cs
new file mode 100755 (executable)
index 0000000..d6f31d9
--- /dev/null
@@ -0,0 +1,928 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Windows;\r
+using System.Windows.Controls;\r
+using System.Windows.Data;\r
+using System.Windows.Documents;\r
+using System.Windows.Input;\r
+using System.Windows.Media;\r
+using System.Windows.Media.Imaging;\r
+using System.Windows.Navigation;\r
+using System.Windows.Shapes;\r
+using System.IO;\r
+using NT2chView.NtNet;\r
+using NT2chView.NtFile;\r
+using NT2chView.NtHtml;\r
+using System.Threading;\r
+using System.Windows.Threading;\r
+using System.ComponentModel;\r
+using NT2chCtrl;\r
+using NT2chHistory;\r
+using NT2chObject;\r
+using NT2chView.NtUI;\r
+\r
+namespace NT2chView\r
+{\r
+    /// <summary>\r
+    /// MainWindow.xaml の相互作用ロジック\r
+    /// </summary>\r
+    public partial class MainWindow : Window\r
+    {\r
+\r
+        Dictionary<string, NTBoard> mDicBoardUpdateRequest = \r
+            new Dictionary<string, NTBoard>();\r
+        //int mProgressDelta;\r
+        //int mProgressValue;\r
+\r
+        NTFavorite mFavoriteData;\r
+\r
+        NTBoard.DelegateMsgOnNotifyBoardUpdate mOnNotifyBoardUpdate;\r
+        NTBoard.DelegateMsgOnNotifyBoardUpdate mOnNotifyBoardUpdateB;\r
+\r
+        public NTFavorite getFavoriteData()\r
+        {\r
+            return mFavoriteData;\r
+        }\r
+\r
+        public MainWindow()\r
+        {\r
+            InitializeComponent();\r
+\r
+            mOnNotifyBoardUpdate = new NTBoard.DelegateMsgOnNotifyBoardUpdate(onNotifyBoardUpdateA);\r
+            mOnNotifyBoardUpdateB = new NTBoard.DelegateMsgOnNotifyBoardUpdate(onNotifyBoardUpdateB);\r
+\r
+\r
+            if (!init())\r
+            {\r
+                Close();\r
+                return;\r
+            }\r
+\r
+            Width = NTUserPreference.WindowWidth;\r
+            Height = NTUserPreference.WindowHeight;\r
+            this.Top = NTUserPreference.WindowTop;\r
+            this.Left = NTUserPreference.WindowLeft;\r
+\r
+            if (NTUserPreference.WindowMaximized)\r
+            {\r
+                this.WindowStyle = System.Windows.WindowStyle.None;\r
+                this.WindowState = System.Windows.WindowState.Maximized;\r
+                this.btnMaximizeWindow.Visibility = System.Windows.Visibility.Collapsed;\r
+            }\r
+            else\r
+            {\r
+                this.WindowState = System.Windows.WindowState.Normal;\r
+                this.btnRestoreWindow.Visibility = System.Windows.Visibility.Collapsed;\r
+            }\r
+\r
+            mMainColumn1.Width = new GridLength(NTUserPreference.WindowColumn1);\r
+            mMainRow1.Height = new GridLength(NTUserPreference.WindowRow1);\r
+            mLeftPanelRow1.Height = new GridLength(NTUserPreference.WindowLeftPanelRow1);\r
+\r
+            this.ResizeMode = System.Windows.ResizeMode.CanResizeWithGrip;\r
+\r
+            if (NTUserPreference.ResViewToolbarPosition ==\r
+                NTDragDrop.TOOLBAR_LOCATION_LEFT)\r
+            {\r
+                mTooltrayResView.SetValue(DockPanel.DockProperty, Dock.Left);\r
+            }\r
+            if (NTUserPreference.ThreadTitleViewToolbarPosition ==\r
+                NTDragDrop.TOOLBAR_LOCATION_LEFT)\r
+            {\r
+                mTooltrayThreadTitleView.SetValue(DockPanel.DockProperty, Dock.Left);\r
+            }\r
+\r
+            hideAllToolbarDropCanvas();\r
+\r
+\r
+        }\r
+\r
+        bool init()\r
+        {\r
+\r
+            // Assign the file of root path to store and retrive.\r
+            string path = System.Reflection.Assembly.GetExecutingAssembly().Location;\r
+            int n = path.LastIndexOf(@"\");\r
+            if (0 > n)\r
+                return false;\r
+\r
+            path = path.Substring(0, n);\r
+\r
+            if (!NTFileAccess.init(path))\r
+                return false;\r
+\r
+            NTExportUtil.init(path);\r
+\r
+            NTAppState.init(this);\r
+\r
+            NTHtmlUtils.init();\r
+\r
+            NTHtmlParser.init();\r
+\r
+            NTUserPreference.init();\r
+\r
+            NTMaru.init();\r
+\r
+            NTResMenuCommand.init();\r
+\r
+            progressCtrlCloud.IsIndeterminate = NTUserPreference.NTCloudIsEnabled;\r
+\r
+            NTExportUtil util = new NTExportUtil();\r
+            util.MsgOpenThreadTitleListRequest += MsgOpenThreadtitleListRequest;\r
+            mSubjectPanel.OnInitApplicationInterface(util, util);\r
+            mResPanel.OnInitApplicationInterface(util, util);\r
+\r
+            mGraphicsPanel.Init();\r
+\r
+            mMoviePanel.Init();\r
+\r
+            return true;\r
+        }\r
+\r
+        \r
+        private void MainWindow_Loaded(object sender, RoutedEventArgs e)\r
+        {\r
+\r
+            mCategoryPanel.OpenBoardListRequest =\r
+                new DelegateMsgOpenBoardListRequest(MsgOpenBoardListRequest);\r
+            mCategoryPanel.OpenFavoriteListRequest =\r
+                new DelegateMsgOpenFavoriteListRequest(MsgOpenFavoriteListRequest);\r
+            mBoardPanel.OpenThreadTitleListRequest =\r
+                new DelegateMsgOpenThreadTitleListRequest(MsgOpenThreadtitleListRequest);\r
+            mFavoritePanel.OpenThreadTitleListRequest =\r
+                new DelegateMsgOpenThreadTitleListRequest2(MsgOpenThreadtitleListRequest2);\r
+            mHistoryPanel.OpenThreadRequest =\r
+                new DelegateMsgOpenThreadRequest(MsgOpenThreadRequest);\r
+            mHistoryPanel.GetHistoryOnCloud =\r
+                new DelegateMsgGetHistoryOnCloud(MsgGetHistoryOnCloud);\r
+\r
+\r
+            btnSaveNgEdit.IsEnabled = false;\r
+\r
+            btnStopAutoScroll.Visibility = System.Windows.Visibility.Collapsed;\r
+\r
+#if DOTNET45\r
+            if (NTUserPreference.ResViewTextSelMode)\r
+                btnTextTool.Visibility = System.Windows.Visibility.Collapsed;\r
+            else\r
+                btnTouchMode.Visibility = System.Windows.Visibility.Collapsed;\r
+#endif\r
+\r
+            mResPanel.initResLayout(NTUserPreference.DebugOption);\r
+\r
+            initData();\r
+\r
+        }\r
+\r
+       \r
+        private void MainWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)\r
+        {\r
+            mFavoritePanel.OnClosing();\r
+            mResPanel.SaveCurrentState();\r
+            //tabCtrlDat_AppClosing();\r
+\r
+            //storeOpenedThreadList();\r
+            \r
+            storeOpenedBoardList();\r
+\r
+            List<IThreadDescription> threadHistoryList = mResPanel.QueryThreadReadHistory();\r
+\r
+            if(threadHistoryList != null)\r
+            {\r
+                NTOpenedThreadTable.saveThreadHistoryList(threadHistoryList);\r
+            }\r
+\r
+\r
+            NTUserPreference.WindowWidth =  this.Width;\r
+            NTUserPreference.WindowHeight = this.Height;\r
+            NTUserPreference.WindowTop = this.Top;\r
+            NTUserPreference.WindowLeft = this.Left;\r
+\r
+            NTUserPreference.WindowColumn1 = mMainColumn1.Width.Value;\r
+            NTUserPreference.WindowRow1 = mMainRow1.Height.Value;\r
+            NTUserPreference.WindowLeftPanelRow1 = mLeftPanelRow1.Height.Value;\r
+\r
+\r
+\r
+            NTUserPreference.savePreferences();\r
+\r
+\r
+        }\r
+\r
+\r
+        private void initData()\r
+        {\r
+            BackgroundWorker bkWorkerInitBoardMenu =\r
+                new BackgroundWorker();\r
+\r
+            bkWorkerInitBoardMenu.DoWork += \r
+                new DoWorkEventHandler(InitBoardMenu_OnDoWork);\r
+            bkWorkerInitBoardMenu.RunWorkerCompleted += \r
+                new RunWorkerCompletedEventHandler(InitBoardMenu_OnRunWorkerCompleted); \r
+\r
+            bkWorkerInitBoardMenu.RunWorkerAsync();\r
+        }\r
+\r
+        private void completeData()\r
+        {\r
+            if (!NTUserPreference.NTCloudIsEnabled)\r
+            {\r
+                initThreadHistoryList();\r
+            }\r
+\r
+\r
+            MainWindowProgressBar.Width = 0;\r
+            MainWindowProgressBar.Height = 0;\r
+            MainWindowLblStatusBar.Content = " Ready ";\r
+\r
+            NTMaru.loginAsync();\r
+        }\r
+\r
+        private void InitBoardMenu(bool? result)\r
+        {\r
+            if(result == null || result == false)\r
+                NTDebug.l("ボードメニューの取得に失敗");\r
+\r
+            string html = NTFileAccess.retrieveBoardMenuDataFromFile();\r
+            if (null == html)\r
+            {\r
+                MessageBox.Show("ボードファイルが見つかりません。");\r
+                return;\r
+            }\r
+\r
+            List<NTCategory> cList = NTCategory.parseBoardMenu(html);\r
+\r
+            NTDataRoot.mCategoryList = cList;\r
+\r
+            mCategoryPanel.CategoryTable = cList;\r
+            //constructCategoryTreeView();\r
+            Thread thread = new Thread(getFavorites);\r
+            thread.Start();\r
+            thread = new Thread(getNgItems);\r
+            thread.Start();\r
+\r
+            MsgGetHistoryOnCloud(1);\r
+\r
+            //MainWindowProgressBar.Value = e.ProgressPercentage;\r
+            int progressValue = 10;\r
+            MainWindowProgressBar.Value = progressValue;\r
+\r
+            string[] boardlist = NTPersistentFileAccess.retrieveOpenedBoards();\r
+\r
+            int progressDelta;\r
+\r
+            if (boardlist != null && boardlist.Length > 0)\r
+            {\r
+\r
+                progressDelta = 40 / boardlist.Length;\r
+\r
+                List<IBoard> iboardList = new List<IBoard>();\r
+                foreach (string s in boardlist)\r
+                {\r
+                    NTBoard board = NTDataRoot.getBoardByName(s);\r
+                    if (board != null)\r
+                    {\r
+                        //mSubjectPanel.OpenBoard(board);\r
+                        iboardList.Add(board);\r
+                        //constructBoardTabItem(board);\r
+                    }\r
+                    progressValue += progressDelta;\r
+                    MainWindowProgressBar.Value = progressValue;\r
+                }\r
+                mSubjectPanel.InitBoardList(iboardList);\r
+                if (iboardList.Count > 0)\r
+                {\r
+                    //mSubjectPanel.OpenBoard(iboardList[iboardList.Count-1]);\r
+                    ((NTBoard)(iboardList[iboardList.Count - 1])).Update(mOnNotifyBoardUpdate);\r
+                }\r
+\r
+                /*int num = tabCtrlSubject.Items.Count;\r
+                if (0 < num)\r
+                {\r
+                    int idx = tabCtrlSubject.SelectedIndex;\r
+                    if (idx < 0)\r
+                        idx = num - 1;\r
+\r
+                    TabItem item = tabCtrlSubject.Items[idx] as TabItem;\r
+                    if (item != null)\r
+                    {\r
+                        NTBoard board = item.Tag as NTBoard;\r
+                        if (board != null)\r
+                        {\r
+                            tabCtrlSubject.SelectedIndex = idx;\r
+                            board.Update(mOnNotifyBoardUpdate);\r
+                        }\r
+                    }\r
+                }*/\r
+            }\r
+\r
+            /*string[] threadList = NTPersistentFileAccess.retrieveOpenedThreads();\r
+            if (threadList != null && threadList.Length > 0)\r
+            {\r
+              foreach (string s in threadList)\r
+              {\r
+                    //Thread.Sleep(100);\r
+                    string[] words = s.Split(NTTextUtiles.COMMA_VALUE);\r
+                    if (words.Length != 2)\r
+                        continue;\r
+                    string boardName = words[1];\r
+\r
+                    if (mDicBoardUpdateRequest.ContainsKey(boardName))\r
+                        continue;\r
+\r
+                    NTBoard board = NTDataRoot.getBoardByName(boardName);\r
+                    if (board == null)\r
+                        continue;\r
+\r
+                    mDicBoardUpdateRequest.Add(boardName, board);\r
+              }\r
+            }*/\r
+\r
+            /*foreach(NTBoard board in mDicBoardUpdateRequest.Values)\r
+            {\r
+                board.Update(new NTBoard.DelegateMsgOnNotifyBoardUpdate(onNotifyBoardUpdateForFavoriteThread));\r
+            }\r
+\r
+            if (mDicBoardUpdateRequest.Count > 0)\r
+            {\r
+                //mProgressValue = 50;\r
+                //mProgressDelta = 50 / mDicBoardUpdateRequest.Count;\r
+            }\r
+            else*/\r
+            completeData();\r
+        }\r
+\r
+        private void onNotifyBoardUpdateA(NTBoard board)\r
+        {\r
+            mSubjectPanel.OpenBoard((IBoard)board);\r
+        }\r
+        private void onNotifyBoardUpdateB(NTBoard board)\r
+        {\r
+            mDicBoardUpdateRequest.Remove(board.mName);\r
+            mResPanel.OnNotifyThreadUpdated((IBoard)board);\r
+        }\r
+#if false\r
+        private void onNotifyBoardUpdateForFavoriteThread(NTBoard board)\r
+        {\r
+            \r
+\r
+            /*string[] threadList = NTPersistentFileAccess.retrieveOpenedThreads();\r
+            if (threadList != null && threadList.Length > 0)\r
+            {\r
+                foreach (string s in threadList)\r
+                {\r
+                    string[] words = s.Split(NTTextUtiles.COMMA_VALUE);\r
+                    if (words.Length != 2)\r
+                        continue;\r
+                    string boardName = words[1];\r
+                    if (!boardName.Equals(board.mName))\r
+                        continue;\r
+                    string datName = words[0];\r
+\r
+                    NTThreadTitle tt = board.findThreadTitleByDatName(datName);\r
+                    //if (tt != null)\r
+                    //    constructResViewTabItem(tt);\r
+                    mProgressValue += mProgressDelta;\r
+                    MainWindowProgressBar.Value = mProgressValue;\r
+                }\r
+            }\r
+            mDicBoardUpdateRequest.Remove(board.mName);\r
+            if (mDicBoardUpdateRequest.Count == 0)\r
+            {\r
+                completeData();\r
+            }*/\r
+        }\r
+#endif\r
+\r
+#if false \r
+        private void backgroundWorker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)\r
+        {\r
+\r
+            if (!NTHttpAccess.getBoardMenu())\r
+            {\r
+                NTDebug.l("ボードメニューの取得に失敗");\r
+            }\r
+            \r
+            string html = NTFileAccess.retrieveBoardMenuDataFromFile();\r
+            if (null == html)\r
+            {\r
+                this.Dispatcher.BeginInvoke(DispatcherPriority.Normal,\r
+                (ThreadStart)delegate()\r
+                {\r
+                    MessageBox.Show("ボードファイルが見つかりません。");\r
+                    \r
+                });\r
+                return;\r
+            }\r
+\r
+            List<NTCategory> cList = NTCategory.parseBoardMenu(html);\r
+\r
+            NTDataRoot.mCategoryList = cList;\r
+\r
+           // string[] externalBoards = NTFileAccess.retrieveExternalBoards();\r
+           // if (null != externalBoards && externalBoards.Length > 0)\r
+           //     NTCategory.parseExternalBoardMenu(externalBoards);\r
+\r
+            this.Dispatcher.BeginInvoke(DispatcherPriority.Normal,\r
+                (ThreadStart)delegate()\r
+            {\r
+                mCategoryPanel.CategoryTable = cList;\r
+                constructCategoryTreeView();\r
+                Thread thread = new Thread(getFavorites);\r
+                thread.Start();\r
+                thread = new Thread(getNgItems);\r
+                thread.Start();\r
+           });\r
+           \r
+           int progressValue = 10;\r
+\r
+            mBackgroundWorker.ReportProgress(progressValue);\r
+\r
+            Thread.Sleep(500);\r
+\r
+            \r
+            string[] boardlist = NTPersistentFileAccess.retrieveOpenedBoards();\r
+\r
+            int progressOffset;\r
+\r
+            if (boardlist != null && boardlist.Length > 0)\r
+            {\r
+                       \r
+                progressOffset = 40 / boardlist.Length;\r
+\r
+                foreach (string s in boardlist)\r
+                {\r
+                    NTBoard board = NTDataRoot.getBoardByName(s);\r
+                    if (board != null)\r
+                    {\r
+                        this.Dispatcher.BeginInvoke(DispatcherPriority.Normal,\r
+                                                    (ThreadStart)delegate()\r
+                        {\r
+                            constructBoardTabItem(board /*, false*/);\r
+                            //TabItem item = null;\r
+                           // constructBoardTabItemContent(board, item);\r
+                        });\r
+                       // Thread.Sleep(1000);\r
+                    }\r
+                    progressValue += progressOffset;\r
+                    mBackgroundWorker.ReportProgress(progressValue);\r
+                }\r
+\r
+                this.Dispatcher.BeginInvoke(DispatcherPriority.Normal,\r
+                                                    (ThreadStart)delegate()\r
+                {\r
+\r
+                    int num = tabCtrlSubject.Items.Count;\r
+                    if (0 < num)\r
+                    {\r
+                        TabItem item = tabCtrlSubject.Items[num - 1] as TabItem;\r
+                        if (item != null)\r
+                        {\r
+                            NTBoard board = item.Tag as NTBoard;\r
+                            if (board != null)\r
+                            {\r
+                                tabCtrlSubject.SelectedIndex = num - 1;\r
+                                constructBoardTabItemContent(board, item);\r
+                            }\r
+                        }\r
+                    }\r
+                });\r
+\r
+                        \r
+           }\r
+\r
+            /*this.Dispatcher.BeginInvoke(DispatcherPriority.Normal,\r
+            (ThreadStart)delegate()\r
+            {\r
+                Thread.Sleep(100);\r
+            });*/\r
+\r
+            //Thread.Sleep(2000);\r
+\r
+            progressValue = 50;\r
+\r
+            string[] threadList = NTPersistentFileAccess.retrieveOpenedThreads();\r
+            if (threadList != null && threadList.Length > 0)\r
+            {\r
+                progressOffset = 50 / threadList.Length;\r
+                 //this.Dispatcher.BeginInvoke(DispatcherPriority.Normal,\r
+                 //                               (ThreadStart)delegate()\r
+                 //                           {\r
+                \r
+                    foreach (string s in threadList)\r
+                    {\r
+                        //Thread.Sleep(100);\r
+                        string[] words = s.Split(NTTextUtiles.COMMA_VALUE);\r
+                        if (words.Length != 2)\r
+                            continue;\r
+\r
+                        NTBoard board = NTDataRoot.getBoardByName(words[1]);\r
+                        if (board == null)\r
+                            continue;\r
+\r
+                        string strSubject= null;\r
+                        if (!board.mDataInit)\r
+                        {\r
+                            NTHttpAccess.getSubject(board.mAddress, board.mName);\r
+                            strSubject = NTFileAccess.retrieveSubjectDataFromFile(board.mName);\r
+                        }\r
+                        \r
+                        //if(strSubject == null)\r
+                        //    continue;\r
+\r
+                        //bool bRet = false;\r
+                         \r
+                        this.Dispatcher.BeginInvoke(DispatcherPriority.Normal,\r
+                                                (ThreadStart)delegate()\r
+                        {\r
+                            if (strSubject != null)\r
+                            {\r
+                                if (!board.parseSubjectData(strSubject))\r
+                                    return;\r
+                            }\r
+                            \r
+\r
+                            NTThreadTitle tt = board.findThreadTitleByDatName(words[0]);\r
+                            if (tt != null)\r
+                                constructResViewTabItem(tt/*, false*/);\r
+                        });\r
+                       \r
+                        progressValue += progressOffset;\r
+                        mBackgroundWorker.ReportProgress(progressValue);\r
+                        //Thread.Sleep(1000);\r
+\r
+\r
+                    }\r
+                this.Dispatcher.BeginInvoke(DispatcherPriority.Normal,\r
+                                         (ThreadStart)delegate()\r
+                {\r
+                    int num = tabCtrlDat.Items.Count;\r
+                    if (num > 0)\r
+                    {\r
+                        TabItem tabItem = tabCtrlDat.Items[num - 1] as TabItem;\r
+                        if (tabItem != null)\r
+                        {\r
+                            \r
+                            tabCtrlDat.SelectedIndex = num - 1;\r
+                            constructResContent(tabItem);\r
+                           // tabCtrlDat.Items.CurrentChanging += Items_CurrentChanging;\r
+                           // tabCtrlDat.SelectionChanged += tabCtrlDat_SelectionChanged;\r
+                        }\r
+                    }\r
+                });\r
+\r
+           }\r
+           mBackgroundWorker.ReportProgress(100);\r
+        }\r
+\r
+        //void Items_CurrentChanging(object sender, CurrentChangingEventArgs e)\r
+       // {\r
+        //    NTDebug.l(sender.ToString());\r
+            //throw new NotImplementedException();\r
+       // }\r
+  \r
+        \r
+        \r
+\r
+        private void backgroundWorker_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e)\r
+        {\r
+            MainWindowProgressBar.Value = e.ProgressPercentage;\r
+        }\r
+\r
+        private void backgroundWorker_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)\r
+        {\r
+            MainWindowProgressBar.Width = 0;\r
+            MainWindowProgressBar.Height = 0;\r
+            MainWindowLblStatusBar.Content = " Ready ";\r
+\r
+            NTMaru.loginAsync();\r
+            \r
+        }\r
+#endif\r
+        private void initThreadHistoryList()\r
+        {\r
+            List<IThreadDescription> threadHistoryList = NTOpenedThreadTable.retrieveThreadHistoryList();\r
+            if (threadHistoryList == null)\r
+                threadHistoryList = new List<IThreadDescription>();\r
+            foreach (IThreadDescription threadDecl in threadHistoryList)\r
+            {\r
+                NTBoard board = threadDecl.getBoard() as NTBoard;\r
+                if (board == null)\r
+                    continue;\r
+\r
+                 if (threadDecl.getTitle() == null)\r
+                {\r
+                    if (!NTUserPreference.NTCloudIsEnabled)\r
+                    {\r
+\r
+                        string strSubject = null;\r
+                        if (!board.mDataInit)\r
+                        {\r
+                            if (!NTFileAccess.isSubjectExsists(board.mName))\r
+                                if (!NTHttpAccess.getSubject(board.mAddress, board.mName))\r
+                                    continue;\r
+\r
+                            strSubject = NTFileAccess.retrieveSubjectDataFromFile(board.mName);\r
+                            if (strSubject == null)\r
+                                continue;\r
+\r
+                            if (!board.parseSubjectData(strSubject, mFavoriteData))\r
+                                continue;\r
+                        }\r
+                        NTThreadTitle tt = board.findThreadTitleByDatName(threadDecl.getDatName());\r
+                        string title = null;\r
+                        if (tt != null && (null != (title = tt.getTitle())))\r
+                        {\r
+                            NTThreadCashData data = threadDecl as NTThreadCashData;\r
+                            if (data != null)\r
+                                data.setTitle(title);\r
+                        }\r
+                    }\r
+                    else\r
+                    {\r
+                        if (!mDicBoardUpdateRequest.ContainsKey(board.mName))\r
+                        {\r
+                            mDicBoardUpdateRequest.Add(board.mName, board);\r
+                        }\r
+                    }\r
+                }\r
+            }\r
+            if (NTUserPreference.NTCloudIsEnabled)\r
+            {\r
+                foreach (NTBoard board in mDicBoardUpdateRequest.Values)\r
+                {\r
+                   board.Update(mOnNotifyBoardUpdateB);\r
+                }\r
+            }\r
+            mResPanel.SetThreadReadHistory(threadHistoryList);\r
+       }\r
+\r
+        \r
+\r
+        private void getFavorites()\r
+        {\r
+\r
+            //bool initHistory = false;\r
+            string boardList;// = string.Empty;\r
+            string [] threadLists;// = string.Empty;\r
+            if (NTUserPreference.NTCloudIsEnabled)\r
+            {\r
+                NTHttpAccess.getFavoriteBoards();\r
+                NTHttpAccess.getFavoriteThreads();\r
+                NTHttpAccess.getExternalBoards();\r
+                //initHistory =\r
+                NTHttpAccess.getThreadHistoryList();\r
+            }\r
+\r
+            boardList = NTFileAccess.retrieveFavoriteBoardFromFile();\r
+            threadLists = NTFileAccess.retrieveFavoriteThreadFromFile();\r
+\r
+            string[] externalBoards = NTFileAccess.retrieveExternalBoards();\r
+\r
+\r
+            this.Dispatcher.BeginInvoke(DispatcherPriority.Normal,\r
+                (ThreadStart)delegate()\r
+                {\r
+                    if (boardList.Length > 0 || threadLists[0].Length > 0 || null != externalBoards)\r
+                    {\r
+                        NTFavorite favorite = new NTFavorite();\r
+                        if (boardList.Length > 0)\r
+                            favorite.parseBoardList(boardList);\r
+                        //if (threadLists[0].Length > 0)\r
+                        favorite.parseThreadList(threadLists);\r
+                        mFavoritePanel.FavoriteData = favorite;\r
+                        mFavoriteData = favorite;\r
+\r
+                        //constructFavoriteList(boardList, threadList);\r
+\r
+                        if (null != externalBoards && externalBoards.Length > 0)\r
+                        {\r
+                            NTCategory.parseExternalBoardMenu(externalBoards);\r
+                            NTCategory exCate = NTDataRoot.getExternalBoards();\r
+                            if (exCate != null)\r
+                                mCategoryPanel.addExternalCategory(exCate);\r
+                            //constructExternalBoardToCategoryTree();\r
+                            //NTBoard board = NTDataRoot.getExternalBoards\r
+                            //appendBoardToExternalCategoryTree(NTBoard board);\r
+                        }\r
+                    }\r
+                    else\r
+                    {\r
+                        NTFavorite favorite = new NTFavorite();\r
+                        favorite.parseThreadList(threadLists);\r
+                        mFavoritePanel.FavoriteData = favorite;\r
+                        mFavoriteData = favorite;\r
+\r
+\r
+                    }\r
+\r
+                    //if (initHistory)\r
+                    if (NTUserPreference.NTCloudIsEnabled)\r
+                    {\r
+                        initThreadHistoryList();\r
+                    }\r
+                });\r
+        }\r
+\r
+        private void getReadHistoryOnCloud()\r
+        {\r
+            if (NTUserPreference.NTCloudIsEnabled)\r
+            {\r
+                string uid, pass, result;\r
+                if (NTUserPreference.NTUserCloudIsEnabled)\r
+                {\r
+                    uid = NTUserPreference.NTCloudID;\r
+                    pass = NTUserPreference.NTUserCloudGetHashedPasswd();\r
+                    result = NTHttpAccess.UserCloudQueryReadHistory(uid, pass);\r
+                }\r
+                else\r
+                {\r
+                    uid = NTUserPreference.NTCloudID;\r
+                    pass = NTUserPreference.NTCloudPSS;\r
+                    result = NTHttpAccess.ntQueryReadHistory(uid, pass);\r
+                }\r
+                if (result != null)\r
+                {\r
+                    this.Dispatcher.BeginInvoke(DispatcherPriority.Normal,\r
+                        (ThreadStart)delegate()\r
+                        {\r
+                            NTDebug.l(result);\r
+                            NTHistory history = new NTHistory();\r
+                            if (history.parse(result))\r
+                            {\r
+                                mHistoryPanel.History = history;\r
+                            }\r
+                        });\r
+                }\r
+            }\r
+        }\r
+\r
+        private void getWriteHistoryOnCloud()\r
+        {\r
+            if (NTUserPreference.NTCloudIsEnabled)\r
+            {\r
+                string uid, pass, result;\r
+                if (NTUserPreference.NTUserCloudIsEnabled)\r
+                {\r
+                    uid = NTUserPreference.NTCloudID;\r
+                    pass = NTUserPreference.NTUserCloudGetHashedPasswd();\r
+                    result = NTHttpAccess.UserCloudQueryWriteHistory(uid, pass);\r
+                }\r
+                else\r
+                {\r
+                    uid = NTUserPreference.NTCloudID;\r
+                    pass = NTUserPreference.NTCloudPSS;\r
+                    result = NTHttpAccess.ntQueryWriteHistory(uid, pass);\r
+                }\r
+                if (result != null)\r
+                {\r
+                    this.Dispatcher.BeginInvoke(DispatcherPriority.Normal,\r
+                        (ThreadStart)delegate()\r
+                        {\r
+                            NTDebug.l(result);\r
+                            NTHistory history = new NTHistory();\r
+                            if (history.parse(result))\r
+                            {\r
+                                mHistoryPanel.History = history;\r
+                            }\r
+                        });\r
+                }\r
+            }\r
+        }\r
+\r
+        private void getBookmarkHistoryOnCloud()\r
+        {\r
+            if (NTUserPreference.NTCloudIsEnabled)\r
+            {\r
+                string uid, pass, result;\r
+                if (NTUserPreference.NTUserCloudIsEnabled)\r
+                {\r
+                    uid = NTUserPreference.NTCloudID;\r
+                    pass = NTUserPreference.NTUserCloudGetHashedPasswd();\r
+                    result = NTHttpAccess.UserCloudQueryBookmarkHistory(uid, pass);\r
+                }\r
+                else\r
+                {\r
+                    uid = NTUserPreference.NTCloudID;\r
+                    pass = NTUserPreference.NTCloudPSS;\r
+                    result = NTHttpAccess.ntQueryBookmarkHistory(uid, pass);\r
+                }\r
+                if (result != null)\r
+                {\r
+                    this.Dispatcher.BeginInvoke(DispatcherPriority.Normal,\r
+                        (ThreadStart)delegate()\r
+                        {\r
+                            NTDebug.l(result);\r
+                            NTHistory history = new NTHistory();\r
+                            if (history.parse(result))\r
+                            {\r
+                                mHistoryPanel.History = history;\r
+                            }\r
+                        });\r
+                }\r
+            }\r
+        }\r
+\r
+        private void getNgItems()\r
+        {\r
+\r
+           // string boardList = string.Empty;\r
+            //string threadList = string.Empty;\r
+            if (NTUserPreference.NTCloudIsEnabled)\r
+            {\r
+                if (NTUserPreference.NTUserCloudIsEnabled)\r
+                {\r
+                    NTHttpAccess.UserCloudGetNgId();\r
+                    NTHttpAccess.UserCloudGetNgName();\r
+                    NTHttpAccess.UserCloudGetNgWord();\r
+                }\r
+                else\r
+                {\r
+                    NTHttpAccess.ntGetNgId();\r
+                    NTHttpAccess.ntGetNgName();\r
+                    NTHttpAccess.ntGetNgWord();\r
+                }\r
+            }\r
+\r
+            NTNgItems ngItem = NTNgItems.getContext();\r
+            string source = NTFileAccess.retrieveNgWordFromFile();\r
+            if (source != null && source.Length > 0)\r
+            {\r
+                string[] lines = NTTextUtiles.splitLine(source);\r
+                for (int i = 0; i < lines.Length; i++)\r
+                {\r
+                    string line;\r
+                    if(NTUserPreference.AESEnabled)\r
+                        line = NTTextUtiles.aesDecodeBase64URL(lines[i]);\r
+                    else\r
+                        line = NTTextUtiles.decodeBase64URL(lines[i]);\r
+                    lines[i] = line;\r
+                }\r
+                ngItem.WriteNgWord(lines);\r
+            }\r
+\r
+            source = NTFileAccess.retrieveNgIdFromFile();\r
+            if (source != null && source.Length > 0)\r
+            {\r
+                string [] lines = NTTextUtiles.splitLine(source);\r
+                for (int i = 0; i < lines.Length; i++)\r
+                {\r
+                    string line;\r
+                    if (NTUserPreference.AESEnabled)\r
+                        line = NTTextUtiles.aesDecodeBase64URL(lines[i]);\r
+                    else\r
+                        line = NTTextUtiles.decodeBase64URL(lines[i]);\r
+                    lines[i] = line;\r
+                }\r
+                ngItem.WriteNgId(lines);\r
+            }\r
+\r
+            source = NTFileAccess.retrieveNgNameFromFile();\r
+            if (source != null && source.Length > 0)\r
+            {\r
+                string [] lines = NTTextUtiles.splitLine(source);\r
+                for (int i = 0; i < lines.Length; i++)\r
+                {\r
+                    string line;\r
+                    if (NTUserPreference.AESEnabled)\r
+                        line = NTTextUtiles.aesDecodeBase64URL(lines[i]);\r
+                    else\r
+                        line = NTTextUtiles.decodeBase64URL(lines[i]);\r
+                    lines[i] = line;\r
+                }\r
+                ngItem.WriteNgName(lines);\r
+            }\r
+\r
+        }\r
+\r
+        private void MainWindow_PreviewKeyDown(object sender, KeyEventArgs e)\r
+        {\r
+            if (e.Key == Key.F11)\r
+            {\r
+                if (this.WindowState == System.Windows.WindowState.Maximized)\r
+                    RestoreMainWindow();\r
+                else\r
+                    MaximizeMainWindow();\r
+\r
+            }\r
+        }\r
+\r
+        private void RestoreMainWindow()\r
+        {\r
+            NTUserPreference.WindowMaximized = false;\r
+            this.WindowStyle = System.Windows.WindowStyle.ThreeDBorderWindow;\r
+            this.WindowState = System.Windows.WindowState.Normal;\r
+            this.btnMaximizeWindow.Visibility = System.Windows.Visibility.Visible;\r
+            this.btnRestoreWindow.Visibility = System.Windows.Visibility.Collapsed;\r
+        }\r
+        private void MaximizeMainWindow()\r
+        {\r
+            NTUserPreference.WindowMaximized = true;\r
+            this.WindowStyle = System.Windows.WindowStyle.None;\r
+            this.WindowState = System.Windows.WindowState.Maximized;\r
+            this.btnMaximizeWindow.Visibility = System.Windows.Visibility.Collapsed;\r
+            this.btnRestoreWindow.Visibility = System.Windows.Visibility.Visible;\r
+        }\r
+    }\r
+}\r
diff --git a/NT2chView45/MainWindow_backgroudworker.cs b/NT2chView45/MainWindow_backgroudworker.cs
new file mode 100755 (executable)
index 0000000..ea557d6
--- /dev/null
@@ -0,0 +1,53 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.ComponentModel;\r
+using System.Text;\r
+using NT2chView.NtNet;\r
+\r
+namespace NT2chView\r
+{\r
+    partial class MainWindow\r
+    {\r
+        //class BackgroudWorkerInitBoardMenu : BackgroundWorker\r
+        //{\r
+            //MainWindow mMainWnd;\r
+           // public BackgroudWorkerInitBoardMenu(MainWindow wnd)\r
+           // {\r
+           //     mMainWnd = wnd;\r
+          //  }\r
+        private void InitBoardMenu_OnDoWork(object sender, DoWorkEventArgs e)\r
+            {\r
+                bool result = NTHttpAccess.getBoardMenu();\r
+                e.Result = result;\r
+            }\r
+           // private void OnProgressChanged(System.ComponentModel.ProgressChangedEventArgs e)\r
+           // {\r
+           // }\r
+            private void InitBoardMenu_OnRunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)\r
+            {\r
+                bool? result = e.Result as bool?;\r
+                InitBoardMenu(result);\r
+            }\r
+     //   }\r
+\r
+        /*\r
+        class BackgroudWorkerTemplate : BackgroundWorker\r
+        {\r
+            MainWindow mMainWnd;\r
+            BackgroudWorkerTemplate(MainWindow wnd)\r
+            {\r
+                mMainWnd = wnd;\r
+            }\r
+            private void OnDoWork(DoWorkEventArgs e)\r
+            {\r
+            }\r
+            private void OnProgressChanged(System.ComponentModel.ProgressChangedEventArgs e)\r
+            {\r
+            }\r
+            private void OnRunWorkerCompleted(System.ComponentModel.RunWorkerCompletedEventArgs e)\r
+            {\r
+            }\r
+        }\r
+         */\r
+    }\r
+}\r
diff --git a/NT2chView45/MainWindow_ctrl_event_handler.cs b/NT2chView45/MainWindow_ctrl_event_handler.cs
new file mode 100755 (executable)
index 0000000..6d5dcad
--- /dev/null
@@ -0,0 +1,1050 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Windows;\r
+using System.Windows.Controls;\r
+using System.Windows.Documents;\r
+using System.Windows.Input;\r
+using System.Windows.Threading;\r
+using NT2chCtrl;\r
+using NT2chView.NtFile;\r
+using NT2chView.NtNet;\r
+using NT2chObject;\r
+\r
+namespace NT2chView\r
+{\r
+    public partial class MainWindow : Window\r
+    {\r
+        private void btnJumpToBottom_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            IResViewJump jump = mResPanel as IResViewJump;\r
+            jump.JumpToBottom();\r
+        }\r
+\r
+        private void btnJumpToTop_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            IResViewJump jump = mResPanel as IResViewJump;\r
+            jump.JumpToTop();\r
+        }\r
+\r
+\r
+        private void btnJumpToNew_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            IResViewJump jump = mResPanel as IResViewJump;\r
+            jump.JumpToNew();\r
+        }\r
+\r
+        private void btnJumpNextBookmark_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            IResViewJump jump = mResPanel as IResViewJump;\r
+            jump.JumpToNextBookmark();\r
+        }\r
+\r
+\r
+        private void btnCreateThread_Click(object sender, RoutedEventArgs e)\r
+        {\r
+           // string errMsg = null;\r
+            NTBoard board = mSubjectPanel.GetCurrentBoard() as NTBoard;\r
+            if (board == null)\r
+            {\r
+                MessageBox.Show("板が見つかりません。");\r
+                return;\r
+            }\r
+            /*try\r
+            {\r
+                TabItem item = tabCtrlSubject.SelectedItem as TabItem;\r
+                if (item == null)\r
+                    throw new Exception("板が見つかりません。");\r
+\r
+                board = item.Tag as NTBoard;\r
+            if (board == null)\r
+                throw new Exception("板が見つかりません。");\r
+\r
+\r
+\r
+            }\r
+            catch(Exception ex)\r
+            {\r
+                MessageBox.Show(ex.Message);\r
+                return;\r
+            }*/\r
+            NTCreateThreadWindow wnd = new NTCreateThreadWindow(board, null);\r
+            wnd.ShowDialog();\r
+        }\r
+\r
+        private void btnThreadTitleSearch_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            tabItemSearch.IsSelected = true;\r
+            Thread th = new Thread(btnThreadTitleSearch_Worker);\r
+            th.Start(this);\r
+\r
+        }\r
+\r
+        static void btnThreadTitleSearch_Worker(object o)\r
+        {\r
+            MainWindow wnd = o as MainWindow;\r
+            if (wnd == null)\r
+                return;\r
+\r
+            wnd.Dispatcher.BeginInvoke(DispatcherPriority.Normal,\r
+                    (ThreadStart)delegate()\r
+            {\r
+                Thread.Sleep(500);\r
+                wnd.txtTitleSearch.Focus();\r
+  \r
+            });\r
+        }\r
+\r
+\r
+        private void btnResSearch_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            tabItemSearch.IsSelected = true;\r
+            txtMsgSearch.Focus();\r
+        }\r
+        private void btnMsgSearchNext_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            string sWord = txtMsgSearch.Text.Trim();\r
+            if (sWord.Length == 0)\r
+                return;\r
+\r
+            IResViewSearch search = mResPanel as IResViewSearch;\r
+            if (search == null)\r
+                return;\r
+\r
+            search.SetSearchWord(sWord);\r
+            search.SearchNext();\r
+\r
+        }\r
+        private void btnMsgSearchPrev_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            string sWord = txtMsgSearch.Text.Trim();\r
+            if (sWord.Length == 0)\r
+                return;\r
+\r
+            IResViewSearch search = mResPanel as IResViewSearch;\r
+            if (search == null)\r
+                return;\r
+\r
+            search.SetSearchWord(sWord);\r
+            search.SearchPrev();\r
+\r
+        }\r
+        \r
+#if false      \r
+        private void btnJmpNextBookmark_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            mResPanel.JumpToNextBookmark();\r
+            /*\r
+            TabItem ti = tabCtrlDat.SelectedItem as TabItem;\r
+            if (ti == null)\r
+                return;\r
+\r
+            NTThreadTitle tt = ti.Tag as NTThreadTitle;\r
+            if (tt == null)\r
+                return;\r
+\r
+            tt.FocusNextBookmark();*/\r
+        }\r
+#endif\r
+        private void btnAddNgName_Click(object sender, RoutedEventArgs e)\r
+        {\r
+\r
+            cmbNgEditKind.SelectedIndex = 1;\r
+\r
+            string src = txtNgNameEdit.Text;\r
+            NTNgItems ng = NTNgItems.getContext();\r
+            if(!ng.addNgName(src))\r
+                return;\r
+\r
+            List<string> list = new List<string>();\r
+            list.Add(src);\r
+            Thread th = new Thread(uploadNgNames);\r
+            th.Start(list);\r
+\r
+            string dest = txtNgEdit.Text;\r
+            string [] dests = NTTextUtiles.splitLine(dest);\r
+            StringBuilder sb = new StringBuilder(64);\r
+            foreach(string s in dests)\r
+            {\r
+                if(s.Length > 0)\r
+                    sb.Append(s).Append('\n');\r
+            }\r
+            sb.Append(src).Append('\n');\r
+            txtNgEdit.Text = sb.ToString();\r
+            txtNgNameEdit.Text = string.Empty;\r
+\r
+            NTFileAccess.ntWriteNgNamesToFile(ng.getNgNames());\r
+        }\r
+\r
+        private void btnAddNgId_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            cmbNgEditKind.SelectedIndex = 2;\r
+            \r
+            string src = txtNgIdEdit.Text;\r
+            NTNgItems ng = NTNgItems.getContext();\r
+            if(!ng.addNgId(src))\r
+                return;\r
+\r
+            List<string> list = new List<string>();\r
+            list.Add(src);\r
+            Thread th = new Thread(uploadNgIds);\r
+            th.Start(list);\r
+\r
+\r
+            string dest = txtNgEdit.Text;\r
+            string[] dests = NTTextUtiles.splitLine(dest);\r
+            StringBuilder sb = new StringBuilder(64);\r
+            foreach (string s in dests)\r
+            {\r
+                if (s.Length > 0)\r
+                    sb.Append(s).Append('\n');\r
+            }\r
+            sb.Append(src).Append('\n');\r
+            txtNgEdit.Text = sb.ToString();\r
+            txtNgIdEdit.Text = string.Empty;\r
+\r
+            NTFileAccess.ntWriteNgIdsToFile(ng.getNgIds());\r
+\r
+        }\r
+\r
+        private void btnAddNgWord_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            cmbNgEditKind.SelectedIndex = 0;\r
+\r
+            string src = txtNgWordEdit.Text;\r
+            List<string> list = new List<string>();\r
+\r
+            NTNgItems ng = NTNgItems.getContext();\r
+            string[] lines = NTTextUtiles.splitLine(src);\r
+            foreach (string s in lines)\r
+            {\r
+                string s1 = s.Trim();\r
+                if(s1.Length>0)\r
+                    if (ng.addNgWord(s1))\r
+                        list.Add(s1);\r
+            }\r
+            if (list.Count == 0)\r
+                return;\r
+\r
+            Thread th = new Thread(uploadNgWords);\r
+            th.Start(list);\r
+\r
+            NTFileAccess.ntWriteNgWordsToFile(ng.getNgWords());\r
+\r
+            \r
+            string dest = txtNgEdit.Text;\r
+            string[] dests = NTTextUtiles.splitLine(dest);\r
+            StringBuilder sb = new StringBuilder(64);\r
+            foreach (string s in dests)\r
+            {\r
+                if (s.Length > 0)\r
+                    sb.Append(s).Append('\n');\r
+            }\r
+            foreach (string s in list)\r
+            {\r
+                sb.Append(s).Append('\n');\r
+            }\r
+            txtNgEdit.Text = sb.ToString();\r
+            txtNgWordEdit.Text = string.Empty;\r
+        }\r
+\r
+        void uploadNgWords(object para)\r
+        {\r
+            List<string> list = para as List<string>;\r
+            if (list == null)\r
+                return;\r
+            string result;\r
+            if (NTUserPreference.NTUserCloudIsEnabled)\r
+            {\r
+                string uid = NTUserPreference.NTCloudID;\r
+                string hashed = NTUserPreference.NTUserCloudGetHashedPasswd();\r
+                    //NTCrypt.getSHA256Hashed(\r
+                    //NTUserPreference.NTCloudPSS + NTUserPreference.NTUserCloudSeed);\r
+                result = NTHttpAccess.UserCloudUploadNgWord(uid, hashed, list, true);\r
+\r
+            }\r
+            else\r
+            {\r
+                string uid = NTUserPreference.NTCloudID;\r
+                string passwd = NTUserPreference.NTCloudPSS;\r
+                result = NTHttpAccess.ntUploadNgWord(uid, passwd, list, true);\r
+            }\r
+            NTDebug.l(result);\r
+        }\r
+\r
+        void uploadNgIds(object para)\r
+        {\r
+            List<string> list = para as List<string>;\r
+            if (list == null)\r
+                return;\r
+            string result;\r
+            if (NTUserPreference.NTUserCloudIsEnabled)\r
+            {\r
+                string uid = NTUserPreference.NTCloudID;\r
+                string hashed = NTUserPreference.NTUserCloudGetHashedPasswd(); \r
+                //NTCrypt.getSHA256Hashed(\r
+                //    NTUserPreference.NTCloudPSS + NTUserPreference.NTUserCloudSeed);\r
+                result = NTHttpAccess.UserCloudUploadNgId(uid, hashed, list, true);\r
+\r
+            }\r
+            else\r
+            {\r
+                string uid = NTUserPreference.NTCloudID;\r
+                string passwd = NTUserPreference.NTCloudPSS;\r
+                result = NTHttpAccess.ntUploadNgId(uid, passwd, list, true);\r
+            }\r
+            NTDebug.l(result);\r
+        }\r
+\r
+        void uploadNgNames(object para)\r
+        {\r
+            List<string> list = para as List<string>;\r
+            if (list == null)\r
+                return;\r
+            string result;\r
+            if (NTUserPreference.NTUserCloudIsEnabled)\r
+            {\r
+                string uid = NTUserPreference.NTCloudID;\r
+                string hashed = NTUserPreference.NTUserCloudGetHashedPasswd(); \r
+                //NTCrypt.getSHA256Hashed(\r
+                 //   NTUserPreference.NTCloudPSS + NTUserPreference.NTUserCloudSeed);\r
+                result = NTHttpAccess.UserCloudUploadNgName(uid, hashed, list, true);\r
+\r
+            }\r
+            else\r
+            {\r
+                string uid = NTUserPreference.NTCloudID;\r
+                string passwd = NTUserPreference.NTCloudPSS;\r
+                result = NTHttpAccess.ntUploadNgName(uid, passwd, list, true);\r
+            }\r
+            NTDebug.l(result);\r
+        }\r
+\r
+        void uploadAllNgWords(object para)\r
+        {\r
+            List<string> list = para as List<string>;\r
+            if (list == null)\r
+                return;\r
+            string result;\r
+            if (NTUserPreference.NTUserCloudIsEnabled)\r
+            {\r
+                string uid = NTUserPreference.NTCloudID;\r
+                string hashed = NTUserPreference.NTUserCloudGetHashedPasswd(); \r
+                //NTCrypt.getSHA256Hashed(\r
+                  //  NTUserPreference.NTCloudPSS + NTUserPreference.NTUserCloudSeed);\r
+                result = NTHttpAccess.UserCloudUploadNgWord(uid, hashed, list, false);\r
+\r
+            }\r
+            else\r
+            {\r
+                string uid = NTUserPreference.NTCloudID;\r
+                string passwd = NTUserPreference.NTCloudPSS;\r
+                result = NTHttpAccess.ntUploadNgWord(uid, passwd, list, false);\r
+            }\r
+            NTDebug.l(result);\r
+        }\r
+\r
+        void uploadAllNgIds(object para)\r
+        {\r
+            List<string> list = para as List<string>;\r
+            if (list == null)\r
+                return;\r
+            string result;\r
+            if (NTUserPreference.NTUserCloudIsEnabled)\r
+            {\r
+                string uid = NTUserPreference.NTCloudID;\r
+                string hashed = NTUserPreference.NTUserCloudGetHashedPasswd(); \r
+                //NTCrypt.getSHA256Hashed(\r
+                  //  NTUserPreference.NTCloudPSS + NTUserPreference.NTUserCloudSeed);\r
+                result = NTHttpAccess.UserCloudUploadNgId(uid, hashed, list, false);\r
+\r
+            }\r
+            else\r
+            {\r
+                string uid = NTUserPreference.NTCloudID;\r
+                string passwd = NTUserPreference.NTCloudPSS;\r
+                result = NTHttpAccess.ntUploadNgId(uid, passwd, list, false);\r
+            }\r
+            NTDebug.l(result);\r
+        }\r
+\r
+        void uploadAllNgNames(object para)\r
+        {\r
+            List<string> list = para as List<string>;\r
+            if (list == null)\r
+                return;\r
+            string result;\r
+            if (NTUserPreference.NTUserCloudIsEnabled)\r
+            {\r
+                string uid = NTUserPreference.NTCloudID;\r
+                string hashed = NTUserPreference.NTUserCloudGetHashedPasswd(); \r
+                //NTCrypt.getSHA256Hashed(\r
+                  //  NTUserPreference.NTCloudPSS + NTUserPreference.NTUserCloudSeed);\r
+                result = NTHttpAccess.UserCloudUploadNgName(uid, hashed, list, false);\r
+\r
+            }\r
+            else\r
+            {\r
+                string uid = NTUserPreference.NTCloudID;\r
+                string passwd = NTUserPreference.NTCloudPSS;\r
+                result = NTHttpAccess.ntUploadNgName(uid, passwd, list, false);\r
+            }\r
+            NTDebug.l(result);\r
+        }\r
+\r
+        private void txtNgEdit_TextChanged(object sender, TextChangedEventArgs e)\r
+        {\r
+            btnSaveNgEdit.IsEnabled = true;\r
+        }\r
+\r
+\r
+        private void btnSaveNgEdit_Click(object sender, RoutedEventArgs e)\r
+        {\r
+\r
+            string src = txtNgEdit.Text;\r
+            string[] sArr = NTTextUtiles.splitLine(src);\r
+            List<string> list = new List<string>();\r
+\r
+            foreach (string s in sArr)\r
+            {\r
+                string s1 = s.Trim();\r
+                if (s1.Length == 0)\r
+                    continue;\r
+                list.Add(s1);\r
+            }\r
+\r
+            NTNgItems ngItem = NTNgItems.getContext();\r
+\r
+            int idx = cmbNgEditKind.SelectedIndex;\r
+            switch (idx)\r
+            {\r
+                case 0: // word\r
+                    ngItem.WriteNgWord(list.ToArray());\r
+                    Thread th = new Thread(uploadAllNgWords);\r
+                    th.Start(list);\r
+                    NTFileAccess.ntWriteNgWordsToFile(ngItem.getNgWords());\r
+                    break;\r
+                case 1: // name\r
+                    ngItem.WriteNgName(list.ToArray());\r
+                    th = new Thread(uploadAllNgNames);\r
+                    th.Start(list);\r
+                    NTFileAccess.ntWriteNgNamesToFile(ngItem.getNgNames());\r
+                    break;\r
+                case 2: // id\r
+                    ngItem.WriteNgId(list.ToArray());\r
+                    th = new Thread(uploadAllNgIds);\r
+                    th.Start(list);\r
+                    NTFileAccess.ntWriteNgIdsToFile(ngItem.getNgIds());\r
+                    break;\r
+                default:\r
+                    return;\r
+            }\r
+            btnSaveNgEdit.IsEnabled = false;\r
+            //txtNgEdit.Text = string.Empty;\r
+        }\r
+\r
+\r
+        private void cmbNgEditKind_SelectionChanged(object sender, SelectionChangedEventArgs e)\r
+        {\r
+            constructNgTabItem(tabItemNgEdit);\r
+        }\r
+\r
+\r
+        private void tabCtrlMain_SelectionChanged(object sender, SelectionChangedEventArgs e)\r
+        {\r
+            TabControl tc = sender as TabControl;\r
+            if (tc == null)\r
+                return;\r
+\r
+            TabItem ti = tc.SelectedItem as TabItem;\r
+            if (ti == null || ti.Name == null)\r
+                return;\r
+            switch (ti.Name)\r
+            {\r
+                case "tabItemNgEdit":\r
+                    constructNgTabItem(ti);\r
+                    break;\r
+            }\r
+\r
+\r
+\r
+\r
+\r
+        }\r
+\r
+\r
+        private void btnExit_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            Close();\r
+        }\r
+        private void btnRestoreWindow_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            RestoreMainWindow();\r
+        }\r
+        private void btnMaximizeWindow_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            MaximizeMainWindow();\r
+        }\r
+\r
+        private void btnSetup_Click(object sender, RoutedEventArgs e)\r
+        {\r
+\r
+            NTSetupWindow w = new NTSetupWindow();\r
+            w.Owner = this;\r
+            if (w.ShowDialog() == true)\r
+            {\r
+                NTDebug.l("OK");\r
+            }\r
+            else\r
+            {\r
+                NTDebug.l("Cancel");\r
+            }\r
+            progressCtrlCloud.IsIndeterminate = NTUserPreference.NTCloudIsEnabled;\r
+            \r
+        }\r
+\r
+\r
+        /*private void imgBtnTabClose_MouseDown(object sender, MouseButtonEventArgs e)\r
+        {\r
+            //MessageBox.Show();\r
+            NTDebug.l("Invoke the tab close");\r
+        }*/\r
+\r
+        private void btnWriteRes_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            IThread ithread = mResPanel.getCurrentThread();\r
+            NTThreadTitle thread = ithread as NTThreadTitle;// findSelectedThreadTitle();\r
+            if (thread == null)\r
+            {\r
+                MessageBox.Show("書き込む板が見つかりません。");\r
+                return;\r
+            }\r
+            WriteRes_Invoke(thread, null);\r
+        }\r
+\r
+        private void btnFontSetup_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            mResPanel.ToggleFontSetupTool();\r
+        }\r
+\r
+        private void btnPlayAutoScroll_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            mResPanel.ToggleAutoScroll();\r
+            btnPlayAutoScroll.Visibility = System.Windows.Visibility.Collapsed;\r
+            btnStopAutoScroll.Visibility = System.Windows.Visibility.Visible;\r
+        }\r
+\r
+        private void btnStopAutoScroll_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            mResPanel.ToggleAutoScroll();\r
+            btnPlayAutoScroll.Visibility = System.Windows.Visibility.Visible;\r
+            btnStopAutoScroll.Visibility = System.Windows.Visibility.Collapsed;\r
+        }\r
+\r
+#if DOTNET45\r
+        private void btnTextTool_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            NTUserPreference.ResViewTextSelMode = true;\r
+            mResPanel.UpdateTextSelMode(true);\r
+            btnTextTool.Visibility = System.Windows.Visibility.Collapsed;\r
+            btnTouchMode.Visibility = System.Windows.Visibility.Visible;\r
+\r
+        }\r
+        private void btnTouchMode_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            NTUserPreference.ResViewTextSelMode = false;\r
+            mResPanel.UpdateTextSelMode(false);\r
+            btnTextTool.Visibility = System.Windows.Visibility.Visible;\r
+            btnTouchMode.Visibility = System.Windows.Visibility.Collapsed;\r
+\r
+        }\r
+#endif\r
+        public void WriteRes_Invoke(NTThreadTitle tt, string siteMsg)\r
+        {\r
+\r
+            NTWriteResWindow w = new NTWriteResWindow(this, tt, siteMsg);\r
+            w.Owner = this;\r
+            w.Show();\r
+\r
+        }\r
+\r
+        public void WriteResCallback(bool update, NTThreadTitle thread)\r
+        {\r
+            if (update)\r
+            {\r
+                UpdateThread(thread);\r
+                //OpenNewThread(thread);\r
+                //updateResViewTabItem(thread);\r
+            }\r
+        }\r
+        \r
+#if false\r
+        private void treeBoardView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)\r
+        {\r
+            //MessageBox.Show("sender: " + sender.ToString());\r
+            if (e.NewValue is TreeViewItem)\r
+            {\r
+                TreeViewItem item = (TreeViewItem)e.NewValue;\r
+\r
+                NTDebug.l(item.Header.ToString());\r
+                if (item.Tag is NTBoard)\r
+                {\r
+                    NTBoard board = (NTBoard)item.Tag;\r
+                    mSubjectPanel.OpenBoard(board);\r
+                    constructBoardTabItem(board/*, true*/);\r
+                    TabItem tabitem = searchBoardFromTabItem(board);\r
+                    if (tabitem != null || tabitem.Tag == null)\r
+                    {\r
+                        constructBoardTabItemContent(board, tabitem);\r
+                        int num = tabCtrlSubject.Items.Count;\r
+                        if (num > 0)\r
+                        {\r
+                            tabCtrlSubject.SelectedIndex = num - 1;\r
+                        }\r
+                    }\r
+                 }\r
+            }\r
+\r
+        }\r
+#endif\r
+        private void btnUpdate_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            NTThreadTitle thread = mResPanel.getCurrentThread() as NTThreadTitle;\r
+            if(thread != null)\r
+                UpdateThread(thread);\r
+#if false\r
+            NTDebug.l("Entering btnUpdate");\r
+            object o;\r
+            if ((o = tabCtrlDat.SelectedItem) != null)\r
+            {\r
+                TabItem tabItem = (TabItem)o;\r
+                if (tabItem.Tag is NTThreadTitle)\r
+                {\r
+                    updateResViewTabItem((NTThreadTitle)tabItem.Tag);\r
+                }\r
+\r
+            }\r
+\r
+\r
+            IInputElement focusedElement = FocusManager.GetFocusedElement(this);\r
+            TabItem tabItem;\r
+            if (focusedElement != null)\r
+            {\r
+                if (focusedElement is ListViewItem)\r
+                {\r
+                    NTDebug.l("Update subject");\r
+                    tabItem = (TabItem)tabCtrlSubject.SelectedItem;\r
+\r
+                    if (tabItem.Tag is NTBoard)\r
+                    {\r
+                        UpdateBoardTabItem((NTBoard)tabItem.Tag);\r
+                    }\r
+                }\r
+                else if (focusedElement is TreeView)\r
+                {\r
+                    NTDebug.l("Update board_menu");\r
+\r
+                }\r
+                else if (focusedElement is FlowDocumentScrollViewer)\r
+                {\r
+                    NTDebug.l("Update dat");\r
+                    tabItem = (TabItem)tabCtrlDat.SelectedItem;\r
+\r
+                    if (tabItem.Tag is NTThreadTitle)\r
+                    {\r
+                        updateResViewTabItem((NTThreadTitle)tabItem.Tag);\r
+                    }\r
+                }\r
+                else\r
+                {\r
+                    object o;\r
+                    if ((o = tabCtrlDat.SelectedItem) != null)\r
+                    {\r
+                        tabItem = (TabItem)o;\r
+                        if (tabItem.Tag is NTThreadTitle)\r
+                        {\r
+                            updateResViewTabItem((NTThreadTitle)tabItem.Tag);\r
+                        }\r
+                    }\r
+                    else if ((o = tabCtrlSubject.SelectedItem) != null)\r
+                    {\r
+                        tabItem = (TabItem)o;\r
+\r
+                        if (tabItem.Tag is NTBoard)\r
+                        {\r
+                            UpdateBoardTabItem((NTBoard)tabItem.Tag);\r
+                        }\r
+                    }\r
+                }\r
+            }\r
+            else\r
+            {\r
+                object o;\r
+                if ((o = tabCtrlDat.SelectedItem) != null)\r
+                {\r
+                    tabItem = (TabItem)o;\r
+                    if (tabItem.Tag is NTThreadTitle)\r
+                    {\r
+                        updateResViewTabItem((NTThreadTitle)tabItem.Tag);\r
+                    }\r
+                }\r
+                else if ((o = tabCtrlSubject.SelectedItem) != null)\r
+                {\r
+                    tabItem = (TabItem)o;\r
+\r
+                    if (tabItem.Tag is NTBoard)\r
+                    {\r
+                        UpdateBoardTabItem((NTBoard)tabItem.Tag);\r
+                    }\r
+                }\r
+            }\r
+#endif               \r
+        }\r
+\r
+        private void btnUpdateInSubject_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            NTBoard board = mSubjectPanel.GetCurrentBoard() as NTBoard;\r
+            if (board == null)\r
+                return;\r
+\r
+            board.Update(null);\r
+            \r
+            /*object o;\r
+            if ((o = tabCtrlSubject.SelectedItem) != null)\r
+            {\r
+                TabItem tabItem = (TabItem)o;\r
+\r
+                if (tabItem.Tag is NTBoard)\r
+                {\r
+                    UpdateBoardTabItem((NTBoard)tabItem.Tag);\r
+                }\r
+            }*/\r
+        }\r
+#if true\r
+        private void btnJumpToTopInSubject_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            mSubjectPanel.JumpToTop();\r
+            /*TabItem item = tabCtrlSubject.SelectedItem as TabItem;\r
+            if (item == null)\r
+                return;\r
+\r
+            ListView lv = item.Content as ListView;\r
+            if (lv == null)\r
+                return;\r
+\r
+            int cnt = lv.Items.Count;\r
+            if (cnt < 1)\r
+                return;\r
+\r
+            NTThreadTitle th = lv.Items[0] as NTThreadTitle;\r
+            if (th != null)\r
+                lv.ScrollIntoView(th);*/\r
+        }\r
+\r
+        private void btnJumpToBottomInSubject_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            mSubjectPanel.JumpToBottom();\r
+            /*TabItem item = tabCtrlSubject.SelectedItem as TabItem;\r
+            if (item == null)\r
+                return;\r
+\r
+            ListView lv = item.Content as ListView;\r
+            if (lv == null)\r
+                return;\r
+\r
+            int cnt = lv.Items.Count;\r
+            if (cnt < 1)\r
+                return;\r
+\r
+            NTThreadTitle th = lv.Items[cnt - 1] as NTThreadTitle;\r
+            if (th != null)\r
+                lv.ScrollIntoView(th);*/\r
+\r
+        }\r
+#endif\r
+\r
+\r
+#if false\r
+        void lv_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)\r
+        {\r
+            //NTDebug.l("TEST");\r
+            ListView lv;\r
+            //lv.SelectionMode = SelectionMode.Single;\r
+            //lv.\r
+            if (!(sender is ListView))\r
+                return;\r
+\r
+            lv = (ListView)sender;\r
+            object o = lv.SelectedItem;\r
+            if (!(o is NTThreadTitle))\r
+                return;\r
+\r
+            NTThreadTitle tt = (NTThreadTitle)o;\r
+\r
+           \r
+            constructResViewTabItem(tt, true);\r
+\r
+\r
+        }\r
+\r
+        void lv_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)\r
+        {\r
+            NTDebug.l("TEST");\r
+        }\r
+\r
+        void btnSubjectTabItemClose_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            //NTDebug.l("Clicked");\r
+\r
+            if (!(sender is Button))\r
+                return;\r
+\r
+            if (!((((Button)sender).Tag) is NTBoard))\r
+                return;\r
+            NTBoard board = (NTBoard)(((Button)sender).Tag);\r
+            int idx;\r
+            if (0 <= (idx = searchBoardFromTabItemIndex(board)))\r
+            {\r
+                tabCtrlSubject.Items.RemoveAt(idx);\r
+                //storeOpenedBoardList();\r
+            }\r
+\r
+        }\r
+\r
+        void btnDatTabItemClose_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            //NTDebug.l("Clicked");\r
+\r
+            if (!(sender is Button))\r
+                return;\r
+\r
+            if (!((((Button)sender).Tag) is NTThreadTitle))\r
+                return;\r
+            NTThreadTitle thread = (NTThreadTitle)(((Button)sender).Tag);\r
+            int idx;\r
+            if (0 <= (idx = searchThreadFromTabItems(thread)))\r
+            {\r
+                tabCtrlDat.Items.RemoveAt(idx);\r
+               \r
+                //storeOpenedThreadList();\r
+\r
+\r
+                int num = tabCtrlDat.Items.Count;\r
+                if (num <= 0)\r
+                    return;\r
+                num--;\r
+                //idx++;\r
+                idx = (idx > num) ? num : idx;\r
+                TabItem tabItem = tabCtrlDat.Items[idx] as TabItem;\r
+                if (tabItem == null)\r
+                    return;\r
+                if(tabItem.Content == null)\r
+                    constructResContent(tabItem);\r
+\r
+                tabCtrlDat.SelectedIndex = idx;\r
+                \r
+            }\r
+\r
+        }\r
+#endif\r
+\r
+\r
+        void btnAllBoardSearch_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            string sWord = txtAllBoardSeach.Text.Trim();\r
+            if (sWord.Length == 0)\r
+                return;\r
+\r
+            string result = NTHttpAccess.queryThreadFromAllBoard(sWord);\r
+            if (result == null)\r
+            {\r
+                MessageBox.Show("検索に失敗しました。");\r
+                return;\r
+            }\r
+\r
+            NTDebug.l(sWord);\r
+\r
+            lstSearchedThread.Items.Clear();\r
+\r
+\r
+\r
+            List<NTAllboardSearch> abs = NTAllboardSearch.Parse(result);\r
+\r
+            foreach (NTAllboardSearch search in abs)\r
+            {\r
+                ListBoxItem lbi = new ListBoxItem();\r
+                lbi.Content = search.mTitle + "[" + search.mBoard.mName + "]";\r
+                lbi.Tag = search;\r
+                lstSearchedThread.Items.Add(lbi);\r
+            }\r
+\r
+\r
+        }\r
+\r
+        public void setupTitleSearchListBySimString(NTThreadTitle tt)\r
+        {\r
+            tabItemSearch.IsSelected = true;\r
+\r
+            NTSimString simStr = new NTSimString(tt.Title);\r
+            NTBoard board = tt.mBoard;\r
+            lstSearchedThread.Items.Clear();\r
+            foreach (NTThreadTitle thread in board.mThreadTitleList)\r
+            {\r
+                string title = thread.Title;\r
+                int match_len =simStr.match(title);\r
+                if((match_len*2) > (title.Length))\r
+                {\r
+                    ListBoxItem lbi = new ListBoxItem();\r
+                    lbi.Content = thread.Title;\r
+                    lbi.Tag = thread;\r
+                    lstSearchedThread.Items.Add(lbi);\r
+                }\r
+            }\r
+        }\r
+\r
+        void btnTitleSearch_Click(object sender, RoutedEventArgs e)\r
+        {\r
+\r
+\r
+            /*TabItem item = tabCtrlSubject.SelectedItem as TabItem;\r
+            if (item == null)\r
+                return;\r
+\r
+\r
+            NTBoard board = item.Tag as NTBoard;*/\r
+            NTBoard board = mSubjectPanel.GetCurrentBoard() as NTBoard;\r
+            if (board == null)\r
+                return;\r
+\r
+            string sWord = txtTitleSearch.Text.Trim();\r
+            if (sWord.Length == 0)\r
+                return;\r
+\r
+            NTVagueSearchWord v = new NTVagueSearchWord(sWord);\r
+\r
+            lstSearchedThread.Items.Clear();\r
+\r
+            foreach (NTThreadTitle tt in board.mThreadTitleList)\r
+            {\r
+                string title = tt.Title;\r
+                int len;\r
+                if (0 <= v.match(title, 0, out len))\r
+                {\r
+\r
+                    ListBoxItem lbi = new ListBoxItem();\r
+                    lbi.Content = tt.Title;\r
+                    lbi.Tag = tt;\r
+                    lstSearchedThread.Items.Add(lbi);\r
+                }\r
+            }\r
+\r
+        }\r
+\r
+        private void lstSearchedThread_SelectionChanged(object sender, SelectionChangedEventArgs e)\r
+        {\r
+            ListBoxItem item = lstSearchedThread.SelectedItem as ListBoxItem;\r
+            if (item == null)\r
+                return;\r
+\r
+            NTThreadTitle tt = item.Tag as NTThreadTitle;\r
+            if (tt == null)\r
+            {\r
+                NTAllboardSearch abs = item.Tag as NTAllboardSearch;\r
+                if (abs != null)\r
+                {\r
+                    NTBoard board = abs.mBoard;\r
+                    if (board == null)\r
+                        return;\r
+\r
+                    string strSubject = null;\r
+                    if (!board.mDataInit)\r
+                    {\r
+\r
+                       // if (!NTFileAccess.isSubjectExsists(board.mName))\r
+                            if (!NTHttpAccess.getSubject(board.mAddress, board.mName))\r
+                                return;\r
+\r
+                        strSubject = NTFileAccess.retrieveSubjectDataFromFile(board.mName);\r
+                        if (strSubject == null)\r
+                            return;\r
+\r
+                        if (!board.parseSubjectData(strSubject, mFavoriteData))\r
+                            return;\r
+                    }\r
+\r
+                    tt = board.findThreadTitleByDatName(abs.mDat + ".dat");\r
+                    if (tt != null)\r
+                    {\r
+                        OpenNewThread(tt);\r
+#if false\r
+                        //bool datExists = NTFileAccess.isDatExsists(board.mName, tt.mDat);\r
+                        constructResViewTabItem(tt/*, !datExists*/);\r
+                        int idx = searchThreadFromTabItems(tt);\r
+                        if (idx >= 0)\r
+                        {\r
+                            TabItem tabItem = tabCtrlDat.Items[idx] as TabItem;\r
+                            if (tabItem != null)\r
+                            {\r
+\r
+                                constructResContent(tabItem);\r
+                                tabCtrlDat.SelectedIndex = idx;\r
+                            }\r
+\r
+                        }\r
+#endif\r
+                    }\r
+\r
+\r
+                }\r
+                return;\r
+            }\r
+            //NTDebug.l(tt.Title);\r
+            else\r
+            {\r
+                NTBoard board = tt.mBoard;\r
+                if (board == null)\r
+                    return;\r
+\r
+                string strSubject = null;\r
+                if (!board.mDataInit)\r
+                {\r
+\r
+                    if (!NTFileAccess.isSubjectExsists(board.mName))\r
+                        if (!NTHttpAccess.getSubject(board.mAddress, board.mName))\r
+                            return;\r
+\r
+                    strSubject = NTFileAccess.retrieveSubjectDataFromFile(board.mName);\r
+                    if (strSubject == null)\r
+                        return;\r
+\r
+                    if (!board.parseSubjectData(strSubject, mFavoriteData))\r
+                        return;\r
+                }\r
+\r
+                OpenNewThread(tt);\r
+#if false\r
+                //NTThreadTitle tt = board.findThreadTitleByDatName(values[0]);\r
+                //if (tt != null)\r
+                //{\r
+                bool datExists = NTFileAccess.isDatExsists(board.mName, tt.mDat);\r
+                //constructResViewTabItem(tt/*, !datExists*/);\r
+                idx = searchThreadFromTabItems(tt);\r
+                if (idx >= 0)\r
+                {\r
+                    TabItem tabItem = tabCtrlDat.Items[idx] as TabItem;\r
+                    if (tabItem != null && tabItem.Content == null)\r
+                    {\r
+                        constructResContent(tabItem);\r
+                    }\r
+                    tabCtrlDat.SelectedIndex = idx;\r
+                }\r
+                //}\r
+#endif\r
+            }\r
+        }\r
\r
+\r
+\r
+    }\r
+}\r
diff --git a/NT2chView45/MainWindow_delegates.cs b/NT2chView45/MainWindow_delegates.cs
new file mode 100755 (executable)
index 0000000..e614423
--- /dev/null
@@ -0,0 +1,98 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Windows.Controls;\r
+\r
+namespace NT2chView\r
+{\r
+    partial class MainWindow\r
+    {\r
+        public delegate void DelegateMsgOpenBoardListRequest(NTCategory category);\r
+        public delegate void DelegateMsgOpenFavoriteListRequest(NTFavorite favorite);\r
+        public delegate void DelegateMsgOpenThreadTitleListRequest(NTBoard board);\r
+        public delegate void DelegateMsgOpenThreadTitleListRequest2(string boardName);\r
+        public delegate void DelegateMsgOpenThreadRequest(NTThreadTitle tt);\r
+        public delegate void DelegateMsgGetHistoryOnCloud(int type);\r
+\r
+        void MsgOpenBoardListRequest(NTCategory category)\r
+        {\r
+            mBoardPanel.BoardTable = category.mBoardList;\r
+            mBoardPanel.Visibility = System.Windows.Visibility.Visible;\r
+            mFavoritePanel.Visibility = System.Windows.Visibility.Hidden;\r
+        }\r
+\r
+        void MsgOpenFavoriteListRequest(NTFavorite favorite)\r
+        {\r
+            mFavoritePanel.Visibility = System.Windows.Visibility.Visible;\r
+            mBoardPanel.Visibility = System.Windows.Visibility.Hidden;\r
+        }\r
+\r
+        void MsgOpenThreadtitleListRequest(NTBoard board)\r
+        {\r
+            if (board == null)\r
+                return;\r
+\r
+            if(board.mDataInit)\r
+                mSubjectPanel.OpenBoard(board);\r
+            else\r
+                board.Update(mOnNotifyBoardUpdate);\r
+\r
+            /*constructBoardTabItem(board);\r
+            TabItem tabitem = searchBoardFromTabItem(board);\r
+            if (tabitem != null)// || tabitem.Tag == null)\r
+            {\r
+                if (tabitem.Tag != null)\r
+                {\r
+                    constructBoardTabItemContent(board, tabitem);\r
+                    int num = tabCtrlSubject.Items.Count;\r
+                    if (num > 0)\r
+                    {\r
+                        tabCtrlSubject.SelectedIndex = num - 1;\r
+                    }\r
+                }\r
+                else\r
+                {\r
+                    board.Update(mOnNotifyBoardUpdate);\r
+                }\r
+            }*/\r
+        }\r
+        void MsgOpenThreadtitleListRequest2(string boardName)\r
+        {\r
+            if (boardName == null)\r
+                return;\r
+\r
+            NTBoard board = NTDataRoot.getBoardByName(boardName);\r
+            if (board == null)\r
+                return;\r
+\r
+            MsgOpenThreadtitleListRequest(board);\r
+        }\r
+\r
+        void MsgOpenThreadRequest(NTThreadTitle tt)\r
+        {\r
+            OpenNewThread(tt);\r
+        }\r
+\r
+        void MsgGetHistoryOnCloud(int type)\r
+        {\r
+            Thread thread;\r
+            switch (type)\r
+            {\r
+                case 1:\r
+                    thread = new Thread(getReadHistoryOnCloud);\r
+                    break;\r
+                case 2:\r
+                    thread = new Thread(getWriteHistoryOnCloud);\r
+                    break;\r
+                case 3:\r
+                    thread = new Thread(getBookmarkHistoryOnCloud);\r
+                    break;\r
+                default:\r
+                    return;\r
+            }\r
+            thread.Start();\r
+        }\r
+\r
+    }\r
+}\r
diff --git a/NT2chView45/MainWindow_manipulate_ctrl.cs b/NT2chView45/MainWindow_manipulate_ctrl.cs
new file mode 100755 (executable)
index 0000000..15a1a02
--- /dev/null
@@ -0,0 +1,1199 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Windows;\r
+using System.Windows.Controls;\r
+using System.Windows.Data;\r
+using System.Windows.Media;\r
+using System.Windows.Documents;\r
+\r
+using NT2chView.NtNet;\r
+using NT2chView.NtFile;\r
+using NT2chView.NtHtml;\r
+using System.Threading;\r
+using System.Windows.Threading;\r
+using System.Windows.Controls.Primitives;\r
+using System.Diagnostics;\r
+using System.Collections.ObjectModel;\r
+using System.Windows.Media.Imaging;\r
+using System.IO;\r
+using System.Windows.Input;\r
+using NT2chCtrl;\r
+using NT2chObject;\r
+\r
+\r
+namespace NT2chView\r
+{\r
+    public partial class MainWindow : Window\r
+    {\r
+        //List<string> mFavoriteBoardList = new List<string>();\r
+        //List<string> mFavoriteThreadList = new List<string>();\r
+\r
+        public void AddGraphic(string path)\r
+        {\r
+            tabCtrlMain.SelectedItem = tabItemGraphics;\r
+            mGraphicsPanel.AddGraphic(path);\r
+        }\r
+\r
+        public void OpenMoviePanel(string id)\r
+        {\r
+            tabCtrlMain.SelectedItem = tabItemMovie;\r
+            mMoviePanel.NavigateYoutube(id);\r
+\r
+        }\r
+        void constructNgTabItem(TabItem ti)\r
+        {\r
+            NTNgItems ngItem = NTNgItems.getContext();\r
+            List<string> list;// = ngItem.getNgWords();\r
+            int idx = cmbNgEditKind.SelectedIndex;\r
+            switch (idx)\r
+            {\r
+                case 0://word\r
+                    list = ngItem.getNgWords();\r
+                    break;\r
+                case 1: // name\r
+                    list = ngItem.getNgNames();\r
+                    break;\r
+                case 2: // id\r
+                    list = ngItem.getNgIds();\r
+                    break;\r
+                default:\r
+                    return;\r
+            }\r
+    \r
+            StringBuilder sb = new StringBuilder(64);\r
+            foreach (string s in list)\r
+                sb.Append(s).Append('\n');\r
+\r
+            if(txtNgEdit != null)\r
+                txtNgEdit.Text = sb.ToString();\r
+\r
+        }\r
+\r
+        /*void removeFavoriteThread(string description)\r
+        {\r
+            if (description.Trim().Length == 0)\r
+                return;\r
+            int len = mFavoriteThreadList.Count;\r
+            int idx = 0;\r
+            for (; idx < len; idx++)\r
+            {\r
+                if (mFavoriteThreadList[idx].Equals(description))\r
+                    break;\r
+            }\r
+            if (idx == len)\r
+                return;\r
+\r
+            mFavoriteThreadList.RemoveAt(idx);\r
+            \r
+\r
+        }\r
+        void removeFavoriteBoard(string description)\r
+        {\r
+            if (description.Trim().Length == 0)\r
+                return;\r
+            int len = mFavoriteBoardList.Count;\r
+            int idx = 0;\r
+            for (; idx < len; idx++)\r
+            {\r
+                if (mFavoriteBoardList[idx].Equals(description))\r
+                    break;\r
+            }\r
+            if (idx == len)\r
+                return;\r
+\r
+            mFavoriteBoardList.RemoveAt(idx);\r
+\r
+        }*/\r
+\r
+\r
+\r
+        public void addFavoriteBoard(string description)\r
+        {\r
+            if (description.Trim().Length == 0)\r
+                return;\r
+\r
+            /*foreach (string s in mFavoriteBoardList)\r
+                if (s.Equals(description))\r
+                    return;\r
+\r
+            //ListBoxItem item = new ListBoxItem();\r
+            //item.Tag = description;\r
+            //item.Content = description;\r
+            mFavoriteBoardList.Add(description);*/\r
+            //NTFileAccess.addFavoriteBoardToFile(description);\r
+            NTFavoriteBoard fb = mFavoriteData.addBoardByDescription(description, false);\r
+            mFavoritePanel.addBoard(fb);\r
+\r
+        }\r
+\r
+        public void addFavoriteThread(NTThreadTitle thread)\r
+        {\r
+            string description = thread.mDat + NTTextUtiles.YEN_VALUE[0]\r
+                + thread.mBoard.mName + NTTextUtiles.YEN_VALUE[0]\r
+                + thread.Title;\r
+\r
+            if (description.Trim().Length == 0)\r
+                return;\r
+\r
+            string[] values = description.Split(NTTextUtiles.YEN_VALUE);\r
+            if (values.Length < 3)\r
+                return;\r
+\r
+            NTFavoriteThread ft = mFavoriteData.addThreadByDescription(description, false, true);\r
+            if(ft == null)\r
+                return;\r
+\r
+            mFavoritePanel.addThread(ft);\r
+\r
+\r
+            /*foreach (string s in mFavoriteThreadList)\r
+                if (s.Equals(description))\r
+                    return;\r
+\r
+            mFavoriteThreadList.Add(description);*/\r
+\r
+        }\r
+\r
+\r
+        public void removeFavoriteThread(NTThreadTitle thread)\r
+        {\r
+            string description = thread.mDat + NTTextUtiles.YEN_VALUE[0]\r
+                + thread.mBoard.mName + NTTextUtiles.YEN_VALUE[0]\r
+                + thread.Title;\r
+\r
+            if (description.Trim().Length == 0)\r
+                return;\r
+\r
+            string[] values = description.Split(NTTextUtiles.YEN_VALUE);\r
+            if (values.Length < 3)\r
+                return;\r
+\r
+            int idx = mFavoriteData.findThread(thread.getBoard().getName(), thread.getDatName(), thread.getTitle());\r
+            if (idx < 0)\r
+                return;\r
+\r
+            NTFavoriteThread ft = mFavoriteData.getThreadList()[idx];\r
+            if (ft == null)\r
+                return;\r
+\r
+            mFavoritePanel.removeThread(ft);\r
+\r
+\r
+            if (!mFavoriteData.removeThreadByDescription(description, true))\r
+                return;\r
+\r
+            /*foreach (string s in mFavoriteThreadList)\r
+                if (s.Equals(description))\r
+                    return;\r
+\r
+            mFavoriteThreadList.Remove(description);*/\r
+\r
+        }\r
+\r
+        public void appendBoardToExternalCategoryTree(NTBoard board)\r
+        {\r
+            NTCategory exCate = NTDataRoot.getExternalBoards();\r
+            mCategoryPanel.addExternalCategory(exCate);\r
+            if (mCategoryPanel.isExternalCategorySelected())\r
+            {\r
+                mBoardPanel.BoardTable = exCate.mBoardList;\r
+            }\r
+\r
+        }\r
+\r
+        public void removeBoardFromExternalCategoryTree(string boardName)\r
+        {\r
+            if (mCategoryPanel.isExternalCategorySelected())\r
+            {\r
+                NTCategory exCate = NTDataRoot.getExternalBoards();\r
+                mBoardPanel.BoardTable = exCate.mBoardList;\r
+            }\r
+\r
+\r
+        }\r
+\r
+        //static readonly string[] LIST_COLUMN_HEADERS =\r
+       // { " No. ", "スレッドタイトル", "レス数 ", " 既読 "," 未読 ", "最終取得日", "最終書込日" };\r
+       // static readonly string[] LIST_COLUMN_HEADERS_PNAME = \r
+       // { "SeqNo", "Title", "ResCnt", "ReadCnt", "RemainCnt","LastMod", "LastWrite" };\r
+#if false    \r
+        TabItem  constructResViewTabItem(NTThreadTitle thread)\r
+        {\r
+            int idx;\r
+            if (0 <= (idx = searchThreadFromTabItems(thread)))\r
+            {\r
+                return tabCtrlDat.Items[idx] as TabItem;\r
+            }\r
+\r
+            StackPanel sp = new StackPanel();\r
+            sp.Orientation = Orientation.Horizontal;\r
+            sp.MaxWidth = 250;\r
+            sp.Tag = thread;\r
+            sp.Margin = new Thickness(0);\r
+            ContextMenu cm = new System.Windows.Controls.ContextMenu();\r
+            sp.ContextMenu = cm;\r
+            setThreadTabHeaderContextMenu(thread, sp.ContextMenu);\r
+\r
+            \r
+            sp.MouseLeftButtonDown += new System.Windows.Input.MouseButtonEventHandler(threadTab_MouseLeftButtonDown);\r
+            sp.MouseEnter += sp_MouseEnter;\r
+            sp.MouseLeave += sp_MouseLeave;\r
+            TextBlock tb = new TextBlock();\r
+            string title = thread.Title.Trim();\r
+            if (title.Length > 20)\r
+                tb.Text = title.Substring(0, 20);\r
+            else\r
+                tb.Text = title;\r
+\r
+            tb.Tag = tb.Text;\r
+\r
+            tb.ContextMenu = cm;\r
+            sp.Children.Add(tb);\r
+            tb = new TextBlock();\r
+            tb.Text = "×";\r
+            tb.VerticalAlignment = System.Windows.VerticalAlignment.Center;\r
+            tb.FontSize = 8;\r
+            Button btn = new Button();\r
+            btn.Content = tb;\r
+            btn.Tag = thread;\r
+            btn.Click += new RoutedEventHandler(btnDatTabItemClose_Click);\r
+            //btn.MouseEnter += btn_MouseEnter;\r
+\r
+            \r
+            sp.Children.Add(btn);\r
+            btn.Width = 0;\r
+            btn.Height = 0;\r
+\r
+            TabItem tabItem = new TabItem();\r
+            tabItem.Header = sp;\r
+            tabItem.Tag = thread;\r
+\r
+            tabItem.GotFocus += new RoutedEventHandler(tabItem_GotFocus);\r
+            tabCtrlDat.Items.Add(tabItem);\r
+\r
+            return tabItem;\r
+        }\r
+#endif\r
+        void sp_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e)\r
+        {\r
+            StackPanel sp = sender as StackPanel;\r
+            if (sp == null)\r
+                return;\r
+            if (sp.Children.Count < 2)\r
+                return;\r
+            TextBlock tb = sp.Children[0] as TextBlock;\r
+            if (tb == null)\r
+                return;\r
+            Button btn = sp.Children[1] as Button;\r
+            if (null == btn)\r
+                return;\r
+\r
+            string s = tb.Tag as string;\r
+            if (s != null)\r
+            {\r
+                //if (s.Length > 20)\r
+                //    s.Substring(0, 20);\r
+                 tb.Text = s;\r
+            }\r
+\r
+            btn.Width = 0;\r
+            btn.Height = 0;\r
+        }\r
+\r
+        void sp_MouseEnter(object sender, System.Windows.Input.MouseEventArgs e)\r
+        {\r
+            StackPanel sp = sender as StackPanel;\r
+            if (sp == null)\r
+                return;\r
+            if(sp.Children.Count < 2)\r
+                return;\r
+            TextBlock tb = sp.Children[0] as TextBlock;\r
+            if (tb == null)\r
+                return;\r
+            Button btn = sp.Children[1] as Button;\r
+            if (null == btn)\r
+                return;\r
+\r
+            string s = tb.Tag as string;\r
+            if (s != null)\r
+            {\r
+                //if (s.Length > 20)\r
+               //     s.Substring(0, 20);\r
+\r
+                int len = s.Length;\r
+                //len = (len < 4) ? 2 : len - 1;\r
+                s = s.Substring(0, --len);\r
+                tb.Text = s;\r
+\r
+            }\r
+\r
+            btn.Width = 12;\r
+            btn.Height = 12;\r
+        }\r
+\r
+       /* void btn_MouseEnter(object sender, System.Windows.Input.MouseEventArgs e)\r
+        {\r
+            Button btn = sender as Button;\r
+            if (btn == null)\r
+                return;\r
+\r
+            ContextMenu cm = btn.ContextMenu;\r
+            if (null == cm)\r
+                return;\r
+\r
+            //throw new NotImplementedException();\r
+        }*/\r
+\r
+        DateTime mMouseMovetime = DateTime.Now;\r
+\r
+        void document_MouseMove(object sender, MouseEventArgs e)\r
+        {\r
+            //NTDebug.l("+++ AAA +++");\r
+            DateTime dt = DateTime.Now;\r
+            TimeSpan ts = dt.Subtract(mMouseMovetime);\r
+            if(2 < ((int)(ts.TotalSeconds))){\r
+                //NTDebug.l("+++ BBB +++");\r
+                mMouseMovetime = DateTime.Now;\r
+            }\r
+            //throw new NotImplementedException();\r
+        }\r
+\r
+        void UpdateThread(NTThreadTitle thread)\r
+        {\r
+            NTBoard board = thread.mBoard;\r
+            //int oldReadCnt = thread.mResCnt;\r
+\r
+            if (board.mMachiBBS)\r
+            {\r
+                //updateResViewTabItemMachiBBS(thread);\r
+                return;\r
+            }\r
+\r
+            //int idx;\r
+            //if (0 > (idx = searchThreadFromTabItems(thread)))\r
+            //{\r
+            //    return;\r
+            //}\r
+\r
+\r
+\r
+            thread.mPrevReadCnt = thread.ReadCnt;\r
+\r
+\r
+            if (!NTHttpAccess.getDat(board.mAddress, board.mName, thread.mDat, thread.Title))\r
+            {\r
+                NTDebug.l("getting the dat data failed.");\r
+                return;\r
+            }\r
+\r
+            string strDat = NTFileAccess.retrieveDatFromFile(board.mName, thread.mDat);\r
+            if (null == strDat)\r
+            {\r
+                return;\r
+            }\r
+\r
+\r
+            thread.parseDat(strDat);\r
+            thread.updateReadCntOnCloud();\r
+\r
+            int numRead;// = thread.ReadCnt;\r
+            int[] writes;\r
+            int[] bookmarkes;\r
+            string lastWrite;\r
+            NTFileAccess.retrieveDatAttrToFile(board.mName, thread.mDat,\r
+                out numRead, out writes, out bookmarkes, out lastWrite);\r
+\r
+\r
+            if (thread.ReadCnt > thread.mPrevReadCnt)\r
+            {\r
+                int wroteNo = thread.findWroteMsg(thread.mPrevReadCnt + 1);\r
+                if (wroteNo >= 0)\r
+                {\r
+                    thread.addWriteTag(wroteNo);\r
+                    thread.addBookmark(wroteNo);\r
+                    writes = thread.mWriteNoList.ToArray();\r
+                    bookmarkes = thread.mBookmarkList.ToArray();\r
+                    NTRes res = thread.findRes(wroteNo);\r
+                    if (res != null)\r
+                    {\r
+                        res.mWroteMsg = true;\r
+                        res.mBookmark = true;\r
+                    }\r
+\r
+                }\r
+            }\r
+\r
+\r
+            NTFileAccess.storeDatAttrToFile(board.mName, thread.mDat, thread.ResCnt, writes, bookmarkes);\r
+            thread.LastMod = DateTime.Now.ToString();\r
+\r
+\r
+            /*bool readNew;\r
+            if (numRead > 0 && thread.mPrevReadCnt == numRead)\r
+                readNew = false;\r
+            else\r
+                readNew = true;*/\r
+\r
+\r
+            thread.mPrevReadCnt = numRead;\r
+\r
+            mResPanel.OpenThread(thread);\r
+\r
+            if (numRead < thread.ResCnt)\r
+            {\r
+                Thread th = new Thread(ResTabUpdate);\r
+                th.Start();\r
+            }\r
+\r
+            mFavoritePanel.OnNotifyBoardUpdate(board);\r
+\r
+\r
+        }\r
+        public void ResTabUpdate()\r
+        {\r
+            Thread.Sleep(1000);\r
+\r
+            this.Dispatcher.BeginInvoke(DispatcherPriority.Normal,\r
+                (ThreadStart)delegate()\r
+            {\r
+                mResPanel.JumpToNew();\r
+                IThread ithread = mResPanel.getCurrentThread();\r
+                NTThreadTitle thread = ithread as NTThreadTitle;\r
+                if (thread != null)\r
+                {\r
+                    thread.mPrevReadCnt = thread.ReadCnt;\r
+                    NTBoard board = thread.mBoard;\r
+                    if(board != null)\r
+                        mFavoritePanel.OnNotifyBoardUpdate(board);\r
+\r
+                }\r
+\r
+            });\r
+\r
+\r
+        }\r
+\r
+        public void NgEdit_setResSection(NTRes res)\r
+        {\r
+            tabItemNgEdit.IsSelected = true;\r
+\r
+            string name = res.mName;\r
+            string id = res.mId;\r
+            string msg = res.mMsg;\r
+\r
+            txtNgNameEdit.Text = name;\r
+            txtNgIdEdit.Text = id;\r
+            txtNgWordEdit.Text = NTTextFormat.removeTag(msg);// parseResMsgForNgWord(msg);\r
+\r
+        }\r
+        void lv_MouseRightButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)\r
+        {\r
+            NTDebug.l("R-Button Down on LIstView.");\r
+            //throw new NotImplementedException();\r
+        }\r
+\r
+\r
+        void SubjectListHeader_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)\r
+        {\r
+            TextBlock tb = sender as TextBlock;\r
+            if (tb == null)\r
+                return;\r
+\r
+            ListView lv = tb.Tag as ListView;\r
+            if (lv == null)\r
+                return;\r
+\r
+            NTBoard board = lv.Tag as NTBoard;\r
+            if (board == null)\r
+                return;\r
+\r
+            ObservableCollection<NTThreadTitle> list = lv.ItemsSource as ObservableCollection<NTThreadTitle>;\r
+            if (list == null)\r
+                return;\r
+\r
+            List<NTThreadTitle> sortList = new List<NTThreadTitle>();\r
+            foreach (NTThreadTitle tt in list)\r
+                sortList.Add(tt);\r
+\r
+\r
+            list.Clear();\r
+\r
+            //board.mThreadListSortStack;\r
+            foreach (string s in board.mThreadListSortStack)\r
+            {\r
+                if (s.Equals(tb.Text))\r
+                {\r
+                    board.mThreadListSortStack.Remove(s);\r
+                    break;\r
+                }\r
+            }\r
+            //board.mThreadListSortStack.Add(tb.Text);\r
+\r
+            //foreach (string s in board.mThreadListSortStack)\r
+            //{\r
+\r
+                switch (tb.Text)\r
+                {\r
+                    case " No. ":\r
+                        sortList.Sort(SubjectListSortBySeqNo);\r
+                        break;\r
+                    case "スレッドタイトル":\r
+                        sortList.Sort(SubjectListSortByTitle);\r
+                        break;\r
+                    case "レス数 ":\r
+                        sortList.Sort(SubjectListSortByResCnt);\r
+                        break;\r
+                    case " 既読 ":\r
+                        sortList.Sort(SubjectListSortByReadCnt);\r
+                        break;\r
+                    case " 未読 ":\r
+                        sortList.Sort(SubjectListSortByRemainCnt);\r
+                        break;\r
+                    case "最終取得日":\r
+                        sortList.Sort(SubjectListSortByLastMod);\r
+                        break;\r
+                    case "最終書込日":\r
+                        sortList.Sort(SubjectListSortByLastWrite);\r
+                        break;\r
+                }\r
+            //}\r
+\r
+            foreach (NTThreadTitle tt in sortList)\r
+                list.Add(tt);\r
+        }\r
+\r
+        static int SubjectListSortBySeqNo(NTThreadTitle thread1, NTThreadTitle thread2)\r
+        {\r
+            return thread1.SeqNo - thread2.SeqNo;\r
+        }\r
+\r
+        static int SubjectListSortByTitle(NTThreadTitle thread1, NTThreadTitle thread2)\r
+        {\r
+            return thread2.Title.CompareTo(thread1.Title);\r
+        }\r
+        static int SubjectListSortByResCnt(NTThreadTitle thread1, NTThreadTitle thread2)\r
+        {\r
+            return thread2.ResCnt - thread1.ResCnt;\r
+        }\r
+        static int SubjectListSortByReadCnt(NTThreadTitle thread1, NTThreadTitle thread2)\r
+        {\r
+            return thread2.ReadCnt - thread1.ReadCnt;\r
+         }\r
+        static int SubjectListSortByRemainCnt(NTThreadTitle thread1, NTThreadTitle thread2)\r
+        {\r
+            return thread2.RemainCnt - thread1.RemainCnt;\r
+        }\r
+        static int SubjectListSortByLastMod(NTThreadTitle thread1, NTThreadTitle thread2)\r
+        {\r
+            DateTime dt1 = DateTime.MinValue;\r
+            DateTime dt2 = DateTime.MinValue;\r
+            try\r
+            {\r
+                dt1 = DateTime.Parse(thread1.LastMod);\r
+            }\r
+            catch { }\r
+            try\r
+            {\r
+                dt2 = DateTime.Parse(thread2.LastMod);\r
+            }\r
+            catch { }\r
+\r
+            return dt2.CompareTo(dt1);\r
+        }\r
+\r
+        static int SubjectListSortByLastWrite(NTThreadTitle thread1, NTThreadTitle thread2)\r
+        {\r
+            DateTime dt1 = DateTime.MinValue;\r
+            DateTime dt2 = DateTime.MinValue;\r
+            try\r
+            {\r
+                dt1 = DateTime.Parse(thread1.LastWrite);\r
+            }\r
+            catch { }\r
+            try\r
+            {\r
+                dt2 = DateTime.Parse(thread2.LastWrite);\r
+            }\r
+            catch { }\r
+\r
+            return dt2.CompareTo(dt1);\r
+        }\r
+\r
+\r
+\r
+        void lv_SelectionChanged(object sender, SelectionChangedEventArgs e)\r
+        {\r
+            //NTDebug.l("TEST");\r
+            ListView lv;\r
+            //lv.SelectionMode = SelectionMode.Single;\r
+            //lv.\r
+            if (!(sender is ListView))\r
+                return;\r
+\r
+            lv = (ListView)sender;\r
+            object o = lv.SelectedItem;\r
+            if (!(o is NTThreadTitle))\r
+                return;\r
+\r
+            NTThreadTitle tt = (NTThreadTitle)o;\r
+\r
+            OpenNewThread(tt);\r
+        }\r
+\r
+\r
+        public bool OpenNewBoard(NTBoard board)\r
+        {\r
+            string strSubject = null;\r
+            if (!board.mDataInit)\r
+            {\r
+\r
+                if (!NTFileAccess.isSubjectExsists(board.mName))\r
+                    if (!NTHttpAccess.getSubject(board.mAddress, board.mName))\r
+                        return false;\r
+\r
+                strSubject = NTFileAccess.retrieveSubjectDataFromFile(board.mName);\r
+                if (strSubject == null)\r
+                    return false;\r
+\r
+                if (!board.parseSubjectData(strSubject, mFavoriteData))\r
+                    return false;\r
+            }\r
+            return true;\r
+        }\r
+\r
+        public void OpenNewThread(NTThreadTitle thread)\r
+        {\r
+            if (thread == null)\r
+                return;\r
+\r
+            bool bRet = false;\r
+            string strDat;\r
+            string strDatName = thread.mDat;\r
+\r
+            NTBoard board = thread.mBoard;\r
+\r
+            if (board.mMachiBBS)\r
+            {\r
+                bRet = NTHttpAccess.getMachiBBSDat(board.mAddress, board.mName, thread.mDat, thread.Title);\r
+                strDatName = NTHttpUtils.ridSuffixFromCgiName(thread.mDat);\r
+                strDat = NTFileAccess.retrieveDatFromFile(board.mName, strDatName);\r
+                if (null == strDat)\r
+                    return;\r
+            }\r
+            else\r
+            {\r
+                if (!thread.mLocalDat)\r
+                {\r
+                    bRet = NTHttpAccess.getDat(board.mAddress, board.mName, thread.mDat, thread.Title);\r
+                }\r
+                else if (NTUserPreference.MaruIsEnabled)\r
+                {\r
+                    string sid = NTMaru.getSessionId();\r
+                    bRet = NTHttpAccess.getDatFromKako(board.mAddress, board.mName,\r
+                        thread.mDat, thread.Title, sid);\r
+                }\r
+                strDat = NTFileAccess.retrieveDatFromFile(board.mName, thread.mDat);\r
+                if (null == strDat)\r
+                    return;\r
+            }\r
+\r
+            if (thread.Title.Length == 0)\r
+            {\r
+                string strTitle = NTFileAccess.retrieveTitleFromDat(strDat);\r
+                if (strTitle != null)\r
+                {\r
+                    thread.Title = strTitle;\r
+                    NTFileAccess.storeDatTitle(board.mName, strDatName/*thread.mDat*/, strTitle);\r
+                }\r
+            }\r
+            bool cloudData = false;\r
+            if (NTUserPreference.NTCloudIsEnabled)\r
+            {\r
+                string strThreadAttr ;\r
+                if (NTUserPreference.NTUserCloudIsEnabled)\r
+                {\r
+                    strThreadAttr = NTHttpAccess.UserCloudQueryAttrValue(board.mName, thread.mDat);\r
+                }\r
+                else\r
+                {\r
+                    strThreadAttr = NTHttpAccess.ntQueryAttrValue(board.mName, thread.mDat);\r
+                }\r
+                if (strThreadAttr != null)\r
+                {\r
+                    cloudData = true;\r
+                    thread.parseAttr(strThreadAttr);\r
+                }\r
+            }\r
+\r
+\r
+            thread.mPrevReadCnt = thread.ReadCnt;\r
+\r
+            thread.parseDat(strDat);\r
+\r
+\r
+            if (bRet)\r
+                thread.updateReadCntOnCloud();\r
+\r
+            int numRead = -1;\r
+            int[] writes;\r
+            int[] bookmarkes;\r
+            string lastWrite;\r
+            NTFileAccess.retrieveDatAttrToFile(board.mName, strDatName,//thread.mDat,\r
+                out numRead, out writes, out bookmarkes, out lastWrite);\r
+            if (cloudData)\r
+            {\r
+                writes = thread.mWriteNoList.ToArray();\r
+                bookmarkes = thread.mBookmarkList.ToArray();\r
+            }\r
+            else\r
+            {\r
+                thread.mWriteNoList.Clear();\r
+                thread.mWriteNoList.AddRange(writes);\r
+                thread.mBookmarkList.Clear();\r
+                thread.mBookmarkList.AddRange(bookmarkes);\r
+\r
+            }\r
+            thread.setupBookmark();\r
+            thread.setupWriteTag();\r
+            if (numRead < thread.ResCnt || cloudData)\r
+            {\r
+                NTFileAccess.storeDatAttrToFile(board.mName, strDatName/*thread.mDat*/, thread.ResCnt, writes, bookmarkes);\r
+                thread.LastMod = DateTime.Now.ToString();\r
+            }\r
+            else\r
+            {\r
+                thread.LastMod = lastWrite;\r
+            }\r
+            thread.mPrevReadCnt = (thread.mPrevReadCnt < numRead) ? numRead : thread.mPrevReadCnt;\r
+\r
+            \r
+            mResPanel.OpenThread(thread);\r
+\r
+            if (numRead < thread.ResCnt)\r
+            {\r
+                Thread th = new Thread(ResTabUpdate);\r
+                th.Start();\r
+            }\r
+\r
+#if false\r
+            TabItem item = constructResViewTabItem(tt/*, true*/);\r
+            if (item != null)\r
+            {\r
+                if (item.Content == null || tt.ResCnt > tt.ReadCnt)\r
+                {\r
+                    string savedTitle = tt.Title;\r
+                    constructResContent(item);\r
+                    if (savedTitle.Length == 0 && tt.Title.Length > 0)\r
+                    {\r
+                        StackPanel sp = item.Header as StackPanel;\r
+                        if (sp != null)\r
+                        {\r
+                            if(sp.Children.Count > 0)\r
+                            {\r
+                                TextBlock tb = sp.Children[0] as TextBlock;\r
+                                if (tb != null)\r
+                                {\r
+                                    if (tt.Title.Length > 20)\r
+                                        tb.Text = tt.Title.Substring(0, 20);\r
+                                    else\r
+                                        tb.Text = tt.Title;\r
+                                    tb.Tag = tb.Text;\r
+                                }\r
+                            }\r
+                        }\r
+                    }\r
+                }\r
+                tabCtrlDat.SelectedItem = item;\r
+            }\r
+ #endif\r
+        }\r
+\r
+       \r
+#if false\r
+        void UpdateBoardTabItem(NTBoard board)\r
+        {\r
+\r
+            int idx;\r
+            if (0 > (idx = searchBoardFromTabItemIndex(board)))\r
+            {\r
+                MessageBox.Show("開かれた板が見つかりません。");\r
+                return;\r
+            }\r
+            \r
+            TabItem ti = (TabItem)tabCtrlSubject.Items[idx];\r
+\r
+            constructBoardTabItemContent(board, ti);\r
+\r
+            //ti.Tag = board;\r
+\r
+\r
+\r
+        }\r
+#endif\r
+#if false\r
+        void constructBoardTabItem(NTBoard board /*, bool fromWeb*/)\r
+        {\r
+            int idx;\r
+            if (0 <= (idx = searchBoardFromTabItemIndex(board)))\r
+            {\r
+                tabCtrlSubject.SelectedIndex = idx;\r
+                return;\r
+            }\r
+            /*if (fromWeb)\r
+            {\r
+                if (!NTHttpAccess.getSubject(board.mAddress, board.mName))\r
+                    return;\r
+            }\r
+            \r
+            string strSubject = NTFileAccess.retrieveSubjectDataFromFile(board.mName);\r
+\r
+            if (null == strSubject)\r
+                return;\r
+            \r
+            if (!board.parseSubjectData(strSubject))\r
+                return;\r
+            */\r
+\r
+            TabItem tabItem = new TabItem();\r
+            StackPanel sp = new StackPanel();\r
+            sp.Orientation = Orientation.Horizontal;\r
+            sp.MaxWidth = 200;\r
+            ContextMenu cm = new System.Windows.Controls.ContextMenu();\r
+            sp.ContextMenu = cm;\r
+            setBoardTabHeaderContextMenu(board, cm);\r
+            sp.MouseLeftButtonDown += new System.Windows.Input.MouseButtonEventHandler(boardTab_MouseLeftButtonDown);\r
+            //sp.MouseLeftButtonUp += new System.Windows.Input.MouseButtonEventHandler(sp_MouseLeftButtonUp);\r
+            sp.MouseEnter +=sp_MouseEnter;\r
+            sp.MouseLeave +=sp_MouseLeave;\r
+            sp.Tag = board;\r
+            sp.Margin = new Thickness(0);\r
+\r
+            TextBlock tb = new TextBlock();\r
+            string boardName = board.mName;\r
+            if(boardName.Length < 3)\r
+                boardName = " " + boardName + " ";\r
+            else if(boardName.Length == 3)\r
+                boardName = boardName + " ";\r
+            tb.Text = boardName;\r
+            tb.Tag = boardName;\r
+            sp.Children.Add(tb);\r
+            tb = new TextBlock();\r
+            tb.Text = "×";\r
+            tb.VerticalAlignment = System.Windows.VerticalAlignment.Center;\r
+            tb.FontSize = 8;\r
+            tb.Tag = board;\r
+            Button btn = new Button();\r
+            btn.Content = tb;\r
+            btn.Tag = board;\r
+            btn.Width = 0;\r
+            btn.Height = 0;\r
+            btn.Click += new RoutedEventHandler(btnSubjectTabItemClose_Click);\r
+            sp.Children.Add(btn);\r
+\r
+            tabItem.Header = sp;\r
+            tabItem.Tag = board;\r
+            tabCtrlSubject.Items.Add(tabItem);\r
+            tabCtrlSubject.SelectionChanged += tabCtrlSubject_SelectionChanged;\r
+        }\r
+#endif\r
+        //NTThreadTitle mSelectedThreadTitle = null;\r
+        //NTBoard mSelectedBoard = null;\r
+\r
+#if false\r
+        private int mDoubleCickTime = System.Windows.Forms.SystemInformation.DoubleClickTime;\r
+        private int mFirstClickTime = 0;\r
+        void boardTab_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)\r
+        {\r
+            NTDebug.l("Enterinf MouseDown");\r
+\r
+            if (mSelectedBoard == null)\r
+            {\r
+                if (sender is StackPanel)\r
+                {\r
+                    StackPanel sp = (StackPanel)sender;\r
+                    if (sp.Tag is NTBoard)\r
+                    {\r
+                        mSelectedBoard = (NTBoard)sp.Tag;\r
+                        DateTime dt = DateTime.Now;\r
+                        mFirstClickTime = dt.Second*1000 + dt.Millisecond;\r
+                    }\r
+                }\r
+            }\r
+            else\r
+            {\r
+                DateTime dt = DateTime.Now;\r
+                int clickTime =  dt.Second*1000 + dt.Millisecond;\r
+                clickTime -= mFirstClickTime;\r
+                if (clickTime <= mDoubleCickTime)\r
+                {\r
+                    if (sender is StackPanel)\r
+                    {\r
+                        StackPanel sp = (StackPanel)sender;\r
+                        if (sp.Tag is NTBoard)\r
+                        {\r
+                            if (mSelectedBoard.Equals(sp.Tag))\r
+                            {\r
+                                NTDebug.l("Dbl Clicked!");\r
+                                UpdateBoardTabItem(mSelectedBoard);\r
+                            }\r
+                        }\r
+                    }\r
+                    mSelectedBoard = null;\r
+                    mFirstClickTime = 0;\r
+                }\r
+                else\r
+                {\r
+                    if (sender is StackPanel)\r
+                    {\r
+                        StackPanel sp = (StackPanel)sender;\r
+                        if (sp.Tag is NTBoard)\r
+                        {\r
+                            mSelectedBoard = (NTBoard)sp.Tag;\r
+                            mFirstClickTime = dt.Second * 1000 + dt.Millisecond;\r
+                        }\r
+                    }\r
+                }\r
+            }\r
+        }\r
+\r
+        void threadTab_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)\r
+        {\r
+            NTDebug.l("Entering MouseDown");\r
+            if (mSelectedThreadTitle == null)\r
+            {\r
+                if (sender is StackPanel)\r
+                {\r
+                    StackPanel sp = (StackPanel)sender;\r
+                    if (sp.Tag is NTThreadTitle)\r
+                    {\r
+                        mSelectedThreadTitle = (NTThreadTitle)sp.Tag;\r
+                        DateTime dt = DateTime.Now;\r
+                        mFirstClickTime = dt.Second * 1000 + dt.Millisecond;\r
+                    }\r
+                }\r
+            }\r
+            else\r
+            {\r
+                DateTime dt = DateTime.Now;\r
+                int clickTime = dt.Second * 1000 + dt.Millisecond;\r
+                clickTime -= mFirstClickTime;\r
+                if (clickTime <= mDoubleCickTime)\r
+                {\r
+                    if (sender is StackPanel)\r
+                    {\r
+                        StackPanel sp = (StackPanel)sender;\r
+                        if (sp.Tag is NTThreadTitle)\r
+                        {\r
+                            if (mSelectedThreadTitle.Equals(sp.Tag))\r
+                            {\r
+                                NTDebug.l("Dbl Clicked!");\r
+                                //UpdateBoardTabItem(mSelectedBoard);\r
+                                //updateResViewTabItem(mSelectedThreadTitle);\r
+                            }\r
+                        }\r
+                    }\r
+                    mSelectedThreadTitle = null;\r
+                    mFirstClickTime = 0;\r
+                }\r
+                else\r
+                {\r
+                    if (sender is StackPanel)\r
+                    {\r
+                        StackPanel sp = (StackPanel)sender;\r
+                        if (sp.Tag is NTThreadTitle)\r
+                        {\r
+                            mSelectedThreadTitle = (NTThreadTitle)sp.Tag;\r
+                            mFirstClickTime = dt.Second * 1000 + dt.Millisecond;\r
+                        }\r
+                    }\r
+                }\r
+            }\r
+        }\r
+\r
+        public NTThreadTitle findSelectedThreadTitle()\r
+        {\r
+            object o = tabCtrlDat.SelectedItem;\r
+            TabItem item = o as TabItem;\r
+            if(item == null)\r
+                return null;\r
+\r
+            NTDebug.l(item.Header.ToString());\r
+            object o2 = item.Tag;\r
+            NTThreadTitle thread = o2 as NTThreadTitle;\r
+            return thread;\r
+\r
+        }\r
+#endif\r
+\r
+\r
+        void storeOpenedBoardList()\r
+        {\r
+            List<IBoard> boardList = mSubjectPanel.QueryOpenedBoardList();\r
+            if (boardList == null)\r
+                return;\r
+            int cnt = boardList.Count;\r
+            string[] list = new string[cnt];\r
+            for (int i = 0; i < cnt; i++)\r
+            {\r
+                list[i] = boardList[i].getName();\r
+            }\r
+            \r
+            /*int cnt = tabCtrlSubject.Items.Count;\r
+            string[] list = new string[cnt];\r
+            for (int i = 0; i < cnt; i++)\r
+            {\r
+                object o = tabCtrlSubject.Items[i];\r
+\r
+                if (!(o is TabItem))\r
+                    return;\r
+                if (!((((TabItem)o).Tag) is NTBoard))\r
+                    return;\r
+\r
+                NTBoard b = (NTBoard)(((TabItem)o).Tag);\r
+                list[i] = b.mName;\r
+\r
+            }*/\r
+            NTPersistentFileAccess.storeOpenedBoards(list);\r
+\r
+        }\r
+#if false\r
+        void storeOpenedThreadList()\r
+        {\r
+\r
+            int cnt = tabCtrlDat.Items.Count;\r
+            string[] list = new string[cnt];\r
+            for (int i = 0; i < cnt; i++)\r
+            {\r
+                object o = tabCtrlDat.Items[i];\r
+\r
+                if (!(o is TabItem))\r
+                    return;\r
+                if (!((((TabItem)o).Tag) is NTThreadTitle))\r
+                    return;\r
+\r
+                NTThreadTitle tt = (NTThreadTitle)(((TabItem)o).Tag);\r
+                list[i] =tt.mDat + "," + tt.mBoard.mName;\r
+\r
+            }\r
+            NTPersistentFileAccess.storeOpenedThreads(list);\r
+\r
+        }\r
+\r
+\r
+        int searchBoardFromTabItemIndex(NTBoard board)\r
+        {\r
+            for (int i = 0; i < tabCtrlSubject.Items.Count; i++)\r
+            {\r
+                object o = tabCtrlSubject.Items[i];\r
+\r
+                if (!(o is TabItem))\r
+                    continue;\r
+                if (!((((TabItem)o).Tag) is NTBoard))\r
+                    continue;\r
+\r
+                NTBoard b = (NTBoard)(((TabItem)o).Tag);\r
+\r
+                if (board.mName.Equals(b.mName))\r
+                    return i;\r
+            }\r
+            return -1;\r
+        }\r
+\r
+        int searchTabItemIndexFromTabCtrl(TabControl ctrl, TabItem item)\r
+        {\r
+            for (int i = 0; i < ctrl.Items.Count; i++)\r
+            {\r
+                if (item.Equals(tabCtrlDat.Items[i]))\r
+                    return i;\r
+            }\r
+            return -1;\r
+        }\r
+\r
+        TabItem searchBoardFromTabItem(NTBoard board)\r
+        {\r
+            int idex = searchBoardFromTabItemIndex(board);\r
+            if (idex < 0)\r
+                return null;\r
+\r
+            return  tabCtrlSubject.Items[idex] as TabItem;\r
+        }\r
+#endif\r
+\r
+        int searchThreadFromTabItems(NTThreadTitle thread)\r
+        {\r
+#if false\r
+            for (int i = 0; i < tabCtrlDat.Items.Count; i++)\r
+            {\r
+                object o = tabCtrlDat.Items[i];\r
+\r
+                if (!(o is TabItem))\r
+                    continue;\r
+                if (!((((TabItem)o).Tag) is NTThreadTitle))\r
+                    continue;\r
+\r
+                NTThreadTitle tt = (NTThreadTitle)(((TabItem)o).Tag);\r
+\r
+                if (thread.Title.Equals(tt.Title))\r
+                    return i;\r
+            }\r
+#endif\r
+            return -1;\r
+        }\r
+#if false\r
+        public void removeThreadFromTabCtrl(NTThreadTitle tt)\r
+        {\r
+\r
+            int idx = searchThreadFromTabItems(tt);\r
+            if (idx < 0)\r
+                return;\r
+\r
+            tabCtrlDat.Items.RemoveAt(idx);\r
+\r
+            int cnt = tabCtrlDat.Items.Count;\r
+            if (cnt > 0)\r
+            {\r
+                if (tabCtrlDat.SelectedIndex < 0)\r
+                {\r
+                    tabCtrlDat.SelectedIndex = cnt - 1;\r
+                }\r
+                else\r
+                {\r
+                    TabItem item = tabCtrlDat.SelectedItem as TabItem;\r
+                    if (item == null)\r
+                        return;\r
+\r
+                    if (item.Content == null)\r
+                        constructResContent(item);\r
+\r
+\r
+                }\r
+            }\r
+\r
+        }\r
+#endif\r
+        public static ScrollViewer findScrollViewer(FlowDocumentScrollViewer flowDocumentScrollViewer)\r
+        {\r
+            if (VisualTreeHelper.GetChildrenCount(flowDocumentScrollViewer) == 0)\r
+            {\r
+                return null;\r
+            }\r
+\r
+            // Border is the first child of first child of a ScrolldocumentViewer \r
+            DependencyObject firstChild = VisualTreeHelper.GetChild(flowDocumentScrollViewer, 0);\r
+            if (firstChild == null)\r
+            {\r
+                return null;\r
+            }\r
+\r
+            Decorator border = VisualTreeHelper.GetChild(firstChild, 0) as Decorator;\r
+\r
+            if (border == null)\r
+            {\r
+                return null;\r
+            }\r
+\r
+            return border.Child as ScrollViewer;\r
+        } \r
+    }\r
+}\r
diff --git a/NT2chView45/MainWindow_toolbar_dragdrop.cs b/NT2chView45/MainWindow_toolbar_dragdrop.cs
new file mode 100755 (executable)
index 0000000..f0ff6de
--- /dev/null
@@ -0,0 +1,287 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Windows;\r
+using System.Windows.Controls;\r
+using System.Windows.Input;\r
+using System.Windows.Media;\r
+using NT2chView.NtUI;\r
+\r
+namespace NT2chView\r
+{\r
+    partial class MainWindow\r
+    {\r
+        private void hideAllToolbarDropCanvas()\r
+        {\r
+            mThreadTitleViewLHSDragCanvas.Visibility = System.Windows.Visibility.Collapsed;\r
+            mThreadTitleViewRHSDragCanvas.Visibility = System.Windows.Visibility.Collapsed;\r
+            mLHSDragCanvas.Visibility = System.Windows.Visibility.Collapsed;\r
+            mRHSDragCanvas.Visibility = System.Windows.Visibility.Collapsed;\r
+        }\r
+\r
+        private void mLHSDragCanvas_DragEnter(object sender, DragEventArgs e)\r
+        {\r
+            if (validateResViewToolbarDropData(e))\r
+                mLHSDragCanvas.Background = (Brush)TryFindResource("lhsDragBrush");\r
+        }\r
+\r
+        private void mLHSDragCanvas_DragLeave(object sender, DragEventArgs e)\r
+        {\r
+            mLHSDragCanvas.Background = (Brush)TryFindResource("lhsDragOrgBrush");\r
+        }\r
+\r
+        private void mLHSDragCanvas_DragOver(object sender, DragEventArgs e)\r
+        {\r
+            if (validateResViewToolbarDropData(e))\r
+                mLHSDragCanvas.Background = (Brush)TryFindResource("lhsDragBrush");\r
+        }\r
+\r
+        private void mLHSDragCanvas_Drop(object sender, DragEventArgs e)\r
+        {\r
+            mLHSDragCanvas.Background = (Brush)TryFindResource("lhsDragOrgBrush");\r
+            if (validateResViewToolbarDropData(e))\r
+            {\r
+                mTooltrayResView.SetValue(DockPanel.DockProperty, Dock.Left);\r
+                NTUserPreference.ResViewToolbarPosition = NTDragDrop.TOOLBAR_LOCATION_LEFT;\r
+            }\r
+            hideAllToolbarDropCanvas();\r
+        }\r
+\r
+        private void mRHSDragCanvas_DragEnter(object sender, DragEventArgs e)\r
+        {\r
+            if (validateResViewToolbarDropData(e))\r
+                mRHSDragCanvas.Background = (Brush)TryFindResource("rhsDragBrush");\r
+        }\r
+\r
+        private void mRHSDragCanvas_DragLeave(object sender, DragEventArgs e)\r
+        {\r
+            mRHSDragCanvas.Background = (Brush)TryFindResource("rhsDragOrgBrush");\r
+        }\r
+\r
+        private void mRHSDragCanvas_DragOver(object sender, DragEventArgs e)\r
+        {\r
+            if (validateResViewToolbarDropData(e))\r
+                mRHSDragCanvas.Background = (Brush)TryFindResource("rhsDragBrush");\r
+        }\r
+\r
+        private void mRHSDragCanvas_Drop(object sender, DragEventArgs e)\r
+        {\r
+            mRHSDragCanvas.Background = (Brush)TryFindResource("rhsDragOrgBrush");\r
+            if (validateResViewToolbarDropData(e))\r
+            {\r
+                mTooltrayResView.SetValue(DockPanel.DockProperty, Dock.Right);\r
+                NTUserPreference.ResViewToolbarPosition = NTDragDrop.TOOLBAR_LOCATION_RIGHT;\r
+            }\r
+            hideAllToolbarDropCanvas();\r
+        }\r
+\r
+        bool validateResViewToolbarDropData(DragEventArgs e)\r
+        {\r
+            IDataObject data = e.Data;\r
+\r
+            if (!data.GetDataPresent(NTDragDrop.RES_VIEW_TOOLBAR_DRAG_FORMAT))\r
+            {\r
+                e.Effects = DragDropEffects.None;\r
+                return false;\r
+            }\r
+            else\r
+            {\r
+                e.Effects = DragDropEffects.Move;\r
+                e.Handled = true;\r
+                return true;\r
+            }\r
+        }\r
+\r
+\r
+        bool mResViewToolbarDragCapture = false;\r
+        Point mResViewPointCapture;\r
+\r
+        void startDrag()\r
+        {\r
+            NTDragDrop.ResViewToolbarData data = new NTDragDrop.ResViewToolbarData();\r
+            DataObject dObj = new DataObject(NTDragDrop.RES_VIEW_TOOLBAR_DRAG_FORMAT, data);\r
+            DragDrop.DoDragDrop(mToolbarResView, dObj, DragDropEffects.All);\r
+            hideAllToolbarDropCanvas();\r
+        }\r
+\r
+        private void mResViewToolHandle_MouseEnter(object sender, MouseEventArgs e)\r
+        {\r
+\r
+        }\r
+\r
+        private void mResViewToolHandle_MouseLeave(object sender, MouseEventArgs e)\r
+        {\r
+\r
+        }\r
+\r
+        private void mResViewToolHandle_MouseLeftBouttnDown(object sender, MouseButtonEventArgs e)\r
+        {\r
+            mResViewToolbarDragCapture = true;\r
+            mResViewPointCapture = e.GetPosition(mToolbarResView);\r
+\r
+        }\r
+\r
+        private void mResViewToolHandle_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)\r
+        {\r
+            mResViewToolbarDragCapture = false;\r
+\r
+        }\r
+\r
+        private void mResViewToolHandle_MouseMove(object sender, MouseEventArgs e)\r
+        {\r
+            if (!mResViewToolbarDragCapture)\r
+                return;\r
+            Point p = e.GetPosition(mToolbarResView);\r
+            Vector v = Point.Subtract(p, mResViewPointCapture);\r
+            if (v.Length > NTDragDrop.DRAG_START_MOVE_DELTA)\r
+            {\r
+                if (NTUserPreference.ResViewToolbarPosition\r
+                    == NTDragDrop.TOOLBAR_LOCATION_RIGHT)\r
+                {\r
+                    mLHSDragCanvas.Visibility = System.Windows.Visibility.Visible;\r
+                }\r
+                else\r
+                {\r
+                    mRHSDragCanvas.Visibility = System.Windows.Visibility.Visible;\r
+                }\r
+                startDrag();\r
+                e.Handled = true;\r
+                mResViewToolbarDragCapture = false;\r
+            }\r
+\r
+        }\r
+//----------------------------\r
+        private void mThreadTitleViewLHSDragCanvas_DragEnter(object sender, DragEventArgs e)\r
+        {\r
+            if (validateThreadTitleViewToolbarDropData(e))\r
+                mThreadTitleViewLHSDragCanvas.Background = (Brush)TryFindResource("lhsDragBrush");\r
+        }\r
+\r
+        private void mThreadTitleViewLHSDragCanvas_DragLeave(object sender, DragEventArgs e)\r
+        {\r
+            mThreadTitleViewLHSDragCanvas.Background = (Brush)TryFindResource("lhsDragOrgBrush");\r
+        }\r
+\r
+        private void mThreadTitleViewLHSDragCanvas_DragOver(object sender, DragEventArgs e)\r
+        {\r
+            if (validateThreadTitleViewToolbarDropData(e))\r
+                mThreadTitleViewLHSDragCanvas.Background = (Brush)TryFindResource("lhsDragBrush");\r
+        }\r
+\r
+        private void mThreadTitleViewLHSDragCanvas_Drop(object sender, DragEventArgs e)\r
+        {\r
+            mThreadTitleViewLHSDragCanvas.Background = (Brush)TryFindResource("lhsDragOrgBrush");\r
+            if (validateThreadTitleViewToolbarDropData(e))\r
+            {\r
+                mTooltrayThreadTitleView.SetValue(DockPanel.DockProperty, Dock.Left);\r
+                NTUserPreference.ThreadTitleViewToolbarPosition = NTDragDrop.TOOLBAR_LOCATION_LEFT;\r
+            }\r
+            hideAllToolbarDropCanvas();\r
+        }\r
+\r
+        private void mThreadTitleViewRHSDragCanvas_DragEnter(object sender, DragEventArgs e)\r
+        {\r
+            if (validateThreadTitleViewToolbarDropData(e))\r
+                mThreadTitleViewRHSDragCanvas.Background = (Brush)TryFindResource("rhsDragBrush");\r
+        }\r
+\r
+        private void mThreadTitleViewRHSDragCanvas_DragLeave(object sender, DragEventArgs e)\r
+        {\r
+            mThreadTitleViewRHSDragCanvas.Background = (Brush)TryFindResource("rhsDragOrgBrush");\r
+        }\r
+\r
+        private void mThreadTitleViewRHSDragCanvas_DragOver(object sender, DragEventArgs e)\r
+        {\r
+            if (validateThreadTitleViewToolbarDropData(e))\r
+                mThreadTitleViewRHSDragCanvas.Background = (Brush)TryFindResource("rhsDragBrush");\r
+        }\r
+\r
+        private void mThreadTitleViewRHSDragCanvas_Drop(object sender, DragEventArgs e)\r
+        {\r
+            mThreadTitleViewRHSDragCanvas.Background = (Brush)TryFindResource("rhsDragOrgBrush");\r
+            if (validateThreadTitleViewToolbarDropData(e))\r
+            {\r
+                mTooltrayThreadTitleView.SetValue(DockPanel.DockProperty, Dock.Right);\r
+                NTUserPreference.ThreadTitleViewToolbarPosition = NTDragDrop.TOOLBAR_LOCATION_RIGHT;\r
+            }\r
+            hideAllToolbarDropCanvas();\r
+        }\r
+\r
+        bool validateThreadTitleViewToolbarDropData(DragEventArgs e)\r
+        {\r
+            IDataObject data = e.Data;\r
+\r
+            if (!data.GetDataPresent(NTDragDrop.THREADTITLE_VIEW_TOOLBAR_DRAG_FORMAT))\r
+            {\r
+                e.Effects = DragDropEffects.None;\r
+                return false;\r
+            }\r
+            else\r
+            {\r
+                e.Effects = DragDropEffects.Move;\r
+                e.Handled = true;\r
+                return true;\r
+            }\r
+        }\r
+\r
+\r
+        bool mThreadTitleViewToolbarDragCapture = false;\r
+        Point mThreadTitleViewPointCapture;\r
+\r
+        void startDrag2()\r
+        {\r
+            NTDragDrop.ThreadTitleToolbarData data = new NTDragDrop.ThreadTitleToolbarData();\r
+            DataObject dObj = new DataObject(NTDragDrop.THREADTITLE_VIEW_TOOLBAR_DRAG_FORMAT, data);\r
+            DragDrop.DoDragDrop(mToolbarThreadTitleView, dObj, DragDropEffects.All);\r
+            hideAllToolbarDropCanvas();\r
+        }\r
+\r
+        private void mThreadTitleViewToolHandle_MouseEnter(object sender, MouseEventArgs e)\r
+        {\r
+\r
+        }\r
+\r
+        private void mThreadTitleViewToolHandle_MouseLeave(object sender, MouseEventArgs e)\r
+        {\r
+\r
+        }\r
+\r
+        private void mThreadTitleViewToolHandle_MouseLeftBouttnDown(object sender, MouseButtonEventArgs e)\r
+        {\r
+            mThreadTitleViewToolbarDragCapture = true;\r
+            mThreadTitleViewPointCapture = e.GetPosition(mToolbarThreadTitleView);\r
+\r
+        }\r
+\r
+        private void mThreadTitleViewToolHandle_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)\r
+        {\r
+            mThreadTitleViewToolbarDragCapture = false;\r
+\r
+        }\r
+\r
+        private void mThreadTitleViewToolHandle_MouseMove(object sender, MouseEventArgs e)\r
+        {\r
+            if (!mThreadTitleViewToolbarDragCapture)\r
+                return;\r
+            Point p = e.GetPosition(mToolbarThreadTitleView);\r
+            Vector v = Point.Subtract(p, mThreadTitleViewPointCapture);\r
+            if (v.Length > NTDragDrop.DRAG_START_MOVE_DELTA)\r
+            {\r
+                if (NTUserPreference.ThreadTitleViewToolbarPosition\r
+                    == NTDragDrop.TOOLBAR_LOCATION_RIGHT)\r
+                {\r
+                    mThreadTitleViewLHSDragCanvas.Visibility = System.Windows.Visibility.Visible;\r
+                }\r
+                else\r
+                {\r
+                    mThreadTitleViewRHSDragCanvas.Visibility = System.Windows.Visibility.Visible;\r
+                }\r
+                startDrag2();\r
+                e.Handled = true;\r
+                mThreadTitleViewToolbarDragCapture = false;\r
+            }\r
+\r
+        }\r
+\r
+    }\r
+}\r
diff --git a/NT2chView45/NT2chView.csproj b/NT2chView45/NT2chView.csproj
new file mode 100755 (executable)
index 0000000..0289635
--- /dev/null
@@ -0,0 +1,272 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+  <PropertyGroup>\r
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>\r
+    <Platform Condition=" '$(Platform)' == '' ">x86</Platform>\r
+    <ProductVersion>8.0.30703</ProductVersion>\r
+    <SchemaVersion>2.0</SchemaVersion>\r
+    <ProjectGuid>{2F22FF46-4990-4FA0-ACBA-B53F0C5CF179}</ProjectGuid>\r
+    <OutputType>WinExe</OutputType>\r
+    <AppDesignerFolder>Properties</AppDesignerFolder>\r
+    <RootNamespace>NT2chView</RootNamespace>\r
+    <AssemblyName>NT2chView</AssemblyName>\r
+    <TargetFrameworkVersion>v3.0</TargetFrameworkVersion>\r
+    <FileAlignment>512</FileAlignment>\r
+    <ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>\r
+    <WarningLevel>4</WarningLevel>\r
+    <IsWebBootstrapper>false</IsWebBootstrapper>\r
+    <TargetFrameworkProfile />\r
+    <PublishUrl>publish\</PublishUrl>\r
+    <Install>true</Install>\r
+    <InstallFrom>Disk</InstallFrom>\r
+    <UpdateEnabled>false</UpdateEnabled>\r
+    <UpdateMode>Foreground</UpdateMode>\r
+    <UpdateInterval>7</UpdateInterval>\r
+    <UpdateIntervalUnits>Days</UpdateIntervalUnits>\r
+    <UpdatePeriodically>false</UpdatePeriodically>\r
+    <UpdateRequired>false</UpdateRequired>\r
+    <MapFileExtensions>true</MapFileExtensions>\r
+    <ApplicationRevision>0</ApplicationRevision>\r
+    <ApplicationVersion>0.1.0.0</ApplicationVersion>\r
+    <UseApplicationTrust>false</UseApplicationTrust>\r
+    <BootstrapperEnabled>true</BootstrapperEnabled>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">\r
+    <PlatformTarget>x86</PlatformTarget>\r
+    <DebugSymbols>true</DebugSymbols>\r
+    <DebugType>full</DebugType>\r
+    <Optimize>false</Optimize>\r
+    <OutputPath>bin\Debug\</OutputPath>\r
+    <DefineConstants>DEBUG;TRACE</DefineConstants>\r
+    <ErrorReport>prompt</ErrorReport>\r
+    <WarningLevel>4</WarningLevel>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">\r
+    <PlatformTarget>x86</PlatformTarget>\r
+    <DebugType>pdbonly</DebugType>\r
+    <Optimize>true</Optimize>\r
+    <OutputPath>bin\Release\</OutputPath>\r
+    <DefineConstants>TRACE</DefineConstants>\r
+    <ErrorReport>prompt</ErrorReport>\r
+    <WarningLevel>4</WarningLevel>\r
+  </PropertyGroup>\r
+  <PropertyGroup>\r
+    <ApplicationIcon>favicon.ico</ApplicationIcon>\r
+  </PropertyGroup>\r
+  <PropertyGroup>\r
+    <NoWin32Manifest>true</NoWin32Manifest>\r
+  </PropertyGroup>\r
+  <ItemGroup>\r
+    <Reference Include="System" />\r
+    <Reference Include="System.Data" />\r
+    <Reference Include="System.Web" />\r
+    <Reference Include="System.Windows.Forms" />\r
+    <Reference Include="System.Xml" />\r
+    <Reference Include="WindowsBase" />\r
+    <Reference Include="PresentationCore" />\r
+    <Reference Include="PresentationFramework" />\r
+    <Reference Include="WPFToolkit, Version=3.5.40128.1, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ApplicationDefinition Include="App.xaml">\r
+      <Generator>MSBuild:Compile</Generator>\r
+      <SubType>Designer</SubType>\r
+    </ApplicationDefinition>\r
+    <Page Include="Dictionary1.xaml">\r
+      <SubType>Designer</SubType>\r
+      <Generator>MSBuild:Compile</Generator>\r
+    </Page>\r
+    <Page Include="Dictionary2.xaml">\r
+      <SubType>Designer</SubType>\r
+      <Generator>MSBuild:Compile</Generator>\r
+    </Page>\r
+    <Page Include="MainWindow.xaml">\r
+      <Generator>MSBuild:Compile</Generator>\r
+      <SubType>Designer</SubType>\r
+    </Page>\r
+    <Compile Include="App.xaml.cs">\r
+      <DependentUpon>App.xaml</DependentUpon>\r
+      <SubType>Code</SubType>\r
+    </Compile>\r
+    <Compile Include="MainWindow.xaml.cs">\r
+      <DependentUpon>MainWindow.xaml</DependentUpon>\r
+      <SubType>Code</SubType>\r
+    </Compile>\r
+    <Page Include="NTBoardPanel.xaml">\r
+      <SubType>Designer</SubType>\r
+      <Generator>MSBuild:Compile</Generator>\r
+    </Page>\r
+    <Page Include="NTCategoryPanel.xaml">\r
+      <SubType>Designer</SubType>\r
+      <Generator>MSBuild:Compile</Generator>\r
+    </Page>\r
+    <Page Include="NTCreateThreadWindow.xaml">\r
+      <SubType>Designer</SubType>\r
+      <Generator>MSBuild:Compile</Generator>\r
+    </Page>\r
+    <Page Include="NTFavoritePanel.xaml">\r
+      <SubType>Designer</SubType>\r
+      <Generator>MSBuild:Compile</Generator>\r
+    </Page>\r
+    <Page Include="NTFontSelectDialog.xaml">\r
+      <SubType>Designer</SubType>\r
+      <Generator>MSBuild:Compile</Generator>\r
+    </Page>\r
+    <Page Include="NTSetupWindow.xaml">\r
+      <SubType>Designer</SubType>\r
+      <Generator>MSBuild:Compile</Generator>\r
+    </Page>\r
+    <Page Include="NTWriteResResultWindow.xaml">\r
+      <SubType>Designer</SubType>\r
+      <Generator>MSBuild:Compile</Generator>\r
+    </Page>\r
+    <Page Include="NTWriteResWindow.xaml">\r
+      <SubType>Designer</SubType>\r
+      <Generator>MSBuild:Compile</Generator>\r
+    </Page>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <Compile Include="MainWindow_backgroudworker.cs" />\r
+    <Compile Include="MainWindow_ctrl_event_handler.cs" />\r
+    <Compile Include="MainWindow_delegates.cs" />\r
+    <Compile Include="MainWindow_manipulate_ctrl.cs" />\r
+    <Compile Include="NTAllboardSearch.cs" />\r
+    <Compile Include="NTAppState.cs" />\r
+    <Compile Include="NTAsciiArt.cs" />\r
+    <Compile Include="NTBoard.cs" />\r
+    <Compile Include="NTBoardPanel.xaml.cs">\r
+      <DependentUpon>NTBoardPanel.xaml</DependentUpon>\r
+    </Compile>\r
+    <Compile Include="NTBoard_backgroundworker.cs" />\r
+    <Compile Include="NTCategory.cs" />\r
+    <Compile Include="NTCategoryPanel.xaml.cs">\r
+      <DependentUpon>NTCategoryPanel.xaml</DependentUpon>\r
+    </Compile>\r
+    <Compile Include="NTCloud.cs" />\r
+    <Compile Include="NTCookie.cs" />\r
+    <Compile Include="NTCreateThreadWindow.xaml.cs">\r
+      <DependentUpon>NTCreateThreadWindow.xaml</DependentUpon>\r
+    </Compile>\r
+    <Compile Include="NTDataRoot.cs" />\r
+    <Compile Include="NTDebug.cs" />\r
+    <Compile Include="NTDragDrop.cs" />\r
+    <Compile Include="NTFavorite.cs" />\r
+    <Compile Include="NTFavoritePanel.xaml.cs">\r
+      <DependentUpon>NTFavoritePanel.xaml</DependentUpon>\r
+    </Compile>\r
+    <Compile Include="NTFavoriteThread.cs" />\r
+    <Compile Include="NTFileAccess.cs" />\r
+    <Compile Include="NTFontSelectDialog.xaml.cs">\r
+      <DependentUpon>NTFontSelectDialog.xaml</DependentUpon>\r
+    </Compile>\r
+    <Compile Include="NTFontUtil.cs" />\r
+    <Compile Include="NTHtmlParser.cs" />\r
+    <Compile Include="NTHtmlUtils.cs" />\r
+    <Compile Include="NTHtmlUtils_EscapeTable.cs" />\r
+    <Compile Include="NTHtmlWriteResParser.cs" />\r
+    <Compile Include="NTHttpAccess.cs" />\r
+    <Compile Include="NTHttpAccess_cloud.cs" />\r
+    <Compile Include="NTHttpAccess_util.cs" />\r
+    <Compile Include="NTHttpUtils.cs" />\r
+    <Compile Include="NTMaru.cs" />\r
+    <Compile Include="NTMenuCommand.cs" />\r
+    <Compile Include="NTNgItems.cs" />\r
+    <Compile Include="NTPersistentFileAccess.cs" />\r
+    <Compile Include="NTRelatedResPopup.cs" />\r
+    <Compile Include="NTRes.cs" />\r
+    <Compile Include="NTResMenuCommand.cs" />\r
+    <Compile Include="NTResPopupMenu.cs" />\r
+    <Compile Include="NTSetupWindow.xaml.cs">\r
+      <DependentUpon>NTSetupWindow.xaml</DependentUpon>\r
+    </Compile>\r
+    <Compile Include="NTSimString.cs" />\r
+    <Compile Include="NTTextFormat.cs" />\r
+    <Compile Include="NTTextUtiles.cs" />\r
+    <Compile Include="NTThreadTitle.cs" />\r
+    <Compile Include="NTThreadTitlePopupMenu.cs" />\r
+    <Compile Include="NTUserPreference.cs" />\r
+    <Compile Include="NTVagueSearchWord.cs" />\r
+    <Compile Include="NTWriteResHistoryPopup.cs" />\r
+    <Compile Include="NTWriteResResultWindow.xaml.cs">\r
+      <DependentUpon>NTWriteResResultWindow.xaml</DependentUpon>\r
+    </Compile>\r
+    <Compile Include="NTWriteResWindow.xaml.cs">\r
+      <DependentUpon>NTWriteResWindow.xaml</DependentUpon>\r
+    </Compile>\r
+    <Compile Include="Properties\AssemblyInfo.cs">\r
+      <SubType>Code</SubType>\r
+    </Compile>\r
+    <Compile Include="Properties\Resources.Designer.cs">\r
+      <AutoGen>True</AutoGen>\r
+      <DesignTime>True</DesignTime>\r
+      <DependentUpon>Resources.resx</DependentUpon>\r
+    </Compile>\r
+    <Compile Include="Properties\Settings.Designer.cs">\r
+      <AutoGen>True</AutoGen>\r
+      <DependentUpon>Settings.settings</DependentUpon>\r
+      <DesignTimeSharedInput>True</DesignTimeSharedInput>\r
+    </Compile>\r
+    <EmbeddedResource Include="Properties\Resources.resx">\r
+      <Generator>ResXFileCodeGenerator</Generator>\r
+      <LastGenOutput>Resources.Designer.cs</LastGenOutput>\r
+    </EmbeddedResource>\r
+    <None Include="app.config" />\r
+    <None Include="Properties\Settings.settings">\r
+      <Generator>SettingsSingleFileGenerator</Generator>\r
+      <LastGenOutput>Settings.Designer.cs</LastGenOutput>\r
+    </None>\r
+    <AppDesigner Include="Properties\" />\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <Resource Include="images\back_btn.png" />\r
+    <Resource Include="images\down.png" />\r
+    <Resource Include="images\exit_btn.png" />\r
+    <Resource Include="images\home_btn.png" />\r
+    <Resource Include="images\jmp_to_new.png" />\r
+    <Resource Include="images\left.png" />\r
+    <Resource Include="images\neetchan2.png" />\r
+    <Resource Include="images\right.png" />\r
+    <Resource Include="images\search_btn.png" />\r
+    <Resource Include="images\tag.png" />\r
+    <Resource Include="images\tag_btn.png" />\r
+    <Resource Include="images\to_the_bottom.png" />\r
+    <Resource Include="images\to_the_top.png" />\r
+    <Resource Include="images\up.png" />\r
+    <Resource Include="images\update_btn.png" />\r
+    <Resource Include="images\write_btn.png" />\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <Resource Include="images\close_tab.png" />\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <BootstrapperPackage Include="Microsoft.Net.Client.3.5">\r
+      <Visible>False</Visible>\r
+      <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>\r
+      <Install>false</Install>\r
+    </BootstrapperPackage>\r
+    <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">\r
+      <Visible>False</Visible>\r
+      <ProductName>.NET Framework 3.5 SP1</ProductName>\r
+      <Install>true</Install>\r
+    </BootstrapperPackage>\r
+    <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">\r
+      <Visible>False</Visible>\r
+      <ProductName>Windows インストーラー 3.1</ProductName>\r
+      <Install>true</Install>\r
+    </BootstrapperPackage>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <Resource Include="images\setup_btn.png" />\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <Resource Include="favicon.ico" />\r
+  </ItemGroup>\r
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />\r
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. \r
+       Other similar extension points exist, see Microsoft.Common.targets.\r
+  <Target Name="BeforeBuild">\r
+  </Target>\r
+  <Target Name="AfterBuild">\r
+  </Target>\r
+  -->\r
+</Project>
\ No newline at end of file
diff --git a/NT2chView45/NT2chView.csproj.user b/NT2chView45/NT2chView.csproj.user
new file mode 100755 (executable)
index 0000000..709b98e
--- /dev/null
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+  <PropertyGroup>\r
+    <PublishUrlHistory>publish\</PublishUrlHistory>\r
+    <InstallUrlHistory />\r
+    <SupportUrlHistory />\r
+    <UpdateUrlHistory />\r
+    <BootstrapperUrlHistory />\r
+    <ErrorReportUrlHistory />\r
+    <FallbackCulture>ja-JP</FallbackCulture>\r
+    <VerifyUploadedFiles>false</VerifyUploadedFiles>\r
+  </PropertyGroup>\r
+</Project>
\ No newline at end of file
diff --git a/NT2chView45/NT2chView45.csproj b/NT2chView45/NT2chView45.csproj
new file mode 100755 (executable)
index 0000000..f72e0aa
--- /dev/null
@@ -0,0 +1,332 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />\r
+  <PropertyGroup>\r
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>\r
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>\r
+    <ProjectGuid>{197BD61C-EC0B-44AF-9531-01999F437EB2}</ProjectGuid>\r
+    <OutputType>WinExe</OutputType>\r
+    <AppDesignerFolder>Properties</AppDesignerFolder>\r
+    <RootNamespace>NT2chView</RootNamespace>\r
+    <AssemblyName>NT2chView45</AssemblyName>\r
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>\r
+    <FileAlignment>512</FileAlignment>\r
+    <ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>\r
+    <WarningLevel>4</WarningLevel>\r
+    <TargetFrameworkProfile />\r
+    <PublishUrl>publish\</PublishUrl>\r
+    <Install>true</Install>\r
+    <InstallFrom>Disk</InstallFrom>\r
+    <UpdateEnabled>false</UpdateEnabled>\r
+    <UpdateMode>Foreground</UpdateMode>\r
+    <UpdateInterval>7</UpdateInterval>\r
+    <UpdateIntervalUnits>Days</UpdateIntervalUnits>\r
+    <UpdatePeriodically>false</UpdatePeriodically>\r
+    <UpdateRequired>false</UpdateRequired>\r
+    <MapFileExtensions>true</MapFileExtensions>\r
+    <ApplicationRevision>0</ApplicationRevision>\r
+    <ApplicationVersion>1.0.0.%2a</ApplicationVersion>\r
+    <IsWebBootstrapper>false</IsWebBootstrapper>\r
+    <UseApplicationTrust>false</UseApplicationTrust>\r
+    <BootstrapperEnabled>true</BootstrapperEnabled>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">\r
+    <PlatformTarget>AnyCPU</PlatformTarget>\r
+    <DebugSymbols>true</DebugSymbols>\r
+    <DebugType>full</DebugType>\r
+    <Optimize>false</Optimize>\r
+    <OutputPath>bin\Debug\</OutputPath>\r
+    <DefineConstants>TRACE;DEBUG;DOTNET45</DefineConstants>\r
+    <ErrorReport>prompt</ErrorReport>\r
+    <WarningLevel>4</WarningLevel>\r
+    <Prefer32Bit>false</Prefer32Bit>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">\r
+    <PlatformTarget>AnyCPU</PlatformTarget>\r
+    <DebugType>pdbonly</DebugType>\r
+    <Optimize>true</Optimize>\r
+    <OutputPath>bin\Release\</OutputPath>\r
+    <DefineConstants>TRACE;DOTNET45</DefineConstants>\r
+    <ErrorReport>prompt</ErrorReport>\r
+    <WarningLevel>4</WarningLevel>\r
+    <Prefer32Bit>false</Prefer32Bit>\r
+  </PropertyGroup>\r
+  <PropertyGroup>\r
+    <ApplicationIcon>neetchan6.ico</ApplicationIcon>\r
+  </PropertyGroup>\r
+  <PropertyGroup>\r
+    <SignAssembly>false</SignAssembly>\r
+  </PropertyGroup>\r
+  <PropertyGroup>\r
+    <AssemblyOriginatorKeyFile>\r
+    </AssemblyOriginatorKeyFile>\r
+  </PropertyGroup>\r
+  <PropertyGroup>\r
+    <SignManifests>false</SignManifests>\r
+  </PropertyGroup>\r
+  <ItemGroup>\r
+    <Reference Include="System" />\r
+    <Reference Include="System.Data" />\r
+    <Reference Include="System.Drawing" />\r
+    <Reference Include="System.Web" />\r
+    <Reference Include="System.Windows.Forms" />\r
+    <Reference Include="System.Xaml" />\r
+    <Reference Include="System.Xml" />\r
+    <Reference Include="UIAutomationProvider" />\r
+    <Reference Include="WindowsBase" />\r
+    <Reference Include="PresentationCore" />\r
+    <Reference Include="PresentationFramework" />\r
+    <Reference Include="WindowsFormsIntegration" />\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ApplicationDefinition Include="App.xaml">\r
+      <Generator>MSBuild:Compile</Generator>\r
+      <SubType>Designer</SubType>\r
+    </ApplicationDefinition>\r
+    <Page Include="MainWindow.xaml">\r
+      <Generator>MSBuild:Compile</Generator>\r
+      <SubType>Designer</SubType>\r
+    </Page>\r
+    <Compile Include="App.xaml.cs">\r
+      <DependentUpon>App.xaml</DependentUpon>\r
+      <SubType>Code</SubType>\r
+    </Compile>\r
+    <Compile Include="MainWindow.xaml.cs">\r
+      <DependentUpon>MainWindow.xaml</DependentUpon>\r
+      <SubType>Code</SubType>\r
+    </Compile>\r
+    <Page Include="NTBoardPanel.xaml">\r
+      <Generator>MSBuild:Compile</Generator>\r
+      <SubType>Designer</SubType>\r
+    </Page>\r
+    <Page Include="NTCategoryPanel.xaml">\r
+      <Generator>MSBuild:Compile</Generator>\r
+      <SubType>Designer</SubType>\r
+    </Page>\r
+    <Page Include="NTCreateThreadWindow.xaml">\r
+      <Generator>MSBuild:Compile</Generator>\r
+      <SubType>Designer</SubType>\r
+    </Page>\r
+    <Page Include="NTFavoritePanel.xaml">\r
+      <Generator>MSBuild:Compile</Generator>\r
+      <SubType>Designer</SubType>\r
+    </Page>\r
+    <Page Include="NTFavoriteTagEditWindow.xaml">\r
+      <Generator>MSBuild:Compile</Generator>\r
+      <SubType>Designer</SubType>\r
+    </Page>\r
+    <Page Include="NTFontSelectDialog.xaml">\r
+      <Generator>MSBuild:Compile</Generator>\r
+      <SubType>Designer</SubType>\r
+    </Page>\r
+    <Page Include="NTGraphicsPanel.xaml">\r
+      <Generator>MSBuild:Compile</Generator>\r
+      <SubType>Designer</SubType>\r
+    </Page>\r
+    <Page Include="NTHistoryPanel.xaml">\r
+      <Generator>MSBuild:Compile</Generator>\r
+      <SubType>Designer</SubType>\r
+    </Page>\r
+    <Page Include="NTMoviePanel.xaml">\r
+      <SubType>Designer</SubType>\r
+      <Generator>MSBuild:Compile</Generator>\r
+    </Page>\r
+    <Page Include="NTSetupAESWindow.xaml">\r
+      <Generator>MSBuild:Compile</Generator>\r
+      <SubType>Designer</SubType>\r
+    </Page>\r
+    <Page Include="NTSetupWindow.xaml">\r
+      <Generator>MSBuild:Compile</Generator>\r
+      <SubType>Designer</SubType>\r
+    </Page>\r
+    <Page Include="NTThreadInfoWindow.xaml">\r
+      <SubType>Designer</SubType>\r
+      <Generator>MSBuild:Compile</Generator>\r
+    </Page>\r
+    <Page Include="NTWriteResResultWindow.xaml">\r
+      <Generator>MSBuild:Compile</Generator>\r
+      <SubType>Designer</SubType>\r
+    </Page>\r
+    <Page Include="NTWriteResWindow.xaml">\r
+      <Generator>MSBuild:Compile</Generator>\r
+      <SubType>Designer</SubType>\r
+    </Page>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <Compile Include="MainWindow_backgroudworker.cs" />\r
+    <Compile Include="MainWindow_ctrl_event_handler.cs" />\r
+    <Compile Include="MainWindow_delegates.cs" />\r
+    <Compile Include="MainWindow_manipulate_ctrl.cs" />\r
+    <Compile Include="MainWindow_toolbar_dragdrop.cs" />\r
+    <Compile Include="NTAllboardSearch.cs" />\r
+    <Compile Include="NTAppState.cs" />\r
+    <Compile Include="NTAsciiArt.cs" />\r
+    <Compile Include="NTBoard.cs" />\r
+    <Compile Include="NTBoardPanel.xaml.cs">\r
+      <DependentUpon>NTBoardPanel.xaml</DependentUpon>\r
+    </Compile>\r
+    <Compile Include="NTBoardPopupMenu.cs" />\r
+    <Compile Include="NTBoard_backgroundworker.cs" />\r
+    <Compile Include="NTCategory.cs" />\r
+    <Compile Include="NTCategoryPanel.xaml.cs">\r
+      <DependentUpon>NTCategoryPanel.xaml</DependentUpon>\r
+    </Compile>\r
+    <Compile Include="NtNet\NTCloud.cs" />\r
+    <Compile Include="NtNet\NTCookie.cs" />\r
+    <Compile Include="NTCreateThreadWindow.xaml.cs">\r
+      <DependentUpon>NTCreateThreadWindow.xaml</DependentUpon>\r
+    </Compile>\r
+    <Compile Include="NtNet\NTCrypt.cs" />\r
+    <Compile Include="NTDataRoot.cs" />\r
+    <Compile Include="NTDebug.cs" />\r
+    <Compile Include="NTDragDrop.cs" />\r
+    <Compile Include="NTExportUtil.cs" />\r
+    <Compile Include="NTFavorite.cs" />\r
+    <Compile Include="NTFavoriteBoard.cs" />\r
+    <Compile Include="NTFavoriteBoardPopupMenu.cs" />\r
+    <Compile Include="NTFavoritePanel.xaml.cs">\r
+      <DependentUpon>NTFavoritePanel.xaml</DependentUpon>\r
+    </Compile>\r
+    <Compile Include="NTFavoriteTagEditWindow.xaml.cs">\r
+      <DependentUpon>NTFavoriteTagEditWindow.xaml</DependentUpon>\r
+    </Compile>\r
+    <Compile Include="NTFavoriteThread.cs" />\r
+    <Compile Include="NTFavoriteThreadPopupMenu.cs" />\r
+    <Compile Include="NTFavoriteThreadTag.cs" />\r
+    <Compile Include="NTFavoriteThreadTagPopupMenu.cs" />\r
+    <Compile Include="NtFile\NTFileAccess.cs" />\r
+    <Compile Include="NtFile\NTFileUtil.cs" />\r
+    <Compile Include="NTFontSelectDialog.xaml.cs">\r
+      <DependentUpon>NTFontSelectDialog.xaml</DependentUpon>\r
+    </Compile>\r
+    <Compile Include="NTFontUtil.cs" />\r
+    <Compile Include="NTGraphicsPanel.xaml.cs">\r
+      <DependentUpon>NTGraphicsPanel.xaml</DependentUpon>\r
+    </Compile>\r
+    <Compile Include="NTHistory.cs" />\r
+    <Compile Include="NTHistoryPanel.xaml.cs">\r
+      <DependentUpon>NTHistoryPanel.xaml</DependentUpon>\r
+    </Compile>\r
+    <Compile Include="NTHistoryThread.cs" />\r
+    <Compile Include="NtHtml\NTHtmlParser.cs" />\r
+    <Compile Include="NtHtml\NTHtmlUtils.cs" />\r
+    <Compile Include="NtHtml\NTHtmlUtils_EscapeTable.cs" />\r
+    <Compile Include="NtHtml\NTHtmlWriteResParser.cs" />\r
+    <Compile Include="NtNet\NTHttpAccess.cs" />\r
+    <Compile Include="NtNet\NTHttpAccess_cloud.cs" />\r
+    <Compile Include="NtNet\NTHttpAccess_user_cloud.cs" />\r
+    <Compile Include="NtNet\NTHttpAccess_util.cs" />\r
+    <Compile Include="NtNet\NTHttpUtils.cs" />\r
+    <Compile Include="NTMaru.cs" />\r
+    <Compile Include="NTMenuCommand.cs" />\r
+    <Compile Include="NTMovieHistory.cs" />\r
+    <Compile Include="NTMovieHistoryPopup.cs" />\r
+    <Compile Include="NTMoviePanel.xaml.cs">\r
+      <DependentUpon>NTMoviePanel.xaml</DependentUpon>\r
+    </Compile>\r
+    <Compile Include="NTNgItems.cs" />\r
+    <Compile Include="NTOpenedThreadTable.cs" />\r
+    <Compile Include="NtFile\NTPersistentFileAccess.cs" />\r
+    <Compile Include="NTRes.cs" />\r
+    <Compile Include="NTResMenuCommand.cs" />\r
+    <Compile Include="NTResPopupMenu.cs" />\r
+    <Compile Include="NTSetupAESWindow.xaml.cs">\r
+      <DependentUpon>NTSetupAESWindow.xaml</DependentUpon>\r
+    </Compile>\r
+    <Compile Include="NTSetupWindow.xaml.cs">\r
+      <DependentUpon>NTSetupWindow.xaml</DependentUpon>\r
+    </Compile>\r
+    <Compile Include="NTSimString.cs" />\r
+    <Compile Include="NTTextFormat.cs" />\r
+    <Compile Include="NTTextUtiles.cs" />\r
+    <Compile Include="NTThreadCashData.cs" />\r
+    <Compile Include="NTThreadInfoWindow.xaml.cs">\r
+      <DependentUpon>NTThreadInfoWindow.xaml</DependentUpon>\r
+    </Compile>\r
+    <Compile Include="NTThreadTitle.cs" />\r
+    <Compile Include="NTUserPreference.cs" />\r
+    <Compile Include="NTVagueSearchWord.cs" />\r
+    <Compile Include="NTWriteResHistoryPopup.cs" />\r
+    <Compile Include="NTWriteResResultWindow.xaml.cs">\r
+      <DependentUpon>NTWriteResResultWindow.xaml</DependentUpon>\r
+    </Compile>\r
+    <Compile Include="NTWriteResWindow.xaml.cs">\r
+      <DependentUpon>NTWriteResWindow.xaml</DependentUpon>\r
+    </Compile>\r
+    <Compile Include="Properties\AssemblyInfo.cs">\r
+      <SubType>Code</SubType>\r
+    </Compile>\r
+    <Compile Include="Properties\Resources.Designer.cs">\r
+      <AutoGen>True</AutoGen>\r
+      <DesignTime>True</DesignTime>\r
+      <DependentUpon>Resources.resx</DependentUpon>\r
+    </Compile>\r
+    <Compile Include="Properties\Settings.Designer.cs">\r
+      <AutoGen>True</AutoGen>\r
+      <DependentUpon>Settings.settings</DependentUpon>\r
+      <DesignTimeSharedInput>True</DesignTimeSharedInput>\r
+    </Compile>\r
+    <EmbeddedResource Include="Properties\Resources.resx">\r
+      <Generator>ResXFileCodeGenerator</Generator>\r
+      <LastGenOutput>Resources.Designer.cs</LastGenOutput>\r
+    </EmbeddedResource>\r
+    <None Include="app.config" />\r
+    <None Include="Properties\Settings.settings">\r
+      <Generator>SettingsSingleFileGenerator</Generator>\r
+      <LastGenOutput>Settings.Designer.cs</LastGenOutput>\r
+    </None>\r
+    <AppDesigner Include="Properties\" />\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ProjectReference Include="..\NT2chCtrl245\NT2chCtrl245.csproj">\r
+      <Project>{8ab65b58-6b41-47dc-aa6f-6ca444180556}</Project>\r
+      <Name>NT2chCtrl245</Name>\r
+    </ProjectReference>\r
+    <ProjectReference Include="..\NT2chCtrl45\NT2chCtrl45.csproj">\r
+      <Project>{4873f294-5f91-4364-8e6b-2b539b76f495}</Project>\r
+      <Name>NT2chCtrl45</Name>\r
+    </ProjectReference>\r
+    <ProjectReference Include="..\NT2chObject45\NT2chObject45.csproj">\r
+      <Project>{4e9cecf8-7dea-45db-9b25-d3f768a10c4b}</Project>\r
+      <Name>NT2chObject45</Name>\r
+    </ProjectReference>\r
+    <ProjectReference Include="..\NT2chStyle45\NT2chStyle45.csproj">\r
+      <Project>{d9d1b7b7-3e6e-4ced-b16a-1677ba957f73}</Project>\r
+      <Name>NT2chStyle45</Name>\r
+    </ProjectReference>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <Resource Include="images\left.png" />\r
+    <Resource Include="images\neetchan2.png" />\r
+    <Resource Include="images\right.png" />\r
+    <Resource Include="images\search_btn.png" />\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <Resource Include="neetchan6.ico" />\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <BootstrapperPackage Include=".NETFramework,Version=v4.5">\r
+      <Visible>False</Visible>\r
+      <ProductName>Microsoft .NET Framework 4.5 %28x86 および x64%29</ProductName>\r
+      <Install>true</Install>\r
+    </BootstrapperPackage>\r
+    <BootstrapperPackage Include="Microsoft.Net.Client.3.5">\r
+      <Visible>False</Visible>\r
+      <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>\r
+      <Install>false</Install>\r
+    </BootstrapperPackage>\r
+    <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">\r
+      <Visible>False</Visible>\r
+      <ProductName>.NET Framework 3.5 SP1</ProductName>\r
+      <Install>false</Install>\r
+    </BootstrapperPackage>\r
+  </ItemGroup>\r
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />\r
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. \r
+       Other similar extension points exist, see Microsoft.Common.targets.\r
+  <Target Name="BeforeBuild">\r
+  </Target>\r
+  <Target Name="AfterBuild">\r
+  </Target>\r
+  -->\r
+</Project>
\ No newline at end of file
diff --git a/NT2chView45/NT2chView45.csproj.user b/NT2chView45/NT2chView45.csproj.user
new file mode 100755 (executable)
index 0000000..709b98e
--- /dev/null
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+  <PropertyGroup>\r
+    <PublishUrlHistory>publish\</PublishUrlHistory>\r
+    <InstallUrlHistory />\r
+    <SupportUrlHistory />\r
+    <UpdateUrlHistory />\r
+    <BootstrapperUrlHistory />\r
+    <ErrorReportUrlHistory />\r
+    <FallbackCulture>ja-JP</FallbackCulture>\r
+    <VerifyUploadedFiles>false</VerifyUploadedFiles>\r
+  </PropertyGroup>\r
+</Project>
\ No newline at end of file
diff --git a/NT2chView45/NTAllboardSearch.cs b/NT2chView45/NTAllboardSearch.cs
new file mode 100755 (executable)
index 0000000..a28a7dd
--- /dev/null
@@ -0,0 +1,72 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+\r
+namespace NT2chView\r
+{\r
+    class NTAllboardSearch\r
+    {\r
+        NTAllboardSearch(NTBoard board, string title, string dat)\r
+        {\r
+            mBoard = board;\r
+            mTitle = title;\r
+            mDat = dat;\r
+        }\r
+        public string mDat;\r
+        public string mTitle;\r
+        public NTBoard mBoard;\r
+\r
+        public static List<NTAllboardSearch> Parse(string source)\r
+        {\r
+\r
+            List<NTAllboardSearch> list = new List<NTAllboardSearch>();\r
+                   int offest = 0;\r
+               \r
+                   for(int cur = 1; cur <= 50/*MAX_SEARCH_COUNT*/; cur++){\r
+                           String s = cur.ToString()+":<a href=";\r
+                           int n;\r
+                           if(0 > (n = source.IndexOf(s, offest))){\r
+                                   break;\r
+                           }\r
+                           String line = source.Substring(n);\r
+                           int n2 = line.IndexOf('>');\r
+                           int n3 = line.IndexOf("</a>");\r
+                           if(0 > n2 || 0 > n3 || n2 >= n3){\r
+                                   break;\r
+                           }\r
+                String title = line.Substring(n2 + 1, n3 - (n2 + 1));\r
+                           n2 = line.IndexOf('[', n3);\r
+                           if(0 > n2){\r
+                                   break;\r
+                           }\r
+                           n3 = line.IndexOf(']', n2);\r
+                           if(0 > n3 || n3 <= n2){\r
+                                   break;\r
+                           }\r
+                           String board = line.Substring(n2+1, n3 - (n2+1));\r
+                       \r
+                           n3 = line.IndexOf(board);\r
+                           if(0 > n3 || n3 >= n2){\r
+                                   break;\r
+                           }\r
+                           int n4 = n3+board.Length;\r
+                           if('/' != line[n4]){\r
+                                   break;\r
+                           }\r
+                           n2 = line.IndexOf('/', n4+1);\r
+                           if(0 > n2){\r
+                                   break;\r
+                           }\r
+                           String dat = line.Substring(n4+1, n2-(n4+1));\r
+\r
+                NTBoard b = NTDataRoot.getMatchBoard(board);\r
+                if (b != null)\r
+                {\r
+                    NTAllboardSearch bSearch = new NTAllboardSearch(b, title, dat);\r
+                    list.Add(bSearch);\r
+                }\r
+                   }\r
+            return list;\r
+        }\r
+    }\r
+}\r
diff --git a/NT2chView45/NTAppState.cs b/NT2chView45/NTAppState.cs
new file mode 100755 (executable)
index 0000000..e91cc10
--- /dev/null
@@ -0,0 +1,26 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Windows.Controls;\r
+using System.Windows.Media;\r
+using System.Windows;\r
+\r
+namespace NT2chView\r
+{\r
+    static class NTAppState\r
+    {\r
+        public const string HOST_2CH_ENCODING = "Shift_JIS";\r
+        static MainWindow mMainWindow;\r
+\r
+        public static void init(MainWindow main)\r
+        {\r
+            mMainWindow = main;\r
+        }\r
+\r
+        public static MainWindow getMainWindow()\r
+        {\r
+            return mMainWindow;\r
+        }\r
+        \r
+    }\r
+}\r
diff --git a/NT2chView45/NTAsciiArt.cs b/NT2chView45/NTAsciiArt.cs
new file mode 100755 (executable)
index 0000000..9006945
--- /dev/null
@@ -0,0 +1,25 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+\r
+namespace NT2chView\r
+{\r
+    static class NTAsciiArt\r
+    {\r
+        public const string DEFAULT_AA_DATA = "  ";\r
+        public static bool testAsciiArt(string source)\r
+        {\r
+            if (source == null || source.Length == 0)\r
+                return false;\r
+\r
+            string [] aaData = NTUserPreference.AAData;\r
+\r
+            foreach (string aa in aaData)\r
+            {\r
+                if (0 <= source.IndexOf(aa))\r
+                    return true;\r
+            }\r
+            return false;\r
+        }\r
+    }\r
+}\r
diff --git a/NT2chView45/NTBoard.cs b/NT2chView45/NTBoard.cs
new file mode 100755 (executable)
index 0000000..2059852
--- /dev/null
@@ -0,0 +1,661 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Collections.ObjectModel;\r
+using System.ComponentModel;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Windows;\r
+using NT2chCtrl;\r
+using NT2chView.NtFile;\r
+using NT2chView.NtHtml;\r
+using NT2chView.NtNet;\r
+using NT2chObject;\r
+\r
+\r
+namespace NT2chView\r
+{\r
+    public sealed partial class NTBoard : IBoard\r
+    {\r
+        public event DelegateMsgOnNotifyBoardUpdate OnNotifyBoardUpdate;\r
+        public delegate void DelegateMsgOnNotifyBoardUpdate(NTBoard board);\r
+\r
+        public string getName() { return mName; }\r
+        public string getAddress() { return mAddress; }\r
+        private object mObjExtra;\r
+        public object getExtra() { return mObjExtra; }\r
+        public void setExtra(object o) { mObjExtra = o; }\r
+        public List<IThread> getThreadList()\r
+        {\r
+            if (mThreadTitleList == null)\r
+                return null;\r
+            List<IThread> list = new List<IThread>(mThreadTitleList.Count);\r
+            foreach (NTThreadTitle tt in mThreadTitleList)\r
+            {\r
+                list.Add(tt);\r
+            }\r
+            return list;\r
+        }\r
+        \r
+\r
+        public NTBoard(string name, string address)\r
+        {\r
+            mName = name;\r
+            mAddress = address;\r
+            mMachiBBS = NTHttpUtils.chkMachiBBSAddress(address);\r
+        }\r
+\r
+        public string mName;\r
+        public string mAddress;\r
+        public bool mMachiBBS;\r
+        public ObservableCollection<NTThreadTitle> \r
+            mThreadTitleList = new ObservableCollection<NTThreadTitle>();\r
+        public bool mDataInit = false;\r
+        public List<string> mThreadListSortStack = new List<string>();\r
+\r
\r
+        public void delAllDat()\r
+        {\r
+\r
+            foreach (NTThreadTitle tt in mThreadTitleList)\r
+            {\r
+\r
+                //MainWindow wnd = NTAppState.getMainWindow();\r
+                //wnd.removeThreadFromTabCtrl(tt);\r
+\r
+                tt.clearLoadedDat();\r
+\r
+                //NTFileAccess.deleteDatDir(mName, tt.mDat);\r
+            }\r
+\r
+            NTFileAccess.deleteBoardDir(mName);\r
+            Thread th = new Thread(delDat_Worker);\r
+            string[] s = new string[2];\r
+            s[0] = mName;\r
+            s[1] = "*";\r
+            th.Start(s);\r
+\r
+        }\r
+\r
+\r
+        NTThreadTitle removeThreadFromList(string dat)\r
+        {\r
+            int length = mThreadTitleList.Count;\r
+            for (int i = 0; i < length; i++ )\r
+            {\r
+                NTThreadTitle tt = mThreadTitleList[i];\r
+                if (dat.Equals(tt.mDat))\r
+                {\r
+                    mThreadTitleList.RemoveAt(i);\r
+                    return tt;\r
+                }\r
+            }\r
+            return null;\r
+        }\r
+\r
+        public NTThreadTitle addExtraThread(string datName, string title)\r
+        {\r
+            NTThreadTitle tt = new NTThreadTitle(this);\r
+            tt.SeqNo = mThreadTitleList.Count + 1;\r
+            tt.mDat = datName;\r
+            tt.Title = (title != null) ? title : string.Empty;\r
+            tt.ResCnt = 0;\r
+            tt.ReadCnt = 0;\r
+            tt.RemainCnt = 0;\r
+            tt.LastMod = string.Empty;\r
+            tt.mLocalDat = true;\r
+            mThreadTitleList.Add(tt);\r
+\r
+            return tt;\r
+        }\r
+        public bool parseSubjectData(string source, NTFavorite favorite)\r
+        {\r
+            bool result;\r
+\r
+            if (mMachiBBS)\r
+                result = parseMachiSubjectData(source);\r
+            else\r
+                result = parseSubjectData1(source);\r
+\r
+            if (favorite != null && mThreadTitleList != null)\r
+            {\r
+                foreach (NTThreadTitle tt in mThreadTitleList)\r
+                {\r
+                    if (0 > favorite.findThread(\r
+                        tt.getBoard().getName(), tt.getDatName(), tt.getTitle()))\r
+                    {\r
+                        tt.IsFavorite = false;\r
+                    }\r
+                    else\r
+                    {\r
+                        tt.IsFavorite = true;\r
+                    }\r
+                }\r
+            }\r
+            return result;\r
+        }\r
+\r
+        private bool parseSubjectData1(string source)\r
+        {\r
+\r
+            bool bRet = false;\r
+            try\r
+            {\r
+\r
+                List<string> datList = NTFileAccess.getStoredDat(mName);\r
+\r
+                string[] lines = NTTextUtiles.splitLine(source);\r
+\r
+                //mThreadTitleList.Clear();\r
+                List<NTThreadTitle> newList = new List<NTThreadTitle>();\r
+                int seqNo = 1;\r
+                foreach (string s in lines)\r
+                {\r
+                    int n1 = s.IndexOf("<>");\r
+                    if (n1 < 0)\r
+                        continue;\r
+                    int n2 = s.LastIndexOf('(');\r
+                    int n3 = s.LastIndexOf(')');\r
+                    if (n2 < 0 || n3 < 0 || n2 >= n3)\r
+                        continue;\r
+                    n2++;\r
+                    string strResCnt = s.Substring(n2, n3 - n2);\r
+                    int nResCnt = Int32.Parse(strResCnt);\r
+                    string dat = s.Substring(0, n1);\r
+                    n1 += 2;\r
+                    string title = NTHtmlUtils.parseHTMLEscape(s.Substring(n1, n2 - n1 - 1));\r
+                    NTThreadTitle tt = removeThreadFromList(dat);\r
+                    if(tt == null)\r
+                        tt = new NTThreadTitle(this);\r
+                    tt.SeqNo = seqNo++;\r
+                    tt.mDat = dat;\r
+                    tt.Title = title;\r
+                    tt.ResCnt = nResCnt;\r
+                    tt.ReadCnt = 0;\r
+                    tt.RemainCnt = 0;// nResCnt;\r
+                    tt.LastMod = string.Empty;\r
+                    if (!NTUserPreference.NTShowOnlyCloudReadCount)\r
+                    {\r
+                        int numRead;\r
+                        int[] writes;\r
+                        int[] bookmarkes;\r
+                        string lastWrite;\r
+                        if (NTFileAccess.retrieveDatAttrToFile(mName, tt.mDat,\r
+                            out numRead, out writes, out bookmarkes, out lastWrite))\r
+                        {\r
+                            tt.ReadCnt = numRead;\r
+                            tt.LastMod = lastWrite;\r
+                        }\r
+                    }\r
+                    dat = NTHttpUtils.ridSuffixFromDatName(dat);\r
+                    foreach (string oldDat in datList)\r
+                    {\r
+                        if (dat.Equals(oldDat))\r
+                        {\r
+                            datList.Remove(oldDat);\r
+                            break;\r
+                        }\r
+                    }\r
+                    newList.Add(tt);\r
+                }\r
+#if true\r
+                foreach (NTThreadTitle tt in mThreadTitleList)\r
+                {\r
+                    newList.Add(tt);\r
+                }\r
+#endif\r
+                mThreadTitleList.Clear();\r
+                foreach(NTThreadTitle tt in newList)\r
+                    mThreadTitleList.Add(tt);\r
+\r
+                foreach (string localDatName in datList)\r
+                {\r
+                    string[] attr = NTFileAccess.retrieveDatAttrBinFromFile(\r
+                                    this.mName, localDatName);\r
+                    if (attr == null || attr.Length < 1)\r
+                        continue;\r
+                    NTThreadTitle tt = removeThreadFromList(localDatName);\r
+                    if (tt == null)\r
+                        tt = new NTThreadTitle(this, true);\r
+                    tt.SeqNo = seqNo++;\r
+                    tt.mDat = localDatName;\r
+                    tt.Title = "[DAT落] "+attr[0];\r
+                    int numRead;\r
+                    int[] writeIndexies;\r
+                    int[] bookmarkedIndexies;\r
+                    string lastMod;\r
+                    if (NTFileAccess.retrieveDatAttrToFile(mName, localDatName, \r
+                        out numRead, out writeIndexies, out bookmarkedIndexies, out lastMod))\r
+                    {\r
+                        tt.ResCnt = numRead;\r
+                        tt.ReadCnt = numRead;\r
+                    }\r
+                    //tt.RemainCnt = 0;\r
+                    tt.LastMod = string.Empty;\r
+                    mThreadTitleList.Add(tt);\r
+                }\r
+\r
+                bRet = true;\r
+\r
+               \r
+            }\r
+            catch(Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+\r
+            }\r
+            return mDataInit = bRet;\r
+        }\r
+\r
+\r
+        private bool parseMachiSubjectData(string source)\r
+        {\r
+           \r
+            bool bRet = false;\r
+            try\r
+            {\r
+\r
+                List<string> datList = NTFileAccess.getStoredDat(mName);\r
+\r
+                string[] lines = NTTextUtiles.splitLine(source);\r
+\r
+                //mThreadTitleList.Clear();\r
+                List<NTThreadTitle> newList = new List<NTThreadTitle>();\r
+                int seqNo = 1;\r
+                foreach (string s in lines)\r
+                {\r
+                    int n1 = s.IndexOf(",");\r
+                    if (n1 < 0)\r
+                        continue;\r
+                    int n2 = s.LastIndexOf('(');\r
+                    int n3 = s.LastIndexOf(')');\r
+                    if (n2 < 0 || n3 < 0 || n2 >= n3)\r
+                        continue;\r
+                    n2++;\r
+                    string strResCnt = s.Substring(n2, n3 - n2);\r
+                    int nResCnt = Int32.Parse(strResCnt);\r
+                    string dat = s.Substring(0, n1);\r
+                    n1 += 1;\r
+                    string title = NTHtmlUtils.parseHTMLEscape(s.Substring(n1, n2 - n1 - 1));\r
+                    NTThreadTitle tt = removeThreadFromList(dat);\r
+                    if (tt == null)\r
+                        tt = new NTThreadTitle(this);\r
+                    tt.SeqNo = seqNo++;\r
+                    tt.mDat = dat;\r
+                    tt.Title = title;\r
+                    tt.ResCnt = nResCnt;\r
+                    tt.ReadCnt = 0;\r
+                    tt.RemainCnt = 0;// nResCnt;\r
+                    tt.LastMod = string.Empty;\r
+                    if (!NTUserPreference.NTShowOnlyCloudReadCount)\r
+                    {\r
+                        int numRead;\r
+                        int[] writes;\r
+                        int[] bookmarkes;\r
+                        string lastWrite;\r
+                        if (NTFileAccess.retrieveDatAttrToFile(mName, tt.mDat,\r
+                            out numRead, out writes, out bookmarkes, out lastWrite))\r
+                        {\r
+                            tt.ReadCnt = numRead;\r
+                            tt.LastMod = lastWrite;\r
+                        }\r
+                    }\r
+                    dat = NTHttpUtils.ridSuffixFromCgiName(dat);\r
+                    foreach (string oldDat in datList)\r
+                    {\r
+                        if (dat.Equals(oldDat))\r
+                        {\r
+                            datList.Remove(oldDat);\r
+                            break;\r
+                        }\r
+                    }\r
+                    newList.Add(tt);\r
+                }\r
+                foreach (NTThreadTitle tt in mThreadTitleList)\r
+                {\r
+                    newList.Add(tt);\r
+                }\r
+                mThreadTitleList.Clear();\r
+                foreach (NTThreadTitle tt in newList)\r
+                    mThreadTitleList.Add(tt);\r
+\r
+                foreach (string localDatName in datList)\r
+                {\r
+                    string[] attr = NTFileAccess.retrieveDatAttrBinFromFile(\r
+                                    this.mName, localDatName);\r
+                    if (attr == null || attr.Length < 1)\r
+                        continue;\r
+                    NTThreadTitle tt = removeThreadFromList(localDatName);\r
+                    if (tt == null)\r
+                        tt = new NTThreadTitle(this, true);\r
+                    tt.SeqNo = seqNo++;\r
+                    tt.mDat = localDatName;\r
+                    tt.Title = "[DAT落] " + attr[0];\r
+                    int numRead;\r
+                    int[] writeIndexies;\r
+                    int[] bookmarkedIndexies;\r
+                    string lastMod;\r
+                    if (NTFileAccess.retrieveDatAttrToFile(mName, localDatName,\r
+                        out numRead, out writeIndexies, out bookmarkedIndexies, out lastMod))\r
+                    {\r
+                        tt.ResCnt = numRead;\r
+                        tt.ReadCnt = numRead;\r
+                    }\r
+                    //tt.RemainCnt = 0;\r
+                    tt.LastMod = string.Empty;\r
+                    mThreadTitleList.Add(tt);\r
+                }\r
+                bRet = true;\r
+\r
+\r
+            }\r
+            catch\r
+            {\r
+            }\r
+            return mDataInit = bRet;\r
+        }\r
\r
+        \r
+        \r
+        public NTThreadTitle findThreadTitleByDatName(string datName)\r
+        {\r
+            foreach (NTThreadTitle tt in mThreadTitleList)\r
+            {\r
+                if (datName.Equals(tt.mDat))\r
+                {\r
+                    return tt;\r
+                }\r
+            }\r
+            return null;\r
+        }\r
+\r
+        public NTThreadTitle findThreadTitleByTitle(string title)\r
+        {\r
+            foreach (NTThreadTitle tt in mThreadTitleList)\r
+            {\r
+                if (title.Equals(tt.Title))\r
+                {\r
+                    return tt;\r
+                }\r
+            }\r
+            return null;\r
+        }\r
+\r
+        public void Update(DelegateMsgOnNotifyBoardUpdate notifyUpdate)\r
+        {\r
+            lock (mLockUpdate)\r
+            {\r
+                if (/*OnNotifyBoardUpdate != null &&*/ notifyUpdate != null)\r
+                {\r
+                    OnNotifyBoardUpdate += notifyUpdate;\r
+                }\r
+                if (mUpdateBackgroundWorker != null)\r
+                    return;\r
+\r
+                mUpdateBackgroundWorker = new BackgroundWorker();\r
+                mUpdateBackgroundWorker.DoWork += new DoWorkEventHandler(NTBoardUpdate_DoWork);\r
+                mUpdateBackgroundWorker.RunWorkerCompleted +=\r
+                    new RunWorkerCompletedEventHandler(NTBoardUpdate_RunWorkerCompleted);\r
+                mUpdateBackgroundWorker.RunWorkerAsync();\r
+            }\r
+        }\r
+\r
+        //public void NotifyThreadUpdate()\r
+        //{\r
+        //    if (OnNotifyBoardUpdate != null)\r
+        //        OnNotifyBoardUpdate(this);\r
+       // }\r
+\r
+\r
+\r
+        private void QueryReadCountFromCloud(string resultHtml)\r
+        {\r
+            //string uid = NTUserPreference.NTCloudID;\r
+            //string passwd = NTUserPreference.NTCloudPSS;\r
+\r
+            //string result = NTHttpAccess.ntQueryReadCountList(uid, passwd, mName);\r
+            if (resultHtml != null)\r
+            {\r
+                string [] lines = NTTextUtiles.splitLine(resultHtml);\r
+                foreach (string line  in lines)\r
+                {\r
+                    string dat;\r
+                    int seqNo, type;\r
+                    DateTime dt;\r
+                    int ret = parseReadCntList(line, out dat, out seqNo, out type, out dt);\r
+                    if (ret < 3)\r
+                        continue;\r
+                    foreach (NTThreadTitle thread in mThreadTitleList)\r
+                    {\r
+                        if (dat.Equals(thread.mDat))\r
+                        {\r
+                            switch (type)\r
+                            {\r
+                                case 1:\r
+                                case 4:\r
+                                    if (thread.ReadCnt < seqNo)\r
+                                        thread.ReadCnt = seqNo;\r
+                                    if (ret > 3)\r
+                                    {\r
+                                        if (0 == thread.LastMod.Length)\r
+\r
+                                        {\r
+                                            thread.LastMod = dt.ToString();\r
+                                        }\r
+                                        else\r
+                                        {\r
+                                            DateTime dt2;\r
+                                            if (DateTime.TryParse(thread.LastMod, out dt2))\r
+                                            {\r
+                                                if (0 < DateTime.Compare(dt, dt2))\r
+                                                    thread.LastMod = dt.ToString();\r
+                                            }\r
+                                        }\r
+                                    }\r
+                                    break;\r
+                                case 2:\r
+                                case 5:\r
+                                    if (ret > 3)\r
+                                    {\r
+                                        if (thread.LastWrite.Length == 0)\r
+                                        {\r
+                                            thread.LastWrite = dt.ToString();\r
+                                        }\r
+                                        else\r
+                                        {\r
+                                            DateTime dt2;\r
+                                            if (DateTime.TryParse(thread.LastWrite, out dt2))\r
+                                            {\r
+                                                if (0 < DateTime.Compare(dt, dt2))\r
+                                                    thread.LastWrite = dt.ToString();\r
+                                            }\r
+                                        }\r
+                                    }\r
+                                    break;\r
+                            }//End switch\r
+                            break;\r
+                        }//End if \r
+                    }//End foreach\r
+                }\r
+            }\r
+        }\r
+#if false\r
+        public void aaa_QueryReadCountFromCloudAsync()\r
+        {\r
+                BackgroundWorker bw = new BackgroundWorker();\r
+                bw.DoWork += new DoWorkEventHandler(NTBoard_DoWork);\r
+                bw.RunWorkerCompleted += \r
+                    new RunWorkerCompletedEventHandler(NTBoard_RunWorkerCompleted);\r
+                \r
+                bw.RunWorkerAsync();\r
+        }\r
+\r
\r
+        private void NTBoard_DoWork(object sender,\r
+            DoWorkEventArgs e)\r
+        {\r
+            //NTBoard board = e.Argument as NTBoard;\r
+            //if (board == null)\r
+            //    return;\r
+\r
+            string uid = NTUserPreference.NTCloudID;\r
+            string passwd = NTUserPreference.NTCloudPSS;\r
+\r
+            string result = NTHttpAccess.ntQueryReadCountList(uid, passwd, mName);\r
+\r
+            e.Result = result;\r
+\r
+            NTDebug.l("Entering NTBoard_DoWork: " + mName);\r
+\r
+            //Thread.Sleep(2000);\r
+\r
+            // Get the BackgroundWorker that raised this event.\r
+            //BackgroundWorker worker = sender as BackgroundWorker;\r
+            // Assign the result of the computation\r
+            // to the Result property of the DoWorkEventArgs\r
+            // object. This is will be available to the \r
+            // RunWorkerCompleted eventhandler.\r
+            //e.Result = null;/// ComputeFibonacci((int)e.Argument, worker, e);\r
+        }\r
+\r
+        private void NTBoard_RunWorkerCompleted(\r
+            object sender, RunWorkerCompletedEventArgs e)\r
+        {\r
+            //e.\r
+            //NTBoard board = e.Argument as NTBoard;\r
+            //if (board != null)\r
+            //    NTDebug.l(board.mName);\r
+                \r
+\r
+\r
+            NTDebug.l("Entering NTBoard_RunWorkCompleted: " + this.mName);\r
+            // First, handle the case where an exception was thrown.\r
+            if (e.Error != null)\r
+            {\r
+                MessageBox.Show(e.Error.Message);\r
+            }\r
+            else if (e.Cancelled)\r
+            {\r
+\r
+            }\r
+            else\r
+            {\r
+                string result = e.Result as string;\r
+                if (result != null)\r
+                {\r
+\r
+                    string [] lines = NTTextUtiles.splitLine(result);\r
+                    foreach (string line  in lines)\r
+                    {\r
+                        string dat;\r
+                        int seqNo, type;\r
+                        DateTime dt;\r
+                        int ret = parseReadCntList(line, out dat, out seqNo, out type, out dt);\r
+                        if (ret < 3)\r
+                            continue;\r
+                        foreach (NTThreadTitle thread in mThreadTitleList)\r
+                        {\r
+                            if (dat.Equals(thread.mDat))\r
+                            {\r
+                                switch (type)\r
+                                {\r
+                                    case 1:\r
+                                        if (thread.ReadCnt < seqNo)\r
+                                            thread.ReadCnt = seqNo;\r
+                                        if (ret > 3)\r
+                                        {\r
+                                            if (0 == thread.LastMod.Length)\r
+\r
+                                            {\r
+                                                thread.LastMod = dt.ToString();\r
+                                            }\r
+                                            else\r
+                                            {\r
+                                                DateTime dt2;\r
+                                                if (DateTime.TryParse(thread.LastMod, out dt2))\r
+                                                {\r
+                                                    if (0 < DateTime.Compare(dt, dt2))\r
+                                                        thread.LastMod = dt.ToString();\r
+                                                }\r
+                                            }\r
+                                        }\r
+                                        break;\r
+                                    case 2:\r
+                                        if (ret > 3)\r
+                                        {\r
+                                            if (thread.LastWrite.Length == 0)\r
+                                            {\r
+                                                thread.LastWrite = dt.ToString();\r
+                                            }\r
+                                            else\r
+                                            {\r
+                                                DateTime dt2;\r
+                                                if (DateTime.TryParse(thread.LastWrite, out dt2))\r
+                                                {\r
+                                                    if (0 < DateTime.Compare(dt, dt2))\r
+                                                        thread.LastWrite = dt.ToString();\r
+                                                }\r
+                                            }\r
+                                        }\r
+                                        break;\r
+                                }//End switch\r
+                                break;\r
+                            }//End if \r
+                        }//End foreach\r
+                    }\r
+                }\r
+            }\r
+        }\r
+#endif\r
+        static int parseReadCntList(string source, \r
+            out string datName, out int seqNo, out int type, out DateTime dt)\r
+        {\r
+            datName = null;\r
+            seqNo = -1;\r
+            type = -1;\r
+            dt = DateTime.MinValue;\r
+            int retVal = -1;\r
+\r
+            try\r
+            {\r
+                \r
+                string[] values = source.Split(NTTextUtiles.COMMA_VALUE);\r
+                retVal = values.Length;\r
+                if (retVal < 3)\r
+                    return -1;\r
+                for (int i = 0; i < values.Length; i++)\r
+                {\r
+                    string s = values[i];\r
+                    switch (i)\r
+                    {\r
+                        case 0:\r
+                            if(NTUserPreference.AESEnabled)\r
+                                datName = NTTextUtiles.aesDecodeBase64URL(s);\r
+                            else\r
+                                datName = NTTextUtiles.decodeBase64URL(s);\r
+                            break;\r
+                        case 1:\r
+                            seqNo = int.Parse(s);\r
+                            break;\r
+                        case 2:\r
+                            type = int.Parse(s);\r
+                            break;\r
+                        case 3:\r
+                            dt = DateTime.Parse(s);\r
+                            break;\r
+                    }\r
+            \r
+                }\r
+            }\r
+            catch(Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+                return -1;\r
+            }\r
+            return retVal;\r
+\r
+        }\r
+\r
+\r
+\r
+    }\r
+}\r
diff --git a/NT2chView45/NTBoardPanel.xaml b/NT2chView45/NTBoardPanel.xaml
new file mode 100755 (executable)
index 0000000..f591da3
--- /dev/null
@@ -0,0 +1,15 @@
+<UserControl x:Class="NT2chView.NTBoardPanel"\r
+             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"\r
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"\r
+             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" \r
+             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"\r
+             mc:Ignorable="d" \r
+             d:DesignHeight="600" d:DesignWidth="300">\r
+    <ScrollViewer>\r
+        \r
+            <WrapPanel x:Name="mMainPanel" Orientation="Horizontal">\r
+            <!--Grid Height="300"/ -->\r
+            </WrapPanel>\r
+        \r
+    </ScrollViewer>\r
+</UserControl>\r
diff --git a/NT2chView45/NTBoardPanel.xaml.cs b/NT2chView45/NTBoardPanel.xaml.cs
new file mode 100755 (executable)
index 0000000..ca50146
--- /dev/null
@@ -0,0 +1,120 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Windows;\r
+using System.Windows.Controls;\r
+using System.Windows.Data;\r
+using System.Windows.Documents;\r
+using System.Windows.Input;\r
+using System.Windows.Media;\r
+using System.Windows.Media.Imaging;\r
+using System.Windows.Navigation;\r
+using System.Windows.Shapes;\r
+\r
+namespace NT2chView\r
+{\r
+    /// <summary>\r
+    /// NTBoardPanel.xaml の相互作用ロジック\r
+    /// </summary>\r
+    public partial class NTBoardPanel : UserControl\r
+\r
+\r
+\r
+    {\r
+\r
+        public MainWindow.DelegateMsgOpenThreadTitleListRequest OpenThreadTitleListRequest\r
+        {\r
+            get;\r
+            set;\r
+        }\r
+\r
+        public NTBoardPanel()\r
+        {\r
+            InitializeComponent();\r
+        }\r
+\r
+        List<NTBoard> mBoardTable;\r
+\r
+        public List<NTBoard> BoardTable\r
+        {\r
+            get \r
+            {\r
+                return mBoardTable;\r
+            }\r
+            set\r
+            {\r
+                mBoardTable = value;\r
+                initBoard();\r
+            }\r
+        }\r
+\r
+        private void initBoard()\r
+        {\r
+            if(mBoardTable == null)\r
+                return;\r
+\r
+            //Brush brush = (Brush)TryFindResource("BasicBkBrush");\r
+\r
+            Style style = (Style)TryFindResource("BoardDisplayButton");\r
+\r
+            mMainPanel.Children.Clear();\r
+            Button btn;\r
+\r
+            foreach(NTBoard board in mBoardTable)\r
+            {\r
+                btn = new Button();\r
+                if(style != null)\r
+                    btn.Style = style;\r
+                btn.Content = board.mName;\r
+                btn.Tag = board;\r
+                btn.Click += btn_Click;\r
+                btn.MouseRightButtonDown += btn_MouseRightButtonDown;\r
+                btn.MouseRightButtonUp += btn_MouseRightButtonUp;\r
+                mMainPanel.Children.Add(btn);\r
+            }\r
+        }\r
+\r
+        void btn_MouseRightButtonUp(object sender, MouseButtonEventArgs e)\r
+        {\r
+            Button btn = sender as Button;\r
+            if (btn == null)\r
+                return;\r
+\r
+            NTBoard board = btn.Tag as NTBoard;\r
+            if (board == null)\r
+                return;\r
+\r
+            NTBoardPopupMenu popup = new NTBoardPopupMenu(board.mName);\r
+            popup.OnNotifiAddBoardToFavorite += \r
+                    new NTBoardPopupMenu.DelegateMsgOnNotifiAddBoardToFavorite(\r
+                    OnNotifiAddBoardToFavorite);\r
+            popup.show();\r
+            e.Handled = true;\r
+        }\r
+\r
+        void btn_MouseRightButtonDown(object sender, MouseButtonEventArgs e)\r
+        {\r
+            e.Handled = true;\r
+        }\r
+\r
+        void btn_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            if (OpenThreadTitleListRequest == null)\r
+                return;\r
+            Button btn = sender as Button;\r
+            if (btn == null)\r
+                return;\r
+\r
+            NTBoard board = btn.Tag as NTBoard;\r
+            if (board == null)\r
+                return;\r
+\r
+            OpenThreadTitleListRequest(board);\r
+        }\r
+\r
+        void OnNotifiAddBoardToFavorite(string boardName)\r
+        {\r
+            NTAppState.getMainWindow().addFavoriteBoard(boardName);\r
+        }\r
+    }\r
+}\r
diff --git a/NT2chView45/NTBoardPopupMenu.cs b/NT2chView45/NTBoardPopupMenu.cs
new file mode 100755 (executable)
index 0000000..50ff3bb
--- /dev/null
@@ -0,0 +1,119 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Windows.Controls;\r
+using System.Windows.Controls.Primitives;\r
+using System.Windows.Documents;\r
+using System.Windows.Media;\r
+\r
+namespace NT2chView\r
+{\r
+    public class NTBoardPopupMenu : Popup\r
+    {\r
+        public delegate void DelegateMsgOnNotifiAddBoardToFavorite(string boardName);\r
+        public event DelegateMsgOnNotifiAddBoardToFavorite OnNotifiAddBoardToFavorite;\r
+\r
+        string mBoardName;\r
+\r
+        public void show()\r
+        {\r
+            IsOpen = true;\r
+            Placement = PlacementMode.Mouse;\r
+            Focus();\r
+        }\r
+\r
+        public NTBoardPopupMenu(string boardName)\r
+            : base()\r
+        {\r
+\r
+            mBoardName = boardName;\r
\r
+            this.StaysOpen = false;\r
+            //this.MouseLeave += NTResPopupMenu_MouseLeave;\r
+            //this.LostFocus += NTResPopupMenu_LostFocus;\r
+            \r
+            \r
+\r
+            StackPanel sp = new StackPanel();\r
+            sp.Orientation = Orientation.Horizontal;\r
+\r
+\r
+            StackPanel panel = new StackPanel();\r
+            Border border = new Border();\r
+            border.BorderThickness = new System.Windows.Thickness(1);\r
+            border.BorderBrush = new SolidColorBrush(Colors.DarkGray);\r
+           \r
+\r
+            ListBoxItem item1 = new ListBoxItem();\r
+\r
+            sp = new StackPanel();\r
+            //sp.MouseLeftButtonDown += threadTitle_MouseLeftButtonDown;\r
+            sp.Children.Add(new TextBlock(new Run(mBoardName)));\r
+            //sp.Tag = tt;\r
+            item1.Content = sp;\r
+            item1.Padding = new System.Windows.Thickness(10, 2, 10, 2);\r
+            //item1.Tag = tt;\r
+            //item1.MouseEnter += item1_MouseEnter;\r
+            //item1.MouseLeave += item1_MouseLeave;\r
+            panel.Children.Add(item1);\r
+\r
+            sp = new StackPanel();\r
+            sp.Children.Add(new Separator());\r
+            item1 = new ListBoxItem();\r
+            item1.BorderBrush = new SolidColorBrush(Colors.LightGray);\r
+            item1.BorderThickness = new System.Windows.Thickness(1);\r
+            item1.Height = 1;\r
+            item1.Content = sp;\r
+            panel.Children.Add(item1);\r
+            panel.Background = new SolidColorBrush(Colors.White);\r
+\r
+\r
+            sp = new StackPanel();\r
+            sp.Children.Add(new TextBlock(new Run("お気に入りに追加")));\r
+            sp.MouseLeftButtonDown += itemDelete_MouseLeftButtonDown;\r
+            sp.Tag = mBoardName;\r
+            item1 = new ListBoxItem();\r
+            item1.Padding = new System.Windows.Thickness(10, 2, 10, 2);\r
+            item1.Content = sp;\r
+            //item1.MouseEnter += item1_MouseEnter;\r
+            //item1.MouseLeave += item1_MouseLeave;\r
+            //item1.MouseLeftButtonDown += item1_MouseLeftButtonDown;\r
+            //item1.MouseLeftButtonUp += item1_MouseLeftButtonUp;\r
+            panel.Children.Add(item1);\r
\r
+\r
+            sp = new StackPanel();\r
+            sp.Children.Add(new TextBlock(new Run("閉じる")));\r
+            sp.MouseLeftButtonDown += itemClose_MouseLeftButtonDown;\r
+            item1 = new ListBoxItem();\r
+            item1.Padding = new System.Windows.Thickness(10, 2, 10, 2);\r
+            item1.Content = sp;\r
+            //item1.MouseEnter += item1_MouseEnter;\r
+            //item1.MouseLeave += item1_MouseLeave;\r
+            //item1.MouseLeftButtonDown += item1_MouseLeftButtonDown;\r
+            //item1.MouseLeftButtonUp += item1_MouseLeftButtonUp;\r
+            panel.Children.Add(item1);\r
+            //this.Child = panel;\r
+            border.Child = panel; \r
+            this.Child = border;\r
+\r
+        }\r
+\r
+        void itemDelete_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)\r
+        {\r
+            IsOpen = false;\r
+\r
+            if (OnNotifiAddBoardToFavorite != null)\r
+            {\r
+                OnNotifiAddBoardToFavorite(mBoardName);\r
+            }\r
+        }\r
+\r
+        void itemClose_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)\r
+        {\r
+            //Hide();\r
+            IsOpen = false;\r
+            //mMainWnd.NgEdit_setResSection(mRes);\r
+        }\r
+    }\r
+}\r
diff --git a/NT2chView45/NTBoard_backgroundworker.cs b/NT2chView45/NTBoard_backgroundworker.cs
new file mode 100755 (executable)
index 0000000..c7142fe
--- /dev/null
@@ -0,0 +1,109 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.ComponentModel;\r
+using System.Text;\r
+using NT2chView.NtFile;\r
+using NT2chView.NtNet;\r
+\r
+namespace NT2chView\r
+{\r
+    public sealed partial class NTBoard\r
+    {\r
+        private static object mLockUpdate = new object();\r
+        private BackgroundWorker mUpdateBackgroundWorker = null;\r
+\r
+        static void delDat_Worker(object o)\r
+        {\r
+            string[] s = o as string[];\r
+            if (s == null)\r
+                return;\r
+\r
+            string result = NTHttpAccess.ntDeleteDatValue(s[0], s[1]);\r
+            NTDebug.l(result);\r
+\r
+        }\r
+\r
+        private void NTBoardUpdate_DoWork(object sender,\r
+            DoWorkEventArgs e)\r
+        {\r
+            lock (mLockUpdate)\r
+            {\r
+                mUpdateBackgroundWorker = null;\r
+            }\r
+            NTHttpAccess.getSubject(mAddress, mName);\r
+            e.Result = true;\r
+\r
+        }\r
+\r
+        private void NTBoardUpdate_RunWorkerCompleted(\r
+            object sender, RunWorkerCompletedEventArgs e)\r
+        {\r
+            \r
+\r
+            lock (mLockUpdate)\r
+            {\r
+                string strSubject = NTFileAccess.retrieveSubjectDataFromFile(mName);\r
+\r
+                if (null != strSubject)\r
+                    parseSubjectData(strSubject, NTAppState.getMainWindow().getFavoriteData());\r
+\r
+                if (NTUserPreference.NTCloudIsEnabled)\r
+                {\r
+                    BackgroundWorker bw = new BackgroundWorker();\r
+                    bw.DoWork +=\r
+                        new DoWorkEventHandler(NTCloudBoardUpdate_DoWork);\r
+                    bw.RunWorkerCompleted += \r
+                        new RunWorkerCompletedEventHandler(\r
+                            NTCloudBoardUpdate_RunWorkerCompleted);\r
+                    bw.RunWorkerAsync();\r
+                }\r
+                else\r
+                {\r
+                    fireEvent();\r
+                }\r
+\r
+            }\r
+            \r
+        }\r
+\r
+        private void fireEvent()\r
+        {\r
+            if (OnNotifyBoardUpdate != null)\r
+                OnNotifyBoardUpdate(this);\r
+            //mUpdateBackgroundWorker = null;\r
+        }\r
+\r
+        private void NTCloudBoardUpdate_DoWork(object sender,\r
+            DoWorkEventArgs e)\r
+        {\r
+            string result;\r
+            if (NTUserPreference.NTUserCloudIsEnabled)\r
+            {\r
+                string uid = NTUserPreference.NTCloudID;\r
+                string passwd = NTUserPreference.NTUserCloudGetHashedPasswd();\r
+                result = NTHttpAccess.UserCloudQueryReadCountList(uid, passwd, mName);\r
+            }\r
+            else\r
+            {\r
+                string uid = NTUserPreference.NTCloudID;\r
+                string passwd = NTUserPreference.NTCloudPSS;\r
+                result = NTHttpAccess.ntQueryReadCountList(uid, passwd, mName);\r
+            }\r
+            e.Result = result;\r
+        }\r
+        private void NTCloudBoardUpdate_RunWorkerCompleted(\r
+            object sender, RunWorkerCompletedEventArgs e)\r
+        {\r
+\r
+            string resultHtml = e.Result as string;\r
+            if (resultHtml != null)\r
+            {\r
+                QueryReadCountFromCloud(resultHtml);\r
+            }\r
+            lock (mLockUpdate)\r
+            {\r
+                fireEvent();\r
+            }             \r
+       }\r
+    }\r
+}\r
diff --git a/NT2chView45/NTCategory.cs b/NT2chView45/NTCategory.cs
new file mode 100755 (executable)
index 0000000..d1947ca
--- /dev/null
@@ -0,0 +1,132 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+\r
+namespace NT2chView\r
+{\r
+    public sealed class NTCategory\r
+    {\r
+        public string mName = null;\r
+        public List<NTBoard> mBoardList = new List<NTBoard>();\r
+\r
+        public NTBoard getMatchBoard(string searchAddress)\r
+        {\r
+            foreach (NTBoard board in mBoardList)\r
+            {\r
+                int n1 = board.mAddress.LastIndexOf(searchAddress);\r
+                int n2 = board.mAddress.LastIndexOf("2ch.net");\r
+                if (n2 > 0 && n2 < n1)\r
+                    return board;\r
+\r
+            }\r
+            return null;\r
+\r
+        }\r
+\r
+\r
+\r
+        public NTCategory(string name)\r
+        {\r
+            mName = name;\r
+        }\r
+\r
+        public NTBoard getBoardByName(string name)\r
+        {\r
+            foreach (NTBoard board in mBoardList)\r
+            {\r
+                if (name.Equals(board.mName))\r
+                    return board;\r
+            }\r
+            return null;\r
+        }\r
+\r
+        public NTBoard getBoardByAddress(string address)\r
+        {\r
+            foreach (NTBoard board in mBoardList)\r
+            {\r
+                if (0 <= board.mAddress.IndexOf(address))\r
+                    return board;\r
+            }\r
+            return null;\r
+        }\r
+\r
+\r
+\r
+        public static List<NTCategory> parseBoardMenu(string html)\r
+        {\r
+            List<NTCategory> clist = new List<NTCategory>();\r
+            NTCategory category = null;\r
+\r
+            string[] lines = html.Split('\n');\r
+\r
+            foreach (string s in lines)\r
+            {\r
+                int n1;\r
+                if (0 <= (n1 = s.IndexOf("<B>")))\r
+                {\r
+\r
+                    n1 += 3;\r
+\r
+                    int n2 = s.IndexOf("</B>", n1);\r
+                    if (n2 < 0)\r
+                        continue;\r
+                    string cName = s.Substring(n1, n2 - n1);\r
+\r
+                    category = new NTCategory(cName);\r
+\r
+                    //NTDebug.l("Category: " + cName);\r
+\r
+                    clist.Add(category);\r
+                }\r
+                else if (0 <= (n1 = s.IndexOf("<A")))\r
+                {\r
+                    int n2, n3, n4;\r
+                    if (0 <= (n2 = s.IndexOf("HREF=", n1)))\r
+                    {\r
+                        if (0 <= (n3 = s.IndexOf('>', n2)))\r
+                        {\r
+\r
+                            if (0 <= (n4 = s.IndexOf("</A>", n3)))\r
+                            {\r
+                                string boardName = s.Substring(n3 + 1, n4 - (n3 + 1)).Trim();\r
+                                string boardAddress = s.Substring(n2 + 5, n3 - (n2 + 5)).Trim();\r
+                                if (0 <= (n1 = boardAddress.IndexOf(' ')))\r
+                                {\r
+                                    boardAddress = boardAddress.Substring(0, n1);\r
+                                }\r
+                                //NTDebug.l("\tBoard: " + boardName);\r
+                                //NTDebug.l("\t\t" + boardAddress);\r
+                                if (null != category)\r
+                                {\r
+                                    category.mBoardList.Add(new NTBoard(boardName, boardAddress));\r
+                                }\r
+                            }\r
+\r
+                        }\r
+                    }\r
+                }\r
+            }\r
+            return clist;\r
+        }\r
+\r
+        public static void parseExternalBoardMenu(string[] descriptions)\r
+        {\r
+            NTCategory category = NTDataRoot.getExternalBoards();\r
+            List<NTBoard> bList = category.mBoardList;\r
+\r
+            bList.Clear();\r
+\r
+            foreach (string s in descriptions)\r
+            {\r
+                int n1;\r
+                if (0 <= (n1 = s.IndexOf("<>")))\r
+                {\r
+                    string address = s.Substring(0, n1);\r
+                    string name = s.Substring(n1 + 2);\r
+                    category.mBoardList.Add(new NTBoard(name, address));\r
+\r
+                }\r
+            }\r
+        }\r
+    }\r
+}\r
diff --git a/NT2chView45/NTCategoryPanel.xaml b/NT2chView45/NTCategoryPanel.xaml
new file mode 100755 (executable)
index 0000000..3033501
--- /dev/null
@@ -0,0 +1,13 @@
+<UserControl x:Class="NT2chView.NTCategoryPanel"\r
+             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"\r
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"\r
+             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" \r
+             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" \r
+             mc:Ignorable="d" Loaded="CategoryPanel_Loaded" ><!--\r
+             d:DesignHeight="300" d:DesignWidth="300" -->\r
+    <ScrollViewer x:Name="mCategoryPanelScrollViewer">\r
+        <WrapPanel x:Name="mMainPanel" Orientation="Horizontal">            \r
+        </WrapPanel>   \r
+    </ScrollViewer>\r
+\r
+</UserControl>\r
diff --git a/NT2chView45/NTCategoryPanel.xaml.cs b/NT2chView45/NTCategoryPanel.xaml.cs
new file mode 100755 (executable)
index 0000000..c5b57c3
--- /dev/null
@@ -0,0 +1,234 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Windows;\r
+using System.Windows.Controls;\r
+using System.Windows.Controls.Primitives;\r
+using System.Windows.Data;\r
+using System.Windows.Documents;\r
+using System.Windows.Input;\r
+using System.Windows.Media;\r
+using System.Windows.Media.Imaging;\r
+using System.Windows.Navigation;\r
+using System.Windows.Shapes;\r
+using NT2chCtrl;\r
+\r
+namespace NT2chView\r
+{\r
+    /// <summary>\r
+    /// NTCategoryPanel.xaml の相互作用ロジック\r
+    /// </summary>\r
+    public partial class NTCategoryPanel : UserControl\r
+    {\r
+        public MainWindow.DelegateMsgOpenBoardListRequest OpenBoardListRequest\r
+        {\r
+            get;\r
+            set;\r
+        }\r
+\r
+        public MainWindow.DelegateMsgOpenFavoriteListRequest OpenFavoriteListRequest\r
+        {\r
+            get;\r
+            set;\r
+        }\r
+\r
+\r
+        public NTCategoryPanel()\r
+        {\r
+            InitializeComponent();\r
+        }\r
+        List<NTCategory> mCategoryTable;\r
+\r
+        public List<NTCategory> CategoryTable\r
+        {\r
+            get \r
+            {\r
+                return mCategoryTable;\r
+            }\r
+            set\r
+            {\r
+                mCategoryTable = value;\r
+                initCategory();\r
+            }\r
+        }\r
+\r
+        public void addExternalCategory(NTCategory exCate)\r
+        {\r
+            if (mCategoryTable == null || exCate == null)\r
+                return;\r
+\r
+            if (hasExternalCategory())\r
+                return;\r
+\r
+            Style style = (Style)TryFindResource("CategoryDisplayButton");\r
+\r
\r
+            ToggleButton btn = new ToggleButton();\r
+            btn.Checked += btn_Checked;\r
+            btn.Unchecked += btn_Unchecked;\r
+\r
+            if (style != null)\r
+                btn.Style = style;\r
+            btn.Content = NTDataRoot.EXTERNAL_BOARD_CATEGORY_NAME;\r
+            btn.Tag = exCate;\r
+\r
+            mMainPanel.Children.Add(btn);\r
+            mCategoryTable.Add(exCate);\r
+        }\r
+\r
+        private bool hasExternalCategory()\r
+        {\r
+            foreach (object o in mMainPanel.Children)\r
+            {\r
+                ToggleButton tglBtn = o as ToggleButton;\r
+                if (tglBtn == null)\r
+                    continue;\r
+                string content = tglBtn.Content as string;\r
+                if (content == null)\r
+                    continue;\r
+\r
+                if (content.Equals(NTDataRoot.EXTERNAL_BOARD_CATEGORY_NAME))\r
+                    return true; ;\r
+\r
+            }\r
+            return false;\r
+        }\r
+\r
+        public bool isExternalCategorySelected()\r
+        {\r
+            foreach (object o in mMainPanel.Children)\r
+            {\r
+                ToggleButton tglBtn = o as ToggleButton;\r
+                if (tglBtn == null)\r
+                    continue;\r
+                string content = tglBtn.Content as string;\r
+                if (content == null)\r
+                    continue;\r
+\r
+                if(!content.Equals(NTDataRoot.EXTERNAL_BOARD_CATEGORY_NAME))\r
+                    continue;\r
+                if(tglBtn.IsChecked.HasValue)\r
+                    return (bool)tglBtn.IsChecked;\r
+                else\r
+                    return false;\r
+\r
+            }\r
+            return false;\r
+        }\r
+\r
+        private void initCategory()\r
+        {\r
+            if(mCategoryTable == null)\r
+                return;\r
+\r
+            Brush brush = (Brush)TryFindResource("BasicBkBrush");\r
+\r
+            Style style = (Style)TryFindResource("CategoryDisplayButton");\r
+\r
+            //StackPanel sp = null;\r
+            \r
+            //StackPanel sp = new StackPanel();\r
+            //sp.Orientation = Orientation.Horizontal;\r
+            if (brush != null)\r
+                mMainPanel.Background = brush;\r
+\r
+            ToggleButton btn = new ToggleButton();\r
+            btn.Checked += btn_Checked;\r
+            btn.Unchecked += btn_Unchecked;\r
+            \r
+            if (style != null)\r
+                btn.Style = style;\r
+            btn.Content = "お気に入り";\r
+            btn.Tag = new NTFavorite();\r
+\r
+            mMainPanel.Children.Add(btn);\r
+\r
+            //sp = sp2;\r
+\r
+\r
+            foreach(NTCategory category in mCategoryTable)\r
+            {\r
+                btn = new ToggleButton();\r
+                btn.Checked += btn_Checked;\r
+                btn.Unchecked += btn_Unchecked;\r
+\r
+                if (style != null)\r
+                    btn.Style = style;\r
+                btn.Content = category.mName;\r
+                btn.Tag = category;\r
+\r
+                mMainPanel.Children.Add(btn);\r
+\r
+                //TextBlock tb = new TextBlock(new Run(category.mName));\r
+                /*if (sp == null)\r
+                {\r
+                    sp = new StackPanel();\r
+                    sp.Orientation = Orientation.Horizontal;\r
+                    if (brush != null)\r
+                        sp.Background = brush;\r
+                    sp.Children.Add(btn);\r
+                }\r
+                else\r
+                {\r
+                    sp.Children.Add(btn);\r
+                    mMainPanel.Children.Add(sp);\r
+                    sp = null;\r
+                }\r
+            }\r
+            if(sp != null)\r
+            {\r
+                mMainPanel.Children.Add(sp);*/\r
+            }\r
+        }\r
+\r
+        void btn_Checked(object sender, RoutedEventArgs e)\r
+        {\r
+            object selectedObj = null;\r
+            foreach (object o in mMainPanel.Children)\r
+            {\r
+                ToggleButton tb = o as ToggleButton;\r
+                if (tb == null)\r
+                    continue;\r
+\r
+                if (sender.Equals(o))\r
+                {\r
+                    selectedObj = o;\r
+                }\r
+                else\r
+                {\r
+                    tb.IsChecked = false;\r
+                }\r
+\r
+            }\r
+            if (OpenBoardListRequest != null)\r
+            {\r
+                ToggleButton tglBtn = selectedObj as ToggleButton;\r
+                if (tglBtn != null)\r
+                {\r
+                    NTCategory category = tglBtn.Tag as NTCategory;\r
+                    if(category != null)\r
+                        OpenBoardListRequest(category);\r
+\r
+                    NTFavorite favorite = tglBtn.Tag as NTFavorite;\r
+                    if (favorite != null)\r
+                        OpenFavoriteListRequest(favorite);\r
+                }\r
+            }\r
+\r
+        }\r
+\r
+        void btn_Unchecked(object sender, RoutedEventArgs e)\r
+        {\r
+            //throw new NotImplementedException();\r
+        }\r
+\r
+        private void CategoryPanel_Loaded(object sender, RoutedEventArgs e)\r
+        {\r
+#if DOTNET45\r
+\r
+            TouchSupportScrollViewer sv =\r
+                new TouchSupportScrollViewer(mCategoryPanelScrollViewer, mMainPanel);\r
+#endif\r
+        }\r
+    }\r
+}\r
diff --git a/NT2chView45/NTCreateThreadWindow.xaml b/NT2chView45/NTCreateThreadWindow.xaml
new file mode 100755 (executable)
index 0000000..3781f73
--- /dev/null
@@ -0,0 +1,34 @@
+<Window x:Class="NT2chView.NTCreateThreadWindow"\r
+        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"\r
+        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"\r
+        Title="新規スレッドの作成" Height="300" Width="400">\r
+    <Grid>\r
+        <Grid.RowDefinitions>\r
+            <RowDefinition Height="Auto"></RowDefinition>\r
+            <RowDefinition Height="Auto"></RowDefinition>\r
+            <RowDefinition Height="Auto"></RowDefinition>\r
+            <RowDefinition Height="*"></RowDefinition>\r
+            <RowDefinition Height="Auto"></RowDefinition>\r
+        </Grid.RowDefinitions>\r
+        <Grid.ColumnDefinitions>\r
+            <ColumnDefinition Width="Auto"></ColumnDefinition>\r
+            <ColumnDefinition></ColumnDefinition>\r
+            <ColumnDefinition Width="Auto"></ColumnDefinition>\r
+        </Grid.ColumnDefinitions>\r
+        <Label Content="名前:" />\r
+        <Label Content="E-Mail:" Grid.Row="1" />\r
+        <Label Content="スレッド:" Grid.Row="2" />\r
+        <Label Content="メッセージ:" Grid.Row="3" />\r
+        <Label Grid.Row="4" Grid.Column="1"  Margin="50,0,0,0" VerticalContentAlignment="Center">(Shift+Enter)</Label>\r
+        <Button Margin="5" Content="書き込む" Height="23" Name="btnWriteRes" Width="75" Grid.Row="4" Grid.Column="1" HorizontalAlignment="Right" Click="btnCreateThread_Click" />\r
+        <Button Margin="5"  Content="戻る" Height="23" Name="btnWriteResClose" Width="75" Grid.Row="4" Grid.Column="2" Click="btnCreateThreadClose_Click" />\r
+        <TextBox Grid.Column="1" Grid.ColumnSpan="1" Grid.RowSpan="1" Name="txtName" Grid.Row="0" />\r
+        <TextBox Grid.Column="1" Grid.ColumnSpan="1" Grid.RowSpan="1" Name="txtMail" Grid.Row="1" />\r
+        <TextBox SpellCheck.IsEnabled="True" Grid.Column="1" Grid.ColumnSpan="2" Grid.Row="2" Name="txtTitle" AcceptsReturn="False" AcceptsTab="False" TextWrapping="WrapWithOverflow" TabIndex="1" />\r
+        <TextBox SpellCheck.IsEnabled="True" Grid.Column="1" Grid.ColumnSpan="2" Grid.Row="3" Name="txtMsg" AcceptsReturn="True" AcceptsTab="True" TextWrapping="WrapWithOverflow" VerticalScrollBarVisibility="Auto" TabIndex="1" />\r
+        <CheckBox Content="_sage" Grid.Column="2" Grid.Row="1" Grid.RowSpan="1" Name="chkSage" HorizontalAlignment="Center" VerticalAlignment="Center" Unchecked="chkSage_Unchecked" Checked="chkSage_Checked" />\r
+        <CheckBox Content="P2を使う" Grid.ColumnSpan="2" Grid.Row="4" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="20,0,0,0" Name="chkWriteTroughP2" Checked="chkWriteTroughP2_Checked" Unchecked="chkWriteTroughP2_Unchecked" />\r
+\r
+            \r
+    </Grid>\r
+</Window>\r
diff --git a/NT2chView45/NTCreateThreadWindow.xaml.cs b/NT2chView45/NTCreateThreadWindow.xaml.cs
new file mode 100755 (executable)
index 0000000..802c3a8
--- /dev/null
@@ -0,0 +1,394 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Web;\r
+using System.Windows;\r
+using System.Windows.Controls;\r
+using System.Windows.Data;\r
+using System.Windows.Documents;\r
+using System.Windows.Input;\r
+using System.Windows.Media;\r
+using System.Windows.Media.Imaging;\r
+using System.Windows.Shapes;\r
+using NT2chView.NtHtml;\r
+using NT2chView.NtNet;\r
+\r
+namespace NT2chView\r
+{\r
+    /// <summary>\r
+    /// NTCreateThreadWindow.xaml の相互作用ロジック\r
+    /// </summary>\r
+    public partial class NTCreateThreadWindow : Window\r
+    {\r
+        NTBoard mBoard;\r
+\r
+        string mName;\r
+        string mMail;\r
+        string mTitle;\r
+        string mMsg;\r
+        bool mP2;\r
+\r
+        bool  setUserInput(out string error)\r
+        {\r
+            error = string.Empty;\r
+\r
+            mTitle = txtTitle.Text.Trim();\r
+            if (mTitle.Length == 0)\r
+            {\r
+                error = "タイトルが指定されていません。";\r
+                return false;\r
+            }\r
+            mName = txtName.Text.Trim();\r
+            if (chkSage.HasContent && (bool)chkSage.IsChecked)\r
+                mMail = "sage";\r
+            else\r
+                mMail = txtMail.Text.Trim();\r
+\r
+            mMsg = txtMsg.Text;\r
+\r
+            if (chkWriteTroughP2.HasContent && (bool)chkWriteTroughP2.IsChecked)\r
+                mP2 = true;\r
+            else\r
+                mP2 = false;\r
+\r
+            return true;\r
+        }\r
+\r
+        public NTCreateThreadWindow(NTBoard board, NTThreadTitle tt)\r
+        {\r
+            InitializeComponent();\r
+\r
+            mBoard = board;\r
+\r
+            if (tt != null)\r
+            {\r
+                string address = mBoard.mAddress;\r
+                string hostName, boardName;\r
+                if (NTHttpUtils.parseHostAddress(address, out hostName, out boardName))\r
+                {\r
+                    string title = tt.Title;\r
+                    string dat = NTHttpUtils.ridSuffixFromDatName(tt.mDat);\r
+                    StringBuilder sb = new StringBuilder();\r
+                    sb.Append(title).Append("\r\n")\r
+                        .Append("http://").Append(hostName).Append("/test/read.cgi/")\r
+                        .Append(boardName).Append('/')\r
+                        .Append(dat).Append("/\r\n");\r
+                    txtTitle.Text = title;\r
+                    txtMsg.Text = sb.ToString();\r
+\r
+                }\r
+            }\r
+        }\r
+        public NTCreateThreadWindow(NTBoard board, string title, string message)\r
+        {\r
+            InitializeComponent();\r
+\r
+            mBoard = board;\r
+\r
+            if(title != null)\r
+                txtTitle.Text = title;\r
+\r
+            if (message != null)\r
+                txtMsg.Text = message;\r
+        }\r
+\r
+        private void btnCreateThread_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            string error = string.Empty;\r
+\r
+            if (!setUserInput(out error))\r
+            {\r
+                MessageBox.Show(error);\r
+                return;\r
+            }\r
+\r
+            string retStr = null;\r
+            if (mP2)\r
+            {\r
+                retStr = createThreadP2(out error);\r
+            }\r
+            else\r
+            {\r
+                retStr = createThread(out error, null);\r
+            }\r
+            if(retStr == null)\r
+            {\r
+                if (error.Length > 0) \r
+                    MessageBox.Show(error);\r
+                //return;\r
+            }\r
+            Close();\r
+            //return;\r
+        }\r
+\r
+        private void btnCreateThreadClose_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            Close();\r
+        }\r
+\r
+        private void chkSage_Unchecked(object sender, RoutedEventArgs e)\r
+        {\r
+\r
+        }\r
+\r
+        private void chkSage_Checked(object sender, RoutedEventArgs e)\r
+        {\r
+\r
+        }\r
+\r
+        private void chkWriteTroughP2_Checked(object sender, RoutedEventArgs e)\r
+        {\r
+\r
+        }\r
+\r
+        private void chkWriteTroughP2_Unchecked(object sender, RoutedEventArgs e)\r
+        {\r
+\r
+        }\r
+\r
+        string createThread(out string errorMsg, NTHtmlParser extra)\r
+        {\r
+            //bool bRet = false;\r
+            string result = null;\r
+            errorMsg = string.Empty;\r
+            FlowDocument doc;\r
+\r
+            Encoding enc = Encoding.GetEncoding(NTAppState.HOST_2CH_ENCODING);\r
+\r
+            string extraParam = null;\r
+            if (NTUserPreference.MaruIsEnabled)\r
+            {\r
+                string sessionId = NTMaru.getSessionId();\r
+                if (sessionId.Length > 0)\r
+                {\r
+                    extraParam = "&sid=" + sessionId;\r
+                }\r
+            }\r
+\r
+\r
+            Mouse.OverrideCursor = Cursors.Wait;\r
+            try\r
+            {\r
+                //string[] args = new string[7];\r
+                string address = mBoard.mAddress;\r
+                string hostName, boardName;\r
+\r
+                if (!NTHttpUtils.parseHostAddress(address, out hostName, out boardName))\r
+                {\r
+                    throw new Exception();\r
+                }\r
+\r
+                string referer = "http://" + hostName + "/" + boardName;\r
+                string url = "http://" + hostName + "/test/bbs.cgi";\r
+                StringBuilder postData = new StringBuilder(256);\r
+\r
+                if (extra == null)\r
+                {\r
+                    TimeSpan ts = new TimeSpan(0, 10, 0);\r
+                    int time = NTHttpUtils.GetTime(DateTime.Now.Subtract(ts));\r
+\r
+                    postData.Append("submit=").Append(HttpUtility.UrlEncode("新規スレッド作成画面へ", enc))\r
+                    .Append("&bbs=").Append(boardName)\r
+                    .Append("&time=").Append(time);\r
+                    if (extraParam != null)\r
+                        postData.Append(extraParam);\r
+                    result = NTHttpAccess.createThread(url, referer, hostName, postData.ToString());\r
+\r
+                    if (result == null)\r
+                    {\r
+                        errorMsg = "サーバーの応答が不正です";\r
+                        return null;\r
+                    }\r
+\r
+                    doc = new FlowDocument();\r
+                    NTHtmlParser parser = new NTHtmlParser(doc);\r
+                    string resultHtml = parser.parse(result);\r
+                    if (resultHtml == null)\r
+                    {\r
+                        errorMsg = "サーバーの応答が不正です";\r
+                        return null;\r
+                    }\r
+\r
+                    postData.Remove(0, postData.Length);\r
+\r
+                    if (parser.mInputTypeSubmit.Count == 0 || parser.mInputTypeHidden.Count == 0)\r
+                    {\r
+                        postData.Append("submit=").Append(HttpUtility.UrlEncode("新規スレッド作成", enc))\r
+                            .Append("&bbs=").Append(boardName)\r
+                            .Append("&time=").Append(time);\r
+                        //errorMsg = "サーバーの応答が不正です";\r
+                        //return null;\r
+                    }\r
+                    else\r
+                    {\r
+                        postData.Append(parser.mInputTypeSubmit[0].Key)\r
+                            .Append('=')\r
+                            .Append(HttpUtility.UrlEncode(parser.mInputTypeSubmit[0].Value, enc));\r
+                    }\r
+                    postData.Append("&subject=")\r
+                        .Append(HttpUtility.UrlEncode(mTitle, enc))\r
+                        .Append("&FROM=")\r
+                        .Append(HttpUtility.UrlEncode(mName, enc))\r
+                        .Append("&mail=")\r
+                        .Append(HttpUtility.UrlEncode(mMail, enc))\r
+                        .Append("&MESSAGE=")\r
+                        .Append(HttpUtility.UrlEncode(mMsg, enc));\r
+\r
+\r
+\r
+                    foreach (KeyValuePair<string, string> pair in parser.mInputTypeHidden)\r
+                    {\r
+                        postData.Append('&').Append(pair.Key)\r
+                            .Append('=')\r
+                            .Append(HttpUtility.UrlEncode(pair.Value, enc));\r
+                    }\r
+\r
+                    if (extraParam != null)\r
+                        postData.Append(extraParam);\r
+                }\r
+                else\r
+                {\r
+                    if (extra.mInputTypeSubmit.Count == 0 || extra.mInputTypeHidden.Count == 0)\r
+                    {\r
+                        errorMsg = "サーバーの応答が不正です";\r
+                        return null;\r
+                    }\r
+\r
+                    //postData = new StringBuilder();\r
+\r
+                    postData.Append(extra.mInputTypeSubmit[0].Key)\r
+                        .Append('=')\r
+                        .Append(HttpUtility.UrlEncode(extra.mInputTypeSubmit[0].Value, enc));\r
+                    foreach (KeyValuePair<string, string> pair in extra.mInputTypeHidden)\r
+                    {\r
+                        postData.Append('&').Append(pair.Key)\r
+                            .Append('=')\r
+                            .Append(HttpUtility.UrlEncode(pair.Value, enc));\r
+                    }\r
+                    if (extraParam != null)\r
+                        postData.Append(extraParam);\r
+\r
+                }\r
+\r
+                result = NTHttpAccess.createThread(url, url, hostName, postData.ToString());\r
+\r
+                if (result == null)\r
+                {\r
+                    errorMsg = "サーバーの応答が不正です";\r
+                    return null;\r
+                }\r
+            }\r
+            catch\r
+            {\r
+                return null;\r
+            }\r
+            finally\r
+            {\r
+                Mouse.OverrideCursor = null;\r
+            }\r
+\r
+            doc = new FlowDocument();\r
+            NTHtmlParser htmlParser = new NTHtmlParser(doc);\r
+            string parsedHtml = htmlParser.parse(result);\r
+            if (parsedHtml == null)\r
+            {\r
+                errorMsg = "サーバーの応答が不正です";\r
+                return null;\r
+            }\r
+\r
+            X_CONFIRM_RESULT xResult = NTHtmlWriteResParser.validateResult(htmlParser);\r
+            if (xResult == X_CONFIRM_RESULT.SUCCESS)\r
+                return result;\r
+\r
+            NTDebug.l(parsedHtml);\r
+            NTWriteResResultWindow w\r
+                = new NTWriteResResultWindow(htmlParser.getTitle(), doc, xResult);\r
+            w.Owner = this;\r
+            bool? bRet = w.ShowDialog();\r
+\r
+            if (bRet.HasValue && ((bool)bRet))\r
+            {\r
+                List<KeyValuePair<string, string>> list = htmlParser.mInputTypeSubmit;\r
+                if (list.Count > 0)\r
+                {\r
+                    return createThread(out errorMsg, htmlParser);\r
+                }\r
+            }\r
+            return result;\r
+        }\r
+\r
+\r
+\r
+        string createThreadP2(out string errorMsg)\r
+        {\r
+            //bool bRet = false;\r
+            string result = null;\r
+            errorMsg = string.Empty;\r
+\r
+            Mouse.OverrideCursor = Cursors.Wait;\r
+            try\r
+            {\r
+                string[] args = new string[7];\r
+                string address = mBoard.mAddress;\r
+                string hostName, boardName;\r
+\r
+                if (!NTHttpUtils.parseHostAddress(address, out hostName, out boardName))\r
+                {\r
+                    throw new Exception();\r
+                }\r
+                args[0] = hostName;\r
+                args[1] = boardName;\r
+                args[2] = mName;\r
+                args[3] = mMail;\r
+                args[4] = mTitle;\r
+                args[5] = mMsg;\r
+                args[6] = "新規スレッド作成";\r
+\r
+                result = NTHttpAccess.createThreadP2(args, null, false);\r
+\r
+            }\r
+            catch\r
+            {\r
+                return null;\r
+            }\r
+            finally\r
+            {\r
+                Mouse.OverrideCursor = null;\r
+            }\r
+\r
+            FlowDocument doc = new FlowDocument();\r
+            NTHtmlParser htmlParser = new NTHtmlParser(doc);\r
+            string parsedHtml = htmlParser.parse(result);\r
+            if (parsedHtml == null)\r
+            {\r
+                errorMsg = "サーバーの応答が不正です";\r
+                return null;\r
+            }\r
+\r
+            X_CONFIRM_RESULT xResult = NTHtmlWriteResParser.validateResult(htmlParser);\r
+            if (xResult == X_CONFIRM_RESULT.SUCCESS)\r
+                return result;\r
+\r
+            NTDebug.l(parsedHtml);\r
+            NTWriteResResultWindow w\r
+                = new NTWriteResResultWindow(htmlParser.getTitle(), doc, xResult);\r
+            w.Owner = this;\r
+            bool? bRet = w.ShowDialog();\r
+\r
+            if (bRet.HasValue && ((bool)bRet))\r
+            {\r
+                List<KeyValuePair<string, string>> list = htmlParser.mInputTypeSubmit;\r
+                if (list.Count > 0)\r
+                {\r
+                    return createThreadP2(out errorMsg);\r
+                }\r
+            }\r
+            return result;\r
+        }\r
+\r
+\r
+\r
+\r
+\r
+    }\r
+}\r
diff --git a/NT2chView45/NTDataRoot.cs b/NT2chView45/NTDataRoot.cs
new file mode 100755 (executable)
index 0000000..54c1463
--- /dev/null
@@ -0,0 +1,70 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+\r
+namespace NT2chView\r
+{\r
+    static class NTDataRoot\r
+    {\r
+\r
+        public static List<NTCategory> mCategoryList;\r
+        public const string EXTERNAL_BOARD_CATEGORY_NAME = "外部板";\r
+\r
+        public static NTCategory getExternalBoards()\r
+        {\r
+            if (null == mCategoryList)\r
+                return null;\r
+\r
+            foreach (NTCategory category in mCategoryList)\r
+            {\r
+                if(category.mName.Equals(EXTERNAL_BOARD_CATEGORY_NAME))\r
+                    return category;\r
+            }\r
+            NTCategory c =  new NTCategory(EXTERNAL_BOARD_CATEGORY_NAME);\r
+            mCategoryList.Add(c);\r
+            return c;\r
+        }\r
+\r
+        //public static string mWroteMsg = null;\r
+        \r
+        public static NTBoard getBoardByName(string name)\r
+        {\r
+            for (int i = mCategoryList.Count - 1;\r
+                i >= 0; i--)\r
+            {\r
+                NTBoard board = mCategoryList[i].getBoardByName(name);\r
+                if (board != null)\r
+                    return board;\r
+            }\r
+            return null;\r
+        }\r
+\r
+        public static NTBoard getBoardByAddress(string address)\r
+        {\r
+            for (int i = mCategoryList.Count - 1;\r
+                i >= 0; i--)\r
+            {\r
+                NTBoard board = mCategoryList[i].getBoardByAddress(address);\r
+                if (board != null)\r
+                    return board;\r
+            }\r
+            return null;\r
+        }\r
+\r
+        public static NTBoard getMatchBoard(string searchAddress)\r
+        {\r
+            for (int i = mCategoryList.Count - 1;\r
+                i >= 0; i--)\r
+            {\r
+                NTBoard board = mCategoryList[i].getMatchBoard(searchAddress);\r
+                if (board != null)\r
+                    return board;\r
+            }\r
+            return null;\r
+\r
+        }\r
+\r
+\r
+\r
+    }\r
+}\r
diff --git a/NT2chView45/NTDebug.cs b/NT2chView45/NTDebug.cs
new file mode 100755 (executable)
index 0000000..5dd7674
--- /dev/null
@@ -0,0 +1,18 @@
+#define TRACE\r
+\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Diagnostics;\r
+\r
+\r
+namespace NT2chView\r
+{\r
+    class NTDebug\r
+    {\r
+        public static void l(string message)\r
+        {\r
+            System.Diagnostics.Debug.WriteLine(message);\r
+        }\r
+    }\r
+}\r
diff --git a/NT2chView45/NTDragDrop.cs b/NT2chView45/NTDragDrop.cs
new file mode 100755 (executable)
index 0000000..02b18df
--- /dev/null
@@ -0,0 +1,61 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+\r
+namespace NT2chView.NtUI\r
+{\r
+    class NTDragDrop\r
+    {\r
+        public const string THREAD_DRAG_DATA_FORMAT = "threadDragDataFormat";\r
+        public const string BOARD_DRAG_DATA_FORMAT = "boardDragDataFormat";\r
+        public const string RES_VIEW_TOOLBAR_DRAG_FORMAT = "resview_toolbar_dragdrop";\r
+        public const string THREADTITLE_VIEW_TOOLBAR_DRAG_FORMAT = "threadtitleview_toolbar_dragdrop";\r
+\r
+        public const int DRAG_START_MOVE_DELTA = 8;\r
+\r
+        public const int TOOLBAR_LOCATION_LEFT = 1;\r
+        public const int TOOLBAR_LOCATION_RIGHT = 2;\r
+\r
+\r
+        public class BoardData\r
+        {\r
+            private string mBoardName;\r
+            public string BoardName { get { return mBoardName; } }\r
+            public BoardData(string boardName)\r
+            {\r
+                mBoardName = boardName;\r
+            }\r
+        }\r
+\r
+        public class ThreadData\r
+        {\r
+            private string mAddress;\r
+            private string mBoardName;\r
+            private string mTitle;\r
+            public string Address { get { return mAddress; } }\r
+            public string Title { get { return mTitle; } }\r
+            public string BoardName { get { return mBoardName; } }\r
+\r
+            public ThreadData(NTFavoriteThread thread)\r
+            {\r
+                mAddress = thread.Address;\r
+                mBoardName = thread.BoardName;\r
+                mTitle = thread.Title;\r
+            }\r
+\r
+        }\r
+\r
+        public class ResViewToolbarData\r
+        {\r
+\r
+        }\r
+\r
+        public class ThreadTitleToolbarData\r
+        {\r
+        }\r
+\r
+\r
+    }\r
+\r
+\r
+}\r
diff --git a/NT2chView45/NTExportUtil.cs b/NT2chView45/NTExportUtil.cs
new file mode 100755 (executable)
index 0000000..18b35f2
--- /dev/null
@@ -0,0 +1,623 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Diagnostics;\r
+using System.IO;\r
+using System.Text;\r
+using System.Windows.Controls;\r
+using System.Windows.Forms;\r
+using System.Windows.Input;\r
+using NT2chCtrl;\r
+using NT2chView.NtFile;\r
+using NT2chView.NtHtml;\r
+using NT2chView.NtNet;\r
+using NT2chObject;\r
+using System.Threading;\r
+using System.ComponentModel;\r
+using System.Windows.Media.Imaging;\r
+using System.Net;\r
+\r
+namespace NT2chView\r
+{\r
+    class NTExportUtil : IUtil, ICommand2\r
+    {\r
+        public event MainWindow.DelegateMsgOpenThreadTitleListRequest MsgOpenThreadTitleListRequest;\r
+\r
+        static string mRootPath;\r
+        const string ROOTDIR_NAME = @"\ExternalControlData";\r
+        \r
+        public static void init(string rootPath)\r
+        {\r
+            mRootPath = rootPath + ROOTDIR_NAME;\r
+            DirectoryInfo dir = new DirectoryInfo(mRootPath);\r
+            if (!dir.Exists)\r
+                dir.Create();\r
+            \r
+            Worker.init(5);\r
+        }\r
+\r
+        public int GetApplicationApiVersion() \r
+        { \r
+            return 1;\r
+        }\r
+\r
+        public string GetDataPath()\r
+        {\r
+            return (mRootPath == null) ? string.Empty : mRootPath;\r
+        }\r
+\r
+        public Dictionary<PREF_PARAM, object> GetPreference()\r
+        {\r
+            return NTUserPreference.getExportPreference();\r
+        } \r
+\r
+        public int ParseResLinkReference(string source, int startPosition)\r
+        {\r
+            return NTTextFormat.parse2chNumA(source, startPosition);\r
+        }\r
+        \r
+        public int[] ParseResLinkReferenceNumber(string source)\r
+        {\r
+            List<int> arr = NTTextFormat.parseReferenceNumber(source);\r
+            if (arr != null)\r
+            {\r
+                return arr.ToArray();\r
+            }\r
+            return null;\r
+        }\r
+\r
+        string[] httpSchem = { "http://", "https://", "ttp://", "ttps://"};\r
+        public int ParseURLString(string source, int startIndex)\r
+        {\r
+            foreach(string schem in httpSchem)\r
+            {\r
+                if (myCompare(schem, source, startIndex))\r
+                {\r
+                    int n = NTHtmlUtils.parseWebAddress(source, startIndex + schem.Length);\r
+                    if( n <= 0)// || n < (startIndex+schem.Length))\r
+                        continue;\r
+                    return n + schem.Length;\r
+                }\r
+            }\r
+            return -1;\r
+        }\r
+        private static bool myCompare(string target, string source, int startIndex)\r
+        {\r
+            int len= target.Length;\r
+            if (source.Length < len+startIndex)\r
+                return false;\r
+            for (int i = 0; i < len; i++)\r
+            {\r
+                if (target[i] != source[i+startIndex])\r
+                    return false;\r
+            }\r
+            return true;\r
+        }\r
+\r
+        public void ExecURL(string url)\r
+        {\r
+            if (Keyboard.Modifiers == ModifierKeys.Shift)\r
+            {\r
+                Process.Start(url);\r
+                return;\r
+            }\r
+            string youtubeId;\r
+            //string url = uri.AbsoluteUri;\r
+            string boardAddress, datName;\r
+            if (NTHttpUtils.parseBBSAddress(url, out boardAddress, out datName))\r
+            {\r
+\r
+                NTBoard board = NTDataRoot.getBoardByAddress(boardAddress);\r
+                if (board == null)\r
+                {\r
+                    MessageBox.Show("そんな板無いです。" +\r
+                         "\nShitキーを押しながらリンクをクリックするとブラウザーで開きます。");\r
+                    return;\r
+                }\r
+\r
+                if (!NTAppState.getMainWindow().OpenNewBoard(board))\r
+                {\r
+                    MessageBox.Show("板が開けませんでした。" +\r
+                         "\nShitキーを押しながらリンクをクリックするとブラウザーで開きます。");\r
+                    return;\r
+                }\r
+                NTThreadTitle tt = board.findThreadTitleByDatName(datName);\r
+                if (tt == null)\r
+                {\r
+                    if (NTUserPreference.MaruIsEnabled)\r
+                    {\r
+                        tt = board.addExtraThread(datName, null);\r
+                    }\r
+                    if (tt == null)\r
+                    {\r
+                        MessageBox.Show("スレッドが見つかりませんでした。" +\r
+                           "\nShitキーを押しながらリンクをクリックするとブラウザーで開きます。");\r
+                        return;\r
+                    }\r
+                }\r
+                NTAppState.getMainWindow().OpenNewThread(tt);\r
+            }\r
+            else if(NTUserPreference.OpenYoutubeOnApp && \r
+                NTHttpUtils.TryParseYouTubeId(url, out youtubeId))\r
+            {\r
+                NTAppState.getMainWindow().OpenMoviePanel(youtubeId);\r
+            }\r
+            else\r
+            {\r
+                Process.Start(url);\r
+            }\r
+        }\r
+\r
+        //ユーザーの設定ファイルから\r
+        //レス画面用のコンテキストメニューを生成します。\r
+        public void CreateResViewContextMenu(FlowDocumentScrollViewer sv)\r
+        {\r
+            NTResMenuCommand.createContextMenu(sv);\r
+        }\r
+\r
+\r
+\r
+        public void OpenThread(IThreadDescription threadDesc)\r
+        {\r
+            if (threadDesc == null)\r
+                return;\r
+            NTBoard board = threadDesc.getBoard() as NTBoard;\r
+            if (board == null)\r
+                return;\r
+\r
+            string strSubject = null;\r
+            if (!board.mDataInit)\r
+            {\r
+                if (!NTFileAccess.isSubjectExsists(board.mName))\r
+                    if (!NTHttpAccess.getSubject(board.mAddress, board.mName))\r
+                        return;\r
+\r
+                strSubject = NTFileAccess.retrieveSubjectDataFromFile(board.mName);\r
+                if (strSubject == null)\r
+                    return;\r
+\r
+                if (!board.parseSubjectData(strSubject, NTAppState.getMainWindow().getFavoriteData()))\r
+                    return;\r
+            }\r
+\r
+            NTThreadTitle tt = board.findThreadTitleByDatName(\r
+                        threadDesc.getDatName());\r
+            if (tt == null)\r
+                return;\r
+\r
+            NTAppState.getMainWindow().OpenNewThread(tt);\r
+        }\r
+\r
+        public void AddBoardToFavorite(IBoard iboard)\r
+        {\r
+            NTAppState.getMainWindow().addFavoriteBoard(iboard.getName());\r
+        }\r
+\r
+        public bool AddThreadToFavorite(IThreadDescription threadDesc)\r
+        {\r
+            if (threadDesc == null)\r
+                return  false;\r
+            NTBoard board = threadDesc.getBoard() as NTBoard;\r
+            if (board == null)\r
+                return false;\r
+\r
+            string strSubject = null;\r
+            if (!board.mDataInit)\r
+            {\r
+                if (!NTFileAccess.isSubjectExsists(board.mName))\r
+                    if (!NTHttpAccess.getSubject(board.mAddress, board.mName))\r
+                        return false;\r
+\r
+                strSubject = NTFileAccess.retrieveSubjectDataFromFile(board.mName);\r
+                if (strSubject == null)\r
+                    return false;\r
+\r
+                if (!board.parseSubjectData(strSubject, NTAppState.getMainWindow().getFavoriteData()))\r
+                    return false;\r
+            }\r
+\r
+            NTThreadTitle tt = board.findThreadTitleByDatName(\r
+                        threadDesc.getDatName());\r
+            if (tt == null)\r
+                return false;\r
+\r
+            NTAppState.getMainWindow().addFavoriteThread(tt);\r
+            return true;\r
+        }\r
+\r
+        public bool RemoveThreadFromFavorite(IThreadDescription threadDesc)\r
+        {\r
+            if (threadDesc == null)\r
+                return false;\r
+            NTBoard board = threadDesc.getBoard() as NTBoard;\r
+            if (board == null)\r
+                return false;\r
+\r
+            string strSubject = null;\r
+            if (!board.mDataInit)\r
+            {\r
+                if (!NTFileAccess.isSubjectExsists(board.mName))\r
+                    if (!NTHttpAccess.getSubject(board.mAddress, board.mName))\r
+                        return false;\r
+\r
+                strSubject = NTFileAccess.retrieveSubjectDataFromFile(board.mName);\r
+                if (strSubject == null)\r
+                    return false;\r
+\r
+                if (!board.parseSubjectData(strSubject, NTAppState.getMainWindow().getFavoriteData()))\r
+                    return false;\r
+            }\r
+\r
+            NTThreadTitle tt = board.findThreadTitleByDatName(\r
+                        threadDesc.getDatName());\r
+            if (tt == null)\r
+                return false;\r
+\r
+            NTAppState.getMainWindow().removeFavoriteThread(tt);\r
+            return true;\r
+        }\r
+\r
+        //指定したスレッドの取得済ログを消去します\r
+        //クラウド同期が有効な場合、クラウドの同期情報も削除されます。\r
+        public void DeleteLog(IThread ithread)\r
+        {\r
+            NTThreadTitle tt = ithread as NTThreadTitle;\r
+            if (tt == null)\r
+                return;\r
+            tt.delDat();\r
+        }\r
+\r
+        //指定した板に含まれるスレッドの全ての取得済ログを消去します\r
+        //クラウド同期が有効な場合、クラウドの同期情報も削除されます。\r
+        public void DeleteLog(IBoard iboard)\r
+        {\r
+            NTBoard board = iboard as NTBoard;\r
+            if (board == null)\r
+                return;\r
+            board.delAllDat();\r
+        }\r
+\r
+        //指定したスレッドと類似したタイトルを持つ\r
+        //スレッドを検索します。表示方法はフレームワークが\r
+        //決定するので、呼び出し側ではコールバックを受け取りません\r
+        public void SearchSimilarTitle(IThread2 ithread)\r
+        {\r
+\r
+            NTThreadTitle tt = ithread.getDependencyObject() as NTThreadTitle;\r
+            if (tt == null)\r
+                return;\r
+\r
+            NTAppState.getMainWindow().setupTitleSearchListBySimString(tt);\r
+\r
+        }\r
+\r
+\r
+        //レスにブックマークをつけるように要求します\r
+        public bool AddBookmark(IThread ithread, IRes ires)\r
+        {\r
+            NTThreadTitle tt = ithread as NTThreadTitle;\r
+            if (tt == null)\r
+                return false;\r
+            NTRes res = ires as NTRes;\r
+            if (res == null)\r
+                return false;\r
+\r
+            res.mBookmark = true;\r
+\r
+            int seqNo = ires.getSequenceNo();\r
+            tt.addBookmark(seqNo);\r
+             return true;\r
+        }\r
+\r
+        //レスにブックマークをつけるように要求します\r
+        public bool DeleteBookmark(IThread ithread, IRes ires)\r
+        {\r
+            NTThreadTitle tt = ithread as NTThreadTitle;\r
+            if (tt == null)\r
+                return false;\r
+            NTRes res = ires as NTRes;\r
+            if (res == null)\r
+                return false;\r
+\r
+            res.mBookmark = false;\r
+\r
+            int seqNo = ires.getSequenceNo();\r
+            tt.removeBookmark(seqNo);\r
+            return true;\r
+        }\r
+        //スレッドを指定して、書き込み用のダイアログを開きます。\r
+        //名前、E-Mail、メッセージの初期値を指定できます。\r
+        //指定する値がない場合、nullを指定できます。\r
+        public bool WriteMessage(IThread ithread, string message)\r
+        {\r
+            NTThreadTitle thread = ithread as NTThreadTitle;// findSelectedThreadTitle();\r
+            if (thread == null)\r
+            {\r
+                MessageBox.Show("書き込む板が見つかりません。");\r
+                return false;\r
+            }\r
+            NTAppState.getMainWindow().WriteRes_Invoke(thread, message);\r
+            return true;\r
+        }\r
+        public bool CreateThread(IBoard iboard, string title, string message)\r
+        {\r
+            //NTAppState.getMainWindow().\r
+            NTBoard board = iboard as NTBoard;\r
+            if (board == null)\r
+                return false;\r
+\r
+            NTCreateThreadWindow wnd = new NTCreateThreadWindow(board, title, message);\r
+            wnd.ShowDialog();\r
+            return true;\r
+        }\r
+\r
+        public void ShowThreadInfoWindow(string title, string address)\r
+        {\r
+            NTThreadInfoWindow wnd = new NTThreadInfoWindow(title, address);\r
+            wnd.ShowDialog();\r
+        }\r
+        \r
+        //板オブジェクトを指定して、板を開きます。\r
+        public void TryToOpenBoard(IBoard iboard)\r
+        {\r
+            NTBoard board = iboard as NTBoard;\r
+            if (board == null)\r
+                return;\r
+\r
+            if (MsgOpenThreadTitleListRequest != null)\r
+                MsgOpenThreadTitleListRequest(board);\r
+        }\r
+\r
+        //板オブジェクトを指定して、板を更新します。\r
+        public void UpdateBoard(IBoard iboard)\r
+        {\r
+            NTBoard board = iboard as NTBoard;\r
+            if (board == null)\r
+                return;\r
+            board.Update(null);\r
+        }\r
+\r
+        //NGワード編集ダイアログを開きます。\r
+        //iresを指定すると、そのレスからNGに指定する各項目の文字列を\r
+        //抽出して初期設定します。\r
+        public void ShowNgwordDialog(IRes ires) {\r
+            NTRes res = ires as NTRes;\r
+            if(res != null)\r
+                NTAppState.getMainWindow().NgEdit_setResSection(res);\r
+        }\r
+\r
+        //設定されているNGワード文字列のリストを取得します\r
+        public string[] GetNgWordList()\r
+        {\r
+            NTNgItems ngItem = NTNgItems.getContext();\r
+            List<string> list = ngItem.getNgWords();\r
+            return list.ToArray();\r
+        }\r
+\r
+        //設定されているNG-ID文字列のリストを取得します\r
+        public string[] GetNgIdList()\r
+        {\r
+            NTNgItems ngItem = NTNgItems.getContext();\r
+            List<string> list = ngItem.getNgIds();\r
+            return list.ToArray();\r
+        }\r
+\r
+        //設定されているNG-NAME文字列のリストを取得します\r
+        public string[] GetNgNameList()\r
+        {\r
+            NTNgItems ngItem = NTNgItems.getContext();\r
+            List<string> list = ngItem.getNgNames();\r
+            return list.ToArray();\r
+        }\r
+\r
+        public IAmbiguousSearch CreateAmbiguousSearchInstance(string word)\r
+        {\r
+            NTVagueSearchWord v = new NTVagueSearchWord(word);\r
+\r
+            return v;\r
+        }\r
+\r
+        public void SetThumbnailImage(ThumbnailImageHelper helper, string url)\r
+        {\r
+            Worker.RunWorker(helper, url);\r
+            //BackgroundWorker worker = new BackgroundWorker();\r
+            //worker.DoWork += DoWork;\r
+\r
+            //+= new DoWorkEventHandler(DoWork);\r
+            //worker.RunWorkerCompleted += RunWorkerCompleted;\r
+            //+=\r
+            //  new RunWorkerCompletedEventHandler(RunCompleted);\r
+\r
+            //worker.Run(url);\r
+        }\r
+\r
+\r
+        public class Worker// : BackgroundWorker\r
+        {\r
+            static Semaphore mSemaphore;\r
+            static int mConnections;\r
+            public static void init(int nSemaphoreCount)\r
+            {\r
+                if (nSemaphoreCount <= 0)\r
+                    nSemaphoreCount = 1;\r
+                else if (nSemaphoreCount > 20)\r
+                    nSemaphoreCount = 20;\r
+                mConnections = nSemaphoreCount;\r
+                mSemaphore = new Semaphore(nSemaphoreCount, nSemaphoreCount);\r
+            }\r
+\r
+            public static void resetConnectionCount(int count)\r
+            {\r
+                if (mConnections == count)\r
+                    return;\r
+                init(count);\r
+            }\r
+\r
+            static Dictionary<string , object> mFileNameLock\r
+                = new Dictionary<string,object>();\r
+\r
+            static object GetLock(string path)\r
+            {\r
+                object o;\r
+                lock (mFileNameLock)\r
+                {\r
+                    if (mFileNameLock.ContainsKey(path))\r
+                    {\r
+                        if (mFileNameLock.TryGetValue(path, out o))\r
+                            return o;\r
+                    }\r
+                    else\r
+                    {\r
+                        o = new object();\r
+                        mFileNameLock.Add(path, o);\r
+                    }\r
+\r
+                }\r
+                return o;\r
+            }\r
+\r
+            ThumbnailImageHelper mParent;\r
+            string mUrl;\r
+            string mFullPath;\r
+            public static void RunWorker(ThumbnailImageHelper helper, string url)\r
+            {\r
+                string path;\r
+                string file;\r
+\r
+                try\r
+                {\r
+                    if (NtFile.NTFileUtil.Url2FilePath(url, out path, out file))\r
+                    {\r
+                        Directory.CreateDirectory(path);\r
+\r
+                        Worker w = new Worker();\r
+                        w.mParent = helper;\r
+                        w.mUrl = url;\r
+                        w.mFullPath = path + '\\' + file;\r
+                        BackgroundWorker mWorker = new BackgroundWorker();\r
+                        mWorker.DoWork += worker_DoWork;\r
+                        mWorker.RunWorkerCompleted += worker_RunWorkerCompleted;\r
+                        mWorker.RunWorkerAsync(w);\r
+                    }\r
+                }\r
+                catch (DirectoryNotFoundException e)\r
+                {                    \r
+                }\r
+            }\r
+\r
+             static void worker_DoWork(object sender, DoWorkEventArgs e)\r
+            {\r
+\r
+                Worker w = e.Argument as Worker;\r
+                if (w == null)\r
+                    return;\r
+                if (w.mUrl == null)\r
+                    return;\r
+                if (w.mFullPath == null)\r
+                    return;\r
+\r
+                try\r
+                {\r
+                    object objLock = GetLock(w.mFullPath);\r
+                    if (objLock == null)\r
+                        objLock = new object();\r
+                    lock (objLock)\r
+                    {\r
+                        if (!File.Exists(w.mFullPath))\r
+                        {\r
+                            \r
+                            WebClient wc = new WebClient();\r
+                            try\r
+                            {\r
+                                mSemaphore.WaitOne();\r
+                                wc.DownloadFile(new Uri(w.mUrl), w.mFullPath);\r
+                            }\r
+                            finally\r
+                            {\r
+                                mSemaphore.Release();\r
+                            }\r
+                            wc.Dispose();\r
+                        }\r
+                    }\r
+                    e.Result = w;\r
+\r
+                }\r
+                catch (Exception ex)\r
+                {\r
+\r
+                }\r
+                finally\r
+                {\r
+                }\r
+            }\r
+\r
+            static void worker_RunWorkerCompleted(object sender,\r
+                System.ComponentModel.RunWorkerCompletedEventArgs e)\r
+            {\r
+                Worker w = e.Result as Worker;\r
+                if (w == null)\r
+                    return;\r
+                                   \r
+                object objLock = GetLock(w.mFullPath);\r
+                if (objLock == null)\r
+                    objLock = new object();\r
+\r
+                BitmapImage bi = new BitmapImage();\r
+\r
+                lock (objLock)\r
+                {\r
+\r
+                    bi.BeginInit();\r
+\r
+                    bi.CacheOption = BitmapCacheOption.OnDemand;\r
+                    bi.CreateOptions = BitmapCreateOptions.DelayCreation;\r
+                    bi.DecodePixelHeight = NTUserPreference.ResViewThumbnailHeight;\r
+                    bi.DecodePixelWidth = NTUserPreference.ResViewThumbnailWidth;\r
+                    bi.UriSource = new Uri(w.mFullPath, UriKind.Absolute);\r
+\r
+                    bi.EndInit();\r
+                }\r
+\r
+\r
+                Image img = new Image();\r
+                img.Stretch = System.Windows.Media.Stretch.UniformToFill;\r
+                img.Width = NTUserPreference.ResViewThumbnailWidth;\r
+                img.Height = NTUserPreference.ResViewThumbnailHeight;\r
+                img.Source = bi;\r
+                img.MouseLeftButtonDown += img_MouseLeftButtonDown;\r
+                //img.MouseLeftButtonUp += img_MouseLeftButtonUp;\r
+                img.Tag = w.mFullPath;\r
+                w.mParent.SetImage(img);\r
+\r
+\r
+                    //mParent.setImage(image);\r
+            }\r
+\r
+           // static Image mClickedImage;\r
+            static void img_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)\r
+            {\r
+                //if (mClickedImage == null)\r
+                //    return;\r
+                //if (!sender.Equals(mClickedImage))\r
+                //{\r
+                //    mClickedImage = null;\r
+                //    return;\r
+                //}\r
+\r
+           }\r
+\r
+            static void img_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)\r
+            {\r
+                Image img = sender as Image;\r
+                if (img == null)\r
+                    return;\r
+\r
+                string path = img.Tag as string;\r
+                if (path == null)\r
+                    return;\r
+\r
+                NTAppState.getMainWindow().AddGraphic(path);\r
+\r
+            }\r
+        }\r
+    }\r
+} \r
diff --git a/NT2chView45/NTFavorite.cs b/NT2chView45/NTFavorite.cs
new file mode 100755 (executable)
index 0000000..77258a6
--- /dev/null
@@ -0,0 +1,519 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Threading;\r
+using NT2chView.NtFile;\r
+using NT2chView.NtNet;\r
+\r
+namespace NT2chView\r
+{\r
+    public sealed class NTFavorite\r
+    {\r
+\r
+        List<NTFavoriteBoard> mBoardList = new List<NTFavoriteBoard>();\r
+        List<NTFavoriteThread> mThreadList = new List<NTFavoriteThread>();\r
+        List<NTFavoriteThreadTag> mThreadTagList = new List<NTFavoriteThreadTag>();\r
+\r
+        \r
+        public NTFavorite()\r
+        { \r
+        \r
+        }\r
+\r
+        public int findBoard(string boardName)\r
+        {\r
+            int cnt = mBoardList.Count;\r
+            for (int i = 0; i < cnt; i++)\r
+            {\r
+                if (mBoardList[i].BoardName.Equals(boardName))\r
+                    return i;\r
+            }\r
+            return -1;\r
+        }\r
+\r
+        public int findThread(NTFavoriteThread thread)\r
+        {\r
+            int cnt = mThreadList.Count;\r
+            for (int i = 0; i < cnt; i++)\r
+            {\r
+                if (mThreadList[i].Equals(thread))\r
+                {\r
+                    return i;\r
+                }\r
+            }\r
+            return -1;\r
+        }\r
+\r
+        public int findThread(string boardName,\r
+            string address, string title)\r
+        {\r
+            int cnt = mThreadList.Count;\r
+            for (int i = 0; i < cnt; i++)\r
+            {\r
+                if (mThreadList[i].BoardName.Equals(boardName) &&\r
+                    mThreadList[i].Address.Equals(address) &&\r
+                    mThreadList[i].Title.Equals(title))\r
+                {\r
+                    return i;\r
+                }\r
+            }\r
+            return -1;\r
+        }\r
+\r
+        public NTFavoriteThreadTag findTag(string tagName)\r
+        {\r
+            foreach (NTFavoriteThreadTag tag in mThreadTagList)\r
+            {\r
+                if (tag.getTagName().Equals(tagName))\r
+                    return tag;\r
+            }\r
+            return null;\r
+        }\r
+\r
+        public NTFavoriteThreadTag findTag(NTFavoriteThread thread)\r
+        {\r
+            foreach (NTFavoriteThreadTag tag in mThreadTagList)\r
+            {\r
+                List<NTFavoriteThread> threadList = tag.getThreadList();\r
+                foreach (NTFavoriteThread ft in threadList)\r
+                {\r
+                    if(ft.Equals(thread))\r
+                        return tag;\r
+                }\r
+            }\r
+            return null;\r
+        }\r
+\r
+        public List<NTFavoriteBoard> getBoardList()\r
+        {\r
+            return mBoardList;\r
+        }\r
+\r
+        public List<NTFavoriteThread> getThreadList()\r
+        {\r
+            return mThreadList;\r
+        }\r
+\r
+        public List<NTFavoriteThreadTag> getThreadTagList()\r
+        {\r
+            return mThreadTagList;\r
+        }\r
+\r
+        public void parseBoardList(string boardList)\r
+        {\r
+            string[] lines = NTTextUtiles.splitLine(boardList);\r
+            foreach (string line in lines)\r
+            {\r
+                addBoardByDescription(line, true);\r
+            }\r
+        }\r
+\r
+        public NTFavoriteBoard addBoardByDescription(string boardDescriptiont, bool doEncode)\r
+        {\r
+            if (boardDescriptiont.Trim().Length == 0)\r
+                    return null;\r
+            NTFavoriteBoard fb = null;\r
+            if (doEncode)\r
+            {\r
+                string decSrc;\r
+                if(NTUserPreference.AESEnabled)\r
+                    decSrc = NTTextUtiles.aesDecodeBase64URL(boardDescriptiont);\r
+                else\r
+                    decSrc = NTTextUtiles.decodeBase64URL(boardDescriptiont);\r
+                \r
+                fb = new NTFavoriteBoard(decSrc);\r
+            }\r
+            else\r
+            {\r
+                fb = new NTFavoriteBoard(boardDescriptiont);\r
+            }\r
+            if(fb != null)\r
+                mBoardList.Add(fb);\r
+            return fb;\r
+        }\r
+\r
+        public void parseThreadList(string [] threadLists)\r
+        {\r
+            int cnt = mThreadList.Count;\r
+            if (cnt > 0)\r
+            {\r
+                mThreadList.RemoveRange(0, cnt);\r
+            }\r
+            string[] threads = NTTextUtiles.splitLine(threadLists[0]);\r
+            string[] tags = NTTextUtiles.splitLine(threadLists[1]);\r
+\r
+\r
+\r
+            foreach (string line in threads)\r
+            {\r
+                addThreadByDescription(line, true, false);\r
+            }\r
+\r
+            foreach (string line in tags)\r
+            {\r
+                addThreadTagByDescription(line, true, false);\r
+            }\r
+            int threadCnt = mThreadList.Count;\r
+            int threadIdx = 0;\r
+            foreach (NTFavoriteThreadTag tag in mThreadTagList)\r
+            {\r
+                int count = tag.getCount();\r
+                if ((count + threadIdx) > threadCnt)\r
+                {\r
+                    count = threadCnt - threadIdx;\r
+                    tag.setCount(count);\r
+                }\r
+                for (int i = 0; i < count; i++)\r
+                {\r
+                    tag.add(mThreadList[threadIdx + i]);\r
+                }\r
+\r
+                threadIdx += count;\r
+            }\r
+            if (threadIdx < threadCnt)\r
+                cnt = threadCnt - threadIdx;\r
+            else\r
+                cnt = 0;\r
+            NTFavoriteThreadTag tag1 = \r
+                new NTFavoriteThreadTag("お気に入りのスレ", \r
+                    cnt.ToString(), "open update");\r
+            for (int i = 0; i < cnt; i++)\r
+            {\r
+                tag1.add(mThreadList[threadIdx + i]);\r
+            }\r
+            mThreadTagList.Add(tag1);\r
+  \r
+\r
+        }\r
+\r
+        public bool removeBoardByBoardName(string boardName, bool save)\r
+        {\r
+            if (boardName.Trim().Length == 0)\r
+                return false;\r
+\r
+\r
+            \r
+            bool found = false;\r
+            foreach (NTFavoriteBoard fb in mBoardList)\r
+            {\r
+                if (fb.BoardName.Equals(boardName))\r
+                {\r
+                    found = true;\r
+                    mBoardList.Remove(fb);\r
+                    break;\r
+                }\r
+            }\r
+            if (!found)\r
+                return false;\r
+\r
+            if (save)\r
+            {\r
+\r
+                int cnt = mBoardList.Count;\r
+                List<string> descriptions = new List<string>();\r
+                foreach (NTFavoriteBoard fb in mBoardList)\r
+                {\r
+                    descriptions.Add(fb.BoardName);\r
+                }\r
+\r
+                NTFileAccess.updateFavoriteBoardToFile(descriptions.ToArray());\r
+\r
+                Thread th = new Thread(new ParameterizedThreadStart(removeFavoriteBoardFromCloud));\r
+                th.Start(boardName);\r
+            }\r
+            return true;\r
+\r
+        }\r
+\r
+        public bool removeThreadByDescription(string threadDescription, bool save)\r
+        {\r
+            if (threadDescription.Trim().Length == 0)\r
+                return false;\r
+\r
+            \r
+            string[] values = threadDescription.Split(NTTextUtiles.YEN_VALUE);\r
+            if (values.Length < 3)\r
+                return false;\r
+\r
+            bool found = false;\r
+            foreach (NTFavoriteThread ft in mThreadList)\r
+            {\r
+                if (ft.Same(values[0], values[1], values[2]))\r
+                {\r
+                    found = true;\r
+                    mThreadList.Remove(ft);\r
+                    break;\r
+                }\r
+            }\r
+            if (!found)\r
+                return false;\r
+\r
+            if (save)\r
+            {\r
+\r
+                int cnt = mThreadList.Count;\r
+                List<string> descriptions = new List<string>();\r
+                foreach(NTFavoriteThread ft in mThreadList)\r
+                {\r
+                    descriptions.Add(ft.getDescription());\r
+                }\r
+                NTFileAccess.updateFavoriteThreadToFile(descriptions.ToArray());\r
+\r
+                Thread th = new Thread(new ParameterizedThreadStart(removeFavoriteThreadFromCloud));\r
+                th.Start(threadDescription);\r
+            }\r
+            return true;\r
+\r
+        }\r
+\r
+        public NTFavoriteThread addThreadByDescription(string threadDescription, bool doEncode, bool save)\r
+        {\r
+            if (threadDescription.Trim().Length == 0)\r
+                    return null;\r
+            string decSrc;\r
+            if (doEncode)\r
+            {\r
+                if(NTUserPreference.AESEnabled)\r
+                    decSrc = NTTextUtiles.aesDecodeBase64URL(threadDescription);\r
+                else\r
+                    decSrc = NTTextUtiles.decodeBase64URL(threadDescription);\r
+            }\r
+            else\r
+            {\r
+                decSrc = threadDescription;\r
+            }\r
+\r
+            string[] values = decSrc.Split(NTTextUtiles.YEN_VALUE);\r
+            if (values.Length < 3)\r
+                return null;\r
+\r
+            foreach (NTFavoriteThread comp in mThreadList)\r
+            {\r
+                if (comp.Same(values[0], values[1], values[2]))\r
+                    return null;\r
+            }\r
+\r
+            NTFavoriteThread thread = new NTFavoriteThread(values[0], values[1], values[2]);\r
+            mThreadList.Add(thread);\r
+\r
+            if (save)\r
+            {\r
+                NTFileAccess.addFavoriteThreadToFile(decSrc);\r
+\r
+                Thread th = new Thread(uploadFavoriteThreadToCloud);\r
+                th.Start(decSrc);\r
+            }\r
+            return thread;\r
+\r
+        }\r
+\r
+        public NTFavoriteThreadTag addThreadTagByDescription(string tagDescription, bool doEncode, bool save)\r
+        {\r
+            return addThreadTagByDescription(tagDescription, doEncode, save, false);\r
+        }\r
+        public NTFavoriteThreadTag insertThreadTagByDescription(string tagDescription, bool doEncode, bool save)\r
+        {\r
+            return addThreadTagByDescription(tagDescription, doEncode, save, true);\r
+        }\r
+        private NTFavoriteThreadTag addThreadTagByDescription(string tagDescription, bool doEncode, bool save, bool insertLast)\r
+        {\r
+            if (tagDescription.Trim().Length == 0)\r
+                return null;\r
+            string decSrc;\r
+            if (doEncode)\r
+            {\r
+                if (NTUserPreference.AESEnabled)\r
+                    decSrc = NTTextUtiles.aesDecodeBase64URL(tagDescription);\r
+                else\r
+                    decSrc = NTTextUtiles.decodeBase64URL(tagDescription);\r
+            }\r
+            else\r
+            {\r
+                decSrc = tagDescription;\r
+            }\r
+\r
+            string[] values = decSrc.Split(NTTextUtiles.COMMA_VALUE);\r
+            if (values.Length < 3)\r
+                return null;\r
+\r
+\r
+            NTFavoriteThreadTag tag = new NTFavoriteThreadTag(values[0], values[1], values[2]);\r
+            if (insertLast)\r
+            {\r
+                int tagCnt = mThreadTagList.Count;\r
+                if (tagCnt == 0)\r
+                    return null;\r
+                mThreadTagList.Insert(tagCnt - 1, tag);\r
+            }\r
+            else\r
+            {\r
+                mThreadTagList.Add(tag);\r
+            }\r
+\r
+            if (save)\r
+            {\r
+                NTFileAccess.addFavoriteThreadTagToFile(decSrc);\r
+                string [] threadLists = NTFileAccess.retrieveFavoriteThreadFromFile();\r
+                //Thread th = new Thread(uploadFavoriteThreadTagToCloud);\r
+                //th.Start(threadLists[1]);\r
+            }\r
+            return tag;\r
+\r
+        }\r
+\r
+        public static void uploadFavoriteThreadToCloud(object t)\r
+        {\r
+            string src = t as string;\r
+            if (src == null)\r
+                return;\r
+\r
+            if (NTUserPreference.NTCloudIsEnabled)\r
+            {\r
+                string uid = NTUserPreference.NTCloudID;\r
+                string pass = NTUserPreference.NTCloudPSS;\r
+\r
+                List<string> boardList = new List<string>();\r
+                List<string> threadList = new List<string>();\r
+\r
+\r
+                threadList.Add(src);\r
+\r
+                string result = NTHttpAccess.ntUploadFavorites(uid, pass, boardList, threadList);\r
+            }\r
+        }\r
+\r
+        public static void uploadFavoriteBoardToCloud(object t)\r
+        {\r
+            string src = t as string;\r
+            if (src == null)\r
+                return;\r
+\r
+            if (NTUserPreference.NTCloudIsEnabled)\r
+            {\r
+                string uid = NTUserPreference.NTCloudID;\r
+                string pass = NTUserPreference.NTCloudPSS;\r
+\r
+                List<string> boardList = new List<string>();\r
+                List<string> threadList = new List<string>();\r
+\r
+\r
+                boardList.Add(src);\r
+\r
+                string result = NTHttpAccess.ntUploadFavorites(uid, pass, boardList, threadList);\r
+            }\r
+        }\r
+\r
+        public static void removeFavoriteBoardFromCloud(object o)\r
+        {\r
+            string boardDescription = o as string;\r
+            if (boardDescription == null)\r
+                return;\r
+\r
+            if (NTUserPreference.NTCloudIsEnabled)\r
+            {\r
+                string uid = NTUserPreference.NTCloudID;\r
+                string pass = NTUserPreference.NTCloudPSS;\r
+\r
+                List<string> boardList = new List<string>();\r
+                boardList.Add(boardDescription);\r
+\r
+                string result = NTHttpAccess.ntDeletedFavoriteBoard(uid, pass, boardList);\r
+            }\r
+\r
+        }\r
+\r
+        public static void removeFavoriteThreadFromCloud(object o)\r
+        {\r
+            string threadDescription = o as string;\r
+            if (threadDescription == null)\r
+                return;\r
+\r
+            if (NTUserPreference.NTCloudIsEnabled)\r
+            {\r
+                string uid = NTUserPreference.NTCloudID;\r
+                string pass = NTUserPreference.NTCloudPSS;\r
+\r
+                List<string> threadList = new List<string>();\r
+                threadList.Add(threadDescription);\r
+\r
+                string result = NTHttpAccess.ntDeletedFavoriteThread(uid, pass, threadList);\r
+            }\r
+        }\r
+\r
+        public void updateFavoriteBoards()\r
+        {\r
+            NTFileAccess.updateFavoriteBoardToFile(\r
+                NTFavoriteBoard.getStringArray(mBoardList).ToArray());\r
+           \r
+            if (NTUserPreference.NTCloudIsEnabled)\r
+            {\r
+                if (NTUserPreference.NTUserCloudIsEnabled)\r
+                {\r
+                    string uid = NTUserPreference.NTCloudID;\r
+                    //string pass = NTUserPreference.NTCloudPSS + NTUserPreference.NTUserCloudSeed;\r
+                    string hashedPass = NTUserPreference.NTUserCloudGetHashedPasswd(); \r
+                    //NTCrypt.getSHA256Hashed(pass);\r
+                    string result = NTHttpAccess.UserCloudUpdateFavoriteBoards(uid, hashedPass,\r
+                        NTFavoriteBoard.getStringArray(mBoardList));\r
+                }\r
+                else\r
+                {\r
+                    string uid = NTUserPreference.NTCloudID;\r
+                    string pass = NTUserPreference.NTCloudPSS;\r
+                    string result = NTHttpAccess.ntUpdateFavoriteBoards(uid, pass,\r
+                        NTFavoriteBoard.getStringArray(mBoardList));\r
+                }\r
+            }\r
+        }\r
+\r
+        public void updateFavoriteThread()\r
+        {\r
+            List<string> threadList = new List<string>(mThreadList.Count);\r
+            foreach (NTFavoriteThread ft in mThreadList)\r
+            {\r
+                threadList.Add(ft.getDescription());\r
+            }\r
+\r
+            NTFileAccess.updateFavoriteThreadToFile(threadList.ToArray());\r
+\r
+            List<string> tagList;\r
+            int tagCnt = mThreadTagList.Count;\r
+            if (tagCnt > 1)\r
+            {\r
+                tagCnt--;\r
+                tagList = new List<string>(tagCnt);\r
+\r
+                for(int i = 0; i < tagCnt; i++)\r
+                {\r
+                    NTFavoriteThreadTag tag = mThreadTagList[i];\r
+                    tagList.Add(tag.getDescription());\r
+                }\r
+            }\r
+            else\r
+            {\r
+                tagList = new List<string>();\r
+            }\r
+\r
+            NTFileAccess.updateFavoriteThreadTagToFile(tagList.ToArray());\r
+\r
+            if (NTUserPreference.NTCloudIsEnabled)\r
+            {\r
+                if (NTUserPreference.NTUserCloudIsEnabled)\r
+                {\r
+                    string uid = NTUserPreference.NTCloudID;\r
+                    //string pass = NTUserPreference.NTCloudPSS + NTUserPreference.NTUserCloudSeed;\r
+                    string hashedPass = NTUserPreference.NTUserCloudGetHashedPasswd(); \r
+                    //NTCrypt.getSHA256Hashed(pass);\r
+                    string result = NTHttpAccess.UserCloudUpdateFavoriteThreads(uid, hashedPass,\r
+                        threadList, tagList);\r
+                }\r
+                else\r
+                {\r
+                    string uid = NTUserPreference.NTCloudID;\r
+                    string pass = NTUserPreference.NTCloudPSS;\r
+                    string result = NTHttpAccess.ntUpdateFavoriteThreads(uid, pass, threadList, tagList);\r
+                }\r
+            }\r
+        }\r
+    }\r
+}\r
diff --git a/NT2chView45/NTFavoriteBoard.cs b/NT2chView45/NTFavoriteBoard.cs
new file mode 100755 (executable)
index 0000000..875f711
--- /dev/null
@@ -0,0 +1,120 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Windows;\r
+using System.Windows.Controls;\r
+using System.Windows.Controls.Primitives;\r
+using System.Windows.Media;\r
+using NT2chView.NtUI;\r
+\r
+namespace NT2chView\r
+{\r
+    public class NTFavoriteBoard\r
+    {\r
+        Button mButton;\r
+        Point mMouseObservePoint;\r
+        bool mMousePressed = false;\r
+        string mBoardName;\r
+        Brush mFavoriteBKBrush;\r
+        Brush mFavoriteDragOverBKBrush;\r
+        public NTFavoriteBoard(string boardName)\r
+        {\r
+            mBoardName = boardName;\r
+            mFavoriteDragOverBKBrush = (Brush)\r
+               NTAppState.getMainWindow().TryFindResource("FavoriteBoardDragOverBKBrush");\r
+            mFavoriteBKBrush = (Brush)\r
+                NTAppState.getMainWindow().TryFindResource("FavoritePanelBKBrush");\r
+        }\r
+\r
+        public void setDragOverBrush(bool isOver)\r
+        {\r
+            if (isOver)\r
+            {\r
+                if (mFavoriteDragOverBKBrush != null)\r
+                    mButton.Background = mFavoriteDragOverBKBrush;\r
+            }\r
+            else\r
+            {\r
+                if (mFavoriteBKBrush != null)\r
+                    mButton.Background = mFavoriteBKBrush;\r
+            }\r
+        }\r
+\r
+        public string BoardName\r
+        {\r
+            get { return mBoardName; }\r
+        }\r
+\r
+        public void setButton (Button button){\r
+            mButton = button;\r
+            //button.MouseLeftButtonDown += button_MouseLeftButtonDown;\r
+            button.PreviewMouseLeftButtonDown += button_PreviewMouseLeftButtonDown;\r
+            button.PreviewMouseMove += button_PreviewMouseMove;\r
+            //button.MouseLeftButtonUp += button_MouseLeftButtonUp;\r
+            //button.MouseMove += button_MouseMove;            \r
+        }\r
+\r
+\r
+\r
+        public static List<string> getStringArray(List<NTFavoriteBoard> boardList)\r
+        {\r
+            List<string> list = new List<string>();\r
+            foreach (NTFavoriteBoard fb in boardList)\r
+            {\r
+                list.Add(fb.mBoardName);\r
+            }\r
+            return list;\r
+        }\r
+\r
+        /*void button_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)\r
+        {\r
+        }*/\r
+        void button_PreviewMouseMove(object sender, System.Windows.Input.MouseEventArgs e)\r
+        {\r
+            if (!mMousePressed)\r
+                return;\r
+\r
+            Button btn = sender as Button;\r
+            if (btn == null)\r
+                return;\r
+\r
+            Point point = e.GetPosition(btn);\r
+            NTDebug.l("Point (" + point.X + "," + point.Y + ")");\r
+            Vector v = Point.Subtract(point, mMouseObservePoint);\r
+            if (v.Length > NTDragDrop.DRAG_START_MOVE_DELTA)\r
+            {\r
+                startDrag();\r
+                e.Handled = true;\r
+                mMousePressed = false;\r
+            }\r
+        }\r
+\r
+        /*void button_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)\r
+        {\r
+            mMousePressed = false;\r
+        }\r
+\r
+        void button_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)\r
+        {\r
+        }*/\r
+        void button_PreviewMouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)\r
+        {\r
+            //throw new NotImplementedException();\r
+            Button btn = sender as Button;\r
+            if (btn == null)\r
+                return;\r
+\r
+            mMousePressed = true;\r
+            //e.Handled = true;\r
+            mMouseObservePoint = e.GetPosition(btn);\r
+        }\r
+        void startDrag()\r
+        {\r
+            NTDebug.l("*** Drag Start!!! ***");\r
+            NTDragDrop.BoardData data = new NTDragDrop.BoardData(mBoardName);\r
+            DataObject dObj = new DataObject(NTDragDrop.BOARD_DRAG_DATA_FORMAT, data);\r
+\r
+            DragDrop.DoDragDrop(mButton, dObj, DragDropEffects.All);\r
+        }\r
+    }\r
+}\r
diff --git a/NT2chView45/NTFavoriteBoardPopupMenu.cs b/NT2chView45/NTFavoriteBoardPopupMenu.cs
new file mode 100755 (executable)
index 0000000..6907cc5
--- /dev/null
@@ -0,0 +1,119 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Windows.Controls;\r
+using System.Windows.Controls.Primitives;\r
+using System.Windows.Documents;\r
+using System.Windows.Media;\r
+\r
+namespace NT2chView\r
+{\r
+    class NTFavoriteBoardPopupMenu : Popup\r
+    {\r
+        public delegate void DelegateMsgOnNotifiDeleteFavoriteBoard(NTFavoriteBoard board);\r
+        public event DelegateMsgOnNotifiDeleteFavoriteBoard OnNotifiDeleteFavoriteBoard;\r
+\r
+        NTFavoriteBoard mFavoriteBoard;\r
+\r
+        public void show()\r
+        {\r
+            IsOpen = true;\r
+            Placement = PlacementMode.Mouse;\r
+            Focus();\r
+        }\r
+\r
+        public NTFavoriteBoardPopupMenu(NTFavoriteBoard fb)\r
+            : base()\r
+        {\r
+\r
+            mFavoriteBoard = fb;\r
\r
+            this.StaysOpen = false;\r
+            //this.MouseLeave += NTResPopupMenu_MouseLeave;\r
+            //this.LostFocus += NTResPopupMenu_LostFocus;\r
+            \r
+            \r
+\r
+            StackPanel sp = new StackPanel();\r
+            sp.Orientation = Orientation.Horizontal;\r
+\r
+\r
+            StackPanel panel = new StackPanel();\r
+            Border border = new Border();\r
+            border.BorderThickness = new System.Windows.Thickness(1);\r
+            border.BorderBrush = new SolidColorBrush(Colors.DarkGray);\r
+           \r
+\r
+            ListBoxItem item1 = new ListBoxItem();\r
+\r
+            sp = new StackPanel();\r
+            //sp.MouseLeftButtonDown += threadTitle_MouseLeftButtonDown;\r
+            sp.Children.Add(new TextBlock(new Run(fb.BoardName)));\r
+            //sp.Tag = tt;\r
+            item1.Content = sp;\r
+            item1.Padding = new System.Windows.Thickness(10, 2, 10, 2);\r
+            //item1.Tag = tt;\r
+            //item1.MouseEnter += item1_MouseEnter;\r
+            //item1.MouseLeave += item1_MouseLeave;\r
+            panel.Children.Add(item1);\r
+\r
+            sp = new StackPanel();\r
+            sp.Children.Add(new Separator());\r
+            item1 = new ListBoxItem();\r
+            item1.BorderBrush = new SolidColorBrush(Colors.LightGray);\r
+            item1.BorderThickness = new System.Windows.Thickness(1);\r
+            item1.Height = 1;\r
+            item1.Content = sp;\r
+            panel.Children.Add(item1);\r
+            panel.Background = new SolidColorBrush(Colors.White);\r
+\r
+\r
+            sp = new StackPanel();\r
+            sp.Children.Add(new TextBlock(new Run("お気に入りから削除")));\r
+            sp.MouseLeftButtonDown += itemDelete_MouseLeftButtonDown;\r
+            sp.Tag = fb;\r
+            item1 = new ListBoxItem();\r
+            item1.Padding = new System.Windows.Thickness(10, 2, 10, 2);\r
+            item1.Content = sp;\r
+            //item1.MouseEnter += item1_MouseEnter;\r
+            //item1.MouseLeave += item1_MouseLeave;\r
+            //item1.MouseLeftButtonDown += item1_MouseLeftButtonDown;\r
+            //item1.MouseLeftButtonUp += item1_MouseLeftButtonUp;\r
+            panel.Children.Add(item1);\r
\r
+\r
+            sp = new StackPanel();\r
+            sp.Children.Add(new TextBlock(new Run("閉じる")));\r
+            sp.MouseLeftButtonDown += itemClose_MouseLeftButtonDown;\r
+            item1 = new ListBoxItem();\r
+            item1.Padding = new System.Windows.Thickness(10, 2, 10, 2);\r
+            item1.Content = sp;\r
+            //item1.MouseEnter += item1_MouseEnter;\r
+            //item1.MouseLeave += item1_MouseLeave;\r
+            //item1.MouseLeftButtonDown += item1_MouseLeftButtonDown;\r
+            //item1.MouseLeftButtonUp += item1_MouseLeftButtonUp;\r
+            panel.Children.Add(item1);\r
+            //this.Child = panel;\r
+            border.Child = panel; \r
+            this.Child = border;\r
+\r
+        }\r
+\r
+        void itemDelete_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)\r
+        {\r
+            IsOpen = false;\r
+\r
+            if (OnNotifiDeleteFavoriteBoard != null)\r
+            {\r
+                OnNotifiDeleteFavoriteBoard(mFavoriteBoard);\r
+            }\r
+        }\r
+\r
+        void itemClose_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)\r
+        {\r
+            //Hide();\r
+            IsOpen = false;\r
+            //mMainWnd.NgEdit_setResSection(mRes);\r
+        }\r
+    }\r
+}\r
diff --git a/NT2chView45/NTFavoritePanel.xaml b/NT2chView45/NTFavoritePanel.xaml
new file mode 100755 (executable)
index 0000000..050e0b0
--- /dev/null
@@ -0,0 +1,53 @@
+<UserControl x:Class="NT2chView.NTFavoritePanel"\r
+             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"\r
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"\r
+             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" \r
+             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"\r
+             mc:Ignorable="d" \r
+             d:DesignHeight="300" d:DesignWidth="300" Loaded="NTFavoritePanel_Loaded">\r
+    <Grid Background="{DynamicResource FavoritePanelBKBrush}">\r
+        <Grid.RowDefinitions>\r
+            <RowDefinition Height="*"/>\r
+            <RowDefinition Height="Auto" />\r
+        </Grid.RowDefinitions>\r
+        <ScrollViewer x:Name="mFavoritePanelScrollViewer">\r
+            <StackPanel x:Name="mPanelMain"\r
+                        Background="{DynamicResource FavoritePanelBKBrush}">\r
+                <Expander Header="お気に入り(板)" HorizontalAlignment="Left">\r
+                    <WrapPanel x:Name="mFavoriteBoardPanel"/>\r
+                </Expander>\r
+            </StackPanel>\r
+        </ScrollViewer>\r
+        <Grid Grid.Row="1" \r
+                    Background="{DynamicResource HorizontalToolBKBrush}">\r
+            <Grid.ColumnDefinitions>\r
+                <ColumnDefinition Width="Auto"/>\r
+                <ColumnDefinition Width="*"/>\r
+                <ColumnDefinition Width="Auto"/>\r
+                <ColumnDefinition Width="Auto"/>\r
+            </Grid.ColumnDefinitions>  \r
+            <Button x:Name="btnNewFolder" \r
+                    Click="btnNewFolder_Click"\r
+                    HorizontalAlignment="Left" Margin="5,2,5,2">\r
+                <StackPanel>\r
+                    <Image Source="/NT2chStyle45;component/images/history_btn.png" Stretch="None" />\r
+                </StackPanel>\r
+            </Button>\r
+            <TextBox x:Name="mEdtFolderName" Grid.Column="1" Margin="0,5,50,5"/>\r
+            <Button x:Name="btnUpdateTimer"  \r
+                    Grid.Column="2"\r
+                    Margin="5,2,5,0" Click="btnUpdateTimer_Click">\r
+                <StackPanel>\r
+                    <Image Source="/NT2chStyle45;component/images/timer_btn.png" Stretch="None" />\r
+                </StackPanel>\r
+            </Button>\r
+            <Button x:Name="btnUpdate"  \r
+                    Grid.Column="3"\r
+                    Margin="5,2,5,0" Click="btnUpdate_Click">\r
+                <StackPanel>\r
+                    <Image Source="/NT2chStyle45;component/images/update_btn.png" Stretch="None" />\r
+                </StackPanel>\r
+            </Button>\r
+        </Grid>\r
+    </Grid>\r
+</UserControl>\r
diff --git a/NT2chView45/NTFavoritePanel.xaml.cs b/NT2chView45/NTFavoritePanel.xaml.cs
new file mode 100755 (executable)
index 0000000..412e108
--- /dev/null
@@ -0,0 +1,1360 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Windows;\r
+using System.Windows.Controls;\r
+using System.Windows.Controls.Primitives;\r
+using System.Windows.Data;\r
+using System.Windows.Documents;\r
+using System.Windows.Input;\r
+using System.Windows.Media;\r
+using System.Windows.Media.Imaging;\r
+using System.Windows.Navigation;\r
+using System.Windows.Shapes;\r
+using System.Windows.Threading;\r
+using NT2chView.NtUI;\r
+\r
+namespace NT2chView\r
+{\r
+    /// <summary>\r
+    /// NTFavoritePanel.xaml の相互作用ロジック\r
+    /// </summary>\r
+    public partial class NTFavoritePanel : UserControl\r
+    {\r
+        FlowDocument mThreadListDocument;\r
+        System.Threading.Timer mTimer;\r
+        System.Threading.Timer mUpdateTimer;\r
+        object mLockTimerObj = new object();\r
+        object mLockUpdateTimerObj = new object();\r
+        bool mBoardDirty = false;\r
+        bool mThreadDirty = false;\r
+\r
+        NTBoard.DelegateMsgOnNotifyBoardUpdate mOnNotifyBoardUpdate;\r
+\r
+        public MainWindow.DelegateMsgOpenThreadTitleListRequest2 OpenThreadTitleListRequest\r
+        {\r
+            get;\r
+            set;\r
+        }\r
+\r
+        NTFavorite mFavorite;\r
+        public NTFavorite FavoriteData \r
+        {\r
+            set\r
+            {\r
+                initData(value);\r
+                mFavorite = value;\r
+            }\r
+        } \r
+\r
+        public NTFavoritePanel()\r
+        {\r
+            InitializeComponent();\r
+\r
+            mOnNotifyBoardUpdate = new NTBoard.DelegateMsgOnNotifyBoardUpdate(OnNotifyBoardUpdate);\r
+\r
+        }\r
+\r
+        private void NTFavoritePanel_Loaded(object sender, RoutedEventArgs e)\r
+        {\r
+            \r
+        }\r
+\r
+        public void OnClosing()\r
+        {\r
+            lock (mLockTimerObj)\r
+            {\r
+                if (mTimer != null)\r
+                {\r
+                    mTimer.Dispose();\r
+                    // since a Thread.Timer.Timer works on a background thread,\r
+                    // To avoid being killed by System when the process is terminated. \r
+                    Thread th = new Thread(saveFavoriteTimerCallback);\r
+                    th.Start(null);\r
+                    //mTimer.Change(0, Timeout.Infinite);\r
+                    //mTimer = null;\r
+                }\r
+            }\r
+            lock (mLockUpdateTimerObj)\r
+            {\r
+                if (mUpdateTimer != null)\r
+                {\r
+                    mUpdateTimer.Dispose();\r
+                }\r
+            }\r
+        }\r
+\r
+        private void setDirty(bool board)\r
+        {\r
+\r
+            lock (mLockTimerObj)\r
+            {\r
+                if (board)\r
+                    mBoardDirty = true;\r
+                else\r
+                    mThreadDirty = true;\r
+\r
+                if (mTimer == null)\r
+                    mTimer = new System.Threading.Timer(saveFavoriteTimerCallback, null, 15000, Timeout.Infinite);\r
+                else\r
+                    mTimer.Change(15000, Timeout.Infinite);\r
+            }\r
+        }\r
+\r
+        private void setUpdateTimer(int millisecond)\r
+        {\r
+            lock (mLockUpdateTimerObj)\r
+            {\r
+                if (millisecond <= 0)\r
+                {\r
+                    if (mUpdateTimer != null)\r
+                    {\r
+                        mUpdateTimer.Dispose();\r
+                        mUpdateTimer = null;\r
+                    }\r
+                }\r
+                else\r
+                {\r
+                    if (mUpdateTimer == null)\r
+                        mUpdateTimer = new System.Threading.Timer(\r
+                            updateFavoriteTimerCallback, null, millisecond, millisecond);\r
+                    else\r
+                        mUpdateTimer.Change(millisecond, millisecond);\r
+                }\r
+            }\r
+\r
+        }\r
+\r
+\r
+        /*void btn_LayoutUpdated(object sender, EventArgs e)\r
+        {\r
+            //NTDebug.l(sender.ToString());\r
+        }\r
+        private void TestButtonLoaded(\r
+            Object sender,\r
+            RoutedEventArgs e\r
+        )\r
+        {\r
+            NTDebug.l(sender.ToString());\r
+        }*/\r
+\r
+        public void addBoard(NTFavoriteBoard fb)\r
+        {\r
+            if (mFavoriteBoardPanel == null)\r
+                return;\r
+\r
+            Button btn = new Button();\r
+            if (btn == null)\r
+                return;\r
+            Style style = (Style)TryFindResource("FavoriteBoardDisplayButton");\r
+            \r
+            fb.setButton(btn);\r
+            if(style != null)\r
+                btn.Style = style;\r
+            btn.Content = fb.BoardName;\r
+            btn.Tag = fb;\r
+            btn.Click += boardBtn_Click;\r
+            btn.DragEnter += boardBtn_DragEnter;\r
+            btn.DragLeave += boardBtn_DragLeave;\r
+            btn.DragOver += boardBtn_DragOver;\r
+            btn.Drop += boardBtn_Drop;\r
+            btn.MouseRightButtonDown += boardBtn_MouseRightButtonDown;\r
+            btn.MouseRightButtonUp += boardBtn_MouseRightButtonUp;\r
+            btn.AllowDrop = true;\r
+\r
+            mFavoriteBoardPanel.Children.Add(btn);\r
+            setDirty(true);\r
+  \r
+        }\r
+        private void initData(NTFavorite favorite)\r
+        {\r
+            Style style = (Style)TryFindResource("FavoriteBoardDisplayButton");\r
+            //Style style2 = (Style)TryFindResource("FavoriteThreadDisplayButton");\r
+            //Style style3 = (Style)TryFindResource("FavoriteThreadDisplayButtonHeader");\r
+\r
+            \r
+\r
+            List<NTFavoriteBoard> boardList = favorite.getBoardList();\r
+            foreach (NTFavoriteBoard fb in boardList)\r
+            {\r
+                Button btn = new Button();\r
+                if (btn != null)\r
+                {\r
+                    fb.setButton(btn);\r
+                    btn.Style = style;\r
+                    btn.Content = fb.BoardName;\r
+                    btn.Tag = fb;\r
+                    btn.Click += boardBtn_Click;\r
+                    btn.DragEnter += boardBtn_DragEnter;\r
+                    btn.DragLeave += boardBtn_DragLeave;\r
+                    btn.DragOver += boardBtn_DragOver;\r
+                    btn.Drop += boardBtn_Drop;\r
+                    btn.MouseRightButtonDown += boardBtn_MouseRightButtonDown;\r
+                    btn.MouseRightButtonUp += boardBtn_MouseRightButtonUp;\r
+                    btn.AllowDrop = true;\r
+\r
+                    mFavoriteBoardPanel.Children.Add(btn);\r
+                }\r
+            }\r
+\r
+            Dictionary<string, NTBoard> boardListForUpdate = \r
+                new Dictionary<string, NTBoard>();\r
+\r
+\r
+            List<NTFavoriteThreadTag> tagList = favorite.getThreadTagList();\r
+\r
+            mPanelMain.MouseWheel += mPanelMain_MouseWheel;\r
+#if DOTNET45\r
+            mPanelMain.TouchDown += mPanelMain_TouchDown;\r
+            //mPanelMain.TouchEnter += mPanelMain_TouchEnter;\r
+            mPanelMain.TouchMove += mPanelMain_TouchMove;\r
+            mPanelMain.TouchUp += mPanelMain_TouchUp;\r
+#endif\r
+            foreach (NTFavoriteThreadTag tag in tagList)\r
+            {\r
+                string tagName = tag.getTagName();\r
+\r
+                Expander exp = new Expander();\r
+                exp.Header = tagName;\r
+                Grid grid = new Grid();\r
+                exp.Content = grid;\r
+                exp.Tag = tag;\r
+                exp.AllowDrop = true;\r
+                exp.Drop += threadTagExpander_Drop;\r
+\r
+                if(!tagName.Equals("お気に入りのスレ"))\r
+                    exp.MouseRightButtonUp += threadTagExpander_MouseRightButtonUp;\r
+                mPanelMain.Children.Add(exp);\r
+\r
+\r
+                FlowDocumentScrollViewer sv = new FlowDocumentScrollViewer();\r
+                sv.VerticalScrollBarVisibility = ScrollBarVisibility.Hidden;\r
+                FlowDocument document = new FlowDocument();\r
+                sv.Document = document;\r
+                mThreadListDocument = document;\r
+                grid.Children.Add(sv);\r
+\r
+                document.AllowDrop = true;\r
+                document.Cursor = Cursors.Arrow;\r
+\r
+\r
+\r
+                List<NTFavoriteThread> threadList = tag.getThreadList();\r
+                foreach (NTFavoriteThread thread in threadList)\r
+                {\r
+                    thread.setScrollViewer(mFavoritePanelScrollViewer, mPanelMain);\r
+                    string boardName = thread.BoardName;\r
+                    if (boardName != null && boardName.Length > 0 &&\r
+                            !boardListForUpdate.ContainsKey(boardName))\r
+                    {\r
+                        NTBoard board = NTDataRoot.getBoardByName(boardName);\r
+                        if (board != null)\r
+                            boardListForUpdate.Add(thread.BoardName, board);\r
+                    }\r
+                    Paragraph para = thread.createParagraph();\r
+                    if (para == null)\r
+                        continue;\r
+                    para.AllowDrop = true;\r
+                    para.Cursor = Cursors.Hand;\r
+                    para.DragEnter += threadParagraph_DragEnter;\r
+                    para.DragOver += threadParagraph_DragOver;\r
+                    para.DragLeave += threadParagraph_DragLeave;\r
+                    para.Drop += threadParagraph_Drop;\r
+                    para.MouseRightButtonDown += threadParagraph_MouseRightButtonDown;\r
+                    para.MouseRightButtonUp += threadParagraph_MouseRightButtonUp;\r
+                    document.Blocks.Add(para);\r
+\r
+                }\r
+\r
+                exp.IsExpanded = tag.Opened();\r
+\r
+            }\r
+\r
+            foreach(NTBoard board in boardListForUpdate.Values)\r
+            {\r
+                board.Update(mOnNotifyBoardUpdate);\r
+            }\r
+\r
\r
+        }\r
+\r
+#if DOTNET45\r
+        bool fDown = false;\r
+        TouchPoint mPos;\r
+        double mVOffest;\r
+        void mPanelMain_TouchUp(object sender, TouchEventArgs e)\r
+        {\r
+            fDown = false;\r
+            e.Handled = true;\r
+        }\r
+\r
+        void mPanelMain_TouchMove(object sender, TouchEventArgs e)\r
+        {\r
+            if (!fDown)\r
+                return;\r
+            if (mFavoritePanelScrollViewer == null)\r
+                return;\r
+\r
+\r
+            TouchPoint pos = e.GetTouchPoint(mPanelMain);\r
+            double y = mPos.Position.Y - pos.Position.Y;\r
+            double newOffset = mVOffest + y;\r
+            if (mFavoritePanelScrollViewer != null)\r
+                mFavoritePanelScrollViewer.ScrollToVerticalOffset(newOffset);\r
+\r
+            e.Handled = true;\r
+        }\r
+\r
+\r
+        void mPanelMain_TouchDown(object sender, TouchEventArgs e)\r
+        {\r
+            if (mFavoritePanelScrollViewer == null)\r
+                return;\r
+\r
+            try\r
+            {\r
+                mPos = e.GetTouchPoint(mPanelMain);\r
+                mVOffest = mFavoritePanelScrollViewer.VerticalOffset;\r
+                fDown = true;\r
+                e.Handled = true;\r
+            }\r
+            catch (Exception ex)\r
+            {\r
+                MessageBox.Show(ex.Message);\r
+            }\r
+        }\r
+#endif\r
+        void mPanelMain_MouseWheel(object sender, MouseWheelEventArgs e)\r
+        {\r
+            int d = e.Delta;\r
+            if (d == 0)\r
+                return;\r
+            if (mFavoritePanelScrollViewer == null)\r
+                return;\r
+\r
+            int vOffset = (int)mFavoritePanelScrollViewer.VerticalOffset;\r
+\r
+            vOffset -= e.Delta;\r
+\r
+            mFavoritePanelScrollViewer.ScrollToVerticalOffset(vOffset);\r
+\r
+        }\r
+\r
+        //void unhandle_MouseWheel(object sender, MouseWheelEventArgs e)\r
+        //{\r
+        //    e.Handled = false;\r
+            //throw new NotImplementedException();\r
+        //}\r
+\r
+        void addFavoriteTag(string tagName)\r
+        {\r
+            int nChild = mPanelMain.Children.Count;\r
+            if (nChild < 2)\r
+                return;\r
+            //already exists such name.\r
+            if(null != mFavorite.findTag(tagName))\r
+                return;\r
+\r
+            NTFavoriteThreadTag tag = \r
+                mFavorite.insertThreadTagByDescription(tagName+",0,update", false, true);\r
+            if (tag == null)\r
+                return;\r
+\r
+            Expander exp = new Expander();\r
+            exp.Header = tagName;\r
+            Grid grid = new Grid();\r
+            exp.Content = grid;\r
+            exp.Tag = tag;\r
+            exp.AllowDrop = true;\r
+            exp.Drop += threadTagExpander_Drop;\r
+            exp.MouseRightButtonUp += threadTagExpander_MouseRightButtonUp;\r
+\r
+            mPanelMain.Children.Insert(nChild - 1, exp);\r
+            FlowDocumentScrollViewer sv = new FlowDocumentScrollViewer();\r
+            sv.VerticalScrollBarVisibility = ScrollBarVisibility.Hidden;\r
+            FlowDocument document = new FlowDocument();\r
+            sv.Document = document;\r
+            grid.Children.Add(sv);\r
+\r
+            setDirty(false);\r
+        }\r
+\r
+        Expander getExpanderByThreadTag(NTFavoriteThreadTag tag)\r
+        {\r
+            if (tag == null)\r
+                return null;\r
+\r
+            foreach (UIElement ui in mPanelMain.Children)\r
+            {\r
+                Expander exp = ui as Expander;\r
+                if (exp == null)\r
+                    continue;\r
+\r
+                if (tag.Equals(exp.Tag))\r
+                    return exp;\r
+            }\r
+            return null;\r
+        }\r
+\r
+        FlowDocument getFlowDocumentFromExpander(Expander expander)\r
+        {\r
+            Grid grid = expander.Content as Grid;\r
+            if (grid == null || grid.Children.Count == 0)\r
+                return null;\r
+            FlowDocumentScrollViewer sv = grid.Children[0] as FlowDocumentScrollViewer;\r
+            if (sv == null)\r
+                return null;\r
+\r
+            return sv.Document;\r
+        }\r
+\r
+\r
+        void boardBtn_Drop(object sender, DragEventArgs e)\r
+        {\r
+            //NTDebug.l("Drop");\r
+            Button btn = sender as Button;\r
+            if (btn == null)\r
+                return;\r
+\r
+            NTFavoriteBoard destBoard = btn.Tag as NTFavoriteBoard;\r
+            if (destBoard == null)\r
+                return;\r
+\r
+            destBoard.setDragOverBrush(false);\r
+\r
+            IDataObject data = e.Data;\r
+\r
+\r
+            if (data.GetDataPresent(NTDragDrop.BOARD_DRAG_DATA_FORMAT))\r
+            {\r
+                NTDragDrop.BoardData\r
+                    boardData =\r
+                        data.GetData(NTDragDrop.BOARD_DRAG_DATA_FORMAT)\r
+                        as NTDragDrop.BoardData;\r
+                if (boardData == null)\r
+                    return;\r
+\r
+                List<NTFavoriteBoard> boardList =\r
+                        mFavorite.getBoardList();\r
+                if (boardList == null)\r
+                    return;\r
+\r
+                int srcIdx = mFavorite.findBoard(boardData.BoardName);\r
+                if (srcIdx < 0)\r
+                    return;\r
+\r
+                int destIdx = mFavorite.findBoard(destBoard.BoardName);\r
+                if (destIdx < 0)\r
+                    return;\r
+\r
+                if (srcIdx == destIdx)\r
+                    return;\r
+\r
+                Button findBoardBtn = null;\r
+\r
+                foreach (UIElement element in mFavoriteBoardPanel.Children)\r
+                {\r
+                    btn = element as Button;\r
+                    if (btn == null)\r
+                        continue;\r
+                    NTFavoriteBoard board = btn.Tag as NTFavoriteBoard;\r
+                    if (board == null)\r
+                        continue;\r
+\r
+                    if (boardList[srcIdx].Equals(board))\r
+                    {\r
+                        findBoardBtn = btn;\r
+                        mFavoriteBoardPanel.Children.Remove(btn);\r
+                        break;\r
+                    }\r
+                }\r
+\r
+                if (findBoardBtn == null)\r
+                    return;\r
+\r
+\r
+                foreach (UIElement element in mFavoriteBoardPanel.Children)\r
+                {\r
+                    btn = element as Button;\r
+                    if (btn == null)\r
+                        continue;\r
+                    NTFavoriteBoard board = btn.Tag as NTFavoriteBoard;\r
+                    if (board == null)\r
+                        continue;\r
+\r
+                    if (destBoard.Equals(board))\r
+                    {\r
+                        int idx = mFavoriteBoardPanel.Children.IndexOf(element);\r
+                        if (idx < 0)\r
+                            return;\r
+                        mFavoriteBoardPanel.Children.Insert(idx+1, findBoardBtn);\r
+                        break;\r
+                    }\r
+                }\r
+\r
+                NTFavoriteBoard fb = boardList[srcIdx];\r
+                boardList.RemoveAt(srcIdx);\r
+                if (srcIdx < destIdx)\r
+                    destIdx--;\r
+                boardList.Insert(destIdx + 1, fb);\r
+\r
+                e.Handled = true;\r
+\r
+                setDirty(true);\r
+\r
+            }\r
+        }\r
+\r
+\r
+        void boardBtn_DragLeave(object sender, DragEventArgs e)\r
+        {\r
+            Button btn = sender as Button;\r
+            if (btn == null)\r
+                return;\r
+\r
+            NTFavoriteBoard board = btn.Tag as NTFavoriteBoard;\r
+            if (board == null)\r
+                return;\r
+\r
+            board.setDragOverBrush(false);\r
+        }\r
+\r
+        void boardBtn_DragOver(object sender, DragEventArgs e)\r
+        {\r
+            validateBoardDropData(sender, e, false);\r
+        }\r
+\r
+        void boardBtn_DragEnter(object sender, DragEventArgs e)\r
+        {\r
+            validateBoardDropData(sender, e, true);\r
+        }\r
+\r
+        void boardBtn_MouseRightButtonDown(object sender, MouseButtonEventArgs e)\r
+        {\r
+            e.Handled = true;\r
+        }\r
+        void boardBtn_MouseRightButtonUp(object sender, MouseButtonEventArgs e)\r
+        {\r
+            Button btn = sender as Button;\r
+            if (btn == null)\r
+                return;\r
+\r
+            NTFavoriteBoard fb = btn.Tag as NTFavoriteBoard;\r
+            if (fb == null)\r
+                return;\r
+\r
+            NTFavoriteBoardPopupMenu popup = new NTFavoriteBoardPopupMenu(fb);\r
+            popup.OnNotifiDeleteFavoriteBoard +=\r
+                new NTFavoriteBoardPopupMenu.DelegateMsgOnNotifiDeleteFavoriteBoard(\r
+                    OnNotifiDeleteFavoriteBoard);\r
+            popup.show();\r
+            e.Handled = true;\r
+        }\r
+\r
+        void OnNotifiDeleteFavoriteBoard(NTFavoriteBoard fb)\r
+        {\r
+            //NTDebug.l("Delete Call: " + ft.Title);\r
+            mFavorite.removeBoardByBoardName(fb.BoardName, false);\r
+            foreach (UIElement element in mFavoriteBoardPanel.Children)\r
+            {\r
+                Button btn = element as Button;\r
+                if (btn == null)\r
+                    continue;\r
+                NTFavoriteBoard board = btn.Tag as NTFavoriteBoard;\r
+                if (board == null)\r
+                    continue;\r
+\r
+                if (fb.Equals(board))\r
+                {\r
+                    mFavoriteBoardPanel.Children.Remove(btn);\r
+                    setDirty(true);\r
+                    break;\r
+                }\r
+            }\r
+        }\r
+\r
+        void threadParagraph_MouseRightButtonDown(object sender, MouseButtonEventArgs e)\r
+        {\r
+            //NTFavoriteThreadPopupMenu popup = new NTFavoriteThreadPopupMenu();\r
+            //popup.show();\r
+            e.Handled = true;\r
+        }\r
+        void threadParagraph_MouseRightButtonUp(object sender, MouseButtonEventArgs e)\r
+        {\r
+            Paragraph para = sender as Paragraph;\r
+            if (para == null)\r
+                return;\r
+\r
+            NTFavoriteThread ft = para.Tag as NTFavoriteThread;\r
+            if (ft == null)\r
+                return;\r
+\r
+\r
+            NTFavoriteThreadPopupMenu popup = new NTFavoriteThreadPopupMenu(ft);\r
+            popup.OnNotifiDeleteFavoriteThread += \r
+                new NTFavoriteThreadPopupMenu.DelegateMsgOnNotifiDeleteFavoriteThread(\r
+                    OnNotifiDeleteFavoriteThread);\r
+            popup.show();\r
+            e.Handled = true;\r
+        }\r
+\r
+        void threadTagExpander_MouseRightButtonUp(object sender, MouseButtonEventArgs e)\r
+        {\r
+            Expander exp = sender as Expander;\r
+            if (exp == null)\r
+                return;\r
+\r
+            NTFavoriteThreadTag tag = exp.Tag as NTFavoriteThreadTag;\r
+            if (tag == null)\r
+                return;\r
+\r
+\r
+            NTFavoriteThreadTagPopupMenu popup = new NTFavoriteThreadTagPopupMenu(tag);\r
+            popup.OnNotifiDeleteFavoriteThreadTag +=\r
+                new NTFavoriteThreadTagPopupMenu.DelegateMsgOnNotifiDeleteFavoriteThreadTag(\r
+                    OnNotifiDeleteFavoriteThreadTag);\r
+            popup.OnNotifiChangeFavoriteThreadTagName +=\r
+                new NTFavoriteThreadTagPopupMenu.DelegateMsgOnNotifiChangeFavoriteThreadTagName(\r
+                    OnNotifiChangeFavoriteThreadTagName);\r
+            popup.show();\r
+            e.Handled = true;\r
+        }\r
+\r
+        public void addThread(NTFavoriteThread ft)\r
+        {\r
+            if (mThreadListDocument == null)\r
+                return;\r
+\r
+            Paragraph para = ft.createParagraph();\r
+            if (para == null)\r
+                return;\r
+            para.AllowDrop = true;\r
+            para.DragEnter += threadParagraph_DragEnter;\r
+            para.DragOver += threadParagraph_DragOver;\r
+            para.DragLeave += threadParagraph_DragLeave;\r
+            para.Drop += threadParagraph_Drop;\r
+            //mThreadListDocument.Blocks.Add(para);\r
+            List<NTFavoriteThreadTag> tagList = mFavorite.getThreadTagList();\r
+            if (tagList.Count == 0)\r
+                return;\r
+\r
+            NTFavoriteThreadTag tag = tagList[tagList.Count - 1];\r
+            List<NTFavoriteThread> threadList = tag.getThreadList();\r
+            threadList.Add(ft);\r
+            tag.setCount(threadList.Count);\r
+\r
+            Expander exp = getExpanderByThreadTag(tag);\r
+            if (exp == null)\r
+                return;\r
+            FlowDocument doc = getFlowDocumentFromExpander(exp);\r
+            if (doc == null)\r
+                return;\r
+\r
+            doc.MouseWheel += doc_MouseWheel;\r
+\r
+            doc.Blocks.Add(para);\r
+\r
+\r
+            setDirty(false);\r
+\r
+\r
+        }\r
+\r
+        void doc_MouseWheel(object sender, MouseWheelEventArgs e)\r
+        {\r
+            //throw new NotImplementedException();\r
+        }\r
+\r
+        void OnNotifiDeleteFavoriteThreadTag(NTFavoriteThreadTag tag, bool withItem)\r
+        {\r
+            Expander exp = getExpanderByThreadTag(tag);\r
+            if (exp == null)\r
+                return;\r
+\r
+            int threadIdx = 0;\r
+            List<NTFavoriteThreadTag> tagList = mFavorite.getThreadTagList();\r
+            foreach (NTFavoriteThreadTag tmpTag in tagList)\r
+            {\r
+                if(tmpTag.Equals(tag))\r
+                {\r
+                    List<NTFavoriteThread> threadList = mFavorite.getThreadList();\r
+                    List<NTFavoriteThread> moveThreadList = new List<NTFavoriteThread>(); \r
+                    int removeCount = tmpTag.getCount();\r
+                    if ((threadIdx + removeCount) > threadList.Count)\r
+                        return;\r
+                    for (int i = 0; i < removeCount; i++)\r
+                    {\r
+                        if(!withItem)\r
+                            moveThreadList.Add(threadList[threadIdx]);\r
+                        threadList.RemoveAt(threadIdx);\r
+                    }\r
+                    tagList.Remove(tag);\r
+                    if (!withItem)\r
+                    {\r
+                        Expander exp2 = null;\r
+                        FlowDocument doc2 = null;\r
+                        int nLastParagraph = mPanelMain.Children.Count;\r
+                        if (nLastParagraph > 0)\r
+                        {\r
+                            exp2 = mPanelMain.Children[nLastParagraph - 1] as Expander;\r
+                            doc2 = getFlowDocumentFromExpander(exp2);\r
+                        }\r
+                        foreach (NTFavoriteThread thread in moveThreadList)\r
+                        {\r
+                            threadList.Add(thread);\r
+                            if (doc2 != null)\r
+                            {\r
+                                Paragraph para = thread.createParagraph();\r
+                                if (para != null)\r
+                                {\r
+                                    para.AllowDrop = true;\r
+                                    para.DragEnter += threadParagraph_DragEnter;\r
+                                    para.DragOver += threadParagraph_DragOver;\r
+                                    para.DragLeave += threadParagraph_DragLeave;\r
+                                    para.Drop += threadParagraph_Drop;\r
+                                    para.MouseRightButtonDown += threadParagraph_MouseRightButtonDown;\r
+                                    para.MouseRightButtonUp += threadParagraph_MouseRightButtonUp;\r
+                                    doc2.Blocks.Add(para);\r
+                                }\r
+                            }\r
+                        }\r
+                    }\r
+                    mPanelMain.Children.Remove(exp);\r
+                    setDirty(false);\r
+                    break;\r
+                }\r
+                threadIdx += tmpTag.getCount();\r
+            }           \r
+        }\r
+        void OnNotifiChangeFavoriteThreadTagName(NTFavoriteThreadTag tag)\r
+        {\r
+            Expander exp = getExpanderByThreadTag(tag);\r
+            if (exp == null)\r
+                return;\r
+\r
+            exp.Header = tag.getTagName();\r
+            setDirty(false);\r
+        }\r
+\r
+        void OnNotifiDeleteFavoriteThread(NTFavoriteThread ft)\r
+        {\r
+            removeThread(ft);\r
+        }\r
+\r
+        public void removeThread(NTFavoriteThread ft)\r
+        {\r
+            int idx = mFavorite.findThread(ft);\r
+            if (idx < 0)\r
+                return;\r
+\r
+            List<NTFavoriteThread> threadList = mFavorite.getThreadList();\r
+            //NTFavoriteThread srcThread = threadList[idx];\r
+            NTFavoriteThreadTag tag = mFavorite.findTag(ft);\r
+            if (tag == null)\r
+                return;\r
+\r
+            Expander exp = getExpanderByThreadTag(tag);\r
+            if (exp == null)\r
+                return;\r
+            FlowDocument doc = getFlowDocumentFromExpander(exp);\r
+            if (doc == null)\r
+                return;\r
+\r
+           // Paragraph paraRemoved = null;\r
+            foreach (Block block in doc.Blocks)\r
+            {\r
+                Paragraph para1 = block as Paragraph;\r
+                if (para1 == null)\r
+                    continue;\r
+                if (ft.Equals(para1.Tag))\r
+                {\r
+                    if (doc.Blocks.Remove(para1))\r
+                    {\r
+                        threadList.RemoveAt(idx);\r
+                        tag.setCount(tag.getCount() - 1);\r
+                        setDirty(false);\r
+                    }\r
+                    break;\r
+                }\r
+            }\r
+        }\r
+\r
+\r
+        void threadParagraph_DragLeave(object sender, DragEventArgs e)\r
+        {\r
+            Paragraph para = sender as Paragraph;\r
+            if (para == null)\r
+                return;\r
+\r
+            NTFavoriteThread thread = para.Tag as NTFavoriteThread;\r
+            if (thread == null)\r
+                return;\r
+\r
+            thread.setDragOverBrush(false);\r
+        }\r
+\r
+        void threadParagraph_DragEnter(object sender, DragEventArgs e)\r
+        {\r
+            validateThreadDropData(sender, e, true);\r
+        }\r
+\r
+        void threadParagraph_DragOver(object sender, DragEventArgs e)\r
+        {\r
+            validateThreadDropData(sender, e, false);\r
+        }\r
+\r
+        void threadParagraph_Drop(object sender, DragEventArgs e)\r
+        {\r
+            //NTDebug.l("Drop");\r
+            Paragraph para = sender as Paragraph;\r
+            if (para == null)\r
+                return;\r
+\r
+            NTFavoriteThread destThread = para.Tag as NTFavoriteThread;\r
+            if (destThread == null)\r
+                return;\r
+\r
+            destThread.setDragOverBrush(false);\r
+\r
+            IDataObject data = e.Data;\r
+\r
+\r
+            if (!data.GetDataPresent(NTDragDrop.THREAD_DRAG_DATA_FORMAT))\r
+                return;\r
+\r
+            NTDragDrop.ThreadData\r
+                threadData = \r
+                    data.GetData(NTDragDrop.THREAD_DRAG_DATA_FORMAT)\r
+                    as NTDragDrop.ThreadData;\r
+            if (threadData == null)\r
+                return;\r
+\r
+            List<NTFavoriteThread> threadList = \r
+                    mFavorite.getThreadList();\r
+            if(threadList == null)\r
+                return;\r
+\r
+            int srcIdx = mFavorite.findThread(threadData.BoardName, \r
+                threadData.Address,\r
+                threadData.Title);\r
+            if (srcIdx < 0)\r
+                return;\r
+\r
+            int destIdx = mFavorite.findThread(destThread);\r
+            if (destIdx < 0)\r
+                return;\r
+\r
+            if (srcIdx == destIdx)\r
+                return;\r
+\r
+            NTFavoriteThread srcThread = threadList[srcIdx];\r
+            NTFavoriteThreadTag srcTag = mFavorite.findTag(srcThread);\r
+            if (srcTag == null)\r
+                return;\r
+\r
+            Expander srcExp = getExpanderByThreadTag(srcTag);\r
+            if (srcExp == null)\r
+                return;\r
+            FlowDocument srcDoc = getFlowDocumentFromExpander(srcExp);\r
+            if (srcDoc == null)\r
+                return;\r
+\r
+            Paragraph paraRemoved = null;\r
+            foreach (Block block in srcDoc.Blocks)\r
+            {\r
+                Paragraph para1 = block as Paragraph;\r
+                if (para1 == null)\r
+                    continue;\r
+                if (srcThread.Equals(para1.Tag))\r
+                {\r
+                    if(srcDoc.Blocks.Remove(para1))\r
+                        paraRemoved = para1;\r
+                    break;\r
+                }\r
+            }\r
+            if (paraRemoved == null)\r
+                return;\r
+\r
+            NTFavoriteThreadTag destTag = mFavorite.findTag(threadList[destIdx]);\r
+            if (destTag == null)\r
+                return;\r
+            Expander destExp = getExpanderByThreadTag(destTag);\r
+            if (destExp == null)\r
+                return;\r
+            FlowDocument destDoc = getFlowDocumentFromExpander(destExp);\r
+            if (destDoc == null)\r
+                return;\r
+\r
+            foreach (Block block in destDoc.Blocks)\r
+            {\r
+                Paragraph para1 = block as Paragraph;\r
+                if (para1 == null)\r
+                    continue;\r
+                if (destThread.Equals(para1.Tag))\r
+                {\r
+                    Paragraph para2 = srcThread.createParagraph();\r
+                    if (para2 == null)\r
+                        continue;\r
+                    para2.AllowDrop = true;\r
+                    para2.DragEnter += threadParagraph_DragEnter;\r
+                    para2.DragOver += threadParagraph_DragOver;\r
+                    para2.DragLeave += threadParagraph_DragLeave;\r
+                    para2.Drop += threadParagraph_Drop;\r
+                    para2.MouseRightButtonDown += threadParagraph_MouseRightButtonDown;\r
+                    para2.MouseRightButtonUp += threadParagraph_MouseRightButtonUp;\r
+                    destDoc.Blocks.InsertAfter(para1, para2);\r
+                    break;\r
+                }\r
+            }\r
+\r
+            srcTag.getThreadList().Remove(srcThread);\r
+            int n1 = destTag.getThreadList().IndexOf(destThread);\r
+            if(n1 >= 0)\r
+                destTag.getThreadList().Insert(n1, srcThread);\r
+\r
+            threadList.RemoveAt(srcIdx);\r
+            if (srcIdx < destIdx)\r
+                destIdx--;\r
+            threadList.Insert(destIdx + 1, srcThread);\r
+\r
+            if (!srcTag.Equals(destTag))\r
+            {\r
+                srcTag.setCount(srcTag.getCount() - 1);\r
+                destTag.setCount(destTag.getCount() + 1);\r
+                updateExpanderHeader(srcTag);\r
+                updateExpanderHeader(destTag);\r
+            }\r
+\r
+            setDirty(false);\r
+            \r
+        }\r
+\r
+        void threadTagExpander_Drop(object sender, DragEventArgs e)\r
+        {\r
+            Expander destExp = sender as Expander;\r
+            if (destExp == null)\r
+                return;\r
+\r
+            NTFavoriteThreadTag destTag = destExp.Tag as NTFavoriteThreadTag;\r
+            if (destTag == null)\r
+                return;\r
+\r
+            IDataObject data = e.Data;\r
+\r
+            if (!data.GetDataPresent(NTDragDrop.THREAD_DRAG_DATA_FORMAT))\r
+                return;\r
+\r
+            NTDragDrop.ThreadData\r
+                threadData =\r
+                    data.GetData(NTDragDrop.THREAD_DRAG_DATA_FORMAT)\r
+                    as NTDragDrop.ThreadData;\r
+            if (threadData == null)\r
+                return;\r
+\r
+            List<NTFavoriteThread> threadList =\r
+                    mFavorite.getThreadList();\r
+            if (threadList == null)\r
+                return;\r
+\r
+            int srcIdx = mFavorite.findThread(threadData.BoardName,\r
+                threadData.Address,\r
+                threadData.Title);\r
+            if (srcIdx < 0)\r
+                return;\r
+\r
+            NTFavoriteThread srcThread = threadList[srcIdx];\r
+            NTFavoriteThreadTag srcTag = mFavorite.findTag(srcThread);\r
+            if (srcTag == null)\r
+                return;\r
+\r
+            Expander srcExp = getExpanderByThreadTag(srcTag);\r
+            if (srcExp == null)\r
+                return;\r
+\r
+            FlowDocument srcDoc = getFlowDocumentFromExpander(srcExp);\r
+            if (srcDoc == null)\r
+                return;\r
+\r
+            Paragraph paraRemoved = null;\r
+            foreach (Block block in srcDoc.Blocks)\r
+            {\r
+                Paragraph para1 = block as Paragraph;\r
+                if (para1 == null)\r
+                    continue;\r
+                if (srcThread.Equals(para1.Tag))\r
+                {\r
+                    if (srcDoc.Blocks.Remove(para1))\r
+                        paraRemoved = para1;\r
+                    break;\r
+                }\r
+            }\r
+            if (paraRemoved == null)\r
+                return;\r
+\r
+            FlowDocument destDoc = getFlowDocumentFromExpander(destExp);\r
+            if (destDoc == null)\r
+                return;\r
+\r
+            Block firstBlock = destDoc.Blocks.FirstBlock;\r
+            if (firstBlock != null)\r
+                destDoc.Blocks.InsertBefore(firstBlock, paraRemoved);\r
+            else\r
+                destDoc.Blocks.Add(paraRemoved);\r
+\r
+            if (!srcTag.Equals(destTag))\r
+            {\r
+                srcTag.setCount(srcTag.getCount() - 1);\r
+                destTag.setCount(destTag.getCount() + 1);\r
+            }\r
+\r
+            threadList.RemoveAt(srcIdx);\r
+\r
+            int insertIdx = 0;\r
+            List<NTFavoriteThreadTag> tagList = mFavorite.getThreadTagList();\r
+            foreach(NTFavoriteThreadTag tag in tagList)\r
+            {\r
+                if (tag.Equals(destTag))\r
+                {\r
+                    threadList.Insert(insertIdx, srcThread);\r
+                    break;\r
+                }\r
+                insertIdx += tag.getCount();\r
+            }\r
+\r
+            setDirty(false);\r
+\r
+       }\r
+\r
+        void validateBoardDropData(object sender, DragEventArgs e, bool startEvent)\r
+        {\r
+\r
+            Button btn = sender as Button;\r
+            if (btn == null)\r
+                return;\r
+\r
+            NTFavoriteBoard destBoard = btn.Tag as NTFavoriteBoard;\r
+            if (destBoard == null)\r
+                return;\r
+\r
+            if(startEvent)\r
+                destBoard.setDragOverBrush(true);\r
+\r
+            IDataObject data = e.Data;\r
+\r
+            \r
+            if (!data.GetDataPresent(NTDragDrop.BOARD_DRAG_DATA_FORMAT))\r
+            {\r
+                //NTDebug.l("Drag Enter None");\r
+                e.Effects = DragDropEffects.None;\r
+            }\r
+            else\r
+            {\r
+                //NTDebug.l("Drag Enter All");\r
+                NTDragDrop.BoardData\r
+                    boardData =\r
+                        data.GetData(NTDragDrop.BOARD_DRAG_DATA_FORMAT)\r
+                        as NTDragDrop.BoardData;\r
+                if (boardData == null)\r
+                {\r
+                    e.Effects = DragDropEffects.None;\r
+                    return;\r
+                }\r
+\r
+                List<NTFavoriteBoard> boardList =\r
+                        mFavorite.getBoardList();\r
+                if (boardList == null)\r
+                {\r
+                    e.Effects = DragDropEffects.None;\r
+                    return;\r
+                }\r
+\r
+                int srcIdx = mFavorite.findBoard(boardData.BoardName);\r
+                if (srcIdx < 0)\r
+                {\r
+                    e.Effects = DragDropEffects.None;\r
+                    return;\r
+                }\r
+\r
+                int destIdx = mFavorite.findBoard(destBoard.BoardName);\r
+                if (destIdx < 0)\r
+                {\r
+                    e.Effects = DragDropEffects.None;\r
+                    return;\r
+                }\r
+\r
+                if (srcIdx == destIdx)\r
+                {\r
+                    e.Effects = DragDropEffects.None;\r
+                    return;\r
+                }\r
+                e.Effects = DragDropEffects.Move;\r
+                e.Handled = true;\r
+            }\r
+        }\r
+\r
+        void validateThreadDropData(object sender, DragEventArgs e, bool startEvent)\r
+        {\r
+\r
+            Paragraph para = sender as Paragraph;\r
+            if (para == null)\r
+                return;\r
+\r
+            NTFavoriteThread destThread = para.Tag as NTFavoriteThread;\r
+            if (destThread == null)\r
+                return;\r
+\r
+            if (startEvent)\r
+                destThread.setDragOverBrush(true);\r
+\r
+            IDataObject data = e.Data;\r
+\r
+\r
+            if (!data.GetDataPresent(NTDragDrop.THREAD_DRAG_DATA_FORMAT))\r
+            {\r
+                //NTDebug.l("Drag Enter None");\r
+                e.Effects = DragDropEffects.None;\r
+            }\r
+            else\r
+            {\r
+                //NTDebug.l("Drag Enter All");\r
+                NTDragDrop.ThreadData\r
+                    threadData =\r
+                        data.GetData(NTDragDrop.THREAD_DRAG_DATA_FORMAT)\r
+                        as NTDragDrop.ThreadData;\r
+                if (threadData == null)\r
+                {\r
+                    e.Effects = DragDropEffects.None;\r
+                    return;\r
+                }\r
+\r
+                List<NTFavoriteThread> threadList =\r
+                        mFavorite.getThreadList();\r
+                if (threadList == null)\r
+                {\r
+                    e.Effects = DragDropEffects.None;\r
+                    return;\r
+                }\r
+\r
+                int srcIdx = mFavorite.findThread(threadData.BoardName,\r
+                    threadData.Address,\r
+                    threadData.Title);\r
+                if (srcIdx < 0)\r
+                {\r
+                    e.Effects = DragDropEffects.None;\r
+                    return;\r
+                }\r
+\r
+                int destIdx = mFavorite.findThread(destThread);\r
+                if (destIdx < 0)\r
+                {\r
+                    e.Effects = DragDropEffects.None;\r
+                    return;\r
+                }\r
+\r
+                if (srcIdx == destIdx)\r
+                {\r
+                    e.Effects = DragDropEffects.None;\r
+                    return;\r
+                }\r
+                e.Effects = DragDropEffects.Move;\r
+                e.Handled = true;\r
+            }\r
+        }\r
+\r
+        public void OnNotifyBoardUpdate(NTBoard board)\r
+        {\r
+            if (mFavorite == null)\r
+                return;\r
+\r
+            List<NTFavoriteThreadTag> tagList = mFavorite.getThreadTagList();\r
+            foreach (NTFavoriteThreadTag tag in tagList)\r
+            {\r
+                bool update = false;\r
+                List<NTFavoriteThread> threadList = tag.getThreadList();\r
+                foreach (NTFavoriteThread thread in threadList)\r
+                {\r
+                    string boardName = thread.BoardName;\r
+                    if (board.mName.Equals(boardName))\r
+                    {\r
+                        NTThreadTitle tt = board.findThreadTitleByDatName(thread.Address);\r
+                        if (tt != null)\r
+                        {\r
+                            thread.updateParagraph(tt);\r
+                            update = true;\r
+                        }\r
+                    }\r
+                }\r
+                if (update)\r
+                    updateExpanderHeader(tag);\r
+            }\r
+         }\r
+\r
+        void updateExpanderHeader(NTFavoriteThreadTag tag)\r
+        {\r
+            Expander exp = getExpanderByThreadTag(tag);\r
+            if (exp == null)\r
+                return;\r
+            int nNewMsg = 0;\r
+\r
+            List<NTFavoriteThread> threadList = tag.getThreadList();\r
+            foreach (NTFavoriteThread thread in threadList)\r
+            {\r
+                NTBoard board = NTDataRoot.getBoardByName(thread.BoardName);\r
+                if (board == null)\r
+                    continue;\r
+                NTThreadTitle tt = board.findThreadTitleByDatName(thread.Address);\r
+                if(tt == null)\r
+                    continue;\r
+                if (tt.ReadCnt > 0 &&\r
+                    tt.RemainCnt > 0)\r
+                {\r
+                    nNewMsg++;\r
+                }\r
+            }\r
+            StackPanel sp = new StackPanel();\r
+            sp.Orientation = Orientation.Horizontal;\r
+            TextBlock tb = new TextBlock(new Run(tag.getTagName()));\r
+            sp.Children.Add(tb);\r
+            if (nNewMsg > 0)\r
+            {\r
+                string s = " 新着 " + nNewMsg.ToString() + "件";\r
+                tb = new TextBlock(new Run(s));\r
+                tb.Foreground = new SolidColorBrush(Colors.Red);\r
+                sp.Children.Add(tb);\r
+            }\r
+            exp.Header = sp;\r
+\r
+        }\r
+\r
+        void boardBtn_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            if (OpenThreadTitleListRequest == null)\r
+                return;\r
+            Button btn = sender as Button;\r
+            if (btn == null)\r
+                return;\r
+\r
+            NTFavoriteBoard fb = btn.Tag as NTFavoriteBoard;\r
+            if (fb == null)\r
+                return;\r
+\r
+            OpenThreadTitleListRequest(fb.BoardName);\r
+        }\r
+\r
+         /*void btn_Click21(object sender, RoutedEventArgs e)\r
+        {\r
+           \r
+            NTBoard board = NTDataRoot.getBoardByName(values[1]);\r
+            if (board == null)\r
+                return;\r
+\r
+            if (!OpenNewBoard(board))\r
+                return;\r
+\r
+            NTThreadTitle tt = board.findThreadTitleByDatName(values[0]);\r
+            if (tt != null)\r
+            {\r
+                OpenNewThread(tt);\r
+            }\r
+        \r
+        }*/\r
+\r
+        private void btnNewFolder_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            string folderName = mEdtFolderName.Text;\r
+            if (folderName == null || folderName.Length == 0)\r
+                return;\r
+\r
+            addFavoriteTag(folderName);\r
+\r
+        }\r
+\r
+        bool mUpdateing = false;\r
+        private void btnUpdateTimer_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            mUpdateing = !mUpdateing;\r
+            if (mUpdateing)\r
+            {\r
+                int duration = NTUserPreference.FavoriteUpdateDuration;\r
+                btnUpdateTimer.Background = new SolidColorBrush(Colors.Blue);\r
+                setUpdateTimer(duration * 60 * 1000);\r
+\r
+            }\r
+            else\r
+            {\r
+                btnUpdateTimer.Background = null;\r
+                setUpdateTimer(0);//dispose update timer.\r
+            }\r
+        }\r
+        private void btnUpdate_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            updateFavorite();\r
+        }\r
+\r
+        private void updateFavorite()\r
+        {\r
+\r
+            if (mFavorite == null)\r
+                return;\r
+\r
+            Dictionary<string, NTBoard> boardListForUpdate =\r
+                new Dictionary<string, NTBoard>();\r
+\r
+            List<NTFavoriteThread> threadList = mFavorite.getThreadList();\r
+            foreach (NTFavoriteThread thread in threadList)\r
+            {\r
+                string boardName = thread.BoardName;\r
+                if (boardName != null &&\r
+                        !boardListForUpdate.ContainsKey(boardName))\r
+                {\r
+                    NTBoard board = NTDataRoot.getBoardByName(boardName);\r
+                    if (board != null)\r
+                        boardListForUpdate.Add(thread.BoardName, board);\r
+                }\r
+            }\r
+\r
+            foreach (NTBoard board in boardListForUpdate.Values)\r
+            {\r
+                board.Update(null);\r
+            }\r
+\r
+        }\r
+\r
+        private void updateFavoriteTimerCallback(object StateObj)\r
+        {\r
+            DateTime dt = DateTime.Now;\r
+            string strTime = dt.ToString();\r
+            NTDebug.l("*** Timer called in updateFavoriteTimerCallback ***");\r
+            NTDebug.l("\tBackgroud:" + Thread.CurrentThread.IsBackground + " on " + strTime);\r
+\r
+            this.Dispatcher.BeginInvoke(DispatcherPriority.Normal,\r
+            (ThreadStart)delegate()\r
+            {\r
+\r
+                updateFavorite();\r
+            });\r
+        }\r
+        private void saveFavoriteTimerCallback(object StateObj)\r
+        {\r
+            \r
+            lock (mLockTimerObj)\r
+            {\r
+                if (mTimer != null)\r
+                {\r
+                    mTimer.Dispose();\r
+                    mTimer = null;\r
+\r
+                    if (mBoardDirty)\r
+                        mFavorite.updateFavoriteBoards();\r
+                    if (mThreadDirty)\r
+                        mFavorite.updateFavoriteThread();\r
+\r
+                    mBoardDirty = false;\r
+                    mThreadDirty = false;\r
+                }\r
+            }\r
+\r
+        }\r
+     }\r
+}\r
diff --git a/NT2chView45/NTFavoriteTagEditWindow.xaml b/NT2chView45/NTFavoriteTagEditWindow.xaml
new file mode 100755 (executable)
index 0000000..8643571
--- /dev/null
@@ -0,0 +1,27 @@
+<Window x:Class="NT2chView.NTFavoriteTagEditWindow"\r
+        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"\r
+        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"\r
+        Title="フォルダーの編集" Height="150" Width="300">\r
+    <Grid>\r
+        <Grid.RowDefinitions>\r
+            <RowDefinition Height="Auto"/>\r
+            <RowDefinition Height="*"/>\r
+            <RowDefinition Height="Auto"/>\r
+        </Grid.RowDefinitions>\r
+        <Grid.ColumnDefinitions>\r
+            <ColumnDefinition Width="*"/>\r
+            <ColumnDefinition Width="Auto"/>\r
+            <ColumnDefinition Width="Auto"/>\r
+        </Grid.ColumnDefinitions>\r
+        <Label Grid.ColumnSpan="3" Content="名前の変更" TabIndex="100"/>\r
+        <TextBox x:Name="mEdtFolderName" Grid.Row="1" Grid.ColumnSpan="3" \r
+                 TabIndex="1"\r
+                 Width="250" Height="25" TextChanged="mEdtFolderName_TextChanged"/>\r
+        <Button x:Name="mBtnSave" Content="保存" Grid.Row="2" Grid.Column="1"\r
+                TabIndex="2"\r
+                Width="75" Margin="10,5,10,5" Click="mBtnSave_Click" IsEnabled="False"/>\r
+        <Button x:Name="mBtnCancel" Content="やめる" Grid.Row="2" Grid.Column="2" \r
+                TabIndex="3"\r
+                Width="75" Margin="10,5,10,5" Click="mBtnCancel_Click"/>\r
+    </Grid>\r
+</Window>\r
diff --git a/NT2chView45/NTFavoriteTagEditWindow.xaml.cs b/NT2chView45/NTFavoriteTagEditWindow.xaml.cs
new file mode 100755 (executable)
index 0000000..5f1b1a1
--- /dev/null
@@ -0,0 +1,55 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Windows;\r
+using System.Windows.Controls;\r
+using System.Windows.Data;\r
+using System.Windows.Documents;\r
+using System.Windows.Input;\r
+using System.Windows.Media;\r
+using System.Windows.Media.Imaging;\r
+using System.Windows.Shapes;\r
+\r
+namespace NT2chView\r
+{\r
+    /// <summary>\r
+    /// NTFavoriteTagEditWindow.xaml の相互作用ロジック\r
+    /// </summary>\r
+    public partial class NTFavoriteTagEditWindow : Window\r
+    {\r
+        public void setText(string value)\r
+        {\r
+            if (value != null)\r
+                mEdtFolderName.Text = value;\r
+        }\r
+        public string getText()\r
+        {\r
+            if (!DialogResult.HasValue)\r
+                return null;\r
+            if (!(bool)DialogResult)\r
+                return null;\r
+\r
+           return mEdtFolderName.Text;\r
+        }\r
+        public NTFavoriteTagEditWindow()\r
+        {\r
+            InitializeComponent();\r
+        }\r
+\r
+        private void mBtnSave_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            this.DialogResult = true;\r
+            Close();\r
+        }\r
+        private void mBtnCancel_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            this.DialogResult = true;\r
+            Close();\r
+        }\r
+\r
+        private void mEdtFolderName_TextChanged(object sender, TextChangedEventArgs e)\r
+        {\r
+            ((Button)mBtnSave).IsEnabled = true;\r
+        }\r
+    }\r
+}\r
diff --git a/NT2chView45/NTFavoriteThread.cs b/NT2chView45/NTFavoriteThread.cs
new file mode 100755 (executable)
index 0000000..74bbe26
--- /dev/null
@@ -0,0 +1,385 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Windows;\r
+using System.Windows.Controls;\r
+using System.Windows.Documents;\r
+using System.Windows.Input;\r
+using System.Windows.Media;\r
+using NT2chView.NtUI;\r
+\r
+namespace NT2chView\r
+{\r
+    public class NTFavoriteThread\r
+    {\r
+        private string mAddress;\r
+        private string mBoardName;\r
+        private string mTitle;\r
+        public string Address { get { return mAddress; } }\r
+        public string Title { get{return mTitle;} }\r
+        public string BoardName { get{ return mBoardName; }}\r
+\r
+        //private int mResCnt;\r
+        //private int mReadResCnt;\r
+\r
+\r
+        private Paragraph mParagraph = null;\r
+        private bool mMousePressed = false;\r
+        //LinearGradientBrush mFavoriteMouseOverBKBrush;\r
+        Brush mFavoriteBKBrush;\r
+        Brush mFavoriteForeBrush;\r
+        Brush mBoardForeBrush;\r
+        Brush mFavoriteEmphasizeBKBrush;\r
+        Brush mFavoriteEmphasizeForeBrush;\r
+        Brush mFavoriteMouseOverBKBrush;\r
+        Brush mFavoriteDragOverBKBrush;\r
+\r
+\r
+        ScrollViewer mScrollViewer;\r
+        StackPanel mPanelMain;\r
+\r
+        public void setScrollViewer(ScrollViewer sv, StackPanel panel)\r
+        {\r
+            mScrollViewer = sv;\r
+            mPanelMain = panel;\r
+        }\r
+\r
+        public string getDescription()\r
+        {\r
+            StringBuilder sb = new StringBuilder(128);\r
+            sb.Append(mAddress).Append(NTTextUtiles.YEN_VALUE[0]);\r
+            sb.Append(mBoardName).Append(NTTextUtiles.YEN_VALUE[0]);\r
+            sb.Append(mTitle);\r
+            return sb.ToString();\r
+        }\r
+        \r
+        public bool Same(NTFavoriteThread source)\r
+        {\r
+            return Same(source.mAddress, source.mBoardName, source.mTitle);\r
+        }\r
+\r
+        public bool Same(string address, string boardName, string title)\r
+        {\r
+            return (mAddress != null && mBoardName != null && mTitle != null &&\r
+                      address != null && boardName != null && title != null &&\r
+                      mAddress.Equals(address) &&\r
+                      mBoardName.Equals(boardName) &&\r
+                      mTitle.Equals(title));\r
+        }\r
+\r
+        public NTFavoriteThread(string address, string boardName, string title)\r
+        {\r
+            mAddress = address;\r
+            mBoardName = boardName;\r
+            mTitle = title;\r
+            mFavoriteMouseOverBKBrush = (Brush)\r
+                NTAppState.getMainWindow().TryFindResource("FavoriteThreadMouseOverBKBrush");\r
+            mFavoriteDragOverBKBrush = (Brush)\r
+                NTAppState.getMainWindow().TryFindResource("FavoriteThreadDragOverBKBrush");\r
+            mFavoriteBKBrush = (Brush)\r
+                NTAppState.getMainWindow().TryFindResource("FavoriteThreadBKBrush");\r
+            mFavoriteForeBrush = (Brush)\r
+                NTAppState.getMainWindow().TryFindResource("FavoriteThreadForeBrush");\r
+            mBoardForeBrush = (Brush)\r
+                NTAppState.getMainWindow().TryFindResource("FavoriteThreadBoardForeBrush");\r
+            mFavoriteEmphasizeBKBrush = (Brush)\r
+                NTAppState.getMainWindow().TryFindResource("FavoriteThreadEmphasizedBKBrush");\r
+            mFavoriteEmphasizeForeBrush = (Brush)\r
+                NTAppState.getMainWindow().TryFindResource("FavoriteThreadEmphasizedForeBrush");\r
+\r
+            //FavoriteThreadBoardForeBrush FavoriteThreadEmphasizedBKBrush\r
+            // NTAppState.getMainWindow().TryFindResource("FavoriteThreadBKBrush");FavoriteThreadMouseOverBKBrush\r
+        }\r
+\r
+        public void updateParagraph(NTThreadTitle thread)\r
+        {\r
+            if (mParagraph == null)\r
+                return;\r
+\r
+            int cnt = mParagraph.Inlines.Count;\r
+            if(cnt < 3)\r
+                return;\r
+\r
+            for(int i = cnt; cnt > 3; cnt--)\r
+            {\r
+                Inline inline = mParagraph.Inlines.LastInline;\r
+                mParagraph.Inlines.Remove(inline);\r
+\r
+            }\r
+\r
+            int resCnt = thread.ResCnt;\r
+            Run run = new Run("("+resCnt+") ");\r
+            if (mFavoriteForeBrush != null)\r
+            {\r
+                run.Foreground = mFavoriteForeBrush;\r
+            }\r
+            else\r
+            {\r
+                run.Foreground = Brushes.Black;\r
+            }\r
+            run.FontSize = 12;\r
+            //run.AllowDrop = true;\r
+            mParagraph.Inlines.Add(run);\r
+\r
+            int readCnt = thread.ReadCnt;\r
+            int unreadCnt = resCnt - readCnt;\r
+\r
+            if (readCnt != 0)\r
+            {\r
+                run = new Run("未読" + unreadCnt);\r
+                if (resCnt > readCnt)\r
+                {\r
+                    if (mFavoriteEmphasizeForeBrush != null)\r
+                        run.Foreground = mFavoriteEmphasizeForeBrush;\r
+                    else\r
+                        run.Foreground = Brushes.White;\r
+                    if (mFavoriteEmphasizeBKBrush != null)\r
+                        run.Background = mFavoriteEmphasizeBKBrush;\r
+                    else\r
+                        run.Background = Brushes.Red;\r
+                }\r
+                else\r
+                {\r
+                    if (mFavoriteForeBrush != null)\r
+                        run.Foreground = mFavoriteForeBrush;\r
+                    else\r
+                        run.Foreground = Brushes.Black;\r
+                }\r
+                run.FontSize = 14;\r
+                //run.AllowDrop = true;\r
+                mParagraph.Inlines.Add(run);\r
+            }\r
+        }\r
+\r
+        public void setDragOverBrush(bool isOver)\r
+        {\r
+            if (isOver)\r
+            {\r
+                if (mFavoriteDragOverBKBrush != null)\r
+                    mParagraph.Background = mFavoriteDragOverBKBrush;\r
+            }\r
+            else\r
+            {\r
+                if (mFavoriteBKBrush != null)\r
+                    mParagraph.Background = mFavoriteBKBrush;\r
+            }\r
+        }\r
+\r
+        public Paragraph createParagraph()\r
+        {\r
+            Paragraph para = new Paragraph();\r
+            para.Tag = this;\r
+            para.Margin = new Thickness(0, 5, 0, 5);\r
+            para.MouseEnter += para_MouseEnter;\r
+            para.MouseLeave += para_MouseLeave;\r
+            para.MouseLeftButtonDown += para_MouseLeftButtonDown;\r
+            para.MouseLeftButtonUp += para_MouseLeftButtonUp;\r
+            para.MouseMove += para_MouseMove;\r
+            para.MouseWheel += para_MouseWheel;\r
+            //para.AllowDrop = true;\r
+\r
+            para.Typography.NumeralStyle = FontNumeralStyle.Lining;\r
+            para.Typography.Fraction = FontFraction.Slashed;\r
+            para.Typography.Variants = FontVariants.Normal;\r
+\r
+            Run run = new Run(mBoardName);\r
+            if (mBoardForeBrush != null)\r
+                run.Foreground = mBoardForeBrush;\r
+            else\r
+                run.Foreground = Brushes.Orange;\r
+\r
+            //if (mFavoriteBKBrush != null)\r
+            //{\r
+            //    para.Background = mFavoriteBKBrush;\r
+            //    run.Background = mFavoriteBKBrush;\r
+            //}\r
+\r
+            run.FontWeight = FontWeights.Bold;\r
+            run.FontSize = 12;\r
+            para.Inlines.Add(run);\r
+\r
+            LineBreak lb = new LineBreak();\r
+            para.Inlines.Add(lb);\r
+\r
+            run = new Run(mTitle);\r
+            if (mFavoriteForeBrush != null)\r
+                run.Foreground = mFavoriteForeBrush;\r
+            else\r
+                run.Foreground = Brushes.Black;\r
+            //if (mFavoriteBKBrush != null)\r
+            //    run.Background = mFavoriteBKBrush;\r
+            run.FontSize = 14;\r
+            run.AllowDrop = true;\r
+            para.Inlines.Add(run);\r
+\r
+           // lb = new LineBreak();\r
+           // para.Inlines.Add(lb);\r
+\r
+            mParagraph = para;\r
+\r
+            return para;\r
+\r
+        }\r
+\r
+        bool fDown = false;\r
+        TouchPoint mPos;\r
+        double mVOffest;\r
+        void document_TouchUp(object sender, TouchEventArgs e)\r
+        {\r
+            fDown = false;\r
+            //throw new NotImplementedException();\r
+        }\r
+\r
+        void document_TouchMove(object sender, TouchEventArgs e)\r
+        {\r
+            if (!fDown)\r
+                return;\r
+            if (mScrollViewer == null)\r
+                return;\r
+\r
+\r
+            TouchPoint pos = e.GetTouchPoint(mPanelMain);\r
+            double y = mPos.Position.Y - pos.Position.Y;\r
+            double newOffset = mVOffest + y;\r
+            if (mScrollViewer != null)\r
+                mScrollViewer.ScrollToVerticalOffset(newOffset);\r
+        }\r
+\r
+\r
+        void document_TouchDown(object sender, TouchEventArgs e)\r
+        {\r
+            if (mScrollViewer == null)\r
+                return;\r
+\r
+            try\r
+            {\r
+                mPos = e.GetTouchPoint(mPanelMain);\r
+                mVOffest = mScrollViewer.VerticalOffset;\r
+                fDown = true;\r
+            }\r
+            catch (Exception ex)\r
+            {\r
+                MessageBox.Show(ex.Message);\r
+            }\r
+        }\r
+        void para_MouseWheel(object sender, MouseWheelEventArgs e)\r
+        {\r
+            int d = e.Delta;\r
+            if (d == 0)\r
+                return;\r
+            if (mScrollViewer == null)\r
+                return;\r
+\r
+            int vOffset = (int)mScrollViewer.VerticalOffset;\r
+\r
+            vOffset -= e.Delta;\r
+\r
+            mScrollViewer.ScrollToVerticalOffset(vOffset);\r
+\r
+\r
+            //throw new NotImplementedException();\r
+        }\r
+\r
+        Paragraph mMouseObservParagraph = null;\r
+        Point mMouseObservePoint;\r
+\r
+        void para_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)\r
+        {\r
+            //NTDebug.l("Mouse LeftUp");\r
+            if (mMousePressed)\r
+            {\r
+               NTBoard board = NTDataRoot.getBoardByName(mBoardName);\r
+                if (board != null)\r
+                {\r
+                    if (NTAppState.getMainWindow().OpenNewBoard(board))\r
+                    {\r
+                        NTThreadTitle tt = board.findThreadTitleByDatName(mAddress);\r
+                        if (tt != null)\r
+                        {\r
+                            NTAppState.getMainWindow().OpenNewThread(tt);\r
+                            e.Handled = true;\r
+                        }\r
+                    }\r
+                }\r
+            }\r
+            mMousePressed = false;\r
+            if (mFavoriteMouseOverBKBrush != null)\r
+                mParagraph.Background = mFavoriteMouseOverBKBrush;\r
+            else\r
+                mParagraph.Background = Brushes.Yellow;\r
+        }\r
+\r
+        void para_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)\r
+        {\r
+            //NTDebug.l("Mouse LeftDown");\r
+            mMousePressed = true;\r
+            e.Handled = true;\r
+\r
+            Paragraph para = sender as Paragraph;\r
+            if (para == null)\r
+            {\r
+                mMouseObservParagraph = null;\r
+                return;\r
+            }\r
+            mMouseObservParagraph = para;\r
+            mMouseObservePoint = e.GetPosition(para);\r
+\r
+        }\r
+\r
+        void para_MouseMove(object sender, MouseEventArgs e)\r
+        {\r
+            //NTDebug.l("Mouse Move");\r
+            if (mMouseObservParagraph == null)\r
+                return;\r
+            Paragraph para = sender as Paragraph;\r
+            if (para == null || !para.Equals(mMouseObservParagraph))\r
+            {\r
+                mMouseObservParagraph = null;\r
+                return;\r
+            }\r
+            Point point = e.GetPosition(para);\r
+            NTDebug.l("Point (" + point.X + "," + point.Y + ")");\r
+            Vector v = Point.Subtract(point, mMouseObservePoint);\r
+            if (v.Length > NTDragDrop.DRAG_START_MOVE_DELTA)\r
+            {\r
+                startDrag();\r
+                e.Handled = true;\r
+                mMousePressed = false;\r
+                //mParagraph.Background = Brushes.White;\r
+                mMouseObservParagraph = null;\r
+            }\r
+\r
+        }\r
+\r
+        void startDrag()\r
+        {\r
+            //NTDebug.l("*** Drag Start!!! ***");\r
+            NTDragDrop.ThreadData data = new NTDragDrop.ThreadData(this);\r
+            DataObject dObj = new DataObject(NTDragDrop.THREAD_DRAG_DATA_FORMAT, data);\r
+\r
+            DragDrop.DoDragDrop(mParagraph, dObj, DragDropEffects.All);\r
+        }\r
+\r
+        void para_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e)\r
+        {\r
+            mMousePressed = false;\r
+            if(mFavoriteBKBrush != null)\r
+                mParagraph.Background = mFavoriteBKBrush;\r
+            else\r
+                mParagraph.Background = Brushes.White;\r
+            mMouseObservParagraph = null;\r
+            //NTDebug.l("Mouse Leave");\r
+        }\r
+\r
+        void para_MouseEnter(object sender, System.Windows.Input.MouseEventArgs e)\r
+        {\r
+            //NTDebug.l("Mouse Enter");\r
+            mMousePressed = false;\r
+            if (mFavoriteMouseOverBKBrush != null)\r
+                mParagraph.Background = mFavoriteMouseOverBKBrush;\r
+            else\r
+                mParagraph.Background = Brushes.Yellow;\r
+        }\r
+\r
+    }\r
+}\r
diff --git a/NT2chView45/NTFavoriteThreadPopupMenu.cs b/NT2chView45/NTFavoriteThreadPopupMenu.cs
new file mode 100755 (executable)
index 0000000..61fc334
--- /dev/null
@@ -0,0 +1,119 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Windows.Controls;\r
+using System.Windows.Controls.Primitives;\r
+using System.Windows.Documents;\r
+using System.Windows.Media;\r
+\r
+namespace NT2chView\r
+{\r
+    class NTFavoriteThreadPopupMenu : Popup\r
+    {\r
+        public delegate void DelegateMsgOnNotifiDeleteFavoriteThread(NTFavoriteThread thread);\r
+        public event DelegateMsgOnNotifiDeleteFavoriteThread OnNotifiDeleteFavoriteThread;\r
+\r
+        NTFavoriteThread mFavoriteThread;\r
+\r
+        public void show()\r
+        {\r
+            IsOpen = true;\r
+            Placement = PlacementMode.Mouse;\r
+            Focus();\r
+        }\r
+\r
+        public NTFavoriteThreadPopupMenu(NTFavoriteThread ft)\r
+            : base()\r
+        {\r
+\r
+            mFavoriteThread = ft;\r
\r
+            this.StaysOpen = false;\r
+            //this.MouseLeave += NTResPopupMenu_MouseLeave;\r
+            //this.LostFocus += NTResPopupMenu_LostFocus;\r
+            \r
+            \r
+\r
+            StackPanel sp = new StackPanel();\r
+            sp.Orientation = Orientation.Horizontal;\r
+\r
+\r
+            StackPanel panel = new StackPanel();\r
+            Border border = new Border();\r
+            border.BorderThickness = new System.Windows.Thickness(1);\r
+            border.BorderBrush = new SolidColorBrush(Colors.DarkGray);\r
+           \r
+\r
+            ListBoxItem item1 = new ListBoxItem();\r
+\r
+            sp = new StackPanel();\r
+            //sp.MouseLeftButtonDown += threadTitle_MouseLeftButtonDown;\r
+            sp.Children.Add(new TextBlock(new Run(ft.Title)));\r
+            //sp.Tag = tt;\r
+            item1.Content = sp;\r
+            item1.Padding = new System.Windows.Thickness(10, 2, 10, 2);\r
+            //item1.Tag = tt;\r
+            //item1.MouseEnter += item1_MouseEnter;\r
+            //item1.MouseLeave += item1_MouseLeave;\r
+            panel.Children.Add(item1);\r
+\r
+            sp = new StackPanel();\r
+            sp.Children.Add(new Separator());\r
+            item1 = new ListBoxItem();\r
+            item1.BorderBrush = new SolidColorBrush(Colors.LightGray);\r
+            item1.BorderThickness = new System.Windows.Thickness(1);\r
+            item1.Height = 1;\r
+            item1.Content = sp;\r
+            panel.Children.Add(item1);\r
+            panel.Background = new SolidColorBrush(Colors.White);\r
+\r
+\r
+            sp = new StackPanel();\r
+            sp.Children.Add(new TextBlock(new Run("お気に入りから削除")));\r
+            sp.MouseLeftButtonDown += itemDelete_MouseLeftButtonDown;\r
+            sp.Tag = ft;\r
+            item1 = new ListBoxItem();\r
+            item1.Padding = new System.Windows.Thickness(10, 2, 10, 2);\r
+            item1.Content = sp;\r
+            //item1.MouseEnter += item1_MouseEnter;\r
+            //item1.MouseLeave += item1_MouseLeave;\r
+            //item1.MouseLeftButtonDown += item1_MouseLeftButtonDown;\r
+            //item1.MouseLeftButtonUp += item1_MouseLeftButtonUp;\r
+            panel.Children.Add(item1);\r
\r
+\r
+            sp = new StackPanel();\r
+            sp.Children.Add(new TextBlock(new Run("閉じる")));\r
+            sp.MouseLeftButtonDown += itemClose_MouseLeftButtonDown;\r
+            item1 = new ListBoxItem();\r
+            item1.Padding = new System.Windows.Thickness(10, 2, 10, 2);\r
+            item1.Content = sp;\r
+            //item1.MouseEnter += item1_MouseEnter;\r
+            //item1.MouseLeave += item1_MouseLeave;\r
+            //item1.MouseLeftButtonDown += item1_MouseLeftButtonDown;\r
+            //item1.MouseLeftButtonUp += item1_MouseLeftButtonUp;\r
+            panel.Children.Add(item1);\r
+            //this.Child = panel;\r
+            border.Child = panel; \r
+            this.Child = border;\r
+\r
+        }\r
+\r
+        void itemDelete_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)\r
+        {\r
+            IsOpen = false;\r
+\r
+            if (OnNotifiDeleteFavoriteThread != null)\r
+            {\r
+                OnNotifiDeleteFavoriteThread(mFavoriteThread);\r
+            }\r
+        }\r
+\r
+        void itemClose_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)\r
+        {\r
+            //Hide();\r
+            IsOpen = false;\r
+            //mMainWnd.NgEdit_setResSection(mRes);\r
+        }\r
+    }\r
+}\r
diff --git a/NT2chView45/NTFavoriteThreadTag.cs b/NT2chView45/NTFavoriteThreadTag.cs
new file mode 100755 (executable)
index 0000000..a3099a4
--- /dev/null
@@ -0,0 +1,82 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+\r
+namespace NT2chView\r
+{\r
+    public class NTFavoriteThreadTag\r
+    {\r
+        string mTagName;\r
+        int mCount;\r
+        bool mOpened = false;\r
+        bool mAutoUpdate = true;\r
+        List<NTFavoriteThread> mThreadList = new List<NTFavoriteThread>();\r
+\r
+        public bool Opened()\r
+        {\r
+            return mOpened;\r
+        }\r
+\r
+        public string getTagName()\r
+        {\r
+            return mTagName;\r
+        }\r
+        public void setTagName(string  tagName)\r
+        {\r
+            mTagName = tagName;\r
+        }\r
+\r
+        public List<NTFavoriteThread> getThreadList()\r
+        {\r
+            return mThreadList;\r
+        }\r
+\r
+        public int getCount()\r
+        {\r
+            return mCount;\r
+        }\r
+\r
+        public void setCount(int value)\r
+        {\r
+            if (value < 0)\r
+                return;\r
+            mCount = value;\r
+        }\r
+\r
+        public void add(NTFavoriteThread thread)\r
+        {\r
+            mThreadList.Add(thread);\r
+        }\r
+\r
+        public NTFavoriteThreadTag(string tagName, string count, string attr)\r
+        {\r
+            mTagName = tagName;\r
+            int nCnt;\r
+            if (int.TryParse(count, out nCnt))\r
+                mCount = nCnt;\r
+            else\r
+                mCount = 0;\r
+\r
+            if (0 <= attr.IndexOf("open"))\r
+                mOpened = true;\r
+            else\r
+                mOpened = false;\r
+            if (0 <= attr.IndexOf("update"))\r
+                mAutoUpdate = true;\r
+            else\r
+                mAutoUpdate = false;\r
+        }\r
+\r
+        public string getDescription()\r
+        {\r
+            StringBuilder sb = new StringBuilder(mTagName.Length+16);\r
+            sb.Append(mTagName).Append(',').Append(mCount.ToString()).Append(',');\r
+            if (mOpened)\r
+                sb.Append("open ");\r
+            if (mAutoUpdate)\r
+                sb.Append("update ");\r
+            return sb.ToString();\r
+        }\r
+\r
+    }\r
+}\r
diff --git a/NT2chView45/NTFavoriteThreadTagPopupMenu.cs b/NT2chView45/NTFavoriteThreadTagPopupMenu.cs
new file mode 100755 (executable)
index 0000000..e6f08c5
--- /dev/null
@@ -0,0 +1,163 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Windows.Controls;\r
+using System.Windows.Controls.Primitives;\r
+using System.Windows.Documents;\r
+using System.Windows.Media;\r
+\r
+namespace NT2chView\r
+{\r
+    class NTFavoriteThreadTagPopupMenu : Popup\r
+    {\r
+        public delegate void DelegateMsgOnNotifiDeleteFavoriteThreadTag(\r
+            NTFavoriteThreadTag threadTag, bool delWithItem);\r
+        public event DelegateMsgOnNotifiDeleteFavoriteThreadTag OnNotifiDeleteFavoriteThreadTag;\r
+        public delegate void DelegateMsgOnNotifiChangeFavoriteThreadTagName(\r
+            NTFavoriteThreadTag threadTag);\r
+        public event DelegateMsgOnNotifiChangeFavoriteThreadTagName OnNotifiChangeFavoriteThreadTagName;\r
+\r
+        NTFavoriteThreadTag mFavoriteThreadTag;\r
+\r
+        public void show()\r
+        {\r
+            IsOpen = true;\r
+            Placement = PlacementMode.Mouse;\r
+            Focus();\r
+        }\r
+\r
+        public NTFavoriteThreadTagPopupMenu(NTFavoriteThreadTag tag)\r
+            : base()\r
+        {\r
+\r
+            mFavoriteThreadTag = tag;\r
\r
+            this.StaysOpen = false;\r
+            //this.MouseLeave += NTResPopupMenu_MouseLeave;\r
+            //this.LostFocus += NTResPopupMenu_LostFocus;\r
+            \r
+            \r
+\r
+            StackPanel sp = new StackPanel();\r
+            sp.Orientation = Orientation.Horizontal;\r
+\r
+\r
+            StackPanel panel = new StackPanel();\r
+            Border border = new Border();\r
+            border.BorderThickness = new System.Windows.Thickness(1);\r
+            border.BorderBrush = new SolidColorBrush(Colors.DarkGray);\r
+           \r
+\r
+            ListBoxItem item1 = new ListBoxItem();\r
+\r
+            sp = new StackPanel();\r
+            //sp.MouseLeftButtonDown += threadTitle_MouseLeftButtonDown;\r
+            sp.Children.Add(new TextBlock(new Run(tag.getTagName())));\r
+            //sp.Tag = tt;\r
+            item1.Content = sp;\r
+            item1.Padding = new System.Windows.Thickness(10, 2, 10, 2);\r
+            //item1.Tag = tt;\r
+            //item1.MouseEnter += item1_MouseEnter;\r
+            //item1.MouseLeave += item1_MouseLeave;\r
+            panel.Children.Add(item1);\r
+\r
+            sp = new StackPanel();\r
+            sp.Children.Add(new Separator());\r
+            item1 = new ListBoxItem();\r
+            item1.BorderBrush = new SolidColorBrush(Colors.LightGray);\r
+            item1.BorderThickness = new System.Windows.Thickness(1);\r
+            item1.Height = 1;\r
+            item1.Content = sp;\r
+            panel.Children.Add(item1);\r
+            panel.Background = new SolidColorBrush(Colors.White);\r
+\r
+\r
+            sp = new StackPanel();\r
+            sp.Children.Add(new TextBlock(new Run("フォルダーをアイテムごと削除")));\r
+            sp.MouseLeftButtonDown += itemDeleteWithItem_MouseLeftButtonDown;\r
+            sp.Tag = tag;\r
+            item1 = new ListBoxItem();\r
+            item1.Padding = new System.Windows.Thickness(10, 2, 10, 2);\r
+            item1.Content = sp;\r
+            panel.Children.Add(item1);\r
+\r
+            sp = new StackPanel();\r
+            sp.Children.Add(new TextBlock(new Run("フォルダーだけを削除")));\r
+            sp.MouseLeftButtonDown += itemDeleteWithoutItem_MouseLeftButtonDown;\r
+            sp.Tag = tag;\r
+            item1 = new ListBoxItem();\r
+            item1.Padding = new System.Windows.Thickness(10, 2, 10, 2);\r
+            item1.Content = sp;\r
+            panel.Children.Add(item1);\r
+\r
+            sp = new StackPanel();\r
+            sp.Children.Add(new TextBlock(new Run("名前の変更")));\r
+            sp.MouseLeftButtonDown += itemChangeName_MouseLeftButtonDown;\r
+            sp.Tag = tag;\r
+            item1 = new ListBoxItem();\r
+            item1.Padding = new System.Windows.Thickness(10, 2, 10, 2);\r
+            item1.Content = sp;\r
+            panel.Children.Add(item1);\r
+\r
+\r
+            sp = new StackPanel();\r
+            sp.Children.Add(new TextBlock(new Run("閉じる")));\r
+            sp.MouseLeftButtonDown += itemClose_MouseLeftButtonDown;\r
+            item1 = new ListBoxItem();\r
+            item1.Padding = new System.Windows.Thickness(10, 2, 10, 2);\r
+            item1.Content = sp;\r
+            panel.Children.Add(item1);\r
+            //this.Child = panel;\r
+            border.Child = panel; \r
+            this.Child = border;\r
+\r
+        }\r
+\r
+        void itemDeleteWithItem_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)\r
+        {\r
+            IsOpen = false;\r
+\r
+            if (OnNotifiDeleteFavoriteThreadTag != null)\r
+            {\r
+                OnNotifiDeleteFavoriteThreadTag(mFavoriteThreadTag, true);\r
+            }\r
+        }\r
+        void itemDeleteWithoutItem_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)\r
+        {\r
+            IsOpen = false;\r
+\r
+            if (OnNotifiDeleteFavoriteThreadTag != null)\r
+            {\r
+                OnNotifiDeleteFavoriteThreadTag(mFavoriteThreadTag, false);\r
+            }\r
+        }\r
+        void itemChangeName_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)\r
+        {\r
+            IsOpen = false;\r
+\r
+            NTFavoriteTagEditWindow wnd = new NTFavoriteTagEditWindow();\r
+            wnd.setText(mFavoriteThreadTag.getTagName());\r
+            bool? result = wnd.ShowDialog();\r
+            if (!result.HasValue)\r
+                return;\r
+            if (!(bool)result)\r
+                return;\r
+            string newName = wnd.getText();\r
+            if (newName == null || newName.Length == 0)\r
+                return;\r
+\r
+            mFavoriteThreadTag.setTagName(newName);\r
+            if (OnNotifiChangeFavoriteThreadTagName != null)\r
+            {\r
+                OnNotifiChangeFavoriteThreadTagName(mFavoriteThreadTag);\r
+            }\r
+        }\r
+\r
+        void itemClose_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)\r
+        {\r
+            IsOpen = false;\r
+            //mMainWnd.NgEdit_setResSection(mRes);\r
+        }\r
+\r
+    }\r
+}\r
diff --git a/NT2chView45/NTFontSelectDialog.xaml b/NT2chView45/NTFontSelectDialog.xaml
new file mode 100755 (executable)
index 0000000..eb6dfa7
--- /dev/null
@@ -0,0 +1,23 @@
+<Window x:Class="NT2chView.NTFontSelectDialog"\r
+        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"\r
+        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"\r
+        Title="フォント選択ダイアログ" Height="400" Width="300" Loaded="NTFontSelectDialog_Loaded">\r
+    <Grid>\r
+        <Grid.RowDefinitions>\r
+            <RowDefinition Height="Auto"/>\r
+            <RowDefinition Height="Auto"/>\r
+            <RowDefinition Height="*"/>\r
+            <RowDefinition Height="Auto"/>\r
+        </Grid.RowDefinitions>\r
+        <Label Grid.Row="0" Margin="3">フォントの指定</Label>\r
+        <TextBox Grid.Row="1" x:Name="edtFontName"  BorderThickness="2" BorderBrush="Gray" Text="Font Name"/>\r
+        <Border Grid.Row="2" BorderBrush="Gray" BorderThickness="2">\r
+            <ScrollViewer>\r
+                <ListBox x:Name="lstFonts" SelectionChanged="lstFonts_selectionChanged"/>\r
+            </ScrollViewer>\r
+        </Border>\r
+        <StackPanel  Grid.Row="3" Orientation="Horizontal" FlowDirection="RightToLeft">\r
+            <Button x:Name="btnCancel" Margin="5" Padding="10,1" Width="100" Click="btnCancel_Click">キャンセル</Button>\r
+            <Button x:Name="btnOK" Margin="5" Padding="5,1" Width="100" Click="btnOK_Click">O K</Button>\r
+        </StackPanel>    </Grid>\r
+</Window>\r
diff --git a/NT2chView45/NTFontSelectDialog.xaml.cs b/NT2chView45/NTFontSelectDialog.xaml.cs
new file mode 100755 (executable)
index 0000000..d560d88
--- /dev/null
@@ -0,0 +1,96 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Windows;\r
+using System.Windows.Controls;\r
+using System.Windows.Data;\r
+using System.Windows.Documents;\r
+using System.Windows.Input;\r
+using System.Windows.Media;\r
+using System.Windows.Media.Imaging;\r
+using System.Windows.Shapes;\r
+\r
+namespace NT2chView\r
+{\r
+    /// <summary>\r
+    /// NTFontSelectDialog.xaml の相互作用ロジック\r
+    /// </summary>\r
+    public partial class NTFontSelectDialog : Window\r
+    {\r
+        public String FontName\r
+        {\r
+            get;\r
+            set;\r
+        }\r
+\r
+        public NTFontSelectDialog()\r
+        {\r
+            InitializeComponent();\r
+        }\r
+\r
+         private void NTFontSelectDialog_Loaded(object sender, RoutedEventArgs e)\r
+        {\r
+            edtFontName.Text = FontName;\r
+\r
+\r
+            int idx = 0;\r
+            int selIdx = -1;\r
+            foreach (FontFamily fontFamily in Fonts.SystemFontFamilies)\r
+            {\r
+                string source = fontFamily.Source;\r
+                lstFonts.Items.Add(source);\r
+                if (source.Equals(FontName))\r
+                    selIdx = idx;\r
+                idx++;\r
+            }\r
+\r
+            if (selIdx >= 0)\r
+            {\r
+                \r
+                lstFonts.SelectedIndex = selIdx;\r
+                lstFonts.ScrollIntoView(lstFonts.SelectedItem);\r
+            }\r
+\r
+        }\r
+       \r
+        private void lstFonts_selectionChanged(object sender, SelectionChangedEventArgs e)\r
+        {\r
+            ListBox lb = sender as ListBox;\r
+            if (lb != null)\r
+            {\r
+                ListBoxItem lbi =lb.SelectedItem as ListBoxItem;\r
+                if (lbi != null)\r
+                {\r
+                    edtFontName.Text = lbi.Content.ToString();\r
+                }\r
+                else\r
+                {\r
+                    string fontName = lb.SelectedItem as string;\r
+                    if (fontName != null)\r
+                    {\r
+                        edtFontName.Text = fontName;\r
+                    }\r
+\r
+                }\r
+\r
+            }\r
+\r
+        }\r
+\r
+        private void btnOK_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            this.DialogResult = true;\r
+            FontName = edtFontName.Text;\r
+            this.Close();\r
+        }\r
+\r
+        private void btnCancel_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            this.DialogResult = false;\r
+            FontName = string.Empty;\r
+            this.Close();\r
+\r
+        }\r
+\r
+    }\r
+}\r
diff --git a/NT2chView45/NTFontUtil.cs b/NT2chView45/NTFontUtil.cs
new file mode 100755 (executable)
index 0000000..6de413b
--- /dev/null
@@ -0,0 +1,54 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Windows.Media;\r
+\r
+namespace NT2chView\r
+{\r
+    static class NTFontUtil\r
+    {\r
+        static FontFamily mResFont;\r
+        static FontFamily mAAFont;\r
+\r
+        static NTFontUtil()\r
+        {\r
+\r
+        }\r
+\r
+        public static void clear()\r
+        {\r
+            mResFont = null;\r
+            mAAFont = null;\r
+        }\r
+\r
+        public static FontFamily getResFont()\r
+        {\r
+            if (!NTUserPreference.UseResFontTypeface)\r
+                return null;\r
+\r
+            if (mResFont == null)\r
+            {\r
+                string fontName = NTUserPreference.ResFontTypeface;\r
+                if (fontName != null && fontName.Length > 0)\r
+                    mResFont = new FontFamily(fontName);\r
+\r
+            }\r
+            return mResFont;\r
+        }\r
+        public static FontFamily getAAFont()\r
+        {\r
+            if (!NTUserPreference.UseAAFontTypeface)\r
+                return null;\r
+\r
+            if (mAAFont == null)\r
+            {\r
+                string fontName = NTUserPreference.AAFontTypeface;\r
+                if (fontName != null && fontName.Length > 0)\r
+                    mAAFont = new FontFamily(fontName);\r
+\r
+            }\r
+            return mAAFont;\r
+        }\r
+    \r
+    }\r
+}\r
diff --git a/NT2chView45/NTGraphicsPanel.xaml b/NT2chView45/NTGraphicsPanel.xaml
new file mode 100755 (executable)
index 0000000..4f90702
--- /dev/null
@@ -0,0 +1,53 @@
+<UserControl x:Class="NT2chView.NTGraphicsPanel"\r
+             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"\r
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"\r
+             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" \r
+             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" \r
+             mc:Ignorable="d" \r
+             d:DesignHeight="300" d:DesignWidth="300" Loaded="UserControl_Loaded">\r
+    <Grid>\r
+        <Grid.RowDefinitions>\r
+            <RowDefinition Height="*"/>\r
+            <RowDefinition Height="Auto"/>\r
+            <RowDefinition Height="Auto"/>\r
+        </Grid.RowDefinitions>\r
+        <ScrollViewer>\r
+            <StackPanel x:Name="mGrallyPanel" Background="DimGray" Orientation="Vertical"/>\r
+        </ScrollViewer>\r
+        <GridSplitter Grid.Column="0" Height="3" \r
+                          Grid.Row="1"\r
+                          VerticalAlignment="Center" HorizontalAlignment="Stretch"\r
+                          ShowsPreview="False" Background="LightGray" Cursor="SizeNS"/>\r
+        <StackPanel Grid.Row="2">\r
+            <Border BorderBrush="LightGray" BorderThickness="2" Margin="5">\r
+                <StackPanel>\r
+                    <Label>画像ビューア</Label>\r
+                    <Button x:Name="mBtnClearGarally" Width="60" HorizontalAlignment="Left" Click="mBtnClearGarally_Click">全消去</Button>\r
+                    <!--StackPanel Orientation="Horizontal">\r
+                        <Label>縦:</Label>\r
+                        <TextBox x:Name="mEdtImageHeight" Width="60" LostFocus="mEdtImageHeight_LostFocus"></TextBox>\r
+                        <Label>px</Label>\r
+                        <Label>横:</Label>\r
+                        <TextBox x:Name="mEdtImageWidth" Width="60" LostFocus="mEdtImageWidth_LostFocus"></TextBox>\r
+                        <Label>px</Label>\r
+                    </StackPanel-->\r
+                </StackPanel>\r
+            </Border>\r
+            <Label> </Label>\r
+            <Border BorderBrush="LightGray" BorderThickness="2" Margin="5">\r
+                <StackPanel>\r
+                    <Label>レスビューサムネイル</Label>\r
+                    <StackPanel Orientation="Horizontal">\r
+                        <Label>縦:</Label>\r
+                        <TextBox x:Name="mEdtThumbnailHeight"   Width="60" LostFocus="mEdtThumbmailHeight_LostFocus"></TextBox>\r
+                        <Label>px</Label>\r
+                        <Label>横:</Label>\r
+                        <TextBox x:Name="mEdtThumbnailWidth" Width="60" LostFocus="mEdtThumnailWidth_LostFocus"></TextBox>\r
+                        <Label>px</Label>\r
+                    </StackPanel>\r
+                    <CheckBox x:Name="mChkShowThumbnail" Margin="5" Content="レスビューにサムネイルを表示する" Unchecked="mChkShowThumbnail_Unchecked" Checked="mChkShowThumbnail_Checked"/>\r
+                </StackPanel>\r
+            </Border>\r
+        </StackPanel>            \r
+    </Grid>\r
+</UserControl>\r
diff --git a/NT2chView45/NTGraphicsPanel.xaml.cs b/NT2chView45/NTGraphicsPanel.xaml.cs
new file mode 100755 (executable)
index 0000000..3d8d749
--- /dev/null
@@ -0,0 +1,331 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.IO;\r
+using System.Text;\r
+using System.Windows;\r
+using System.Windows.Controls;\r
+using System.Windows.Data;\r
+using System.Windows.Documents;\r
+using System.Windows.Input;\r
+using System.Windows.Media;\r
+using System.Windows.Media.Imaging;\r
+using System.Windows.Navigation;\r
+using System.Windows.Shapes;\r
+using NT2chObject;\r
+\r
+namespace NT2chView\r
+{\r
+    /// <summary>\r
+    /// NTGraphicsPanel.xaml の相互作用ロジック\r
+    /// </summary>\r
+    public partial class NTGraphicsPanel : UserControl\r
+    {\r
+        const string ERROR_CAPTION = "入力エラー";\r
+        const string ERROR_MESSAGE = "整数値を入力してください";\r
+\r
+        public NTGraphicsPanel()\r
+        {\r
+            InitializeComponent();\r
+        }\r
+\r
+        public void Init()\r
+        {\r
+        }\r
+\r
+        public void AddGraphic(string path)\r
+        {\r
+            if (path == null || !File.Exists(path))\r
+                return;\r
+   \r
+            try\r
+            {\r
+                BitmapImage bi = new BitmapImage();\r
+\r
+                bi.BeginInit();\r
+\r
+                bi.CacheOption = BitmapCacheOption.OnDemand;\r
+                bi.CreateOptions = BitmapCreateOptions.DelayCreation;\r
+                //bi.DecodePixelHeight = height;\r
+                //bi.DecodePixelWidth = width;\r
+                bi.UriSource = new Uri(path, UriKind.Absolute);\r
+\r
+                bi.EndInit();\r
+     \r
+                Image img = new Image();\r
+                img.Stretch = System.Windows.Media.Stretch.UniformToFill;\r
+                img.Tag = path;\r
+                //img.Width = width;\r
+                //img.Height = height;\r
+                img.Source = bi;\r
+                img.MouseEnter += img_MouseEnter;\r
+                img.MouseLeave += img_MouseLeave;\r
+                img.MouseMove += img_MouseMove;\r
+                img.MouseLeftButtonDown += img_MouseLeftButtonDown;\r
+\r
+\r
+                Grid grid = new Grid();\r
+\r
+                grid.Children.Add(img);\r
+\r
+                img = new Image();\r
+                img.Width = 9;\r
+                img.Height = 9;\r
+                Uri oUri = new Uri(\r
+                    "pack://application:,,,/NT2chStyle45;component/images/close_tab.png",\r
+                    UriKind.RelativeOrAbsolute);\r
+                bi = new BitmapImage();\r
+                bi.BeginInit();\r
+                bi.UriSource = oUri;\r
+\r
+                bi.EndInit();\r
+                img.Source = bi;\r
+\r
+                Button btn = new Button();\r
+                btn.Content = img;\r
+                btn.HorizontalAlignment = System.Windows.HorizontalAlignment.Right;\r
+                btn.VerticalAlignment = System.Windows.VerticalAlignment.Top;\r
+                btn.Margin = new Thickness(4);\r
+                btn.Click += btn_Click;\r
+                \r
+                grid.Children.Add(btn);\r
+\r
+                btn.Visibility = System.Windows.Visibility.Hidden;\r
+\r
+\r
+                grid.VerticalAlignment = System.Windows.VerticalAlignment.Center;\r
+\r
+                mGrallyPanel.Children.Insert(0,grid);\r
+                ScrollViewer sv = mGrallyPanel.Parent as ScrollViewer;\r
+                sv.ScrollToTop();\r
+\r
+            }\r
+            catch (Exception e)\r
+            {\r
+\r
+            }\r
\r
+        }\r
+\r
+        void img_MouseMove(object sender, MouseEventArgs e)\r
+        {\r
+            if (mSelectedImage == null)\r
+                return;\r
+\r
+            Image img = sender as Image;\r
+            if (img == null || !mSelectedImage.Equals(img))\r
+            {\r
+                mSelectedImage = null;\r
+                return;\r
+            }\r
+            string path = img.Tag as string;\r
+            if (path == null)\r
+            {\r
+                mSelectedImage = null;\r
+                return;\r
+            }\r
+            string[] arr = new string[1];\r
+            arr[0] = path;\r
+\r
+            double DELTA = 8;\r
+            Point point = e.GetPosition(img);\r
+            Vector v = Point.Subtract(point, mObserveMousePoint);\r
+            if (v.Length > DELTA)\r
+            {\r
+                DataObject dObj = new DataObject(\r
+                    DataFormats.FileDrop, arr);\r
+                DragDrop.DoDragDrop(img, dObj, DragDropEffects.Copy);\r
+                //e.Handled = true;\r
+                mSelectedImage = null;\r
+            }\r
+\r
+        }\r
+\r
+        Image mSelectedImage = null;\r
+        Point mObserveMousePoint;\r
+        void img_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)\r
+        {\r
+            mSelectedImage = sender as Image;\r
+            if (mSelectedImage == null)\r
+                return;\r
+\r
+            mObserveMousePoint = e.GetPosition(mSelectedImage);\r
+            //Mouse.Capture(mSelectedImage, CaptureMode.Element);\r
+\r
+        }\r
+\r
+        void btn_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            Button btn = sender as Button;\r
+            if (btn == null)\r
+                return;\r
+\r
+            Grid grid = btn.Parent as Grid;\r
+            if (grid == null)\r
+                return;\r
+\r
+            mGrallyPanel.Children.Remove(grid);\r
+\r
+\r
+\r
+        }\r
+\r
+        void img_MouseLeave(object sender, MouseEventArgs e)\r
+        {\r
\r
+            Image img = sender as Image;\r
+            if (img == null)\r
+                return;\r
+\r
+            Grid grid = img.Parent as Grid;\r
+            if (grid == null)\r
+                return;\r
+\r
+            if (grid.Children.Count != 2)\r
+                return;\r
+\r
+            Button btn = grid.Children[1] as Button;\r
+            if (btn == null)\r
+                return;\r
+\r
+            double btnHeight = btn.ActualHeight;\r
+            double btnWidth = btn.ActualWidth;\r
+\r
+            Point pos = e.GetPosition(grid);\r
+            if ((pos.X > (grid.ActualWidth - (btnWidth + 4)) &&\r
+                pos.X < (grid.ActualWidth - 4)) &&\r
+                (pos.Y < (btnHeight + 4)) && pos.Y > 4)\r
+                return;\r
+\r
+\r
+            btn.Visibility = System.Windows.Visibility.Hidden;\r
+        }\r
+\r
+        void img_MouseEnter(object sender, MouseEventArgs e)\r
+        {\r
+            Image img = sender as Image;\r
+            if (img == null)\r
+                return;\r
+\r
+            Grid grid = img.Parent as Grid;\r
+            if (grid == null)\r
+                return;\r
+\r
+            if (grid.Children.Count != 2)\r
+                return;\r
+\r
+            Button btn = grid.Children[1] as Button;\r
+            if (btn == null)\r
+                return;\r
+            btn.Visibility = System.Windows.Visibility.Visible;\r
+        }\r
+\r
\r
+        /*private void mEdtImageWidth_LostFocus(object sender, RoutedEventArgs e)\r
+        {\r
+            TextBox tb = sender as TextBox;\r
+            if (tb == null)\r
+                return;\r
+            int value;\r
+            if (!int.TryParse(tb.Text, out value))\r
+            {\r
+                MessageBox.Show(ERROR_MESSAGE,ERROR_CAPTION);\r
+                tb.Text = NTUserPreference.ImageViewWidth.ToString();\r
+                return;\r
+            }\r
+            NTUserPreference.ImageViewWidth = value;\r
+\r
+        }\r
+        private void mEdtImageHeight_LostFocus(object sender, RoutedEventArgs e)\r
+        {\r
+            TextBox tb = sender as TextBox;\r
+            if (tb == null)\r
+                return;\r
+            int value;\r
+            if (!int.TryParse(tb.Text, out value))\r
+            {\r
+                MessageBox.Show(ERROR_MESSAGE, ERROR_CAPTION);\r
+                tb.Text = NTUserPreference.ImageViewHeight.ToString();\r
+                return;\r
+            }\r
+            NTUserPreference.ImageViewHeight = value;\r
+        }*/\r
+        private void mEdtThumbmailHeight_LostFocus(object sender, RoutedEventArgs e)\r
+        {\r
+            TextBox tb = sender as TextBox;\r
+            if (tb == null)\r
+                return;\r
+            int value;\r
+            if (!int.TryParse(tb.Text, out value))\r
+            {\r
+                MessageBox.Show(ERROR_MESSAGE, ERROR_CAPTION);\r
+                tb.Text = NTUserPreference.ResViewThumbnailHeight.ToString();\r
+                return;\r
+            }\r
+            NTUserPreference.ResViewThumbnailHeight = value;\r
+        }\r
+        \r
+        private void mEdtThumnailWidth_LostFocus(object sender, RoutedEventArgs e)\r
+        {\r
+            TextBox tb = sender as TextBox;\r
+            if (tb == null)\r
+                return;\r
+            int value;\r
+            if (!int.TryParse(tb.Text, out value))\r
+            {\r
+                MessageBox.Show(ERROR_MESSAGE, ERROR_CAPTION);\r
+                tb.Text = NTUserPreference.ResViewThumbnailWidth.ToString();\r
+                return;\r
+            }\r
+            NTUserPreference.ResViewThumbnailWidth = value;\r
+        }\r
+\r
+        private void mChkShowThumbnail_Unchecked(object sender, RoutedEventArgs e)\r
+        {\r
+            NTUserPreference.ResViewShowThumbnail = false;\r
+        }\r
+\r
+        private void mChkShowThumbnail_Checked(object sender, RoutedEventArgs e)\r
+        {\r
+            NTUserPreference.ResViewShowThumbnail = true;\r
+        }\r
+\r
+        private void UserControl_Loaded(object sender, RoutedEventArgs e)\r
+        {\r
+            //mEdtImageHeight.Text = NTUserPreference.ImageViewHeight.ToString();\r
+            //mEdtImageWidth.Text = NTUserPreference.ImageViewWidth.ToString();\r
+\r
+            mEdtThumbnailHeight.Text = NTUserPreference.ResViewThumbnailHeight.ToString();\r
+            mEdtThumbnailWidth.Text = NTUserPreference.ResViewThumbnailWidth.ToString();\r
+\r
+            mChkShowThumbnail.IsChecked = NTUserPreference.ResViewShowThumbnail;\r
+        }\r
+\r
+        private void mBtnClearGarally_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            mGrallyPanel.Children.Clear();\r
+        }\r
+\r
+\r
+\r
+        /*private bool ShowThumbnail\r
+        {\r
+            get\r
+            {\r
+                object o;\r
+                if (!mDict.TryGetValue(PREF_PARAM.RES_VIEW_SHOW_THUMBNAIL, out o))\r
+                    return false;\r
+                bool? show = o as bool?;\r
+\r
+                return (show.HasValue && (bool)show);\r
+            }\r
+            set\r
+            {\r
+                mDict.Remove(PREF_PARAM.RES_VIEW_SHOW_THUMBNAIL);\r
+                mDict.Add(PREF_PARAM.RES_VIEW_SHOW_THUMBNAIL,\r
+                    (value ? bool.TrueString : bool.FalseString));\r
+\r
+            }\r
+        }*/\r
\r
+    }\r
+}\r
diff --git a/NT2chView45/NTHistory.cs b/NT2chView45/NTHistory.cs
new file mode 100755 (executable)
index 0000000..77d25c4
--- /dev/null
@@ -0,0 +1,138 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Collections.ObjectModel;\r
+using System.Text;\r
+\r
+namespace NT2chView\r
+{\r
+    public class NTHistory\r
+    {\r
+        NTBoard.DelegateMsgOnNotifyBoardUpdate mOnNotifyBoardUpdate;\r
+\r
+        private static string mStrState = string.Empty;\r
+        public static string getLastState()\r
+        {\r
+            return mStrState;\r
+        }\r
+        public NTHistory()\r
+        {\r
+            mOnNotifyBoardUpdate \r
+                = new NTBoard.DelegateMsgOnNotifyBoardUpdate(OnNotifyBoardUpdate);\r
+        }\r
+\r
+        private ObservableCollection<NTHistoryThread> mThreadList = new ObservableCollection<NTHistoryThread>();\r
+        public ObservableCollection<NTHistoryThread> getThreadList()\r
+        {\r
+            return mThreadList;\r
+        }\r
+\r
+        public void onDetach()\r
+        {\r
+            Dictionary<string, NTBoard> boardDic = new Dictionary<string,NTBoard>();\r
+            foreach (NTHistoryThread ht in mThreadList)\r
+            {\r
+                if(boardDic.ContainsKey(ht.BoardName))\r
+                    continue;\r
+                NTBoard board = NTDataRoot.getBoardByName(ht.BoardName);\r
+                if (board == null)\r
+                    continue;\r
+                boardDic.Add(ht.BoardName, board);\r
+            }\r
+            foreach (NTBoard board in boardDic.Values)\r
+            {\r
+                if(mOnNotifyBoardUpdate != null)\r
+                    board.OnNotifyBoardUpdate -= mOnNotifyBoardUpdate;\r
+            }\r
+\r
+            mThreadList.Clear();\r
+        }\r
+\r
+        void OnNotifyBoardUpdate(NTBoard board)\r
+        {\r
+            if (mThreadList == null)\r
+                return;\r
+\r
+            foreach (NTHistoryThread ht in mThreadList)\r
+            {\r
+                if (board.mName.Equals(ht.BoardName))\r
+                    ht.update(board);\r
+            }\r
+\r
+        }\r
+        \r
\r
+        public bool parse(string source)\r
+        {\r
+            onDetach();\r
+\r
+            if (source == null || source.Length == 0)\r
+                return false;\r
+\r
+            string[] lines = NTTextUtiles.splitLine(source);\r
+            int lineLen = lines.Length;\r
+            if (lineLen == 0)\r
+                return false;\r
+            int retVal;\r
+            if (!int.TryParse(lines[0], out retVal))\r
+                return false;\r
+            \r
+            if (lineLen == 1)\r
+                return false;\r
+\r
+            mStrState = lines[1];\r
+\r
+            if (retVal != 100)\r
+                return false;\r
+\r
+\r
+            Dictionary<string, NTBoard> boardDic = new Dictionary<string, NTBoard>();\r
+\r
+            for (int i = 2; i < lineLen; i++)\r
+            {\r
+                string line = lines[i];\r
+                string[] values = line.Split(NTTextUtiles.COMMA_VALUE);\r
+                if (values.Length != 3)\r
+                    continue;\r
+\r
+                string boardName;\r
+                string datName;\r
+                if (NTUserPreference.AESEnabled)\r
+                {\r
+                    boardName = NTTextUtiles.aesDecodeBase64URL(values[0]);\r
+                    datName = NTTextUtiles.aesDecodeBase64URL(values[1]);\r
+                }\r
+                else\r
+                {\r
+                    boardName = NTTextUtiles.decodeBase64URL(values[0]);\r
+                    datName = NTTextUtiles.decodeBase64URL(values[1]);\r
+                }\r
+                string dateTimeDescription = values[2];\r
+\r
+                NTHistoryThread ht = new NTHistoryThread(boardName, datName, dateTimeDescription);\r
+\r
+                mThreadList.Add(ht);\r
+\r
+                if (!boardDic.ContainsKey(boardName))\r
+                {\r
+                    NTBoard board = NTDataRoot.getBoardByName(boardName);\r
+                    if (board != null)\r
+                        boardDic.Add(boardName, board);\r
+                }\r
+            }\r
+\r
+            foreach (NTBoard board in boardDic.Values)\r
+            {\r
+                if (board.mDataInit)\r
+                {\r
+                    OnNotifyBoardUpdate(board);\r
+                }\r
+                else\r
+                {\r
+                    board.Update(mOnNotifyBoardUpdate);\r
+                }\r
+            }\r
+\r
+            return true;\r
+        }\r
+    }\r
+}\r
diff --git a/NT2chView45/NTHistoryPanel.xaml b/NT2chView45/NTHistoryPanel.xaml
new file mode 100755 (executable)
index 0000000..33f5df1
--- /dev/null
@@ -0,0 +1,30 @@
+<UserControl x:Class="NT2chView.NTHistoryPanel"\r
+             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"\r
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"\r
+             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" \r
+             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" \r
+             mc:Ignorable="d" \r
+             d:DesignHeight="300" d:DesignWidth="300">\r
+    <Grid>\r
+        <Grid.RowDefinitions>\r
+            <RowDefinition Height="Auto"/>\r
+            <RowDefinition Height="*" />\r
+        </Grid.RowDefinitions>\r
+        <ComboBox x:Name="cmbHistoryType" SelectionChanged="cmbHistoryType_SelectionChanged">\r
+            <ComboBox.Items>               \r
+                <ComboBoxItem  IsSelected="True" Content="読み込み履歴(クラウド)"/>\r
+                <ComboBoxItem Content="書込履歴(クラウド)" />\r
+                <ComboBoxItem Content="しおりの履歴(クラウド)" />\r
+            </ComboBox.Items>\r
+        </ComboBox>\r
+        <ListView Grid.Row="1" x:Name="lstHistory" MouseLeftButtonUp="lstHistory_MouseLeftButtonUp">\r
+            <ListView.View>\r
+                <GridView>\r
+                    <GridViewColumn Header="タイトル" Width="150"/>\r
+                    <GridViewColumn Header="取得時間" Width="150"/>\r
+                </GridView>\r
+            </ListView.View>\r
+        </ListView>\r
+\r
+    </Grid>\r
+</UserControl>\r
diff --git a/NT2chView45/NTHistoryPanel.xaml.cs b/NT2chView45/NTHistoryPanel.xaml.cs
new file mode 100755 (executable)
index 0000000..d0f01a9
--- /dev/null
@@ -0,0 +1,132 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Windows;\r
+using System.Windows.Controls;\r
+using System.Windows.Data;\r
+using System.Windows.Documents;\r
+using System.Windows.Input;\r
+using System.Windows.Media;\r
+using System.Windows.Media.Imaging;\r
+using System.Windows.Navigation;\r
+using System.Windows.Shapes;\r
+\r
+namespace NT2chView\r
+{\r
+    /// <summary>\r
+    /// NTHistoryPanel.xaml の相互作用ロジック\r
+    /// </summary>\r
+    public partial class NTHistoryPanel : UserControl\r
+    {\r
+        static readonly string[] LIST_COLUMN_HEADERS_PNAME = { "Title", "DateTimeDescription" };\r
+\r
+        public MainWindow.DelegateMsgOpenThreadRequest OpenThreadRequest { get; set; }\r
+        public MainWindow.DelegateMsgGetHistoryOnCloud GetHistoryOnCloud { get; set; }\r
+\r
+        NTHistory mHistory = null;\r
+        public NTHistory History\r
+        {\r
+            set \r
+            {\r
+                if (mHistory != null)\r
+                    mHistory.onDetach();\r
+\r
+                mHistory = value;\r
+                parse();\r
+            }\r
+        }\r
+\r
+        public NTHistoryPanel()\r
+        {\r
+            InitializeComponent();\r
+        }\r
+\r
+\r
+        private void parse()\r
+        {\r
+            if (mHistory == null)\r
+                return;\r
+\r
+            GridView gv = lstHistory.View as GridView;\r
+            int cnt = gv.Columns.Count;\r
+            cnt = (cnt < LIST_COLUMN_HEADERS_PNAME.Length) ? cnt : LIST_COLUMN_HEADERS_PNAME.Length;\r
+\r
+            for(int i = 0; i < cnt; i++)\r
+            {\r
+                GridViewColumn gvc = gv.Columns[i]; \r
+                PropertyPath pp = new PropertyPath(LIST_COLUMN_HEADERS_PNAME[i]);\r
+                Binding b = new Binding();\r
+                b.Path = pp;\r
+                gvc.DisplayMemberBinding = b;\r
+\r
+            }\r
+\r
+            lstHistory.ItemsSource = mHistory.getThreadList();\r
+\r
+        }\r
+\r
+        private void lstHistory_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)\r
+        {\r
+            ListView lv = sender as ListView;\r
+            if (lv == null)\r
+                return;\r
+\r
+            NTHistoryThread ht = lv.SelectedItem as NTHistoryThread;\r
+            if (ht == null)\r
+                return;\r
+\r
+            //NTDebug.l(ht.Title);\r
+            NTBoard board = NTDataRoot.getBoardByName(ht.BoardName);\r
+            if(board == null)\r
+                return;\r
+            NTThreadTitle tt = board.findThreadTitleByDatName(ht.getDatName());\r
+            if (tt != null)\r
+            {\r
+                if (OpenThreadRequest != null)\r
+                    OpenThreadRequest(tt);\r
+            }\r
+        }\r
+\r
+        private void cmbHistoryType_SelectionChanged(object sender, SelectionChangedEventArgs e)\r
+        {\r
+            if (1 != e.AddedItems.Count)\r
+                return;\r
+            ComboBoxItem cbi1 = e.AddedItems[0] as ComboBoxItem;\r
+            if (cbi1 == null)\r
+                return;\r
+\r
+            //string addStr = e.AddedItems[0] as string;\r
+\r
+            if (1 != e.RemovedItems.Count)\r
+                return;\r
+\r
+            ComboBoxItem cbi2 = e.RemovedItems[0] as ComboBoxItem;\r
+            if (cbi2 == null)\r
+                return;\r
+\r
+            int type;\r
+            string text = cbi1.Content as string;\r
+            if (text == null)\r
+                return;\r
+\r
+            switch (text)\r
+            {\r
+\r
+                case "読み込み履歴(クラウド)":\r
+                    type = 1;\r
+                    break;\r
+                case "書込履歴(クラウド)":\r
+                    type = 2;\r
+                    break;\r
+                case "しおりの履歴(クラウド)":\r
+                    type = 3;\r
+                    break;\r
+                default:\r
+                    return;\r
+            }\r
+            //NTDebug.l(cbi1.ToString() + ":" + cbi2.ToString());\r
+            if(GetHistoryOnCloud != null)\r
+                GetHistoryOnCloud(type);\r
+        }\r
+    }\r
+}\r
diff --git a/NT2chView45/NTHistoryThread.cs b/NT2chView45/NTHistoryThread.cs
new file mode 100755 (executable)
index 0000000..edd5ef3
--- /dev/null
@@ -0,0 +1,77 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Windows;\r
+\r
+namespace NT2chView\r
+{\r
+    public class NTHistoryThread : DependencyObject\r
+    {\r
+        const string UNKNOWN_THREADTITLE_DESCRIPTION = "Unknown Title";\r
+\r
+        private string mDatName;\r
+        public string getDatName() { return mDatName; }\r
+\r
+        public static readonly DependencyProperty BoardNameProperty;\r
+        public static readonly DependencyProperty TitleProperty;\r
+        public static readonly DependencyProperty DateTimeDescriptionProperty;\r
+\r
+        static NTHistoryThread()\r
+        {\r
+            \r
+            PropertyMetadata pmBoard = new PropertyMetadata(string.Empty);\r
+            PropertyMetadata pmDateTime = new PropertyMetadata(string.Empty);\r
+            PropertyMetadata pmTitle = new PropertyMetadata(string.Empty);\r
+\r
+            BoardNameProperty = DependencyProperty.Register("BoardName", typeof(string), \r
+                        typeof(NTHistoryThread), pmBoard);\r
+            TitleProperty = DependencyProperty.Register("Title", typeof(string), \r
+                        typeof(NTHistoryThread), pmTitle);\r
+            DateTimeDescriptionProperty = DependencyProperty.Register("DateTimeDescription",\r
+                        typeof(string), typeof(NTHistoryThread), pmDateTime);\r
+       \r
+        }\r
+\r
+        public string Title\r
+        {\r
+            set { SetValue(TitleProperty, value); }\r
+            get { return (string)GetValue(TitleProperty); }\r
+        }\r
+\r
+        public string BoardName\r
+        {\r
+            set { SetValue(BoardNameProperty, value); }\r
+            get { return (string)GetValue(BoardNameProperty); }\r
+        }\r
+        public string DateTimeDescription\r
+        {\r
+            set { SetValue(DateTimeDescriptionProperty, value); }\r
+            get { return (string)GetValue(DateTimeDescriptionProperty); }\r
+        }\r
+\r
+\r
+        public void update(NTBoard board)\r
+        {\r
+            if (board == null || !board.mDataInit)\r
+                return;\r
+\r
+            foreach (NTThreadTitle tt in board.mThreadTitleList)\r
+            {\r
+                if (tt.mDat.Equals(this.mDatName))\r
+                {\r
+                    this.Title = tt.Title;\r
+                    return;\r
+                }\r
+            }\r
+        }\r
+\r
+  \r
+        public NTHistoryThread(string boardName, string datName, string dateTimeDescription)\r
+        {\r
+            mDatName = datName;\r
+            BoardName = boardName;\r
+            Title = UNKNOWN_THREADTITLE_DESCRIPTION + " (" + boardName + ")";\r
+            DateTimeDescription = dateTimeDescription;\r
+        }\r
+    }\r
+}\r
diff --git a/NT2chView45/NTMaru.cs b/NT2chView45/NTMaru.cs
new file mode 100755 (executable)
index 0000000..cb8e89f
--- /dev/null
@@ -0,0 +1,98 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Threading;\r
+using NT2chView.NtNet;\r
+\r
+namespace NT2chView\r
+{\r
+    static class NTMaru\r
+    {\r
+        const string SESSION_ID_KEY = "SESSION-ID=";\r
+        static string mSessionId;\r
+        static object mLockThis;\r
+\r
+        public static void init()\r
+        {\r
+            mSessionId = string.Empty;\r
+            mLockThis = new object();\r
+\r
+        }\r
+\r
+        public static string getSessionId()\r
+        {\r
+            string id = string.Empty;\r
+            lock (mLockThis)\r
+            {\r
+                if (mSessionId.Length == 0)\r
+                    login();\r
+                id = mSessionId;\r
+            }\r
+            return id;\r
+        }\r
+\r
+        public static bool login()\r
+        {\r
+            if (!NTUserPreference.MaruIsEnabled)\r
+                return false;\r
+\r
+            string uid = NTUserPreference.MaruID;\r
+            string passwd = NTUserPreference.MaruPSS;\r
+            if (uid == null || passwd == null)\r
+                return false;\r
+            if (uid.Length == 0 || passwd.Length == 0)\r
+                return false;\r
+            lock (mLockThis)\r
+            {\r
+\r
+                string result = NTHttpAccess.loginMaru(uid, passwd);\r
+\r
+                if (result == null || result.Length == 0)\r
+                    return false;\r
+\r
+                int idx = result.IndexOf(SESSION_ID_KEY);\r
+                if (idx < 0)\r
+                    return false;\r
+                idx += SESSION_ID_KEY.Length;\r
+                int idx2 = result.IndexOf(':', idx);\r
+                if (idx2 < 0)\r
+                    return false;\r
+\r
+                string agent = result.Substring(idx, idx2-idx).Trim();\r
+                //string sessionKey = result.Substring(idx2 + 1).Trim();\r
+                string sessionKey = result.Substring(idx).Trim();\r
+                if (agent.Length == 0 || sessionKey.Length == 0)\r
+                    return false;\r
+\r
+                if (0 <= agent.IndexOf("ERROR", StringComparison.CurrentCultureIgnoreCase))\r
+                {\r
+                    return false;\r
+                }\r
+                if (!NTHttpAccess.HTTP_HEADER_USER_AGENT.Equals(agent))\r
+                {\r
+                    NTDebug.l("UserAgent Unmatched.");\r
+                }\r
+\r
+\r
+                mSessionId = NTTextUtiles.percentEncode(sessionKey);\r
+                //mSessionId = sessionKey;\r
+            }\r
+\r
+\r
+            return (mSessionId.Length > 0) ? true : false;\r
+        }\r
+\r
+        public static void loginAsync()\r
+        {\r
+            Thread t = new Thread(loginAsync_DoWord);\r
+            t.Start();\r
+        }\r
+\r
+        static void loginAsync_DoWord()\r
+        {\r
+            login();\r
+        }\r
+\r
+\r
+    }\r
+}\r
diff --git a/NT2chView45/NTMenuCommand.cs b/NT2chView45/NTMenuCommand.cs
new file mode 100755 (executable)
index 0000000..fd7988d
--- /dev/null
@@ -0,0 +1,13 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+\r
+namespace NT2chView\r
+{\r
+    class NTMenuCommand\r
+    {\r
+        public string DisplayText { get; set; }\r
+        public string FileName { get; set; }\r
+        public string Arguments { get; set; }\r
+    }\r
+}\r
diff --git a/NT2chView45/NTMovieHistory.cs b/NT2chView45/NTMovieHistory.cs
new file mode 100755 (executable)
index 0000000..a7b7a26
--- /dev/null
@@ -0,0 +1,172 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Collections.ObjectModel;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading.Tasks;\r
+using NT2chView.NtFile;\r
+\r
+namespace NT2chView\r
+{\r
+    class NTMovieHistory\r
+    {\r
+        private static bool mDirty = false;\r
\r
+        private static ObservableCollection<NTMovie> \r
+            mList = new ObservableCollection<NTMovie>();\r
+        public static ObservableCollection<NTMovie> GetList()\r
+        {\r
+            return mList;\r
+        }\r
+\r
+        public static NTMovie GetMovie(string id)\r
+        {\r
+            foreach (NTMovie movie in mList)\r
+            {\r
+                if (id.Equals(movie.ID))\r
+                    return movie;\r
+            }\r
+            return null;\r
+        }\r
+\r
+        public static void AddMovie(NTMovie movie)\r
+        {\r
+            if (movie == null)\r
+                return;\r
+            NTMovie exist = GetMovie(movie.ID);\r
+            if (exist != null)\r
+                mList.Remove(exist);\r
+\r
+            mList.Insert(0, movie);\r
+            mDirty = true;\r
+        }\r
+\r
+        public static void RemoveMovie(NTMovie movie)\r
+        {\r
+            if (movie == null)\r
+                return;\r
+            NTMovie exist = GetMovie(movie.ID);\r
+            if (exist != null)\r
+                mList.Remove(exist);\r
+        }\r
+\r
+        public static void Load()\r
+        {\r
+            mList.Clear();\r
+\r
+            mDirty = false;\r
+            string [] lines = NTFileAccess.retrieveMovieHistory();\r
+            if (lines == null)\r
+                return;\r
+            foreach (string line in lines)\r
+            {\r
+                NTMovie movie = NTMovie.CreateFromDescription(line);\r
+                if (movie == null)\r
+                    continue;\r
+                mList.Add(movie);\r
+            }\r
+\r
+\r
+        }\r
+        public static void Save()\r
+        {\r
+            mDirty = true;\r
+            List<string> list = new List<string>();\r
+            foreach (NTMovie movie in mList)\r
+            {\r
+                string line = movie.GetDescription();\r
+                if (line == null)\r
+                    continue;\r
+                list.Add(line);\r
+            }\r
+            NTFileAccess.storeMovieHistory(list.ToArray());\r
+\r
+        }\r
+\r
+    }\r
+    class NTMovie\r
+    {\r
+        private static bool mDirty = false;\r
+        private string mId;\r
+        private string mCaption;\r
+        private DateTime mDateTime;\r
+\r
+        public static bool GetDirty()\r
+        {\r
+            return mDirty;\r
+        }\r
+        public static void ClearDirty()\r
+        {\r
+            mDirty = false;\r
+        }\r
+\r
+        public string ID\r
+        {\r
+            get { return mId; }\r
+            set\r
+            {\r
+                mDirty = true;\r
+                mId = value;\r
+            }\r
+        }\r
+        public string Caption\r
+        {\r
+            get { return mCaption; }\r
+            set\r
+            {\r
+                mDirty = true;\r
+                mCaption = value;\r
+            }\r
+        }\r
+        public DateTime LastAccessDate\r
+        {\r
+            get { return mDateTime; }\r
+            set\r
+            {\r
+                mDirty = true;\r
+                mDateTime = value;\r
+            }\r
+        }\r
+\r
+        public NTMovie(string id)\r
+        {\r
+            ID = id;\r
+        }\r
+\r
+        public string GetDescription()\r
+        {\r
+            string caption = mCaption.Replace(",", "&#44;");\r
+            StringBuilder sb = new StringBuilder();\r
+            sb.Append(mId).Append(',')\r
+                .Append(caption).Append(',')\r
+                .Append(mDateTime.ToString());\r
+            return sb.ToString();\r
+        }\r
+\r
+        public static NTMovie CreateFromDescription(string description)\r
+        {\r
+            if (description == null)\r
+                return null;\r
+\r
+            string [] values = description.Split(NTTextUtiles.COMMA_VALUE);\r
+            if (values == null || values.Length != 3)\r
+                return null;\r
+\r
+            string id = values[0];\r
+            if (id.Length != 11)\r
+                return null;\r
+\r
+            DateTime dt;\r
+            if (!DateTime.TryParse(values[2], out dt))\r
+                return null;\r
+            string caption = values[1].Replace("&#44;", ",");\r
+\r
+            NTMovie movie = new NTMovie(id);\r
+            movie.mCaption = values[1];\r
+            movie.mDateTime = dt;\r
+            return movie;\r
+        }\r
+\r
+\r
+    }\r
+}\r
diff --git a/NT2chView45/NTMovieHistoryPopup.cs b/NT2chView45/NTMovieHistoryPopup.cs
new file mode 100755 (executable)
index 0000000..8380d53
--- /dev/null
@@ -0,0 +1,99 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading.Tasks;\r
+using System.Windows.Controls;\r
+using System.Windows.Controls.Primitives;\r
+using System.Windows.Documents;\r
+using System.Windows.Media;\r
+\r
+namespace NT2chView\r
+{\r
+    class NTMovieHistoryPopup : Popup\r
+    {\r
+        NTMovie mMovie;\r
+\r
+        public NTMovieHistoryPopup(NTMovie movie)\r
+        {\r
+            mMovie = movie;\r
+\r
+            StackPanel sp = new StackPanel();\r
+            sp.Orientation = Orientation.Horizontal;\r
+\r
+\r
+            StackPanel panel = new StackPanel();\r
+            Border border = new Border();\r
+            border.BorderThickness = new System.Windows.Thickness(1);\r
+            border.BorderBrush = new SolidColorBrush(Colors.DarkGray);\r
+\r
+\r
+            ListBoxItem item1 = new ListBoxItem();\r
+\r
+            string title = movie.ID + ": " + movie.Caption;\r
+            sp = new StackPanel();\r
+            sp.Children.Add(new TextBlock(new Run(title)));\r
+            item1.Content = sp;\r
+            item1.Padding = new System.Windows.Thickness(10, 2, 10, 2);\r
+            panel.Children.Add(item1);\r
+\r
+            sp = new StackPanel();\r
+            sp.Children.Add(new Separator());\r
+            item1 = new ListBoxItem();\r
+            item1.BorderBrush = new SolidColorBrush(Colors.LightGray);\r
+            item1.BorderThickness = new System.Windows.Thickness(1);\r
+            item1.Height = 1;\r
+            item1.Content = sp;\r
+            panel.Children.Add(item1);\r
+            panel.Background = new SolidColorBrush(Colors.White);\r
+\r
+\r
+\r
+            sp = new StackPanel();\r
+            sp.Children.Add(new TextBlock(new Run("リストから削除")));\r
+            sp.MouseLeftButtonDown += movieItemDelete_MouseLeftButtonDown;\r
+            sp.Tag = movie;\r
+            item1 = new ListBoxItem();\r
+            item1.Padding = new System.Windows.Thickness(10, 2, 10, 2);\r
+            item1.Content = sp;\r
+            panel.Children.Add(item1);\r
+\r
+            sp = new StackPanel();\r
+            sp.Children.Add(new TextBlock(new Run("閉じる")));\r
+            sp.MouseLeftButtonDown += movieItemClose_MouseLeftButtonDown;\r
+            item1 = new ListBoxItem();\r
+            item1.Padding = new System.Windows.Thickness(10, 2, 10, 2);\r
+            item1.Content = sp;\r
+            panel.Children.Add(item1);\r
+            border.Child = panel;\r
+            this.Child = border;\r
+        }\r
+\r
+        public void show()\r
+        {\r
+            IsOpen = true;\r
+            Placement = PlacementMode.Mouse;\r
+            Focus();\r
+            this.StaysOpen = false;\r
+\r
+        }\r
+\r
+\r
+        void movieItemDelete_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)\r
+        {\r
+            IsOpen = false;\r
+\r
+            NTMovieHistory.RemoveMovie(mMovie);\r
+            NTMovieHistory.Save();\r
+\r
+        }\r
+\r
+        void movieItemClose_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)\r
+        {\r
+            IsOpen = false;\r
+\r
+        }\r
+    }\r
+\r
+\r
+}\r
diff --git a/NT2chView45/NTMoviePanel.xaml b/NT2chView45/NTMoviePanel.xaml
new file mode 100755 (executable)
index 0000000..20b4ca4
--- /dev/null
@@ -0,0 +1,74 @@
+<UserControl x:Class="NT2chView.NTMoviePanel"\r
+             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"\r
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"\r
+             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" \r
+             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" \r
+             mc:Ignorable="d" \r
+             xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"\r
+             d:DesignHeight="600" d:DesignWidth="400">\r
+    <Grid>\r
+        <Grid.RowDefinitions>\r
+            <RowDefinition Height="Auto" />\r
+            <RowDefinition Height="Auto" />\r
+            <RowDefinition Height="Auto" />\r
+            <RowDefinition Height="*" />\r
+        </Grid.RowDefinitions>\r
+        <Grid.ColumnDefinitions>\r
+            <ColumnDefinition Width="Auto"/>\r
+            <ColumnDefinition Width="Auto"/>\r
+            <ColumnDefinition Width="*"/>\r
+        </Grid.ColumnDefinitions>\r
+        <WindowsFormsHost\r
+               Grid.ColumnSpan="3" \r
+               VerticalAlignment="Top" Height="350">\r
+            <wf:WebBrowser x:Name="mWebBrowser" \r
+                           ScriptErrorsSuppressed="True"\r
+                            />\r
+        </WindowsFormsHost>\r
+        <!--WebBrowser x:Name="<WindowsFormsHost />mWebBrowser" \r
+                    \r
+                    Grid.ColumnSpan="3"\r
+                    VerticalAlignment="Top" Height="350"/-->\r
+        <Label Grid.Row="1" Grid.ColumnSpan="2" >キャプション:</Label>\r
+        <TextBox x:Name="mEdtCation" Grid.Row="1" Grid.Column="2"></TextBox>\r
+        <Button Grid.Row="2" Click="btnAddYoutubeIdOnHistory_Click">\r
+            追加↓\r
+        </Button>\r
+        <Label Grid.Row="2" Grid.Column="1" HorizontalAlignment="Right">ID:</Label>\r
+        <TextBox x:Name="mEdtId" Grid.Row="2" Grid.Column="2"\r
+                 IsEnabled="False"></TextBox>\r
+        <ListView x:Name="mLstMovies" Grid.ColumnSpan="3" Grid.Row="3">\r
+            <ListView.View>\r
+                <GridView>\r
+                    <GridViewColumn \r
+                        Header=" ID " Width="150" >\r
+                        <GridViewColumn.CellTemplate>\r
+                            <DataTemplate>\r
+                                <TextBlock Text="{Binding Path=ID}" Tag="{Binding}"\r
+                                           MouseLeftButtonDown="lstItem_MouseLeftButtonDown"\r
+                                           MouseRightButtonDown="lstItem_MouseRightButtonDown"\r
+                                            MouseRightButtonUp="lstItem_MouseRightButtonUp"/>\r
+                            </DataTemplate>\r
+                        </GridViewColumn.CellTemplate>\r
+                    </GridViewColumn>\r
+                    <GridViewColumn \r
+                        Header="   キャプション   "\r
+                        Width="250">\r
+                        <GridViewColumn.CellTemplate>\r
+                            <DataTemplate>\r
+                                <TextBlock\r
+                                    Text="{Binding Path=Caption}"\r
+                                        Tag="{Binding}"\r
+                                           MouseLeftButtonDown="lstItem_MouseLeftButtonDown"\r
+                                           MouseRightButtonDown="lstItem_MouseRightButtonDown"\r
+                                            MouseRightButtonUp="lstItem_MouseRightButtonUp"/>\r
+                            </DataTemplate>\r
+                        </GridViewColumn.CellTemplate>\r
+                    </GridViewColumn>\r
+                    <GridViewColumn Header="最新取得日"\r
+                                    DisplayMemberBinding="{Binding Path=LastAccessDate}"/>\r
+                </GridView>\r
+            </ListView.View>\r
+        </ListView>\r
+    </Grid>\r
+</UserControl>\r
diff --git a/NT2chView45/NTMoviePanel.xaml.cs b/NT2chView45/NTMoviePanel.xaml.cs
new file mode 100755 (executable)
index 0000000..4abfbf6
--- /dev/null
@@ -0,0 +1,185 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading.Tasks;\r
+using System.Windows;\r
+using System.Windows.Controls;\r
+using System.Windows.Data;\r
+using System.Windows.Documents;\r
+using System.Windows.Input;\r
+using System.Windows.Media;\r
+using System.Windows.Media.Imaging;\r
+using System.Windows.Navigation;\r
+using System.Windows.Shapes;\r
+\r
+namespace NT2chView\r
+{\r
+    /// <summary>\r
+    /// NTMoviePanel.xaml の相互作用ロジック\r
+    /// </summary>\r
+    public partial class NTMoviePanel : UserControl\r
+    {\r
+\r
+        public void NavigateYoutube(string id)\r
+        {\r
+\r
+            if (id == null || id.Length != 11)\r
+                return;\r
+\r
+            mEdtId.Text = id;\r
+            mEdtCation.Text = "Untitled";\r
+\r
+            showYoutube(id);\r
+        }\r
+\r
+        private void showYoutube(string id)\r
+        {\r
+            //Version v = mWebBrowser.Version;\r
+\r
+\r
+             //StringBuilder sb = new StringBuilder();\r
+             //sb.Append(\r
+#if false\r
+@"<!DOCTYPE html>\r
+<html>\r
+  <body>\r
+    <!-- 1. The <iframe> (and video player) will replace this <div> tag. -->\r
+    <div id=""player""></div>\r
+\r
+    <script>\r
+      // 2. This code loads the IFrame Player API code asynchronously.\r
+      var tag = document.createElement('script');\r
+\r
+      tag.src = ""https://www.youtube.com/iframe_api"";\r
+      var firstScriptTag = document.getElementsByTagName('script')[0];\r
+      firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);\r
+\r
+      // 3. This function creates an <iframe> (and YouTube player)\r
+      //    after the API code downloads.\r
+      var player;\r
+      function onYouTubeIframeAPIReady() {\r
+        player = new YT.Player('player', {\r
+          height: 315,\r
+          width: 420,\r
+          videoId: 'M7lc1UVf-dVE',\r
+          events: {\r
+            onReady: onPlayerReady,\r
+            onStateChange: onPlayerStateChange\r
+          }\r
+        });\r
+      }\r
+\r
+      // 4. The API will call this function when the video player is ready.\r
+      function onPlayerReady(event) {\r
+        event.target.playVideo();\r
+      }\r
+\r
+      // 5. The API calls this function when the player's state changes.\r
+      //    The function indicates that when playing a video (state=1),\r
+      //    the player should play for six seconds and then stop.\r
+      var done = false;\r
+      function onPlayerStateChange(event) {\r
+        if (event.data == YT.PlayerState.PLAYING && !done) {\r
+          setTimeout(stopVideo, 6000);\r
+          done = true;\r
+        }\r
+      }\r
+      function stopVideo() {\r
+        player.stopVideo();\r
+      }\r
+    </script>\r
+  </body>\r
+</html>");\r
+\r
+<iframe width="560" height="315" src="http://www.youtube.com/embed/28CHlz6DhJQ" frameborder="0" allowfullscreen></iframe>\r
+\r
+\r
+"<!DOCTYPE html><html><head><meta charset=\"UTF-8\">" +\r
+"<title>2ぃとちゃん on Web --- login --- </title>" +\r
+"</head><body><iframe height=315 width=420 src=\"http://www.youtube.com/embed/");\r
+             sb.Append(id);\r
+             sb.Append(/*fxvsUEmKPFo*/\r
+\r
+ "\"  frameborder=0 allowfullscreen>" +\r
+ "</iframe></body></html>");\r
+#endif\r
+             //mWebBrowser.NavigateToString(sb.ToString());\r
+\r
+            //mWebBrowser.DocumentText = sb.ToString();\r
+\r
+            string url = "http://www.youtube.com/embed/" + id;\r
+            mWebBrowser.Navigate(url);\r
+\r
+        }\r
+\r
+        public NTMoviePanel()\r
+        {\r
+            InitializeComponent();\r
+        }\r
+\r
+        public void Init()\r
+        {\r
+            NTMovieHistory.Load();\r
+            mLstMovies.ItemsSource = NTMovieHistory.GetList();\r
+\r
+        }\r
+\r
+        private void btnAddYoutubeIdOnHistory_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            string id = mEdtId.Text;\r
+            string caption = mEdtCation.Text;\r
+            if (id == null || id.Length != 11 ||\r
+                caption == null || caption.Length == 0)\r
+                return;\r
+\r
+            NTMovie movie = new NTMovie(id);\r
+            movie.Caption = caption;\r
+            movie.LastAccessDate = DateTime.Now;\r
+            NTMovieHistory.AddMovie(movie);\r
+            NTMovieHistory.Save();\r
+\r
+        }\r
+\r
+        private void lstItem_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)\r
+        {\r
+            TextBlock tb = sender as TextBlock;\r
+            if (tb == null)\r
+                return;\r
+            NTMovie movie = tb.Tag as NTMovie;\r
+            if (movie == null)\r
+                return;\r
+\r
+            movie.LastAccessDate = DateTime.Now;\r
+\r
+            NTMovieHistory.AddMovie(movie);\r
+            NTMovieHistory.Save();\r
+\r
+            mEdtId.Text = movie.ID;\r
+            mEdtCation.Text = movie.Caption;\r
+            \r
+            showYoutube(movie.ID);\r
+\r
+\r
+\r
+        }\r
+        private void lstItem_MouseRightButtonDown(object sender, MouseButtonEventArgs e)\r
+        {\r
+\r
+            //e.Handled = true;\r
+        }\r
+        private void lstItem_MouseRightButtonUp(object sender, MouseButtonEventArgs e)\r
+        {\r
+            TextBlock tb = sender as TextBlock;\r
+            if (tb == null)\r
+                return;\r
+            NTMovie movie = tb.Tag as NTMovie;\r
+            if (movie == null)\r
+                return;\r
+\r
+            NTMovieHistoryPopup popup = new NTMovieHistoryPopup(movie);\r
+            popup.show();\r
+            e.Handled = true;\r
+        }\r
+    }\r
+}\r
diff --git a/NT2chView45/NTNgItems.cs b/NT2chView45/NTNgItems.cs
new file mode 100755 (executable)
index 0000000..f77f5bf
--- /dev/null
@@ -0,0 +1,125 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+\r
+namespace NT2chView\r
+{\r
+    sealed class NTNgItems\r
+    {\r
+        static NTNgItems mThis = null;\r
+        private List<string> mNgWords = new List<string>();\r
+        private List<string> mNgIds = new List<string>();\r
+        private List<string> mNgNames = new List<string>();\r
+\r
+        public static NTNgItems getContext()\r
+        {\r
+            if (mThis == null)\r
+                mThis = new NTNgItems();\r
+\r
+            return mThis;\r
+        }\r
+\r
+        public bool addNgName(string src)\r
+        {\r
+            src = src.Trim();\r
+            lock (mNgNames)\r
+            {\r
+                foreach (string s in mNgNames)\r
+                {\r
+                    if (s.Equals(src))\r
+                        return false;\r
+                }\r
+                mNgNames.Add(src);\r
+                return true;\r
+            }\r
+        }\r
+\r
+        public bool addNgId(string src)\r
+        {\r
+            src = src.Trim();\r
+            lock (mNgIds)\r
+            {\r
+                foreach (string s in mNgIds)\r
+                {\r
+                    if (s.Equals(src))\r
+                        return false;\r
+                }\r
+                mNgIds.Add(src);\r
+                return true;\r
+            }\r
+        }\r
+        public bool addNgWord(string src)\r
+        {\r
+            src = src.Trim();\r
+            lock (mNgWords)\r
+            {\r
+                foreach (string s in mNgWords)\r
+                {\r
+                    if (s.Equals(src))\r
+                        return false;\r
+                }\r
+                mNgWords.Add(src);\r
+                return true;\r
+            }\r
+        }\r
+\r
+        public List<String> getNgWords()\r
+        {\r
+            lock (mNgWords)\r
+            {\r
+                List<string> list = new List<string>();\r
+                list.AddRange(mNgWords);\r
+                return list;\r
+            }\r
+        }\r
+        public List<String> getNgIds()\r
+        {\r
+            lock (mNgIds)\r
+            {\r
+                List<string> list = new List<string>();\r
+                list.AddRange(mNgIds);\r
+                return list;\r
+            }\r
+        }\r
+\r
+        public List<String> getNgNames()\r
+        {\r
+            lock (mNgNames)\r
+            {\r
+                List<string> list = new List<string>();\r
+                list.AddRange(mNgNames);\r
+                return list;\r
+            }\r
+        }\r
+\r
+        public void WriteNgWord(string [] list)\r
+        {\r
+            lock (mNgWords)\r
+            {\r
+                mNgWords.Clear();\r
+                mNgWords.AddRange(list);\r
+             }\r
+        }\r
+\r
+        public void WriteNgId(string [] list)\r
+        {\r
+            lock (mNgIds)\r
+            {\r
+                mNgIds.Clear();\r
+                foreach (string s in list)\r
+                    mNgIds.Add(s);\r
+            }\r
+        }\r
+\r
+        public void WriteNgName(string [] list)\r
+        {\r
+            lock (mNgNames)\r
+            {\r
+                mNgNames.Clear();\r
+                foreach (string s in list)\r
+                    mNgNames.Add(s);\r
+            }\r
+        }\r
+\r
+    }\r
+}\r
diff --git a/NT2chView45/NTOpenedThreadTable.cs b/NT2chView45/NTOpenedThreadTable.cs
new file mode 100755 (executable)
index 0000000..bcb6c83
--- /dev/null
@@ -0,0 +1,221 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using NT2chCtrl;\r
+using NT2chView;\r
+using NT2chView.NtFile;\r
+using NT2chView.NtNet;\r
+using NT2chObject;\r
+\r
+namespace NT2chHistory\r
+{\r
+    class NTOpenedThreadTable\r
+    {\r
+        public static List<IThreadDescription> retrieveThreadHistoryList()\r
+        {\r
+            string[] list = NTFileAccess.retrieveThreadHistoryList();\r
+            if (list == null)\r
+                return null;\r
+\r
+            List<IThreadDescription> threadList = new List<IThreadDescription>();\r
+            foreach (string s in list)\r
+            {\r
+                IThreadDescription threadDecl = NTThreadCashData.parse(s);\r
+                if(threadDecl != null)\r
+                    threadList.Add(threadDecl);\r
+            }\r
+            return threadList;\r
+        }\r
+\r
+        public static void saveThreadHistoryList(List<IThreadDescription> threadList)\r
+        {\r
+            List<string> list = new List<string>();\r
+            foreach (IThreadDescription threadDecl in threadList)\r
+            {\r
+                string s = NTThreadCashData.getDescription(threadDecl);\r
+                if (s != null)\r
+                    list.Add(s);\r
+            }\r
+            if (NTUserPreference.NTCloudIsEnabled)\r
+            {\r
+                if (NTUserPreference.NTUserCloudIsEnabled)\r
+                {\r
+                    string uid = NTUserPreference.NTCloudID;\r
+                    string hashed = NTUserPreference.NTUserCloudGetHashedPasswd();\r
+                    NTHttpAccess.UserCloudUploadThreadHistoryList(uid, hashed, list);\r
+                }\r
+                else\r
+                {\r
+                    string uid = NTUserPreference.NTCloudID;\r
+                    string passwd = NTUserPreference.NTCloudPSS;\r
+                    NTHttpAccess.ntUploadThreadHistoryList(uid, passwd, list);\r
+                }\r
+            }\r
+\r
+            NTFileAccess.writeThreadHistoryList(list.ToArray());\r
+        }\r
+#if false\r
+           const int MAX_SAVE_LINE_COUNT = 50;\r
+       \r
+           static bool mDirty = false;\r
+           static bool mDirty2 = false;\r
+\r
+           static List<NTThreadCashData> mList = new List<NTThreadCashData>();\r
+       \r
+           public static bool getDirty(){return mDirty2;}\r
+           public static void ClearDirty(){mDirty2 = false;}\r
+       \r
+       \r
+           public static void add(NTThreadCashData data){\r
+                   remove(data.getBoardName(), data.getDatName());\r
+                   mList.Insert(0, data);\r
+                   mDirty = true;\r
+                   mDirty2 = true;\r
+           }\r
+           public static int ListCount(){\r
+                   return mList.Count;\r
+           }\r
+           public static bool remove(String boardName, String datName){\r
+                   NTThreadCashData data = getData( boardName, datName);\r
+                   if(data == null)\r
+                           return false;\r
+                   mDirty = true;\r
+                   mDirty2 = true;\r
+                   return mList.Remove(data);\r
+               \r
+           }\r
+       \r
+           public static bool remove(NTThreadCashData data){\r
+                   mDirty = true;\r
+                   mDirty2 = true;\r
+                   return mList.Remove(data);\r
+           }\r
+       \r
+           public static void removeAll(){\r
+                   mDirty = true;\r
+                   mDirty2 = true;\r
+                   mList.Clear();\r
+           }\r
+\r
+           public static NTThreadCashData getData(int index){\r
+                   if(index < 0 || index >= mList.Count)\r
+                           return null;\r
+                   return mList[index];\r
+           }\r
+\r
+           private static NTThreadCashData getData(String boardName, String datName){\r
+                   foreach(NTThreadCashData data in mList){\r
+                           if(data.getBoardName().Equals(boardName) &&\r
+                                           data.getDatName().Equals(datName))\r
+                                   return data;\r
+                   }\r
+                   return null;\r
+           }\r
+\r
+           public static void OnNotifyBoardUpdate(Context ctx, BoardTable btbl){\r
+                   foreach(NTThreadCashData data in mList){\r
+                           if(data.isTitleSet())\r
+                                   continue;\r
+                           NTThreadTitleTable ttt = btbl.getThreadTitleTableByName(data.mBoardName);\r
+                           if(ttt == null){\r
+                                   continue;\r
+                           }\r
+                       \r
+                           if(ttt.getCount() == 0){\r
+                                   String category = CategoryTable.findCategoryByBoardName(data.mBoardName);\r
+                                   if(category == null)\r
+                                           continue;\r
+                               \r
+                                   if(!FileUtil.readThreadTable(ctx, category, data.mBoardName))\r
+                                           continue;\r
+                               \r
+                                   ttt = btbl.getThreadTitleTableByName(data.mBoardName);\r
+                                   if(ttt == null)\r
+                                           continue;\r
+                               \r
+                           }\r
+                       \r
+                           int idx = ttt.getIndexByFileName(data.mDatName);\r
+                           if(idx < 0)\r
+                                   continue;\r
+                           data.setTitle(ttt.getTitleText(idx));\r
+                   }\r
+               \r
+                   /*DebugUtil.log2("*** ThreadCashData logging... ***");\r
+                   for(ThreadCashData data : mList){\r
+                           DebugUtil.log2("------------------------------");\r
+                           DebugUtil.log2("Board: "+data.mBoardName);\r
+                           DebugUtil.log2("Title: "+data.mTitle);\r
+                           DebugUtil.log2("Dat: "+data.mDatName);\r
+                   }\r
+                   DebugUtil.log2("*** Done... ***");*/\r
+           }\r
+       \r
+           public static boolean store(Context ctx){\r
+                   if(!mDirty)\r
+                           return true;\r
+                   mDirty = false;\r
+                   int numLine = mList.size();\r
+                   if(numLine > MAX_SAVE_LINE_COUNT)\r
+                           numLine = MAX_SAVE_LINE_COUNT;\r
+                   ArrayList<String> lines = new ArrayList<String>(numLine);\r
+                   for(int i = 0; i < numLine; i++){\r
+                           String line = mList.get(i).getDescription();\r
+                           lines.add(HttpUtil.encodeBase64URL(line));\r
+                   }\r
+                   return FileUtil.storeReadHistoryToFile(ctx, lines);\r
+           }\r
+       \r
+           public static ArrayList<String> getCurrentList(){\r
+                   int numLine = mList.size();\r
+                   if(numLine > MAX_SAVE_LINE_COUNT)\r
+                           numLine = MAX_SAVE_LINE_COUNT;\r
+                   ArrayList<String> lines = new ArrayList<String>(numLine);\r
+                   for(int i = 0; i < numLine; i++){\r
+                           String line = mList.get(i).getDescription();\r
+                           lines.add(line);\r
+                   }\r
+                   return lines;\r
+           }\r
+           public static void retrieve(){\r
+\r
+            string [] list = NTFileAccess.retrieveThreadHistoryList();\r
+\r
+            foreach(string s in list)\r
+            {\r
+                IThreadDescription threadDecl = NTThreadCashData.parse(s);\r
+\r
+            }\r
+\r
+\r
+                   try {\r
+                           ArrayList<String> lines = FileUtil.retrieveReadhistoryFromFile(ctx);\r
+                           mList.clear();\r
+                           int lineCnt = lines.size();\r
+                           if(lineCnt > MAX_SAVE_LINE_COUNT)\r
+                                   lineCnt = MAX_SAVE_LINE_COUNT;\r
+                           HashSet<String> boardSet = new HashSet<String>(lineCnt);\r
+                       \r
+                           for(int i = 0; i < lineCnt; i++){\r
+                                   String line = lines.get(i);\r
+                                   String decoded = HttpUtil.decodeBase64URL(line);\r
+                                   ThreadCashData data = \r
+                                                   ThreadCashData.parse(decoded);\r
+                                   if(data != null){\r
+                                           mList.add(data);\r
+                                           boardSet.add(data.mBoardName);\r
+                                   }\r
+                           }\r
+                           for(String boardName : boardSet){\r
+                                   BoardTable bTbl = CategoryTable.getBoardByBoardNameAAA(boardName);\r
+                                   if(bTbl == null)\r
+                                           continue;                           \r
+                                   OnNotifyBoardUpdate(ctx, bTbl);\r
+                           }\r
+                   } catch (UnsupportedEncodingException e) {\r
+                           e.printStackTrace();\r
+                   }\r
+           }\r
+#endif\r
+    }\r
+}\r
diff --git a/NT2chView45/NTRes.cs b/NT2chView45/NTRes.cs
new file mode 100755 (executable)
index 0000000..727f091
--- /dev/null
@@ -0,0 +1,257 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Windows.Controls;\r
+using System.Windows.Documents;\r
+using System.Windows.Media.Imaging;\r
+using NT2chView.NtHtml;\r
+using System.Runtime.Remoting.Contexts;\r
+using NT2chCtrl;\r
+using NT2chObject;\r
+\r
+\r
+namespace NT2chView\r
+{\r
+    //[Synchronization]\r
+    public sealed class NTRes : IRes\r
+    {\r
+        const string ID_TEXT = "ID:";\r
+        public int getSequenceNo() { return mSeqNo; }\r
+        public string getName() { return mName; }\r
+        public string getMail() { return mMail; }\r
+        public string getMsg() { return mMsg; }\r
+        public string getMisc()\r
+        {\r
+            string buf;\r
+            buf = (mDate != null) ? mDate : string.Empty;\r
+            buf += (mId != null) ? (ID_TEXT + mId) : string.Empty;\r
+            return buf;\r
+        }\r
+        public string getDate()\r
+        {\r
+            return mDate;\r
+        }\r
+        public string getID()\r
+        {\r
+            return mId;\r
+        }\r
+        public bool getAttribute(RES_ATTRIBUTE attr)\r
+        {\r
+            switch (attr)\r
+            {\r
+                case RES_ATTRIBUTE.MYMESSAGE:\r
+                    return mWroteMsg;\r
+                case RES_ATTRIBUTE.REPRY:\r
+                    return mIsRepray;\r
+                case RES_ATTRIBUTE.BOOKMARK:\r
+                    return mBookmark;\r
+                default:\r
+                    return false;\r
+            }\r
+        }\r
+\r
+        public int[] getReferenceArray() { return mRefferFrom.ToArray(); }\r
+        private object mObjExtra;\r
+        public object getExtra() { return mObjExtra; }\r
+        public void setExtra(object o) { mObjExtra = o; }\r
+\r
+\r
+        public string mName;\r
+        public string mMail;\r
+        public string mDate;\r
+        public string mId;\r
+        public string mMsg;\r
+        public int mSeqNo;\r
+        public bool mBookmark ;\r
+        public bool mWroteMsg;\r
+        public bool mIsRepray;\r
+        public bool mIsDummy;\r
+\r
+        public NTThreadTitle mThread;\r
+        public List<int> mSameIdList = null;\r
+\r
+        public int[] mRefferTo = null;\r
+        public List<int> mRefferFrom = new List<int>();\r
+\r
+        public Section mSection = null;\r
+\r
+        public NTRes(NTThreadTitle thread,  int seqNo, string name, string mail, string date_id, string msg)\r
+        {\r
+            mThread = thread;\r
+            mSeqNo = seqNo;\r
+            mName = name;\r
+            mMail = mail;\r
+            mMsg = parseMsg(msg);\r
+            mBookmark = false;\r
+            mWroteMsg = false;\r
+            mIsRepray = false;\r
+            mIsDummy = false;\r
+\r
+            \r
+\r
+            int n = date_id.LastIndexOf(ID_TEXT);\r
+            if (n > 0)\r
+            {\r
+                mId = date_id.Substring(n + ID_TEXT.Length);\r
+                mDate = date_id.Substring(0, n).Trim();\r
+                NTRes sameId = thread.findResById(mId);\r
+                if (sameId != null)\r
+                {\r
+                    List<int> list = sameId.mSameIdList;\r
+                    if (list == null)\r
+                    {\r
+                        list = new List<int>();\r
+                        list.Add(sameId.mSeqNo);\r
+                        sameId.mSameIdList = list;\r
+                    }\r
+                    list.Add(this.mSeqNo);\r
+                    this.mSameIdList = list;\r
+                }\r
+            }\r
+            else\r
+            {\r
+                mId = string.Empty;\r
+                mDate = date_id;\r
+            }\r
+        }\r
+#if false\r
+        public void removeBookmark()\r
+        {\r
+            mBookmark = false;\r
+            if (mSection == null)\r
+                return;\r
+\r
+            if (2 > mSection.Blocks.Count)\r
+                return;\r
+\r
+            Paragraph paraBody = mSection.Blocks.LastBlock as Paragraph;\r
+\r
+            if (paraBody == null)\r
+                return;\r
+\r
+            Inline il = paraBody.Inlines.FirstInline;\r
+            if (il == null)\r
+                return;\r
+            Span span = il as Span;\r
+            if (span == null)\r
+                return;\r
+            Hyperlink hl = span as Hyperlink;\r
+            if (hl != null)\r
+                return;\r
+            paraBody.Inlines.Remove(span);\r
+\r
+            mThread.removeBookmark(mSeqNo);\r
+        }\r
+\r
+        public void addBookmark()\r
+        {\r
+            mBookmark = true;\r
+            if (mSection == null)\r
+                return;\r
+\r
+            if (2 > mSection.Blocks.Count)\r
+                return;\r
+\r
+            Paragraph paraBody = mSection.Blocks.LastBlock as Paragraph;\r
+\r
+            if (paraBody == null)\r
+                return;\r
+\r
+            Inline il = paraBody.Inlines.FirstInline;\r
+            if(il == null )\r
+                return;\r
+\r
+            Span span = il as Span;\r
+            if (span != null)\r
+            {\r
+                Hyperlink hl = span as Hyperlink;\r
+                if(hl == null)\r
+                    return;\r
+            }\r
+\r
+            // Create the image element.\r
+            Image img = new Image();\r
+            img.Width = 12;\r
+            img.Height = 20;\r
+            //Uri oUri = new Uri("pack://application:,,,/NT2chView;component/images/tag.png", UriKind.RelativeOrAbsolute);\r
+            Uri oUri = new Uri("pack://application:,,,/NT2chStyle;component/images/tag.png", UriKind.RelativeOrAbsolute);\r
+            BitmapImage bi = new BitmapImage();\r
+            bi.BeginInit();\r
+            bi.UriSource = oUri;\r
+\r
+            bi.EndInit();\r
+            // Set the image source.\r
+            img.Source = bi;\r
+            //Span span2 = new Span();\r
+            //span2.Inlines.Add(img);\r
+            img.VerticalAlignment = System.Windows.VerticalAlignment.Center;\r
+            //img.Margin = new Thickness(3,2,3,0);\r
+            span = new Span();\r
+            span.Inlines.Add(img);\r
+            paraBody.Inlines.InsertBefore(il, span);\r
+\r
+            mThread.addBookmark(mSeqNo);\r
+\r
+        }\r
+#endif\r
+        string parseMsg(string source)\r
+        {\r
+#if false\r
+            int i = 0;\r
+            int start = 0;\r
+            StringBuilder\r
+                sb = new StringBuilder(source.Length);\r
+            for (; i < source.Length; i++)\r
+            {\r
+                switch (source[i])\r
+                {\r
+                    case '&':\r
+                        int retLen;\r
+                        if ((i + 1 < source.Length) && source[i + 1] == '#')\r
+                        {\r
+                            char c = NTHtmlUtils.parseHTMLDecimalHexEscape(source, i + 2, out retLen);\r
+                            if (c != '\0')\r
+                            {\r
+                                if (start < i)\r
+                                    sb.Append(source.Substring(start, i - start));\r
+                                sb.Append(c);\r
+                                start = retLen;\r
+                                i = retLen - 1;\r
+\r
+                            }\r
+                        }\r
+                        else\r
+                        {\r
+                            char c = NTHtmlUtils.HTMLEscapeTable.getCodeFromEscape(source, i + 1, out retLen);\r
+                            if (c != '\0')\r
+                            {\r
+                                if (start < i)\r
+                                    sb.Append(source.Substring(start, i - start));\r
+                                sb.Append(c);\r
+                                start = retLen;\r
+                                i = retLen - 1;\r
+\r
+                            }\r
+                        }\r
+                        break;\r
+                }\r
+            }\r
+            if (start < source.Length)\r
+            {\r
+                sb.Append(source.Substring(start, source.Length - start));\r
+            }\r
+\r
+            source = sb.ToString();\r
+#endif\r
+            source = NTHtmlUtils.parseHTMLEscape(source);\r
+\r
+            List<int> arr = NTTextFormat.parseReferenceNumber(source);\r
+            if (null != arr)\r
+                mRefferTo = arr.ToArray();\r
+            else\r
+                mRefferTo = null;\r
+\r
+            return source;\r
+        }\r
+    }\r
+}\r
diff --git a/NT2chView45/NTResMenuCommand.cs b/NT2chView45/NTResMenuCommand.cs
new file mode 100755 (executable)
index 0000000..5f2bc6a
--- /dev/null
@@ -0,0 +1,198 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Diagnostics;\r
+using System.Text;\r
+using System.Text.RegularExpressions;\r
+using System.Web;\r
+using System.Windows;\r
+using System.Windows.Controls;\r
+using System.Windows.Documents;\r
+using System.Windows.Input;\r
+using NT2chView.NtFile;\r
+\r
+namespace NT2chView\r
+{\r
+    class NTResMenuCommand\r
+    {\r
+        FlowDocumentScrollViewer mViewer;\r
+\r
+        private static List<NTMenuCommand> mMenuCommands = new List<NTMenuCommand>();\r
+\r
+        const string REGEX_PATERN = @"\{[1-9]+\}|\{[0-9]+.+\}";\r
+        const string FORMAT_SPECIFIERS = "{0}";\r
+\r
+        private static bool probeCommand(string arguments)\r
+        {\r
+            if(arguments.Length == 0)\r
+                return false;\r
+\r
+            if (Regex.IsMatch(arguments, REGEX_PATERN))\r
+                return false;\r
+\r
+            /*int idx1 = arguments.IndexOf(FORMAT_SPECIFIERS);\r
+            if (idx1 >= 0)\r
+            {\r
+                int idx2 = arguments.IndexOf(FORMAT_SPECIFIERS);\r
+                if (idx2 >= 0)\r
+                    return false;\r
+            }*/\r
+            return true;\r
+        }\r
+\r
+        public static List<NTMenuCommand> getMenuCommands()\r
+        {\r
+            return mMenuCommands;\r
+        }\r
+\r
+        public static void init()\r
+        {\r
+\r
+            mMenuCommands.Clear();\r
+\r
+            string [] cmdList = NTPersistentFileAccess.retrieveResMenuCmd();\r
+            foreach (string cmd in cmdList)\r
+            {\r
+               \r
+                string s = cmd.Trim();\r
+                //skip a comment line\r
+                if (s[0] == '#')\r
+                    continue;\r
+\r
+                int len = s.Length;\r
+\r
+                int idx1 = s.IndexOf(',');\r
+                if (idx1 <= 0 || idx1 == (len+1))\r
+                    continue;\r
+\r
+                NTMenuCommand menuCmd = new NTMenuCommand();\r
+\r
+                int idx2 = s.IndexOf(',', idx1 + 1);\r
+\r
+                if (idx2 > idx1+1)\r
+                {\r
+                    menuCmd.Arguments = s.Substring(idx2 + 1).Trim();\r
+                    if (!probeCommand(menuCmd.Arguments))\r
+                        continue;\r
+                    menuCmd.FileName = s.Substring(idx1 + 1, idx2 - (idx1 + 1)).Trim();\r
+                }\r
+                else\r
+                {\r
+                    menuCmd.Arguments = string.Empty;\r
+                    menuCmd.FileName = s.Substring(idx1 + 1).Trim();\r
+                }\r
+                menuCmd.DisplayText = s.Substring(0, idx1).Trim();\r
+\r
+                mMenuCommands.Add(menuCmd);\r
+            }\r
+\r
+        }\r
+\r
+        List<NTMenuCommand> mCmdList;\r
+\r
+        NTResMenuCommand(FlowDocumentScrollViewer viewer, List<NTMenuCommand> mcList)\r
+        {\r
+            mViewer = viewer;\r
+            mCmdList = mcList;\r
+        }\r
+\r
+        public static void createContextMenu(FlowDocumentScrollViewer viewer)\r
+        {\r
+            if (viewer == null)\r
+                return ;\r
+\r
+            ContextMenu cm = new ContextMenu();\r
+            if (cm == null)\r
+                return ;\r
+\r
+\r
+\r
+            MenuItem mi = new MenuItem();\r
+            mi.Command = ApplicationCommands.Copy;\r
+            cm.Items.Add(mi);\r
+            mi = new MenuItem();\r
+            mi.Command = ApplicationCommands.Print;\r
+            cm.Items.Add(mi);\r
+            mi = new MenuItem();\r
+            mi.Command = ApplicationCommands.Find;\r
+            cm.Items.Add(mi);\r
+\r
+            List<NTMenuCommand> mcList = NTResMenuCommand.getMenuCommands();\r
+            NTResMenuCommand resCmd = new NTResMenuCommand(viewer, mcList);\r
+            if (resCmd == null)\r
+                return ;\r
+            foreach (NTMenuCommand mc in mcList)\r
+            {\r
+                mi = new MenuItem();\r
+                mi.Tag = resCmd;\r
+                mi.Header = mc.DisplayText;\r
+                mi.Click += MenuItem_Click;\r
+                cm.Items.Add(mi);\r
+            }\r
+\r
+            viewer.ContextMenu = cm;\r
+\r
+        }\r
+\r
\r
+        static void MenuItem_Click(object sender, System.Windows.RoutedEventArgs e)\r
+        {\r
+            MenuItem mi = sender as MenuItem;\r
+            if (mi == null)\r
+                return;\r
+\r
+            string header = mi.Header as string;\r
+            if (header == null)\r
+                return;\r
+\r
+            NTResMenuCommand resCmd = mi.Tag as NTResMenuCommand;\r
+            if (resCmd == null)\r
+                return;\r
+\r
+            List<NTMenuCommand> mcList = resCmd.mCmdList;\r
+            NTMenuCommand mc = null;\r
+            foreach (NTMenuCommand mc2 in mcList)\r
+            {\r
+                if (header.Equals(mc2.DisplayText))\r
+                {\r
+                    mc = mc2;\r
+                    break;\r
+                }\r
+            }\r
+            if (mc == null)\r
+                return;\r
+\r
+\r
+            string param = resCmd.getSelectedText();\r
+            if (param == null)// || param.Length == 0)\r
+                return;\r
+\r
+            string param2 =\r
+                string.Format(mc.Arguments, HttpUtility.UrlEncode(param));\r
+\r
+            try\r
+            {\r
+                Process ie = Process.Start(mc.FileName, param2);\r
+            }\r
+            catch (Exception ex)\r
+            {\r
+                MessageBox.Show(ex.Message);\r
+            }\r
+        }\r
+\r
+        private bool isSelected()\r
+        {\r
+            string s = mViewer.Selection.Text;\r
+            return (s != null && s.Length > 0) ;\r
+        }\r
+\r
+        private string getSelectedText()\r
+        {\r
+            return mViewer.Selection.Text;\r
+        }\r
+\r
+\r
+     \r
+\r
+\r
+    }\r
+}\r
diff --git a/NT2chView45/NTResPopupMenu.cs b/NT2chView45/NTResPopupMenu.cs
new file mode 100755 (executable)
index 0000000..36e4ff3
--- /dev/null
@@ -0,0 +1,242 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Windows.Controls;\r
+using System.Windows.Controls.Primitives;\r
+using System.Windows.Documents;\r
+using System.Windows.Media;\r
+using System.Windows.Media.Imaging;\r
+\r
+namespace NT2chView\r
+{\r
+    class NTResPopupMenu1 : Popup\r
+    {\r
+       // static NTResPopupMenu1 mPopupMenu = null;\r
+\r
+       /* public static void closePopupMenu()\r
+        {\r
+            if (mPopupMenu != null)\r
+            {\r
+                mPopupMenu.IsOpen = false;\r
+                mPopupMenu = null;\r
+            }\r
+        }*/\r
+\r
+        NTRes mRes;\r
+        MainWindow mMainWnd;\r
+        static NTResPopupMenu1 mMe = null;\r
+\r
+        public static void Hide()\r
+        {\r
+            if (mMe != null)\r
+            {\r
+                mMe.IsOpen = false;\r
+                mMe = null;\r
+            }\r
+        }\r
+\r
+        public NTResPopupMenu1(MainWindow main, NTRes res)\r
+            : base()\r
+        {\r
+            mRes = res;\r
+            mMainWnd = main;\r
+\r
+            //closePopupMenu();\r
+\r
+            //mPopupMenu = this;\r
+\r
+            //this.StaysOpen = false;\r
+            //this.MouseLeave += NTResPopupMenu1_MouseLeave;\r
+            //this.LostFocus += NTResPopupMenu1_LostFocus;\r
+            \r
+            //item1.Content = new Run("TEST");\r
+//            item1.Content = new TextBlock(new Run("TEST"));\r
+            //TextBlock tb = new TextBlock(new Run("TEST"));\r
+            //Button btn = new Button();\r
+            //Bitmap bmp = new Bitmap();\r
+\r
+            \r
+            //try\r
+           // {\r
+                //Image img = new Image();\r
+               // Image.\r
+                //img.FindResource("/NT2chView;component/images/tag.png");\r
+               // BitmapImage bimg = new BitmapImage(new Uri(@"/images/tag.png", UriKind.Relative));\r
+               // img.Source = bimg;\r
+               // ImageSource.\r
+               // sp.Children.Add(img);\r
+                \r
+           // }\r
+           // catch (Exception e)\r
+           // {\r
+           //     NTDebug.l(e.Message);\r
+           // }\r
+            //ListBox lBox = new ListBox();\r
+            StackPanel sp = new StackPanel();\r
+            sp.Orientation = Orientation.Horizontal;\r
+            StackPanel panel = new StackPanel();\r
+            Border border = new Border();\r
+            border.BorderThickness = new System.Windows.Thickness(1);\r
+            border.BorderBrush = new SolidColorBrush(Colors.DarkGray);\r
+            //border.\r
+            \r
+            if(!res.mBookmark)\r
+                sp.Children.Add(new TextBlock(new Run("ブックマークを追加")));\r
+            else\r
+                sp.Children.Add(new TextBlock(new Run("ブックマークを削除")));\r
+\r
+            sp.MouseLeftButtonDown += addBookmark_MouseLeftButtonDown;\r
+\r
+            ListBoxItem item1 = new ListBoxItem();\r
+            item1.Content = sp;\r
+            item1.Padding = new System.Windows.Thickness(10, 2, 10, 2);\r
+            item1.MouseEnter += item1_MouseEnter;\r
+            item1.MouseLeave += item1_MouseLeave;\r
+            item1.MouseLeftButtonDown += addBookmark_MouseLeftButtonDown;\r
+            item1.MouseLeftButtonUp += addBookmark_MouseLeftButtonUp;\r
+            panel.Background = new SolidColorBrush(Colors.White);\r
+            panel.Children.Add(item1);\r
+\r
+            sp = new StackPanel();\r
+            sp.MouseLeftButtonDown += reply_with_no_MouseLeftButtonDown;\r
+            sp.Children.Add(new TextBlock(new Run("このレスに返信")));\r
+            item1 = new ListBoxItem();\r
+            item1.Content = sp;\r
+            item1.Padding = new System.Windows.Thickness(10, 2, 10, 2);\r
+            item1.MouseEnter += item1_MouseEnter;\r
+            item1.MouseLeave += item1_MouseLeave;\r
+            //item1.MouseLeftButtonDown += item1_MouseLeftButtonDown;\r
+            //item1.MouseLeftButtonUp += item1_MouseLeftButtonUp;\r
+            panel.Children.Add(item1);\r
+            sp = new StackPanel();\r
+            sp.MouseLeftButtonDown += reply_with_site_MouseLeftButtonDown;\r
+            sp.Children.Add(new TextBlock(new Run("このレスに引用して返信")));\r
+            item1 = new ListBoxItem();\r
+            item1.Padding = new System.Windows.Thickness(10, 2, 10, 2);\r
+            item1.Content = sp;\r
+            item1.MouseEnter += item1_MouseEnter;\r
+            item1.MouseLeave += item1_MouseLeave;\r
+            //item1.MouseLeftButtonDown += item1_MouseLeftButtonDown;\r
+            //item1.MouseLeftButtonUp += item1_MouseLeftButtonUp;\r
+            panel.Children.Add(item1);\r
+            sp = new StackPanel();\r
+            sp.Children.Add(new TextBlock(new Run("このレスからNGを抽出")));\r
+            sp.MouseLeftButtonDown += item1_MouseLeftButtonDown;\r
+            item1 = new ListBoxItem();\r
+            item1.Padding = new System.Windows.Thickness(10, 2, 10, 2);\r
+            item1.Content = sp;\r
+            item1.MouseEnter += item1_MouseEnter;\r
+            item1.MouseLeave += item1_MouseLeave;\r
+            item1.MouseLeftButtonDown += item1_MouseLeftButtonDown;\r
+            item1.MouseLeftButtonUp += item1_MouseLeftButtonUp;\r
+            panel.Children.Add(item1);\r
+\r
+            //this.Child = panel;\r
+            border.Child = panel; \r
+            this.Child = border;\r
+\r
+\r
+        }\r
+\r
+        void addBookmark_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)\r
+        {\r
+            Hide();\r
+            //IsOpen = false;\r
+            //throw new NotImplementedException();\r
+        }\r
+\r
+        \r
+        void reply_with_no_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)\r
+        {\r
+            string siteMsg = ">"+mRes.mSeqNo.ToString();\r
+            mMainWnd.WriteRes_Invoke(mRes.mThread, siteMsg);\r
+\r
+        }\r
+        \r
+        void reply_with_site_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)\r
+        {\r
+            StringBuilder sb = new StringBuilder();\r
+            sb.Append('>').Append(mRes.mSeqNo.ToString()).Append("\r\n");\r
+            string  msg = NTTextFormat.removeTag(mRes.mMsg);\r
+            string [] lines = NTTextUtiles.splitLine(msg);\r
+            foreach (string line in lines)\r
+            {\r
+                sb.Append('>').Append(line).Append("\r\n");\r
+            }\r
+            string siteMsg = sb.ToString();\r
+            mMainWnd.WriteRes_Invoke(mRes.mThread, siteMsg);\r
+        }\r
+\r
+        void addBookmark_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)\r
+        {\r
+            //IsOpen = false;\r
+            Hide();\r
+            /*if (mRes == null)\r
+                return;\r
+            if (!mRes.mBookmark)\r
+                mRes.addBookmark();\r
+            else\r
+                mRes.removeBookmark();*/\r
+            \r
+        }\r
+\r
+        void item1_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)\r
+        {\r
+            Hide();\r
+            //IsOpen = false;\r
+            //throw new NotImplementedException();\r
+        }\r
+\r
+        void item1_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)\r
+        {\r
+            Hide();\r
+            //IsOpen = false;\r
+            //mMainWnd.NgEdit_setResSection(mRes);\r
+        }\r
+\r
+        void item1_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e)\r
+        {\r
+            ListBoxItem item = sender as ListBoxItem;\r
+            if (item == null)\r
+                return;\r
+\r
+            item.Background = new SolidColorBrush(Colors.White);\r
+        }\r
+\r
+        void item1_MouseEnter(object sender, System.Windows.Input.MouseEventArgs e)\r
+        {\r
+            ListBoxItem item = sender as ListBoxItem;\r
+            if (item == null)\r
+                return;\r
+\r
+            item.Background = new SolidColorBrush(Colors.MistyRose);\r
+        }\r
+\r
+        void NTResPopupMenu1_LostFocus(object sender, System.Windows.RoutedEventArgs e)\r
+        {\r
+            Hide();\r
+            //IsOpen = false;\r
+            //mPopupMenu = null;\r
+        }\r
+\r
+        void NTResPopupMenu1_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e)\r
+        {\r
+            Hide();\r
+            //IsOpen = false;\r
+            // mPopupMenu = null;\r
+        }\r
+\r
+        public void show()\r
+        {\r
+            Hide();\r
+\r
+            mMe = this;\r
+            IsOpen = true;\r
+            Placement = PlacementMode.Mouse;\r
+            Focus();\r
+        }\r
+\r
+\r
+\r
+    }\r
+}\r
diff --git a/NT2chView45/NTSetupAESWindow.xaml b/NT2chView45/NTSetupAESWindow.xaml
new file mode 100755 (executable)
index 0000000..40d606c
--- /dev/null
@@ -0,0 +1,62 @@
+<Window x:Class="NT2chView.NTSetupAESWindow"\r
+        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"\r
+        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"\r
+        Title="AES設定" Height="400" Width="400" Loaded="Window_Load">\r
+    <Grid>\r
+        <Grid.RowDefinitions>\r
+            <RowDefinition Height="Auto"/>\r
+            <RowDefinition Height="Auto"/>\r
+            <RowDefinition Height="Auto"/>\r
+            <RowDefinition Height="*"/>\r
+            <RowDefinition Height="Auto"/>\r
+        </Grid.RowDefinitions>\r
+        <Grid.ColumnDefinitions>\r
+            <ColumnDefinition/>\r
+            <ColumnDefinition/>\r
+            <ColumnDefinition/>\r
+        </Grid.ColumnDefinitions>\r
+        <Label Grid.ColumnSpan="3">\r
+            AES暗号パスワードの指定\r
+        </Label>\r
+        <TextBox x:Name="mEdtAESPass" Grid.Row="1" Grid.ColumnSpan="3" Margin="3" MaxLength="32" MaxLines="1"/>\r
+        <CheckBox x:Name="mChkUseAES" Grid.Row="2" Grid.ColumnSpan="3" Margin="5" >\r
+            AES暗号を有効にする。\r
+        </CheckBox>\r
+        <FlowDocumentScrollViewer Grid.Row="3" Grid.ColumnSpan="3">\r
+            <FlowDocument>\r
+                <Section>\r
+                    <Paragraph FontSize="10">\r
+                        <Run>\r
+                             パスワードに日本語を指定出来ますが、\r
+                            プラットフォームやIMEの違いによって\r
+                            見た目が似ていても異なる文字コードが\r
+                            割り当てられる場合があります。\r
+                            不安に感じる場合、十分長い、ランダムな英数字を\r
+                            指定する事をお勧めします。\r
+                            特にAndroidと同期する時には注意が必要です。\r
+                        </Run>\r
+                        <LineBreak/>\r
+                        <Run>\r
+                             このパスワードから256bit暗号鍵が生成されます。(RFC2898)\r
+                             パスワードを変更すると鍵が変更されて、以前のデーターは\r
+                            復元できなくなります。十分注意して下さい。\r
+                            \r
+                        </Run>\r
+                        <LineBreak/>\r
+                        <LineBreak/>                        \r
+                        <Run>\r
+                            [アップロードボタン]\r
+                            クラウド同期が有効なデータ(お気に入り、NG、外部板、既読メニュー)\r
+                            を新しい鍵で暗号化して同期します。\r
+                        </Run>\r
+                    </Paragraph>\r
+                </Section>\r
+            </FlowDocument>\r
+        </FlowDocumentScrollViewer>\r
+        <TextBlock>\r
+        </TextBlock>\r
+        <!--Button Grid.Row="4" Grid.Column="0" Content="アップロード" Margin="5" Click="AESUpload_Click"/-->\r
+        <Button Grid.Row="4" Grid.Column="1" Content="保存" Margin="5" Click="AESOK_Click"/>\r
+        <Button Grid.Row="4" Grid.Column="2" Content="キャンセル" Margin="5" Click="AESCancel_Click" />\r
+    </Grid>\r
+</Window>\r
diff --git a/NT2chView45/NTSetupAESWindow.xaml.cs b/NT2chView45/NTSetupAESWindow.xaml.cs
new file mode 100755 (executable)
index 0000000..225580b
--- /dev/null
@@ -0,0 +1,60 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Windows;\r
+using System.Windows.Controls;\r
+using System.Windows.Data;\r
+using System.Windows.Documents;\r
+using System.Windows.Input;\r
+using System.Windows.Media;\r
+using System.Windows.Media.Imaging;\r
+using System.Windows.Shapes;\r
+\r
+namespace NT2chView\r
+{\r
+    /// <summary>\r
+    /// NTSetupAESWindow.xaml の相互作用ロジック\r
+    /// </summary>\r
+    public partial class NTSetupAESWindow : Window\r
+    {\r
+        public bool Save { get; set; }\r
+        public string AESPass { get; set; }\r
+        public bool AESEnable { get; set; }\r
+\r
+        public NTSetupAESWindow()\r
+        {\r
+            InitializeComponent();\r
+            Save = false;\r
+        }\r
+\r
+        private void AESOK_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            Save = true;\r
+            AESPass = mEdtAESPass.Text;\r
+            if (mChkUseAES.IsChecked.HasValue && (bool)mChkUseAES.IsChecked)\r
+                AESEnable = true;\r
+            else\r
+                AESEnable = false;\r
+\r
+            Close();\r
+        }\r
+\r
+        private void AESCancel_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            Save = false;\r
+            Close();\r
+        }\r
+\r
+        private void AESUpload_Click(object sender, RoutedEventArgs e)\r
+        {\r
+\r
+        }\r
+\r
+        private void Window_Load(object sender, RoutedEventArgs e)\r
+        {\r
+            mEdtAESPass.Text = AESPass;\r
+            mChkUseAES.IsChecked = AESEnable;\r
+            \r
+        }\r
+    }\r
+}\r
diff --git a/NT2chView45/NTSetupWindow.xaml b/NT2chView45/NTSetupWindow.xaml
new file mode 100755 (executable)
index 0000000..b716545
--- /dev/null
@@ -0,0 +1,366 @@
+<Window x:Class="NT2chView.NTSetupWindow"\r
+        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"\r
+        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"\r
+        xmlns:cm="clr-namespace:System.ComponentModel;assembly=System"\r
+        Title="2ぃとちゃん設定" Height="450" Width="530" Name="windowNTSetup" Padding="5" Loaded="windowNTSetup_Loaded">\r
+    <Window.Resources>\r
+        <cm:BackgroundWorker x:Key="bgCloudChkWorker"\r
+                             WorkerReportsProgress="True" WorkerSupportsCancellation="True"\r
+                             DoWork="bgCloudChk_DoWork"\r
+                             ProgressChanged="bgCloudChk_ProgressChanged"\r
+                             RunWorkerCompleted="bgCloudChk_RunWorkerCompleted">\r
+        </cm:BackgroundWorker>\r
+        <cm:BackgroundWorker x:Key="bgUploadExBoardWorker"\r
+                             WorkerReportsProgress="False"\r
+                             DoWork="bgUploadExBoard_DoWork"\r
+                             >\r
+        </cm:BackgroundWorker>\r
+    </Window.Resources>\r
+    <DockPanel LastChildFill="True">\r
+        <StackPanel  DockPanel.Dock="Bottom" Orientation="Horizontal" FlowDirection="RightToLeft">\r
+            <Button Name="btnCancel" Click="btnCancel_Click" Margin="5" Padding="10,1">閉じる</Button>\r
+            <Button Name="btnOK" Click="btnOK_Click" Margin="5" Padding="5,1">保存する</Button>\r
+        </StackPanel>\r
+        <TabControl>\r
+            <TabItem Header="P2">\r
+                <Grid Margin="10">\r
+                    <Grid.RowDefinitions>\r
+                        <RowDefinition Height="Auto"/>\r
+                        <RowDefinition Height="Auto" />\r
+                        <RowDefinition Height="Auto" />\r
+                        <RowDefinition Height="Auto" />\r
+                        <RowDefinition Height="Auto" />\r
+                    </Grid.RowDefinitions>\r
+                    <Grid.ColumnDefinitions>\r
+                        <ColumnDefinition Width="Auto"/>\r
+                        <ColumnDefinition Width="*"/>\r
+                    </Grid.ColumnDefinitions>\r
+                    <Label Content="メールアドレス:" Height="32" HorizontalContentAlignment="Right" VerticalContentAlignment="Center" />\r
+                    <Label Content="パスワード:" Grid.Row="1" VerticalContentAlignment="Center" HorizontalContentAlignment="Right" />\r
+                    <TextBox Grid.Column="1" Padding="5" BorderThickness="3" Name="txtP2ID" />\r
+                    <TextBox Grid.Column="1" Grid.Row="1" Padding="5" BorderThickness="3" Name="txtP2Pass" />\r
+                    <Label Grid.Row="2" Grid.Column="1">\r
+                        <TextBlock TextWrapping="Wrap">\r
+                            <Run Text="P2のリンク" />\r
+                          <Hyperlink Click="NTSetupWindow_hlink_OnClick" NavigateUri="http://p2.2ch.net/">\r
+                            <Run Text="http://p2.2ch.net/"/>\r
+                          </Hyperlink>\r
+                        </TextBlock>\r
+                    </Label>\r
+                    <Label Grid.Row="3" Grid.ColumnSpan="2">2ぃとちゃんは独自のP2ログイン処理をしているので</Label>\r
+                    <Label Grid.Row="4" Grid.ColumnSpan="2">p2proxy.exeなどの外部プログラムは不要です</Label>\r
+                </Grid>\r
+            </TabItem>\r
+            <TabItem Header=" ● " Name="tabItemMaru" Loaded="tabItemMaru_Loaded" >\r
+                <Grid Margin="10">\r
+                    <Grid.RowDefinitions>\r
+                        <RowDefinition Height="Auto"/>\r
+                        <RowDefinition Height="Auto" />\r
+                        <RowDefinition Height="Auto" />\r
+                        <RowDefinition Height="Auto" />\r
+                        <RowDefinition Height="Auto" />\r
+                    </Grid.RowDefinitions>\r
+                    <Grid.ColumnDefinitions>\r
+                        <ColumnDefinition Width="Auto"/>\r
+                        <ColumnDefinition Width="*"/>\r
+                    </Grid.ColumnDefinitions>\r
+                    <Label>2chビューアーの設定</Label>\r
+                    <Label Content="ユーザーID(メールアドレス):" Grid.Row="1" Height="32" HorizontalContentAlignment="Right" VerticalContentAlignment="Center" />\r
+                    <Label Content="パスワード:" Grid.Row="2" VerticalContentAlignment="Center" HorizontalContentAlignment="Right" />\r
+                    <TextBox Grid.Column="1" Grid.Row="1" Padding="5" BorderThickness="3" Name="txtMaruID" />\r
+                    <TextBox Grid.Column="1" Grid.Row="2" Padding="5" BorderThickness="3" Name="txtMaruPass" />\r
+                    <CheckBox Name="chkUseMaru" Grid.Row="3" Grid.Column="1" Checked="chkUseMaru_Checked" Unchecked="chkUseMaru_Unchecked">2chビューアーを使う</CheckBox>\r
+                    <Label Grid.Row="4" Grid.Column="1">\r
+                        <TextBlock TextWrapping="Wrap">\r
+                          <Hyperlink Click="NTSetupWindow_hlink_OnClick" NavigateUri="http://2ch.tora3.net/">\r
+                            <Run Text="http://2ch.tora3.net/"/>\r
+                          </Hyperlink>\r
+                        </TextBlock>\r
+                    </Label>\r
+                </Grid>\r
+\r
+            </TabItem>\r
+\r
+            <TabItem Header="クラウド" Name="tabItem2">\r
+\r
+                <Grid Margin="10">\r
+                    <Grid.RowDefinitions>\r
+                        <RowDefinition Height="Auto"/>\r
+                        <RowDefinition Height="Auto"/>\r
+                        <RowDefinition Height="Auto"/>\r
+                        <RowDefinition Height="Auto"/>\r
+                        <RowDefinition Height="Auto" />\r
+                        <RowDefinition Height="Auto" />\r
+                        <RowDefinition Height="Auto" />\r
+                        <RowDefinition Height="*" />\r
+                    </Grid.RowDefinitions>\r
+                    <Grid.ColumnDefinitions>\r
+                        <ColumnDefinition Width="Auto"/>\r
+                        <ColumnDefinition Width="*"/>\r
+                    </Grid.ColumnDefinitions>\r
+                    <StackPanel Orientation="Horizontal" Grid.ColumnSpan="2">\r
+                        <CheckBox Content="クラウド同期を使用する" Name="chkNTCloudEnable"\r
+                                  HorizontalAlignment="Left" Margin="10,0,10,0" VerticalAlignment="Center" Checked="chkNTCloudEnable_Checked" Unchecked="chkNTCloudEnable_Unchecked">\r
+\r
+                        </CheckBox>\r
+                    </StackPanel>\r
+                    <Label Content="ユーザーID:" Grid.Row="1" Height="32" HorizontalContentAlignment="Right" VerticalContentAlignment="Center" />\r
+                    <Label Content="パスワード:" Grid.Row="2" VerticalContentAlignment="Center" HorizontalContentAlignment="Right" />\r
+                    <TextBox Grid.Column="1" Grid.Row="1" Padding="5" BorderThickness="3" Name="txtNTID" />\r
+                    <TextBox Grid.Column="1" Grid.Row="2" Padding="5" BorderThickness="3" Name="txtNTPass" />\r
+                    <StackPanel Orientation="Horizontal" Grid.ColumnSpan="2" Grid.Row="3">\r
+                        <CheckBox Content="サーバーを指定する" Name="chkUserCloudEnable"\r
+                                  HorizontalAlignment="Left" Margin="10,0,10,0" VerticalAlignment="Center" Checked="chkUserCloudEnable_Checked" Unchecked="chkUserCloudEnable_Unchecked">\r
+\r
+                        </CheckBox>\r
+                    </StackPanel>\r
+                    <Label Content="URL:" Grid.Row="4" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" />\r
+                    <TextBox Grid.Column="1" Grid.Row="4" Padding="5" BorderThickness="3" Name="txtUserServerUrl" />\r
+                    <Grid Grid.Row="5" Grid.ColumnSpan="2">\r
+                        <Grid.ColumnDefinitions>\r
+                            <ColumnDefinition Width="Auto"/>\r
+                            <ColumnDefinition Width="Auto"/>\r
+                        </Grid.ColumnDefinitions>\r
+                        <Grid.RowDefinitions>\r
+                            <RowDefinition/>\r
+                            <RowDefinition/>\r
+                        </Grid.RowDefinitions>\r
+                        <Label Content="AES暗号設定" />\r
+                        <Button Grid.Column="1" Name="btnNTCloudSetupAes" Click="btnNTCloudSetupAes_Click">設定</Button>\r
+                        <Label Grid.Row="1" Content="既存のユーザーIDとパスワードをこの端末に設定" />\r
+                        <Button Grid.Row="1"  Grid.Column="1" Name="btnNTCloudCheckUser" Click="btnNTCloudCheckUser_Click">設定</Button>\r
+                    </Grid>\r
+                    <Label Content="ステータス:" Grid.Row="6" Grid.ColumnSpan="2" VerticalContentAlignment="Bottom" HorizontalContentAlignment="Left" />\r
+                    <Border  Grid.Row="7" Grid.ColumnSpan="2" BorderBrush="AliceBlue" BorderThickness="5">\r
+                        <TextBox Name="txtNTStatus" IsEnabled="False" />\r
+                    </Border>\r
+                </Grid>\r
+\r
+            </TabItem>\r
+            <TabItem Header="表示" Name="tabItem3" Loaded="tabItem3_Loaded">\r
+                <Grid>\r
+                    <Grid.RowDefinitions>\r
+                        <RowDefinition Height="Auto"/>\r
+                        <RowDefinition Height="Auto"/>\r
+                        <RowDefinition Height="*"/>\r
+                        <RowDefinition Height="Auto"/>\r
+                    </Grid.RowDefinitions>\r
+                    <GroupBox>\r
+                        <StackPanel>\r
+                            <Label>スレッドタイトル一覧の既読数表示</Label>\r
+                            <RadioButton Name="rdoShowCloudReadOnly" GroupName="grpRdoReadCnt">クラウドの既読数だけを表示する</RadioButton>\r
+                            <RadioButton Name="rdoShowAllReadLog" GroupName="grpRdoReadCnt">このコンピューターのログも表示する</RadioButton>\r
+                        </StackPanel>\r
+                    </GroupBox>\r
+                    <Grid Grid.Row="2">\r
+                        <Grid.RowDefinitions>\r
+                            <RowDefinition Height="Auto"/>\r
+                            <RowDefinition Height="Auto"/>\r
+                            <RowDefinition Height="Auto"/>\r
+                            <RowDefinition Height="Auto"/>\r
+                            <RowDefinition Height="*"/>\r
+                            <RowDefinition Height="Auto"/>\r
+                        </Grid.RowDefinitions>\r
+                        <Grid.ColumnDefinitions>\r
+                            <ColumnDefinition Width="Auto"/>\r
+                            <ColumnDefinition Width="*"/>\r
+                            <ColumnDefinition Width="Auto"/>\r
+                        </Grid.ColumnDefinitions>\r
+                        <StackPanel Grid.ColumnSpan="3" Margin="5" Orientation="Horizontal">\r
+                            <Label>スレタイ一覧リストビューのフォントサイズ(pt):</Label>\r
+                            <TextBox x:Name="mEdtThreadFontSize" x:FieldModifier="private" Margin="5,5,0,5" Width="50" Text="0" TextChanged="mEdtThreadFontSize_TextChanged" />\r
+                            <Button x:Name="mCmdThreadFontSizeUp" x:FieldModifier="private" Margin="5,5,0,5" Content="˄" Width="20" Click="mBtnThreadFontSizeUp_Click" />\r
+                            <Button x:Name="mCmdThreadFontSizeDown" x:FieldModifier="private" Margin="0,5,0,5"  Content="˅" Width="20" Click="mBtnThreadFontSizeDown_Click" />\r
+                        </StackPanel>\r
+                        <CheckBox x:Name="chkUseResFont" Grid.Row="1" Height="24" VerticalAlignment="Top">フォントを指定する</CheckBox>\r
+                        <TextBox x:Name="edtFontRes" Grid.Row="1" Grid.Column="1"/>\r
+                        <Button x:Name="btnFontRes" Content="フォント..." Grid.Row="1" Grid.Column="2"  Width="75" Click="btnFontRes_Click"/>\r
+                        <CheckBox Name="chkUseAAFont" Grid.Row="2">AAフォントを指定する</CheckBox>\r
+                        <TextBox x:Name="edtFontAA" Grid.Row="2" Grid.Column="1"/>\r
+                        <Button x:Name="btnFontAA" Content="フォント..." Grid.Row="2" Grid.Column="2"  Width="75" Click="btnFontAA_Click"/>\r
+                        <Border Margin="2"\r
+                            Grid.Row="3" Grid.RowSpan="2" Grid.Column="0" Grid.ColumnSpan="2" BorderBrush="Gray">\r
+                            <Grid>\r
+                                <Grid.RowDefinitions>\r
+                                    <RowDefinition Height="Auto"/>\r
+                                    <RowDefinition Height="Auto"/>\r
+                                    <RowDefinition Height="Auto"/>\r
+                                    <RowDefinition Height="*"/>\r
+                                </Grid.RowDefinitions>\r
+                                <Grid.ColumnDefinitions>\r
+                                    <ColumnDefinition Width="Auto"/>\r
+                                    <ColumnDefinition Width="*"/>\r
+                                </Grid.ColumnDefinitions>\r
+                                <Label Grid.Row="0">AA判定文字列の指定:</Label>\r
+                                <TextBox x:Name="edtAATextData" \r
+                                         Margin="2" Grid.Row="0" Grid.Column="1" Grid.RowSpan="4" \r
+                                         AcceptsReturn="True"\r
+                                         VerticalScrollBarVisibility="Auto"\r
+                                         HorizontalScrollBarVisibility="Auto"/>\r
+                                <Label xml:space="preserve" Grid.Row="1" FontSize="8">※ AA(アスキーアート)\r
+として判定する文字列を\r
+一行ずつ指定して下さい。\r
+今のところ、正規表現には\r
+対応していません。\r
+                                </Label>\r
+                                <Button x:Name="btnInitAAText" Grid.Row="2" Width="100" Click="btnInitAAText_Click">\r
+                                    初期値に設定\r
+                                </Button>\r
+                            </Grid>\r
+                        </Border>\r
+                    </Grid>\r
+                </Grid>\r
+            </TabItem>\r
+            <TabItem Header="操作" Loaded="tabItemManipulate_Loaded">\r
+                <Grid>\r
+                    <Grid.RowDefinitions>\r
+                        <RowDefinition Height="Auto"/>\r
+                        <RowDefinition Height="Auto"/>\r
+                    </Grid.RowDefinitions>\r
+                    <CheckBox Margin="5,20,5,3" x:Name="mChkEnablePopupMouseHover" Content="マウスホーバーでメニューを表示する"/>\r
+                    <CheckBox Margin="5,3" Grid.Row="1"\r
+                    x:Name="mChkOpenYoutubeLinkOnApp" \r
+                    Content="Youtubeリンクをアプリで開く"/>\r
+                </Grid>\r
+            </TabItem>\r
+            <TabItem Header="通信" Loaded="tabItemNetwork_Loaded">\r
+                <Grid Margin="10">\r
+                    <Grid.ColumnDefinitions>\r
+                        <ColumnDefinition Width="Auto"/>\r
+                        <ColumnDefinition Width="Auto"/>\r
+                    </Grid.ColumnDefinitions>\r
+                    <Grid.RowDefinitions>\r
+                        <RowDefinition Height="Auto"/>\r
+                        <RowDefinition Height="Auto"/>\r
+                        <RowDefinition Height="Auto"/>\r
+                    </Grid.RowDefinitions>\r
+                    <Label>サムネール画像を開く時に同時に行う通信数: </Label>\r
+                    <StackPanel Orientation="Horizontal" Grid.Column="1">\r
+                        <TextBox x:Name="mEdtThreadNum" x:FieldModifier="private" Margin="5,5,0,5" Width="50" Text="0" TextChanged="mEdtThreadNum_TextChanged" />\r
+                        <Button x:Name="mCmdUp" x:FieldModifier="private" Margin="5,5,0,5" Content="˄" Width="20" Click="mBtnThreadNumUp_Click" />\r
+                        <Button x:Name="mCmdDown" x:FieldModifier="private" Margin="0,5,0,5"  Content="˅" Width="20" Click="mBtnThreadNumDown_Click" />\r
+                    </StackPanel>\r
+                    <Label Grid.Row="1">お気に入りの更新間隔: </Label>\r
+                    <StackPanel Orientation="Horizontal" Grid.Row="1" Grid.Column="1">\r
+                        <TextBox x:Name="mEdtUpdateInterval" Margin="5,5,0,5" Width="50"\r
+                                 Text="0" TextChanged="mEdtUpdateInterval_TextChanged" />\r
+                        <Label>分</Label>\r
+                    </StackPanel>\r
+                </Grid>\r
+            </TabItem>\r
+            <TabItem Header="外部板" Loaded="tabItemExternalBoard_Loaded" >\r
+\r
+                <Grid Margin="3">\r
+                    <Grid.ColumnDefinitions>\r
+                        <ColumnDefinition Width="Auto"/>\r
+                        <ColumnDefinition Width="*"/>\r
+                        <ColumnDefinition Width="Auto"/>\r
+                    </Grid.ColumnDefinitions>\r
+                    <Grid.RowDefinitions>\r
+                        <RowDefinition Height="Auto"/>\r
+                        <RowDefinition Height="Auto"/>\r
+                        <RowDefinition  Height="Auto"/>\r
+                        <RowDefinition Height="*"/>\r
+                        <RowDefinition  Height="Auto"/>\r
+                    </Grid.RowDefinitions>\r
+                    <Label Margin="20,5,10,5" VerticalAlignment="Center">URL:</Label>\r
+                    <TextBox x:Name="txtBoardUrl" Grid.Column="1" Margin="0,5,10,5" VerticalContentAlignment="Center"/>\r
+                    <Button Name="btnExternalBoardConfirm" Grid.Column="2" VerticalAlignment="Center" HorizontalAlignment="Center" \r
+                           Padding="10,3,10,3"  Click="btnExternalBoardConfirm_Click">\r
+                        URL 確認\r
+                    </Button>\r
+                    <Label Grid.Row="1" Margin="20,5,10,5" VerticalAlignment="Center" >板名:</Label>\r
+                    <TextBox x:Name="txtBoardName" Grid.Row="1" Grid.Column="1"  VerticalContentAlignment="Center" Margin="0,5,10,5" MaxLength="20"/>\r
+                    <Button Name="btnExternalBoardRegister" Grid.Row="1" Grid.Column="2"  \r
+                            VerticalAlignment="Center" \r
+                            HorizontalAlignment="Center" \r
+                            Padding="10,3,10,3"  Click="btnExternalBoardRegister_Click">\r
+                        板を登録する\r
+                    </Button>\r
+                    <Label Content="登録板:" Margin="20,5,10,5" Grid.Row="2"\r
+                           VerticalContentAlignment="Bottom" HorizontalContentAlignment="Left" />\r
+                    <Button Name="btnExternalBoardRemove" Grid.Row="4" Grid.Column="2"\r
+                           VerticalAlignment="Center" \r
+                            HorizontalAlignment="Center" \r
+                            Padding="10,3,10,3" Margin="30,5,30,5" Click="btnExternalBoardRemove_Click" >\r
+                        削除\r
+                    </Button>\r
+                    <Border  Grid.Row="3" Grid.ColumnSpan="3" BorderBrush="AliceBlue" BorderThickness="5">\r
+                        <ListBox Name="lstExternalBoardList"></ListBox>\r
+                    </Border>\r
+                </Grid>\r
+            </TabItem>\r
+            <TabItem Header="バージョン情報">\r
+                <Grid>\r
+                    <Grid.RowDefinitions>\r
+                        <RowDefinition Height="Auto"/>\r
+                        <RowDefinition Height="*"/>\r
+                        <RowDefinition Height="Auto"/>\r
+                    </Grid.RowDefinitions>\r
+                    <CheckBox x:Name="mChkDebugOption"  Margin="5,10" Checked="chkDebugOption_Checked" Unchecked="chkDebugOption_Unchecked">デバッグオプション</CheckBox>\r
+                    <ScrollViewer Grid.Row="1" HorizontalScrollBarVisibility="Auto">\r
+                    <Label Name="lblVersionInfo" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">\r
+                    </Label>\r
+                    </ScrollViewer>\r
+                    <Label HorizontalAlignment="Center" Grid.Row="2">\r
+                        <TextBlock TextWrapping="Wrap">\r
+                          <Hyperlink Click="NTSetupWindow_hlink_OnClick" NavigateUri="http://neetchan.on.arena.ne.jp/">\r
+                            <Run Text="http://neetchan.on.arena.ne.jp/"/>\r
+                          </Hyperlink>\r
+                        </TextBlock>\r
+                    </Label>\r
+                </Grid>\r
+            </TabItem>\r
+        </TabControl>\r
+    </DockPanel>\r
+\r
+    <!--\r
+        <TextBlock TextWrapping="Wrap">You can use a Popup to provide a link for aspecific\r
+        <Run TextDecorations="Underline" MouseEnter="run_MouseEnter">item</Run>\r
+            of interest.\r
+        </TextBlock>\r
+        <Popup Name="popLink" StaysOpen="False" Placement="Mouse" MaxWidth="200"\r
+               PopupAnimation="Slide" AllowsTransparency="True">\r
+            <Border BorderBrush="Beige" BorderThickness="2" Background="White">\r
+                <TextBlock Margin="10" TextWrapping="Wrap">\r
+                    For more information, see\r
+                    <Hyperlink NavigateUri="http://en.wikipedia.org/wiki/Term"\r
+                               Click="lnk_Click">Wikipedia</Hyperlink>\r
+                </TextBlock>\r
+            </Border>\r
+        </Popup>\r
+        <Button>\r
+            <Button.ToolTip>\r
+                <ToolTip Background="#60AA4030" Foreground="White"\r
+                         HasDropShadow="False">\r
+                    <StackPanel>\r
+                        <TextBlock Margin="3">Image and text</TextBlock>\r
+                        <Image Source="/NT2chView;component/images/happyface.jpg" />\r
+                        <TextBlock Margin="3">Image and  text</TextBlock>\r
+                    </StackPanel>\r
+                </ToolTip>\r
+            </Button.ToolTip>\r
+            <Button.Content>\r
+                I have a fancy tooltip\r
+            </Button.Content>\r
+        </Button>\r
+        <CheckBox IsChecked="{x:Null}">A check box in indeterminate state</CheckBox>\r
+        <GroupBox Margin="5" Header="Group1">\r
+            <StackPanel >\r
+                <RadioButton>Group 1</RadioButton>\r
+                <RadioButton>Group 1</RadioButton>\r
+                <RadioButton>Group 1</RadioButton>\r
+                <RadioButton Margin="0,10,0,0" GroupName="Group2">Group 2</RadioButton>\r
+            </StackPanel>\r
+        </GroupBox>\r
+        <GroupBox Margin="5">\r
+            <StackPanel >\r
+                <RadioButton>Group 3</RadioButton>\r
+                <RadioButton>Group 3</RadioButton>\r
+                <RadioButton>Group 3</RadioButton>\r
+                <RadioButton Margin="0,10,0,0" GroupName="Group2">Group 2</RadioButton>\r
+            </StackPanel>\r
+        </GroupBox>\r
+        -->\r
+\r
+</Window>\r
diff --git a/NT2chView45/NTSetupWindow.xaml.cs b/NT2chView45/NTSetupWindow.xaml.cs
new file mode 100755 (executable)
index 0000000..8afdb12
--- /dev/null
@@ -0,0 +1,702 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Windows;\r
+using System.Windows.Controls;\r
+using System.Windows.Data;\r
+using System.Windows.Documents;\r
+using System.Windows.Input;\r
+using System.Windows.Media;\r
+using System.Windows.Media.Imaging;\r
+using System.Windows.Shapes;\r
+using System.Diagnostics;\r
+using NT2chView.NtNet;\r
+using System.ComponentModel;\r
+using NT2chView.NtFile;\r
+\r
+namespace NT2chView\r
+{\r
+    /// <summary>\r
+    /// NTSetupWindow.xaml の相互作用ロジック\r
+    /// </summary>\r
+    public partial class NTSetupWindow : Window\r
+    {\r
+        private string mExternalBoardSubject = null;\r
+        private string mExternalBoardUrl = null;\r
+\r
+        public NTSetupWindow()\r
+        {\r
+            InitializeComponent();\r
+        }\r
+\r
+        private void btnCancel_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            this.DialogResult = false;\r
+            Close();\r
+        }\r
+\r
+        private void btnOK_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            string p2id = txtP2ID.Text;\r
+            string p2pss = txtP2Pass.Text;\r
+            string maru_id = txtMaruID.Text;\r
+            string maru_pss = txtMaruPass.Text;\r
+            string ntcloud_id = txtNTID.Text;\r
+            string ntcloud_pss = txtNTPass.Text;\r
+            string ntcloud_url = txtUserServerUrl.Text;\r
+\r
+            NTUserPreference.P2ID = (null != p2id) ? p2id : string.Empty;\r
+            NTUserPreference.P2PSS = (null != p2pss) ? p2pss : string.Empty;\r
+            NTUserPreference.MaruID = (null != maru_id) ? maru_id : string.Empty;\r
+            NTUserPreference.MaruPSS = (null != maru_pss) ? maru_pss : string.Empty;\r
+            NTUserPreference.NTCloudID = (null != ntcloud_id) ? ntcloud_id : string.Empty;\r
+            NTUserPreference.NTCloudPSS = (null != ntcloud_pss) ? ntcloud_pss : string.Empty;\r
+            NTUserPreference.NTUserCloudUrl = (null != ntcloud_url) ? ntcloud_url : string.Empty;\r
+            if (rdoShowCloudReadOnly.IsChecked.HasValue)\r
+                NTUserPreference.NTShowOnlyCloudReadCount = (bool)rdoShowCloudReadOnly.IsChecked;\r
+\r
+            if (chkUseResFont.IsChecked.HasValue)\r
+                NTUserPreference.UseResFontTypeface = (bool)chkUseResFont.IsChecked;\r
+            else\r
+                NTUserPreference.UseResFontTypeface = false;\r
+\r
+            if (chkUseAAFont.IsChecked.HasValue)\r
+                NTUserPreference.UseAAFontTypeface = (bool)chkUseAAFont.IsChecked;\r
+            else\r
+                NTUserPreference.UseAAFontTypeface = false;\r
+            string fontName = edtFontRes.Text as string;\r
+            NTUserPreference.ResFontTypeface = (null != fontName) ? fontName : string.Empty;\r
+            fontName = edtFontAA.Text as string;\r
+            NTUserPreference.AAFontTypeface = (null != fontName) ? fontName : string.Empty;\r
+\r
+\r
+            string aaText = edtAATextData.Text.Replace("\r\n", "\n");\r
+            NTUserPreference.AAData = NTTextUtiles.splitLine(aaText);\r
+\r
+            NTUserPreference.ThreadtitleListViewFontSize = mThreadFontSizeValue;\r
+\r
+            NTUserPreference.FavoriteUpdateDuration = FavoriteUpdateDuration;\r
+\r
+\r
+            if (mChkEnablePopupMouseHover.IsChecked.HasValue)\r
+                NTUserPreference.EnablePopupMouseHover = (bool)mChkEnablePopupMouseHover.IsChecked;\r
+            else\r
+                NTUserPreference.EnablePopupMouseHover = false;\r
+\r
+            if (mChkOpenYoutubeLinkOnApp.IsChecked.HasValue)\r
+                NTUserPreference.OpenYoutubeOnApp = (bool)mChkOpenYoutubeLinkOnApp.IsChecked;\r
+            else\r
+                NTUserPreference.OpenYoutubeOnApp = false;\r
+\r
+            NTUserPreference.ResViewThumbnailConnectionCount = NumValue;\r
+\r
+            NTUserPreference.savePreferences();\r
+\r
+            this.DialogResult = true;\r
+            Close();\r
+\r
+        }\r
+\r
+        private void windowNTSetup_Loaded(object sender, RoutedEventArgs e)\r
+        {\r
+            string p2id = NTUserPreference.P2ID;\r
+            string p2pass = NTUserPreference.P2PSS;\r
+            string maru_id = NTUserPreference.MaruID;\r
+            string maru_pass = NTUserPreference.MaruPSS;\r
+            string ntcloud_id = NTUserPreference.NTCloudID;\r
+            string ntcloud_pass = NTUserPreference.NTCloudPSS;\r
+            string nt_user_server_url = NTUserPreference.NTUserCloudUrl;\r
+            bool bCloudEnable = NTUserPreference.NTCloudIsEnabled;\r
+            bool useResFont = NTUserPreference.UseResFontTypeface;\r
+            bool useAAFont = NTUserPreference.UseAAFontTypeface;\r
+\r
+\r
+            txtP2ID.Text = (null != p2id) ? p2id : string.Empty;\r
+            txtP2Pass.Text = (null != p2pass) ? p2pass : string.Empty;\r
+            txtMaruID.Text = (null != maru_id) ? maru_id : string.Empty;\r
+            txtMaruPass.Text = (null != maru_pass) ? maru_pass : string.Empty;\r
+            txtNTID.Text = (null != ntcloud_id) ? ntcloud_id : string.Empty;\r
+            txtNTPass.Text = (null != ntcloud_pass) ? ntcloud_pass : string.Empty;\r
+            txtUserServerUrl.Text = (null != nt_user_server_url) ? nt_user_server_url : string.Empty;\r
+\r
+\r
+            mChkDebugOption.IsChecked = NTUserPreference.DebugOption;\r
+            chkNTCloudEnable.IsChecked = NTUserPreference.NTCloudIsEnabled;\r
+            chkUseMaru.IsChecked = NTUserPreference.MaruIsEnabled;\r
+\r
+            chkUserCloudEnable.IsChecked = NTUserPreference.NTUserCloudIsEnabled;\r
+\r
+            System.Diagnostics.FileVersionInfo ver =\r
+                System.Diagnostics.FileVersionInfo.GetVersionInfo(\r
+                System.Reflection.Assembly.GetExecutingAssembly().Location);\r
+\r
+            lblVersionInfo.Content = ver;\r
+\r
+            chkUseResFont.IsChecked = NTUserPreference.UseResFontTypeface;\r
+            chkUseAAFont.IsChecked = NTUserPreference.UseAAFontTypeface;\r
+\r
+            string resFontName = NTUserPreference.ResFontTypeface;\r
+            edtFontRes.Text = resFontName;\r
+            string aaFontName = NTUserPreference.AAFontTypeface;\r
+            edtFontAA.Text = aaFontName;\r
+\r
+            edtAATextData.Text = NTTextUtiles.concatLines(NTUserPreference.AAData);\r
+\r
+            mThreadFontSizeValue = (int)NTUserPreference.ThreadtitleListViewFontSize;\r
+\r
+            mChkEnablePopupMouseHover.IsChecked = NTUserPreference.EnablePopupMouseHover;\r
+\r
+            mChkOpenYoutubeLinkOnApp.IsChecked = NTUserPreference.OpenYoutubeOnApp;\r
+\r
+            NumValue = NTUserPreference.ResViewThumbnailConnectionCount;\r
+\r
+            FavoriteUpdateDuration = NTUserPreference.FavoriteUpdateDuration;\r
+\r
+        }\r
+\r
+        private void chkDebugOption_Checked(object sender, RoutedEventArgs e)\r
+        {\r
+            NTUserPreference.DebugOption = true;\r
+        }\r
+\r
+        private void chkDebugOption_Unchecked(object sender, RoutedEventArgs e)\r
+        {\r
+            NTUserPreference.DebugOption = false;\r
+        }\r
+        private void chkNTCloudEnable_Checked(object sender, RoutedEventArgs e)\r
+        {\r
+            NTUserPreference.NTCloudIsEnabled = true;\r
+        }\r
+\r
+        private void chkNTCloudEnable_Unchecked(object sender, RoutedEventArgs e)\r
+        {\r
+            NTUserPreference.NTCloudIsEnabled = false;\r
+        }\r
+        private void chkUserCloudEnable_Checked(object sender, RoutedEventArgs e)\r
+        {\r
+            NTUserPreference.NTUserCloudIsEnabled = true;\r
+        }\r
+\r
+        private void chkUserCloudEnable_Unchecked(object sender, RoutedEventArgs e)\r
+        {\r
+            NTUserPreference.NTUserCloudIsEnabled = false;\r
+        }\r
+\r
+        /*private enum BGWORKSTATUS\r
+        {\r
+            OK,\r
+            FAIL\r
+        }*/\r
+        //private BGWORKSTATUS mBgStatus = BGWORKSTATUS.FAIL;\r
\r
+\r
+        private void bgCloudChk_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)\r
+        {\r
+\r
+            \r
+            string result = string.Empty;\r
+\r
+            string[] para = e.Argument as string[];\r
+\r
+            if(para == null || para.Length < 2)\r
+                return;\r
+            if (mSetUserCloud)\r
+                result = NTHttpAccess.UserCloudCheckUser(para[2], para[0], para[1]);\r
+            else if (para.Length == 2)\r
+                result = NTHttpAccess.ntCheckUser(para[0], para[1]);\r
+            e.Result = result;\r
+        }\r
+\r
+        private void bgCloudChk_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e)\r
+        {\r
+\r
+        }\r
+\r
+        private void bgCloudChk_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)\r
+        {\r
+\r
+            string result = e.Result as string;\r
+            if (result == null)\r
+                return;\r
+\r
+            string [] lines = NTTextUtiles.splitLine(result);\r
+            if (0 >= lines.Length)\r
+                return;\r
+\r
+            int status = 0;\r
+            try\r
+            {\r
+                status = int.Parse(lines[0]);\r
+            }\r
+            catch\r
+            {\r
+                return;\r
+            }\r
+            switch (status)\r
+            {\r
+                case 100:\r
+                    if (mSetUserCloud)\r
+                    {\r
+                        if (lines.Length >= 5)\r
+                        {\r
+                            txtNTStatus.Text = lines[0] + "\n" + lines[1];\r
+                            NTUserPreference.NTCloudPSS = txtNTPass.Text;\r
+                            NTUserPreference.NTCloudID = txtNTID.Text;\r
+                            NTUserPreference.NTUserCloudScriptUrl = lines[2];\r
+                            NTUserPreference.NTUserCloudFileUrl = lines[3];\r
+                            NTUserPreference.NTUserCloudSeed = lines[4];\r
+                            NTUserPreference.savePreferences();\r
+                        }\r
+                    }\r
+                    else\r
+                    {\r
+                        if (lines.Length >= 3)\r
+                        {\r
+                            string srvUrl = lines[2];\r
+                            txtNTStatus.Text = lines[0] + "\n" + lines[1];\r
+                            NTUserPreference.NTCloudUrl = srvUrl;\r
+                            NTUserPreference.NTCloudPSS = txtNTPass.Text;\r
+                            NTUserPreference.NTCloudID = txtNTID.Text;\r
+                            NTUserPreference.savePreferences();\r
+                        }\r
+                    }\r
+                    NTFileAccess.deleteCloudLastModified();\r
+                    break;\r
+                default:\r
+                    if(lines.Length >= 2)\r
+                    {\r
+                        txtNTStatus.Text = lines[0] +"\n" + lines[1];\r
+                    }\r
+                    break;\r
+            }\r
+        \r
+\r
+\r
+        }\r
+\r
+        private void btnNTCloudSetupAes_Click(object sender , RoutedEventArgs e)\r
+        {\r
+            NTSetupAESWindow window = new NTSetupAESWindow();\r
+            window.AESEnable = NTUserPreference.AESEnabled;\r
+            window.AESPass = NTUserPreference.AESPass;\r
+            window.ShowDialog();\r
+            if (window.Save)\r
+            {\r
+                NTUserPreference.AESEnabled = window.AESEnable;\r
+                NTUserPreference.AESPass = window.AESPass;\r
+                NTUserPreference.savePreferences();\r
+            }\r
+        }\r
+\r
+        bool mSetUserCloud;\r
+        private void btnNTCloudCheckUser_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            string ntcloud_id = txtNTID.Text;\r
+            string ntcloud_pss = txtNTPass.Text;\r
+            string nt_user_server_url = txtUserServerUrl.Text;\r
+            if (ntcloud_id.Length == 0)\r
+            {\r
+                MessageBox.Show("ユーザーIDが指定されていません。");\r
+                return;\r
+            }\r
+            if (ntcloud_pss.Length == 0)\r
+            {\r
+                MessageBox.Show("パスワードが指定されていません。");\r
+                return;\r
+            }\r
+            string[] para;\r
+            bool? userCloud = chkUserCloudEnable.IsChecked;\r
+            if (userCloud.HasValue && (bool)userCloud)\r
+            {\r
+                para = new string[3];\r
+                para[0] = ntcloud_id;\r
+                para[1] = ntcloud_pss;\r
+                para[2] = nt_user_server_url;\r
+                mSetUserCloud = true;\r
+            }\r
+            else\r
+            {\r
+                para = new string[2];\r
+                para[0] = ntcloud_id;\r
+                para[1] = ntcloud_pss;\r
+                mSetUserCloud = false;\r
+            }\r
+            BackgroundWorker worker;\r
+            worker = ((BackgroundWorker)this.FindResource("bgCloudChkWorker"));\r
+            worker.RunWorkerAsync(para);\r
+\r
+        }\r
+\r
+        private void tabItemMaru_Loaded(object sender, RoutedEventArgs e)\r
+        {\r
+        }\r
+\r
+        private void tabItem3_Loaded(object sender, RoutedEventArgs e)\r
+        {\r
+            if (NTUserPreference.NTShowOnlyCloudReadCount)\r
+                rdoShowCloudReadOnly.IsChecked = true;\r
+            else\r
+                rdoShowAllReadLog.IsChecked = true;\r
+        }\r
+\r
+        string chkUrl(string source)\r
+        {\r
+            int len = source.Trim().Length;\r
+            if(len == 0)\r
+                return source;\r
+            if ('/' != source[len - 1])\r
+                return source + '/';\r
+            else\r
+                return source; \r
+        }\r
+\r
+        private void btnExternalBoardConfirm_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            string url = txtBoardUrl.Text;\r
+            if (confirmExternalBoard(url))\r
+            {\r
+                MessageBox.Show("掲示板を確認しました。");\r
+                btnExternalBoardRegister.IsEnabled = true;\r
+            }\r
+            else\r
+            {\r
+                MessageBox.Show("有効なURLではありません。");\r
+                btnExternalBoardRegister.IsEnabled = false;\r
+\r
+            }\r
\r
+        }\r
+\r
\r
+        private void btnExternalBoardRegister_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            string boardName = txtBoardName.Text.Trim();\r
+            if (boardName.Length == 0)\r
+            {\r
+                MessageBox.Show("板に名前を指定して下さい。");\r
+                return;\r
+            }\r
+            int boardNameLen = boardName.Length*2;//regard ucs2\r
+            boardNameLen = ((boardNameLen / 16) * 16) + (((boardNameLen % 16) > 0) ? 16 : 0);//for aes encrypt\r
+            boardNameLen = ((boardNameLen * 133) / 100) + 3;//for base64\r
+            boardNameLen += 10;//for url encode\r
+\r
+            if (boardNameLen > 60)\r
+            {\r
+                MessageBox.Show(\r
+                    string.Format("名前が長すぎます。limit 60, length {0}", boardNameLen));\r
+                return;\r
+            }\r
+            if (mExternalBoardSubject == null ||\r
+                mExternalBoardUrl == null)\r
+            {\r
+                string url = chkUrl(txtBoardUrl.Text);\r
+                if (!confirmExternalBoard(url))\r
+                {\r
+                    MessageBox.Show("有効なURLではありません。");\r
+                    btnExternalBoardRegister.IsEnabled = false;\r
+                    return;\r
+                }\r
+\r
+            }\r
+            txtBoardName.Text = string.Empty;\r
+            txtBoardUrl.Text = string.Empty;\r
+            string description = mExternalBoardUrl + "<>" + boardName;\r
+            NTFileAccess.appendExternalBoard(description);\r
+            NTCategory category = NTDataRoot.getExternalBoards();\r
+            List<string> list = new List<string>();\r
+            NTBoard newBoard = new NTBoard(boardName, mExternalBoardUrl);\r
+            category.mBoardList.Add(newBoard);\r
+            NTAppState.getMainWindow().appendBoardToExternalCategoryTree(newBoard);\r
+            ListBoxItem subitem = new ListBoxItem();\r
+            subitem.Content = boardName;\r
+            lstExternalBoardList.Items.Add(subitem);\r
+\r
+            if (NTUserPreference.NTCloudIsEnabled)\r
+            {\r
+                BackgroundWorker worker;\r
+                worker = ((BackgroundWorker)this.FindResource("bgUploadExBoardWorker"));\r
+                worker.RunWorkerAsync(description);\r
+            }\r
+\r
+\r
+        }\r
+\r
+        private void bgUploadExBoard_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)\r
+        {\r
+            string description = e.Argument as string;\r
+            if (description == null)\r
+                return;\r
+\r
+            string result;\r
+            if (NTUserPreference.NTUserCloudIsEnabled)\r
+            {\r
+                result = NTHttpAccess.UserCloudUploadExternalBoards(description);\r
+            }\r
+            else\r
+            {\r
+                result = NTHttpAccess.ntUploadExternalBoards(description);\r
+            }\r
+            NTDebug.l(result);\r
+\r
+\r
+        }\r
+\r
+\r
+\r
+        private bool confirmExternalBoard(string url)\r
+        {\r
+            bool bRet = false;\r
+            try\r
+            {\r
+                if (url.Length == 0)\r
+                    throw new Exception();\r
+                \r
+\r
+                int idx = url.IndexOf("http://", StringComparison.CurrentCultureIgnoreCase);\r
+                if (0 > idx)\r
+                    throw new Exception();\r
+\r
+                idx = NTHttpUtils.parseWebHost(url, idx + "http://".Length);\r
+                if (idx < 0)\r
+                    throw new Exception();\r
+\r
+                url = chkUrl(url);\r
+               \r
+                string result = NTHttpAccess.getExternalBoardSubject(url, null);\r
+\r
+                if(result == null)\r
+                    throw new Exception();\r
+\r
+                NTDebug.l(result);\r
+\r
+                mExternalBoardSubject = result;\r
+                mExternalBoardUrl = url;\r
+                bRet = true;\r
+\r
+            }\r
+            catch\r
+            {\r
+                mExternalBoardSubject = null;\r
+                mExternalBoardUrl = null;\r
+            }\r
+            return bRet;\r
+       }\r
+\r
+        private void tabItemManipulate_Loaded(object sender, RoutedEventArgs e)\r
+        {\r
+\r
+        }\r
+        private void tabItemNetwork_Loaded(object sender, RoutedEventArgs e)\r
+        {\r
+\r
+        }\r
+\r
+        private int _threadFontSizeValue = 0;\r
+        public int mThreadFontSizeValue\r
+        {\r
+            get { return _threadFontSizeValue; }\r
+            set\r
+            {\r
+                _threadFontSizeValue = value;\r
+                if (_threadFontSizeValue < 1)\r
+                    _threadFontSizeValue = 1;\r
+                else if (_threadFontSizeValue > 36)\r
+                    _threadFontSizeValue = 36;\r
+                mEdtThreadFontSize.Text = value.ToString();\r
+            }\r
+        }\r
+\r
+        private void mBtnThreadFontSizeUp_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            mThreadFontSizeValue++;\r
+        }\r
+        private void mBtnThreadFontSizeDown_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            mThreadFontSizeValue--;\r
+        }\r
+        private void mEdtThreadFontSize_TextChanged(object sender,\r
+            TextChangedEventArgs e)\r
+        {\r
+            if (!int.TryParse(mEdtThreadFontSize.Text, out _threadFontSizeValue))\r
+                mEdtThreadFontSize.Text = _threadFontSizeValue.ToString();\r
+        }\r
+        private void mEdtUpdateInterval_TextChanged(object sender,\r
+            TextChangedEventArgs e)\r
+        {\r
+            if (!int.TryParse(mEdtUpdateInterval.Text, out _favoriteUpdateDuration))\r
+                mEdtThreadFontSize.Text = _favoriteUpdateDuration.ToString();\r
+            else\r
+            {\r
+                if (_favoriteUpdateDuration < 0 || _favoriteUpdateDuration > 60)\r
+                    mEdtThreadFontSize.Text = _favoriteUpdateDuration.ToString();\r
+            }\r
+        }\r
+\r
+        private int _favoriteUpdateDuration =\r
+            NTUserPreference.DEFAULT_FAVORITE_UPDATE_DURATION;\r
+        public int FavoriteUpdateDuration\r
+        {\r
+            get { return _favoriteUpdateDuration; }\r
+            set\r
+            {\r
+                if (value < 0 || value > 60)\r
+                    _favoriteUpdateDuration =\r
+                    NTUserPreference.DEFAULT_FAVORITE_UPDATE_DURATION;\r
+                else\r
+                    _favoriteUpdateDuration = value;\r
+                mEdtUpdateInterval.Text = _favoriteUpdateDuration.ToString();\r
+            }\r
+        }\r
+\r
+        private int _numValue = 0;\r
+        public int NumValue\r
+        {\r
+            get { return _numValue; }\r
+            set\r
+            {\r
+                _numValue = value;\r
+                if (_numValue < 1)\r
+                    _numValue = 1;\r
+                else if (_numValue > 20)\r
+                    _numValue = 20;\r
+                mEdtThreadNum.Text = value.ToString();\r
+            }\r
+        }\r
+\r
+        private void mBtnThreadNumUp_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            NumValue++;\r
+        }\r
+        private void mBtnThreadNumDown_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            NumValue--;\r
+        }\r
+\r
+        private void mEdtThreadNum_TextChanged(object sender,\r
+            TextChangedEventArgs e)\r
+        {\r
+            if (!int.TryParse(mEdtThreadNum.Text, out _numValue))\r
+                mEdtThreadNum.Text = _numValue.ToString();\r
+        }\r
+\r
+        private void tabItemExternalBoard_Loaded(object sender, RoutedEventArgs e)\r
+        {\r
+            string[] lines = NTFileAccess.retrieveExternalBoards();\r
+            if (lines != null)\r
+            {\r
+                foreach(string line in lines){\r
+                    int idx = line.IndexOf("<>");\r
+                    if (idx < 0)\r
+                        continue;\r
+                    ListBoxItem item = new ListBoxItem();\r
+                    item.Content = line.Substring(idx + 2);\r
+                    lstExternalBoardList.Items.Add(item);\r
+                }\r
+            }\r
+            btnExternalBoardRegister.IsEnabled = false;\r
+        }\r
+\r
+        private void btnExternalBoardRemove_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            ListBoxItem item = lstExternalBoardList.SelectedItem as ListBoxItem;\r
+            if (item == null)\r
+                return;\r
+\r
+            string s = item.Content as string;\r
+            if (s == null)\r
+                return;\r
+\r
+            lstExternalBoardList.Items.Remove(item);\r
+\r
+            NTCategory category = NTDataRoot.getExternalBoards();\r
+            List<string> list = new List<string>();\r
+            NTBoard removeBoard = null;\r
+            int len = category.mBoardList.Count;\r
+            for(int i = 0; i < len; i++)\r
+            {\r
+                NTBoard board = category.mBoardList[i] as NTBoard;\r
+                if (board == null)\r
+                    continue;\r
+                if (board.mName.Equals(s))\r
+                {\r
+                    removeBoard = board;\r
+                    //category.mBoardList.Remove(board);\r
+                }\r
+                else\r
+                {\r
+                    list.Add(board.mAddress + "<>" + board.mName);\r
+                }\r
+            }\r
+            if (removeBoard != null)\r
+            {\r
+                category.mBoardList.Remove(removeBoard);\r
+                if(NTUserPreference.NTCloudIsEnabled){\r
+                    if (NTUserPreference.NTUserCloudIsEnabled)\r
+                    {\r
+                        NTHttpAccess.UserCloudDeleteExternalBoards(\r
+                            removeBoard.mAddress + "<>" + removeBoard.mName);\r
+                    }\r
+                    else\r
+                    {\r
+                        NTHttpAccess.ntDeleteExternalBoards(\r
+                            removeBoard.mAddress + "<>" + removeBoard.mName);\r
+                    }\r
+                }\r
+            }\r
+            NTAppState.getMainWindow().removeBoardFromExternalCategoryTree(s);\r
+            NTFileAccess.writeExternalBoards(list.ToArray());\r
+        }\r
+\r
+        private void NTSetupWindow_hlink_OnClick(object sender, RoutedEventArgs e)\r
+        {\r
+            Hyperlink hl = sender as Hyperlink;\r
+            if (hl == null)\r
+                return;\r
+\r
+            Uri uri = hl.NavigateUri;\r
+            if (uri == null)\r
+                return;\r
+\r
+            Process.Start(uri.ToString());\r
+\r
+        }\r
+\r
+        private void chkUseMaru_Checked(object sender, RoutedEventArgs e)\r
+        {\r
+            NTUserPreference.MaruIsEnabled = true;\r
+        }\r
+\r
+        private void chkUseMaru_Unchecked(object sender, RoutedEventArgs e)\r
+        {\r
+            NTUserPreference.MaruIsEnabled = false;\r
+        }\r
+\r
+        private void btnFontRes_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            NTFontSelectDialog dlg = new NTFontSelectDialog();\r
+            if (NTUserPreference.UseResFontTypeface)\r
+                dlg.FontName = NTUserPreference.ResFontTypeface;// "IPAMonaPGothic";\r
+            bool? result = dlg.ShowDialog();\r
+            if(result.HasValue && (bool)result)\r
+                edtFontRes.Text = dlg.FontName;\r
+\r
+        }\r
+        private void btnFontAA_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            NTFontSelectDialog dlg = new NTFontSelectDialog();\r
+            if (NTUserPreference.UseAAFontTypeface)\r
+                dlg.FontName = NTUserPreference.AAFontTypeface;// "IPAMonaPGothic";\r
+            bool? result = dlg.ShowDialog();\r
+            if (result.HasValue && (bool)result)\r
+                edtFontAA.Text = dlg.FontName;\r
+\r
+        }\r
+\r
+        private void btnInitAAText_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            edtAATextData.Text = "  \n";\r
+        }\r
+        \r
+    }\r
+}\r
diff --git a/NT2chView45/NTSimString.cs b/NT2chView45/NTSimString.cs
new file mode 100755 (executable)
index 0000000..b4a0e33
--- /dev/null
@@ -0,0 +1,129 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+\r
+namespace NT2chView\r
+{\r
+    class NTSimString\r
+    {\r
+               List<string> mSplitedString;\r
+               \r
+               \r
+               const int TOKEN_SPACE = 0;\r
+               const int TOKEN_HIRAKANA = 1;\r
+               const int TOKEN_NUMALPHA = 2;\r
+               const int TOKEN_OTHER = 3;\r
+               \r
+               public NTSimString(String seed){\r
+            mSplitedString = new List<string>();\r
+                       int current = TOKEN_OTHER;\r
+                       int len = seed.Length;\r
+                       int start = 0;\r
+                       int i = 0;\r
+                       for(; i < len; i++){\r
+                               char c = seed[i];\r
+                               int token = getToken(c);\r
+                               if(token == TOKEN_SPACE){\r
+                                       if(current != TOKEN_SPACE){\r
+                                               if(start < i){\r
+                            mSplitedString.Add(seed.Substring(start, i - start));\r
+                                               }\r
+                                               current = TOKEN_SPACE;\r
+                                       }\r
+                                       start = i+1;\r
+                               }else{\r
+                                       if(current != token){\r
+                                               if(start < i){\r
+                            mSplitedString.Add(\r
+                                seed.Substring(start, i - start));\r
+                                               }\r
+                                               current = token;\r
+                                               start = i;\r
+                                       }\r
+                               }\r
+                       }\r
+                       if(start < i && current != TOKEN_SPACE){\r
+                mSplitedString.Add(\r
+                    seed.Substring(start, i - start));\r
+                       }\r
+               }\r
+               \r
+               public int match(String source){\r
+                       int match_len = 0;\r
+            foreach (string line in mSplitedString)\r
+            {\r
+                //int len;\r
+                //int idx = line.match(source, 0, out len);\r
+                //if (idx >= 0 && len > 1)\r
+                //{\r
+                //    match_len += len;\r
+                //}\r
+                if (0 <= source.IndexOf(line, StringComparison.CurrentCultureIgnoreCase))\r
+                {\r
+                                       match_len += line.Length;\r
+                               }\r
+                       }\r
+                       return match_len;\r
+               }\r
+               public void log(){\r
+                       //DebugUtil.log("SimString logging...");\r
+                       //foreach(String line in mSplitedString){\r
+                               //DebugUtil.log(line);\r
+                       //}\r
+               }\r
+               int getToken(char c){\r
+                       for(int i = 0; i < mSeparatorChar.Length; i++){\r
+                               if(c == mSeparatorChar[i]){\r
+                                       return TOKEN_SPACE;\r
+                               }\r
+                       }\r
+                       for(int i = 0; i < mHiraKakaChar.Length; i++){\r
+                               if(c == mHiraKakaChar[i]){\r
+                                       return TOKEN_HIRAKANA;\r
+                               }\r
+                       }\r
+                       for(int i = 0; i < mNumAlphaChar.Length; i++){\r
+                               if(c == mNumAlphaChar[i]){\r
+                                       return TOKEN_NUMALPHA;\r
+                               }\r
+                       }\r
+                       \r
+                       return TOKEN_OTHER;\r
+               }\r
+               static char [] mSeparatorChar = {\r
+                       ' ',' ','(',')','【','】','(',')','「','」','{','}','{','}','〈','〉',\r
+                       '《','》','「','」','『','』',',','.','、','。','★','※','*','?','!','?','!','・'};\r
+               static char [] mHiraKakaChar = {\r
+                       'ー','ー','あ','ア','ぁ','ァ','い','イ','ぃ','ィ','う','ウ','ぅ','ゥ',\r
+                       'え','エ','ぇ','ェ','お','オ','ぉ','ォ','を','ヲ',\r
+                       'か','カ','ヵ','ヵ','き','キ','く','ク','け','ケ','ヶ','ヶ','こ','コ',\r
+                       'さ','サ','し','シ','す','ス','せ','セ','そ','ソ',\r
+                       'た','タ','ち','チ','つ','ツ','っ','ッ','て','テ','と','ト',\r
+                       'な','ナ','に','ニ','ぬ','ヌ','ね','ネ','の','ノ',\r
+                       'は','ハ','ワ','わ','ひ','ヒ','ふ','フ','へ','ヘ','ほ','ホ',\r
+                       'ま','マ','み','ミ','む','ム','め','メ','も','モ',\r
+                       'や','ヤ','ゃ','ャ','ゆ','ユ','ゅ','ュ','よ','ヨ','ょ','ョ',\r
+                       'ラ','ら','ラ','り','リ','リ','る','ル','ル',\r
+                       'れ','レ','レ','ろ','ロ','ロ','ん','ン',\r
+                       'が','ガ','ぎ','ギ','ぐ','グ','げ','ゲ','ご','ゴ',\r
+                       'ざ','ザ','じ','ジ','ぢ','ヂ','ず','ズ','づ','ヅ',\r
+                       'ぜ','ゼ','ぞ','ゾ','だ','ダ','で','デ','ど','ド',\r
+                       'ば','バ','び','ビ','ぶ','ブ','べ','ベ','ぼ','ボ',\r
+                       'ぱ','パ','ぴ','ピ','ぷ','プ','ぺ','ペ','ぽ','ポ'};\r
+               static char [] mNumAlphaChar = {\r
+                       '-','_','-','_',\r
+                       '0','0','1','1','2','2','3','3','4','4',\r
+                       '5','5','6','6','7','7','8','8','9','9',\r
+                       'A','a','A','a','B','b','B','b','C','c','C','c',\r
+                       'D','d','D','d','E','e','E','e','F','f','F','f',\r
+                       'G','g','G','g','H','h','H','h','I','i','I','i',\r
+                       'J','j','J','j','K','k','K','k',        'L','l','L','l',\r
+                       'M','m','M','m','N','n','N','n','O','o','O','o',\r
+                       'P','p','P','p','Q','q','Q','q','R','r','R','r',\r
+                       'S','s','S','s','T','t','T','t',        'U','u','U','u',\r
+                       'V','v','V','v','W','w','W','w','X','x','X','x',\r
+                       'Y','y','Y','y','Z','z','Z','z','%','%','$','$','#','#',\r
+                       '@','@','+','+'};\r
+       }\r
+    \r
+}\r
diff --git a/NT2chView45/NTTextFormat.cs b/NT2chView45/NTTextFormat.cs
new file mode 100755 (executable)
index 0000000..ceddd9c
--- /dev/null
@@ -0,0 +1,438 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+\r
+namespace NT2chView\r
+{\r
+    sealed class NTTextFormat\r
+    {\r
+        public static string[] HTTP_SCHME_ARR = { "TTP://", "TTPS://", "ttp://", "ttps://"};\r
+\r
+        static char [] NUMERIC_2ch = {'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9'};\r
+\r
+\r
+        public static string convertLineBreakToHtmlTag(string source)\r
+        {\r
+            string[] lines = NTTextUtiles.splitLine(source);\r
+            StringBuilder sb = new StringBuilder();\r
+            foreach (string line in lines)\r
+            {\r
+                sb.Append(line.Trim()).Append("<br>");\r
+            }\r
+            return sb.ToString();\r
+        }\r
+\r
+        public static string removeTag(string source)\r
+        {\r
+            source = source.Replace("<br>", "\n");\r
+            source = source.Replace("<BR>", "\n");\r
+            StringBuilder sb = new StringBuilder();\r
+            int len = source.Length;\r
+            bool inTag = false;\r
+            for (int i = 0; i < len; i++)\r
+            {\r
+                char c = source[i];\r
+                switch (c)\r
+                {\r
+                    case '<':\r
+                        inTag = true;\r
+                        break;\r
+                    case '>':\r
+                        if (!inTag)\r
+                            sb.Append(c);\r
+                        inTag = false;\r
+                        break;\r
+                    default:\r
+                        if (!inTag)\r
+                            sb.Append(c);\r
+                        break;\r
+                }\r
+            }\r
+\r
+            return sb.ToString();\r
+        }\r
+\r
+        public static int parse2chNumA(string inText, int start)\r
+        {              \r
+                   bool flag1 = false;\r
+                   bool flag2 = false;\r
+\r
+            int ltCnt = 0;\r
+               \r
+                   int charCnt = 0, numCharCnt = 0;\r
+               \r
+                   for(int i = start; i < inText.Length; i++){\r
+                           char c= inText[i];\r
+                           if('>' == c || '>' == c)\r
+                {\r
+                                   if(0 < numCharCnt){\r
+                                           break;\r
+                    }else if(ltCnt > 1){//&lt;は2回まで\r
+                        return -1;\r
+                                   }\r
+                    ltCnt++;\r
+                                   charCnt++;\r
+                           }\r
+                else if (ltCnt == 0)\r
+                {\r
+                    return -1;\r
+                }\r
+                else if ('-' == c)\r
+                {\r
+                    if (!flag1)\r
+                    {\r
+                        charCnt--;\r
+                        break;\r
+                    }\r
+                    else if (flag2)\r
+                    {\r
+                        break;\r
+                    }\r
+                    charCnt++;\r
+                    flag1 = false;\r
+                    flag2 = true;\r
+                    continue;\r
+\r
+                }\r
+                else if (',' == c)\r
+                {\r
+                    if (!flag1)\r
+                    {\r
+                        charCnt--;\r
+                        break;\r
+                    }\r
+                    charCnt++;\r
+                    flag1 = false;\r
+                    continue;\r
+                }\r
+                else\r
+                {\r
+                    flag1 = false;\r
+                    for (int j = 0; j < NUMERIC_2ch.Length; j++)\r
+                    {\r
+                        if (NUMERIC_2ch[j] == c)\r
+                        {\r
+                            flag1 = true;\r
+                            charCnt++;\r
+                            numCharCnt++;\r
+                            break;\r
+                        }\r
+\r
+                    }\r
+                    if (!flag1)\r
+                    {\r
+                        break;\r
+                    }\r
+                }\r
+                   }   \r
+                   return (0 < numCharCnt) ? charCnt : -1;\r
+           }\r
+\r
+        public static int parse2chNum(string inText, int start)\r
+        {\r
+               \r
+                   bool flag1 = false;\r
+                   bool flag2 = false;\r
+               \r
+                   int charCnt = 0, numCharCnt = 0;\r
+               \r
+                   for(int i = start; i < inText.Length; i++){\r
+                           char c= inText[i];\r
+                           if('-' == (c)){\r
+                                   if(0 == charCnt){\r
+                                           return 0;\r
+                                   }else if(!flag1){\r
+                                           charCnt--;\r
+                                           break;\r
+                                   }else if(flag2){\r
+                                           break;\r
+                                   }\r
+                                   charCnt++;\r
+                                   flag1 = false;\r
+                                   flag2 = true;\r
+                                   continue;\r
+                       \r
+                           }else if(',' == c){\r
+                                   if(0 == charCnt){\r
+                                           return 0;\r
+                                   }else if(!flag1){\r
+                                           charCnt--;\r
+                                           break;\r
+                                   }\r
+                                   charCnt++;\r
+                                   flag1 = false;\r
+                                   continue;\r
+                           }else if('>' == c){\r
+                                   if(0 < numCharCnt){\r
+                                           break;\r
+                                   }else if(i != start){\r
+                                           return 0;\r
+                                   }\r
+                                   charCnt++;\r
+                           }else if('>' == c){\r
+                                       if(0 < numCharCnt){\r
+                                           break;\r
+                                   }else if(i != start){\r
+                                           return 0;\r
+                                   }\r
+                                   charCnt++;\r
+                           }else{\r
+                                   flag1 = false;\r
+                                   for(int j = 0; j < NUMERIC_2ch.Length; j++){\r
+                                           if(NUMERIC_2ch[j] == c){\r
+                                                   flag1 = true;\r
+                                                   charCnt++;\r
+                                                   numCharCnt++;\r
+                                                   break;\r
+                                           }\r
+                                       \r
+                                   }\r
+                                   if(0 == charCnt){\r
+                                           return 0;\r
+                                   }else if(!flag1){\r
+                                           break;\r
+                                   }\r
+                           }\r
+                   }\r
+               \r
+                   return (0 < numCharCnt) ? charCnt : 0;\r
+           }\r
+\r
+        public static List<int> parseReferenceNumber(string source)\r
+        {\r
+            List<int> list = new List<int>();\r
+\r
+\r
+            bool fGT = false; //Greater than symbol\r
+            //bool fLT = false; //Less than symbol\r
+            bool fNum = false;// previous char is numeric.\r
+            StringBuilder buf = new StringBuilder();\r
+            int previousNum = -1;\r
+            bool resetPrevChar = false;\r
+\r
+            char prevChar = '\0';\r
+\r
+            for (int i = 0; i < source.Length; i++)\r
+            {\r
+                char c = source[i];\r
+                switch (c)\r
+                {\r
+                    case '-':\r
+                        if (fNum && previousNum == -1)\r
+                        {\r
+                            string s = buf.ToString();\r
+                            buf.Remove(0, buf.Length);\r
+                            try\r
+                            {\r
+                                previousNum = int.Parse(s);\r
+                            }\r
+                            catch (Exception e)\r
+                            {\r
+                                NTDebug.l(e.Message);\r
+                                previousNum = -1;\r
+                            }\r
+                            resetPrevChar = false;\r
+                        }\r
+                        else\r
+                        {\r
+                            resetPrevChar = true;\r
+                            previousNum = -1;\r
+                        }\r
+                        fNum = false;\r
+                        fGT = false;\r
+                        break;\r
+                    case ',':\r
+                        if (fNum)\r
+                        {\r
+                            string s = buf.ToString();\r
+                            buf.Remove(0, buf.Length);\r
+                            int n = 0;// null;\r
+                            try\r
+                            {\r
+                                n = int.Parse(s);\r
+                                if (-1 == previousNum)\r
+                                {\r
+                                    list.Add(n);\r
+                                }\r
+                                else\r
+                                {\r
+                                    int len = n - previousNum;\r
+                                    if (len > 11) { len = -1; }//ignore more than 10 successive references\r
+                                    for (int j = 0; j <= len; j++)\r
+                                    {\r
+                                        list.Add((previousNum + j));\r
+                                    }\r
+                                    previousNum = -1;\r
+                                }\r
+                            }\r
+                            catch (Exception e)\r
+                            {\r
+                                NTDebug.l(e.Message);\r
+                            }\r
+                            fNum = false;\r
+                            resetPrevChar = false;\r
+                        }\r
+                        else\r
+                        {\r
+                            resetPrevChar = true;\r
+                        }\r
+                        fGT = false;\r
+                        break;\r
+                    case '>':\r
+                    case '>':\r
+                        fGT = true;\r
+                        fNum = false;\r
+                        break;\r
+                    default:\r
+                        if (fGT || fNum || (!resetPrevChar && (prevChar == ',' || prevChar == '-')))\r
+                        {\r
+                            int j = 0;\r
+                            for (; j < NUMERIC_2ch.Length; j++)\r
+                            {\r
+                                if (NUMERIC_2ch[j] == c)\r
+                                {\r
+                                    break;\r
+                                }\r
+                            }\r
+                            if (NUMERIC_2ch.Length > j)\r
+                            {\r
+                                fNum = true;\r
+                                if (9 < j)\r
+                                {\r
+                                    c = NUMERIC_2ch[j - 10];\r
+                                }\r
+                                buf.Append(c);\r
+                            }\r
+                            else\r
+                            {\r
+                                if (fNum)\r
+                                {\r
+                                    String s = buf.ToString();\r
+                                    buf.Remove(0, buf.Length);\r
+                                    int n = 0;// null;\r
+                                    try\r
+                                    {\r
+                                        n = int.Parse(s);\r
+                                        if (-1 == previousNum)\r
+                                        {\r
+                                            list.Add(n);\r
+                                        }\r
+                                        else\r
+                                        {\r
+                                            int len = n - previousNum;\r
+                                            if (len > 11) { len = -1; }//ignore more than 10 successive references\r
+                                            for (int k = 0; k <= len; k++)\r
+                                            {\r
+                                                list.Add((previousNum + k));\r
+                                            }\r
+                                            previousNum = -1;\r
+                                        }\r
+                                    }\r
+                                    catch (Exception e) {\r
+                                        NTDebug.l(e.Message);\r
+                                    }\r
+                                }\r
+                                fNum = false;\r
+                            }\r
+                        }\r
+                        fGT = false;\r
+                        break;\r
+                }// end of switch\r
+                prevChar = c;\r
+            }//end of for\r
+            if (fNum)\r
+            {\r
+                string s = buf.ToString();\r
+                //buf.Remove(0, buf.Length);\r
+                int n;\r
+                if (int.TryParse(s, out n))\r
+                {\r
+                    if (previousNum < 0)\r
+                    {\r
+                        list.Add(n);\r
+                    }\r
+                    else\r
+                    {\r
+                        int len = n - previousNum;\r
+                        if (len > 11) { len = -1; }//ignore more than 10 successive references\r
+                        for (int k = 0; k <= len; k++)\r
+                        {\r
+                            list.Add((previousNum + k));\r
+                        }\r
+                    }\r
+                }\r
+            }\r
+            if (list.Count == 0)\r
+            {\r
+                return null;\r
+            }\r
+            return list;\r
+        }\r
+\r
+        public static string formatReferenceNumbers(int[] valList)\r
+        {\r
+            if (null == valList) { return null; }\r
+            if (0 >= valList.Length) { return null; }\r
+\r
+            StringBuilder buf = new StringBuilder();\r
+            buf.Append("<<");\r
+\r
+            bool flagFirst = true;\r
+\r
+            int prevVal = 0;\r
+            int i = 0;\r
+            for (; i < valList.Length - 1; i++)\r
+            {\r
+                int val1 = valList[i];\r
+                int val2 = valList[i + 1];\r
+                if (val1 == val2 - 1)\r
+                {\r
+                    if (0 == prevVal)\r
+                    {\r
+                        prevVal = val1;\r
+                    }\r
+                }\r
+                else\r
+                {\r
+                    if (!flagFirst)\r
+                    {\r
+                        buf.Append(',');\r
+                    }\r
+                    else\r
+                    {\r
+                        flagFirst = false;\r
+                    }\r
+                    if (0 != prevVal)\r
+                    {\r
+                        buf.Append(prevVal.ToString());\r
+                        buf.Append('-');\r
+                        buf.Append(val1.ToString());\r
+                        prevVal = 0;\r
+                    }\r
+                    else\r
+                    {\r
+                        buf.Append(val1.ToString());\r
+                    }\r
+                }\r
+            }\r
+\r
+            if (!flagFirst)\r
+            {\r
+                buf.Append(',');\r
+            }\r
+            if (0 != prevVal)\r
+            {\r
+                buf.Append(prevVal.ToString());\r
+                buf.Append('-');\r
+                buf.Append(valList[i].ToString());\r
+            }\r
+            else\r
+            {\r
+                buf.Append(valList[i].ToString());\r
+            }\r
+\r
+            return buf.ToString();\r
+        }\r
+       \r
+    }\r
+}\r
diff --git a/NT2chView45/NTTextUtiles.cs b/NT2chView45/NTTextUtiles.cs
new file mode 100755 (executable)
index 0000000..27a9786
--- /dev/null
@@ -0,0 +1,256 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Globalization;\r
+using System.IO;\r
+using System.Text;\r
+using NT2chView.NtNet;\r
+\r
+namespace NT2chView\r
+{\r
+    sealed class NTTextUtiles\r
+    {\r
+        public static int[] EMPTY_INT_ARRAY = new int[0];\r
+        public static char[] COMMA_VALUE = { ',' };\r
+        public static char[] LINE_SEPARATOR = { '\n' };\r
+        public static char[] YEN_VALUE = { '\\' };\r
+        public static char[] EQUAL_VALUE = { '=' };\r
+\r
+        static char[] HEX_CHAR_ARR = {\r
+            '0', '1', '2', '3', '4', '5', '6','7', '8','9',\r
+            'A', 'B','C','D','E','F'};\r
+\r
+\r
+\r
+        public static char[] byteToHexChar(char n)\r
+        {\r
+            int upper = ((n & 0xf0) >> 4);\r
+            int lower = n & 0x0f;\r
+            char[] c = new char[2];\r
+            c[0] = HEX_CHAR_ARR[upper];\r
+            c[1] = HEX_CHAR_ARR[lower];\r
+            return c;\r
+\r
+        }\r
+        public static string[] splitLine(string source)\r
+        {\r
+            return source.Split(LINE_SEPARATOR);\r
+        }\r
+\r
+        public static string concatLines(string[] lines)\r
+        {\r
+            bool init = false;\r
+            StringBuilder sb = new StringBuilder();\r
+            foreach (string line in lines)\r
+            {\r
+                if (line.Length == 0)\r
+                    continue;\r
+                if(line.Length == 1 && line[0] == 0x0d)\r
+                    continue;\r
+\r
+                if (!init)\r
+                {\r
+                    init = true;\r
+                }\r
+                else\r
+                {\r
+                    sb.Append(LINE_SEPARATOR);\r
+                }\r
+                int len = line.Length;\r
+                if (line[len - 1] == 0x0d)\r
+                {\r
+                    sb.Append(line.Substring(0, len-1));\r
+                }\r
+                else\r
+                {\r
+                    sb.Append(line);\r
+                }\r
+            }\r
+            return sb.ToString();\r
+        }\r
+        \r
+\r
+        public static string constructCommaSepLineFromInt(int[] numbers)\r
+        {\r
+            if (numbers == null)\r
+                return string.Empty;\r
+\r
+            StringBuilder sb = new StringBuilder(numbers.Length * 4 + 1);\r
+            bool init = false;\r
+            foreach (int n in numbers)\r
+            {\r
+                if (init)\r
+                    sb.Append(',');\r
+                else\r
+                    init = true;\r
+                sb.Append(n);\r
+            }\r
+\r
+            return sb.ToString();\r
+        }\r
+        public static int [] extructCommaSepLineFromInt(string source)\r
+        {\r
+            if (source == null)\r
+                return EMPTY_INT_ARRAY;\r
+\r
+            string [] words = source.Split(COMMA_VALUE);\r
+            int[] retValue = new int[words.Length];\r
+\r
+            try\r
+            {\r
+                for (int i = 0; i < words.Length; i++)\r
+                {\r
+                    retValue[i] = int.Parse(words[i]);\r
+                }\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+                retValue = EMPTY_INT_ARRAY;\r
+            }\r
+\r
+            return retValue;\r
+        }\r
+\r
+\r
+        public static string decodeBase64URL(string source)\r
+        {\r
+            StringBuilder buf = new StringBuilder(128);\r
+            char[] ch = new char[2];\r
+\r
+            if (null == source)\r
+            {\r
+                return string.Empty;\r
+            }\r
+            int len = source.Length;\r
+            for (int i = 0; i < len; i++)\r
+            {\r
+                char c = source[i];\r
+                if ('%' == c && i + 2 < len)\r
+                {\r
+                    ch[0] = source[++i];\r
+                    ch[1] = source[++i];\r
+                    int n = int.Parse(new String(ch), NumberStyles.HexNumber);\r
+                    buf.Append((char)n);\r
+                }\r
+                else\r
+                {\r
+                    buf.Append(c);\r
+                }\r
+            }\r
+\r
+            Encoding enc = Encoding.GetEncoding(NTAppState.HOST_2CH_ENCODING);\r
+            return enc.GetString(Convert.FromBase64String(buf.ToString()));\r
+\r
+        }\r
+\r
+        public static string aesDecodeBase64URL(string source)\r
+        {\r
+            StringBuilder buf = new StringBuilder(128);\r
+            char[] ch = new char[2];\r
+\r
+            if (null == source)\r
+            {\r
+                return string.Empty;\r
+            }\r
+            int len = source.Length;\r
+            for (int i = 0; i < len; i++)\r
+            {\r
+                char c = source[i];\r
+                if ('%' == c && i + 2 < len)\r
+                {\r
+                    ch[0] = source[++i];\r
+                    ch[1] = source[++i];\r
+                    int n = int.Parse(new String(ch), NumberStyles.HexNumber);\r
+                    buf.Append((char)n);\r
+                }\r
+                else\r
+                {\r
+                    buf.Append(c);\r
+                }\r
+            }\r
+            byte[] b = Convert.FromBase64String(buf.ToString());\r
+            MemoryStream byteStream = new MemoryStream(b);\r
+            MemoryStream outStream;\r
+            if (!NTCrypt.DecryptStream(byteStream, out outStream))\r
+                return string.Empty;\r
+            Encoding enc = Encoding.GetEncoding(NTAppState.HOST_2CH_ENCODING);\r
+            string result = enc.GetString(outStream.ToArray());\r
+            outStream.Close();\r
+            return result;\r
+\r
+        }\r
+\r
+        public static string encodeBase64URL(String source)\r
+        {\r
+            string resultStr = string.Empty;\r
+            byte[] b;\r
+            try\r
+            {\r
+                Encoding enc = Encoding.GetEncoding(NTAppState.HOST_2CH_ENCODING);\r
+                b = enc.GetBytes(source);\r
+                string base64Str = Convert.ToBase64String(b);\r
+                resultStr = percentEncode(base64Str);\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+            return resultStr;\r
+\r
+        }\r
+        public static string aesEncodeBase64URL(String source)\r
+        {\r
+            string resultStr = string.Empty;\r
+            byte[] b;\r
+            try\r
+            {\r
+                Encoding enc = Encoding.GetEncoding(NTAppState.HOST_2CH_ENCODING);\r
+                b = enc.GetBytes(source);\r
+\r
+                MemoryStream outStream;\r
+                if(!NTCrypt.EncryptStream(new MemoryStream(b), out outStream))\r
+                    return string.Empty;\r
+                //outStream.Seek(0, SeekOrigin.Begin);\r
+                //int len = (int)outStream.Length;\r
+                byte[] outByte = outStream.ToArray();// new byte[len];\r
+                //int ret = outStream.Read(outByte);\r
+                string base64Str = Convert.ToBase64String(outByte);\r
+                outStream.Close();\r
+                resultStr = percentEncode(base64Str);\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+            return resultStr;\r
+\r
+        }\r
+\r
+        public static string percentEncode(string source)\r
+        {\r
+            StringBuilder result = new StringBuilder(128);\r
+\r
+            for (int i = 0; i < source.Length; i++)\r
+            {\r
+                char nVal = source[i];\r
+\r
+                if (('a' <= nVal && nVal <= 'z') || ('A' <= nVal && nVal <= 'Z') || '0' <= nVal && nVal <= '9')\r
+                {\r
+                    result.Append(nVal);\r
+                        \r
+                }\r
+                else\r
+                {\r
+                    //b = new byte[4];\r
+                    //int len = enc.GetBytes(base64Str,i,1,b,0);\r
+                    //if(len != 1)\r
+                    //    return string.Empty;\r
+                    char[] c = byteToHexChar(nVal);\r
+                    result.Append('%').Append(c);\r
+                }\r
+            }\r
+            return result.ToString();\r
+        }\r
+\r
+    }\r
+}\r
diff --git a/NT2chView45/NTThreadCashData.cs b/NT2chView45/NTThreadCashData.cs
new file mode 100755 (executable)
index 0000000..e6e5bd8
--- /dev/null
@@ -0,0 +1,71 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using NT2chCtrl;\r
+using NT2chView;\r
+using NT2chObject;\r
+\r
+namespace NT2chHistory\r
+{\r
+    class NTThreadCashData : IThreadDescription\r
+    {\r
+           //private const string UNKNOWN_TITLE_DESCRIPTION = "Unknown Title";\r
+           String mDatName;\r
+           String mBoardName;\r
+        NTBoard mBoard;\r
+           String mTitle = null;\r
+           public NTThreadCashData(String boardName, String datName){\r
+                   mBoardName = boardName;\r
+            mBoard = NTDataRoot.getBoardByName(boardName);\r
+                   mDatName = datName;\r
+           }\r
+           public String getDatName(){\r
+                   return mDatName;\r
+           }\r
+           public String getBoardName(){\r
+                   return mBoardName;\r
+           }\r
+        public IBoard getBoard(){return mBoard;}\r
+           public String getTitle(){\r
+                   return mTitle;// != null) ? mTitle : UNKNOWN_TITLE_DESCRIPTION;\r
+           }\r
+           public bool isTitleSet(){\r
+                   return mTitle != null;\r
+           }\r
+           public void setTitle(String title){\r
+                   mTitle = title;\r
+           }\r
+\r
+\r
+           public static string getDescription(IThreadDescription threadDecl){\r
+                   StringBuilder sb = new StringBuilder();\r
+            sb.Append(threadDecl.getDatName()).Append(',').Append(threadDecl.getBoard().getName());\r
+                   return sb.ToString();\r
+           }\r
+       \r
+           public static NTThreadCashData parse(String description){\r
+                   int idx = description.IndexOf(',');\r
+                   if(idx <= 0 || idx >= description.Length)\r
+                           return null;\r
+\r
+                   String datName = description.Substring(0, idx);\r
+                   String boardName = description.Substring(idx+1);\r
+            NTBoard board = NTDataRoot.getBoardByName(boardName);\r
+            if (board == null)\r
+                return null;\r
+\r
+                   NTThreadCashData data = new NTThreadCashData(boardName, datName);\r
+\r
+            NTThreadTitle tt =  board.findThreadTitleByDatName(datName);\r
+            if (tt != null)\r
+            {\r
+                string title = tt.Title;\r
+                if (title != null)\r
+                    data.setTitle(title);\r
+            }\r
+            return data;\r
+               \r
+           }\r
+\r
+    }\r
+}\r
diff --git a/NT2chView45/NTThreadInfoWindow.xaml b/NT2chView45/NTThreadInfoWindow.xaml
new file mode 100755 (executable)
index 0000000..34f96fa
--- /dev/null
@@ -0,0 +1,22 @@
+<Window x:Class="NT2chView.NTThreadInfoWindow"\r
+        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"\r
+        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"\r
+        Title="スレッドの情報" Height="300" Width="480">\r
+    <Grid>\r
+        <Grid.RowDefinitions>\r
+            <RowDefinition Height="Auto" />\r
+            <RowDefinition Height="Auto" />\r
+            <RowDefinition Height="Auto" />\r
+            <RowDefinition Height="Auto" />\r
+            <RowDefinition Height="*" />\r
+            <RowDefinition Height="Auto" />\r
+        </Grid.RowDefinitions>\r
+        <Label>タイトル:</Label>\r
+        <TextBox Grid.Row="1" x:Name="txtTitle" />\r
+        <Label Grid.Row="2">アドレス:</Label>\r
+        <TextBox Grid.Row="3" x:Name="txtAddress" />\r
+        <Button Grid.Row="5" \r
+                Click="ButtonOk_Click"\r
+                HorizontalAlignment="Center" MinWidth="100" Margin="50">OK</Button>\r
+    </Grid>\r
+</Window>\r
diff --git a/NT2chView45/NTThreadInfoWindow.xaml.cs b/NT2chView45/NTThreadInfoWindow.xaml.cs
new file mode 100755 (executable)
index 0000000..648164f
--- /dev/null
@@ -0,0 +1,35 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading.Tasks;\r
+using System.Windows;\r
+using System.Windows.Controls;\r
+using System.Windows.Data;\r
+using System.Windows.Documents;\r
+using System.Windows.Input;\r
+using System.Windows.Media;\r
+using System.Windows.Media.Imaging;\r
+using System.Windows.Shapes;\r
+\r
+namespace NT2chView\r
+{\r
+    /// <summary>\r
+    /// NTThreadInfoWindow.xaml の相互作用ロジック\r
+    /// </summary>\r
+    public partial class NTThreadInfoWindow : Window\r
+    {\r
+        public NTThreadInfoWindow(string title, string address)\r
+        {\r
+            InitializeComponent();\r
+\r
+            txtTitle.Text = title;\r
+            txtAddress.Text = address;\r
+        }\r
+\r
+        private void ButtonOk_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            Close();\r
+        }\r
+    }\r
+}\r
diff --git a/NT2chView45/NTThreadTitle.cs b/NT2chView45/NTThreadTitle.cs
new file mode 100755 (executable)
index 0000000..f62b798
--- /dev/null
@@ -0,0 +1,863 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Windows;\r
+using System.Windows.Documents;\r
+using NT2chView.NtFile;\r
+using NT2chView.NtNet;\r
+using System.Runtime.Remoting.Contexts;\r
+using NT2chCtrl;\r
+using NT2chObject;\r
+\r
+\r
+namespace NT2chView\r
+{\r
+    //[Synchronization]\r
+    public class NTThreadTitle :  NTThread, IThread2\r
+    {\r
+        public string getTitle() { return Title; }\r
+        public IBoard getBoard() { return mBoard; }\r
+        public override string  getDatName() { return mDat; }\r
+        public List<IRes> getResList()\r
+        {\r
+            if(mResList == null || mResList.Count == 0)\r
+                return new List<IRes>();\r
+\r
+            List<IRes> list = new List<IRes>(mResList.Count);\r
+\r
+            foreach (IRes res in mResList)\r
+                list.Add(res);        \r
+            \r
+            return list;\r
+        }\r
+        public int getPrevReadCount()\r
+        {\r
+            return mPrevReadCnt;\r
+        }\r
+        private object mObjExtra;\r
+        public object getExtra() { return mObjExtra; }\r
+        public void setExtra(object o) { mObjExtra = o; }\r
+\r
+        public NTThread getDependencyObject(){ return this; }\r
+\r
+#if false\r
+        //     { "SeqNo", "Title", "ResCnt", "ReadCnt", "RemainCnt","LastMod", "LastWrite" };\r
+        public static readonly DependencyProperty SeqNoProperty;\r
+        public static readonly DependencyProperty TitleProperty;\r
+        public static readonly DependencyProperty ResCntProperty;\r
+        public static readonly DependencyProperty ReadCntProperty;\r
+        public static readonly DependencyProperty RemainCntProperty;\r
+        public static readonly DependencyProperty LastModProperty;\r
+        public static readonly DependencyProperty LastWriteProperty;\r
+\r
+        static NTThreadTitle()\r
+        {\r
+            \r
+            PropertyMetadata pm1 = new PropertyMetadata(0);\r
+            PropertyMetadata pm3 = new PropertyMetadata(0, new PropertyChangedCallback(OnResCntChanged));\r
+            PropertyMetadata pm4 = new PropertyMetadata(0,new PropertyChangedCallback(OnReadCntChanged));\r
+            PropertyMetadata pm5 = new PropertyMetadata(0);\r
+            PropertyMetadata pm2 = new PropertyMetadata(string.Empty);\r
+            PropertyMetadata pm6 = new PropertyMetadata(string.Empty);\r
+            PropertyMetadata pm7 = new PropertyMetadata(string.Empty);\r
+\r
+            SeqNoProperty = DependencyProperty.Register("SeqNo", typeof(int), typeof(NTThreadTitle), pm1);\r
+            TitleProperty = DependencyProperty.Register("Title", typeof(string), typeof(NTThreadTitle), pm2);\r
+            ResCntProperty = DependencyProperty.Register("ResCnt", typeof(int), typeof(NTThreadTitle), pm3);\r
+            ReadCntProperty = DependencyProperty.Register("ReadCnt", typeof(int), typeof(NTThreadTitle), pm4);\r
+            RemainCntProperty = DependencyProperty.Register("RemainCnt", typeof(int), typeof(NTThreadTitle), pm5);\r
+            LastModProperty = DependencyProperty.Register("LastMod", typeof(string), typeof(NTThreadTitle), pm6);\r
+            LastWriteProperty = DependencyProperty.Register("LastWrite", typeof(string), typeof(NTThreadTitle), pm7);\r
+        \r
+        }\r
+#endif\r
+        public NTBoard mBoard;\r
+        public string mDat;\r
+        public int mPrevReadCnt = -1;\r
+        public List<NTRes> mResList = new List<NTRes>();\r
+        public List<int> mWriteNoList = new List<int>();\r
+        public List<int> mBookmarkList = new List<int>();\r
+        public bool mLocalDat = false;\r
+        \r
+        //NTVagueSearchWord mVagueSearch = null;\r
+        //int mSearchSecIndex = 0;\r
+        //int mSearchTextIndex = 0;\r
+\r
+        int mCurrentBookmarkFocus = -1;\r
+\r
+        public string mWroteMsg = string.Empty;\r
+\r
+#if false\r
+        public void SearchWordSet(string sWord)\r
+        {\r
+            if (mVagueSearch == null)\r
+                mVagueSearch = new NTVagueSearchWord(sWord);\r
+            else\r
+                mVagueSearch.setSearchWord(sWord);\r
+\r
+\r
+            //mSearchSecIndex = 0;\r
+           // mSearchTextIndex = 0;\r
+\r
+        }\r
+\r
+\r
+        public Section SearchNext()\r
+        {\r
+\r
+            \r
+            if (mVagueSearch == null)\r
+                return null;\r
+\r
+            int len = mResList.Count;\r
+            if (mSearchSecIndex >= len)\r
+                mSearchSecIndex = 0;\r
+\r
+            for (int i = mSearchSecIndex; i < len; i++)\r
+            {\r
+                NTRes res = mResList[i];\r
+                string text = res.mMsg;\r
+                int outLen;\r
+                int ret = mVagueSearch.match(text, mSearchTextIndex, out outLen);\r
+                if (ret >= 0)\r
+                {\r
+                    Section sec = res.mSection;\r
+                    Paragraph para = sec.Blocks.LastBlock as Paragraph;\r
+                    if (para != null)\r
+                    {\r
+                        para.Inlines.Clear();\r
+                        //NTAppState.getMainWindow().parseResMsg(para, res, ret, outLen);\r
+                    }\r
+                    sec.BringIntoView();\r
+                    mSearchTextIndex = outLen;\r
+                    mSearchSecIndex = i;\r
+                    if (mSearchTextIndex >= text.Length)\r
+                    {\r
+                        mSearchSecIndex++;\r
+                        mSearchTextIndex = 0;\r
+                    }\r
+                    return sec;\r
+                }\r
+                mSearchTextIndex = 0;\r
+            }\r
+            for (int i = 0; i < mSearchSecIndex; i++)\r
+            {\r
+                NTRes res = mResList[i];\r
+                string text = res.mMsg;\r
+                int outLen;\r
+                int ret = mVagueSearch.match(text, mSearchTextIndex, out outLen);\r
+                if (ret >= 0)\r
+                {\r
+                    Section sec = res.mSection;\r
+                    Paragraph para = sec.Blocks.LastBlock as Paragraph;\r
+                    if (para != null)\r
+                    {\r
+                        para.Inlines.Clear();\r
+                        //NTAppState.getMainWindow().parseResMsg(para, res, ret, outLen);\r
+                    }\r
+                    sec.BringIntoView();\r
+                    mSearchTextIndex = outLen;\r
+                    mSearchSecIndex = i;\r
+                    if (mSearchTextIndex >= text.Length)\r
+                    {\r
+                        mSearchSecIndex++;\r
+                        mSearchTextIndex = 0;\r
+                    }\r
+                    return sec;\r
+                }\r
+                mSearchTextIndex = 0;\r
+            }\r
+            mSearchSecIndex = 0;\r
+            mSearchTextIndex = 0;\r
+            return null;\r
+        }\r
+\r
+        public Section SearchPrev()\r
+        {\r
+            if (mVagueSearch == null)\r
+                return null;\r
+\r
+            int len = mResList.Count;\r
+            if (mSearchSecIndex < 0)\r
+                mSearchSecIndex = len - 1;\r
+\r
+            for (int i = mSearchSecIndex; i >= 0; i--)\r
+            {\r
+                NTRes res = mResList[i];\r
+                string text = res.mMsg;\r
+                int outLen;\r
+                int ret = mVagueSearch.match(text, mSearchTextIndex, out outLen);\r
+                if (ret >= 0)\r
+                {\r
+                    Section sec = res.mSection;\r
+                    Paragraph para = sec.Blocks.LastBlock as Paragraph;\r
+                    if (para != null)\r
+                    {\r
+                        para.Inlines.Clear();\r
+                        //NTAppState.getMainWindow().parseResMsg(para, res, ret, outLen);\r
+                    }\r
+                    sec.BringIntoView();\r
+                    mSearchTextIndex = outLen;\r
+                    mSearchSecIndex = i;\r
+                    if (mSearchTextIndex >= text.Length)\r
+                    {\r
+                        mSearchSecIndex--;\r
+                        mSearchTextIndex = 0;\r
+                    }\r
+                    return sec;\r
+                }\r
+                mSearchTextIndex = 0;\r
+            }\r
+            for (int i = len - 1; i > mSearchSecIndex; i--)\r
+            {\r
+                NTRes res = mResList[i];\r
+                string text = res.mMsg;\r
+                int outLen;\r
+                int ret = mVagueSearch.match(text, mSearchTextIndex, out outLen);\r
+                if (ret >= 0)\r
+                {\r
+                    Section sec = res.mSection;\r
+                    Paragraph para = sec.Blocks.LastBlock as Paragraph;\r
+                    if (para != null)\r
+                    {\r
+                        para.Inlines.Clear();\r
+                        //NTAppState.getMainWindow().parseResMsg(para, res, ret, outLen);\r
+                    }\r
+                    sec.BringIntoView();\r
+                    mSearchTextIndex = outLen;\r
+                    mSearchSecIndex = i;\r
+                    if (mSearchTextIndex >= text.Length)\r
+                    {\r
+                        mSearchSecIndex--;\r
+                        mSearchTextIndex = 0;\r
+                    }\r
+                    return sec;\r
+                }\r
+                mSearchTextIndex = 0;\r
+            }\r
+            mSearchSecIndex = len -1;\r
+            mSearchTextIndex = 0;\r
+            return null;\r
+        }\r
+\r
+#endif\r
+\r
+        public void clearLoadedDat()\r
+        {\r
+            mResList.Clear();\r
+            mWriteNoList.Clear();\r
+            mBookmarkList.Clear();\r
+            LastMod = string.Empty;\r
+            LastWrite = string.Empty;\r
+            ReadCnt = 0;\r
+        }\r
+\r
+        public void delDat()\r
+        {\r
+           \r
+\r
+            //MainWindow wnd = NTAppState.getMainWindow();\r
+            //wnd.removeThreadFromTabCtrl(this);\r
+\r
+            clearLoadedDat();\r
+\r
+            NTFileAccess.deleteDatDir(mBoard.mName, mDat);\r
+\r
+            Thread th = new Thread(delDat_Worker);\r
+            string[] s = new string[2];\r
+            s[0] = mBoard.mName;\r
+            s[1] = mDat;\r
+            th.Start(s);\r
+\r
+        }\r
+\r
+        static void delDat_Worker(object o)\r
+        {\r
+            string[] s = o as string[];\r
+            if (s == null)\r
+                return;\r
+\r
+            string result = NTHttpAccess.ntDeleteDatValue(s[0], s[1]);\r
+            NTDebug.l(result);\r
+\r
+        }\r
+\r
+#if false\r
+        static void OnResCntChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)\r
+        {\r
+            NTThreadTitle tt = (NTThreadTitle)d;\r
+            tt.RemainCnt = (int)e.NewValue - tt.ReadCnt;\r
+        }\r
+\r
+        static void OnReadCntChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)\r
+        {\r
+            NTThreadTitle tt = (NTThreadTitle)d;\r
+            if(tt.ResCnt < (int)e.NewValue)\r
+                tt.ResCnt = (int)e.NewValue;\r
+            else\r
+                tt.RemainCnt = tt.ResCnt - (int)e.NewValue;\r
+        }\r
+#endif\r
+\r
+        public NTRes findResById(string id)\r
+        {\r
+            if ("???".Equals(id))\r
+                return null;\r
+            foreach (NTRes res in mResList)\r
+            {\r
+                if (id.Equals(res.mId))\r
+                    return res;\r
+            }\r
+            return null;\r
+        }\r
+\r
+\r
+        public NTThreadTitle(NTBoard board)\r
+            : this(board, false)\r
+        {\r
+        }\r
+        \r
+        public NTThreadTitle(NTBoard board, bool localDat)\r
+        {\r
+            mBoard = board;\r
+            mLocalDat = localDat;\r
+        }\r
+\r
+        \r
+\r
+#if false\r
+        public int SeqNo\r
+        {\r
+            set { SetValue(SeqNoProperty, value); }\r
+            get { return (int)GetValue(SeqNoProperty); }\r
+        }\r
+        public string Title\r
+        {\r
+            set { SetValue(TitleProperty, value); }\r
+            get { return (string)GetValue(TitleProperty); }\r
+        }\r
+        public int ResCnt\r
+        {\r
+            set { SetValue(ResCntProperty, value); }\r
+            get { return (int)GetValue(ResCntProperty); }\r
+        }\r
+        public int ReadCnt\r
+        {\r
+            set { SetValue(ReadCntProperty, value); }\r
+            get { return (int)GetValue(ReadCntProperty); }\r
+        }\r
+        public int RemainCnt\r
+        {\r
+            set { SetValue(RemainCntProperty, value); }\r
+            get { return (int)GetValue(RemainCntProperty); }\r
+        }\r
+        public string LastMod\r
+        {\r
+            set { SetValue(LastModProperty, value); }\r
+            get { return (string)GetValue(LastModProperty); }\r
+        }\r
+        public string LastWrite\r
+        {\r
+            set { SetValue(LastWriteProperty, value); }\r
+            get { return (string)GetValue(LastWriteProperty); }\r
+        }\r
+#endif    \r
+\r
+       // static char[] LINE_BREAK = { '\n' };\r
+        const string COLUMN_BREAK = "<>";\r
+\r
+        public void parseMachiBBSDat(string source)\r
+        {\r
+            mResList.Clear();\r
+\r
+            string [] lines = NTTextUtiles.splitLine(source);//.Split(LINE_BREAK);\r
+            int n = 1;\r
+            foreach (string line in lines)\r
+            {\r
+                int n0 = line.IndexOf(COLUMN_BREAK);\r
+                if (n0 < 0)\r
+                    continue;\r
+                int n1 = line.IndexOf(COLUMN_BREAK, n0 + COLUMN_BREAK.Length);\r
+                if (n1 < 0)\r
+                    continue;\r
+                int n2 = line.IndexOf(COLUMN_BREAK, n1 + COLUMN_BREAK.Length);\r
+                if (n2 < 0)\r
+                    continue;\r
+                int n3 = line.IndexOf(COLUMN_BREAK, n2 + COLUMN_BREAK.Length);\r
+                if (n3 < 0)\r
+                    continue;\r
+                int n4 = line.IndexOf(COLUMN_BREAK, n3 + COLUMN_BREAK.Length);\r
+                if (n4 < 0)\r
+                    continue;\r
+                string seqNoStr = line.Substring(0, n0);\r
+                int seqNo;\r
+                if (!int.TryParse(seqNoStr, out seqNo))\r
+                {\r
+                    seqNo = n;\r
+                }\r
+                if (seqNo > n)\r
+                {\r
+                    for (int i = n; n < seqNo; n++)\r
+                    {\r
+                        NTRes dummy = new NTRes(this, n, string.Empty, string.Empty, string.Empty, string.Empty);\r
+                        dummy.mIsDummy = true;\r
+                        mResList.Add(dummy);\r
+                    }\r
+                }\r
+                string name = line.Substring(n0+2, n1-(n0+2)).Trim();\r
+                string mail = line.Substring(n1 + 2, n2 - (n1 + 2)).Trim();\r
+                string date_id = line.Substring(n2 + 2, n3 - (n2 + 2)).Trim();\r
+                string msg = line.Substring(n3 + 2, n4 - (n3 + 2));//.Trim();\r
+                NTRes res = new NTRes(this, seqNo, name, mail, date_id, msg);\r
+                n++;\r
+                mResList.Add(res);\r
+            }\r
+\r
+            ReadCnt = mResList.Count;\r
+            RemainCnt =  ResCnt - ReadCnt;\r
+\r
+            constructResRelations(mResList);\r
+\r
+        }\r
+\r
+        //static object mLockParseDat = new object();//TEST 2012-11-22\r
+\r
+        public void parseDat(string source)\r
+        {\r
+            //lock (mLockParseDat)//TEXT 2012-11-22\r
+            //{\r
+                if (mBoard.mMachiBBS)\r
+                {\r
+                    parseMachiBBSDat(source);\r
+                    return;\r
+                }\r
+                mResList.Clear();\r
+\r
+                string[] lines = NTTextUtiles.splitLine(source);//.Split(LINE_BREAK);\r
+                int n = 1;\r
+                foreach (string line in lines)\r
+                {\r
+                    int n1 = line.IndexOf(COLUMN_BREAK);\r
+                    if (n1 < 0)\r
+                        continue;\r
+                    int n2 = line.IndexOf(COLUMN_BREAK, n1 + COLUMN_BREAK.Length);\r
+                    if (n2 < 0)\r
+                        continue;\r
+                    int n3 = line.IndexOf(COLUMN_BREAK, n2 + COLUMN_BREAK.Length);\r
+                    if (n3 < 0)\r
+                        continue;\r
+                    int n4 = line.IndexOf(COLUMN_BREAK, n3 + COLUMN_BREAK.Length);\r
+                    if (n4 < 0)\r
+                        continue;\r
+\r
+                    string name = line.Substring(0, n1).Trim();\r
+                    string mail = line.Substring(n1 + 2, n2 - (n1 + 2)).Trim();\r
+                    string date_id = line.Substring(n2 + 2, n3 - (n2 + 2)).Trim();\r
+                    string msg = line.Substring(n3 + 2, n4 - (n3 + 2));//.Trim();\r
+                    NTRes res = new NTRes(this, n++, name, mail, date_id, msg);\r
+\r
+                    mResList.Add(res);\r
+                }\r
+\r
+                ReadCnt = mResList.Count;\r
+                RemainCnt = ResCnt - ReadCnt;\r
+\r
+                constructResRelations(mResList);\r
+           //}//TEST 2012-11-22\r
+\r
+        }\r
+        \r
+        public void queryThreadAttrFromCloud()\r
+        {\r
+\r
+        }\r
+\r
+        public int findWroteMsg(int startSeqNo)\r
+        {\r
+            if(mWroteMsg == null || mWroteMsg.Length == 0)\r
+                return -1;\r
+\r
+            string target = mWroteMsg.Trim().Replace("\r\n", " <br> ");\r
+            mWroteMsg = string.Empty;\r
+\r
+            int len = mResList.Count;\r
+            int i = startSeqNo - 1;\r
+            for( ; i < len; i++)\r
+            {\r
+                NTRes res = mResList[i];\r
+                string msg = res.mMsg.Trim();\r
+                if (target.Equals(msg))\r
+                {\r
+                    //mWroteMsg = string.Empty;\r
+                    res.mWroteMsg = true;\r
+                    return res.mSeqNo;\r
+                }\r
+            }\r
+            return -1;\r
+        }\r
+\r
+        public NTRes findRes(int seqNo)\r
+        {\r
+            foreach (NTRes res in mResList)\r
+            {\r
+                if (res.mSeqNo == seqNo)\r
+                    return res;\r
+            }\r
+            return null;\r
+        }\r
+\r
+        public void updateReadCntOnCloud()\r
+        {\r
+            if (!NTUserPreference.NTCloudIsEnabled)\r
+                return;\r
+\r
+            Thread th = new Thread(updateReadCntOnCloud_Worker);\r
+            string[] arr = new string[3];\r
+            arr[0] = mBoard.mName;\r
+            arr[1] = mDat;\r
+            arr[2] = ReadCnt.ToString();\r
+            th.Start(arr);\r
+        }\r
+\r
+        static void updateReadCntOnCloud_Worker(object o)\r
+        {\r
+            string [] sArr = o as string[];\r
+            if (sArr == null)\r
+                return;\r
+            string attrType;\r
+            if (NTUserPreference.AESEnabled)\r
+                attrType = "4";\r
+            else\r
+                attrType = "1";\r
+\r
+            string result;\r
+            if (NTUserPreference.NTUserCloudIsEnabled)\r
+            {\r
+                result = NTHttpAccess.UserCloudUpdateReadCount(\r
+                    sArr[0], sArr[1], attrType/*"1"*/, sArr[2]);\r
+            }\r
+            else\r
+            {\r
+                result = NTHttpAccess.ntUpdateAttrValue(\r
+                    sArr[0], sArr[1], attrType/*"1"*/, sArr[2]);\r
+            }\r
+            if (result != null)\r
+                NTDebug.l(result);\r
+        }\r
+\r
+        public void addWriteTagOnCloud(int SeqNo)\r
+        {\r
+            if (!NTUserPreference.NTCloudIsEnabled)\r
+                return;\r
+\r
+            Thread th = new Thread(addWriteTagOnCloud_Worker);\r
+            string[] arr = new string[3];\r
+            arr[0] = mBoard.mName;\r
+            arr[1] = mDat;\r
+            arr[2] = SeqNo.ToString();\r
+            th.Start(arr);\r
+        }\r
+\r
+        public void addBookmarkOnCloud(int SeqNo)\r
+        {\r
+            if (!NTUserPreference.NTCloudIsEnabled)\r
+                return;\r
+\r
+            Thread th = new Thread(addBookmarkOnCloud_Worker);\r
+            string[] arr = new string[3];\r
+            arr[0] = mBoard.mName;\r
+            arr[1] = mDat;\r
+            arr[2] = SeqNo.ToString();\r
+            th.Start(arr);\r
+        }\r
+\r
+        public void removeBookmarkOnCloud(int SeqNo)\r
+        {\r
+            if (!NTUserPreference.NTCloudIsEnabled)\r
+                return;\r
+\r
+            Thread th = new Thread(removeBookmarkOnCloud_Worker);\r
+            string[] arr = new string[3];\r
+            arr[0] = mBoard.mName;\r
+            arr[1] = mDat;\r
+            arr[2] = SeqNo.ToString();\r
+            th.Start(arr);\r
+        }\r
+\r
+        static void addWriteTagOnCloud_Worker(object o)\r
+        {\r
+            string[] sArr = o as string[];\r
+            if (sArr == null)\r
+                return;\r
+\r
+            string attrType;\r
+            if (NTUserPreference.AESEnabled)\r
+                attrType = "5";\r
+            else\r
+                attrType = "2";\r
+            string result;\r
+            if (NTUserPreference.NTUserCloudIsEnabled)\r
+            {\r
+                result = NTHttpAccess.UserCloudUpdateAttrValue(\r
+                    sArr[0], sArr[1], attrType, sArr[2]);\r
+            }\r
+            else\r
+            {\r
+                result = NTHttpAccess.ntUpdateAttrValue(\r
+                    sArr[0], sArr[1], attrType/*"2"*/, sArr[2]);\r
+            }\r
+            if (result != null)\r
+                NTDebug.l(result);\r
+        }\r
+\r
+\r
+        static void addBookmarkOnCloud_Worker(object o)\r
+        {\r
+            string[] sArr = o as string[];\r
+            if (sArr == null)\r
+                return;\r
+\r
+            string attrType;\r
+            if (NTUserPreference.AESEnabled)\r
+                attrType = "6";\r
+            else\r
+                attrType = "3";\r
+            string result;\r
+            if (NTUserPreference.NTUserCloudIsEnabled)\r
+            {\r
+                result = NTHttpAccess.UserCloudUpdateAttrValue(\r
+                    sArr[0], sArr[1], attrType, sArr[2]);\r
+            }\r
+            else\r
+            {\r
+                result = NTHttpAccess.ntUpdateAttrValue(\r
+                    sArr[0], sArr[1], attrType/*"3"*/, sArr[2]);\r
+            }\r
+            if (result != null)\r
+                NTDebug.l(result);\r
+        }\r
+\r
+\r
+\r
+        static void removeBookmarkOnCloud_Worker(object o)\r
+        {\r
+            string[] sArr = o as string[];\r
+            if (sArr == null)\r
+                return;\r
+            string attrType;\r
+            if (NTUserPreference.AESEnabled)\r
+                attrType = "6";\r
+            else\r
+                attrType = "3";\r
+\r
+            string result;\r
+            if (NTUserPreference.NTUserCloudIsEnabled)\r
+            {\r
+                result = NTHttpAccess.UserCloudDeleteAttrValue(\r
+                    sArr[0], sArr[1], attrType, sArr[2]);\r
+            }\r
+            else\r
+            {\r
+                result = NTHttpAccess.ntDeleteAttrValue(\r
+                    sArr[0], sArr[1], attrType/*"3"*/, sArr[2]);\r
+            }\r
+\r
+            if (result != null)\r
+                NTDebug.l(result);\r
+        }\r
+        void constructResRelations(List<NTRes> resList)\r
+        {\r
+            foreach (NTRes res in resList)\r
+            {\r
+                int[] arr = res.mRefferTo;\r
+                if (arr != null)\r
+                {\r
+                    foreach (int n in arr)\r
+                    {\r
+                        if (n <= resList.Count && n > 0)\r
+                        {\r
+                            resList[n - 1].mRefferFrom.Add(res.mSeqNo);\r
+                        }\r
+                    }\r
+                }\r
+            }\r
+        }\r
+\r
+        public void setupBookmark()\r
+        {\r
+            foreach(NTRes res in mResList)\r
+            {\r
+                foreach(int n in mBookmarkList)\r
+                {\r
+                    if(res.mSeqNo == n)\r
+                    {\r
+                        res.mBookmark = true;\r
+                        break;\r
+                    }\r
+                }\r
+            }\r
+        }\r
+\r
+        public void setupWriteTag()\r
+        {\r
+            foreach (NTRes res in mResList)\r
+            {\r
+                foreach (int n in mWriteNoList)\r
+                {\r
+                    if (res.mSeqNo == n)\r
+                    {\r
+                        res.mWroteMsg = true;\r
+                        if (res.mRefferFrom != null)\r
+                        {\r
+                            foreach (int n2 in res.mRefferFrom)\r
+                            {\r
+                                NTRes res2 = findRes(n2);\r
+                                if (res2 != null)\r
+                                {\r
+                                    res2.mIsRepray = true;\r
+                                }\r
+                            }\r
+                        }\r
+                        break;\r
+                    }\r
+                }\r
+            }\r
+        }\r
+\r
+        \r
+        public void addWriteTag(int seqNo)\r
+        {\r
+            if (mWriteNoList.Contains(seqNo))\r
+                return;\r
+\r
+            mWriteNoList.Add(seqNo);\r
+            /*int numRead;\r
+            int[] writes;\r
+            int[] bookmarkes;\r
+            string lastWrite;\r
+\r
+            NTFileAccess.retrieveDatAttrToFile(mBoard.mName, mDat,\r
+                out numRead, out writes, out bookmarkes, out lastWrite);\r
+\r
+            NTFileAccess.storeDatAttrToFile(mBoard.mName, mDat,\r
+                numRead, mWriteNoList.ToArray(), bookmarkes);\r
+            */\r
+            addWriteTagOnCloud(seqNo);\r
+\r
+        }\r
+        public void addBookmark(int seqNo)\r
+        {\r
+            if (mBookmarkList.Contains(seqNo))\r
+                return;\r
+\r
+            mBookmarkList.Add(seqNo);\r
+            int numRead;\r
+            int[] writes;\r
+            int[] bookmarkes;\r
+            string lastWrite;\r
+\r
+            NTFileAccess.retrieveDatAttrToFile(mBoard.mName, mDat,\r
+                out numRead, out writes, out bookmarkes, out lastWrite);\r
+\r
+            NTFileAccess.storeDatAttrToFile(mBoard.mName, mDat,\r
+                numRead, writes, mBookmarkList.ToArray());\r
+\r
+            addBookmarkOnCloud(seqNo);\r
+\r
+        }\r
+        public void removeBookmark(int seqNo)\r
+        {\r
+            int numRead;\r
+            int[] writes;\r
+            int[] bookmarkes;\r
+            string lastWrite;\r
+\r
+            NTFileAccess.retrieveDatAttrToFile(mBoard.mName, mDat,\r
+                out numRead, out writes, out bookmarkes, out lastWrite);\r
+            for (int i = 0; i < mBookmarkList.Count; i++)\r
+            {\r
+                int num = mBookmarkList[i];\r
+                if (seqNo == num)\r
+                {\r
+                    mBookmarkList.RemoveAt(i);\r
+                    i--;\r
+                }\r
+            }\r
+\r
+            NTFileAccess.storeDatAttrToFile(mBoard.mName, mDat, numRead, writes, mBookmarkList.ToArray());\r
+\r
+            removeBookmarkOnCloud(seqNo);\r
+\r
+        }\r
+\r
+        public void FocusNextBookmark()\r
+        {\r
+            if (0 == mBookmarkList.Count)\r
+                return;\r
+\r
+            mCurrentBookmarkFocus++;\r
+\r
+            if (mCurrentBookmarkFocus >= mBookmarkList.Count)\r
+                mCurrentBookmarkFocus = 0;\r
+\r
+            int seqNo = mBookmarkList[mCurrentBookmarkFocus];\r
+            foreach (NTRes res in mResList)\r
+            {\r
+                if (res.mSeqNo == seqNo)\r
+                {\r
+                    Section sec = res.mSection;\r
+                    if (sec != null)\r
+                        sec.BringIntoView();\r
+                    break;\r
+                }\r
+            }\r
+        }\r
+\r
+        public void parseAttr(string strAttr)\r
+        {\r
+            if (strAttr == null || strAttr.Length == 0)\r
+                return;\r
+\r
+            string[] lines = NTTextUtiles.splitLine(strAttr);\r
+            int len = lines.Length;\r
+            if (len == 0)\r
+                return;\r
+            int result;\r
+            if (!int.TryParse(lines[0], out result))\r
+                return;\r
+            if (100 != result)\r
+                return;\r
+\r
+            for (int i = 2; i < len; i++)\r
+            {\r
+                string[] values = lines[i].Split(NTTextUtiles.EQUAL_VALUE);\r
+                if (values.Length != 2)\r
+                    continue;\r
+                switch (values[0])\r
+                {\r
+                    case "1":\r
+                    case "4":\r
+                        int num;\r
+                        if (int.TryParse(values[1], out num))\r
+                            ReadCnt = num;\r
+                        break;\r
+                    case "2":\r
+                    case "5":\r
+                        if (int.TryParse(values[1], out num))\r
+                            mWriteNoList.Add(num);\r
+                        break;\r
+                    case "3":\r
+                    case "6":\r
+                        if (int.TryParse(values[1], out num))\r
+                            mBookmarkList.Add(num);\r
+                        break;\r
+                }\r
+            }\r
+        }\r
+        \r
+\r
+\r
+\r
+    }\r
+}\r
diff --git a/NT2chView45/NTUserPreference.cs b/NT2chView45/NTUserPreference.cs
new file mode 100755 (executable)
index 0000000..b2fb2d1
--- /dev/null
@@ -0,0 +1,1039 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using NT2chView.NtFile;\r
+using NT2chCtrl;\r
+using NT2chView.NtNet;\r
+using NT2chObject;\r
+using NT2chView.NtUI;\r
+\r
+namespace NT2chView\r
+{\r
+    static class NTUserPreference\r
+    {\r
+        const string KEY_DEBUG_OPTION = "debug_option";\r
+        const string KEY_P2ID = "p2id";\r
+        const string KEY_P2PASS = "p2pass";\r
+        const string KEY_P2ENABLE = "p2enable";\r
+        const string KEY_MARUID = "maru_id";\r
+        const string KEY_MARUPASS = "maru_pass";\r
+        const string KEY_MARUENABLE = "maru_enable";\r
+        const string KEY_NTCLOUDID = "ntcloud_id";\r
+        const string KEY_NTCLOUDPASS = "ntcloud_pass";\r
+        const string KEY_NTCLOUDENABLE = "ntcloud_enable";\r
+        const string KEY_NTCLOUDURL = "ntcloud_url";\r
+        const string KEY_NTUSERCLOUDENABLE = "nt_usercloud_enable";\r
+        const string KEY_NTUSERCLOUD_SEED = "nt_usercloud_seed";\r
+        const string KEY_NTUSERCLOUDURL = "nt_usercloud_url";\r
+        const string KEY_NTUSERCLOUDSCRIPTURL = "nt_usercloud_script_url";\r
+        const string KEY_NTUSERCLOUDFILEURL = "nt_usercloud_file_url";\r
+        const string KEY_WRITE_SAGE = "sage";\r
+        const string KEY_ZOOM_VALUE = "zoom";\r
+        const string KEY_WINDOW_MAXIMIZED = "window_maximized";\r
+        const string KEY_RESVIEW_TOOLBAR_POSITION = "resview_toolbar_position";\r
+        const string KEY_THREADTITLEVIEW_TOOLBAR_POSITION = "threadtitleview_toolbar_position";\r
+        const string KEY_WINDOW_HEIGHT = "window_height";\r
+        const string KEY_WINDOW_WIDTH = "window_width";\r
+        const string KEY_WINDOW_TOP = "window_top";\r
+        const string KEY_WINDOW_LEFT = "window_left";\r
+        const string KEY_WINDOW_COLUMN1 = "window_column1";\r
+        const string KEY_WINDOW_ROW1 = "window_row1";\r
+        const string KEY_WINDOW_LEFT_PANEL_ROW1 = "window_left_panel_row1";\r
+        const string KEY_NT_SHOW_ONLY_CLOUD_READ_COUNT = "nt_only_cloud_read_count";\r
+        const string KEY_USE_RES_FONT = "use_explicit_res_font";\r
+        const string KEY_RES_FONT_TYPEFACE = "res_font_name";\r
+        const string KEY_USE_AA_FONT = "use_explicit_aa_font";\r
+        const string KEY_AA_FONT_TYPEFACE = "aa_font_name";\r
+        const string KEY_AESPASS = "aes_pass";\r
+        const string KEY_AESENABLE = "aes_enable";\r
+        const string KEY_POPUPENABLE_MOUSEHOVER = "mousehover_enable";\r
+        const string KEY_OPEN_YOUTUBE_ON_APP = "open_youtube_on_app";\r
+        const string KEY_RESVIEW_SHOW_THUMBNAIL = "resview_show_thumbnail";\r
+        const string KEY_RESVIEW_THUMBNAIL_WIDTH = "resview_thumbnail_width";\r
+        const string KEY_RESVIEW_THUMBNAIL_HEIGHT = "resview_thumbnail_height";\r
+        const string KEY_RESVIEW_THUMBNAIL_CONNECTION_COUNT = "resview_thumbnail_connection_count";\r
+        const string KEY_RESVIEW_TEXTSEL_MODE = "resview_textsel_mode";\r
+        const string KEY_THREADTITLE_LISTVIEW_FONTSIZE = "threadtitle_listview_fontsize";\r
+        //const string KEY_IMAGE_VIEW_WIDTH = "imageview_width";\r
+        //const string KEY_IMAGE_VIEW_HEIGHT = "imageview_height";\r
+        const string KEY_FAVORITE_UPDATE_DURATION = "favorite_update_duration";\r
+        public const int DEFAULT_FAVORITE_UPDATE_DURATION = 10;\r
+\r
+\r
+        public static bool DebugOption\r
+        {\r
+            get\r
+            {\r
+                object o;\r
+                if (mDictExportPreference.TryGetValue(PREF_PARAM.DEGUB_MODE, out o))\r
+                {\r
+                    bool? b = o as bool?;\r
+                    if (b == null)\r
+                        return false;\r
+                    return (bool)b;\r
+                }\r
+                else\r
+                {\r
+                    return false;\r
+                }\r
+            }\r
+            set\r
+            {\r
+                mDictExportPreference.Remove(PREF_PARAM.DEGUB_MODE);\r
+                mDictExportPreference.Add(\r
+                    PREF_PARAM.DEGUB_MODE, value);\r
+\r
+            }\r
+        }\r
+\r
+        public static int FavoriteUpdateDuration\r
+        {\r
+            get;\r
+            set;\r
+        }\r
+\r
+        static bool mResViewTextSelMode;\r
+        public static bool ResViewTextSelMode {\r
+            get\r
+            {\r
+#if DOTNET45\r
+                return mResViewTextSelMode;\r
+#else\r
+                return true;\r
+#endif\r
+            }\r
+            set\r
+            {\r
+                mResViewTextSelMode = value;\r
+                mDictExportPreference.Remove(PREF_PARAM.RES_VIEW_TEXTSEL_MODE);\r
+                mDictExportPreference.Add(\r
+                    PREF_PARAM.RES_VIEW_TEXTSEL_MODE, mResViewTextSelMode);\r
+\r
+            }\r
+        }\r
+\r
+        private static int mResViewThumbnailConnectionCount;\r
+        private static int mResViewThumbnailHeight;\r
+        private static int mResViewThumbnailWidth;\r
+        private static bool mResViewShowThumbnail;\r
+\r
+        //public static int ImageViewWidth { get; set; }\r
+        //public static int ImageViewHeight { get; set; }\r
+        public static int ResViewThumbnailConnectionCount\r
+        {\r
+            get\r
+            {\r
+                return mResViewThumbnailConnectionCount;\r
+            }\r
+            set\r
+            {\r
+                if (value < 1)\r
+                    mResViewThumbnailConnectionCount = 1;\r
+                else if (value > 20)\r
+                    mResViewThumbnailConnectionCount = 20;\r
+                else\r
+                    mResViewThumbnailConnectionCount = value;\r
+                NTExportUtil.Worker.resetConnectionCount(\r
+                    mResViewThumbnailConnectionCount);\r
+            }\r
+        }\r
+        public static int ResViewThumbnailWidth\r
+        {\r
+            get\r
+            {\r
+                return mResViewThumbnailWidth;\r
+            }\r
+            set\r
+            {\r
+                mResViewThumbnailWidth = value;\r
+                mDictExportPreference.Remove(PREF_PARAM.RES_VIEW_THUMBNAIL_WIDTH);\r
+                mDictExportPreference.Add(\r
+                    PREF_PARAM.RES_VIEW_THUMBNAIL_WIDTH, ResViewThumbnailWidth);\r
+            }\r
+        }\r
+        public static int ResViewThumbnailHeight\r
+        { \r
+            get\r
+            {\r
+                return mResViewThumbnailHeight;\r
+            }\r
+            set\r
+            {\r
+                mResViewThumbnailHeight = value;\r
+                mDictExportPreference.Remove(PREF_PARAM.RES_VIEW_THUMBNAIL_HEIGHT);\r
+                mDictExportPreference.Add(\r
+                    PREF_PARAM.RES_VIEW_THUMBNAIL_HEIGHT, ResViewThumbnailHeight);\r
+            }\r
+        }\r
+        public static bool ResViewShowThumbnail\r
+        {\r
+            get\r
+            {\r
+                return mResViewShowThumbnail;\r
+            }\r
+            set\r
+            {\r
+                mResViewShowThumbnail = value;\r
+                mDictExportPreference.Remove(PREF_PARAM.RES_VIEW_SHOW_THUMBNAIL);\r
+                mDictExportPreference.Add(\r
+                    PREF_PARAM.RES_VIEW_SHOW_THUMBNAIL, mResViewShowThumbnail.ToString());\r
+             }\r
+        }\r
+\r
+\r
+        static bool mP2Enabled;\r
+        static bool mMaruEnabled;\r
+        static bool mNTCloudEnabled;\r
+        static bool mNTUserCloudEnabled;\r
+        static bool mSage;\r
+        static double mZoom;\r
+        static bool mShowCloudReadCnt;\r
+        static bool mUseExplicitResFont;\r
+        static bool mUseExplicitAAFont;\r
+\r
+        static bool mAvoidSaveToPreferenceFile = false;\r
+\r
+        static string[] mAADataText;\r
+\r
+        static Dictionary<PREF_PARAM, object> mDictExportPreference\r
+            = new Dictionary<PREF_PARAM, object>();\r
+        public static Dictionary<PREF_PARAM, object> getExportPreference()\r
+        {\r
+            return mDictExportPreference;\r
+        }\r
+\r
+        public static string[] AAData\r
+        {\r
+            get { return mAADataText; }\r
+            set \r
+            { \r
+                mAADataText = value;\r
+\r
+                if (mDictExportPreference.ContainsKey(PREF_PARAM.RES_VIEW_AA_STRING_LIST))\r
+                    mDictExportPreference.Remove(PREF_PARAM.RES_VIEW_AA_STRING_LIST);\r
+                \r
+                mDictExportPreference.Add(\r
+                        PREF_PARAM.RES_VIEW_AA_STRING_LIST, mAADataText);\r
+                \r
+            }\r
+        }\r
+\r
+\r
+        const string VALUE_STRING_TRUE = "True";\r
+        const string VALUE_STRING_FALSE = "False";\r
+\r
+        static string getBoolValueString(bool value)\r
+        {\r
+            if (value)\r
+                return VALUE_STRING_TRUE;\r
+            else\r
+                return VALUE_STRING_FALSE;\r
+        }\r
+\r
+        public static bool EnableTouch { get; set;} \r
+        public static double WindowTop { get; set; }\r
+        public static double WindowLeft { get; set; }\r
+        public static double WindowWidth { get; set; }\r
+        public static double WindowHeight { get; set; }\r
+        public static bool WindowMaximized { get; set; }\r
+        public static int ResViewToolbarPosition { get; set; }\r
+        public static int ThreadTitleViewToolbarPosition { get; set; }\r
+        public static double WindowColumn1 { get; set; }\r
+        public static double WindowRow1 { get; set; }\r
+        public static double WindowLeftPanelRow1 { get; set; }\r
+        public static string P2ID { get; set; }\r
+        public static string P2PSS { get; set; }\r
+        public static bool P2IsEnabled\r
+       {\r
+            get \r
+            {\r
+                return mP2Enabled; \r
+            }\r
+            set\r
+            {\r
+                if (mP2Enabled != value)\r
+                {\r
+                    mP2Enabled = value;\r
+                    savePreferences();\r
+                }\r
+            }\r
+        }\r
+\r
+        public static string MaruID { get; set; }\r
+        public static string MaruPSS { get; set; }\r
+        public static bool MaruIsEnabled\r
+        {\r
+            get\r
+            {\r
+                return mMaruEnabled;\r
+            }\r
+            set\r
+            {\r
+                if (mMaruEnabled != value)\r
+                {\r
+                    mMaruEnabled = value;\r
+                    savePreferences();\r
+                }\r
+            }\r
+        }\r
+\r
+        static string mAESPass = string.Empty;\r
+        public static string AESPass\r
+        {\r
+            get\r
+            {\r
+                return mAESPass;\r
+            }\r
+            set\r
+            {\r
+                mAESPass = value;\r
+                NTCrypt.setPassword(value);\r
+            }\r
+        }\r
+        static bool mUseAES;\r
+        public static bool AESEnabled\r
+        {\r
+            get\r
+            {\r
+                return mUseAES && mAESPass != null && mAESPass.Length > 0;\r
+            }\r
+            set\r
+            {\r
+                mUseAES = value;\r
+            }\r
+        }\r
+\r
+        public static string ResFontTypeface { get; set; }\r
+        public static bool UseResFontTypeface\r
+        {\r
+            get { return mUseExplicitResFont; }\r
+            set { mUseExplicitResFont = value; }\r
+        }\r
+\r
+        public static string AAFontTypeface { get; set; }\r
+        public static bool UseAAFontTypeface\r
+        {\r
+            get { return mUseExplicitAAFont; }\r
+            set { mUseExplicitAAFont = value; }\r
+        }\r
+        \r
+        public static string NTCloudID { get; set; }\r
+        public static string NTCloudPSS { get; set; }\r
+        public static string NTCloudUrl { get; set; }\r
+        public static bool NTCloudIsEnabled\r
+        {\r
+            get\r
+            {\r
+                return mNTCloudEnabled;\r
+            }\r
+            set\r
+            {\r
+                if (mNTCloudEnabled != value)\r
+                {\r
+                    mNTCloudEnabled = value;\r
+                    savePreferences();\r
+                }\r
+            }\r
+        }\r
+\r
+        public static string NTUserCloudSeed { get; set; }\r
+        public static string NTUserCloudScriptUrl { get; set; }\r
+        public static string NTUserCloudFileUrl { get; set; }\r
+        public static string NTUserCloudUrl { get; set; }\r
+        public static bool NTUserCloudIsEnabled\r
+        {\r
+            get\r
+            {\r
+                return mNTUserCloudEnabled;\r
+            }\r
+            set\r
+            {\r
+                if (mNTUserCloudEnabled != value)\r
+                {\r
+                    mNTUserCloudEnabled = value;\r
+                    savePreferences();\r
+                }\r
+            }\r
+        }\r
+        private static string mUserCloudHashedPasswd = null;\r
+        public static string NTUserCloudGetHashedPasswd()\r
+        {\r
+            if (null == mUserCloudHashedPasswd)\r
+            {\r
+                mUserCloudHashedPasswd = NTCrypt.getSHA256Hashed(\r
+                    NTUserPreference.NTCloudPSS + NTUserPreference.NTUserCloudSeed);\r
+            }\r
+            return mUserCloudHashedPasswd;\r
+        }\r
+\r
+        public static bool NTShowOnlyCloudReadCount\r
+        {\r
+            set\r
+            {\r
+                mShowCloudReadCnt = value;\r
+            }\r
+\r
+            get\r
+            {\r
+                if (NTCloudIsEnabled)\r
+                    return mShowCloudReadCnt;\r
+                else\r
+                    return false;\r
+            }\r
+        }\r
+\r
+        public static bool SageIsEnabled\r
+        {\r
+            get \r
+            {\r
+                return mSage; \r
+            }\r
+            set\r
+            {\r
+                if (mSage != value)\r
+                {\r
+                    mSage = value;\r
+                    savePreferences();\r
+                }\r
+            }\r
+        }\r
+\r
+        public static bool EnablePopupMouseHover\r
+        {\r
+            set;\r
+            get;\r
+        }\r
+\r
+        public static bool OpenYoutubeOnApp\r
+        {\r
+            set;\r
+            get;\r
+        }\r
+\r
+        public static double ThreadtitleListViewFontSize { get; set; }\r
+\r
+        public static void init()\r
+        {\r
+            mP2Enabled = false;\r
+            mMaruEnabled = false;\r
+            mNTCloudEnabled = false;\r
+            mNTUserCloudEnabled = false;\r
+            mUseExplicitResFont = false;\r
+            mUseExplicitAAFont = false;\r
+\r
+            mSage = true;\r
+            mZoom = 95;\r
+            WindowTop = 50;\r
+            WindowLeft = 50;\r
+            WindowHeight = 640;\r
+            WindowWidth = 920;\r
+            WindowColumn1 = 310.0;\r
+            WindowRow1 = 310.0;\r
+            WindowLeftPanelRow1 = 250.0;\r
+            WindowMaximized = false;\r
+\r
+            EnableTouch = false;\r
+\r
+#if DOTNET45\r
+            ResViewToolbarPosition = NTDragDrop.TOOLBAR_LOCATION_RIGHT;\r
+            ThreadTitleViewToolbarPosition = NTDragDrop.TOOLBAR_LOCATION_RIGHT;\r
+#else\r
+            ResViewToolbarPosition = NTDragDrop.TOOLBAR_LOCATION_LEFT;\r
+            ThreadTitleViewToolbarPosition = NTDragDrop.TOOLBAR_LOCATION_LEFT;\r
+#endif\r
+\r
+\r
+            mShowCloudReadCnt = true;\r
+\r
+            P2ID = string.Empty;\r
+            P2PSS = string.Empty;\r
+            MaruID = string.Empty;\r
+            MaruPSS = string.Empty;\r
+            AESPass = string.Empty;\r
+            NTCloudID = string.Empty;\r
+            NTCloudPSS = string.Empty;\r
+            NTUserCloudUrl = string.Empty;\r
+            NTUserCloudSeed = string.Empty;\r
+            NTUserCloudScriptUrl = string.Empty;\r
+            NTUserCloudFileUrl = string.Empty;\r
+            ResFontTypeface = string.Empty;\r
+            AAFontTypeface = string.Empty;\r
+\r
+            EnablePopupMouseHover = false;\r
+            OpenYoutubeOnApp = true;\r
+\r
+            ResViewThumbnailConnectionCount = 5;\r
+            mResViewThumbnailHeight = 80;\r
+            mResViewThumbnailWidth = 80;\r
+            mResViewShowThumbnail = false;\r
+\r
+            //ImageViewHeight = 300;\r
+            //ImageViewWidth = 300;\r
+\r
+            ThreadtitleListViewFontSize = 14;\r
+\r
+            FavoriteUpdateDuration = 10;\r
+\r
+#if DOTNET45\r
+            ResViewTextSelMode = false;\r
+#else\r
+            ResViewTextSelMode = true;\r
+#endif\r
+\r
+\r
+            loadPreferences();\r
+\r
+\r
+            if (!NTUserCloudIsEnabled)\r
+            {\r
+                if (NTCloudID.Length == 0 ||\r
+                NTCloudPSS.Length == 0 ||\r
+                NTCloudUrl.Length == 0)\r
+                {\r
+                    NTCloudIsEnabled = false;\r
+                }\r
+            }\r
+            else\r
+            {\r
+                if (NTUserCloudUrl.Length == 0 ||\r
+                NTUserCloudSeed.Length == 0 ||\r
+                NTUserCloudScriptUrl.Length == 0 ||\r
+                NTUserCloudFileUrl.Length == 0)\r
+                {\r
+                    NTCloudIsEnabled = false;\r
+                }\r
+            }\r
+        }\r
+\r
+\r
+        static void loadPreferences()\r
+        {\r
+            try\r
+            {\r
+                mAvoidSaveToPreferenceFile = true;\r
+\r
+                List<KeyValuePair<string, string>> list\r
+                    = NTPersistentFileAccess.retrieveUserPreferences();\r
+                foreach (KeyValuePair<string, string> pair in list)\r
+                {\r
+                    switch (pair.Key)\r
+                    {\r
+                        case KEY_FAVORITE_UPDATE_DURATION:\r
+                            try\r
+                            {\r
+                               int duration = int.Parse(pair.Value);\r
+                               if (duration < 0 || duration > 60)\r
+                                   FavoriteUpdateDuration = \r
+                                       DEFAULT_FAVORITE_UPDATE_DURATION;\r
+                               else\r
+                                   FavoriteUpdateDuration = duration;\r
+                            }\r
+                            catch (Exception e)\r
+                            {\r
+                                NTDebug.l(e.Message);\r
+                            }\r
+                            break;\r
+                        case KEY_P2ID:\r
+                            P2ID = pair.Value;\r
+                            break;\r
+                        case KEY_P2PASS:\r
+                            P2PSS = pair.Value;\r
+                            break;\r
+                        case KEY_P2ENABLE:\r
+                            if (VALUE_STRING_TRUE.Equals(pair.Value))\r
+                                P2IsEnabled = true;\r
+                            else\r
+                                P2IsEnabled = false;\r
+                            break;\r
+                        case KEY_MARUID:\r
+                            MaruID = pair.Value;\r
+                            break;\r
+                        case KEY_MARUPASS:\r
+                            MaruPSS = pair.Value;\r
+                            break;\r
+                        case KEY_MARUENABLE:\r
+                            if (VALUE_STRING_TRUE.Equals(pair.Value))\r
+                                MaruIsEnabled = true;\r
+                            else\r
+                                MaruIsEnabled = false;\r
+                            break;\r
+                        case KEY_AESPASS:\r
+                            AESPass = pair.Value;\r
+                            break;\r
+                        case KEY_AESENABLE:\r
+                            if (VALUE_STRING_TRUE.Equals(pair.Value))\r
+                                AESEnabled = true;\r
+                            else\r
+                                AESEnabled = false;\r
+                            break;\r
+                        case KEY_NTCLOUDID:\r
+                            NTCloudID = pair.Value;\r
+                            break;\r
+                        case KEY_NTCLOUDPASS:\r
+                            NTCloudPSS = pair.Value;\r
+                            break;\r
+                        case KEY_NTCLOUDURL:\r
+                            NTCloudUrl = pair.Value;\r
+                            break;\r
+                        case KEY_NTUSERCLOUDURL:\r
+                            NTUserCloudUrl = pair.Value;\r
+                            break;\r
+\r
+                        case KEY_NTUSERCLOUD_SEED:\r
+                            NTUserCloudSeed = pair.Value;\r
+                            break;\r
+                        case KEY_NTUSERCLOUDSCRIPTURL:\r
+                            NTUserCloudScriptUrl = pair.Value;\r
+                            break;\r
+                        case KEY_NTUSERCLOUDFILEURL:\r
+                            NTUserCloudFileUrl = pair.Value;\r
+                            break;\r
+\r
+                        case KEY_NTCLOUDENABLE:\r
+                            if (VALUE_STRING_TRUE.Equals(pair.Value))\r
+                                NTCloudIsEnabled = true;\r
+                            else\r
+                                NTCloudIsEnabled = false;\r
+                            break;\r
+                        case KEY_NTUSERCLOUDENABLE:\r
+                            if (VALUE_STRING_TRUE.Equals(pair.Value))\r
+                                NTUserCloudIsEnabled = true;\r
+                            else\r
+                                NTUserCloudIsEnabled = false;\r
+                            break;\r
+                        case KEY_NT_SHOW_ONLY_CLOUD_READ_COUNT:\r
+                            if (VALUE_STRING_TRUE.Equals(pair.Value))\r
+                                mShowCloudReadCnt = true;\r
+                            else\r
+                                mShowCloudReadCnt = false;\r
+                            break;\r
+\r
+                        case KEY_WRITE_SAGE:\r
+                            if (VALUE_STRING_TRUE.Equals(pair.Value))\r
+                                SageIsEnabled = true;\r
+                            else\r
+                                SageIsEnabled = false;\r
+                            break;\r
+                        case KEY_ZOOM_VALUE:\r
+                            try\r
+                            {\r
+                                mZoom = double.Parse(pair.Value);\r
+                            }\r
+                            catch (Exception e)\r
+                            {\r
+                                NTDebug.l(e.Message);\r
+                            }\r
+                            break;\r
+                        case KEY_WINDOW_TOP:\r
+                            try\r
+                            {\r
+                                WindowTop = double.Parse(pair.Value);\r
+                            }\r
+                            catch (Exception e)\r
+                            {\r
+                                NTDebug.l(e.Message);\r
+                            }\r
+                            break;\r
+                        case KEY_WINDOW_LEFT:\r
+                            try\r
+                            {\r
+                                WindowLeft = double.Parse(pair.Value);\r
+                            }\r
+                            catch (Exception e)\r
+                            {\r
+                                NTDebug.l(e.Message);\r
+                            }\r
+                            break;\r
+                        case KEY_WINDOW_MAXIMIZED:\r
+                            if (VALUE_STRING_TRUE.Equals(pair.Value))\r
+                                WindowMaximized = true;\r
+                            else\r
+                                WindowMaximized = false;\r
+                            break;\r
+                        case KEY_RESVIEW_TOOLBAR_POSITION:\r
+                            try\r
+                            {\r
+                                ResViewToolbarPosition = int.Parse(pair.Value);\r
+                            }\r
+                            catch (Exception e)\r
+                            {\r
+                                NTDebug.l(e.Message);\r
+                            }\r
+                            break;\r
+                        case KEY_THREADTITLEVIEW_TOOLBAR_POSITION:\r
+                            try\r
+                            {\r
+                                ThreadTitleViewToolbarPosition = int.Parse(pair.Value);\r
+                            }\r
+                            catch (Exception e)\r
+                            {\r
+                                NTDebug.l(e.Message);\r
+                            }\r
+                            break;\r
+                        case KEY_WINDOW_HEIGHT:\r
+                            try\r
+                            {\r
+                                WindowHeight = double.Parse(pair.Value);\r
+                            }\r
+                            catch (Exception e)\r
+                            {\r
+                                NTDebug.l(e.Message);\r
+                            }\r
+                            break;\r
+                        case KEY_WINDOW_WIDTH:\r
+                            try\r
+                            {\r
+                                WindowWidth = double.Parse(pair.Value);\r
+                            }\r
+                            catch (Exception e)\r
+                            {\r
+                                NTDebug.l(e.Message);\r
+                            }\r
+                            break;\r
+                        case KEY_WINDOW_COLUMN1:\r
+                            try\r
+                            {\r
+                                WindowColumn1 = double.Parse(pair.Value);\r
+                            }\r
+                            catch (Exception e)\r
+                            {\r
+                                NTDebug.l(e.Message);\r
+                            }\r
+                            break;\r
+                        case KEY_WINDOW_ROW1:\r
+                            try\r
+                            {\r
+                                WindowRow1 = double.Parse(pair.Value);\r
+                            }\r
+                            catch (Exception e)\r
+                            {\r
+                                NTDebug.l(e.Message);\r
+                            }\r
+                            break;\r
+                        case KEY_WINDOW_LEFT_PANEL_ROW1:\r
+                            try\r
+                            {\r
+                                WindowLeftPanelRow1 = double.Parse(pair.Value);\r
+                            }\r
+                            catch (Exception e)\r
+                            {\r
+                                NTDebug.l(e.Message);\r
+                            }\r
+                            break;\r
+                        case KEY_THREADTITLE_LISTVIEW_FONTSIZE:\r
+                            try\r
+                            {\r
+                                ThreadtitleListViewFontSize = double.Parse(pair.Value);\r
+                            }\r
+                            catch (Exception e)\r
+                            {\r
+                                NTDebug.l(e.Message);\r
+                            }\r
+                            break;\r
+                        case KEY_USE_RES_FONT:\r
+                            if (VALUE_STRING_TRUE.Equals(pair.Value))\r
+                                mUseExplicitResFont = true;\r
+                            else\r
+                                mUseExplicitResFont = false;\r
+                            break;\r
+                        case KEY_RES_FONT_TYPEFACE:\r
+                            ResFontTypeface = pair.Value;\r
+                            break;\r
+                        case KEY_USE_AA_FONT:\r
+                            if (VALUE_STRING_TRUE.Equals(pair.Value))\r
+                                mUseExplicitAAFont = true;\r
+                            else\r
+                                mUseExplicitAAFont = false;\r
+                            break;\r
+                        case KEY_POPUPENABLE_MOUSEHOVER:\r
+                            if (VALUE_STRING_TRUE.Equals(pair.Value))\r
+                                EnablePopupMouseHover = true;\r
+                            else\r
+                                EnablePopupMouseHover = false;\r
+                            break;\r
+                        case KEY_OPEN_YOUTUBE_ON_APP:\r
+                            if (VALUE_STRING_TRUE.Equals(pair.Value))\r
+                                OpenYoutubeOnApp = true;\r
+                            else\r
+                                OpenYoutubeOnApp = false;\r
+                            break;\r
+                        case KEY_AA_FONT_TYPEFACE:\r
+                            AAFontTypeface = pair.Value;\r
+                            break;\r
+                        case KEY_RESVIEW_SHOW_THUMBNAIL:\r
+                            if (VALUE_STRING_TRUE.Equals(pair.Value))\r
+                                ResViewShowThumbnail = true;\r
+                            else\r
+                                ResViewShowThumbnail = false;\r
+                            break;\r
+                        case KEY_RESVIEW_THUMBNAIL_CONNECTION_COUNT:\r
+                            try\r
+                            {\r
+                                ResViewThumbnailConnectionCount = int.Parse(pair.Value);\r
+                            }\r
+                            catch (Exception e)\r
+                            {\r
+                                NTDebug.l(e.Message);\r
+                            }\r
+                            break;\r
+                        case KEY_RESVIEW_THUMBNAIL_HEIGHT:\r
+                            try\r
+                            {\r
+                                ResViewThumbnailHeight = int.Parse(pair.Value);\r
+                            }\r
+                            catch (Exception e)\r
+                            {\r
+                                NTDebug.l(e.Message);\r
+                            }\r
+                            break;\r
+                        case KEY_RESVIEW_THUMBNAIL_WIDTH:\r
+                            try\r
+                            {\r
+                                ResViewThumbnailWidth = int.Parse(pair.Value);\r
+                            }\r
+                            catch (Exception e)\r
+                            {\r
+                                NTDebug.l(e.Message);\r
+                            }\r
+                            break;\r
+                        case KEY_RESVIEW_TEXTSEL_MODE:\r
+                            if (VALUE_STRING_TRUE.Equals(pair.Value))\r
+                                mResViewTextSelMode = true;\r
+                            else\r
+                                mResViewTextSelMode = false;\r
+                            break;\r
+                        case KEY_DEBUG_OPTION:\r
+                            if (VALUE_STRING_TRUE.Equals(pair.Value))\r
+                                DebugOption = true;\r
+                            else\r
+                                DebugOption = false;\r
+                            break;\r
+\r
+                    }\r
+                }\r
+\r
+                mAADataText = NTPersistentFileAccess.retrieveAAData();\r
+                if (mAADataText == null)\r
+                {\r
+                    mAADataText = new string[1];\r
+                    mAADataText[0] = "  ";\r
+                }\r
+\r
+                resetExportPreference();\r
+\r
+            }\r
+            finally\r
+            {\r
+                mAvoidSaveToPreferenceFile = false;\r
+            }\r
+\r
+        }\r
+\r
+        static void resetExportPreference()\r
+        {\r
+            if (mAADataText != null)\r
+            {\r
+                mDictExportPreference.Remove(PREF_PARAM.RES_VIEW_AA_STRING_LIST);\r
+                mDictExportPreference.Add(\r
+                    PREF_PARAM.RES_VIEW_AA_STRING_LIST, mAADataText);\r
+            }\r
+            if (mUseExplicitAAFont && AAFontTypeface != null)\r
+            {\r
+                mDictExportPreference.Remove(PREF_PARAM.RES_VIEW_AA_FONT_TYPEFACE);\r
+                mDictExportPreference.Add(\r
+                    PREF_PARAM.RES_VIEW_AA_FONT_TYPEFACE, AAFontTypeface);\r
+            }\r
+            if (mUseExplicitResFont && ResFontTypeface != null)\r
+            {\r
+                mDictExportPreference.Remove(PREF_PARAM.RES_VIEW_FONT_TYPEFACE);\r
+                mDictExportPreference.Add(\r
+                    PREF_PARAM.RES_VIEW_FONT_TYPEFACE, ResFontTypeface);\r
+            }\r
+            \r
+            mDictExportPreference.Remove(PREF_PARAM.RES_VIEW_ZOOM_VALUE);\r
+            mDictExportPreference.Add(\r
+                PREF_PARAM.RES_VIEW_ZOOM_VALUE, mZoom.ToString());\r
+            mDictExportPreference.Remove(PREF_PARAM.RES_VIEW_POPUP_MOUSEHOVER);\r
+            mDictExportPreference.Add(\r
+                PREF_PARAM.RES_VIEW_POPUP_MOUSEHOVER, EnablePopupMouseHover.ToString());\r
+\r
+            mDictExportPreference.Remove(PREF_PARAM.RES_VIEW_SHOW_THUMBNAIL);\r
+            mDictExportPreference.Add(\r
+                PREF_PARAM.RES_VIEW_SHOW_THUMBNAIL, ResViewShowThumbnail.ToString());\r
+            mDictExportPreference.Remove(PREF_PARAM.RES_VIEW_THUMBNAIL_WIDTH);\r
+            mDictExportPreference.Add(\r
+                PREF_PARAM.RES_VIEW_THUMBNAIL_WIDTH, ResViewThumbnailWidth);\r
+            mDictExportPreference.Remove(PREF_PARAM.RES_VIEW_THUMBNAIL_HEIGHT);\r
+            mDictExportPreference.Add(\r
+                PREF_PARAM.RES_VIEW_THUMBNAIL_HEIGHT, ResViewThumbnailHeight);\r
+\r
+            mDictExportPreference.Remove(PREF_PARAM.THREADTITLE_LIST_FONT_SIZE);\r
+            mDictExportPreference.Add(\r
+                PREF_PARAM.THREADTITLE_LIST_FONT_SIZE, ThreadtitleListViewFontSize);\r
+\r
+            mDictExportPreference.Remove(PREF_PARAM.RES_VIEW_TEXTSEL_MODE);\r
+            mDictExportPreference.Add(\r
+                PREF_PARAM.RES_VIEW_TEXTSEL_MODE, mResViewTextSelMode);\r
+\r
+        }\r
+\r
+        \r
+\r
+        public static void savePreferences()\r
+        {\r
+            if (mAvoidSaveToPreferenceFile)\r
+                return;\r
+\r
+            List<KeyValuePair<string, string>> list\r
+                = new List<KeyValuePair<string, string>>();\r
+\r
+            KeyValuePair<string, string> pair \r
+                = new KeyValuePair<string, string>(KEY_P2ID, P2ID);\r
+            list.Add(pair);\r
+\r
+            pair = new KeyValuePair<string, string>(KEY_P2PASS, P2PSS);\r
+            list.Add(pair);\r
+\r
+            pair = new KeyValuePair<string, string>(KEY_P2ENABLE, getBoolValueString(P2IsEnabled));\r
+            list.Add(pair);\r
+\r
+            pair = new KeyValuePair<string, string>(KEY_MARUID, MaruID);\r
+            list.Add(pair);\r
+\r
+            pair = new KeyValuePair<string, string>(KEY_MARUPASS, MaruPSS);\r
+            list.Add(pair);\r
+\r
+            pair = new KeyValuePair<string, string>(KEY_MARUENABLE, getBoolValueString(MaruIsEnabled));\r
+            list.Add(pair);\r
+\r
+            pair = new KeyValuePair<string, string>(KEY_AESPASS, AESPass);\r
+            list.Add(pair);\r
+\r
+            pair = new KeyValuePair<string, string>(KEY_AESENABLE, getBoolValueString(AESEnabled));\r
+            list.Add(pair);\r
+\r
+\r
+            pair = new KeyValuePair<string, string>(KEY_WRITE_SAGE, getBoolValueString(SageIsEnabled));\r
+            list.Add(pair);\r
+\r
+            object o;\r
+            if (mDictExportPreference.TryGetValue(PREF_PARAM.RES_VIEW_ZOOM_VALUE, out o))\r
+            {\r
+                double zoom;\r
+                String s = o as String;\r
+                if (s != null)\r
+                    if(double.TryParse(s, out zoom))\r
+                        mZoom = zoom;\r
+            }\r
+            pair = new KeyValuePair<string, string>(KEY_ZOOM_VALUE, mZoom.ToString());\r
+            list.Add(pair);\r
+\r
+            pair = new KeyValuePair<string, string>(KEY_THREADTITLEVIEW_TOOLBAR_POSITION, ThreadTitleViewToolbarPosition.ToString());\r
+            list.Add(pair);\r
+            pair = new KeyValuePair<string, string>(KEY_RESVIEW_TOOLBAR_POSITION, ResViewToolbarPosition.ToString());\r
+            list.Add(pair);\r
+\r
+            pair = new KeyValuePair<string, string>(KEY_WINDOW_MAXIMIZED, getBoolValueString(WindowMaximized));\r
+            list.Add(pair);\r
+            pair = new KeyValuePair<string, string>(KEY_WINDOW_HEIGHT, WindowHeight.ToString());\r
+            list.Add(pair);\r
+            pair = new KeyValuePair<string, string>(KEY_WINDOW_WIDTH, WindowWidth.ToString());\r
+            list.Add(pair);\r
+\r
+            pair = new KeyValuePair<string, string>(KEY_WINDOW_TOP, WindowTop.ToString());\r
+            list.Add(pair);\r
+            pair = new KeyValuePair<string, string>(KEY_WINDOW_LEFT, WindowLeft.ToString());\r
+            list.Add(pair);\r
+\r
+            pair = new KeyValuePair<string, string>(KEY_WINDOW_COLUMN1, WindowColumn1.ToString());\r
+            list.Add(pair);\r
+            pair = new KeyValuePair<string, string>(KEY_WINDOW_ROW1, WindowRow1.ToString());\r
+            list.Add(pair);\r
+            pair = new KeyValuePair<string, string>(KEY_WINDOW_LEFT_PANEL_ROW1, WindowLeftPanelRow1.ToString());\r
+            list.Add(pair);\r
+\r
+            pair = new KeyValuePair<string, string>(KEY_NTCLOUDID, NTCloudID);\r
+            list.Add(pair);\r
+\r
+            pair = new KeyValuePair<string, string>(KEY_NTCLOUDPASS, NTCloudPSS);\r
+            list.Add(pair);\r
+\r
+            pair = new KeyValuePair<string, string>(KEY_NTCLOUDURL, NTCloudUrl);\r
+            list.Add(pair);\r
+\r
+            pair = new KeyValuePair<string, string>(KEY_NTCLOUDENABLE, getBoolValueString(NTCloudIsEnabled));\r
+            list.Add(pair);\r
+\r
+            pair = new KeyValuePair<string, string>(KEY_NTUSERCLOUDURL, NTUserCloudUrl);\r
+            list.Add(pair);\r
+\r
+            pair = new KeyValuePair<string, string>(KEY_NTUSERCLOUD_SEED, NTUserCloudSeed);\r
+            list.Add(pair);\r
+            pair = new KeyValuePair<string, string>(KEY_NTUSERCLOUDSCRIPTURL, NTUserCloudScriptUrl);\r
+            list.Add(pair);\r
+            pair = new KeyValuePair<string, string>(KEY_NTUSERCLOUDFILEURL, NTUserCloudFileUrl);\r
+            list.Add(pair);\r
+\r
+\r
+            pair = new KeyValuePair<string, string>(KEY_NTUSERCLOUDENABLE, getBoolValueString(NTUserCloudIsEnabled));\r
+            list.Add(pair);\r
+\r
+            pair = new KeyValuePair<string, string>(KEY_NT_SHOW_ONLY_CLOUD_READ_COUNT, getBoolValueString(mShowCloudReadCnt));\r
+            list.Add(pair);\r
+\r
+            pair = new KeyValuePair<string, string>(KEY_USE_RES_FONT, getBoolValueString(mUseExplicitResFont));\r
+            list.Add(pair);\r
+\r
+            pair = new KeyValuePair<string, string>(KEY_RES_FONT_TYPEFACE, ResFontTypeface);\r
+            list.Add(pair);\r
+\r
+            pair = new KeyValuePair<string, string>(KEY_USE_AA_FONT, getBoolValueString(mUseExplicitAAFont));\r
+            list.Add(pair);\r
+\r
+            pair = new KeyValuePair<string, string>(KEY_AA_FONT_TYPEFACE, AAFontTypeface);\r
+            list.Add(pair);\r
+\r
+            pair = new KeyValuePair<string, string>(KEY_POPUPENABLE_MOUSEHOVER, getBoolValueString(EnablePopupMouseHover));\r
+            list.Add(pair);\r
+\r
+            pair = new KeyValuePair<string, string>(KEY_OPEN_YOUTUBE_ON_APP, getBoolValueString(OpenYoutubeOnApp));\r
+            list.Add(pair);\r
+\r
+            pair = new KeyValuePair<string, string>(KEY_RESVIEW_SHOW_THUMBNAIL, getBoolValueString(mResViewShowThumbnail));\r
+            list.Add(pair);\r
+            pair = new KeyValuePair<string, string>(KEY_RESVIEW_THUMBNAIL_HEIGHT, mResViewThumbnailHeight.ToString());\r
+            list.Add(pair);\r
+            pair = new KeyValuePair<string, string>(KEY_RESVIEW_THUMBNAIL_WIDTH, mResViewThumbnailWidth.ToString());\r
+            list.Add(pair);\r
+            pair = new KeyValuePair<string, string>(\r
+                    KEY_RESVIEW_THUMBNAIL_CONNECTION_COUNT, \r
+                    mResViewThumbnailConnectionCount.ToString());\r
+            list.Add(pair);\r
+\r
+            pair = new KeyValuePair<string, string>(\r
+                KEY_THREADTITLE_LISTVIEW_FONTSIZE, ThreadtitleListViewFontSize.ToString());\r
+            list.Add(pair);\r
+\r
+            pair = new KeyValuePair<string, string>(\r
+                 KEY_FAVORITE_UPDATE_DURATION, FavoriteUpdateDuration.ToString());\r
+            list.Add(pair);\r
+\r
+            pair = new KeyValuePair<string, string>(KEY_RESVIEW_TEXTSEL_MODE, getBoolValueString(ResViewTextSelMode));\r
+            list.Add(pair);\r
+\r
+            pair = new KeyValuePair<string, string>(KEY_DEBUG_OPTION, getBoolValueString(DebugOption));\r
+            list.Add(pair);\r
+\r
+            NTPersistentFileAccess.storeUserPreferences(list);\r
+\r
+            NTPersistentFileAccess.storeAAData(mAADataText);\r
+\r
+            resetExportPreference();\r
+\r
+            NTFontUtil.clear();\r
+\r
+            mUserCloudHashedPasswd = null;\r
+\r
+        }\r
+    }\r
+}\r
diff --git a/NT2chView45/NTVagueSearchWord.cs b/NT2chView45/NTVagueSearchWord.cs
new file mode 100755 (executable)
index 0000000..a4988ab
--- /dev/null
@@ -0,0 +1,191 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using NT2chCtrl;\r
+using NT2chObject;\r
+\r
+namespace NT2chView\r
+{\r
+    class NTVagueSearchWord : IAmbiguousSearch\r
+    {\r
+        public bool match(string source, \r
+            int startIndex, out int firstIndex, out int length)\r
+        {\r
+            firstIndex = length = -1;\r
+            if (source == null || source.Length == 0)\r
+                return false;\r
+\r
+            firstIndex = match(source, startIndex, out length);\r
+            return (firstIndex < 0) ? false : true;\r
+        }\r
+\r
+        class Tree\r
+        {\r
+            public char mC;\r
+            public char mCode;\r
+            public List<Tree> mTree = new List<Tree>();\r
+            public Tree(char c) { mC = c; mCode = '\0'; }\r
+        }\r
+\r
+               Tree mParentTree;\r
+               String mSearchWord = "";\r
+               \r
+               public NTVagueSearchWord(String searchWord){\r
+                       //DebugUtil.log("VagueSearchWord ctor with " + searchWord);\r
+                       mParentTree = new Tree('\0');\r
+                       setSearchWord(searchWord);\r
+                       \r
+               }\r
+               \r
+               public void setSearchWord(String searchWord){\r
+                       String s = searchWord.Trim();\r
+                       if(mSearchWord.Equals(s)){\r
+                               return;\r
+                       }\r
+                       if(0 < s.Length){\r
+                               mParentTree = new Tree('\0');\r
+                               parseVagueString(mParentTree, s, 0);\r
+                       }\r
+                       mSearchWord = s;\r
+                       //debugPrintTree(mParentTree, "");\r
+               }\r
+               \r
+               /*void debugPrintTree(Tree tree, String parent){\r
+                       List<Tree> treeArr = tree.mTree;\r
+                       for(int i = 0; i < treeArr.Count; i++){\r
+                               Tree newTree = treeArr[i];\r
+                               if(newTree.mCode == 1){\r
+                                       char [] cc = new char[1];\r
+                                       cc[0] = newTree.mC;\r
+                                       //DebugUtil.log("Tree : " + (parent + new String(cc)));\r
+                               }else{\r
+                                       char [] cc = new char[1];\r
+                                       cc[0] = newTree.mC;\r
+                                       debugPrintTree(newTree, (parent + new String(cc)));\r
+                               }\r
+                       }\r
+               }*/\r
+               \r
+               public int compare(String source, int start){\r
+                       return match(mParentTree, source, start);\r
+               }\r
+               \r
+               public int match(String source, int start, out int len){\r
+                       //DebugUtil.log("match() with " + source.substring(start));\r
+                       for(int i = start; i < source.Length; i++){\r
+                               int result = match(mParentTree, source, i);\r
+                               if(0 < result){\r
+                                       //DebugUtil.log("matched!!! : " + source.substring(i, result));\r
+                                       len = result;\r
+                                       return i;\r
+                               }\r
+                       }\r
+            len = -1;\r
+                       return -1;\r
+               }\r
+               int match(Tree tree, String source, int start){\r
+                       if(0 >= tree.mTree.Count){\r
+                               return -1;\r
+                       }\r
+                       if(start == source.Length){\r
+                               return -1;\r
+                       }\r
+                       \r
+                       char c = source[start];\r
+                       for(int i = 0; i < tree.mTree.Count; i++){\r
+                               Tree cTree = tree.mTree[i];\r
+                               if(cTree.mC == c){\r
+                                       if(1 == cTree.mCode){\r
+                                               return start + 1;\r
+                                       }else{\r
+                                               return match(cTree, source, start + 1);\r
+                                       }\r
+                               }\r
+                       }\r
+                       return -1;\r
+               }\r
+               \r
+               private void parseVagueString(Tree parentTree, String source, int start) {\r
+                       //DebugUtil.log("parseVagueString with "+ source.substring(start));\r
+                       char c = source[start];\r
+                       int index = findVagueChar(c);\r
+                       int nextIndex = start + 1;\r
+                       if(0 > index){\r
+                               Tree tree = new Tree(c);\r
+                               parentTree.mTree.Add(tree);\r
+                               if(nextIndex == source.Length){\r
+                                       tree.mCode = (char)1;\r
+                               }else{\r
+                                       parseVagueString(tree, source, nextIndex);\r
+                               }\r
+                       }else{\r
+                               char[] arr = vagueChar[index];\r
+                               for(int j = 0; j < arr.Length; j++){\r
+                                       Tree tree = new Tree(arr[j]);\r
+                                       parentTree.mTree.Add(tree);\r
+                                       if(nextIndex == source.Length){\r
+                                               tree.mCode = (char)1;\r
+                                       }else{\r
+                                               parseVagueString(tree, source, nextIndex);\r
+                                       }                               \r
+                               }\r
+                       }               \r
+               }\r
+       \r
+               int findVagueChar(char c){\r
+                       for(int i = 0; i < vagueChar.Length; i++){\r
+                               for(int j = 0; j < vagueChar[i].Length; j++){\r
+                                       if(c == vagueChar[i][j]){\r
+                                               return i;\r
+                                       }\r
+                               }\r
+                       }\r
+                       return -1;\r
+               }\r
+       \r
+               char [][] vagueChar  = new char[][]{\r
+                       new []{'0','0'},new []{'1','1'},new []{'2','2'},\r
+            new []{'3','3'},new []{'4','4'},new []{'5','5'},\r
+                       new []{'6','6'},new []{'7','7'},new []{'8','8'},new []{'9','9'},\r
+                       new []{'A','a','A','a'},new []{'B','b','B','b'},\r
+            new []{'C','c','C','c'},new []{'D','d','D','d'},\r
+            new []{'E','e','E','e'},new []{'F','f','F','f'},\r
+                       new []{'G','g','G','g'},new []{'H','h','H','h'},\r
+            new []{'I','i','I','i'},new []{'J','j','J','j'},\r
+            new []{'K','k','K','k'},new []{'L','l','L','l'},\r
+                       new []{'M','m','M','m'},new []{'N','n','N','n'},\r
+            new []{'O','o','O','o'},new []{'P','p','P','p'},\r
+            new []{'Q','q','Q','q'},new []{'R','r','R','r'},\r
+                       new []{'S','s','S','s'},new []{'T','t','T','t'},\r
+            new []{'U','u','U','u'},new []{'V','v','V','v'},\r
+            new []{'W','w','W','w'},new []{'X','x','X','x'},\r
+                       new []{'Y','y','Y','y'},new []{'Z','z','Z','z'},\r
+                       new []{'あ','ア','ぁ','ァ'},new []{'い','イ','ぃ','ィ'},\r
+            new []{'う','ウ','ぅ','ゥ'},new []{'え','エ','ぇ','ェ'},\r
+            new []{'お','オ','ぉ','ォ','を','ヲ'},\r
+                       new []{'か','カ','ヵ','ヵ'},new []{'き','キ'},new []{'く','ク'},        \r
+            new []{'け','ケ','ヶ','ヶ'},new []{'こ','コ'},new []{'さ','サ'},\r
+            new []{'し','シ'},new []{'す','ス'},new []{'せ','セ'},\r
+            new []{'そ','ソ'},new []{'た','タ'},new []{'ち','チ'},\r
+            new []{'つ','ツ','っ','ッ'},new []{'て','テ'},new []{'と','ト'},\r
+                       new []{'な','ナ'},new []{'に','ニ'},new []{'ぬ','ヌ'},\r
+            new []{'ね','ネ'},new []{'の','ノ'},new []{'は','ハ','ワ','わ'},\r
+            new []{'ひ','ヒ'},new []{'ふ','フ'},new []{'へ','ヘ'},\r
+            new []{'ほ','ホ'},new []{'ま','マ'},new []{'み','ミ'},\r
+            new []{'む','ム'},new []{'め','メ'},new []{'も','モ'},\r
+                       new []{'や','ヤ','ゃ','ャ'},new []{'ゆ','ユ','ゅ','ュ'},\r
+            new []{'よ','ヨ','ょ','ョ'},new[]{'ら','ラ','ラ'}, \r
+            new[]{'り','リ','リ'},new[]{'る','ル','ル'},new[]{'れ','レ','レ'},\r
+            new[]{'ろ','ロ','ロ'},new []{'ん','ン'},\r
+                       new []{'が','ガ'},new []{'ぎ','ギ'},new []{'ぐ','グ'},\r
+            new []{'げ','ゲ'},new []{'ご','ゴ'},new []{'ざ','ザ'},\r
+            new []{'じ','ジ','ぢ','ヂ'},new []{'ず','ズ','づ','ヅ'},\r
+                       new []{'ぜ','ゼ'},new []{'ぞ','ゾ'},new []{'だ','ダ'},\r
+            new []{'で','デ'},new []{'ど','ド'},new []{'ば','バ'},\r
+            new []{'び','ビ'},new []{'ぶ','ブ'},new []{'べ','ベ'},\r
+            new []{'ぼ','ボ'},new []{'ぱ','パ'},new []{'ぴ','ピ'},\r
+            new []{'ぷ','プ'},new []{'ぺ','ペ'},new []{'ぽ','ポ'},\r
+                       new []{'-','_','-','_','ー','ー',' ',' '}\r
+        };\r
+    }\r
+}\r
diff --git a/NT2chView45/NTWriteResHistoryPopup.cs b/NT2chView45/NTWriteResHistoryPopup.cs
new file mode 100755 (executable)
index 0000000..9703d4b
--- /dev/null
@@ -0,0 +1,79 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Windows;\r
+using System.Windows.Controls;\r
+using System.Windows.Controls.Primitives;\r
+using System.Windows.Documents;\r
+using System.Windows.Media;\r
+using NT2chView.NtFile;\r
+\r
+namespace NT2chView\r
+{\r
+    class NTWriteResHistoryPopup : Popup\r
+    {\r
+        NTWriteResWindow mWnd;\r
+        public NTWriteResHistoryPopup(NTWriteResWindow wnd, string[] history)\r
+            : base()\r
+        {\r
+            mWnd = wnd;\r
+            this.StaysOpen = false;\r
+\r
+            Grid grid = new Grid();\r
+            ScrollViewer sv = new ScrollViewer();\r
+            ListBox lBox = new ListBox();\r
+            grid.Children.Add(sv);\r
+            sv.Content = lBox;\r
+            sv.MaxHeight = mWnd.Height;\r
+            sv.MaxWidth = 480;\r
+            sv.MinWidth = 150;\r
+\r
+            this.Child = grid;\r
+\r
+            ListBoxItem li;\r
+            foreach (string s in history)\r
+            {\r
+                string s2 = NTTextFormat.removeTag(s);\r
+                StackPanel sp = new StackPanel();\r
+                //Border border = new Border();\r
+                //border.BorderThickness = new System.Windows.Thickness(1);\r
+                //border.BorderBrush = new SolidColorBrush(Colors.DarkGray);\r
+                //border.VerticalAlignment = VerticalAlignment.Stretch;\r
+                //border.HorizontalAlignment = HorizontalAlignment.Stretch;\r
+                sp.Children.Add(new TextBlock(new Run(s2)));\r
+                sp.MouseLeftButtonDown += sp_MouseLeftButtonDown;\r
+                sp.Tag = s2;\r
+                //border.Child = sp;           \r
+                li = new ListBoxItem();\r
+                li.Content = sp;\r
+                lBox.Items.Add(li);\r
+            }\r
+\r
+        }\r
+\r
+        void sp_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)\r
+        {\r
+            StackPanel sp = sender as StackPanel;\r
+            if (sp == null)\r
+                return;\r
+\r
+            string msg = sp.Tag as string;\r
+            if (msg == null)\r
+                return;\r
+\r
+            mWnd.setMsg(msg);\r
+\r
+            IsOpen = false;\r
+\r
+\r
+        }\r
+        public void show()\r
+        {\r
+            IsOpen = true;\r
+            Placement = PlacementMode.Mouse;\r
+           // Focus();\r
+        }\r
+\r
+\r
+    }\r
+}\r
diff --git a/NT2chView45/NTWriteResResultWindow.xaml b/NT2chView45/NTWriteResResultWindow.xaml
new file mode 100755 (executable)
index 0000000..12c736f
--- /dev/null
@@ -0,0 +1,18 @@
+<Window x:Class="NT2chView.NTWriteResResultWindow"\r
+        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"\r
+        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"\r
+        Height="640" Width="480">\r
+    <Grid>\r
+        <Grid.RowDefinitions>\r
+            <RowDefinition Height="*"/>\r
+            <RowDefinition Height="Auto"/>\r
+        </Grid.RowDefinitions>\r
+        <FlowDocumentScrollViewer Grid.Row="0" Name="WriteResultDocViewer">\r
+            \r
+        </FlowDocumentScrollViewer>\r
+        <StackPanel Grid.Row="1" Orientation="Horizontal" FlowDirection="RightToLeft">\r
+            <Button Margin="5" Name="btnWriteDeny" Click="btnWriteDeny_Click">戻る</Button>\r
+            <Button Margin="5" Name="btnWriteConfirm" Click="btnWriteConfirm_Click">書き込む</Button>\r
+        </StackPanel>\r
+    </Grid>\r
+</Window>\r
diff --git a/NT2chView45/NTWriteResResultWindow.xaml.cs b/NT2chView45/NTWriteResResultWindow.xaml.cs
new file mode 100755 (executable)
index 0000000..a67f7de
--- /dev/null
@@ -0,0 +1,47 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Windows;\r
+using System.Windows.Controls;\r
+using System.Windows.Data;\r
+using System.Windows.Documents;\r
+using System.Windows.Input;\r
+using System.Windows.Media;\r
+using System.Windows.Media.Imaging;\r
+using System.Windows.Shapes;\r
+using NT2chView.NtHtml;\r
+\r
+\r
+namespace NT2chView\r
+{\r
+    /// <summary>\r
+    /// NTWriteResResultWindow.xaml の相互作用ロジック\r
+    /// </summary>\r
+    public partial class NTWriteResResultWindow : Window\r
+    {\r
+        public NTWriteResResultWindow(string title, FlowDocument document, X_CONFIRM_RESULT xResult)\r
+        {\r
+            InitializeComponent();\r
+\r
+            if (title != null)\r
+                this.Title = title;\r
+\r
+            WriteResultDocViewer.Document = document;\r
+\r
+            if (xResult != X_CONFIRM_RESULT.COOKIE)\r
+                this.btnWriteConfirm.IsEnabled = false;\r
+        }\r
+\r
+        private void btnWriteDeny_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            this.DialogResult = false;\r
+            Close();\r
+        }\r
+\r
+        private void btnWriteConfirm_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            this.DialogResult = true;\r
+            Close();\r
+        }\r
+    }\r
+}\r
diff --git a/NT2chView45/NTWriteResWindow.xaml b/NT2chView45/NTWriteResWindow.xaml
new file mode 100755 (executable)
index 0000000..2c5d36d
--- /dev/null
@@ -0,0 +1,29 @@
+<Window x:Class="NT2chView.NTWriteResWindow"\r
+        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"\r
+        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"\r
+        Title="書き込み" Height="400" Width="400" PreviewKeyDown="NTWriteResWindow_PreviewKeyDown" PreviewKeyUp="NTWriteResWindow_PreviewKeyUp">\r
+    <Grid>\r
+        <Grid.RowDefinitions>\r
+            <RowDefinition Height="Auto"></RowDefinition>\r
+            <RowDefinition Height="Auto"></RowDefinition>\r
+            <RowDefinition></RowDefinition>\r
+            <RowDefinition Height="Auto"></RowDefinition>\r
+        </Grid.RowDefinitions>\r
+        <Grid.ColumnDefinitions>\r
+            <ColumnDefinition Width="Auto"></ColumnDefinition>\r
+            <ColumnDefinition></ColumnDefinition>\r
+            <ColumnDefinition Width="Auto"></ColumnDefinition>\r
+        </Grid.ColumnDefinitions>\r
+        <Label Content="名前:" />\r
+        <Label Content="E-Mail:" Grid.Row="1" />\r
+        <Label Grid.Row="3" Grid.Column="1"  Margin="50,0,0,0" VerticalContentAlignment="Center">(Shift+Enter)</Label>\r
+        <Button Margin="5" Content="書き込む" Height="23" Name="btnWriteRes" Width="75" Grid.Row="3" Grid.Column="1" HorizontalAlignment="Right" Click="btnWriteRes_Click" />\r
+        <Button Margin="5"  Content="戻る" Height="23" Name="btnWriteResClose" Width="75" Grid.Row="3" Grid.Column="2" Click="btnWriteResClose_Click" />\r
+        <TextBox SpellCheck.IsEnabled="True" Grid.ColumnSpan="3" Grid.Row="2" Name="txtMsg" AcceptsReturn="True" AcceptsTab="True" TextWrapping="WrapWithOverflow" VerticalScrollBarVisibility="Auto" TabIndex="1" />\r
+        <TextBox Grid.Column="1" Grid.ColumnSpan="1" Grid.RowSpan="1" Name="txtName" Grid.Row="0" />\r
+        <TextBox Grid.Column="1" Grid.ColumnSpan="1" Grid.RowSpan="1" Name="txtMail" Grid.Row="1" />\r
+        <CheckBox Content="_sage" Grid.Column="2" Grid.Row="1" Grid.RowSpan="1" Name="chkSage" HorizontalAlignment="Center" VerticalAlignment="Center" Unchecked="chkSage_Unchecked" Checked="chkSage_Checked" />\r
+        <Button Content="履歴..." Grid.Column="2" Grid.RowSpan="1" HorizontalAlignment="Center" x:Name="btnWriteHistory" VerticalAlignment="Center" Click="btnWriteHistory_Click" />\r
+        <CheckBox Content="P2を使う" Grid.ColumnSpan="2" Grid.Row="3" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="20,0,0,0" Name="chkWriteTroughP2" Checked="chkWriteTroughP2_Checked" Unchecked="chkWriteTroughP2_Unchecked" />\r
+    </Grid>\r
+</Window>\r
diff --git a/NT2chView45/NTWriteResWindow.xaml.cs b/NT2chView45/NTWriteResWindow.xaml.cs
new file mode 100755 (executable)
index 0000000..ba3aa87
--- /dev/null
@@ -0,0 +1,692 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Windows;\r
+using System.Windows.Controls;\r
+using System.Windows.Data;\r
+using System.Windows.Documents;\r
+using System.Windows.Input;\r
+using System.Windows.Media;\r
+using System.Windows.Media.Imaging;\r
+using System.Windows.Shapes;\r
+using NT2chView.NtNet;\r
+using NT2chView.NtHtml;\r
+using System.Web;\r
+using NT2chView.NtFile;\r
+\r
+\r
+namespace NT2chView\r
+{\r
+    /// <summary>\r
+    /// NTWriteResWindow.xaml の相互作用ロジック\r
+    /// </summary>\r
+    public partial class NTWriteResWindow : Window\r
+    {\r
+        NTThreadTitle mThread;\r
+        MainWindow mMainWindow;\r
+        string mDatName;\r
+        string mBoardName;\r
+        string mHostName;\r
+        //string mSiteMsg;\r
+        string[] mHistory = null;\r
+\r
+\r
+        public NTWriteResWindow(MainWindow main, NTThreadTitle thread, string siteMsg)\r
+        {\r
+\r
+            InitializeComponent();\r
+            mMainWindow = main;\r
+            mThread = thread;\r
+            //mSiteMsg = siteMsg;\r
+\r
+            if (thread.mBoard.mMachiBBS)\r
+            {\r
+                chkWriteTroughP2.IsEnabled = false;\r
+            }\r
+            else\r
+            {\r
+                chkWriteTroughP2.IsChecked = NTUserPreference.P2IsEnabled;\r
+            }\r
+            chkSage.IsChecked = NTUserPreference.SageIsEnabled;\r
+            Title = thread.Title;\r
+\r
+            mHistory = NTPersistentFileAccess.retrieveWriteHistroy();\r
+            if (mHistory == null || mHistory.Length == 0)\r
+            {\r
+                btnWriteHistory.IsEnabled = false;\r
+            }\r
+\r
+\r
+            if (siteMsg != null && siteMsg.Length > 0)\r
+            {\r
+                txtMsg.Text = siteMsg;\r
+            }\r
+\r
+            txtMsg.Focus();\r
+        }\r
+\r
+        private void btnWriteResClose_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            storeMsgToHistory();\r
+            Close();\r
+        }\r
+\r
+        private void btnWriteRes_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            WriteRes_Invoke();\r
+        }\r
+\r
+        private void WriteRes_Invoke()\r
+        {\r
+            mThread.mWroteMsg = string.Empty;\r
+            setupServerParam();\r
+            string [] args = preWriteRes();\r
+\r
+            bool result = false;\r
+            if (!NTHttpUtils.isValid2chAddress(mThread.mBoard.mAddress))\r
+            {\r
+                if (mThread.mBoard.mMachiBBS)\r
+                {\r
+                    if (writeResMachiBBS(args, null))\r
+                    {\r
+                        result = true;\r
+                    }\r
+\r
+                }\r
+                else\r
+                {\r
+                    if (writeResExternalBBS(mThread.mBoard.mAddress,  args, null))\r
+                    {\r
+                        result = true;\r
+                    }\r
+                }\r
+            }\r
+            else{\r
+                if (NTUserPreference.P2IsEnabled)\r
+                {\r
+                    if (writeResP2(args, null))\r
+                    {\r
+                        result = true;\r
+                    }\r
+                }\r
+                else\r
+                {\r
+                    if (writeRes(args, null))\r
+                    {\r
+                        result = true;\r
+                    }\r
+                }\r
+            }\r
+            if (result)\r
+            {\r
+                mThread.mWroteMsg = txtMsg.Text;\r
+                mMainWindow.WriteResCallback(true, mThread);\r
+                storeMsgToHistory();\r
+                Close();\r
+            }\r
+        }\r
+\r
+        private bool setupServerParam()\r
+        {\r
+            NTBoard board = mThread.mBoard;\r
+\r
+            mDatName = NTHttpUtils.ridSuffixFromDatName(mThread.mDat);\r
+\r
+            string hostName;\r
+            string boardName;\r
+\r
+            if (!NTHttpUtils.parseHostAddress(board.mAddress, out hostName, out boardName))\r
+                return false;\r
+\r
+            mBoardName = boardName;\r
+            mHostName = hostName;\r
+            return true;\r
+        }\r
+        private string []  preWriteRes()\r
+        {\r
+\r
+            if (!setupServerParam())\r
+                return null;\r
+\r
+            string mail;\r
+            string name;\r
+            string msg;\r
+\r
+            if (chkSage.IsChecked.HasValue && ((bool)chkSage.IsChecked))\r
+                mail = "sage";\r
+            else\r
+                mail = txtMail.Text;\r
+\r
+            name = txtName.Text;\r
+\r
+            msg = txtMsg.Text;\r
+\r
+            mail = (mail == null) ? string.Empty : mail;\r
+            name = (name == null) ? string.Empty : name;\r
+            msg = (msg == null) ? string.Empty : msg;\r
+\r
+\r
+            string[] args = new string[7];\r
+\r
+            args[0] = mHostName;\r
+            args[1] = mBoardName;\r
+            args[2] = mDatName;\r
+            args[3] = name;\r
+            args[4] = mail;\r
+            args[5] = msg;\r
+            args[6] = NTHttpUtils.DEFAULT_SUBMIT;\r
+\r
+            return args;\r
+\r
+            \r
+\r
+        }\r
+\r
+        private bool writeResP2(string[] args, List<KeyValuePair<string, string>> extra)\r
+        {\r
+\r
+\r
+            string htmlStr = NTHttpAccess.writeResP2(args, extra, mThread.ResCnt, mThread.Title, false);\r
+            \r
+            if (null == htmlStr)\r
+            {\r
+                MessageBox.Show("サーバーの応答が不正です");\r
+                return false;\r
+            }\r
+\r
+            FlowDocument doc = new FlowDocument();\r
+            NTHtmlParser htmlParser = new NTHtmlParser(doc);\r
+            string parsedHtml = htmlParser.parse(htmlStr);\r
+            if (parsedHtml == null)\r
+            {\r
+                MessageBox.Show("サーバーの応答が不正です");\r
+                return false;\r
+            }\r
+\r
+            X_CONFIRM_RESULT xResult = NTHtmlWriteResParser.validateResult(htmlParser);\r
+            if (xResult == X_CONFIRM_RESULT.SUCCESS)\r
+                return true;\r
+\r
+            NTDebug.l(parsedHtml);\r
+            NTWriteResResultWindow w\r
+                = new NTWriteResResultWindow(htmlParser.getTitle(), doc, xResult);\r
+            w.Owner = this;\r
+            bool? result = w.ShowDialog();\r
+\r
+            if (result.HasValue && ((bool)result))\r
+            {\r
+                List<KeyValuePair<string, string>> list = htmlParser.mInputTypeSubmit;\r
+                if (list.Count > 0)\r
+                {\r
+                    args[6] = list[0].Value;\r
+                    return writeResP2(args, htmlParser.mInputTypeHidden);\r
+                }\r
+\r
+            }\r
+            return false;\r
+        }\r
+\r
+        private bool writeRes(string[] args, List<KeyValuePair<string, string>> extra)\r
+        {\r
+\r
+\r
+            string htmlStr = NTHttpAccess.writeRes(args, extra);\r
+            \r
+            if (null == htmlStr)\r
+            {\r
+                MessageBox.Show("サーバーの応答が不正です");\r
+                return false;\r
+            }\r
+            FlowDocument doc = new FlowDocument();\r
+            NTHtmlParser htmlParser = new NTHtmlParser(doc);\r
+            string parsedHtml = htmlParser.parse(htmlStr);\r
+            if (parsedHtml == null)\r
+            {\r
+                MessageBox.Show("サーバーの応答が不正です");\r
+                return false;\r
+            }\r
+\r
+            X_CONFIRM_RESULT xResult = NTHtmlWriteResParser.validateResult(htmlParser);\r
+            if (xResult == X_CONFIRM_RESULT.SUCCESS)\r
+                return true;\r
+\r
+            NTDebug.l(parsedHtml);\r
+            NTWriteResResultWindow w\r
+                = new NTWriteResResultWindow(htmlParser.getTitle(), doc, xResult);\r
+            w.Owner = this;\r
+            bool? result = w.ShowDialog();\r
+\r
+            if (result.HasValue && ((bool)result))\r
+            {\r
+                List<KeyValuePair<string, string>> list = htmlParser.mInputTypeSubmit;\r
+                if (list.Count > 0)\r
+                {\r
+                    args[6] = list[0].Value;\r
+                    return writeRes(args, htmlParser.mInputTypeHidden);\r
+                }\r
+\r
+            }\r
+            return false;\r
+        }\r
+\r
+        private bool writeResMachiBBS(string[] args, List<KeyValuePair<string, string>> extra)\r
+        {\r
+            //string host, bbs;\r
+            string name = args[3];\r
+            string mail = args[4];\r
+            string msg = args[5];\r
\r
+            //if (!NTHttpUtils.splitMachiAddress(args[0], out host, out bbs))\r
+            //    return false;\r
+\r
+            string key = NTHttpUtils.ridSuffixFromCgiName(args[2]);\r
+\r
+        //            public static string getWriteHtmlMachiBBS(string host, string board, string key)\r
+       // {\r
+            string a1 = "/bbs/read.pl?IMODE=TRUE&KEY=";//1341122306\r
+            string a2 = "&BBS=";//tokyo\r
+            string a3 = "&WRITEBOX=TRUE";\r
+\r
+            string url1 = "http://"+args[0] + a1 + key + a2 + args[1] + a3;\r
+\r
+\r
+            //string writeHtml = NTHttpAccess.getWriteHtmlMachiBBS(url1);\r
+            string writeHtml = NTHttpAccess.getWriteHtmlExternalBBS(args[0], url1);\r
+            if (writeHtml == null || writeHtml.Length == 0)\r
+                return false;\r
+\r
+            NTHtmlParser parser = new NTHtmlParser(new FlowDocument());\r
+            string resultStr = parser.parse(writeHtml);\r
+\r
+\r
+            NTDebug.l(resultStr);\r
+\r
+            Encoding enc = Encoding.GetEncoding(NTAppState.HOST_2CH_ENCODING);\r
+\r
+            List<KeyValuePair<string, string>> fAttr = parser.mFormAttributes;\r
+            if (fAttr == null)\r
+                return false;\r
+            string url2 = null;\r
+            //\r
+            foreach (KeyValuePair<string, string> pair in fAttr)\r
+            {\r
+                if (pair.Key.Equals("action", StringComparison.CurrentCultureIgnoreCase))\r
+                {\r
+                    string s = pair.Value;\r
+                    int idx = s.IndexOf('/');\r
+                    if(idx < 0)\r
+                        break;\r
+                    s = s.Substring(idx);\r
+                    idx = s.IndexOf('?');\r
+                    if(idx >= 0)\r
+                        s = s.Substring(0,idx);\r
+                    url2 = "http://" + args[0] + "/bbs" + s;\r
+                    break;\r
+                }\r
+            }\r
+            if(url2 == null)\r
+                return false;\r
+\r
+            StringBuilder postData = new StringBuilder(256);\r
+            \r
+            postData.Append("NAME=").Append(HttpUtility.UrlEncode(name, enc));\r
+            postData.Append("&MAIL=").Append(HttpUtility.UrlEncode(mail, enc));\r
+            foreach(KeyValuePair<string,string> pair3 in parser.mInputTypeHidden)\r
+            {\r
+                string val = HttpUtility.UrlEncode(pair3.Value, enc);\r
+                NTDebug.l(val + " :"+val.Length);\r
+\r
+                postData.Append('&').Append(pair3.Key).Append('=')\r
+                    .Append(val);\r
+            }\r
+            postData.Append("&MESSAGE=").Append(HttpUtility.UrlEncode(msg, enc));\r
+\r
+\r
+\r
+            NTDebug.l(postData.ToString());\r
+\r
+            resultStr = NTHttpAccess.writeResExternalBBS(url2, url1, "http://" + args[0], postData.ToString());\r
+\r
+            NTDebug.l(resultStr);\r
+\r
+            if (resultStr == null)\r
+            {\r
+                MessageBox.Show("サーバーの応答が不正です");\r
+                return false;\r
+            }\r
+\r
+            FlowDocument doc = new FlowDocument();\r
+            parser = new NTHtmlParser(doc);\r
+            parser.parse(resultStr);\r
+\r
+            X_CONFIRM_RESULT xResult = NTHtmlWriteResParser.validateResult(parser);\r
+            if (xResult != X_CONFIRM_RESULT.ERROR)\r
+                return true;\r
+\r
+            NTWriteResResultWindow w\r
+                = new NTWriteResResultWindow(parser.getTitle(), doc, xResult);\r
+            w.Owner = this;\r
+            bool? result = w.ShowDialog();\r
+            if (result.HasValue && ((bool)result))\r
+            {\r
+                List<KeyValuePair<string, string>> list = parser.mInputTypeSubmit;\r
+                if (list.Count > 0)\r
+                {\r
+                    args[6] = list[0].Value;\r
+                    return writeResMachiBBS(args, parser.mInputTypeHidden);\r
+                }\r
+\r
+            }\r
+            return false;\r
+        }\r
+\r
+\r
+\r
+\r
+        private List<KeyValuePair<string,string>> \r
+                parseWriteResPostParams(NTHtmlParser parser, string key, string from, string mail, string msg)\r
+        {\r
+\r
+            List<KeyValuePair<string, string>> pLIst = new List<KeyValuePair<string, string>>();\r
+\r
+            bool setSubmit = false;\r
+            foreach (KeyValuePair<string, string> pair in parser.mInputTypeSubmit)\r
+            {\r
+                string v = pair.Value;\r
+                if (v.Contains("W") || v.Contains("書"))\r
+                {\r
+                    pLIst.Add(pair);\r
+                    setSubmit = true;\r
+                    break;\r
+                }\r
+            }\r
+            if(!setSubmit)\r
+                return null;\r
+\r
+            bool setKey = false;\r
+            foreach (KeyValuePair<string, string> pair in parser.mInputTypeHidden)\r
+            {\r
+                string k = pair.Key;\r
+                bool dup = false;\r
+                    \r
+                switch (k)\r
+                {\r
+                    case "KEY":\r
+                    case "key":\r
+                        if (!setKey)\r
+                        {\r
+                            pLIst.Add(new KeyValuePair<string, string>(k, key));\r
+                            setKey = true;\r
+                        }\r
+                        break;\r
+                    default:\r
+                        foreach (KeyValuePair<string, string> pair2 in pLIst)\r
+                        {\r
+                            if (pair2.Key.Equals(k, StringComparison.CurrentCultureIgnoreCase))\r
+                            {\r
+                                dup = true;\r
+                                break;\r
+                            }\r
+                        }\r
+                        if(!dup)\r
+                            pLIst.Add(pair);\r
+                        break;\r
+\r
+                }\r
+            }\r
+\r
+            bool setFrom = false;\r
+            bool setMail = false;\r
+            foreach (KeyValuePair<string, string> pair in parser.mInputTypeText)\r
+            {\r
+                string k = pair.Key;\r
+                 switch (k)\r
+                {\r
+                    case "FROM":\r
+                    case "from":\r
+                    case "name":\r
+                    case "NAME":\r
+                        if (!setFrom)\r
+                        {\r
+                            pLIst.Add(new KeyValuePair<string, string>(k, from));\r
+                            setFrom = true;\r
+                        }\r
+                        break;\r
+                    case "mail":\r
+                    case "MAIL":\r
+                    case "TO":\r
+                    case "to":\r
+                        if (!setMail)\r
+                        {\r
+                            pLIst.Add(new KeyValuePair<string, string>(k, mail));\r
+                            setMail = true;\r
+                        }\r
+                        break;\r
+                }\r
+                if (setFrom && setMail)\r
+                    break;\r
+            }\r
+            if (!setMail || !setMail)\r
+                return null;\r
+\r
+            bool setMsg = false;\r
+            foreach (KeyValuePair<string, string> pair in parser.mTextAreaAttributes)\r
+            {\r
+                string v = pair.Value;\r
+                switch (v)\r
+                {\r
+                    case "MESSAGE":\r
+                    case "message":\r
+                        if (!setMsg)\r
+                        {\r
+                            pLIst.Add(new KeyValuePair<string, string>(v, msg));\r
+                            setMsg = true;\r
+                        }\r
+                        break;\r
+                }\r
+                if (setMsg)\r
+                    break;\r
+\r
+            }\r
+            if (!setMsg)\r
+                return null;\r
+\r
+            return pLIst;\r
+        }\r
+\r
+\r
+        private bool writeResExternalBBS(string baseUrl, string[] args, List<KeyValuePair<string, string>> extra)\r
+        {\r
+            string host = args[0];//, bbs;\r
+            string name = args[3];\r
+            string mail = args[4];\r
+            string msg = args[5];\r
+\r
+\r
+            string key = args[2];\r
+            int idx = baseUrl.IndexOf(host);\r
+            if (idx < 0)\r
+                return false;\r
+            idx += host.Length;\r
+            string url = baseUrl.Substring(0, idx) + "/test/read.cgi" + \r
+                baseUrl.Substring(idx) + key + '/';\r
+            NTHtmlParser parser = null;\r
+            string resultStr = null;\r
+\r
+            Mouse.OverrideCursor = Cursors.Wait;\r
+\r
+            try\r
+            {\r
+\r
+                string writeHtml = NTHttpAccess.getWriteHtmlExternalBBS(host, url);\r
+                if (writeHtml != null && writeHtml.Length > 0)\r
+                {\r
+                    parser = new NTHtmlParser(new FlowDocument());\r
+                    resultStr = parser.parse(writeHtml);\r
+                }\r
+\r
+                if (writeHtml == null || parser == null ||\r
+                    parser.mFormAttributes.Count == 0 || parser.mInputTypeHidden.Count == 0)\r
+                {\r
+                    url = baseUrl;\r
+                    writeHtml = NTHttpAccess.getWriteHtmlExternalBBS(host, url);\r
+                    if (writeHtml == null || writeHtml.Length == 0)\r
+                        return false;\r
+\r
+                    parser = new NTHtmlParser(new FlowDocument());\r
+                    resultStr = parser.parse(writeHtml);\r
+                    if (parser.mFormAttributes.Count == 0 || parser.mInputTypeHidden.Count == 0)\r
+                        return false;\r
+                }\r
+\r
+                string newUrl = NTHtmlUtils.parseActionUrl(host, url, parser);\r
+\r
+                if (newUrl == null)\r
+                    return false;\r
+\r
+                List<KeyValuePair<string, string>> pList = parseWriteResPostParams(parser, key, name, mail, msg);\r
+                if (pList == null)\r
+                    return false;\r
+\r
+                Encoding enc = Encoding.GetEncoding(NTAppState.HOST_2CH_ENCODING);\r
+                StringBuilder postData = new StringBuilder(256);\r
+\r
+                foreach (KeyValuePair<string, string> pair in pList)\r
+                {\r
+                    if (postData.Length != 0)\r
+                        postData.Append('&');\r
+                    postData.Append(pair.Key).Append('=')\r
+                        .Append(HttpUtility.UrlEncode(pair.Value, enc));\r
+\r
+                }\r
+\r
+                NTDebug.l(postData.ToString());\r
+\r
+                resultStr = NTHttpAccess.writeResExternalBBS(newUrl, url, args[0], postData.ToString());\r
+            }\r
+            finally\r
+            {\r
+                Mouse.OverrideCursor = null;\r
+            }\r
+\r
+            NTDebug.l(resultStr);\r
+            if (resultStr == null)\r
+            {\r
+                MessageBox.Show("サーバーの応答が不正です");\r
+                return false;\r
+            }\r
+\r
+            FlowDocument doc = new FlowDocument();\r
+            parser = new NTHtmlParser(doc);\r
+            parser.parse(resultStr);\r
+\r
+            X_CONFIRM_RESULT xResult = NTHtmlWriteResParser.validateResult(parser);\r
+            if (xResult != X_CONFIRM_RESULT.ERROR)\r
+                return true;\r
+\r
+            NTWriteResResultWindow w\r
+                = new NTWriteResResultWindow(parser.getTitle(), doc, xResult);\r
+            w.Owner = this;\r
+            bool? result = w.ShowDialog();\r
+            return false;\r
+        }\r
+\r
+\r
+        private void chkSage_Checked(object sender, RoutedEventArgs e)\r
+        {\r
+            NTDebug.l("checked!");\r
+            NTUserPreference.SageIsEnabled = true;\r
+            //NTUserPreference.savePreferences();\r
+        }\r
+\r
+        private void chkSage_Unchecked(object sender, RoutedEventArgs e)\r
+        {\r
+            NTDebug.l("unchecked!");\r
+            NTUserPreference.SageIsEnabled = false;\r
+            //NTUserPreference.savePreferences();\r
+        }\r
+        private void chkWriteTroughP2_Checked(object sender, RoutedEventArgs e)\r
+        {\r
+            //NTDebug.l("checked!");\r
+            NTUserPreference.P2IsEnabled = true;\r
+           // NTUserPreference.savePreferences();\r
+        }\r
+\r
+        private void chkWriteTroughP2_Unchecked(object sender, RoutedEventArgs e)\r
+        {\r
+            //NTDebug.l("checked!");\r
+            NTUserPreference.P2IsEnabled = false;\r
+            //NTUserPreference.savePreferences();\r
+        }\r
+\r
+        private void storeMsgToHistory()\r
+        {\r
+            string msg = txtMsg.Text;\r
+\r
+            if (msg.Length == 0)\r
+                return;\r
+\r
+\r
+            string newMsg = NTTextFormat.convertLineBreakToHtmlTag(msg);\r
+\r
+            NTPersistentFileAccess.storeWriteHistory(newMsg);\r
+\r
+        }\r
+\r
+        //bool mLeftShift = false;\r
+        //bool mRightShift = false;\r
+        private void NTWriteResWindow_PreviewKeyDown(object sender, KeyEventArgs e)\r
+        {\r
+            switch (e.Key)\r
+            {\r
+                case Key.LeftShift:\r
+                   // mLeftShift = true;\r
+                    break;\r
+                case Key.RightShift:\r
+                    //mRightShift = true;\r
+                    break;\r
+                case Key.Enter:\r
+                    if(Keyboard.Modifiers == ModifierKeys.Shift)\r
+                    //if (mLeftShift || mRightShift)\r
+                    {\r
+                        NTDebug.l("Pressed Shift + Enter!");\r
+                        WriteRes_Invoke();\r
+                        e.Handled = true;\r
+                    }\r
+                    break;\r
+                case Key.Escape:\r
+                    if (Keyboard.Modifiers == ModifierKeys.Shift)\r
+                    {\r
+                        NTDebug.l("Pressed ESC!");\r
+                        e.Handled = true;\r
+                        storeMsgToHistory();\r
+                        Close();\r
+                    }\r
+                    break;\r
+            }\r
+        }\r
+\r
+        private void NTWriteResWindow_PreviewKeyUp(object sender, KeyEventArgs e)\r
+        {\r
+            if (e.Key == Key.LeftShift)\r
+            {\r
+                //mLeftShift = false;\r
+            }\r
+            else if (e.Key == Key.RightShift)\r
+            {\r
+                //mRightShift = false;\r
+            }\r
+        }\r
+\r
+        private void btnWriteHistory_Click(object sender, RoutedEventArgs e)\r
+        {\r
+            NTWriteResHistoryPopup popup = new NTWriteResHistoryPopup(this, mHistory);\r
+            popup.show();\r
+        }\r
+\r
+        public void setMsg(string msg)\r
+        {\r
+            txtMsg.Text = msg;\r
+        }\r
+    }\r
+}\r
diff --git a/NT2chView45/NtFile/NTFileAccess.cs b/NT2chView45/NtFile/NTFileAccess.cs
new file mode 100755 (executable)
index 0000000..1135e33
--- /dev/null
@@ -0,0 +1,1526 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.IO;\r
+using NT2chView.NtNet;\r
+\r
+\r
+namespace NT2chView.NtFile\r
+{\r
+    \r
+\r
+    sealed class NTFileAccess\r
+    {\r
+        const string ROOTDIR_NAME = @"\Data";\r
+        const string IMAGE_DIR = @"Images";\r
+        const string BOARDMENU_DIR_NAME = @"\BoardMenu";\r
+        const string BOARDMENU_FILE_NAME = @"\BoardMenu.txt";\r
+        const string BOARDMENU_ATTR_FILE_NAME = @"\BoardMenuAttr.txt";\r
+        const string PATH_PEPARATOR = @"\";\r
+        const string SUBJECT_TXT_FILE_NAME = @"\Subject.txt";\r
+        const string SUBJECT_ATTR_FILE_NAME = @"\SubjectAttr.txt";\r
+        const string DAT_FILE_NAME = @"\dat.txt";\r
+        const string DAT_ATTR_FILE_NAME = @"\attr.txt";\r
+        const string DAT_ATTR_B_FILE_NAME = @"\b_attr.txt";\r
+        const string DAT_FILE_SUFFIX = @".dat";\r
+        const string COOKIE_DIR_NAME = @"\Cookie";\r
+        const string FAVORITE_BOARD_LIST_FILE_NAME = @"\FavoriteBoards.txt";\r
+        const string FAVORITE_THREAD_LIST_FILE_NAME = @"\FavoriteThreads.txt";\r
+        const string FAVORITE_THREAD_TAG_LIST_FILE_NAME = @"\FavoriteThreadTag.txt";\r
+        const string FAVORITE_BOARD_ATTR_FILE_NAME = @"\FavoriteBoardsAttr.txt";\r
+        const string FAVORITE_THREAD_ATTR_FILE_NAME = @"\FavoriteThreadsAttr.txt";\r
+        const string FAVORITE_THREAD_TAG_ATTR_FILE_NAME = @"\FavoriteThreadTagAttr.txt";\r
+        const string AES_FAVORITE_BOARD_LIST_FILE_NAME = @"\AesFavoriteBoards.txt";\r
+        const string AES_FAVORITE_THREAD_LIST_FILE_NAME = @"\AesFavoriteThreads.txt";\r
+        const string AES_FAVORITE_THREAD_TAG_LIST_FILE_NAME = @"\AesFavoriteThreadTag.txt";\r
+        const string AES_FAVORITE_BOARD_ATTR_FILE_NAME = @"\AesFavoriteBoardsAttr.txt";\r
+        const string AES_FAVORITE_THREAD_ATTR_FILE_NAME = @"\AesFavoriteThreadsAttr.txt";\r
+        const string AES_FAVORITE_THREAD_TAG_ATTR_FILE_NAME = @"\AesFavoriteThreadTagAttr.txt";\r
+        \r
+        public const string NGWORD_FILE_NAME = @"\NgWord.txt";\r
+        public const string NGWORD_ATTR_FILE_NAME = @"\NgWordAttr.txt";\r
+        public const string NGID_FILE_NAME = @"\NgId.txt";\r
+        public const string NGID_ATTR_FILE_NAME = @"\NgIdAttr.txt";\r
+        public const string NGNAME_FILE_NAME = @"\NgName.txt";\r
+        public const string NGNAME_ATTR_FILE_NAME = @"\NgNameAttr.txt";\r
+\r
+        public const string EXTERNAL_BOARD_FILE_NAME = @"\ExteranlBoard.txt";\r
+        const string EXTERNALBOARD_ATTR_FILE_NAME = @"\ExternalBoardAttr.txt";\r
+        public const string THREAD_HISTORY_LIST_FILE_NAME = @"\ThreadHistory.txt";\r
+        const string THREAD_HISTORY_LIST_ATTR_FILE_NAME = @"\ThreadHistoryAttr.txt";\r
+\r
+        public const string AES_NGWORD_FILE_NAME = @"\AesNgWord.txt";\r
+        public const string AES_NGWORD_ATTR_FILE_NAME = @"\AesNgWordAttr.txt";\r
+        public const string AES_NGID_FILE_NAME = @"\AesNgId.txt";\r
+        public const string AES_NGID_ATTR_FILE_NAME = @"\AesNgIdAttr.txt";\r
+        public const string AES_NGNAME_FILE_NAME = @"\AesNgName.txt";\r
+        public const string AES_NGNAME_ATTR_FILE_NAME = @"\AesNgNameAttr.txt";\r
+\r
+        public const string MOVIE_HISTORY_LIST_FILE_NAME = @"\MovieHistory.txt";\r
+\r
+        /*public const string AES_EXTERNAL_BOARD_FILE_NAME = @"\AesExteranlBoard.txt";\r
+        const string AES_EXTERNALBOARD_ATTR_FILE_NAME = @"\AesExternalBoardAttr.txt";\r
+        public const string AES_THREAD_HISTORY_LIST_FILE_NAME = @"\AesThreadHistory.txt";\r
+        const string AES_THREAD_HISTORY_LIST_ATTR_FILE_NAME = @"\AesThreadHistoryAttr.txt";*/\r
+\r
+\r
+        static string mRootPath = null;\r
+        //static byte[] mByteBuffer = new byte[1024*2];\r
+\r
+        public static string getRootPath()\r
+        {\r
+            return mRootPath + PATH_PEPARATOR;\r
+        }\r
+\r
+        public static string getImageDir()\r
+        {\r
+            return getRootPath() + IMAGE_DIR + PATH_PEPARATOR;\r
+        }\r
+\r
+        public static string[] retrieveThreadHistoryList()\r
+        {\r
+            string path = mRootPath + THREAD_HISTORY_LIST_FILE_NAME;\r
+            string[] results = null;\r
+            try\r
+            {\r
+                results = File.ReadAllLines(path);\r
+            }\r
+            catch (Exception ex)\r
+            {\r
+                NTDebug.l(ex.Message);\r
+            }\r
+            return results;\r
+        }\r
+\r
+        public static void writeThreadHistoryList(string[] threadDescriptions)\r
+        {\r
+            string path = mRootPath + THREAD_HISTORY_LIST_FILE_NAME;\r
+            try\r
+            {\r
+                File.WriteAllLines(path, threadDescriptions);\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+        }\r
+\r
+        public static string[] retrieveExternalBoards()\r
+        {\r
+            string path = mRootPath + EXTERNAL_BOARD_FILE_NAME;\r
+            string[] results = null;\r
+            try\r
+            {\r
+                results = File.ReadAllLines(path);\r
+            }\r
+            catch (Exception ex)\r
+            {\r
+                NTDebug.l(ex.Message);\r
+            }\r
+            return results;\r
+        }\r
+\r
+        public static void writeExternalBoards(string [] externalBoards)\r
+        {\r
+            string path = mRootPath + EXTERNAL_BOARD_FILE_NAME;\r
+            try\r
+            {\r
+                File.WriteAllLines(path, externalBoards);\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+        }\r
+\r
+        public static void appendExternalBoard(string boardDiscription)\r
+        {\r
+            string path = mRootPath + EXTERNAL_BOARD_FILE_NAME;\r
+            FileStream fs = null;\r
+            StreamWriter sw = null;\r
+            try\r
+            {\r
+                fs = File.Open(path, FileMode.Append, FileAccess.Write);\r
+                sw = new StreamWriter(fs);\r
+                sw.WriteLine(boardDiscription);\r
+                sw.Flush();\r
+                fs.Flush();\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+            finally\r
+            {\r
+                if (null != sw)\r
+                    sw.Close();\r
+                if (null != fs)\r
+                    fs.Close();\r
+            }\r
+        }\r
+\r
+        public static void ntWriteNgWordsToFile(List<string> list)\r
+        {\r
+            string path;\r
+            if(NTUserPreference.AESEnabled)\r
+                path = mRootPath + AES_NGWORD_FILE_NAME;\r
+            else\r
+                path = mRootPath + NGWORD_FILE_NAME;\r
+            \r
+            int len = list.Count;\r
+            List<string> arr = new List<string>();\r
+            for (int i = 0; i < len; i++)\r
+            {\r
+                string s = list[i].Trim();\r
+                if (s.Length == 0)\r
+                    continue;\r
+                if (NTUserPreference.AESEnabled)\r
+                    s = NTTextUtiles.aesEncodeBase64URL(s);\r
+                else\r
+                    s = NTTextUtiles.encodeBase64URL(s);\r
+                arr.Add(s);\r
+            }\r
+            File.WriteAllLines(path, arr.ToArray());\r
+        }\r
+        public static void ntWriteNgIdsToFile(List<string> list)\r
+        {\r
+            string path;\r
+            if(NTUserPreference.AESEnabled)\r
+                path = mRootPath + AES_NGID_FILE_NAME;\r
+            else\r
+                path = mRootPath + NGID_FILE_NAME;\r
+            \r
+            int len = list.Count;\r
+            List<string> arr = new List<string>();\r
+            for (int i = 0; i < len; i++)\r
+            {\r
+                string s = list[i].Trim();\r
+                if (s.Length == 0)\r
+                    continue;\r
+                if (NTUserPreference.AESEnabled)\r
+                    s = NTTextUtiles.aesEncodeBase64URL(s);\r
+                else\r
+                    s = NTTextUtiles.encodeBase64URL(s);\r
+                arr.Add(s);\r
+            }\r
+            File.WriteAllLines(path, arr.ToArray());\r
+        }\r
+        public static void ntWriteNgNamesToFile(List<string> list)\r
+        {\r
+            string path;\r
+            if(NTUserPreference.AESEnabled)\r
+                path = mRootPath + AES_NGNAME_FILE_NAME;\r
+            else\r
+                path = mRootPath + NGNAME_FILE_NAME;\r
+            \r
+            int len = list.Count;\r
+            List<string> arr = new List<string>();\r
+            for (int i = 0; i < len; i++)\r
+            {\r
+                string s = list[i].Trim();\r
+                if (s.Length == 0)\r
+                    continue;\r
+                if(NTUserPreference.AESEnabled)\r
+                    s = NTTextUtiles.aesEncodeBase64URL(s);\r
+                else\r
+                    s = NTTextUtiles.encodeBase64URL(s);\r
+                    \r
+                arr.Add(s);\r
+            }\r
+            File.WriteAllLines(path, arr.ToArray());\r
+        }\r
+\r
+        public static void saveCookie(List<KeyValuePair<string, string>> list, string host)\r
+        {\r
+            string cookieDirPath = mRootPath + COOKIE_DIR_NAME;\r
+\r
+            DirectoryInfo dir = new DirectoryInfo(cookieDirPath);\r
+            if (!dir.Exists)\r
+                dir.Create();\r
+\r
+            //if (host == null)\r
+            //    host = COOKIE_ROOT_NAME;\r
+\r
+            string filePath = cookieDirPath + PATH_PEPARATOR + host;\r
+\r
+            FileStream fs = null;\r
+            StreamWriter sw = null;\r
+\r
+            try\r
+            {\r
+                fs = new FileStream(filePath, FileMode.Create, FileAccess.Write);\r
+                sw = new StreamWriter(fs);\r
+\r
+                foreach (KeyValuePair<string, string> pair in list)\r
+                {\r
+                    string key = pair.Key;\r
+                    string value = pair.Value;\r
+                    if (key != null && value != null)\r
+                        sw.WriteLine(key + "=" + value);\r
+                }\r
+                sw.Flush();\r
+                fs.Flush();\r
+            }\r
+            finally\r
+            {\r
+                if (null != sw)\r
+                    sw.Close();\r
+                if (null != fs)\r
+                    fs.Close();\r
+            }\r
+        }\r
+\r
+        public static List<KeyValuePair<string, string>> retrieveCookie(string host)\r
+        {\r
+\r
+            List<KeyValuePair<string, string>> result \r
+                = new List<KeyValuePair<string, string>>();\r
+\r
+            string cookieDirPath = mRootPath + COOKIE_DIR_NAME;\r
+\r
+            DirectoryInfo dir = new DirectoryInfo(cookieDirPath);\r
+            if (!dir.Exists)\r
+                dir.Create();\r
+\r
+            \r
+            string filePath = cookieDirPath + PATH_PEPARATOR + host;\r
+\r
+            FileStream fs = null;\r
+            StreamReader sr = null;\r
+\r
+            try\r
+            {\r
+                fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);\r
+                sr = new StreamReader(fs);\r
+\r
+                string line;\r
+                while (null != (line = sr.ReadLine()))\r
+                {\r
+                    int idx = line.IndexOf("=");\r
+                    if (idx < 0)\r
+                        continue;\r
+\r
+                    string key = line.Substring(0, idx);\r
+                    string value = line.Substring(idx + 1);\r
+                    KeyValuePair<string, string> pair = new KeyValuePair<string, string>(key, value);\r
+                    result.Add(pair);\r
+                }\r
+            }\r
+            catch(Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+            finally\r
+            {\r
+                if (null != sr)\r
+                    sr.Close();\r
+                if (null != fs)\r
+                    fs.Close();\r
+            }\r
+            return result;\r
+        }\r
+\r
+\r
+\r
+        public static bool init(string rootPath)\r
+        {\r
+            bool bRet = false;\r
+            try\r
+            {\r
+                NTPersistentFileAccess.init(rootPath);\r
+                mRootPath = rootPath + ROOTDIR_NAME;\r
+                DirectoryInfo dir = new DirectoryInfo(mRootPath);\r
+                if (!dir.Exists)\r
+                    dir.Create();\r
+\r
+                bRet = true;\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+            finally\r
+            {\r
+            }\r
+            return bRet;\r
+\r
+\r
+        }\r
+\r
+        public static void storeBoardMenuAttrToFile(string attr)\r
+        {\r
+            string boardPath = mRootPath + BOARDMENU_DIR_NAME;\r
+            DirectoryInfo dir = new DirectoryInfo(boardPath);\r
+            if (!dir.Exists)\r
+                dir.Create();\r
+\r
+            string boardAttrFileAbsolutePath = boardPath + BOARDMENU_ATTR_FILE_NAME;\r
+\r
+            File.WriteAllText(boardAttrFileAbsolutePath, attr);\r
+        }\r
+        public static bool storeBoardMenuDataToFile(Stream stream)\r
+        {\r
+            string boardPath = mRootPath + BOARDMENU_DIR_NAME;\r
+            byte[] bBuf = new byte[1024 * 2];\r
+            FileStream fStream = null;\r
+            bool bRet = false;\r
+            try\r
+            {\r
+                DirectoryInfo dir = new DirectoryInfo(boardPath);\r
+                if (!dir.Exists)\r
+                    dir.Create();\r
+\r
+                string boardFileAbsolutePath = boardPath + BOARDMENU_FILE_NAME;\r
+                fStream = File.Open(boardFileAbsolutePath, FileMode.Create, FileAccess.Write);\r
+                int numRead;\r
+                while (0 < (numRead = stream.Read(bBuf, 0, bBuf.Length)))\r
+                {\r
+                    fStream.Write(bBuf, 0, numRead);\r
+                }\r
+                bRet = true;\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+            finally\r
+            {\r
+                if (null != fStream)\r
+                    fStream.Close();\r
+            }\r
+            return bRet;\r
+        }\r
+\r
+        public static string retrieveBoardMenuAttrFromFile()\r
+        {\r
+            string boardPath = mRootPath + BOARDMENU_DIR_NAME;\r
+            string retStr = null;\r
+            DirectoryInfo dir = new DirectoryInfo(boardPath);\r
+            if (!dir.Exists)\r
+                return null;\r
+\r
+            string boardAttrFileAbsolutePath = boardPath + BOARDMENU_ATTR_FILE_NAME;\r
+\r
+            try\r
+            {\r
+                retStr = File.ReadAllText(boardAttrFileAbsolutePath);\r
+            }\r
+            catch\r
+            {\r
+            }\r
+            return retStr;\r
+        }\r
+        public static string retrieveBoardMenuDataFromFile()\r
+        {\r
+            string retStr = null;\r
+            string boardPath = mRootPath + BOARDMENU_DIR_NAME;\r
+            FileStream fStream = null;\r
+            StreamReader sr = null;\r
+\r
+            try\r
+            {\r
+                Encoding enc = Encoding.GetEncoding(NTAppState.HOST_2CH_ENCODING);\r
+\r
+                DirectoryInfo dir = new DirectoryInfo(boardPath);\r
+                if (!dir.Exists)\r
+                    return null;\r
+                \r
+                string boardFileAbsolutePath = boardPath + BOARDMENU_FILE_NAME;\r
+                fStream = File.OpenRead(boardFileAbsolutePath);\r
+                sr = new StreamReader(fStream, enc);\r
+                retStr = sr.ReadToEnd();\r
+                \r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+            finally\r
+            {\r
+                if (null != fStream)\r
+                    fStream.Close();\r
+                if (null != sr)\r
+                    sr.Close();\r
+            }\r
+\r
+            return retStr;\r
+        }\r
+\r
+        public static string retrieveSubjectAttrFromFile(string boardName)\r
+        {\r
+            string subjectPath = mRootPath + PATH_PEPARATOR + boardName;\r
+            string retStr = null;\r
+            DirectoryInfo dir = new DirectoryInfo(subjectPath);\r
+            if (!dir.Exists)\r
+                return null;\r
+\r
+            string subjectAttrFileAbsolutePath = subjectPath + SUBJECT_ATTR_FILE_NAME;\r
+\r
+            try\r
+            {\r
+                retStr = File.ReadAllText(subjectAttrFileAbsolutePath);\r
+            }\r
+            catch\r
+            {\r
+            }\r
+            return retStr;\r
+        }\r
+        public static void storeSubjectAttrToFile(string ifMod, string boardName)\r
+        {\r
+            string subjectPath = mRootPath + PATH_PEPARATOR + boardName;\r
+            DirectoryInfo dir = new DirectoryInfo(subjectPath);\r
+            if (!dir.Exists)\r
+                dir.Create();\r
+\r
+            string subjectAttrFileAbsolutePath = subjectPath + SUBJECT_ATTR_FILE_NAME;\r
+\r
+            File.WriteAllText(subjectAttrFileAbsolutePath, ifMod);\r
+\r
+        }\r
+\r
+        public static bool storeSubjectDataToFile(Stream stream, string boardName)\r
+        {\r
+            string subjectPath = mRootPath + PATH_PEPARATOR + boardName;\r
+            FileStream fStream = null;\r
+            bool bRet = false;\r
+            byte[] bBuf = new byte[1024 * 2];\r
+            try\r
+            {\r
+                DirectoryInfo dir = new DirectoryInfo(subjectPath);\r
+                if (!dir.Exists)\r
+                    dir.Create();\r
+\r
+                string boardFileAbsolutePath = subjectPath + SUBJECT_TXT_FILE_NAME;\r
+                fStream = File.Open(boardFileAbsolutePath, FileMode.Create, FileAccess.Write);\r
+                int numRead;\r
+                while (0 < (numRead = stream.Read(bBuf, 0, bBuf.Length)))\r
+                {\r
+                    fStream.Write(bBuf, 0, numRead);\r
+                }\r
+                fStream.Flush();\r
+                bRet = true;\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+            finally\r
+            {\r
+                if (null != fStream)\r
+                    fStream.Close();\r
+            }\r
+            return bRet;\r
+        }\r
+\r
+        public static bool isSubjectExsists(string boardName)\r
+        {\r
+\r
+            string path = mRootPath + PATH_PEPARATOR + boardName + SUBJECT_TXT_FILE_NAME;\r
+            FileInfo info = new FileInfo(path);\r
+            return info.Exists;\r
+        }\r
+\r
+        public static void deleteCloudLastModified()\r
+        {\r
+            FileInfo fi = new FileInfo(mRootPath + FAVORITE_BOARD_ATTR_FILE_NAME);\r
+            fi.Delete();\r
+            fi = new FileInfo(mRootPath + FAVORITE_THREAD_ATTR_FILE_NAME);\r
+            fi.Delete();\r
+            fi = new FileInfo(mRootPath + FAVORITE_THREAD_TAG_ATTR_FILE_NAME);\r
+            fi.Delete();\r
+            fi = new FileInfo(mRootPath + AES_FAVORITE_BOARD_ATTR_FILE_NAME);\r
+            fi.Delete();\r
+            fi = new FileInfo(mRootPath + AES_FAVORITE_THREAD_ATTR_FILE_NAME);\r
+            fi.Delete();\r
+            fi = new FileInfo(mRootPath + AES_FAVORITE_THREAD_TAG_ATTR_FILE_NAME);\r
+            fi.Delete();\r
+            fi = new FileInfo(mRootPath + NGWORD_ATTR_FILE_NAME);\r
+            fi.Delete();\r
+            fi = new FileInfo(mRootPath + NGID_ATTR_FILE_NAME);\r
+            fi.Delete();\r
+            fi = new FileInfo(mRootPath + NGNAME_ATTR_FILE_NAME);\r
+            fi.Delete();\r
+            fi = new FileInfo(mRootPath + EXTERNALBOARD_ATTR_FILE_NAME);\r
+            fi.Delete();\r
+            fi = new FileInfo(mRootPath + THREAD_HISTORY_LIST_ATTR_FILE_NAME);\r
+            fi.Delete();\r
+            fi = new FileInfo(mRootPath + AES_NGWORD_ATTR_FILE_NAME);\r
+            fi.Delete();\r
+            fi = new FileInfo(mRootPath + AES_NGID_ATTR_FILE_NAME);\r
+            fi.Delete();\r
+            fi = new FileInfo(mRootPath + AES_NGNAME_ATTR_FILE_NAME);\r
+            fi.Delete();        \r
+        }\r
+\r
+        public static string retrieveSubjectDataFromFile(string boardName)\r
+        {\r
+            string retStr = null;\r
+            string subjectPath = mRootPath + PATH_PEPARATOR + boardName;\r
+            FileStream fStream = null;\r
+            StreamReader sr = null;\r
+\r
+            try\r
+            {\r
+                Encoding enc = Encoding.GetEncoding(NTAppState.HOST_2CH_ENCODING);\r
+\r
+                DirectoryInfo dir = new DirectoryInfo(subjectPath);\r
+                if (!dir.Exists)\r
+                    return null;\r
+\r
+                string boardFileAbsolutePath = subjectPath + SUBJECT_TXT_FILE_NAME;\r
+                fStream = File.OpenRead(boardFileAbsolutePath);\r
+                sr = new StreamReader(fStream, enc);\r
+                retStr = sr.ReadToEnd();\r
+\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+            finally\r
+            {\r
+                if (null != fStream)\r
+                    fStream.Close();\r
+                if (null != sr)\r
+                    sr.Close();\r
+            }\r
+\r
+            return retStr;\r
+        }\r
+\r
+        public static string ridSuffixFromDatName(string datName)\r
+        {\r
+            int n1 = datName.IndexOf(".dat");\r
+            if (n1 >= 0)\r
+                datName = datName.Substring(0, n1);\r
+            n1 = datName.IndexOf(".cgi");\r
+            if (n1 >= 0)\r
+                datName = datName.Substring(0, n1);\r
+            return datName;\r
+        }\r
+\r
+\r
+        public static string[] retrieveDatAttrBinFromFile(string boardName, string datName)\r
+        {\r
+            datName = ridSuffixFromDatName(datName);\r
+\r
+            string[] retStr = null;\r
+            string datPath = mRootPath + PATH_PEPARATOR + boardName + PATH_PEPARATOR + datName;\r
+            \r
+            string datAttrPath = datPath + DAT_ATTR_B_FILE_NAME;\r
+            try\r
+            {\r
+                retStr = File.ReadAllLines(datAttrPath);\r
+            }\r
+            catch(Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+            return retStr;\r
+        }\r
+\r
+        public static bool addFavoriteBoardToFile(string boardDescription)\r
+        {\r
+            string path;\r
+            if (NTUserPreference.AESEnabled)\r
+            {\r
+                path = mRootPath + AES_FAVORITE_BOARD_LIST_FILE_NAME;\r
+                return aesAddFavoriteToFile(path, boardDescription);\r
+            }\r
+            else\r
+            {\r
+                path = mRootPath + FAVORITE_BOARD_LIST_FILE_NAME;\r
+                return addFavoriteToFile(path, boardDescription);\r
+            }            \r
+        }\r
+\r
+        public static bool updateFavoriteBoardToFile(string [] boardDescriptions)\r
+        {\r
+            string path;\r
+            if (NTUserPreference.AESEnabled)\r
+            {\r
+                path = mRootPath + AES_FAVORITE_BOARD_LIST_FILE_NAME;\r
+                return aesUpdateFavoritesToFile(path, boardDescriptions);\r
+            }\r
+            else\r
+            {\r
+                path = mRootPath + FAVORITE_BOARD_LIST_FILE_NAME;\r
+                return updateFavoritesToFile(path, boardDescriptions);\r
+            }\r
+        }\r
+\r
+        public static bool addFavoriteThreadToFile(string threadDescription)\r
+        {\r
+            string path;\r
+            if (NTUserPreference.AESEnabled)\r
+                path = mRootPath + AES_FAVORITE_THREAD_LIST_FILE_NAME;\r
+            else\r
+                path = mRootPath + FAVORITE_THREAD_LIST_FILE_NAME;\r
+            return addFavoriteToFile(path, threadDescription);\r
+        }\r
+        public static bool addFavoriteThreadTagToFile(string threadDescription)\r
+        {\r
+            string path;\r
+            if (NTUserPreference.AESEnabled)\r
+                path = mRootPath + AES_FAVORITE_THREAD_TAG_LIST_FILE_NAME;\r
+            else\r
+                path = mRootPath + FAVORITE_THREAD_TAG_LIST_FILE_NAME;\r
+            return addFavoriteToFile(path, threadDescription);\r
+        }\r
+\r
+        public static bool updateFavoriteThreadToFile(string[] threadDescriptions)\r
+        {\r
+            string path;\r
+            if (NTUserPreference.AESEnabled)\r
+                path = mRootPath + AES_FAVORITE_THREAD_LIST_FILE_NAME;\r
+            else\r
+                path = mRootPath + FAVORITE_THREAD_LIST_FILE_NAME;\r
+            return updateFavoritesToFile(path, threadDescriptions);\r
+        }\r
+        public static bool updateFavoriteThreadTagToFile(string[] threadTagDescriptions)\r
+        {\r
+            string path;\r
+            if (NTUserPreference.AESEnabled)\r
+                path = mRootPath + AES_FAVORITE_THREAD_TAG_LIST_FILE_NAME;\r
+            else\r
+                path = mRootPath + FAVORITE_THREAD_TAG_LIST_FILE_NAME;\r
+            return updateFavoritesToFile(path, threadTagDescriptions);\r
+        }\r
+\r
+        private static bool addFavoriteToFile(string path, string description)\r
+        {\r
+            string s = NTTextUtiles.encodeBase64URL(description);\r
+            if(s.Length == 0)\r
+                return false;\r
+\r
+            FileStream fs = null;\r
+            StreamWriter sw = null;\r
+            bool bRet = false;\r
+            try\r
+            {\r
+                fs = File.Open(path, FileMode.Append, FileAccess.Write);\r
+                sw = new StreamWriter(fs);\r
+                sw.WriteLine(s);\r
+                sw.Flush();\r
+                fs.Flush();\r
+                bRet = true;\r
+            }\r
+            catch(Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+            finally\r
+            {\r
+                if (sw != null)\r
+                    sw.Close();\r
+                if (fs != null)\r
+                    fs.Close();\r
+            }\r
+            return bRet;\r
+         }\r
+\r
+        private static bool aesAddFavoriteToFile(string path, string description)\r
+        {\r
+            string s = NTTextUtiles.aesEncodeBase64URL(description);\r
+            if (s.Length == 0)\r
+                return false;\r
+\r
+            FileStream fs = null;\r
+            StreamWriter sw = null;\r
+            bool bRet = false;\r
+            try\r
+            {\r
+                fs = File.Open(path, FileMode.Append, FileAccess.Write);\r
+                sw = new StreamWriter(fs);\r
+                sw.WriteLine(s);\r
+                sw.Flush();\r
+                fs.Flush();\r
+                bRet = true;\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+            finally\r
+            {\r
+                if (sw != null)\r
+                    sw.Close();\r
+                if (fs != null)\r
+                    fs.Close();\r
+            }\r
+            return bRet;\r
+        }\r
+\r
+        private static bool updateFavoritesToFile(string path, string [] descriptions)\r
+        {\r
+            \r
+            if (descriptions == null)\r
+                return false;\r
+\r
+            FileStream fs = null;\r
+            StreamWriter sw = null;\r
+            bool bRet = false;\r
+            try\r
+            {\r
+                fs = File.Open(path, FileMode.Create, FileAccess.Write);\r
+                sw = new StreamWriter(fs);\r
+\r
+                foreach (string description in descriptions)\r
+                {\r
+                    if (description == null || description.Length == 0)\r
+                        continue;\r
+                    string s = NTTextUtiles.encodeBase64URL(description);\r
+                    sw.WriteLine(s);\r
+                }\r
+\r
+                sw.Flush();\r
+                fs.Flush();\r
+                bRet = true;\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+            finally\r
+            {\r
+                if (sw != null)\r
+                    sw.Close();\r
+                if (fs != null)\r
+                    fs.Close();\r
+            }\r
+            return bRet;\r
+        }\r
+\r
+        private static bool aesUpdateFavoritesToFile(string path, string[] descriptions)\r
+        {\r
+\r
+            if (descriptions == null)\r
+                return false;\r
+\r
+            FileStream fs = null;\r
+            StreamWriter sw = null;\r
+            bool bRet = false;\r
+            try\r
+            {\r
+                fs = File.Open(path, FileMode.Create, FileAccess.Write);\r
+                sw = new StreamWriter(fs);\r
+\r
+                foreach (string description in descriptions)\r
+                {\r
+                    if (description == null || description.Length == 0)\r
+                        continue;\r
+                    string s = NTTextUtiles.aesEncodeBase64URL(description);\r
+                    sw.WriteLine(s);\r
+                }\r
+\r
+                sw.Flush();\r
+                fs.Flush();\r
+                bRet = true;\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+            finally\r
+            {\r
+                if (sw != null)\r
+                    sw.Close();\r
+                if (fs != null)\r
+                    fs.Close();\r
+            }\r
+            return bRet;\r
+        }\r
+\r
+        \r
+        \r
+        \r
+        public static bool storeFavoriteBoardsToFile(Stream stream, string ifModified, bool append)\r
+        {\r
+            if (NTUserPreference.AESEnabled)\r
+                return storeFavoritesToFile(stream, ifModified, append,\r
+                    AES_FAVORITE_BOARD_LIST_FILE_NAME, AES_FAVORITE_BOARD_ATTR_FILE_NAME);\r
+            else\r
+                return storeFavoritesToFile(stream, ifModified, append,\r
+                    FAVORITE_BOARD_LIST_FILE_NAME, FAVORITE_BOARD_ATTR_FILE_NAME);\r
+\r
+        }\r
+        public static bool storeFavoriteThreadsToFile(Stream stream, string ifModified, bool append)\r
+        {\r
+            if (NTUserPreference.AESEnabled)\r
+                return storeFavoritesToFile(stream, ifModified, append,\r
+                    AES_FAVORITE_THREAD_LIST_FILE_NAME, AES_FAVORITE_THREAD_ATTR_FILE_NAME);\r
+            else\r
+                return storeFavoritesToFile(stream, ifModified, append,\r
+                    FAVORITE_THREAD_LIST_FILE_NAME, FAVORITE_THREAD_ATTR_FILE_NAME);\r
+\r
+        }\r
+\r
+        public static bool storeFavoriteThreadTagToFile(Stream stream, string ifModified, bool append)\r
+        {\r
+            if (NTUserPreference.AESEnabled)\r
+                return storeFavoritesToFile(stream, ifModified, append,\r
+                    AES_FAVORITE_THREAD_TAG_LIST_FILE_NAME, AES_FAVORITE_THREAD_TAG_ATTR_FILE_NAME);\r
+            else\r
+                return storeFavoritesToFile(stream, ifModified, append,\r
+                    FAVORITE_THREAD_TAG_LIST_FILE_NAME, FAVORITE_THREAD_TAG_ATTR_FILE_NAME);\r
+\r
+        }\r
+\r
+        public static bool StreamToFile(string path, Stream st)\r
+        {\r
+            FileStream fStream = null;\r
+            bool bRet = false;\r
+            try\r
+            {\r
+                fStream = File.Open(path, FileMode.Create, FileAccess.Write);\r
+\r
+                int numRead;\r
+                byte[] buf = new byte[1024];\r
+                while (0 < (numRead = st.Read(buf, 0, buf.Length)))\r
+                {\r
+                    fStream.Write(buf, 0, numRead);\r
+                }\r
+\r
+                fStream.Flush();\r
+                fStream.Close();\r
+                fStream = null;\r
+\r
+                bRet = true;\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+            finally\r
+            {\r
+                if (null != fStream)\r
+                    fStream.Close();\r
+            }\r
+            return bRet;\r
+\r
+        }\r
+\r
+        public static bool storeExternalBoardsToFile(Stream stream, string ifModified)\r
+        {\r
+            FileStream fs = null;\r
+            StreamWriter sw = null;\r
+            bool bRet = false;\r
+            try\r
+            {\r
+                string path = mRootPath + EXTERNAL_BOARD_FILE_NAME;\r
+                fs = File.Open(path, FileMode.Create, FileAccess.Write);\r
+                sw = new StreamWriter(fs);\r
+\r
+\r
+\r
+                StreamReader sr = new StreamReader(stream);\r
+                string line;\r
+                while (null != (line = sr.ReadLine()))\r
+                {\r
+                    string decord;\r
+                    if(NTUserPreference.AESEnabled)\r
+                        decord = NTTextUtiles.aesDecodeBase64URL(line);\r
+                    else\r
+                        decord = NTTextUtiles.decodeBase64URL(line);\r
+                    \r
+                    sw.WriteLine(decord);\r
+\r
+                }\r
+                sw.Flush();\r
+                fs.Flush();\r
\r
+                if (ifModified != null)\r
+                {\r
+                    string attrPath = mRootPath + EXTERNALBOARD_ATTR_FILE_NAME;\r
+                    NTFileAccess.storeAttrToFile(attrPath, ifModified);\r
+                }\r
+\r
+                bRet = true;\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+            finally\r
+            {\r
+                if (null != sw)\r
+                    sw.Close();\r
+                if (null != fs)\r
+                    fs.Close();\r
+            }\r
+            return bRet;\r
+        }\r
+\r
+        public static bool storeThreadHistoryListToFile(Stream stream, string ifModified)\r
+        {\r
+            FileStream fs = null;\r
+            StreamWriter sw = null;\r
+            bool bRet = false;\r
+            try\r
+            {\r
+                string path;\r
+                string attrPath;\r
+                path = mRootPath + THREAD_HISTORY_LIST_FILE_NAME;\r
+                attrPath = mRootPath + THREAD_HISTORY_LIST_ATTR_FILE_NAME;\r
+                \r
+                    fs = File.Open(path, FileMode.Create, FileAccess.Write);\r
+                sw = new StreamWriter(fs);\r
+\r
+\r
+\r
+                StreamReader sr = new StreamReader(stream);\r
+                string line;\r
+                while (null != (line = sr.ReadLine()))\r
+                {\r
+                    string decord;\r
+                    if(NTUserPreference.AESEnabled)\r
+                        decord = NTTextUtiles.aesDecodeBase64URL(line);\r
+                    else\r
+                        decord = NTTextUtiles.decodeBase64URL(line);\r
+                    \r
+                    sw.WriteLine(decord);\r
+\r
+                }\r
+                sw.Flush();\r
+                fs.Flush();\r
+\r
+                if (ifModified != null)\r
+                {                    \r
+                    NTFileAccess.storeAttrToFile(attrPath, ifModified);\r
+                }\r
+\r
+                bRet = true;\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+            finally\r
+            {\r
+                if (null != sw)\r
+                    sw.Close();\r
+                if (null != fs)\r
+                    fs.Close();\r
+            }\r
+            return bRet;\r
+        }\r
\r
+        static bool storeFavoritesToFile(Stream stream, string ifModified, bool append, string fileName, string attrFile)\r
+        {\r
+            FileStream fStream = null;\r
+            bool bRet = false;\r
+            try\r
+            {\r
+                string path = mRootPath + fileName;\r
+                FileMode mode;\r
+                if (append)\r
+                {\r
+                    mode = FileMode.Append;\r
+                }\r
+                else\r
+                {\r
+                    mode = FileMode.Create;\r
+                }\r
+                fStream = File.Open(path, mode, FileAccess.Write);\r
+\r
+                int numRead;\r
+                byte[] buf = new byte[1024];\r
+                while (0 < (numRead = stream.Read(buf, 0, buf.Length)))\r
+                {\r
+                    fStream.Write(buf, 0, numRead);\r
+                }\r
+\r
+                fStream.Flush();\r
+                fStream.Close();\r
+                fStream = null;\r
+\r
+\r
+                if (ifModified != null)\r
+                {\r
+                    string attrPath = mRootPath + attrFile;\r
+                    //FileInfo info = new FileInfo(path);\r
+                    NTFileAccess.storeAttrToFile(attrPath, ifModified);\r
+                }\r
+\r
+                bRet = true;\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+            finally\r
+            {\r
+                if (null != fStream)\r
+                    fStream.Close();\r
+            }\r
+            return bRet;\r
+        }\r
+\r
+        public static string retrieveNgWordFromFile()\r
+        {\r
+            string path;\r
+            if(NTUserPreference.AESEnabled)\r
+                path = mRootPath + AES_NGWORD_FILE_NAME;\r
+            else\r
+                path = mRootPath + NGWORD_FILE_NAME;\r
+            \r
+            return retrieveTextFromFile(path);\r
+        }\r
+        public static string retrieveNgIdFromFile()\r
+        {\r
+            string path;\r
+            if(NTUserPreference.AESEnabled)\r
+                path = mRootPath + AES_NGID_FILE_NAME;\r
+            else\r
+                path = mRootPath + NGID_FILE_NAME;\r
+            return retrieveTextFromFile(path);\r
+        }\r
+        public static string retrieveNgNameFromFile()\r
+        {\r
+            string path;\r
+            if(NTUserPreference.AESEnabled)\r
+                path = mRootPath + AES_NGNAME_FILE_NAME;\r
+            else\r
+                path = mRootPath + NGNAME_FILE_NAME;\r
+            return retrieveTextFromFile(path);\r
+        }\r
+\r
+        public static string retrieveFavoriteBoardFromFile()\r
+        {\r
+            string path;\r
+            if(NTUserPreference.AESEnabled)\r
+                path = mRootPath + AES_FAVORITE_BOARD_LIST_FILE_NAME;\r
+            else\r
+                path = mRootPath + FAVORITE_BOARD_LIST_FILE_NAME;\r
+            \r
+            return retrieveTextFromFile(path);\r
+        }\r
+        public static string [] retrieveFavoriteThreadFromFile()\r
+        {\r
+            string[] result = new string[2]; \r
+            string path;\r
+            if(NTUserPreference.AESEnabled)\r
+                path = mRootPath + AES_FAVORITE_THREAD_LIST_FILE_NAME;\r
+            else\r
+                path = mRootPath + FAVORITE_THREAD_LIST_FILE_NAME;\r
+\r
+            result[0] = retrieveTextFromFile(path);\r
+\r
+            if (NTUserPreference.AESEnabled)\r
+                path = mRootPath + AES_FAVORITE_THREAD_TAG_LIST_FILE_NAME;\r
+            else\r
+                path = mRootPath + FAVORITE_THREAD_TAG_LIST_FILE_NAME;\r
+\r
+            result[1] = retrieveTextFromFile(path);\r
+\r
+            return result;\r
+        }\r
+\r
+\r
+        static string retrieveTextFromFile(string path)\r
+        {\r
+            string retStr = string.Empty;\r
+            FileStream fStream = null;\r
+            StreamReader sr = null;\r
+\r
+            try\r
+            {\r
+                Encoding enc = Encoding.GetEncoding(NTAppState.HOST_2CH_ENCODING);\r
+\r
+                fStream = File.OpenRead(path);\r
+                sr = new StreamReader(fStream, enc);\r
+                retStr = sr.ReadToEnd();\r
+\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+            finally\r
+            {\r
+                if (null != fStream)\r
+                    fStream.Close();\r
+                if (null != sr)\r
+                    sr.Close();\r
+            }\r
+\r
+            return retStr;\r
+        }\r
+\r
+        public static bool retrieveExternalBoardAttrFromFile(out string ifModified)\r
+        {\r
+            string path = mRootPath + EXTERNALBOARD_ATTR_FILE_NAME;\r
+            return retrieveAttrFromFile(path, out ifModified);\r
+        }\r
+        public static bool retrieveThreadHistoryListAttrFromFile(out string ifModified)\r
+        {\r
+            string path;\r
+            path = mRootPath + THREAD_HISTORY_LIST_ATTR_FILE_NAME;       \r
+            return retrieveAttrFromFile(path, out ifModified);\r
+        }\r
+        public static bool retrieveFavoriteBoardAttrFromFile(out string ifModified)\r
+        {\r
+            string path;\r
+            if(NTUserPreference.AESEnabled)\r
+                path = mRootPath + AES_FAVORITE_BOARD_ATTR_FILE_NAME;\r
+            else\r
+                path = mRootPath + FAVORITE_BOARD_ATTR_FILE_NAME;\r
+            \r
+            return retrieveAttrFromFile(path, out ifModified);\r
+        }\r
+        public static bool retrieveFavoriteThreadAttrFromFile(out string ifModified)\r
+        {\r
+            string path;\r
+            if (NTUserPreference.AESEnabled)\r
+                path = mRootPath + AES_FAVORITE_THREAD_ATTR_FILE_NAME;\r
+            else\r
+                path = mRootPath + FAVORITE_THREAD_ATTR_FILE_NAME;\r
+\r
+            return retrieveAttrFromFile(path, out ifModified);\r
+        }\r
+        public static bool retrieveFavoriteThreadTagAttrFromFile(out string ifModified)\r
+        {\r
+            string path;\r
+            if (NTUserPreference.AESEnabled)\r
+                path = mRootPath + AES_FAVORITE_THREAD_TAG_ATTR_FILE_NAME;\r
+            else\r
+                path = mRootPath + FAVORITE_THREAD_TAG_ATTR_FILE_NAME;\r
+\r
+            return retrieveAttrFromFile(path, out ifModified);\r
+        }\r
+\r
+        public static void storeAttrToFile(string path, string ifModified)\r
+        {\r
+            string[] attr = new string[1];\r
+            attr[0] = ifModified;\r
+            //attr[1] = fileSize.ToString();\r
+            File.WriteAllLines(path, attr);\r
+        }\r
+\r
+        public static bool retrieveAttrFromFile(string path , out string ifModified)\r
+        {\r
+            bool bRet = false;\r
+            ifModified = string.Empty;\r
+            //fileSize = 0;\r
+            try\r
+            {\r
+                string [] lines = File.ReadAllLines(path);\r
+                if (lines.Length < 1)\r
+                    return false;\r
+                ifModified = lines[0];\r
+                //fileSize = int.Parse(lines[1]);\r
+                bRet = true;\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+            return bRet;\r
+        }\r
+\r
+        public static List<string> getStoredDat(string boardName)\r
+        {\r
+            List<string> list = new List<string>();\r
+\r
+            string path = mRootPath + PATH_PEPARATOR + boardName;\r
+            DirectoryInfo dInfo = new DirectoryInfo(path);\r
+            try\r
+            {\r
+                DirectoryInfo[] dArr = dInfo.GetDirectories();\r
+                foreach (DirectoryInfo info in dArr)\r
+                {\r
+                    list.Add(info.Name);\r
+                }\r
+            }\r
+            catch (DirectoryNotFoundException ex)\r
+            {\r
+                NTDebug.l(ex.Message);\r
+            }\r
+            return list;\r
+        }\r
+\r
+        static void storeDatAttrBinToFile(string path, string title, string ifModified, long fileSize)\r
+        {\r
+            string datAttrPath = path + DAT_ATTR_B_FILE_NAME;\r
+            string[] attr = new string[3];\r
+            attr[0] = title;\r
+            attr[1] = ifModified;\r
+            attr[2] = fileSize.ToString();\r
\r
+            File.WriteAllLines(datAttrPath, attr);\r
+       }\r
+\r
+        public static bool retrieveDatAttrToFile(string boardName, string datName, \r
+            out int numRead, out int[] writeIndexies, out int[] bookmarkedIndexies , out string lastWriteDateTime)\r
+        {\r
+            bool bRet = false;\r
+            string[] retStr = null;\r
+            string datAttrPath = mRootPath + PATH_PEPARATOR + boardName + PATH_PEPARATOR\r
+                + ridSuffixFromDatName(datName) + DAT_ATTR_FILE_NAME;\r
+            numRead = -1;\r
+            writeIndexies = NTTextUtiles.EMPTY_INT_ARRAY;\r
+            bookmarkedIndexies = NTTextUtiles.EMPTY_INT_ARRAY;\r
+\r
+            lastWriteDateTime = string.Empty;\r
+            try{\r
+                FileInfo fInfo = new FileInfo(datAttrPath);\r
+                DateTime dt = fInfo.LastWriteTime;\r
+                lastWriteDateTime = dt.ToString();\r
+            }catch//(Exception e)\r
+            {\r
+                //NTDebug.l(e.Message);\r
+            }\r
+\r
+            try\r
+            {\r
+                retStr = File.ReadAllLines(datAttrPath);\r
+                if (retStr.Length < 3)\r
+                    throw new Exception();\r
+\r
+                numRead = int.Parse(retStr[0]);\r
+                writeIndexies = NTTextUtiles.extructCommaSepLineFromInt(retStr[1]);\r
+                bookmarkedIndexies = NTTextUtiles.extructCommaSepLineFromInt(retStr[2]);\r
+\r
+                bRet = true;\r
+            }\r
+            catch //(Exception e)\r
+            {\r
+                //NTDebug.l(e.Message);\r
+            }\r
+            return bRet;\r
+        }\r
+        public static void storeDatAttrToFile(string boardName, string datName, int numRead, int[] writeIndexies, int[] bookmarkedIndexies)\r
+        {\r
+            //datName = ridSuffixFromDatName(datName);\r
+            //datName = ridSuffixFromDatName\r
+            string datAttrPath = mRootPath + PATH_PEPARATOR + boardName + PATH_PEPARATOR\r
+                + ridSuffixFromDatName(datName) + DAT_ATTR_FILE_NAME;\r
+            string[] attr = new string[3];\r
+            attr[0] = numRead.ToString();\r
+            attr[1] = NTTextUtiles.constructCommaSepLineFromInt(writeIndexies);\r
+            attr[2] = NTTextUtiles.constructCommaSepLineFromInt(bookmarkedIndexies);\r
+            try\r
+            {\r
+                File.WriteAllLines(datAttrPath, attr);\r
+            }\r
+            catch { }\r
+        }\r
+\r
+        public static bool storeDatTitle(string boardName, string datName, string title)\r
+        {\r
+            datName = ridSuffixFromDatName(datName);\r
+            bool bRet = false;\r
+            string[] arr = retrieveDatAttrBinFromFile(boardName, datName);\r
+            if(arr != null && arr.Length > 2){\r
+                arr[0] = title;\r
+                string datPath = mRootPath + PATH_PEPARATOR + boardName + PATH_PEPARATOR + datName;\r
+                int nRet;\r
+                if (int.TryParse(arr[2], out nRet))\r
+                {\r
+                    storeDatAttrBinToFile(datPath, title, arr[1], nRet);\r
+                    bRet = true;\r
+                }\r
+            }\r
+            return bRet;\r
+        }\r
+        \r
+        public static bool storeDatToFile(Stream stream, string boardName, \r
+            string datName,  string title, string ifModified, bool append)\r
+        {\r
+            string datPath = mRootPath + PATH_PEPARATOR + boardName + PATH_PEPARATOR + datName;\r
+            FileStream fStream = null;\r
+            bool bRet = false;\r
+            byte[] bBuf = new byte[1024 * 2];\r
+            try\r
+            {\r
+                DirectoryInfo dir = new DirectoryInfo(datPath);\r
+                if (!dir.Exists)\r
+                    dir.Create();\r
+\r
+                string datFileAbsolutePath = datPath + DAT_FILE_NAME;\r
+\r
+                FileMode mode;\r
+                if (append)\r
+                {\r
+                    mode = FileMode.Append;\r
+                }\r
+                else\r
+                {\r
+                    mode = FileMode.Create;\r
+                }\r
+                fStream = File.Open(datFileAbsolutePath, mode, FileAccess.Write);\r
+\r
+                int numRead;\r
+                while (0 < (numRead = stream.Read(bBuf, 0, bBuf.Length)))\r
+                {\r
+                    fStream.Write(bBuf, 0, numRead);\r
+                }\r
+\r
+                fStream.Flush();\r
+                fStream.Close();\r
+                fStream = null;\r
+\r
+\r
+                if (ifModified != null)\r
+                {\r
+                    FileInfo info = new FileInfo(datFileAbsolutePath);\r
+                    storeDatAttrBinToFile(datPath, title, ifModified, info.Length);\r
+                }\r
+\r
+                bRet = true;\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+            finally\r
+            {\r
+                if (null != fStream)\r
+                    fStream.Close();\r
+            }\r
+            return bRet;\r
+        }\r
+\r
+        public static bool isDatExsists(string boardName, string datName)\r
+        {\r
+\r
+            string path = mRootPath + PATH_PEPARATOR + boardName + PATH_PEPARATOR + datName;\r
+            FileInfo info = new FileInfo(path);\r
+            return info.Exists;\r
+        }\r
+        public static void deleteDatDir(string boardName, string datName)\r
+        {\r
+            datName = ridSuffixFromDatName(datName);\r
+\r
+            string path = mRootPath + PATH_PEPARATOR + boardName + PATH_PEPARATOR + datName;\r
+            DirectoryInfo info = new DirectoryInfo(path);\r
+            if(info.Exists)\r
+            {\r
+                info.Delete(true);\r
+            }\r
+        }\r
+\r
+        public static void deleteBoardDir(string boardName)\r
+        {\r
+\r
+            string path = mRootPath + PATH_PEPARATOR + boardName;\r
+            DirectoryInfo info = new DirectoryInfo(path);\r
+            if (info.Exists)\r
+            {\r
+                info.Delete(true);\r
+            }\r
+        }\r
+\r
+        public static string retrieveTitleFromDat(string source)\r
+        {\r
+            string[] lines = NTTextUtiles.splitLine(source);\r
+            foreach (string line in lines)\r
+            {\r
+                string line1 = line.Trim();\r
+                int idx = line1.LastIndexOf("<>");\r
+                if (idx >= 0)\r
+                {\r
+                    if (idx < (line1.Length - 2))\r
+                    {\r
+                        return line1.Substring(idx + 2);\r
+                    }\r
+                    return null;\r
+                }\r
+            }\r
+            return null;\r
+        }\r
+\r
+        public static string retrieveDatFromFile(string boardName, string datName)\r
+        {\r
+            datName = ridSuffixFromDatName(datName);\r
+\r
+            string retStr = null;\r
+            string datPath = mRootPath + PATH_PEPARATOR + boardName + PATH_PEPARATOR + datName;\r
+            FileStream fStream = null;\r
+            StreamReader sr = null;\r
+\r
+            try\r
+            {\r
+                Encoding enc = Encoding.GetEncoding(NTAppState.HOST_2CH_ENCODING);\r
+\r
+                DirectoryInfo dir = new DirectoryInfo(datPath);\r
+                if (!dir.Exists)\r
+                    return null;\r
+\r
+                string boardFileAbsolutePath = datPath + DAT_FILE_NAME;\r
+                fStream = File.OpenRead(boardFileAbsolutePath);\r
+                sr = new StreamReader(fStream, enc);\r
+                retStr = sr.ReadToEnd();\r
+\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+            finally\r
+            {\r
+                if (null != fStream)\r
+                    fStream.Close();\r
+                if (null != sr)\r
+                    sr.Close();\r
+            }\r
+\r
+            return retStr;\r
+        }\r
+\r
+        public static string[] retrieveMovieHistory()\r
+        {\r
+            string path = mRootPath + MOVIE_HISTORY_LIST_FILE_NAME;\r
+            \r
+            FileInfo fInfo = new FileInfo(path);\r
+            if (!fInfo.Exists)\r
+            {\r
+                return new string[0];\r
+            }\r
+            else\r
+            {\r
+                return retrieveLinesFile(path);\r
+            }\r
+\r
+        }\r
+\r
+        public static bool storeMovieHistory(string[] lines)\r
+        {\r
+            string path = mRootPath + MOVIE_HISTORY_LIST_FILE_NAME;\r
+            return NTFileAccess.sotreLinesFile(path, lines);\r
+        }\r
+\r
+\r
+        public static string[] retrieveLinesFile(string fileName)\r
+        {\r
+            string[] ret = null;\r
+            try\r
+            {\r
+                ret = File.ReadAllLines(fileName);\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+            return ret;\r
+        }\r
+\r
+        public static bool sotreLinesFile(string fileName, string[] lines)\r
+        {\r
+            if (lines == null)\r
+                return false;\r
+\r
+            bool ret = false;\r
+            try\r
+            {\r
+                File.WriteAllLines(fileName, lines);\r
+                ret = true;\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+            return ret;\r
+        }\r
+    }\r
+}\r
diff --git a/NT2chView45/NtFile/NTFileUtil.cs b/NT2chView45/NtFile/NTFileUtil.cs
new file mode 100755 (executable)
index 0000000..a9a0a0a
--- /dev/null
@@ -0,0 +1,42 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+\r
+namespace NT2chView.NtFile\r
+{\r
+    class NTFileUtil\r
+    {\r
+        static char[] IGNORE_CHAR = {'\\',/*'/',*/':','*','?','"','<','>','|'};\r
+\r
+        public static bool Url2FilePath(string url, out string pathName, out string fileName)\r
+        {\r
+            pathName = string.Empty;\r
+            fileName = string.Empty;\r
+\r
+            if (url == null || url.Length == 0)\r
+                return false;\r
+\r
+            int idx = url.IndexOf("://");\r
+            if (idx < 0)\r
+                return false;\r
+\r
+            string address = url.Substring(idx + "://".Length);\r
+\r
+            idx = address.LastIndexOf('/');\r
+            if (idx < 0)\r
+                return false;\r
+            foreach(char c in IGNORE_CHAR){\r
+                address = address.Replace(c, '・');\r
+            }\r
+\r
+            fileName = address.Substring(idx + 1);\r
+\r
+            address = address.Substring(0, idx);\r
+            address = address.Replace('/', '\\');\r
+\r
+            pathName = NTFileAccess.getImageDir() + address;\r
+\r
+            return true;\r
+        }\r
+    }\r
+}\r
diff --git a/NT2chView45/NtFile/NTPersistentFileAccess.cs b/NT2chView45/NtFile/NTPersistentFileAccess.cs
new file mode 100755 (executable)
index 0000000..d478bc5
--- /dev/null
@@ -0,0 +1,262 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.IO;\r
+\r
+namespace NT2chView.NtFile\r
+{\r
+    sealed class NTPersistentFileAccess\r
+    {\r
+        const string ROOTDIR_NAME = @"\PersistentData";\r
+        const string OPENED_BOARD_LIST_FILE_NAME = @"\OpenedBoardList.txt";\r
+        const string OPENED_THREAD_LIST_FILE_NAME = @"\OpenedThreadList.txt";\r
+        const string WRITE_HISTORY_FILE_NAME = @"\WriteHistory.txt";\r
+        const string USER_PREFERENCE_FILE_NAME = @"\UserPreference.txt";\r
+        const string AA_DATA_FILE_NAME = @"\AA.txt";\r
+        const string MENU_CMD_FILE_NAME = @"\MenuCommand.txt";\r
+        static string[] DEFAULT_CMD_STRINGS = {\r
+                                                 "# MenuCommand.txt",\r
+                                                 "# 書式: メニュー表示文字列 , プログラム名, パラメーター",\r
+                                                 "# ",\r
+                                                 "# メニュー表示文字列: この文字列がポップアップメニューの項目に表示されます",\r
+                                                 "# プログラム名: メニューが選択された時に起動されるプログラムを指定します。",\r
+                                                 "#         ここで指定するプログラムは、アプリケーションと同じか、",\r
+                                                 "#         システムのパスの通っているフォルダーにある必要があります。",\r
+                                                 "# パラメーター:上記のプログラム起動時に指定されるパラメーターを指定します。",\r
+                                                 "#        {0}を指定すると、画面で選択されている文字列に置き換えられます。",\r
+                                                 "#        注)文字列はURLエンコードされます。",\r
+                                                 "# ",\r
+                                                 "# デフォルト設定に戻したい時は、単純にこのファイルを削除して再起動して下さい。",\r
+                                                 "# ",\r
+                                                 "Google 検索, IExplore.exe, http://www.google.co.jp/search?source=ig&hl=ja&rlz=&q={0}",\r
+                                                 " Bing  検索, IExplore.exe, http://www.bing.com/search?q={0}",\r
+                                                 " Wikipedia, IExplore.exe, http://ja.wikipedia.org/wiki/{0}",\r
+                                                 "Google Image 検索, IExplore.exe, http://www.google.co.jp/search?source=ig&hl=ja&rlz=&q={0}&tbm=isch"\r
+                                            };\r
+\r
+        static string mRootPath;\r
+        public static void init(string rootPath)\r
+        {\r
+            mRootPath = rootPath + ROOTDIR_NAME;\r
+            DirectoryInfo dir = new DirectoryInfo(mRootPath);\r
+            if (!dir.Exists)\r
+                dir.Create();\r
+\r
+        }\r
+\r
+\r
+       \r
+\r
+        public static bool storeUserPreferences(List<KeyValuePair<string, string>> list)\r
+        {\r
+            string path = mRootPath + USER_PREFERENCE_FILE_NAME;\r
+            StringBuilder sb = new StringBuilder(64);\r
+\r
+            try\r
+            {\r
+                using (FileStream fs = new FileStream(path, FileMode.Create, FileAccess.Write))\r
+                {\r
+                    using (StreamWriter sw = new StreamWriter(fs))\r
+                    {\r
+\r
+                        foreach (KeyValuePair<string, string> pair in list)\r
+                        {\r
+                            sb.Remove(0, sb.Length);\r
+                            sb.Append(pair.Key).Append("=").Append(pair.Value);\r
+                            sw.WriteLine(sb.ToString());\r
+                        }\r
+                        sw.Flush();\r
+                        fs.Flush();\r
+                    }\r
+                }\r
+\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+                return false;\r
+            }\r
+            return true;\r
+        }\r
+\r
+        public static List<KeyValuePair<string, string>> retrieveUserPreferences()\r
+        {\r
+            List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>();\r
+\r
+\r
+            string path = mRootPath + USER_PREFERENCE_FILE_NAME;\r
+            StringBuilder sb = new StringBuilder(64);\r
+\r
+            try\r
+            {\r
+                using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read))\r
+                {\r
+                    using (StreamReader sr = new StreamReader(fs))\r
+                    {\r
+                        string line;\r
+                        while (null != (line = sr.ReadLine()))\r
+                        {\r
+                            int n = line.IndexOf("=");\r
+                            if (n >= 0)\r
+                            {\r
+\r
+                                KeyValuePair<string, string> pair \r
+                                    = new KeyValuePair<string, string>(line.Substring(0,n), line.Substring(n+1));\r
+                                list.Add(pair);\r
+\r
+                            }\r
+                            \r
+                        }\r
+                    }\r
+                }\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+            return list;\r
+        }\r
+\r
+        public static bool storeWriteHistory(string line)\r
+        {\r
+            bool ret = false;\r
+            try\r
+            {\r
+                string[] prevLInes = retrieveWriteHistroy();\r
+                if (prevLInes != null)\r
+                {\r
+                    foreach (string s in prevLInes)\r
+                    {\r
+                        if (s.Equals(line))\r
+                            return true;\r
+                    }\r
+                }\r
+                List<string> list = new List<string>();\r
+                list.Add(line);\r
+\r
+                if (prevLInes != null)\r
+                {\r
+                    int len = (prevLInes.Length < 20) ? prevLInes.Length : 19;\r
+                    for (int i = 0; i < len; i++)\r
+                    {\r
+                        list.Add(prevLInes[i]);\r
+                    }\r
+                }\r
+\r
+                string path = mRootPath + WRITE_HISTORY_FILE_NAME;\r
+                File.WriteAllLines(path, list.ToArray());\r
+                ret = true;\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+            return ret;\r
+        }\r
+        public static string[] retrieveWriteHistroy()\r
+        {\r
+            string[] ret = null;\r
+            string path = mRootPath + WRITE_HISTORY_FILE_NAME;\r
+            try\r
+            {\r
+                ret = File.ReadAllLines(path);\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+            return ret;\r
+        }\r
+\r
+        public static bool storeAAData(string [] lines)\r
+        {\r
+            string path = mRootPath + AA_DATA_FILE_NAME;\r
+            return NTFileAccess.sotreLinesFile(path, lines);\r
+        }\r
+\r
+\r
+        public static string[] retrieveAAData()\r
+        {\r
+            return NTFileAccess.retrieveLinesFile(mRootPath + AA_DATA_FILE_NAME);\r
+\r
+        }\r
+\r
+        public static string[] retrieveResMenuCmd()\r
+        {\r
+            string path = mRootPath + MENU_CMD_FILE_NAME;\r
+\r
+            FileInfo fInfo = new FileInfo(path);\r
+            if (!fInfo.Exists)\r
+            {\r
+                NTFileAccess.sotreLinesFile(path, DEFAULT_CMD_STRINGS);\r
+                return DEFAULT_CMD_STRINGS;\r
+            }\r
+            else\r
+            {\r
+                return NTFileAccess.retrieveLinesFile(path);\r
+            }\r
+\r
+        }\r
+\r
+\r
+        public static bool storeOpenedBoards(string[] boards)\r
+        {\r
+            bool ret = false;\r
+            try\r
+            {\r
+                string path = mRootPath + OPENED_BOARD_LIST_FILE_NAME;\r
+                File.WriteAllLines(path, boards);\r
+                ret = true;\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+            return ret;\r
+        }\r
+        public static string [] retrieveOpenedBoards()\r
+        {\r
+            string[] ret = null;\r
+            string path = mRootPath + OPENED_BOARD_LIST_FILE_NAME;\r
+            try\r
+            {\r
+                ret = File.ReadAllLines(path);\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+            return ret;\r
+        }\r
+        public static bool storeOpenedThreads(string[] threads)\r
+        {\r
+            bool ret = false;\r
+            try\r
+            {\r
+                string path = mRootPath + OPENED_THREAD_LIST_FILE_NAME;\r
+                File.WriteAllLines(path, threads);\r
+                ret = true;\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+            return ret;\r
+        }\r
+        public static string[] retrieveOpenedThreads()\r
+        {\r
+            string[] ret = null;\r
+            string path = mRootPath + OPENED_THREAD_LIST_FILE_NAME;\r
+            try\r
+            {\r
+                ret = File.ReadAllLines(path);\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+            return ret;\r
+        }\r
+\r
+    }\r
+}\r
diff --git a/NT2chView45/NtHtml/NTHtmlParser.cs b/NT2chView45/NtHtml/NTHtmlParser.cs
new file mode 100755 (executable)
index 0000000..77a1ef7
--- /dev/null
@@ -0,0 +1,1043 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Windows.Media;\r
+using System.Globalization;\r
+using System.Windows.Documents;\r
+\r
+\r
+namespace NT2chView.NtHtml\r
+{\r
+    class NTHtmlParser\r
+    {\r
+\r
+       \r
+           public static void init(){\r
+                   HTMLElementTable.init();\r
+           }\r
+       \r
+           /*public static final int TYPE_NONE = -1;\r
+           public static final int TYPE_HTML = 0;\r
+           public static final int TYPE_COMMENT = 1;\r
+           public static final int TYPE_TITLE = 2;\r
+           public static final int TYPE_BODY = 3;\r
+           public static final int TYPE_ALINK = 4;\r
+           public static final int TYPE_INPUT = 5;*/\r
+           int mUnnumberedListIndent = 0;\r
+       \r
+           String mTitle = string.Empty;//new String();\r
+           StringBuilder mOutput = new StringBuilder(2048);\r
+           String mParsedHtml = null;\r
+           public List<String> mCommentList = new List<String>();\r
+           public List<KeyValuePair<string,string>> mInputTypeHidden = new List<KeyValuePair<string,string>>();\r
+           public List<KeyValuePair<string,string>> mInputTypeSubmit = new List<KeyValuePair<string,string>>();\r
+           public List<KeyValuePair<string,string>> mInputTypeCheckBox = new List<KeyValuePair<string,string>>();\r
+           public List<KeyValuePair<string,string>> mInputTypeText = new List<KeyValuePair<string,string>>();\r
+           public List<KeyValuePair<string,string>> mInputTypePasswd = new List<KeyValuePair<string,string>>();\r
+           public List<KeyValuePair<string,string>> mHtmlAttributes = new List<KeyValuePair<string,string>>();\r
+           public List<KeyValuePair<string,string>> mBodyAttributes = new List<KeyValuePair<string,string>>();\r
+        public List<KeyValuePair<string, string>> mFormAttributes = new List<KeyValuePair<string, string>>();\r
+        public List<KeyValuePair<string, string>> mTextAreaAttributes = new List<KeyValuePair<string, string>>();\r
+        //public ArrayList<SpannableObject> mSpannableObjectStack = new ArrayList<SpannableObject>();\r
+       \r
+           public String getParsedHtml(){return mParsedHtml;}\r
+       \r
+           public String getTitle(){return mTitle;}\r
+\r
+        FlowDocument mDocRoot;\r
+        Stack<TextElement> mDrawElementStack = new Stack<TextElement>();\r
+\r
+           public NTHtmlParser(FlowDocument document){\r
+\r
+            mDocRoot = document;\r
+            Paragraph para = new Paragraph();\r
+            document.Blocks.Add(para);\r
+            mDrawElementStack.Push(para);\r
+           }\r
+\r
+        public void DrawElementClear()\r
+        {\r
+           \r
+            mDocRoot.Blocks.Clear();\r
+            mDrawElementStack.Clear();\r
+\r
+            Paragraph para = new Paragraph();\r
+            mDocRoot.Blocks.Add(para);\r
+            mDrawElementStack.Push(para);\r
+        }\r
+\r
+        public void DrawElementAdd(Inline inline)\r
+        {\r
+           //TextElement element = mDrawElementStack.Peek();\r
+\r
+           Block block = mDocRoot.Blocks.LastBlock;\r
+\r
+            Paragraph para  = block as Paragraph;\r
+            if(para != null){\r
+                TextElement element = mDrawElementStack.Peek();\r
+                Span span = element as Span;\r
+                if (span != null)\r
+                {\r
+                    span.Inlines.Add(inline);\r
+                    return;\r
+                }\r
+                //Paragraph para2 = element as Paragraph;\r
+                //if(para2 != null)\r
+                //{\r
+                para.Inlines.Add(inline);\r
+                //}\r
+                return;\r
+            }\r
+\r
+            List list = block as List;\r
+            if(list != null)\r
+            {\r
+                if (inline is Run)\r
+                {\r
+                    if (((Run)inline).Text.Trim().Length > 0)\r
+                    {\r
+                        ListItem item = new ListItem();\r
+                        para = new Paragraph(inline);\r
+                        item.Blocks.Add(para);\r
+                        list.ListItems.Add(item);\r
+                    }\r
+                }\r
+                return;\r
+            }\r
+         }\r
+\r
+        public void DrawElementPushList()\r
+        {\r
+            List list = new List();\r
+            list.MarkerStyle = System.Windows.TextMarkerStyle.Disc;\r
+            mDocRoot.Blocks.Add(list);\r
+\r
+            mDrawElementStack.Clear();\r
+        }\r
+\r
+        public void DrawElementPopList()\r
+        {\r
+            mDrawElementStack.Clear();\r
+            Paragraph para = new Paragraph();\r
+            mDocRoot.Blocks.Add(para);\r
+            mDrawElementStack.Push(para);\r
+\r
+        }\r
+        public void DrawElementPush(Span source)\r
+        {\r
+            if (mDrawElementStack.Count <= 0)\r
+            {\r
+                return;\r
+            }\r
+\r
+            TextElement element = mDrawElementStack.Peek();\r
+            Paragraph para = element as Paragraph;\r
+            if (para != null)\r
+            {\r
+               para.Inlines.Add(source);\r
+               mDrawElementStack.Push(source);\r
+               return;\r
+            }\r
+\r
+            Span span = element as Span;\r
+            if (span != null)\r
+            {\r
+                span.Inlines.Add(source);\r
+                mDrawElementStack.Push(source);\r
+                return;\r
+            }\r
+       }\r
+        public void  DrawElementPop()\r
+        {\r
+            if (mDrawElementStack.Count <= 0)\r
+            {\r
+                return;\r
+            }\r
+\r
+            if(mDrawElementStack.Peek() is Paragraph)\r
+                return;\r
+\r
+            TextElement element = mDrawElementStack.Pop();\r
+            \r
+        }\r
+\r
+       \r
+           public String parse(String htmlSource){\r
+               \r
+               \r
+                   int[] retVal = new int[1];\r
+               \r
+               \r
+                   AbstractElement ae = new AbstractElement(this);\r
+               \r
+               \r
+                   ae.parse(htmlSource, 0, retVal,HTMLElementTable.ELEMENT_TOKEN_NULL);\r
+               \r
+                   mParsedHtml = mOutput.ToString();\r
+               \r
+                   return mParsedHtml;\r
+               \r
+           }\r
+\r
+        \r
+       \r
+           public Color getBgColor() {\r
+                   for(int i  = 0; i < mBodyAttributes.Count; i++){\r
+                           KeyValuePair<string,string> pair = mBodyAttributes[i];\r
+                           if(pair.Key.Equals("bgcolor")){\r
+                                   return parseColor(pair.Value, 0);\r
+                           }\r
+                   }\r
+                   throw new Exception();\r
+           }\r
+       \r
+           static Color parseColor(String source, int start) {\r
+                   int i = start;\r
+                   if('#' != source[i] || 7 > (source.Length-start)){\r
+                           throw new Exception();\r
+                   }\r
+                   i++;\r
+                   String wrk = source.Substring(i, 2);\r
+                   int red = int.Parse(wrk, NumberStyles.HexNumber);\r
+               \r
+                   i += 2;\r
+                   wrk = source.Substring(i, 2);\r
+                   int green = int.Parse(wrk, NumberStyles.HexNumber);\r
+                   i += 2;\r
+                   wrk = source.Substring(i, 2);\r
+                   int blue = int.Parse(wrk, NumberStyles.HexNumber);\r
+               \r
+                   return Color.FromArgb((byte)255, (byte)red, (byte)green, (byte)blue);       \r
+           }\r
+       \r
+       \r
+           public class AbstractElement {\r
+                   protected NTHtmlParser mParser = null;\r
+                   public AbstractElement(NTHtmlParser parser){\r
+                           mParser = parser;\r
+                   }\r
+                   public virtual int parse(String source, int start,  int [] retVal, int breakType){\r
+                           int start2 = start;\r
+                           int i = 0;\r
+                           for(i = start; i < source.Length; i++){\r
+                                   int type = HTMLElementTable.getElementTypeFromSource(source, i,  retVal);\r
+                                   if(breakType == type){\r
+                                           mParser.mOutput.Append(source.Substring(start2, i-start2));\r
+                        //*****\r
+                        Run run = new Run(source.Substring(start2, i-start2));\r
+                        mParser.DrawElementAdd(run);\r
+                                           return retVal[0];\r
+                                   }\r
+                                   if(HTMLElementTable.ELEMENT_TOKEN_NONE == type){\r
+                                           continue;\r
+                                   }\r
+                                   if(start2 < i){\r
+                                           mParser.mOutput.Append(source.Substring(start2, i-start2));\r
+                        //***\r
+                        if (i > start2)\r
+                        {\r
+                            Run run = new Run(source.Substring(start2, i - start2));\r
+                            mParser.DrawElementAdd(run);\r
+                        }\r
+                                           start2 = i + 1;\r
+                                   }\r
+                               \r
+                                   AbstractElement ae = null;\r
+                               \r
+                                   switch(type){\r
+                                   case HTMLElementTable.ELEMENT_TOKEN_UL_S:\r
+                                           mParser.mUnnumberedListIndent++;\r
+                        mParser.DrawElementPushList();\r
+                        start2 = retVal[0];\r
+                                           i = start2 - 1;\r
+                                           break;\r
+                                   case HTMLElementTable.ELEMENT_TOKEN_UL_E:\r
+                        mParser.mUnnumberedListIndent--;\r
+                        mParser.DrawElementPopList();\r
+                                           start2 = retVal[0];\r
+                                           i = start2 - 1;\r
+                                           break;\r
+                                   case HTMLElementTable.ELEMENT_TOKEN_LI:\r
+                                           ae = new  ListItemElement(mParser);\r
+                                           start2 = ae.parse(source, retVal[0], retVal, HTMLElementTable.ELEMENT_TOKEN_NULL);\r
+                                           i = start2 - 1;\r
+                                           break;      \r
+                                   case HTMLElementTable.ELEMENT_TOKEN_PARAGRAPH:\r
+                                           mParser.mOutput.Append('\n');\r
+                        mParser.mOutput.Append('\n');\r
+                        //***\r
+                        mParser.DrawElementAdd(new LineBreak());\r
+                        mParser.DrawElementAdd(new LineBreak());\r
+                        start2 = retVal[0];\r
+                        i = start2 - 1;\r
+                        break;\r
+                    case HTMLElementTable.ELEMENT_TOKEN_BREAK:\r
+                                           mParser.mOutput.Append('\n');\r
+                        //***\r
+                        mParser.DrawElementAdd(new LineBreak());\r
+                        start2 = retVal[0];\r
+                                           i = start2 - 1;\r
+                                           break;\r
+                                   case HTMLElementTable.ELEMENT_TOKEN_HR:\r
+                                           ae = new  HRElement(mParser);\r
+                                           start2 = ae.parse(source, retVal[0], retVal, HTMLElementTable.ELEMENT_TOKEN_NULL);\r
+                                           i = start2 - 1;\r
+                                           break;\r
+                                   case HTMLElementTable.ELEMENT_TOKEN_BOLD_S:\r
+                                           ae = new  BoldElement(mParser);\r
+                                           start2 = ae.parse(source, retVal[0], retVal, HTMLElementTable.ELEMENT_TOKEN_BOLD_E);\r
+                                           i = start2 - 1;\r
+                                           break;\r
+                                   case HTMLElementTable.ELEMENT_TOKEN_HTML_S:\r
+                                           mParser.mOutput.Remove(0, mParser.mOutput.Length);\r
+                        //***\r
+                        mParser.DrawElementClear();\r
+\r
+                         ae = new  HtmlElement(mParser);\r
+                                           start2 = ae.parse(source, retVal[0], retVal, HTMLElementTable.ELEMENT_TOKEN_HTML_E);\r
+                                           return source.Length;\r
+                                   case HTMLElementTable.ELEMENT_TOKEN_BODY_S:\r
+                                           mParser.mOutput.Remove(0, mParser.mOutput.Length);\r
+                        //***\r
+                        mParser.DrawElementClear();\r
+                        \r
+                        ae = new BodyElement(mParser);\r
+                                           start2 = ae.parse(source, retVal[0], retVal, HTMLElementTable.ELEMENT_TOKEN_BODY_E);\r
+                                           return source.Length;\r
+                                   case HTMLElementTable.ELEMENT_TOKEN_COMMENT_S:\r
+                                           ae = new  CommentElement(mParser);\r
+                                           start2 = ae.parse(source, retVal[0], retVal, HTMLElementTable.ELEMENT_TOKEN_COMMENT_E);\r
+                                           i = start2 - 1;\r
+                                           break;\r
+                                   case HTMLElementTable.ELEMENT_TOKEN_TITLE_S:\r
+                                           ae = new  TitleElement(mParser);\r
+                                           start2 = ae.parse(source, retVal[0], retVal, HTMLElementTable.ELEMENT_TOKEN_TITLE_E);\r
+                                           i = start2 - 1;\r
+                                           break;\r
+                                   case HTMLElementTable.ELEMENT_TOKEN_CENTER_S:\r
+                                           ae = new  CenterElement(mParser);\r
+                                           start2 = ae.parse(source, retVal[0], retVal, HTMLElementTable.ELEMENT_TOKEN_CENTER_E);\r
+                                           i = start2 - 1;\r
+                                           break;\r
+                                   case HTMLElementTable.ELEMENT_TOKEN_ALINK_S:\r
+                                           ae = new  ALinkElement(mParser);\r
+                                           start2 = ae.parse(source, retVal[0], retVal, HTMLElementTable.ELEMENT_TOKEN_ALINK_E);\r
+                                           i = start2 - 1;\r
+                                           break;\r
+                                   case HTMLElementTable.ELEMENT_TOKEN_INPUT:\r
+                                           ae = new  InputElement(mParser);\r
+                                           start2 = ae.parse(source, retVal[0], retVal, HTMLElementTable.ELEMENT_TOKEN_NULL);\r
+                                           i = start2 - 1;\r
+                                           break;\r
+                                   case HTMLElementTable.ELEMENT_TOKEN_FONT_S:\r
+                                           ae = new  FontElement(mParser);\r
+                                           start2 = ae.parse(source, retVal[0], retVal, HTMLElementTable.ELEMENT_TOKEN_FONT_E);\r
+                                           i = start2 - 1;\r
+                                           break;\r
+                    case HTMLElementTable.ELEMENT_TOKEN_FORM_S:\r
+                        ae = new FormElement(mParser);\r
+                        start2 = ae.parse(source, retVal[0], retVal, HTMLElementTable.ELEMENT_TOKEN_FORM_E);\r
+                        i = start2 - 1;\r
+                        break;\r
+                    case HTMLElementTable.ELEMENT_TOKEN_TEXTAREA_S:\r
+                        ae = new TextAreaElement(mParser);\r
+                        start2 = ae.parse(source, retVal[0], retVal, HTMLElementTable.ELEMENT_TOKEN_TEXTAREA_E);\r
+                        i = start2 - 1;\r
+                        break;\r
+                    default:\r
+                                           break;\r
+                                   }\r
+                               \r
+                           }\r
+                           return i;\r
+                   }\r
+           }\r
+       \r
+           /*public class SpannableObject{\r
+                   Object mWhat;\r
+                   int mStart, mEnd, mFlags;\r
+                   public SpannableObject(Object what, int start, int end, int flags){\r
+                           mWhat = what; mStart = start; mEnd = end; mFlags = flags;                   \r
+                   }\r
+           }*/\r
+\r
+           class HtmlElement : AbstractElement{\r
+                   public HtmlElement(NTHtmlParser parser) : base(parser)\r
+            {\r
+                       \r
+                   }\r
+               \r
+            public override int parse(String source, int start, int[] retVal, int breakType){\r
+                mParser.mHtmlAttributes = mParser.parseAttributes(source, start, retVal);\r
+                           start = retVal[0];\r
+                           return base.parse(source, start, retVal, breakType);\r
+                   }\r
+           }\r
+\r
+           class BodyElement : AbstractElement{\r
+                   public BodyElement(NTHtmlParser parser) : base(parser)\r
+            {\r
+               \r
+                   }\r
+                   public override int parse(String source, int start, int[] retVal, int breakType){\r
+                mParser.mBodyAttributes = mParser.parseAttributes(source, start, retVal);\r
+                           start = retVal[0];\r
+                           return base.parse(source, start, retVal, breakType);\r
+                   }\r
+           }\r
+\r
+           class HRElement : AbstractElement{\r
+                   public HRElement(NTHtmlParser parser) : base(parser)\r
+            {\r
+                       \r
+                   }\r
+               \r
+            public override int parse(String source, int dummy, int[] retVal, int breakType){\r
+                String hr = "\n\n                                                            \n\n";\r
+                \r
+                //***\r
+                String hr2 = "---------------------------------------------------------------";\r
+                mParser.DrawElementAdd(new LineBreak());\r
+                mParser.DrawElementAdd(new LineBreak());\r
+                mParser.DrawElementAdd(new Run(hr2));\r
+                mParser.DrawElementAdd(new LineBreak());\r
+                mParser.DrawElementAdd(new LineBreak());\r
+                           \r
+\r
+                StringBuilder buf = mParser.mOutput;\r
+                           int start = buf.Length;\r
+                           buf.Append(hr);\r
+                           int end = buf.Length;\r
+                           /*StrikethroughSpan span = new StrikethroughSpan();\r
+                           mSpannableObjectStack.add(\r
+                                           new SpannableObject(span, \r
+                                                           start+2, end-2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE));\r
+                           AlignmentSpan.Standard center_span = \r
+                                           new AlignmentSpan.Standard(Layout.Alignment.ALIGN_CENTER);\r
+                           mSpannableObjectStack.add(\r
+                                           new SpannableObject(center_span, \r
+                                                           start+2, end-2, \r
+                                                           Spannable.SPAN_EXCLUSIVE_EXCLUSIVE));\r
+                */\r
+                           return retVal[0];\r
+                   }\r
+           }\r
+           class ListItemElement : AbstractElement{\r
+                   public ListItemElement(NTHtmlParser parser) : base(parser)\r
+            {\r
+                       \r
+                   }\r
+               \r
+            public override int parse(String source, int dummy, int[] retVal, int breakType){\r
+                           String indent = "\n";\r
+                mParser.DrawElementAdd(new LineBreak());\r
+                           int i =  0;\r
+                           for(; i < mParser.mUnnumberedListIndent; i++){\r
+                                   indent += "   ";\r
+                           }\r
+                           if(0 < i){\r
+                                   indent += '●';\r
+                                   mParser.mOutput.Append(indent);\r
+                    //mParser.DrawElementAdd(new Run(indent));\r
+                           }\r
+                           return retVal[0];\r
+                   }\r
+           }\r
+\r
+           class BoldElement : AbstractElement{\r
+                   public BoldElement(NTHtmlParser parser) : base(parser)\r
+            {\r
+                       \r
+                   }\r
+               \r
+            public override int parse(String source, int start, int[] retVal, int breakType){\r
+                           //mParser.mBodyAttributes = parseAttributes( source,  start, retVal);\r
+                           //start = retVal[0];\r
+                Bold bold = new Bold();\r
+                //mParser.mDrawElementStack.Push(bold);\r
+                           //int textStart = mParser.mOutput.Length;\r
+                mParser.DrawElementPush(new Bold());\r
+                int end = base.parse(source, start, retVal, breakType);\r
+                mParser.DrawElementPop();\r
+                //int textEnd =  mParser.mOutput.Length;\r
+                           /*StyleSpan span = new StyleSpan(android.graphics.Typeface.BOLD); \r
+                           mSpannableObjectStack.add( \r
+                                           new SpannableObject(span, \r
+                                                                   textStart, textEnd, \r
+                                                                   Spannable.SPAN_EXCLUSIVE_EXCLUSIVE));*/\r
+                return end;\r
+                   }\r
+           }\r
+\r
+       \r
+           class CenterElement : AbstractElement{\r
+                   public CenterElement(NTHtmlParser parser) : base(parser)\r
+            {\r
+                       \r
+                   }\r
+               \r
+            public override int parse(String source, int start, int[] retVal, int breakType){\r
+                           //mParser.mBodyAttributes = parseAttributes( source,  start, retVal);\r
+                           //start = retVal[0];\r
+                           //int textStart = mParser.mOutput.Length;\r
+                           int end = base.parse(source, start, retVal, breakType);\r
+                           //int textEnd =  mParser.mOutput.Length;\r
+                           //if(textStart < textEnd){  \r
+                               /*    AlignmentSpan.Standard center_span = \r
+                                                   new AlignmentSpan.Standard(Layout.Alignment.ALIGN_CENTER);\r
+                       \r
+                                   mSpannableObjectStack.add(\r
+                                                   new SpannableObject(center_span, \r
+                                                                   textStart, textEnd, \r
+                                                                   Spannable.SPAN_EXCLUSIVE_EXCLUSIVE));*/\r
+                          // }\r
+                           return end;\r
+                   }\r
+           }\r
+\r
+           class CommentElement : AbstractElement{\r
+                   public CommentElement(NTHtmlParser parser) : base(parser)\r
+            {\r
+                       \r
+                   }\r
+               \r
+                   public override int parse(String source, int start, int[] retVal, int breakType){\r
+                           //int start2 = start;\r
+                           int i = 0;\r
+                           for(i = start; i < source.Length; i++){\r
+                                   int type = HTMLElementTable.getElementTypeFromSource(source, i, retVal);\r
+                                   if(breakType == type){\r
+                                           String comment = source.Substring(start, retVal[0]-start);\r
+                                           mParser.mCommentList.Add(comment.Trim());\r
+                                           return retVal[0];\r
+                                   }\r
+                           }\r
+                           return i;\r
+                   }\r
+           }\r
+       \r
+           class TitleElement : AbstractElement{\r
+                   public TitleElement(NTHtmlParser parser) : base(parser)\r
+            {\r
+                       \r
+                   }\r
+               \r
+                   public override int parse(String source, int start, int[] retVal, int breakType){\r
+                           //int start2 = start;\r
+                           int i = 0;\r
+                           for(i = start; i < source.Length; i++){\r
+                                   int type = HTMLElementTable.getElementTypeFromSource(source, i, retVal);\r
+                                   if(breakType == type){\r
+                                           String title = source.Substring(start, retVal[0]-8-start);\r
+                                           mParser.mTitle = title.Trim();\r
+                                           return retVal[0];\r
+                                   }\r
+                           }\r
+                           return i;\r
+                   }\r
+           }\r
+       \r
+           class InputElement : AbstractElement{\r
+                   public InputElement(NTHtmlParser parser) : base(parser)\r
+            {\r
+                       \r
+                   }\r
+               \r
+                   public override int parse(String source, int start, int[] retVal, int breakType){\r
+                       \r
+                           List<KeyValuePair<string,string>> list = mParser.parseAttributes( source,  start, retVal);\r
+                       \r
+                           String type = "", name = "", value = "";\r
+                       \r
+                           for(int i = 0; i < list.Count; i++){\r
+                                   KeyValuePair<string,string> pair = list[i];\r
+                    if (pair.Key.Equals("type") || pair.Key.Equals("TYPE"))\r
+                    {\r
+                                           type = pair.Value;\r
+                    }\r
+                    else if (pair.Key.Equals("name") || pair.Key.Equals("NAME"))\r
+                    {\r
+                                           name = pair.Value;\r
+                    }\r
+                    else if (pair.Key.Equals("value") || pair.Key.Equals("VALUE"))\r
+                    {\r
+                                           value = pair.Value;\r
+                                   }\r
+                           }\r
+                       \r
+                               if(type.Equals("submit") || type.Equals("SUBMIT")){\r
+                    //if (0 <= value.Length)\r
+                   // {\r
+                        //if (name.Length == 0)\r
+                        //    name = type;\r
+                  mParser.mInputTypeSubmit.Add(new KeyValuePair<string, string>(name, value));\r
+                                 //  }\r
+                }\r
+                else// if (0 < name.Length && 0 <= value.Length)\r
+                {\r
+                    if (0 < type.Length)\r
+                    {\r
+                        if (type.Equals("hidden") || type.Equals("HIDDEN"))\r
+                        {\r
+                            mParser.mInputTypeHidden.Add(new KeyValuePair<string, string>(name, value));\r
+                        }\r
+                        else if (type.Equals("text") || type.Equals("TEXT"))\r
+                        {\r
+                            mParser.mInputTypeText.Add(new KeyValuePair<string, string>(name, value));\r
+                        }\r
+                        else if (type.Equals("password") || type.Equals("PASSWORD"))\r
+                        {\r
+                            mParser.mInputTypePasswd.Add(new KeyValuePair<string, string>(name, value));\r
+                        }\r
+                        else if (type.Equals("checkbox") || type.Equals("CHECKBOX"))\r
+                        {\r
+                            mParser.mInputTypeCheckBox.Add(new KeyValuePair<string, string>(name, value));\r
+                        }\r
+                    }\r
+                    else\r
+                    {\r
+                        mParser.mInputTypeText.Add(new KeyValuePair<string, string>(name, value));\r
+                    }                   \r
+                           }\r
+                           return retVal[0];\r
+                   }\r
+           }\r
+               \r
+           class ALinkElement : AbstractElement{\r
+                   public ALinkElement(NTHtmlParser parser) : base(parser)\r
+            {\r
+                       \r
+                   }\r
+               \r
+                   public override int parse(String source, int start, int[] retVal, int breakType){\r
+\r
+                List<KeyValuePair<string, string>> list = mParser.parseAttributes(source, start, retVal);\r
+                       \r
+                           String url = "";//, name = "", value = "";\r
+                       \r
+                           for(int i = 0; i < list.Count; i++){\r
+                                   KeyValuePair<string,string> pair = list[i];\r
+                                   if(pair.Key.Equals("href")){\r
+                                           url = pair.Value;\r
+                                           break;\r
+                                   }else if(pair.Key.Equals("HREF")){\r
+                                           url = pair.Value;\r
+                                           break;\r
+                                   }\r
+                           }\r
+                           int textStart = mParser.mOutput.Length;\r
+                Hyperlink hl = new Hyperlink();\r
+                //hl.NavigateUri = new Uri(url);\r
+                mParser.DrawElementPush(hl);\r
+                           int end = base.parse(source, retVal[0], retVal, breakType);\r
+                mParser.DrawElementPop();\r
+                int textEnd = mParser.mOutput.Length;\r
+                       \r
+                           if(0 < url.Length){\r
+                                   if(0 <= url.IndexOf("http") || 0 <= url.IndexOf("HTTP")){\r
+\r
+                                           /*URLSpan urls = new URLSpan(url);\r
+                           \r
+                                           mSpannableObjectStack.add(\r
+                                                   new SpannableObject(urls, textStart, textEnd, 0));*/\r
+                                   }\r
+                           }\r
+                           return end;\r
+                   }\r
+           }\r
+           class FontElement : AbstractElement{\r
+                   public FontElement(NTHtmlParser parser) : base(parser)\r
+            {\r
+                       \r
+                   }\r
+               \r
+                   public override int parse(String source, int start, int[] retVal, int breakType){\r
+\r
+                List<KeyValuePair<string, string>> list = mParser.parseAttributes(source, start, retVal);\r
+                       \r
+                           int nSize = 0;\r
+                Color color;\r
+\r
+                Span span = new Span();\r
+                for(int i = 0; i < list.Count; i++){\r
+                                   KeyValuePair<string,string> pair = list[i];\r
+                                   if(pair.Key.Equals("size")){\r
+                                           try\r
+                        {\r
+                           nSize = int.Parse(pair.Value, NumberStyles.Integer);\r
+                        }\r
+                        catch \r
+                        {\r
+                        }\r
+                    }else if(pair.Key.Equals("color")){\r
+                                           try\r
+                        {\r
+                            color = parseColor(pair.Value, 0);\r
+                            span.Foreground = new SolidColorBrush(color);\r
+                        }\r
+                        catch (Exception e)\r
+                        {\r
+                            NTDebug.l(e.Message);\r
+                        }\r
+                                   }\r
+                           }\r
+                if (nSize >= 0)\r
+                {\r
+                    double fSize = span.FontSize;\r
+                    fSize += fSize / 2 * nSize;\r
+                    span.FontSize = fSize;\r
+                }\r
+                else if (nSize <= 0)\r
+                {\r
+                    double fSize = span.FontSize;\r
+                    fSize += 2 * (double)nSize;\r
+                    span.FontSize = fSize;\r
+                }\r
+\r
+\r
+\r
+                           //int textStart = mParser.mOutput.Length;\r
+                mParser.DrawElementPush(span);\r
+                           int end = base.parse(source, retVal[0], retVal, breakType);\r
+                mParser.DrawElementPop();\r
+                           //int textEnd =  mParser.mOutput.Length;\r
+                       \r
+                          /* if(0 < color.Length){\r
+                                   try{\r
+                                           Color c = parseColor(color, 0);\r
+                                           //if(0 < nColor){\r
+                                                  ForegroundColorSpan span = new ForegroundColorSpan(nColor);\r
+                                   \r
+                                                   mSpannableObjectStack.add(\r
+                                                           new SpannableObject(span, textStart, textEnd, 0));//Spannable.SPAN_EXCLUSIVE_EXCLUSIVE));\r
+                                           //}\r
+                                   }catch(Exception e){\r
+                        NTDebug.l(e.Message);\r
+                    }\r
+                           }*/\r
+                           /*if(0 < size.Length){\r
+                                   try{\r
+                                           int nSize;\r
+                                           if('+' == size[0]){\r
+                                                   size = size.Substring(1);\r
+                                                   nSize = int.Parse(size, NumberStyles.Integer);\r
+                                           }else if('-' == size.charAt(0)){\r
+                                                   size = size.substring(1);\r
+                            nSize = Integer.parseInt(size, NumberStyles.Integer);\r
+                                                   nSize *= -1;\r
+                                           }else{\r
+                            nSize = Integer.parseInt(size, NumberStyles.Integer);\r
+                                           }\r
+                        nSize = int.Parse(size, NumberStyles.Integer);\r
+                                           float fSize = (float)nSize;\r
+                                           fSize /= 5;\r
+                                           fSize += 1;\r
+                                           //RelativeSizeSpan span = new RelativeSizeSpan(fSize);\r
+                                       //mSpannableObjectStack.add(\r
+                                               //          new SpannableObject(span, textStart, textEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE));\r
+                                       \r
+                                   }catch(Exception e){\r
+                        NTDebug.l(e.Message);\r
+                    }\r
+                           }*/\r
+                           return end;\r
+                   }\r
+           }\r
+           class FormElement : AbstractElement{\r
+                   public FormElement(NTHtmlParser parser) : base(parser)\r
+            {\r
+                       \r
+                   }\r
+               \r
+                   public override int parse(String source, int start, int[] retVal, int breakType){\r
+                       \r
+                           mParser.mFormAttributes = mParser.parseAttributes( source,  start, retVal);\r
+                           int n = source.IndexOf('>', start);\r
+                           if(0 > n){\r
+                                   return source.Length;\r
+                           }\r
+                           return base.parse(source, n+1, retVal, breakType);\r
+                   }\r
+       \r
+           }\r
+\r
+        class TextAreaElement : AbstractElement\r
+        {\r
+            public TextAreaElement(NTHtmlParser parser)\r
+                : base(parser)\r
+            {\r
+\r
+            }\r
+\r
+            public override int parse(String source, int start, int[] retVal, int breakType)\r
+            {\r
+\r
+                mParser.mTextAreaAttributes = mParser.parseAttributes(source, start, retVal);\r
+                int n = source.IndexOf('>', start);\r
+                if (0 > n)\r
+                {\r
+                    return source.Length;\r
+                }\r
+                return base.parse(source, n + 1, retVal, breakType);\r
+            }\r
+\r
+        }\r
+\r
+        \r
+        protected List<KeyValuePair<string, string>> parseAttributes(String source, int start, int[] retVal)\r
+        {\r
+\r
+            List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>();\r
+                   bool dFlag = false;//processing text within double quarts \r
+                   bool nameFlag = true; //processing the name word\r
+                   String wrkStr = "";\r
+                   String name = "";//, value = "";\r
+               \r
+                   for(int i = start; i < source.Length; i++){\r
+                           char c = source[i];\r
+                           switch(c){\r
+                           case '>':\r
+                                   if(!dFlag){\r
+                                           if(name.Length > 0 && wrkStr.Length > 0){\r
+                                                   list.Add(new KeyValuePair<string,string>(name, wrkStr));\r
+                                           }\r
+                                           retVal[0] = i+1;\r
+                                           return list;\r
+                                   }\r
+                                   wrkStr += c;\r
+                                   break;\r
+                           case ' ':\r
+                                   if(dFlag){\r
+                                           wrkStr += c;\r
+                                   }else{\r
+                                           if(name.Length > 0 && wrkStr.Length > 0){\r
+                                                   list.Add(new KeyValuePair<string,string>(name, wrkStr));\r
+                                           }\r
+                                           name = wrkStr = "";\r
+                                           nameFlag = true;\r
+                                   }\r
+                                   break;\r
+                           case '=':\r
+                                   if(dFlag){\r
+                                           wrkStr += c;\r
+                                   }else if(nameFlag){\r
+                                           name = wrkStr;\r
+                                           wrkStr = "";\r
+                                           nameFlag = false;\r
+                                   }\r
+                                   break;\r
+                case '"':\r
+                case '\'':\r
+                    if (dFlag)\r
+                    {\r
+                                           if(0 < wrkStr.Length){\r
+                                                   char c1 = wrkStr[wrkStr.Length-1];\r
+                                                   if('\\' == c1){\r
+                                                           wrkStr += c;\r
+                                                           break;\r
+                                                   }\r
+                                           }\r
+                                           dFlag = false;\r
+                                           if(!nameFlag){\r
+                                                   if(name.Length > 0 && wrkStr.Length > 0){\r
+                                                           list.Add(new KeyValuePair<string,string>(name, wrkStr));\r
+                                                   }\r
+                                                   name = wrkStr = "";\r
+                                                   nameFlag = true;\r
+                                           }\r
+                                   }else{\r
+                                           dFlag = true;\r
+                                   }\r
+                                   break;\r
+                           default:\r
+                                   wrkStr += c;\r
+                                   break;\r
+                           }\r
+                   }\r
+                   retVal[0] = source.Length;\r
+                   return list;                \r
+           }\r
+       \r
+    }\r
+\r
+    //--------------------------------------------------------------------------------------\r
+\r
+    class HTMLElementTree{\r
+           public char mC;\r
+           public int mType;\r
+        public List<HTMLElementTree> mTree = new List<HTMLElementTree>();\r
+           public HTMLElementTree(char c){mC = c; mType = HTMLElementTable.ELEMENT_TOKEN_NONE;}\r
+    }\r
+\r
+    class HTMLElementTable{\r
+\r
+           public const  int ELEMENT_TOKEN_NULL = -2;\r
+           public const  int ELEMENT_TOKEN_NONE = -1;\r
+           public const  int ELEMENT_TOKEN_HTML_S = 0;\r
+           public const  int ELEMENT_TOKEN_HTML_E = 1;\r
+           public const  int ELEMENT_TOKEN_COMMENT_S = 2;\r
+           public const  int ELEMENT_TOKEN_COMMENT_E = 3;\r
+           public const  int ELEMENT_TOKEN_TITLE_S = 4;\r
+           public const  int ELEMENT_TOKEN_TITLE_E = 5;\r
+           public const  int ELEMENT_TOKEN_BODY_S = 6;\r
+           public const  int ELEMENT_TOKEN_BODY_E = 7;\r
+           public const  int ELEMENT_TOKEN_ALINK_S = 8;\r
+           public const  int ELEMENT_TOKEN_ALINK_E = 9;\r
+           public const  int ELEMENT_TOKEN_BOLD_S = 10;\r
+           public const  int ELEMENT_TOKEN_BOLD_E = 11;\r
+           public const  int ELEMENT_TOKEN_INPUT = 12;\r
+           public const  int ELEMENT_TOKEN_BREAK = 13;\r
+           public const  int ELEMENT_TOKEN_CENTER_S = 14;\r
+           public const  int ELEMENT_TOKEN_CENTER_E = 15;\r
+           public const  int ELEMENT_TOKEN_FONT_S = 16;\r
+           public const  int ELEMENT_TOKEN_FONT_E = 17;\r
+           public const  int ELEMENT_TOKEN_HR = 18;\r
+           public const  int ELEMENT_TOKEN_PARAGRAPH = 19;\r
+           public const  int ELEMENT_TOKEN_UL_S = 20;\r
+           public const  int ELEMENT_TOKEN_UL_E = 21;\r
+           public const  int ELEMENT_TOKEN_LI = 22;\r
+        public const int ELEMENT_TOKEN_FORM_S = 23;\r
+        public const int ELEMENT_TOKEN_FORM_E = 24;\r
+        public const int ELEMENT_TOKEN_TEXTAREA_S = 25;\r
+        public const int ELEMENT_TOKEN_TEXTAREA_E = 26;\r
+\r
+\r
+\r
+        static HTMLElementTree mTopTree = null;\r
+           private String mElement;\r
+           private int mType;\r
+       \r
+           HTMLElementTable (string element, int type){\r
+                   mElement = element;\r
+                   mType = type;\r
+           }\r
+       \r
+           //static int counter = 0;\r
+       \r
+           public static int getElementTypeFromSource(String source, int index, int [] returnLength){\r
+                   return findTree(mTopTree, source, index, returnLength);\r
+           }\r
+       \r
+           static int findTree(HTMLElementTree parent, String source, int index, int [] returnLength){\r
+               \r
+                   if(source.Length == index){\r
+                           return ELEMENT_TOKEN_NONE;\r
+                   }\r
+               \r
+                   char c = source[index];\r
+               \r
+                   for(int i = 0; i < parent.mTree.Count; i++){\r
+                           HTMLElementTree current = parent.mTree[i];\r
+                           if(current.mC == c){\r
+                                   index++;\r
+                                   if(current.mType != ELEMENT_TOKEN_NONE){                    \r
+                                           returnLength[0] = index;\r
+                                           return current.mType;\r
+                                   }\r
+                                   return findTree(current, source, index, returnLength);\r
+                           }\r
+                   }\r
+                   return HTMLElementTable.ELEMENT_TOKEN_NONE;// No match code available\r
+           }\r
+       \r
+       \r
+           public static void init(){\r
+                   //Making element parse tree\r
+                   mTopTree = new HTMLElementTree((char)0x00);\r
+                   NTDebug.l("HTMLElement.length: " + htmlElement.Length);\r
+                   for( int i = 0; i < htmlElement.Length; i++){\r
+                           parseTree(mTopTree, htmlElement[i].mElement, 0, htmlElement[i].mType);\r
+                   }\r
+           }\r
+       \r
+       \r
+           static void parseTree(HTMLElementTree tree, String source, int index, int type){\r
+                   try{\r
+                           List<HTMLElementTree> parentTree = tree.mTree;\r
+                           HTMLElementTree newTree;\r
+                           char c = source[index];\r
+                           int i;\r
+                           for(i = 0; i < parentTree.Count; i++){\r
+                                   if(parentTree[i].mC == c){\r
+                                           break;\r
+                                   }\r
+                           }\r
+                           if(i == parentTree.Count){\r
+                                   newTree = new HTMLElementTree(c);\r
+                                   parentTree.Add(newTree);\r
+                                       //    NTDebug.l("HTMLEscape.parseTree(): err occured. #1");\r
+                                       //    return;\r
+                                   //}\r
+                           }else{\r
+                                   newTree = parentTree[i];\r
+                           }\r
+                           index++;\r
+                           if(source.Length == index){\r
+                                   newTree.mType = type;\r
+                                   //DebugUtil.log("Element setup:" + source + ":" + type + ":" + ++counter);\r
+                           }else{\r
+                                   parseTree(newTree, source, index, type);\r
+                           }\r
+                   }catch(Exception e){\r
+                NTDebug.l(e.Message);\r
+                   }\r
+           }\r
+       \r
+           static HTMLElementTable [] htmlElement = {\r
+                   new HTMLElementTable("<html", ELEMENT_TOKEN_HTML_S),\r
+                   new HTMLElementTable("<HTML", ELEMENT_TOKEN_HTML_S),\r
+                   new HTMLElementTable("<!--", ELEMENT_TOKEN_COMMENT_S),\r
+                   new HTMLElementTable("-->", ELEMENT_TOKEN_COMMENT_E),\r
+                   new HTMLElementTable("<TITLE>", ELEMENT_TOKEN_TITLE_S),\r
+                   new HTMLElementTable("<title>", ELEMENT_TOKEN_TITLE_S),\r
+                   new HTMLElementTable("<BODY", ELEMENT_TOKEN_BODY_S),\r
+                   new HTMLElementTable("<body", ELEMENT_TOKEN_BODY_S),\r
+                   new HTMLElementTable("<A ", ELEMENT_TOKEN_ALINK_S),\r
+                   new HTMLElementTable("<a ", ELEMENT_TOKEN_ALINK_S),\r
+                   new HTMLElementTable("<input ", ELEMENT_TOKEN_INPUT),\r
+                   new HTMLElementTable("<INPUT ", ELEMENT_TOKEN_INPUT),\r
+                   new HTMLElementTable("</html>", ELEMENT_TOKEN_HTML_E),\r
+                   new HTMLElementTable("</HTML>", ELEMENT_TOKEN_HTML_E),\r
+                   new HTMLElementTable("</TITLE>", ELEMENT_TOKEN_TITLE_E),\r
+                   new HTMLElementTable("</title>", ELEMENT_TOKEN_TITLE_E),\r
+                   new HTMLElementTable("</BODY>", ELEMENT_TOKEN_BODY_E),\r
+                   new HTMLElementTable("</body>", ELEMENT_TOKEN_BODY_E),\r
+                   new HTMLElementTable("</A>", ELEMENT_TOKEN_ALINK_E),\r
+                   new HTMLElementTable("</a>", ELEMENT_TOKEN_ALINK_E),\r
+                   new HTMLElementTable("<br>", ELEMENT_TOKEN_BREAK),\r
+                   new HTMLElementTable("<BR>", ELEMENT_TOKEN_BREAK),\r
+                   new HTMLElementTable("<CENTER>", ELEMENT_TOKEN_CENTER_S),\r
+                   new HTMLElementTable("<center>", ELEMENT_TOKEN_CENTER_S),\r
+                   new HTMLElementTable("</CENTER>", ELEMENT_TOKEN_CENTER_E),\r
+                   new HTMLElementTable("</center>", ELEMENT_TOKEN_CENTER_E),\r
+                   new HTMLElementTable("<FONT", ELEMENT_TOKEN_FONT_S),\r
+                   new HTMLElementTable("<font", ELEMENT_TOKEN_FONT_S),\r
+                   new HTMLElementTable("</font>", ELEMENT_TOKEN_FONT_E),\r
+                   new HTMLElementTable("</FONT>", ELEMENT_TOKEN_FONT_E),\r
+                   new HTMLElementTable("<B>", ELEMENT_TOKEN_BOLD_S),\r
+                   new HTMLElementTable("<b>", ELEMENT_TOKEN_BOLD_S),\r
+                   new HTMLElementTable("</B>", ELEMENT_TOKEN_BOLD_E),\r
+                   new HTMLElementTable("</b>", ELEMENT_TOKEN_BOLD_E),\r
+                   new HTMLElementTable("<HR>", ELEMENT_TOKEN_HR),\r
+                   new HTMLElementTable("<hr>", ELEMENT_TOKEN_HR),\r
+                   new HTMLElementTable("<p>", ELEMENT_TOKEN_PARAGRAPH),\r
+                   new HTMLElementTable("<P>", ELEMENT_TOKEN_PARAGRAPH),\r
+                   new HTMLElementTable("<LI>", ELEMENT_TOKEN_LI),\r
+                   new HTMLElementTable("<li>", ELEMENT_TOKEN_LI),\r
+                   new HTMLElementTable("<ul>", ELEMENT_TOKEN_UL_S),\r
+                   new HTMLElementTable("<UL>", ELEMENT_TOKEN_UL_S),\r
+                   new HTMLElementTable("</ul>", ELEMENT_TOKEN_UL_E),\r
+                   new HTMLElementTable("</UL>", ELEMENT_TOKEN_UL_E),\r
+                   new HTMLElementTable("<FORM", ELEMENT_TOKEN_FORM_S),\r
+                   new HTMLElementTable("<form", ELEMENT_TOKEN_FORM_S),\r
+                   new HTMLElementTable("</FORM>", ELEMENT_TOKEN_FORM_E),\r
+                   new HTMLElementTable("</form>", ELEMENT_TOKEN_FORM_E),\r
+                   new HTMLElementTable("<TEXTAREA", ELEMENT_TOKEN_TEXTAREA_S),\r
+                   new HTMLElementTable("<textarea", ELEMENT_TOKEN_TEXTAREA_S),\r
+                   new HTMLElementTable("</TEXTAREA>", ELEMENT_TOKEN_TEXTAREA_E),\r
+                   new HTMLElementTable("</textarea>", ELEMENT_TOKEN_TEXTAREA_E),\r
+                   //new HTMLElementTable("\n", ELEMENTTYPE_BLANK)\r
+           };\r
+    }// end of class HTMLElement\r
+\r
+}\r
diff --git a/NT2chView45/NtHtml/NTHtmlUtils.cs b/NT2chView45/NtHtml/NTHtmlUtils.cs
new file mode 100755 (executable)
index 0000000..af4dfef
--- /dev/null
@@ -0,0 +1,263 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+\r
+namespace NT2chView.NtHtml\r
+{\r
+    partial class NTHtmlUtils\r
+    {\r
+\r
+\r
+        public static void init()\r
+        {\r
+            HTMLEscapeTable.init();\r
+        }\r
+\r
+        public static string parseActionUrl(string host, string url, NTHtmlParser parser)\r
+        {\r
+            string action = null;\r
+            foreach (KeyValuePair<string, string> pair in parser.mFormAttributes)\r
+            {\r
+                if (pair.Key.Trim().Equals("action", StringComparison.CurrentCultureIgnoreCase))\r
+                {\r
+                    action = pair.Value;\r
+                    break;\r
+                }\r
+            }\r
+            return parseActionUrl( host, url, action);\r
+        }\r
+\r
+        public static string parseActionUrl(string host, string url, string action)\r
+        {\r
+            if (action == null)\r
+                return null;\r
+\r
+            int idx = action.LastIndexOf('?');\r
+            if (idx > 0)\r
+            {\r
+                action = action.Substring(0, idx);\r
+            }\r
+            action = action.Trim();\r
+\r
+            idx = url.LastIndexOf('/');\r
+            if (idx > 0 && idx < url.Length - 1)\r
+            {\r
+                url = url.Substring(0, idx + 1);\r
+            }\r
+\r
+            string newUrl = null;\r
+\r
+            idx = action.IndexOf("http://", StringComparison.CurrentCultureIgnoreCase);\r
+            if (idx == 0)\r
+            {\r
+                newUrl = action;\r
+            }\r
+            if (newUrl == null)\r
+            {\r
+                idx = action.IndexOf("../");\r
+                if (idx == 0)\r
+                {\r
+                    int n1 = url.LastIndexOf('/', url.Length - 2);\r
+                    if (n1 < 0)\r
+                        return null;\r
+                    newUrl = url.Substring(0, n1) + action.Substring(idx + 2);\r
+                }\r
+            }\r
+            if (newUrl == null)\r
+            {\r
+                idx = action.IndexOf("./");\r
+                if (idx == 0)\r
+                {\r
+                    newUrl = url + action.Substring(idx + 2);\r
+                }\r
+            }\r
+            if (newUrl == null)\r
+            {\r
+                idx = action.IndexOf('/');\r
+                if (idx == 0)\r
+                {\r
+                    newUrl = "http://" + host + action;\r
+                }\r
+                else if(idx < 0)\r
+                {\r
+                    newUrl = url + action;\r
+                }\r
+            }\r
+            return newUrl;\r
+        }\r
+\r
+\r
+      public  enum TOKEN{\r
+            NOTHING,\r
+            ALPHABET,\r
+            NUMBER,\r
+            WHITESPACE,\r
+            CONTROL_CODE,\r
+            NON_ASCII,\r
+            OTHER\r
+        };\r
+\r
+        public static TOKEN getToken(char c)\r
+        {\r
+            if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'))\r
+            {\r
+                return TOKEN.ALPHABET;\r
+            }\r
+            else if ('0' <= c && c <= '9')\r
+            {\r
+                return TOKEN.NUMBER;\r
+            }\r
+            else if (c == ' ' || c == '\t' || c == '\n')\r
+            {\r
+                return TOKEN.WHITESPACE;\r
+            }\r
+            else if (c < 0x21 || 0x7e < c)\r
+            {\r
+                return TOKEN.CONTROL_CODE;\r
+            }\r
+            else if (c > 0x7f)\r
+            {\r
+                return TOKEN.NON_ASCII;\r
+            }\r
+            else\r
+            {\r
+                return TOKEN.OTHER;\r
+            }\r
+        }\r
+         static int parseWebHost(string source, int start){\r
+               int charCnt = 0;\r
+           TOKEN previous = TOKEN.NOTHING;\r
+           char previousC = '\0';\r
+           bool hasComma = false; // must has a comma at least one;\r
+           bool initFirstChar = false;\r
+           bool hasAlphabet = false;\r
+           int i;\r
+           //DebugUtil.log(source.substring(start));\r
+           bool loop = true;//LABEL:\r
+           for( i = start; i < source.Length; i++){\r
+                   //DebugUtil.log(source.substring(i));\r
+                   char c = source[i];\r
+                   TOKEN token = getToken(c);\r
+                   switch(token){\r
+                   case TOKEN.ALPHABET:\r
+                           hasAlphabet = true;\r
+                    initFirstChar = true;\r
+                    charCnt++;\r
+                    break;\r
+                case TOKEN.NUMBER:\r
+                           initFirstChar = true;\r
+                           charCnt++;\r
+                           break;\r
+                   case TOKEN.CONTROL_CODE:\r
+                    loop = false;\r
+                           break;// LABEL;\r
+                   case TOKEN.OTHER:\r
+                   default:\r
+                           if(initFirstChar){\r
+                                   // only hyphen allowed in domain name.\r
+                                   if('-' == c){\r
+                                           charCnt++;\r
+                                           break;\r
+                                   }\r
+                                   // not allowed successive comma\r
+                                   if('.' == c && previousC != '.' && previousC != '-'){\r
+                                           charCnt++;\r
+                                           hasComma = true;\r
+                                           break;\r
+                                   }\r
+                           }\r
+                    loop = false;\r
+                           break;// LABEL;\r
+                   }\r
+                if (!loop)\r
+                    break;\r
+                previous = token;\r
+                           previousC = c;\r
+           }\r
+           if('-' == previousC || '.' == previousC){\r
+                   charCnt--;\r
+                   i--;\r
+                   previousC = source[i];\r
+           }\r
+       \r
+           // top domain names haven't degits. \r
+           if(TOKEN.NUMBER == previous && hasAlphabet == true){\r
+                   bool loop2 = true;//LABEL2:\r
+                   for(i--; i > 0; i--){\r
+                           char c = source[i];\r
+                           TOKEN token = getToken(c);\r
+                           switch(token){\r
+                           case TOKEN.NUMBER:\r
+                                   charCnt--;\r
+                                   break;\r
+                           case TOKEN.ALPHABET:\r
+                           default:\r
+                        loop2 = false;\r
+                           break;// LABEL2; \r
+                           }\r
+                           previous = token;\r
+                    if (!loop2)\r
+                        break;\r
+                   }\r
+           }\r
+           return ((TOKEN.ALPHABET == previous || TOKEN.NUMBER == previous) && hasComma) ? charCnt : -1;\r
+         }\r
+         public static int parseWebAddress(string source, int start){\r
+           int n = parseWebHost(source, start);\r
+\r
+           if(0 > n || (source.Length <= (start+n)) || '/' != source[start + n]){\r
+                   return n;\r
+           }\r
+           n++;\r
+           bool loop = true;//LABEL:\r
+            while ((start + n) < source.Length)\r
+            {\r
+                   char c = source[start + n];\r
+                   TOKEN token = getToken(c);\r
+                   switch(token){\r
+                   case TOKEN.NUMBER:\r
+                    break;\r
+                   case TOKEN.ALPHABET:\r
+                           break;\r
+                   case TOKEN.OTHER:\r
+                           switch(c){\r
+                           case '-':\r
+                    case '+':\r
+                           case '_':\r
+                           case '.':\r
+                           case '/':\r
+                           case '?':\r
+                           case '%':\r
+                           case '&':\r
+                           case '=':\r
+                           case '[':\r
+                           case ']':\r
+                           case '*':\r
+                           case '~':\r
+                           case ':':\r
+                           case '#':\r
+                           case '!':\r
+                    case '@':\r
+                    case '(':\r
+                    case ')':\r
+                        break;\r
+                           default:\r
+                        loop = false;\r
+                                   break;// LABEL;\r
+                           }//end of switch(c)\r
+                           break;\r
+                   case TOKEN.NON_ASCII:\r
+                   case TOKEN.CONTROL_CODE:\r
+                   default:\r
+                    loop = false;\r
+                           break;// LABEL; \r
+                   }// end of switch(token)   \r
+                if (!loop)\r
+                    break;\r
+                   n++;\r
+           }// end of while:LABEL\r
+           return n--;\r
+        }\r
+\r
+    }\r
+}\r
diff --git a/NT2chView45/NtHtml/NTHtmlUtils_EscapeTable.cs b/NT2chView45/NtHtml/NTHtmlUtils_EscapeTable.cs
new file mode 100755 (executable)
index 0000000..3d60fe4
--- /dev/null
@@ -0,0 +1,476 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Globalization;\r
+using System.IO;\r
+\r
+namespace NT2chView.NtHtml\r
+{\r
+    partial class  NTHtmlUtils\r
+    {\r
+        public static string parseHTMLEscape(string source)\r
+        {\r
+            int i = 0;\r
+            int start = 0;\r
+            StringBuilder\r
+                sb = new StringBuilder(source.Length);\r
+            for (; i < source.Length; i++)\r
+            {\r
+                switch (source[i])\r
+                {\r
+                    case '&':\r
+                        int retLen;\r
+                        if ((i + 1 < source.Length) && source[i + 1] == '#')\r
+                        {\r
+                            char c = NTHtmlUtils.parseHTMLDecimalHexEscape(source, i + 2, out retLen);\r
+                            if (c != '\0')\r
+                            {\r
+                                if (start < i)\r
+                                    sb.Append(source.Substring(start, i - start));\r
+                                sb.Append(c);\r
+                                start = retLen;\r
+                                i = retLen - 1;\r
+\r
+                            }\r
+                        }\r
+                        else\r
+                        {\r
+                            char c = NTHtmlUtils.HTMLEscapeTable.getCodeFromEscape(source, i + 1, out retLen);\r
+                            if (c != '\0')\r
+                            {\r
+                                if (start < i)\r
+                                    sb.Append(source.Substring(start, i - start));\r
+                                sb.Append(c);\r
+                                start = retLen;\r
+                                i = retLen - 1;\r
+\r
+                            }\r
+                        }\r
+                        break;\r
+                }\r
+            }\r
+            if (start < source.Length)\r
+            {\r
+                sb.Append(source.Substring(start, source.Length - start));\r
+            }\r
+\r
+            return sb.ToString();\r
+\r
+        }\r
+\r
+        public static char parseHTMLDecimalHexEscape(String source, int offset, out int retVal){\r
+            StringBuilder wrk =  new StringBuilder(16);\r
+                   bool fHEX = false;\r
+            retVal = 0;\r
+                   char c;\r
+                   //int nVal;\r
+                   byte [] bVal = new byte[2];\r
+                   bool loop = true;\r
+                   for( int j = offset; j < source.Length; j++){\r
+                           c =  source[j];\r
+                           if(';' == c){\r
+                                   if(wrk.Length > 0 && ((fHEX && wrk.Length <= 4) || !fHEX && wrk.Length <= 5)){\r
+                                           //DebugUtil.log("convert hex escape: 0x" + wrk);\r
+                                           //c = (char)Integer.parseInt(wrk, 16);\r
+                                           retVal = j+1;\r
+                                           try{\r
+                                                   int nVal = int.Parse(wrk.ToString(), fHEX ? NumberStyles.HexNumber : NumberStyles.Integer);\r
+                            bVal[0] = (byte)(nVal & 0x000000ff);\r
+                                                   bVal[1] = (byte)((nVal>>8) & 0x000000ff);\r
+                            MemoryStream ms = new MemoryStream(bVal, false);\r
+                            Encoding enc = Encoding.GetEncoding(NTAppState.HOST_2CH_ENCODING);\r
+                            StreamReader sr = new StreamReader(ms, enc);\r
+                            c = (char)sr.Read();\r
+                            sr.Close();\r
+                            ms.Close();\r
+                                                   return c;\r
+                                           }catch(Exception e){\r
+                            NTDebug.l(e.Message);\r
+                                                   return '\0';\r
+                                           }\r
+                                   }\r
+                                   break;\r
+                           }else if('x' == c || 'X' == c){\r
+                                   if(j != offset){\r
+                                           break;\r
+                                   }\r
+                                   fHEX = true;\r
+                           }else{\r
+                                   switch(getToken(c)){        \r
+                                   case TOKEN.NUMBER:\r
+                                           wrk.Append(c);// = wrk + c;\r
+                                           break;\r
+                                   case TOKEN.ALPHABET:\r
+                                           if(!fHEX){\r
+                            loop = false;\r
+                                                   break;\r
+                                           }\r
+                                           wrk.Append(c);// = wrk + c;\r
+                                           break;\r
+                                   default:\r
+                            loop = false;\r
+                                               break;\r
+                                   }\r
+                    if (!loop)\r
+                        break;\r
+                           }\r
+                   }// End of the for\r
+                   return '\0';\r
+           }\r
+        \r
+\r
+        class HttpEscapeTree\r
+        {\r
+            public char mC;\r
+            public char mCode;\r
+            public List<HttpEscapeTree> mTree = new List<HttpEscapeTree>();\r
+            public HttpEscapeTree(char c) { mC = c; mCode = '\0'; }\r
+        }\r
+\r
+\r
+\r
+        public class HTMLEscapeTable{\r
+               static HttpEscapeTree mTopTree = null;\r
+               //private static ArrayList<HTMLEscape> mHtmlEscape = new ArrayList<HTMLEscape>();\r
+               private String mEscape;\r
+               private char mCode;\r
+               //private ArrayList<HTMLEscapeTable> mTree = new ArrayList<HTMLEscapeTable>();\r
+       \r
+               HTMLEscapeTable (String escape, char code){\r
+                       mEscape = escape;\r
+                       mCode = code;\r
+               }\r
+       \r
+               //static int counter = 0;\r
+\r
+            public static char getCodeFromEscape(String escape, int index, out int returnLength)\r
+            {\r
+                       return findTree(mTopTree, escape, index, out returnLength);\r
+               }\r
+       \r
+               static char findTree(HttpEscapeTree parent, String escape, int index, out int returnLength){\r
+               \r
+                       if(escape.Length == index){\r
+                    returnLength = -1;\r
+                               return '\0';\r
+                       }\r
+               \r
+                       char c = escape[index];\r
+               \r
+                       for(int i = 0; i < parent.mTree.Count; i++){\r
+                               HttpEscapeTree current = parent.mTree[i];\r
+                               if(current.mC == c){\r
+                                       index++;\r
+                                       if(';' == c){                   \r
+                                               returnLength = index;\r
+                                               return current.mCode;\r
+                                       }\r
+                                       return findTree(current, escape, index, out returnLength);\r
+                               }\r
+                       }\r
+                returnLength = -1;\r
+                       return '\0';// No match code available\r
+               }\r
+       \r
+       \r
+               public static void init(){\r
+                       //Making escape-code tree\r
+                       mTopTree = new HttpEscapeTree((char)0x00);\r
+                       //DebugUtil.log("HTMLEscape.length: " + htmlEscape.length);\r
+                       for( int i = 0; i < htmlEscape.Length; i++){\r
+                               parseTree(mTopTree, htmlEscape[i].mEscape, 0, htmlEscape[i].mCode);\r
+                       }\r
+               }\r
+       \r
+       \r
+               static void parseTree(HttpEscapeTree tree, String source, int index, char code){\r
+                       try{\r
+                               List<HttpEscapeTree> parentTree = tree.mTree;\r
+                               HttpEscapeTree newTree;\r
+                               char c = source[index];\r
+                               int i;\r
+                               for(i = 0; i < parentTree.Count; i++){\r
+                                       if(parentTree[i].mC == c){\r
+                                               break;\r
+                                       }\r
+                               }\r
+                               if(i == parentTree.Count){\r
+                                       newTree = new HttpEscapeTree(c);\r
+                                       parentTree.Add(newTree);\r
+                                           //    NTDebug.l("HTMLEscape.parseTree(): err occured. #1");\r
+                                           //    return;\r
+                                       //}\r
+                               }else{\r
+                                       newTree = parentTree[i];//.get(i);\r
+                               }\r
+                               index++;\r
+                               if(source.Length == index){\r
+                                       newTree.mCode = code;\r
+                                       //DebugUtil.log("EscapeCode setup:" + source + ":" + String.format("0x%04X", (int)code) + ":" + ++counter);\r
+                                       //DebugUtil.log("EscapeCode setup:" + source + ":" + String.format("0x%04X", 10));\r
+                               }else{\r
+                                       parseTree(newTree, source, index, code);\r
+                               }\r
+                       }catch(Exception e){\r
+                           NTDebug.l(e.Message);\r
+                       }\r
+               }\r
+       \r
+               static HTMLEscapeTable [] htmlEscape = {\r
+                       new HTMLEscapeTable("quot;", (char)0x22),//quotation mark = APL quote\r
+                       new HTMLEscapeTable("amp;", (char)0x26),//ampersand\r
+                       new HTMLEscapeTable("lt;", (char)0x3C),//less-than sign\r
+                       new HTMLEscapeTable("gt;", (char)0x3E),//greater-than sign\r
+                       new HTMLEscapeTable("nbsp;", (char)0xA0),//no-break space = non-breaking space\r
+                       new HTMLEscapeTable("iexcl;", (char)0xA1),//inverted exclamation mark\r
+                       new HTMLEscapeTable("cent;", (char)0xA2),//cent sign\r
+                       new HTMLEscapeTable("pound;", (char)0xA3),//pound sign\r
+                       new HTMLEscapeTable("curren;", (char)0xA4),//currency sign\r
+                       new HTMLEscapeTable("yen;", (char)0xA5),//yen sign = yuan sign\r
+                       new HTMLEscapeTable("brvbar;", (char)0xA6),//broken bar = broken vertical bar\r
+                       new HTMLEscapeTable("sect;", (char)0xA7),//section sign\r
+                       new HTMLEscapeTable("uml;", (char)0xA8),//diaeresis = spacing diaeresis\r
+                       new HTMLEscapeTable("copy;", (char)0xA9),//copyright sign\r
+                       new HTMLEscapeTable("ordf;", (char)0xAA),//feminine ordinal indicator\r
+                       new HTMLEscapeTable("laquo;", (char)0xAB),//left-pointing double angle quotation mark = left pointing guillemet\r
+                       new HTMLEscapeTable("not;", (char)0xAC),//not sign\r
+                       new HTMLEscapeTable("shy;", (char)0xAD),//soft hyphen = discretionary hyphen\r
+                       new HTMLEscapeTable("reg;", (char)0xAE),//registered sign = registered trade mark sign\r
+                       new HTMLEscapeTable("macr;", (char)0xAF),//macron = spacing macron = overline = APL overbar\r
+                       new HTMLEscapeTable("deg;", (char)0xB0),//degree sign\r
+                       new HTMLEscapeTable("plusmn;", (char)0xB1),//plus-minus sign = plus-or-minus sign\r
+                       new HTMLEscapeTable("sup2;", (char)0xB2),//superscript two = superscript digit two = squared\r
+                       new HTMLEscapeTable("sup3;", (char)0xB3),//superscript three = superscript digit three = cubed\r
+                       new HTMLEscapeTable("acute;",(char)0xB4),//acute accent = spacing acute\r
+                       new HTMLEscapeTable("micro;",(char) 0xB5),//micro sign\r
+                       new HTMLEscapeTable("para;", (char)0xB6),//pilcrow sign = paragraph sign\r
+                       new HTMLEscapeTable("middot;", (char)0xB7),//middle dot = Georgian comma = Greek middle dot\r
+                       new HTMLEscapeTable("cedil;", (char)0xB8),//cedilla = spacing cedilla\r
+                       new HTMLEscapeTable("sup1;", (char)0xB9),//superscript one = superscript digit one\r
+                       new HTMLEscapeTable("ordm;", (char)0xBA),//masculine ordinal indicator\r
+                       new HTMLEscapeTable("raquo;", (char)0xBB),//right-pointing double angle quotation mark = right pointing guillemet\r
+                       new HTMLEscapeTable("frac14;", (char)0xBC),//vulgar fraction one quarter = fraction one quarter\r
+                       new HTMLEscapeTable("frac12;", (char)0xBD),//vulgar fraction one half = fraction one half\r
+                       new HTMLEscapeTable("frac34;", (char)0xBE),//vulgar fraction three quarters = fraction three quarters\r
+                       new HTMLEscapeTable("iquest;", (char)0xBF),//inverted question mark = turned question mark\r
+                       new HTMLEscapeTable("Agrave;", (char)0xC0),//latin capital letter A with grave = latin capital letter A grave\r
+                       new HTMLEscapeTable("Aacute;", (char)0xC1),//latin capital letter A with acute\r
+                       new HTMLEscapeTable("Acirc;", (char)0xC2),//latin capital letter A with circumflex\r
+                       new HTMLEscapeTable("Atilde;", (char)0xC3),//latin capital letter A with tilde\r
+                       new HTMLEscapeTable("Auml;", (char)0xC4),//latin capital letter A with diaeresis\r
+                       new HTMLEscapeTable("Aring;", (char)0xC5),//latin capital letter A with ring above = latin capital letter A ring\r
+                       new HTMLEscapeTable("AElig;", (char)0xC6),//latin capital letter AE = latin capital ligature AE\r
+                       new HTMLEscapeTable("Ccedil;", (char)0xC7),//latin capital letter C with cedilla\r
+                       new HTMLEscapeTable("Egrave;", (char)0xC8),//latin capital letter E with grave\r
+                       new HTMLEscapeTable("Eacute;", (char)0xC9),//latin capital letter E with acute\r
+                       new HTMLEscapeTable("Ecirc;", (char)0xCA),//latin capital letter E with circumflex\r
+                       new HTMLEscapeTable("Euml;",(char) 0xCB),//latin capital letter E with diaeresis\r
+                       new HTMLEscapeTable("Igrave;", (char)0xCC),//latin capital letter I with grave\r
+                       new HTMLEscapeTable("Iacute;", (char)0xCD),//latin capital letter I with acute\r
+                       new HTMLEscapeTable("Icirc;", (char)0xCE),//latin capital letter I with circumflex\r
+                       new HTMLEscapeTable("Iuml;",(char) 0xCF),//latin capital letter I with diaeresis\r
+                       new HTMLEscapeTable("ETH;", (char)0xD0),//latin capital letter ETH\r
+                       new HTMLEscapeTable("Ntilde;", (char)0xD1),//latin capital letter N with tilde\r
+                       new HTMLEscapeTable("Ograve;", (char)0xD2),//latin capital letter O with grave\r
+                       new HTMLEscapeTable("Oacute;",(char) 0xD3),//latin capital letter O with acute\r
+                       new HTMLEscapeTable("Ocirc;", (char)0xD4),//latin capital letter O with circumflex\r
+                       new HTMLEscapeTable("Otilde;", (char)0xD5),//latin capital letter O with tilde\r
+                       new HTMLEscapeTable("Ouml;", (char)0xD6),//latin capital letter O with diaeresis\r
+                       new HTMLEscapeTable("times;", (char)0xD7),//multiplication sign\r
+                       new HTMLEscapeTable("Oslash;", (char)0xD8),//latin capital letter O with stroke = latin capital letter O slash\r
+                       new HTMLEscapeTable("Ugrave;", (char)0xD90),//latin capital letter U with grave\r
+                       new HTMLEscapeTable("Uacute;", (char)0xDA),//latin capital letter U with acute\r
+                       new HTMLEscapeTable("Ucirc;", (char)0xDB),//latin capital letter U with circumflex\r
+                       new HTMLEscapeTable("Uuml;", (char)0xDC),//latin capital letter U with diaeresis\r
+                       new HTMLEscapeTable("Yacute", (char)0xDD),//latin capital letter Y with acute\r
+                       new HTMLEscapeTable("THORN;", (char)0xDE),//latin capital letter THORN\r
+                       new HTMLEscapeTable("szlig;", (char)0xDF),//latin small letter sharp s = ess-zed\r
+                       new HTMLEscapeTable("agrave;", (char)0xE0),//latin small letter a with grave = latin small letter a grave\r
+                       new HTMLEscapeTable("aacute;", (char)0xE1),//latin small letter a with acute\r
+                       new HTMLEscapeTable("acirc;", (char)0xE2),//latin small letter a with circumflex\r
+                       new HTMLEscapeTable("atilde;", (char)0xE3),//latin small letter a with tilde\r
+                       new HTMLEscapeTable("auml;", (char)0xE4),//latin small letter a with diaeresis\r
+                       new HTMLEscapeTable("aring;", (char)0xE5),//latin small letter a with ring above = latin small letter a ring\r
+                       new HTMLEscapeTable("aelig;", (char)0xE6),//latin small letter ae = latin small ligature ae\r
+                       new HTMLEscapeTable("ccedil;", (char)0xE7),//latin small letter c with cedilla\r
+                       new HTMLEscapeTable("egrave;", (char)0xE8),//latin small letter e with grave\r
+                       new HTMLEscapeTable("eacute;", (char)0xE9),//latin small letter e with acute\r
+                       new HTMLEscapeTable("ecirc;", (char)0xEA),//latin small letter e with circumflex\r
+                       new HTMLEscapeTable("euml;", (char)0xEB),//latin small letter e with diaeresis\r
+                       new HTMLEscapeTable("igrave;", (char)0xEC),//latin small letter i with grave\r
+                       new HTMLEscapeTable("iacute;", (char)0xED),//latin small letter i with acute\r
+                       new HTMLEscapeTable("icirc;", (char)0xEE),//latin small letter i with circumflex\r
+                       new HTMLEscapeTable("iuml;", (char)0xEF),//latin small letter i with diaeresis\r
+                       new HTMLEscapeTable("eth;", (char)0xF0),//latin small letter eth\r
+                       new HTMLEscapeTable("ntilde;", (char)0xF1),//latin small letter n with tilde\r
+                       new HTMLEscapeTable("ograve;", (char)0xF2),//latin small letter o with grave\r
+                       new HTMLEscapeTable("oacute;", (char)0xF3),//latin small letter o with acute\r
+                       new HTMLEscapeTable("ocirc;",(char) 0xF4),//latin small letter o with circumflex\r
+                       new HTMLEscapeTable("otilde;", (char)0xF5),//latin small letter o with tilde\r
+                       new HTMLEscapeTable("ouml;", (char)0xF6),//latin small letter o with diaeresis\r
+                       new HTMLEscapeTable("divide;", (char)0xF7),//division sign\r
+                       new HTMLEscapeTable("oslash;", (char)0xF8),//latin small letter o with stroke, = latin small letter o slash\r
+                       new HTMLEscapeTable("ugrave;", (char)0xF9),//latin small letter u with grave\r
+                       new HTMLEscapeTable("uacute;", (char)0xFA),//latin small letter u with acute\r
+                       new HTMLEscapeTable("ucirc;", (char)0xFB),//latin small letter u with circumflex\r
+                       new HTMLEscapeTable("uuml;", (char)0xFC),//latin small letter u with diaeresis\r
+                       new HTMLEscapeTable("yacute;", (char)0xFD),//latin small letter y with acute\r
+                       new HTMLEscapeTable("thorn;",(char) 0xFE),//latin small letter thorn with\r
+                       new HTMLEscapeTable("yuml;", (char)0xFF),//latin small letter y with diaeresis\r
+       \r
+       \r
+                       new HTMLEscapeTable("OElig;", (char)0x0152),//latin capital ligature OE\r
+                       new HTMLEscapeTable("oelig;", (char)0x0153),//latin small ligature oe\r
+                       new HTMLEscapeTable("Scaron;", (char)0x0160),//latin capital letter S with caron\r
+                       new HTMLEscapeTable("scaron;", (char)0x0161),//latin small letter s with caron\r
+                       new HTMLEscapeTable("Yuml;", (char)0x0178),//latin capital letter Y with diaeresis\r
+                       new HTMLEscapeTable("fnof;", (char)0x0192),//latin small f with hook = function = florin\r
+                       new HTMLEscapeTable("circ;", (char)0x02C6),//modifier letter circumflex accent\r
+                       new HTMLEscapeTable("tilde;", (char)0x02DC),//small tilde\r
+                       new HTMLEscapeTable("Alpha;", (char)0x391),//greek capital letter alpha\r
+                       new HTMLEscapeTable("Beta;", (char)0x392),//greek capital letter beta\r
+                       new HTMLEscapeTable("Gamma;", (char)0x393),//greek capital letter gamma\r
+                       new HTMLEscapeTable("Delta;", (char)0x394),//greek capital letter delta\r
+                       new HTMLEscapeTable("Epsilon;", (char)0x395),//greek capital letter epsilon\r
+                       new HTMLEscapeTable("Zeta;", (char)0x396),//greek capital letter zeta\r
+                       new HTMLEscapeTable("Eta;", (char)0x397),//greek capital letter eta\r
+                       new HTMLEscapeTable("Theta;", (char)0x398),//greek capital letter theta\r
+                       new HTMLEscapeTable("Iota;", (char)0x399),//greek capital letter iota\r
+                       new HTMLEscapeTable("Kappa;", (char)0x39A),//greek capital letter kappa\r
+                       new HTMLEscapeTable("Lambda;", (char)0x39B),//greek capital letter lambda\r
+                       new HTMLEscapeTable("Mu;", (char)0x39C),//greek capital letter mu\r
+                       new HTMLEscapeTable("Nu;", (char)0x39D),//greek capital letter nu\r
+                       new HTMLEscapeTable("Xi;", (char)0x39E),//greek capital letter xi\r
+                       new HTMLEscapeTable("Omicron;", (char)0x39F),//greek capital letter omicron\r
+                       new HTMLEscapeTable("Pi;", (char)0x3A0),//greek capital letter pi\r
+                       new HTMLEscapeTable("Rho;", (char)0x3A1),//greek capital letter rho\r
+                       new HTMLEscapeTable("Sigma;", (char)0x3A3),//greek capital letter sigma\r
+                       new HTMLEscapeTable("Tau;", (char)0x3A4),//greek capital letter tau\r
+                       new HTMLEscapeTable("Upsilon;", (char)0x3A5),//greek capital letter upsilon\r
+                       new HTMLEscapeTable("Phi;", (char)0x3A6),//greek capital letter phi\r
+                       new HTMLEscapeTable("Chi;", (char)0x3A7),//greek capital letter chi\r
+                       new HTMLEscapeTable("Psi;", (char)0x3A8),//greek capital letter psi\r
+                       new HTMLEscapeTable("Omega;", (char)0x3A9),//greek capital letter omega\r
+                       new HTMLEscapeTable("alpha;", (char)0x3B1),//greek small letter alpha\r
+                       new HTMLEscapeTable("beta;", (char)0x3B2),//greek small letter beta\r
+                       new HTMLEscapeTable("gamma;", (char)0x3B3),//greek small letter gamma\r
+                       new HTMLEscapeTable("delta;", (char)0x3B4),//greek small letter delta\r
+                       new HTMLEscapeTable("epsilon;", (char)0x3B5),//greek small letter epsilon\r
+                       new HTMLEscapeTable("zeta;", (char)0x3B6),//greek small letter zeta\r
+                       new HTMLEscapeTable("eta;", (char)0x3B7),//greek small letter eta\r
+                       new HTMLEscapeTable("theta;", (char)0x3B8),//greek small letter theta\r
+                       new HTMLEscapeTable("iota;", (char)0x3B9),//greek small letter iota\r
+                       new HTMLEscapeTable("kappa;", (char)0x3BA),//greek small letter kappa\r
+                       new HTMLEscapeTable("lambda;", (char)0x3BB),//greek small letter lambda\r
+                       new HTMLEscapeTable("mu;", (char)0x3BC),//greek small letter mu\r
+                       new HTMLEscapeTable("nu;", (char)0x3BD),//greek small letter nu\r
+                       new HTMLEscapeTable("xi;", (char)0x3BE),//greek small letter xi\r
+                       new HTMLEscapeTable("omicron;", (char)0x3BF),//greek small letter omicron\r
+                       new HTMLEscapeTable("pi;", (char)0x3C0),//greek small letter pi\r
+                       new HTMLEscapeTable("rho;", (char)0x3C1),//greek small letter rho\r
+                       new HTMLEscapeTable("sigmaf;", (char)0x3C2),//greek small letter final sigma\r
+                       new HTMLEscapeTable("sigma;", (char)0x3C3),//greek small letter sigma\r
+                       new HTMLEscapeTable("tau;", (char)0x3C4),//greek small letter tau\r
+                       new HTMLEscapeTable("upsilon;", (char)0x3C5),//greek small letter upsilon\r
+                       new HTMLEscapeTable("phi;", (char)0x3C6),//greek small letter phi\r
+                       new HTMLEscapeTable("chi;", (char)0x3C7),//greek small letter chi\r
+                       new HTMLEscapeTable("psi;", (char)0x3C8),//greek small letter psi\r
+                       new HTMLEscapeTable("omega;", (char)0x3C9),//greek small letter omega\r
+                       new HTMLEscapeTable("thetasym;", (char)0x3D1),//greek small letter theta symbol\r
+                       new HTMLEscapeTable("upsih;", (char)0x3D2),//greek upsilon with hook symbol\r
+                       new HTMLEscapeTable("piv;", (char)0x3D3),//greek pi symbol\r
+                       new HTMLEscapeTable("bull;", (char)0x2022),//bullet = black small circle\r
+                       new HTMLEscapeTable("hellip;", (char)0x2026),//horizontal ellipsis = three dot leader\r
+                       new HTMLEscapeTable("prime;", (char)0x2032),//prime = minutes = feet\r
+                       new HTMLEscapeTable("Prime;", (char)0x2033),//double prime = seconds = inches\r
+                       new HTMLEscapeTable("oline;", (char)0x203E),//overline = spacing overscore\r
+                       new HTMLEscapeTable("frasl;", (char)0x2044),//fraction slash\r
+                       new HTMLEscapeTable("weierp;", (char)0x2118),//script capital P = power set = Weierstrass p\r
+                       new HTMLEscapeTable("image;", (char)0x2111),//blackletter capital I = imaginary part\r
+                       new HTMLEscapeTable("real;", (char)0x211C),//blackletter capital R = real part symbol\r
+                       new HTMLEscapeTable("trade;", (char)0x2122),//trade mark sign\r
+                       new HTMLEscapeTable("alefsym;", (char)0x2135),//alef symbol = first transfinite cardinal\r
+                       new HTMLEscapeTable("larr;", (char)0x2190),//leftwards arrow\r
+                       new HTMLEscapeTable("uarr;", (char)0x2191),//upwards arrow\r
+                       new HTMLEscapeTable("rarr;", (char)0x2192),//rightwards arrow\r
+                       new HTMLEscapeTable("darr;", (char)0x2193),//downwards arrow\r
+                       new HTMLEscapeTable("harr;", (char)0x2194),//left right arrow\r
+                       new HTMLEscapeTable("crarr;", (char)0x21B5),//downwards arrow with corner leftwards = carriage return\r
+                       new HTMLEscapeTable("lArr;", (char)0x21D0),//leftwards double arrow\r
+                       new HTMLEscapeTable("uArr;", (char)0x21D1),//upwards double arrow\r
+                       new HTMLEscapeTable("rArr;", (char)0x21D2),//rightwards double arrow\r
+                       new HTMLEscapeTable("dArr;", (char)0x21D3),//downwards double arrow\r
+                       new HTMLEscapeTable("hArr;", (char)0x21D4),//left right double arrow\r
+                       new HTMLEscapeTable("forall;", (char)0x2200),//for all\r
+                       new HTMLEscapeTable("part;", (char)0x2202),//partial differential\r
+                       new HTMLEscapeTable("exist;", (char)0x2203),//there exists\r
+                       new HTMLEscapeTable("empty;", (char)0x2205),//empty set = null set = diameter\r
+                       new HTMLEscapeTable("nabla;", (char)0x2207),//nabla = backward difference\r
+                       new HTMLEscapeTable("isin;", (char)0x2208),//element of\r
+                       new HTMLEscapeTable("notin;", (char)0x2209),//not an element of\r
+                       new HTMLEscapeTable("ni;", (char)0x220B),//contains as member\r
+                       new HTMLEscapeTable("prod;", (char)0x220F),//n-ary product = product sign\r
+                       new HTMLEscapeTable("sum;", (char)0x2211),//n-ary sumation\r
+                       new HTMLEscapeTable("minus;", (char)0x2212),//minus sign\r
+                       new HTMLEscapeTable("lowast;", (char)0x2217),//asterisk operator\r
+                       new HTMLEscapeTable("radic;", (char)0x221A),//square root = radical sign\r
+                       new HTMLEscapeTable("prop;", (char)0x221D),//proportional to\r
+                       new HTMLEscapeTable("infin;", (char)0x221E),//infinity\r
+                       new HTMLEscapeTable("ang;", (char)0x2220),//angle\r
+                       new HTMLEscapeTable("and;", (char)0x2227),//logical and = wedge\r
+                       new HTMLEscapeTable("or;", (char)0x2228),//logical or = vee\r
+                       new HTMLEscapeTable("cap;", (char)0x2229),//intersection = cap\r
+                       new HTMLEscapeTable("cup;", (char)0x222A),//union = cup\r
+                       new HTMLEscapeTable("int;", (char)0x222B),//integral\r
+                       new HTMLEscapeTable("there4;", (char)0x2234),//therefore\r
+                       new HTMLEscapeTable("sim;", (char)0x223C),//tilde operator = varies with = similar to\r
+                       new HTMLEscapeTable("cong;", (char)0x2245),//approximately equal to\r
+                       new HTMLEscapeTable("asymp;", (char)0x2248),//almost equal to = asymptotic to\r
+                       new HTMLEscapeTable("ne;", (char)0x2260),//not equal to\r
+                       new HTMLEscapeTable("equiv;", (char)0x2261),//identical to\r
+                       new HTMLEscapeTable("le;", (char)0x2264),//less-than or equal to\r
+                       new HTMLEscapeTable("ge;", (char)0x2265),//greater-than or equal to\r
+                       new HTMLEscapeTable("sub;", (char)0x2282),//subset of\r
+                       new HTMLEscapeTable("sup;", (char)0x2283),//superset of\r
+                       new HTMLEscapeTable("nsub;", (char)0x2284),//not a subset of\r
+                       new HTMLEscapeTable("sube;", (char)0x2286),//subset of or equal to\r
+                       new HTMLEscapeTable("supe;", (char)0x2287),//superset of or equal to\r
+                       new HTMLEscapeTable("oplus;", (char)0x2295),//circled plus = direct sum\r
+                       new HTMLEscapeTable("otimes;", (char)0x2297),//circled times = vector product\r
+                       new HTMLEscapeTable("perp;", (char)0x22A5),//up tack = orthogonal to = perpendicular\r
+                       new HTMLEscapeTable("sdot;", (char)0x22C5),//dot operator\r
+                       new HTMLEscapeTable("lceil;", (char)0x2308),//left ceiling = apl upstile\r
+                       new HTMLEscapeTable("rceil;", (char)0x2309),//right ceiling\r
+                       new HTMLEscapeTable("lfloor;", (char)0x230A),//left floor = apl downstile\r
+                       new HTMLEscapeTable("rfloor;", (char)0x230B),//right floor\r
+                       new HTMLEscapeTable("lang;", (char)0x2329),//left-pointing angle bracket = bra\r
+                       new HTMLEscapeTable("rang;", (char)0x232A),//right-pointing angle bracket = ket\r
+                       new HTMLEscapeTable("loz;", (char)0x25CA),//lozenge\r
+                       new HTMLEscapeTable("spades;", (char)0x2660),//black spade suit\r
+                       new HTMLEscapeTable("clubs;", (char)0x2663),//black club suit = shamrock\r
+                       new HTMLEscapeTable("hearts;", (char)0x2665),//black heart suit = valentine\r
+                       new HTMLEscapeTable("diams;", (char)0x2666),//black diamond suit\r
+                       new HTMLEscapeTable("ensp;", (char)0x2002),//en space\r
+                       new HTMLEscapeTable("emsp;", (char)0x2003),//em space\r
+                       new HTMLEscapeTable("thinsp;", (char)0x2009),//thin space\r
+                       new HTMLEscapeTable("zwnj;", (char)0x200C),//zero width non-joiner\r
+                       new HTMLEscapeTable("zwj;", (char)0x200D),//zero width joiner\r
+                       new HTMLEscapeTable("lrm;", (char)0x200E),//left-to-right mark\r
+                       new HTMLEscapeTable("rlm;", (char)0x200F),//right-to-left mark\r
+                       new HTMLEscapeTable("ndash;", (char)0x2013),//en dash\r
+                       new HTMLEscapeTable("mdash;", (char)0x2014),//em dash\r
+                       new HTMLEscapeTable("lsquo;", (char)0x2018),//left single quotation mark\r
+                       new HTMLEscapeTable("rsquo;", (char)0x2019),//right single quotation mark\r
+                       new HTMLEscapeTable("sbquo;", (char)0x201A),//single low-9 quotation mark\r
+                       new HTMLEscapeTable("ldquo;", (char)0x201C),//left double quotation mark\r
+                       new HTMLEscapeTable("rdquo;", (char)0x201D),//right double quotation mark\r
+                       new HTMLEscapeTable("bdquo;", (char)0x201E),//double low-9 quotation mark\r
+                       new HTMLEscapeTable("dagger;", (char)0x2020),//dagger\r
+                       new HTMLEscapeTable("Dagger;", (char)0x2021),//double dagger\r
+                       new HTMLEscapeTable("permil;", (char)0x2030),//per mille sign\r
+                       new HTMLEscapeTable("lsaquo;", (char)0x2039),//single left-pointing angle quotation mark\r
+               };\r
+        }// end of class HTMLEscape\r
+\r
+    }\r
+}\r
diff --git a/NT2chView45/NtHtml/NTHtmlWriteResParser.cs b/NT2chView45/NtHtml/NTHtmlWriteResParser.cs
new file mode 100755 (executable)
index 0000000..23f9c4b
--- /dev/null
@@ -0,0 +1,74 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+\r
+namespace NT2chView.NtHtml\r
+{\r
+    public enum X_CONFIRM_RESULT {\r
+        FALSE,\r
+        ERROR,\r
+        CHECK,\r
+        COOKIE,\r
+        SUCCESS,\r
+        NONE\r
+    }\r
+\r
+    sealed class NTHtmlWriteResParser\r
+    {\r
+\r
+        public static X_CONFIRM_RESULT validateResult(NTHtmlParser htmlParser) {\r
+                  \r
+                   List<String> commentList = htmlParser.mCommentList;\r
+                   X_CONFIRM_RESULT id = X_CONFIRM_RESULT.NONE;\r
+                   foreach(String s in commentList){\r
+                           int n = s.IndexOf("2ch_X:");\r
+                           if(n < 0){\r
+                                   continue;\r
+                           }\r
+                           if(0 == s.IndexOf("true", n+6)){\r
+                                   id = X_CONFIRM_RESULT.SUCCESS;\r
+                                   break;\r
+                           }else if(0 == s.IndexOf("false", n+6)){\r
+                                   id = X_CONFIRM_RESULT.FALSE;\r
+                                   break;\r
+                           }else if(0 == s.IndexOf("error", n+6)){\r
+                                   id = X_CONFIRM_RESULT.ERROR;\r
+                                   break;\r
+                           }else if(0 == s.IndexOf("check", n+6)){\r
+                                   id = X_CONFIRM_RESULT.CHECK;\r
+                                   break;\r
+                           }else if(0 == s.IndexOf("cookie", n+6)){\r
+                                   id = X_CONFIRM_RESULT.COOKIE;\r
+                                   break;\r
+                           }   \r
+                   }\r
+               \r
+                   if( X_CONFIRM_RESULT.NONE != id)\r
+                return id;\r
+\r
+\r
+            if(X_CONFIRM_RESULT.NONE == id){\r
+                           String title = htmlParser.getTitle();\r
+                           if(null != title){\r
+                                   if(0 <= title.IndexOf("書きこみました")){\r
+                                           id = X_CONFIRM_RESULT.SUCCESS;\r
+                                   }else if(0 <= title.IndexOf("ERROR")){\r
+                                           id = X_CONFIRM_RESULT.ERROR;\r
+                    }\r
+                    else if (0 <= title.IndexOf("ERROR"))\r
+                    {\r
+                        id = X_CONFIRM_RESULT.ERROR;\r
+                    }\r
+                    else if (0 <= title.IndexOf("お茶でも"))\r
+                    {\r
+                                           id = X_CONFIRM_RESULT.CHECK;\r
+                                   }else if(0 <= title.IndexOf("書き込み確認")){\r
+                                           id = X_CONFIRM_RESULT.COOKIE;       \r
+                                   }\r
+                           }\r
+                   }\r
+            return id;\r
+           }\r
+\r
+    }\r
+}\r
diff --git a/NT2chView45/NtNet/NTCloud.cs b/NT2chView45/NtNet/NTCloud.cs
new file mode 100755 (executable)
index 0000000..3544334
--- /dev/null
@@ -0,0 +1,88 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+\r
+namespace NT2chView.NtNet\r
+{\r
+    sealed class NTCloud\r
+    {\r
+        public const string SERVER_ROOT = "http://neetchan.on.arena.ne.jp/";\r
+        public const string CHECK_USER_URL = SERVER_ROOT + "db6_checkuser.php";\r
+        public const string UPLOAD_FAVORITES_URL = SERVER_ROOT + "db6_up_favorite.php";\r
+        \r
+        public const string UPDATE_ALL_FAVORITE_BOARDS_URL = SERVER_ROOT + "db6_up_all_b_favorite.php";\r
+        //public const string UPDATE_ALL_FAVORITE_THREADS_URL = SERVER_ROOT + "db6_up_all_t_favorite.php";\r
+        public const string UPDATE_ALL_FAVORITE_THREADS2_URL = SERVER_ROOT + "db6_up_all_t_favorite2.php";\r
+        \r
+        public const string DELETE_FAVORITES_BOARD_URL = SERVER_ROOT + "db6_del_b_favorite.php";\r
+        public const string DELETE_FAVORITES_THREAD_URL = SERVER_ROOT + "db6_del_t_favorite.php";\r
+        \r
+        public const string UPLOAD_EXTERNALBOARD_URL = SERVER_ROOT + "db6_up_exboard.php";\r
+        public const string DELETE_EXTERNALBOARD_URL = SERVER_ROOT + "db6_del_exb_favorite.php";\r
+\r
+        public const string UPLOAD_THREAD_HISTORY_LIST_URL = SERVER_ROOT + "db6_up_history_tab.php";\r
+\r
+        public const string UP_NGWORD_URL = SERVER_ROOT + "db6_up_ngword.php";\r
+        public const string UP_NGID_URL = SERVER_ROOT + "db6_up_ngid.php";\r
+        public const string UP_NGNAME_URL = SERVER_ROOT + "db6_up_ngname.php";\r
+        public const string QUERY_READCNT_LIST_URL = SERVER_ROOT + "db6_get_read_cnt_list.php";\r
+        public const string QUERY_READ_HISTORY_URL = SERVER_ROOT + "db6_query_read_history.php";\r
+        public const string UPDATE_ATTR_VALUE_URL = SERVER_ROOT + "db6_update_attr.php";\r
+        public const string DELETE_ATTR_VALUE_URL = SERVER_ROOT + "db6_delete_attr_with_type.php";\r
+        public const string DELETE_DAT_VALUE_URL = SERVER_ROOT + "db6_delete_attr.php";\r
+        public const string QUERY_ATTR_VALUE_URL = SERVER_ROOT + "db6_query_attr.php";\r
+        public const string FAVORITE_BOARD_LIST = "fb.txt";\r
+        public const string FAVORITE_THREAD_LIST = "ft.txt";\r
+        public const string FAVORITE_THREAD_TAG_LIST = "ftab.txt";\r
+        public const string EXTERNAL_BOARD_LIST = "exboard.txt";\r
+        public const string THREAD_HISTORY_LIST = "histab.txt";\r
+        public const string NGID_TXT = "ngid.txt";\r
+        public const string NGNAME_TXT = "ngnm.txt";\r
+        public const string NGWORD_TXT = "ngwd.txt";\r
+\r
+        public const string AES_UPDATE_ALL_FAVORITE_BOARDS_URL = SERVER_ROOT + "db8_up_all_b_favorite.php";\r
+        public const string AES_UPLOAD_FAVORITES_URL = SERVER_ROOT + "db8_up_favorite.php";\r
+        //public const string AES_UPDATE_ALL_FAVORITE_THREADS_URL = SERVER_ROOT + "db8_up_all_t_favorite.php";\r
+        public const string AES_UPDATE_ALL_FAVORITE_THREADS2_URL = SERVER_ROOT + "db8_up_all_t_favorite2.php";\r
+        public const string AES_DELETE_FAVORITES_BOARD_URL = SERVER_ROOT + "db8_del_b_favorite.php";\r
+        public const string AES_DELETE_FAVORITES_THREAD_URL = SERVER_ROOT + "db8_del_t_favorite.php";\r
+        public const string AES_UPLOAD_EXTERNALBOARD_URL = SERVER_ROOT + "db8_up_exboard.php";\r
+        public const string AES_DELETE_EXTERNALBOARD_URL = SERVER_ROOT + "db8_del_exb_favorite.php";\r
+        public const string AES_UPLOAD_THREAD_HISTORY_LIST_URL = SERVER_ROOT + "db8_up_history_tab.php";\r
+        public const string AES_UP_NGWORD_URL = SERVER_ROOT + "db8_up_ngword.php";\r
+        public const string AES_UP_NGID_URL = SERVER_ROOT + "db8_up_ngid.php";\r
+        public const string AES_UP_NGNAME_URL = SERVER_ROOT + "db8_up_ngname.php";\r
+\r
+        public const string AES_QUERY_READCNT_LIST_URL = SERVER_ROOT + "db8_get_read_cnt_list.php";\r
+        public const string AES_QUERY_READ_HISTORY_URL = SERVER_ROOT + "db8_query_read_history.php";\r
+        public const string AES_UPDATE_ATTR_VALUE_URL = SERVER_ROOT + "db8_update_attr.php";\r
+        public const string AES_DELETE_ATTR_VALUE_URL = SERVER_ROOT + "db8_delete_attr_with_type.php";\r
+        public const string AES_DELETE_DAT_VALUE_URL = SERVER_ROOT + "db8_delete_attr.php";\r
+        public const string AES_QUERY_ATTR_VALUE_URL = SERVER_ROOT + "db8_query_attr.php";\r
\r
+\r
+        public const string AES_FAVORITE_BOARD_LIST = "fb02.txt";\r
+        public const string AES_FAVORITE_THREAD_LIST = "ft02.txt";\r
+        public const string AES_FAVORITE_THREAD_TAG_LIST = "ftab02.txt";\r
+        public const string AES_EXTERNAL_BOARD_LIST = "exboard02.txt";\r
+        public const string AES_THREAD_HISTORY_LIST = "histab02.txt";\r
+        public const string AES_NGID_TXT = "ngid02.txt";\r
+        public const string AES_NGNAME_TXT = "ngnm02.txt";\r
+        public const string AES_NGWORD_TXT = "ngwd02.txt";\r
+\r
+        public const string USER_CLOUD_FAVORITE_BOARD_LIST = "fb03.txt";\r
+        public const string USER_CLOUD_FAVORITE_THREAD_LIST = "ft03.txt";\r
+        public const string USER_CLOUD_FAVORITE_THREAD_TAG_LIST = "ftab03.txt";\r
+        public const string USER_CLOUD_EXTERNAL_BOARD_LIST = "exboard03.txt";\r
+        public const string USER_CLOUD_THREAD_HISTORY_LIST = "histab03.txt";\r
+        public const string USER_CLOUD_NGID_TXT = "ngid03.txt";\r
+        public const string USER_CLOUD_NGNAME_TXT = "ngnm03.txt";\r
+        public const string USER_CLOUD_NGWORD_TXT = "ngwd03.txt";\r
+\r
+        public const string HOST_CLOUDSRV_ENCODING = "UTF-8";\r
+\r
+\r
+       \r
+\r
+    }\r
+}\r
diff --git a/NT2chView45/NtNet/NTCookie.cs b/NT2chView45/NtNet/NTCookie.cs
new file mode 100755 (executable)
index 0000000..003e44e
--- /dev/null
@@ -0,0 +1,160 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Net;\r
+using NT2chView.NtFile;\r
+using System.Runtime.Serialization.Formatters.Binary;\r
+using System.IO;\r
+\r
+namespace NT2chView.NtNet\r
+{\r
+    public class NTCookie\r
+    {\r
+        class CookieValue\r
+        {\r
+            public CookieValue(string hostName)\r
+            {\r
+                mHostName = hostName;\r
+            }\r
+            public string mHostName;\r
+            public List<KeyValuePair<string, string>> mKeyValueList = new List<KeyValuePair<string, string>>();\r
+        }\r
+\r
+        CookieValue findCookieValue(string hostName)\r
+        {\r
+            foreach (CookieValue cv in mCookieValue)\r
+            {\r
+                if(hostName.Equals(cv.mHostName))\r
+                    return cv;\r
+            }\r
+            return null;\r
+        }\r
+\r
+        void addCookieValue(CookieValue cv)\r
+        {\r
+            mCookieValue.Add(cv);\r
+        }\r
+\r
+\r
+        List<CookieValue> mCookieValue = new List<CookieValue>();\r
+\r
+        private Uri mHostUri;\r
+        private string mHostName;\r
+        private bool mDomain2ch;\r
+\r
+\r
+        private CookieContainer mContainer;\r
+\r
+        public CookieContainer Container\r
+        {\r
+            get { return mContainer; }\r
+        }\r
+\r
+        public string Host\r
+        {\r
+            set\r
+            {\r
+                mHostName = value;\r
+                mHostUri = new Uri("http://" + value);\r
+                retrieveCookie();\r
+            }\r
+        }\r
+\r
+        public NTCookie(string host) : this(host, true)\r
+        {\r
+#if false\r
+            mHostName = host;\r
+            mHostUri = new Uri("http://"+host);\r
+            mContainer = new CookieContainer();\r
+\r
+            retrieveCookie();\r
+#endif\r
+        }\r
+\r
+        public NTCookie(string host, bool domain2ch)\r
+        {\r
+            mDomain2ch = domain2ch;\r
+            mHostName = host;\r
+            mHostUri = new Uri("http://" + host);\r
+            mContainer = new CookieContainer();\r
+\r
+            retrieveCookie();\r
+        }\r
+\r
+        \r
+        public void saveCookie()\r
+        {\r
+            //string cookie1 = mContainer.GetCookieHeader(mHostUri);\r
+            //string cookie2 = mContainer.GetCookieHeader(new Uri("http://2ch.net"));\r
+            CookieCollection ccol = mContainer.GetCookies(mHostUri);\r
+\r
+            foreach (Cookie cookie in ccol)\r
+            {\r
+                CookieValue cv = null;\r
+                string domain = cookie.Domain;\r
+                if (domain == null)\r
+                    continue;\r
+                cv = findCookieValue(domain);\r
+                if (cv == null)\r
+                {\r
+                    cv = new CookieValue(domain);\r
+                    addCookieValue(cv);\r
+                }\r
+                string key = cookie.Name;\r
+                string value = cookie.Value;\r
+                KeyValuePair<string, string> pair \r
+                    = new KeyValuePair<string, string>(key, value);\r
+                cv.mKeyValueList.Add(pair);\r
+            }\r
+            \r
+            \r
+            foreach (CookieValue cv in mCookieValue)\r
+            {\r
+                NTFileAccess.saveCookie(cv.mKeyValueList, cv.mHostName);\r
+            }\r
+\r
+        }\r
+\r
+        void retrieveCookie()\r
+        {\r
+            \r
+            List<KeyValuePair<string, string>> rootList = NTFileAccess.retrieveCookie(".2ch.net");\r
+            List<KeyValuePair<string, string>> list = NTFileAccess.retrieveCookie(mHostName);\r
+            \r
+            if(mDomain2ch)\r
+                list.AddRange(rootList);\r
+\r
+            if (list.Count > 0)\r
+            {\r
+                string cookieHeader = constructCookieHeader(list);\r
+                mContainer.SetCookies(mHostUri, cookieHeader);\r
+            }\r
+\r
+        }\r
+\r
\r
+        string constructCookieHeader(List<KeyValuePair<string, string>> list)\r
+        {\r
+            NTDebug.l(" *** Entering constructCookieHeader *** ");\r
+            StringBuilder result = new StringBuilder();\r
+            result.Append(" ");\r
+            int i = 0;\r
+            for(; i < list.Count; i++)\r
+            {\r
+                if (0 < i)\r
+                {\r
+                    //result.Append("; ");\r
+                    result.Append(",");\r
+                }\r
+                KeyValuePair<string, string> pair = list[i];\r
+                NTDebug.l("\t "+pair.Key+" : "+pair.Value);\r
+                result.Append(pair.Key).Append("=").Append(pair.Value);\r
+            }\r
+            return (i == 0) ? null : result.ToString();\r
+\r
+        }\r
+\r
+\r
+\r
+    }\r
+}\r
diff --git a/NT2chView45/NtNet/NTCrypt.cs b/NT2chView45/NtNet/NTCrypt.cs
new file mode 100755 (executable)
index 0000000..38bef64
--- /dev/null
@@ -0,0 +1,235 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.IO;\r
+using System.Security.Cryptography;\r
+using System.Text;\r
+\r
+namespace NT2chView.NtNet\r
+{\r
+    class NTCrypt\r
+    {\r
+        //static string mPassword;\r
+        //public static string getPassword()\r
+        //{\r
+        //    return mPassword;\r
+        //}\r
+\r
+        public static string getSHA256Hashed(string src)\r
+        {\r
+            byte[] byteValue = Encoding.UTF8.GetBytes(src);\r
+\r
+            SHA256 shaM = new SHA256Managed();\r
+            byte[] hashValue = shaM.ComputeHash(byteValue);\r
+\r
+            StringBuilder sb = new StringBuilder();\r
+            for (int i = 0; i < hashValue.Length; i++)\r
+            {\r
+                sb.AppendFormat("{0:X2}", hashValue[i]);\r
+            }\r
+            return sb.ToString();\r
+        }\r
+        public static void setPassword(string pass)\r
+        {\r
+            //mPassword = pass;\r
+            KeyAndIV.setPass(pass);\r
+        }\r
+        class KeyAndIV\r
+        {\r
+            byte[] mIV = null;\r
+            byte[] mKEY = null;\r
+            //const string IV = "1234567890123456"; //ascii 16btes (128bit)\r
+            //const string KEY = "12345678901234567890123456789012";//ascii 32bytes (256bit)\r
+            const string SALT = "abcdefghijklmn";\r
+            static KeyAndIV mThis = null;\r
+            //static string mPasswd = string.Empty;//"あいうえお";\r
+\r
+            public static void setPass(string pass)\r
+            {\r
+                mThis = new KeyAndIV(pass);\r
+            }\r
+\r
+            public static byte[] getIV()\r
+            {\r
+                //if (mThis == null)\r
+                //    mThis = new KeyAndIV();\r
+                return mThis.mIV;\r
+                /*if (mIV != null)\r
+                    return mIV;\r
+\r
+                Encoding enc = new UTF8Encoding();\r
+                mIV = enc.GetBytes(IV);\r
+                return mIV;*/\r
+            }\r
+            public static byte[] getKEY()\r
+            {\r
+               return mThis.mKEY;\r
+                /*if (mKEY != null)\r
+                    return mKEY;\r
+\r
+                Encoding enc = new UTF8Encoding();\r
+                mKEY = enc.GetBytes(KEY);\r
+                return mKEY;*/\r
+            }\r
+\r
+            KeyAndIV(string passwd)\r
+            {\r
+                //byte[] bPass = new UTF8Encoding(false).GetBytes(passwd);\r
+                byte[] bPass = System.Text.Encoding.UTF8.GetBytes(passwd);\r
+                byte[] salt = System.Text.Encoding.UTF8.GetBytes(SALT);\r
+                //Rfc2898DeriveBytesオブジェクトを作成する\r
+                System.Security.Cryptography.Rfc2898DeriveBytes deriveBytes =\r
+                    new System.Security.Cryptography.Rfc2898DeriveBytes(bPass, salt, 1000);\r
+                //.NET Framework 1.1以下の時は、PasswordDeriveBytesを使用する\r
+                //System.Security.Cryptography.PasswordDeriveBytes deriveBytes =\r
+                //    new System.Security.Cryptography.PasswordDeriveBytes(password, salt);\r
+                //反復処理回数を指定する デフォルトで1000回\r
+                //deriveBytes.IterationCount = 1000;\r
+\r
+                //共有キーと初期化ベクタを生成する\r
+                mKEY = deriveBytes.GetBytes(256 / 8);\r
+                mIV = deriveBytes.GetBytes(128 / 8);\r
+            }\r
+\r
+        }\r
+\r
+        /// <summary>\r
+        /// ファイルを暗号化する\r
+        /// </summary>\r
+        /// <param name="sourceFile">暗号化するファイルパス</param>\r
+        /// <param name="destFile">暗号化されたデータを保存するファイルパス</param>\r
+        /// <param name="key">暗号化に使用した共有キー</param>\r
+        /// <param name="iv">暗号化に使用した初期化ベクタ</param>\r
+        public static bool EncryptStream(Stream inStream, out MemoryStream outStream)\r
+        {\r
+            bool bRet = false;\r
+            outStream = null;\r
+            try\r
+            {\r
+                //RijndaelManagedオブジェクトを作成\r
+                System.Security.Cryptography.RijndaelManaged rijndael =\r
+                    new System.Security.Cryptography.RijndaelManaged();\r
+\r
+                //設定を変更するときは、変更する\r
+                rijndael.KeySize = 256;\r
+                rijndael.BlockSize = 128;\r
+                rijndael.FeedbackSize = 128;\r
+                rijndael.Mode = System.Security.Cryptography.CipherMode.CBC;\r
+                rijndael.Padding = System.Security.Cryptography.PaddingMode.PKCS7;\r
+\r
+                //共有キーと初期化ベクタを作成\r
+                //Key、IVプロパティがnullの時に呼びだすと、自動的に作成される\r
+                //自分で作成するときは、GenerateKey、GenerateIVメソッドを使う\r
+                //key = rijndael.Key;\r
+                //iv = rijndael.IV;\r
+                rijndael.Key = KeyAndIV.getKEY();\r
+                rijndael.IV = KeyAndIV.getIV();\r
+\r
+                //string destFile = @"G:\Users\Akira\workspace\WPF Pro\NT2chView\NT2chView\bin\Debug\Data\favorite_test.txt";\r
+                //暗号化されたファイルを書き出すためのFileStream\r
+                //System.IO.FileStream outFs = new System.IO.FileStream(\r
+                //    destFile, System.IO.FileMode.Create, System.IO.FileAccess.Write);\r
+                outStream = new MemoryStream();\r
+                //outStream.Write(BitConverter.GetBytes(rijndael.IV.Length), 0, sizeof(int));\r
+                //outStream.Write(rijndael.IV, 0, rijndael.IV.Length);\r
+\r
+                //対称暗号化オブジェクトの作成\r
+                System.Security.Cryptography.ICryptoTransform encryptor =\r
+                    rijndael.CreateEncryptor();\r
+                //暗号化されたデータを書き出すためのCryptoStreamの作成\r
+                System.Security.Cryptography.CryptoStream cryptStrm =\r
+                    new System.Security.Cryptography.CryptoStream(\r
+                        outStream, encryptor,\r
+                        System.Security.Cryptography.CryptoStreamMode.Write);\r
+\r
+                //暗号化されたデータを書き出す\r
+                //System.IO.FileStream inFs = new System.IO.FileStream(\r
+                //    sourceFile, System.IO.FileMode.Open, System.IO.FileAccess.Read);\r
+                byte[] bs = new byte[16];\r
+                int readLen;\r
+                while ((readLen = inStream.Read(bs, 0, bs.Length)) > 0)\r
+                {\r
+                    cryptStrm.Write(bs, 0, readLen);\r
+                }\r
+\r
+                //閉じる\r
+                //inFs.Close();\r
+                //cryptStrm.Flush();\r
+                cryptStrm.Close();\r
+                encryptor.Dispose();\r
+                //outFs.Close();\r
+                bRet = true;\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+            return bRet;\r
+        }\r
+\r
+        /// <summary>\r
+        /// ファイルを復号化する\r
+        /// </summary>\r
+        /// <param name="sourceFile">復号化するファイルパス</param>\r
+        /// <param name="destFile">復号化されたデータを保存するファイルパス</param>\r
+        /// <param name="key">暗号化に使用した共有キー</param>\r
+        /// <param name="iv">暗号化に使用した初期化ベクタ</param>\r
+        public static bool DecryptStream(Stream inStream, out MemoryStream outStream)\r
+        //            string sourceFile, string destFile, byte[] key, byte[] iv)\r
+        {\r
+            bool bRet = false;\r
+            outStream = null;\r
+            try\r
+            {\r
+                //RijndaelManagedオブジェクトの作成\r
+                System.Security.Cryptography.RijndaelManaged rijndael =\r
+                    new System.Security.Cryptography.RijndaelManaged();\r
+\r
+                rijndael.KeySize = 256;\r
+                rijndael.BlockSize = 128;\r
+                rijndael.FeedbackSize = 128;\r
+                rijndael.Mode = System.Security.Cryptography.CipherMode.CBC;\r
+                rijndael.Padding = System.Security.Cryptography.PaddingMode.PKCS7;\r
+                //共有キーと初期化ベクタを設定\r
+                rijndael.Key = KeyAndIV.getKEY();// key;\r
+                rijndael.IV = KeyAndIV.getIV();// iv;\r
+\r
+                //暗号化されたファイルを読み込むためのFileStream\r
+                //System.IO.FileStream inFs = new System.IO.FileStream(\r
+                //    sourceFile, System.IO.FileMode.Open, System.IO.FileAccess.Read);\r
+                //対称復号化オブジェクトの作成\r
+                System.Security.Cryptography.ICryptoTransform decryptor =\r
+                    rijndael.CreateDecryptor(rijndael.Key, rijndael.IV);\r
+                //暗号化されたデータを読み込むためのCryptoStreamの作成\r
+                System.Security.Cryptography.CryptoStream cryptStrm =\r
+                    new System.Security.Cryptography.CryptoStream(\r
+                        inStream, decryptor,\r
+                        System.Security.Cryptography.CryptoStreamMode.Read);\r
+\r
+                //復号化されたデータを書き出す\r
+                //System.IO.FileStream outFs = new System.IO.FileStream(\r
+                //    destFile, System.IO.FileMode.Create, System.IO.FileAccess.Write);\r
+                outStream = new MemoryStream();\r
+\r
+                byte[] bs = new byte[1024];\r
+                int readLen;\r
+                //復号化に失敗すると例外CryptographicExceptionが発生\r
+                while ((readLen = cryptStrm.Read(bs, 0, bs.Length)) > 0)\r
+                {\r
+                    outStream.Write(bs, 0, readLen);\r
+                }\r
+\r
+                //閉じる\r
+                //outFs.Close();\r
+                cryptStrm.Close();\r
+                decryptor.Dispose();\r
+                bRet = true;\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+            //inFs.Close();\r
+            return bRet;\r
+        }\r
+    }\r
+}\r
diff --git a/NT2chView45/NtNet/NTHttpAccess.cs b/NT2chView45/NtNet/NTHttpAccess.cs
new file mode 100755 (executable)
index 0000000..98577e2
--- /dev/null
@@ -0,0 +1,1463 @@
+using System;\r
+using System.Net;\r
+using System.IO;\r
+using NT2chView.NtFile;\r
+using System.Text;\r
+using System.Web;\r
+using System.Collections.Generic;\r
+using NT2chView.NtHtml;\r
+using System.Windows.Documents;\r
+\r
+namespace NT2chView.NtNet\r
+{\r
+    public sealed partial class NTHttpAccess\r
+    {\r
+        private static string [] ignoreKey = {\r
+                        "bbs","key","time","FROM","mail","MESSAGE","submit"\r
+        };\r
+\r
+        const string SUBJECT_TXT = "subject.txt";\r
+\r
+        public static string getExternalBoardSubject(string url , string filePath)\r
+        {\r
+            string address;\r
+            if (url == null || url.Length == 0)\r
+                return null;\r
+\r
+            if ('/' != url[url.Length - 1])\r
+                address = url + '/' + SUBJECT_TXT;\r
+            else\r
+                address = url + SUBJECT_TXT;\r
+\r
+\r
+            string resultStr = null;\r
+            Stream stream = null;\r
+            HttpWebResponse httpResp = null;\r
+            NTHttpGetClient httpClient = new NTHttpGetClient(address);\r
\r
+            try\r
+            {\r
+                httpResp = httpClient.execute();\r
+\r
+                NTDebug.l(httpResp.StatusCode.ToString());\r
+\r
+                //WebHeaderCollection headers = httpResp.Headers;\r
+                //if ((ifMod = headers.Get("Last-Modified")) != null)\r
+                //    NTFileAccess.storeBoardMenuAttrToFile(ifMod);\r
+\r
+                stream = httpResp.GetResponseStream();\r
+\r
+                Encoding enc = Encoding.GetEncoding(NTAppState.HOST_2CH_ENCODING);\r
+\r
+                StreamReader sr = new StreamReader(stream, enc);\r
+\r
+                resultStr = sr.ReadToEnd();\r
+                // NTFileAccess.storeBoardMenuDataToFile(stream);\r
+                // bRet = true;\r
+\r
+            }\r
+            catch (System.Net.WebException e)\r
+            {\r
+                /*if (e.Status == System.Net.WebExceptionStatus.ProtocolError)\r
+                {\r
+                    HttpWebResponse errres = (HttpWebResponse)e.Response;\r
+                    if (errres.StatusCode == HttpStatusCode.NotModified)\r
+                    {\r
+                        bRet = true;\r
+                    }\r
+                    else\r
+                    {\r
+                        NTDebug.l(e.Message);\r
+                    }\r
+                }\r
+                else\r
+                {\r
+                    NTDebug.l(e.Message);\r
+                }*/\r
+                NTDebug.l(e.Message);\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+            finally\r
+            {\r
+                if (null != stream)\r
+                    stream.Close();\r
+                if (null != httpResp)\r
+                    httpResp.Close();\r
+            }\r
+\r
+            return resultStr;\r
+        }\r
+\r
+        public static string getWriteHtmlExternalBBS(string host, string url)\r
+        {\r
+            string resultStr = null;\r
+            Stream stream = null;\r
+            HttpWebResponse httpResp = null;\r
+            NTHttpGetClient httpClient = new NTHttpGetClient(url);\r
+\r
+            try\r
+            {\r
+                NTCookie cookie = new NTCookie(host, false);\r
+\r
+                httpClient.mHttpReq.CookieContainer = cookie.Container;\r
+\r
+                httpResp = httpClient.execute();\r
+\r
+                NTDebug.l(httpResp.StatusCode.ToString());\r
+\r
+                cookie.saveCookie();\r
+\r
+                stream = httpResp.GetResponseStream();\r
+\r
+                string strCharSet = httpResp.CharacterSet;\r
+\r
+                Encoding enc;\r
+                if(strCharSet.Equals("utf-8", StringComparison.CurrentCultureIgnoreCase))\r
+                    enc = Encoding.GetEncoding("UTF-8");\r
+                else\r
+                    enc = Encoding.GetEncoding(NTAppState.HOST_2CH_ENCODING);\r
+\r
+                StreamReader sr = new StreamReader(stream, enc);\r
+\r
+                resultStr = sr.ReadToEnd();\r
+\r
+            }\r
+            catch (System.Net.WebException e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+            finally\r
+            {\r
+                if (null != stream)\r
+                    stream.Close();\r
+                if (null != httpResp)\r
+                    httpResp.Close();\r
+            }\r
+\r
+            return resultStr;\r
+        }\r
+\r
+\r
+        public static String writeResExternalBBS(string url, string refferer, string host, string postData)\r
+        {\r
+            return BasicHttpPost( url,  refferer,  host,  postData, false);\r
+        }\r
+\r
+\r
+        //static CookieContainer mTempCookie = new CookieContainer();\r
+\r
+\r
+        public static String writeRes(string[] args, List<KeyValuePair<string, string>> extra)\r
+        {\r
+            if (args.Length < 7)\r
+                return null;\r
+\r
+\r
+            string host = args[0];\r
+            string board = args[1];\r
+            string dat = args[2];\r
+            string from = args[3];\r
+            string mail = args[4];\r
+            string msg = args[5];\r
+            string submit = args[6];        \r
+               \r
+                   String result = null;\r
+               \r
+            String postAddress = NTHttpUtils.HTTP_PROTOCOL + host + NTHttpUtils.HTTP_WRITE_CGI_PATH;\r
+            String refAddress = postAddress + NTHttpUtils.HTTP_SLASH + \r
+                        board + NTHttpUtils.HTTP_SLASH + dat + NTHttpUtils.HTTP_SLASH;\r
+            \r
+                   NTHttpPostClient client = null;\r
+  \r
+               \r
+           try{\r
+                           client = new NTHttpPostClient(postAddress , refAddress ,  host);\r
+\r
+                NTCookie cookie = new NTCookie(host);\r
+\r
+                //cookie.saveCookie();\r
+\r
+\r
+                client.mHttpReq.CookieContainer = cookie.Container;\r
+\r
+                Encoding enc = Encoding.GetEncoding(NTAppState.HOST_2CH_ENCODING);\r
+                TimeSpan ts = new TimeSpan(0,10,0);\r
+                int time = NTHttpUtils.GetTime(DateTime.Now.Subtract(ts));\r
+\r
+                StringBuilder postData = \r
+                    new StringBuilder(256).Append("bbs=").Append(board).\r
+                    Append("&key=").Append(dat).\r
+                    Append("&time=").Append(time). //1230144297\r
+                    Append("&FROM=").Append(HttpUtility.UrlEncode(from, enc)). // . %96%BC%96%B3%82%B5" +\r
+                    Append("&mail=").Append(mail).\r
+                    Append("&MESSAGE=").Append(HttpUtility.UrlEncode(msg, enc)). //%82%C4%82%B7%82%C6&submit=%8F%91%82%AB%8D%9E%82%DE";\r
+                    Append("&submit=").Append(HttpUtility.UrlEncode(submit, enc));\r
+                //"&yuki=akari";\r
+\r
+                //postData.Append("&yuki=").Append("akari");\r
+\r
+                if (extra != null)\r
+                {\r
+                    //postData.Remove(0, postData.Length);\r
+                    foreach (KeyValuePair<string, string> pair in extra)\r
+                    {\r
+                        bool ignore = false;\r
+                        foreach (string iKey in ignoreKey)\r
+                        {\r
+                            if (pair.Key.Equals(iKey))\r
+                            {\r
+                                ignore = true;\r
+                                break;\r
+                            }\r
+                        }\r
+                    \r
+                        if (!ignore)\r
+                        {\r
+                        //if(postData.Length > 0)\r
+                            postData.Append("&").Append(pair.Key).Append("=").Append(pair.Value);\r
+                        //else\r
+                        //    postData.Append(pair.Key).Append("=").Append(pair.Value);\r
+\r
+                        }\r
+                    }\r
+                 }\r
+\r
+                if (NTUserPreference.MaruIsEnabled)\r
+                {\r
+                    string sessionId = NTMaru.getSessionId();\r
+                    if (sessionId.Length > 0)\r
+                    {\r
+                        //postData.Append("&sid=").Append(HttpUtility.UrlEncode(sessionId, enc));\r
+                        postData.Append("&sid=").Append(sessionId);\r
+                    }\r
+                }\r
+\r
+                byte[] data = System.Text.Encoding.ASCII.GetBytes(postData.ToString());\r
+                client.setPostData(data);\r
+               \r
+                   HttpWebResponse httpResp = client.execute();\r
+            \r
+                NTDebug.l(httpResp.StatusCode.ToString());\r
+\r
+#if false\r
+                foreach (Cookie cook in httpResp.Cookies)\r
+                {\r
+                    Console.WriteLine("Cookie:");\r
+                    Console.WriteLine("{0} = {1}", cook.Name, cook.Value);\r
+                    Console.WriteLine("Domain: {0}", cook.Domain);\r
+                    Console.WriteLine("Path: {0}", cook.Path);\r
+                    Console.WriteLine("Port: {0}", cook.Port);\r
+                    Console.WriteLine("Secure: {0}", cook.Secure);\r
+\r
+                    Console.WriteLine("When issued: {0}", cook.TimeStamp);\r
+                    Console.WriteLine("Expires: {0} (expired? {1})",\r
+                        cook.Expires, cook.Expired);\r
+                    Console.WriteLine("Don't save: {0}", cook.Discard);\r
+                    Console.WriteLine("Comment: {0}", cook.Comment);\r
+                    Console.WriteLine("Uri for comments: {0}", cook.CommentUri);\r
+                    Console.WriteLine("Version: RFC {0}", cook.Version == 1 ? "2109" : "2965");\r
+\r
+                    // Show the string representation of the cookie.\r
+                    Console.WriteLine("String: {0}", cook.ToString());\r
+                }\r
+#endif\r
+\r
+                cookie.saveCookie();\r
+\r
+                Stream stream = httpResp.GetResponseStream();\r
+                //Encoding enc = Encoding.GetEncoding(NTAppState.HOST_2CH_ENCODING);\r
+                            \r
+                StreamReader sr = new StreamReader(stream, enc);\r
+\r
+                result = sr.ReadToEnd();\r
+\r
+            } catch (Exception e) {\r
+                NTDebug.l(e.Message);\r
+                   }finally{\r
+                   }\r
+                   return result;      \r
+           }\r
+       \r
+\r
+\r
+        public static bool getBoardMenu()\r
+        {\r
+            bool bRet = false;\r
+            Stream stream = null;\r
+            HttpWebResponse httpResp = null;\r
+            NTHttpGetClient httpClient = new NTHttpGetClient(URL_2CH_BOARDMENU);\r
+            httpClient.AcceptGZip = true;\r
\r
+            try\r
+            {\r
+                string ifMod = NTFileAccess.retrieveBoardMenuAttrFromFile();\r
+                if (null != ifMod)\r
+                    httpClient.ModifiedSince = ifMod;\r
+            \r
+                httpResp = httpClient.execute();\r
+\r
+                NTDebug.l(httpResp.StatusCode.ToString());\r
+\r
+                WebHeaderCollection headers = httpResp.Headers;\r
+                if((ifMod = headers.Get("Last-Modified")) != null)\r
+                    NTFileAccess.storeBoardMenuAttrToFile(ifMod);\r
+\r
+                stream = httpResp.GetResponseStream();\r
+                NTFileAccess.storeBoardMenuDataToFile(stream);\r
+                bRet = true;\r
+           \r
+             }\r
+            catch (System.Net.WebException e)\r
+            {\r
+                if (e.Status == System.Net.WebExceptionStatus.ProtocolError)\r
+                {\r
+                    HttpWebResponse errres = (HttpWebResponse)e.Response;\r
+                    if (errres.StatusCode == HttpStatusCode.NotModified)\r
+                    {\r
+                        bRet = true;\r
+                    }\r
+                    else\r
+                    {\r
+                        NTDebug.l(e.Message);\r
+                    }\r
+                }\r
+                else\r
+                {\r
+                    NTDebug.l(e.Message);\r
+                }\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+            finally\r
+            {\r
+                if (null != stream)\r
+                    stream.Close();\r
+                if (null != httpResp)\r
+                    httpResp.Close();\r
+            }\r
+\r
+            return bRet;\r
+        }\r
+\r
+\r
+\r
+        public static bool getSubject(string address, string boardName)\r
+        {\r
+            bool bRet = false;\r
+            Stream stream = null;\r
+            HttpWebResponse httpResp = null;\r
+            NTHttpGetClient httpClient = new NTHttpGetClient(address+"subject.txt");\r
+            httpClient.AcceptGZip = true;\r
+\r
+            try\r
+            {\r
+                string ifMod = NTFileAccess.retrieveSubjectAttrFromFile(boardName);\r
+                if (null != ifMod)\r
+                    httpClient.ModifiedSince = ifMod;\r
+\r
+                httpResp = httpClient.execute();\r
+\r
+                NTDebug.l(httpResp.StatusCode.ToString());\r
+\r
+                WebHeaderCollection headers = httpResp.Headers;\r
+                if ((ifMod = headers.Get("Last-Modified")) != null)\r
+                    NTFileAccess.storeSubjectAttrToFile(ifMod, boardName);\r
+\r
+                stream = httpResp.GetResponseStream();\r
+                bRet = NTFileAccess.storeSubjectDataToFile(stream, boardName);\r
+            }\r
+            catch (System.Net.WebException e)\r
+            {\r
+                if (e.Status == System.Net.WebExceptionStatus.ProtocolError)\r
+                {\r
+                    HttpWebResponse errres = (HttpWebResponse)e.Response;\r
+                    if (errres.StatusCode == HttpStatusCode.NotModified)\r
+                    {\r
+                        bRet = true;\r
+                    }\r
+                    else\r
+                    {\r
+                        NTDebug.l(e.Message);\r
+                    }\r
+                }\r
+                else\r
+                {\r
+                    NTDebug.l(e.Message);\r
+                }\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+            finally\r
+            {\r
+                if (null != stream)\r
+                    stream.Close();\r
+                if (null != httpResp)\r
+                    httpResp.Close();\r
+            }\r
+            return bRet;\r
+        }\r
+\r
+\r
+\r
+        public static bool getDat(string address, string boardName, string datName, string title)\r
+        {\r
+            bool bRet = false;\r
+            Stream stream = null;\r
+            HttpWebResponse httpResp = null;\r
+            NTHttpGetClient httpClient = new NTHttpGetClient(address + "dat/" + datName);\r
+            \r
+            try\r
+            {\r
+                string ifMod;\r
+                long fileSize = 0;\r
+\r
+                string[] attr = NTFileAccess.retrieveDatAttrBinFromFile(boardName, datName);\r
+                \r
+                if (null != attr)\r
+                {\r
+                    httpClient.ModifiedSince = attr[1];\r
+                    try\r
+                    {\r
+                        fileSize = long.Parse(attr[2]);\r
+                    }\r
+                    catch\r
+                    {\r
+                    }\r
+                    if (fileSize <= 0)\r
+                    {\r
+                        httpClient.AcceptGZip = true;\r
+                    }\r
+                    else\r
+                    {\r
+                        httpClient.Range = (int)fileSize;\r
+                    }\r
+                }\r
+\r
+                httpResp = httpClient.execute();\r
+\r
+                NTDebug.l(httpResp.StatusCode.ToString());\r
+\r
+                WebHeaderCollection headers = httpResp.Headers;\r
+                ifMod = headers.Get("Last-Modified");\r
+                    \r
+                stream = httpResp.GetResponseStream();\r
+\r
+                //int n = datName.IndexOf(".dat");\r
+                //if (n >= 0)\r
+                //    datName = datName.Substring(0, n);\r
+                datName = NTFileAccess.ridSuffixFromDatName(datName);\r
+\r
+                bRet = NTFileAccess.storeDatToFile(stream, boardName, datName, title, \r
+                    ifMod, (httpResp.StatusCode == HttpStatusCode.PartialContent));\r
+\r
+            }\r
+            catch (System.Net.WebException e)\r
+            {\r
+                if (e.Status == System.Net.WebExceptionStatus.ProtocolError)\r
+                {\r
+                    HttpWebResponse errres = (HttpWebResponse)e.Response;\r
+                    if (errres.StatusCode == HttpStatusCode.NotModified)\r
+                    {\r
+                        bRet = true;\r
+                    }\r
+                    else\r
+                    {\r
+                        NTDebug.l(e.Message);\r
+                    }\r
+                }\r
+                else\r
+                {\r
+                    NTDebug.l(e.Message);\r
+                }\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+            finally\r
+            {\r
+                if (null != stream)\r
+                    stream.Close();\r
+                if (null != httpResp)\r
+                    httpResp.Close();\r
+            }\r
+\r
+            return bRet;\r
+        }\r
+\r
+        public static bool getDatFromKako(string address, string boardName, string datName, \r
+            string title, string sid)\r
+        {\r
+            if (title == null)\r
+                title = string.Empty;\r
+            int idx = title.IndexOf(NTHttpUtils.LOCAL_DAT_TITEL_PREFIX);\r
+            if (idx >= 0)\r
+            {\r
+                idx += NTHttpUtils.LOCAL_DAT_TITEL_PREFIX.Length;\r
+                title = title.Substring(idx).Trim();\r
+            }\r
+\r
+            bool bRet = false;\r
+            Stream stream = null;\r
+            HttpWebResponse httpResp = null;\r
+\r
+            string host, board, dat;\r
+\r
+            dat = NTHttpUtils.ridSuffixFromDatName(datName);\r
+            if (!NTHttpUtils.parseHostAddress(address, out host, out board))\r
+                return false;\r
+\r
+            string url = NTHttpUtils.HTTP_PROTOCOL + host \r
+                + "/test/offlaw.cgi/" + board + "/" + dat + "/?raw=0.0&sid=" + sid;\r
+\r
+            NTHttpGetClient httpClient = new NTHttpGetClient(url);\r
+\r
+            try\r
+            {\r
+                string ifMod;\r
+                //long fileSize = 0;\r
+\r
+                string[] attr = NTFileAccess.retrieveDatAttrBinFromFile(boardName, datName);\r
+\r
+                if (null != attr && attr.Length > 1)\r
+                {\r
+                    httpClient.ModifiedSince = attr[1];\r
+                }\r
+                httpClient.AcceptGZip = true;\r
+             \r
+                httpResp = httpClient.execute();\r
+\r
+                NTDebug.l(httpResp.StatusCode.ToString());\r
+\r
+                WebHeaderCollection headers = httpResp.Headers;\r
+                ifMod = headers.Get("Last-Modified");\r
+\r
+                stream = httpResp.GetResponseStream();\r
+\r
+                //int n = datName.IndexOf(".dat");\r
+                //if (n >= 0)\r
+                //    datName = datName.Substring(0, n);\r
+                bRet = NTFileAccess.storeDatToFile(stream, boardName, dat, title,\r
+                    ifMod, false);\r
+\r
+            }\r
+            catch (System.Net.WebException e)\r
+            {\r
+                if (e.Status == System.Net.WebExceptionStatus.ProtocolError)\r
+                {\r
+                    HttpWebResponse errres = (HttpWebResponse)e.Response;\r
+                    if (errres.StatusCode == HttpStatusCode.NotModified)\r
+                    {\r
+                        bRet = true;\r
+                    }\r
+                    else\r
+                    {\r
+                        NTDebug.l(e.Message);\r
+                    }\r
+                }\r
+                else\r
+                {\r
+                    NTDebug.l(e.Message);\r
+                }\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+            finally\r
+            {\r
+                if (null != stream)\r
+                    stream.Close();\r
+                if (null != httpResp)\r
+                    httpResp.Close();\r
+            }\r
+\r
+            return bRet;\r
+        }\r
+\r
+\r
+\r
+        static bool mP2LogedIn = false;\r
+        static string P2HostName = null;\r
+        static string P2LoginDir = null;\r
+        static string P2PostDir = null;\r
+        //static NTCookie mCookie = null;\r
+        static CookieContainer mCookie = null;\r
+        static string host;\r
+        static string board;\r
+        static string dat;\r
+        static string from;\r
+        static string mail;\r
+        static string msg;\r
+        static string submit;\r
+        static Encoding enc;\r
+        static string title;\r
+\r
+\r
+\r
+        static  bool writeResP2Login(out HttpStatusCode resultCode)\r
+        {\r
+            string resultHtml;\r
+            resultCode = HttpStatusCode.NotFound;\r
+\r
+            try\r
+            {\r
+                string urlAddress = "http://" + P2HostName + P2LoginDir;\r
+                //getClient;//request;// = new HttpGet("http://p2.2ch.net/p2/?k=1");\r
+\r
+                NTHttpGetClient getClient = new NTHttpGetClient(urlAddress);\r
+                getClient.mHttpReq.CookieContainer = mCookie;// mCookie.Container;\r
+\r
+                HttpWebResponse httpResp = getClient.execute();\r
+\r
+                if (httpResp.StatusCode != HttpStatusCode.OK)\r
+                    return false;\r
+\r
+                //mCookie.saveCookie();\r
+\r
+                Stream stream = httpResp.GetResponseStream();\r
+\r
+                StreamReader sr = new StreamReader(stream, enc);\r
+\r
+                resultHtml = sr.ReadToEnd();\r
+\r
+                httpResp.Close();\r
+\r
+                NTHtmlParser htmlParser = new NTHtmlParser(new FlowDocument());\r
+                string resultHtml2 = htmlParser.parse(resultHtml);\r
+\r
+                NTDebug.l(resultHtml2);\r
+\r
+                StringBuilder postData = new StringBuilder(256);\r
+\r
+                foreach (KeyValuePair<string, string> pair in htmlParser.mInputTypeHidden)\r
+                {\r
+                    if (0 < postData.Length)\r
+                        postData.Append("&");\r
+\r
+                    postData.Append(pair.Key).Append("=").Append(pair.Value);\r
+                }\r
+                foreach (KeyValuePair<string, string> pair in htmlParser.mInputTypeSubmit)\r
+                {\r
+                    if (0 < postData.Length)\r
+                        postData.Append("&");\r
+\r
+                    postData.Append(pair.Key).Append("=").Append(pair.Value);\r
+                    break;\r
+                }\r
+\r
+                foreach (KeyValuePair<string, string> pair in htmlParser.mInputTypeCheckBox)\r
+                {\r
+                    if (0 < postData.Length)\r
+                        postData.Append("&");\r
+\r
+                    postData.Append(pair.Key).Append("=").Append(pair.Value);\r
+                }\r
+\r
+                foreach (KeyValuePair<string, string> pair in htmlParser.mInputTypeText)\r
+                {\r
+                    if (0 < postData.Length)\r
+                        postData.Append("&");\r
+\r
+                    string p2id = NTUserPreference.P2ID;\r
+                    postData.Append(pair.Key).Append("=").Append(p2id);\r
+                    break;\r
+                }\r
+\r
+                foreach (KeyValuePair<string, string> pair in htmlParser.mInputTypePasswd)\r
+                {\r
+                    if (0 < postData.Length)\r
+                        postData.Append("&");\r
+\r
+                    string p2pass = NTUserPreference.P2PSS;\r
+                    postData.Append(pair.Key).Append("=").Append(p2pass);\r
+                    break;\r
+                }\r
+\r
+                string action = null;\r
+                foreach (KeyValuePair<string, string> pair in htmlParser.mFormAttributes)\r
+                {\r
+                    if (pair.Key.Equals("action"))\r
+                    {\r
+                        action = pair.Value;\r
+                        break;\r
+                    }\r
+                }\r
+                string prevUrl = urlAddress;\r
+                if (null != action)\r
+                    urlAddress = "http://" + P2HostName + action;\r
+\r
+\r
+                byte[] data = System.Text.Encoding.ASCII.GetBytes(postData.ToString());\r
+\r
+                NTHttpPostClient postClient = new NTHttpPostClient(urlAddress, prevUrl, "http://" + P2HostName);\r
+                postClient.mHttpReq.CookieContainer = mCookie;// mCookie.Container;\r
+                postClient.setPostData(data);\r
+\r
+                httpResp = postClient.execute();\r
+\r
+                resultCode = httpResp.StatusCode;\r
+\r
+                switch (httpResp.StatusCode)\r
+                {\r
+                    case HttpStatusCode.OK:\r
+                        return true;\r
+                    case HttpStatusCode.Redirect:\r
+                        break;\r
+                    default:\r
+                        return false;\r
+                }\r
+\r
+\r
+                WebHeaderCollection headers = httpResp.Headers;\r
+                string newLocation = headers["Location"];\r
+                httpResp.Close();\r
+\r
+                if (null == newLocation)\r
+                    return false;\r
+\r
+                prevUrl = urlAddress;\r
+\r
+                int n1 = newLocation.IndexOf('&');\r
+                if (0 <= n1)\r
+                {\r
+                    newLocation = newLocation.Substring(0, n1);\r
+                }\r
+                n1 = newLocation.IndexOf("http://");\r
+                if (0 <= n1)\r
+                {\r
+                    n1 += "http://".Length;\r
+                    int n2 = NTHttpUtils.parseWebHost(newLocation, n1);\r
+                    if (0 < n2)\r
+                    {\r
+                        P2HostName = newLocation.Substring(n1, n2);\r
+                    }\r
+                }\r
+                return true;\r
+\r
+            }\r
+            catch (WebException we)\r
+            {\r
+                NTDebug.l(we.Message);\r
+                return false;\r
+            }\r
+            catch\r
+            {\r
+                return false;\r
+            }\r
+\r
+        }\r
+\r
+        static string writeResP2Retry(string postAddress, string refAddress, List<KeyValuePair<string, string>> extra)\r
+        {\r
+\r
+            string resultHtml = null;\r
+\r
+            if(extra == null)\r
+                return null;\r
+\r
+            StringBuilder postData =\r
+                new StringBuilder(256).Append("bbs=").Append(board).\r
+                Append("&key=").Append(dat).\r
+                Append("&time=100").\r
+                Append("&FROM=").Append(from).\r
+                Append("&mail=").Append(mail).\r
+                Append("&MESSAGE=").Append(msg).\r
+                Append("&submit=").Append(submit);\r
+\r
+            \r
+            NTHttpPostClient postClient = new NTHttpPostClient(postAddress, refAddress, "http://" + P2HostName);\r
+            postClient.mHttpReq.CookieContainer = mCookie;// mCookie.Container;\r
+\r
+            try\r
+            {\r
+                foreach (KeyValuePair<string, string> pair in extra)\r
+                {\r
+                    bool ignore = false;\r
+                    foreach (string iKey in ignoreKey)\r
+                    {\r
+                        if (pair.Key.Equals(iKey))\r
+                        {\r
+                            ignore = true;\r
+                            break;\r
+                        }\r
+                    }\r
+\r
+                    if (!ignore)\r
+                    {\r
+                        postData.Append("&").Append(pair.Key).Append("=").Append(pair.Value);\r
+                    }\r
+                }\r
+                byte [] data = System.Text.Encoding.ASCII.GetBytes(postData.ToString());\r
+                postClient.setPostData(data);\r
+\r
+                HttpWebResponse httpResp = postClient.execute();\r
+\r
+                NTDebug.l(httpResp.StatusCode.ToString());\r
+\r
+                Stream stream = httpResp.GetResponseStream();\r
+\r
+                StreamReader sr = new StreamReader(stream, enc);\r
+\r
+                resultHtml = sr.ReadToEnd();\r
+\r
+                httpResp.Close();\r
+\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+            return resultHtml;\r
+        }\r
+\r
+\r
+        public static string createThread(string url, string refferer, string host, string postData)\r
+        {\r
+            return BasicHttpPost( url,  refferer,  host,  postData, true);\r
+        }\r
+\r
+        public static string loginMaru(string uid, string passwd)\r
+        {\r
+            if (uid.Length == 0 || passwd.Length == 0)\r
+                return null;\r
+\r
+            string url = NTHttpUtils.HTTPS_PROTOCOL \r
+                + NTHttpUtils.MARU_HOST \r
+                + NTHttpUtils.MARU_LOGIN_PATH;\r
+            string reffer = NTHttpUtils.HTTPS_PROTOCOL\r
+                    + NTHttpUtils.MARU_HOST + '/';\r
+            string host = NTHttpUtils.MARU_HOST;\r
+\r
+            StringBuilder sb = new StringBuilder();\r
+\r
+            sb.Append("ID=").Append(uid).Append("&PW=").Append(passwd);\r
+            string ua = "DOLIB/1.00";\r
+            List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>();\r
+            list.Add(new KeyValuePair<string, string>("X-2ch-UA",HTTP_HEADER_USER_AGENT));\r
+\r
+            return loginMaruPost( url,  reffer,  host, sb.ToString(), list,  ua);\r
+\r
+        }\r
+        private static string loginMaruPost(string url, string refferer, string host, string postData, List<KeyValuePair<string,string>> list, string ua)\r
+        {\r
+\r
+            string result = null;\r
+\r
+            NTHttpPostClient client = null;\r
+\r
+            try\r
+            {\r
+                client = new NTHttpPostClient(url, refferer, host, list, ua);\r
+\r
+                Encoding enc = Encoding.GetEncoding(NTAppState.HOST_2CH_ENCODING);\r
+\r
+                byte[] data = System.Text.Encoding.ASCII.GetBytes(postData);\r
+\r
+                client.setPostData(data);\r
+\r
+                HttpWebResponse httpResp = client.execute();\r
+\r
+                NTDebug.l(httpResp.StatusCode.ToString());\r
+\r
+                string strCharSet = httpResp.CharacterSet;\r
+                if (strCharSet.Equals("utf-8", StringComparison.CurrentCultureIgnoreCase))\r
+                    enc = Encoding.GetEncoding("UTF-8");\r
+\r
+                Stream stream = httpResp.GetResponseStream();\r
+\r
+                StreamReader sr = new StreamReader(stream, enc);\r
+\r
+                result = sr.ReadToEnd();\r
+\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+            finally\r
+            {\r
+            }\r
+            return result;\r
+        }\r
+\r
+\r
+        private static string BasicHttpPost(string url, string refferer, \r
+            string host, string postData, bool cookieDomain)\r
+        {\r
+\r
+            String result = null;\r
+\r
+            NTHttpPostClient client = null;\r
+\r
+            try\r
+            {\r
+                client = new NTHttpPostClient(url, refferer, host);\r
+\r
+                NTCookie cookie = new NTCookie(host, cookieDomain);\r
+\r
+\r
+                client.mHttpReq.CookieContainer = cookie.Container;\r
+\r
+\r
+                Encoding enc = Encoding.GetEncoding(NTAppState.HOST_2CH_ENCODING);\r
+\r
+                byte[] data = System.Text.Encoding.ASCII.GetBytes(postData);\r
+\r
+                client.setPostData(data);\r
+\r
+                HttpWebResponse httpResp = client.execute();\r
+\r
+                NTDebug.l(httpResp.StatusCode.ToString());\r
+\r
+                string strCharSet = httpResp.CharacterSet;\r
+                if (strCharSet.Equals("utf-8", StringComparison.CurrentCultureIgnoreCase))\r
+                    enc = Encoding.GetEncoding("UTF-8");\r
+\r
+                cookie.saveCookie();\r
+\r
+                Stream stream = httpResp.GetResponseStream();\r
+\r
+                StreamReader sr = new StreamReader(stream, enc);\r
+\r
+                result = sr.ReadToEnd();\r
+\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+            finally\r
+            {\r
+            }\r
+            return result;\r
+        }\r
+\r
+\r
+\r
+        public static string createThreadP2(string[] args, List<KeyValuePair<string, string>> extra, bool retry)\r
+        {\r
+\r
+            string resultHtml = null;\r
+\r
+            enc = Encoding.GetEncoding(NTAppState.HOST_2CH_ENCODING);\r
+\r
+\r
+            host = args[0];\r
+            board = args[1];\r
+            from = HttpUtility.UrlEncode(args[2], enc);\r
+            mail = args[3];\r
+            title = HttpUtility.UrlEncode(args[4], enc);\r
+            msg = HttpUtility.UrlEncode(args[5], enc);\r
+            submit = HttpUtility.UrlEncode(args[6].Trim(), enc);\r
+\r
+            if (null == P2HostName)\r
+                P2HostName = "p2.2ch.net";\r
+            //P2HostName = "w2.p2.2ch.net";\r
+\r
+            if (null == P2LoginDir)\r
+                P2LoginDir = "/p2/?k=1";\r
+\r
+            if (null == P2PostDir)\r
+                P2PostDir = "/p2/post_form.php";\r
+\r
+            String postAddress = "http://" + P2HostName + P2PostDir;\r
+            String refAddress = postAddress;\r
+\r
+            if (null == mCookie)\r
+                mCookie = new CookieContainer();\r
+\r
+            //if (extra != null)\r
+            //    return writeResP2Retry(postAddress, refAddress, extra);\r
+\r
+            \r
+\r
+            if (!mP2LogedIn)\r
+            {\r
+                HttpStatusCode resultCode;\r
+                if (!writeResP2Login(out resultCode))\r
+                    return null;\r
+\r
+                if (resultCode == HttpStatusCode.Redirect)\r
+                {\r
+                    mCookie = new CookieContainer();\r
+                    if (!writeResP2Login(out resultCode))\r
+                        return null;\r
+\r
+                }\r
+            }\r
+\r
+            resultHtml = createThreadP2Create();\r
+#if false\r
+            resultHtml = writeResP2Write(readCnt, threadTitle);\r
+#endif\r
+            if (resultHtml == null)\r
+                return null;\r
+\r
+\r
+            if (0 < resultHtml.IndexOf("p2 error"))\r
+            {\r
+                mP2LogedIn = false;\r
+                //if (!retry)\r
+                //    resultHtml = writeResP2(args, extra, readCnt, threadTitle, true);\r
+                //else\r
+                //    return null;\r
+            }\r
+            else\r
+            {\r
+                mP2LogedIn = true;\r
+            }\r
+            return resultHtml;\r
+        }\r
+\r
+\r
+        static string createThreadP2Create(/*int readCnt, string threadTitle*/)\r
+        {\r
+\r
+            string resultHtml = null;\r
+\r
+            try\r
+            {\r
+\r
+                StringBuilder newAddress =\r
+                    new StringBuilder(256).Append("http://")\r
+                    .Append(P2HostName).Append("/p2/post_form.php?host=")\r
+                    .Append(host)//toro.2ch.net\r
+                    .Append("&bbs=").Append(board)\r
+                    //.Append("&key=").Append(dat)\r
+                    //.Append("&rescount=").Append(readCnt.ToString())\r
+                    .Append("&newthread=1&b=k");\r
+\r
+\r
+                string newAddressStr = newAddress.ToString();\r
+\r
+                NTHttpGetClient getClient = new NTHttpGetClient(newAddressStr);\r
+                getClient.mHttpReq.CookieContainer = mCookie;\r
+\r
+                HttpWebResponse httpResp = getClient.execute();\r
+\r
+                if (httpResp.StatusCode != HttpStatusCode.OK)\r
+                    return null;\r
+\r
+\r
+                Stream stream = httpResp.GetResponseStream();\r
+\r
+                StreamReader sr = new StreamReader(stream, enc);\r
+\r
+                resultHtml = sr.ReadToEnd();\r
+\r
+                httpResp.Close();\r
+\r
+                NTHtmlParser htmlParser = new NTHtmlParser(new FlowDocument());\r
+                string resultHtml2 = htmlParser.parse(resultHtml);\r
+\r
+                NTDebug.l(resultHtml2);\r
+\r
+                string action = null;\r
+                string encStr = null;\r
+                foreach (KeyValuePair<string, string> pair in htmlParser.mFormAttributes)\r
+                {\r
+                    if (pair.Key.Equals("action"))\r
+                    {\r
+                        action = pair.Value;\r
+                        //break;\r
+                    }\r
+                    else if (pair.Key.Equals("accept-charset"))\r
+                    {\r
+                        encStr = pair.Value;\r
+                    }\r
+                }\r
+\r
+                StringBuilder postData = new StringBuilder(256);\r
+\r
+                foreach (KeyValuePair<string, string> pair in htmlParser.mInputTypeHidden)\r
+                {\r
+                    if (0 < postData.Length)\r
+                        postData.Append("&");\r
+                    string val = HttpUtility.UrlEncode(pair.Value, enc);\r
+                    postData.Append(pair.Key).Append("=").Append(val);\r
+                }\r
+                foreach (KeyValuePair<string, string> pair in htmlParser.mInputTypeSubmit)\r
+                {\r
+                    if (0 < postData.Length)\r
+                        postData.Append("&");\r
+                    string val = HttpUtility.UrlEncode(pair.Value, enc);\r
+                    postData.Append(pair.Key).Append("=").Append(val);\r
+                    break;\r
+                }\r
+\r
+                \r
+                postData.Append("&subject=").Append(title)\r
+                        .Append("&MESSAGE=").Append(msg)\r
+                        .Append("&FROM=").Append(from)\r
+                        .Append("&mail=").Append(mail);\r
+\r
+\r
+                string newUrl = NTHtmlUtils.parseActionUrl(P2HostName, newAddressStr, action);\r
+                if (null == newUrl)\r
+                    return null;\r
+#if false\r
+                if (0 != action.IndexOf("/p2/"))\r
+                {\r
+                    P2PostDir = "/p2/" + action;\r
+                }\r
+                else\r
+                {\r
+                    P2PostDir = action;\r
+                }\r
+                String newUrl = "http://" + P2HostName + P2PostDir;\r
+#endif\r
+                byte[] data = System.Text.Encoding.ASCII.GetBytes(postData.ToString());\r
+\r
+                NTHttpPostClient postClient = new NTHttpPostClient(newUrl,\r
+                        "http://" + P2HostName + "/p2/post_form.php", "http://" + P2HostName);\r
+                postClient.mHttpReq.CookieContainer = mCookie;// mCookie.Container;\r
+                postClient.setPostData(data);\r
+\r
+                httpResp = postClient.execute();\r
+\r
+                if (httpResp.StatusCode != HttpStatusCode.OK)\r
+                    return null;\r
+\r
+\r
+\r
+                stream = httpResp.GetResponseStream();\r
+\r
+                sr = new StreamReader(stream, enc);\r
+\r
+                resultHtml = sr.ReadToEnd();\r
+\r
+                httpResp.Close();\r
+\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+                resultHtml = null;\r
+            }\r
+            //finally\r
+            // {\r
+            // }\r
+            //  if (loginAgain)\r
+            //  {\r
+            //     return writeResP2(args, extra, readCnt, threadTitle, true);\r
+            //  }\r
+            //  else\r
+            //  {\r
+            return resultHtml;\r
+            //  }\r
+        }\r
+\r
+\r
+\r
+\r
+        public static String writeResP2(string[] args, List<KeyValuePair<string, string>> extra, int readCnt, string threadTitle, bool retry)\r
+        {\r
+\r
+            string resultHtml = null;\r
+\r
+            enc = Encoding.GetEncoding(NTAppState.HOST_2CH_ENCODING);\r
+\r
+\r
+            host = args[0];\r
+            board = args[1];\r
+            dat = args[2];\r
+            from = HttpUtility.UrlEncode(args[3].Trim(), enc);//args[3];\r
+            mail = args[4];\r
+            msg = HttpUtility.UrlEncode(args[5].Trim(), enc);//args[5];\r
+            submit = HttpUtility.UrlEncode(args[6].Trim(), enc);//args[6];\r
+\r
+            if (null == P2HostName)\r
+                P2HostName = "p2.2ch.net";\r
+                //P2HostName = "w2.p2.2ch.net";\r
+\r
+            if (null == P2LoginDir)\r
+                P2LoginDir = "/p2/?k=1";\r
+\r
+            if (null == P2PostDir)\r
+                P2PostDir = "/p2/post_form.php";\r
+\r
+            String postAddress = "http://" + P2HostName + P2PostDir;\r
+            String refAddress = postAddress;\r
+            \r
+            if (null == mCookie)\r
+                mCookie = new CookieContainer();\r
+\r
+            if (extra != null)\r
+                return writeResP2Retry(postAddress, refAddress, extra);\r
+\r
+            //bool loginAgain = false;\r
+\r
+  \r
+            if (!mP2LogedIn)\r
+            {\r
+                HttpStatusCode resultCode;\r
+                if(!writeResP2Login(out resultCode))\r
+                    return null;\r
+\r
+                if(resultCode == HttpStatusCode.Redirect){\r
+                    mCookie = new CookieContainer();\r
+                    if(!writeResP2Login(out resultCode))\r
+                        return null;\r
+\r
+                }\r
+            }\r
+\r
+            resultHtml = writeResP2Write(readCnt, threadTitle);\r
+\r
+            if (resultHtml == null)\r
+                return null;\r
+            \r
+\r
+            if (0 < resultHtml.IndexOf("p2 error"))\r
+            {\r
+                mP2LogedIn = false;\r
+                if (!retry)\r
+                    resultHtml = writeResP2(args, extra, readCnt, threadTitle, true);\r
+                else\r
+                    return null;\r
+            }\r
+            else\r
+            {\r
+                 mP2LogedIn = true;\r
+            }\r
+            return resultHtml;\r
+        }\r
+\r
+        static string writeResP2Write(int readCnt, string threadTitle)\r
+        {\r
+\r
+            string resultHtml = null;\r
+\r
+            try\r
+            {\r
+\r
+                StringBuilder newAddress =\r
+                    new StringBuilder(256).Append("http://")\r
+                    .Append(P2HostName).Append("/p2/post_form.php?host=")\r
+                    .Append(host)//toro.2ch.net\r
+                    .Append("&bbs=").Append(board)\r
+                    .Append("&key=").Append(dat)\r
+                    .Append("&rescount=").Append(readCnt.ToString())\r
+                    .Append("&ttitle_en=")\r
+                    .Append(HttpUtility.UrlEncode(threadTitle.Trim(), enc))\r
+                    .Append("&b=k");\r
+\r
+\r
+                NTHttpGetClient getClient = new NTHttpGetClient(newAddress.ToString());\r
+                getClient.mHttpReq.CookieContainer = mCookie;\r
+\r
+                HttpWebResponse httpResp = getClient.execute();\r
+\r
+                if (httpResp.StatusCode != HttpStatusCode.OK)\r
+                    return null;\r
+\r
+                \r
+                Stream stream = httpResp.GetResponseStream();\r
+\r
+                StreamReader sr = new StreamReader(stream, enc);\r
+\r
+                resultHtml = sr.ReadToEnd();\r
+\r
+                httpResp.Close();\r
+\r
+                NTHtmlParser htmlParser = new NTHtmlParser(new FlowDocument());\r
+                string resultHtml2 = htmlParser.parse(resultHtml);\r
+\r
+                NTDebug.l(resultHtml2);\r
+\r
+                StringBuilder postData = new StringBuilder(256);\r
+\r
+                foreach (KeyValuePair<string, string> pair in htmlParser.mInputTypeHidden)\r
+                {\r
+                    if (0 < postData.Length)\r
+                        postData.Append("&");\r
+\r
+                    postData.Append(pair.Key).Append("=").Append(pair.Value);\r
+                }\r
+                foreach (KeyValuePair<string, string> pair in htmlParser.mInputTypeSubmit)\r
+                {\r
+                    if (0 < postData.Length)\r
+                        postData.Append("&");\r
+\r
+                    postData.Append(pair.Key).Append("=").Append(pair.Value);\r
+                    break;\r
+                }\r
+\r
+                string action = null;\r
+                foreach (KeyValuePair<string, string> pair in htmlParser.mFormAttributes)\r
+                {\r
+                    if (pair.Key.Equals("action"))\r
+                    {\r
+                        action = pair.Value;\r
+                        break;\r
+                    }\r
+                }\r
+\r
+                if (null != msg)\r
+                    postData.Append("&MESSAGE=").Append(msg);\r
+                if (null != from)\r
+                    postData.Append("&FROM=").Append(from);\r
+                if (null != mail)\r
+                    postData.Append("&mail=").Append(mail);\r
+\r
+                if (null == action)\r
+                    return null;\r
+\r
+                if (0 != action.IndexOf("/p2/"))\r
+                {\r
+                    P2PostDir = "/p2/" + action;\r
+                }\r
+                else\r
+                {\r
+                    P2PostDir = action;\r
+                }\r
+                String newUrl = "http://" + P2HostName + P2PostDir;\r
+\r
+                byte [] data = System.Text.Encoding.ASCII.GetBytes(postData.ToString());\r
+\r
+                NTHttpPostClient postClient = new NTHttpPostClient(newUrl,\r
+                        "http://" + P2HostName + "/p2/post_form.php", "http://" + P2HostName);\r
+                postClient.mHttpReq.CookieContainer = mCookie;// mCookie.Container;\r
+                postClient.setPostData(data);\r
+\r
+                httpResp = postClient.execute();\r
+\r
+                if (httpResp.StatusCode != HttpStatusCode.OK)\r
+                    return null;\r
+\r
+\r
+\r
+                stream = httpResp.GetResponseStream();\r
+\r
+                sr = new StreamReader(stream, enc);\r
+\r
+                resultHtml = sr.ReadToEnd();\r
+\r
+                httpResp.Close();\r
+\r
+             }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+            //finally\r
+           // {\r
+           // }\r
+          //  if (loginAgain)\r
+          //  {\r
+           //     return writeResP2(args, extra, readCnt, threadTitle, true);\r
+          //  }\r
+          //  else\r
+          //  {\r
+            return resultHtml;\r
+          //  }\r
+        }\r
+\r
+\r
+\r
+        public static bool getMachiBBSDat(string address, string boardName, string datName, string title)\r
+        {\r
+            bool bRet = false;\r
+            Stream stream = null;\r
+            HttpWebResponse httpResp = null;\r
+\r
+            address = NTHttpUtils.convertMachiAddress(address);\r
+            if (null == address)\r
+                return false;\r
+\r
+            datName = NTHttpUtils.ridSuffixFromCgiName(datName);\r
+            NTHttpGetClient httpClient = new NTHttpGetClient(address + datName + '/' );\r
+\r
+            try\r
+            {\r
+                string ifMod;\r
+                long fileSize = 0;\r
+\r
+                string[] attr = NTFileAccess.retrieveDatAttrBinFromFile(boardName, datName);\r
+\r
+                if (null != attr)\r
+                {\r
+                    httpClient.ModifiedSince = attr[1];\r
+                    try\r
+                    {\r
+                        //fileSize = long.Parse(attr[2]);\r
+                    }\r
+                    catch\r
+                    {\r
+                    }\r
+                    if (fileSize <= 0)\r
+                    {\r
+                        httpClient.AcceptGZip = true;\r
+                    }\r
+                    else\r
+                    {\r
+                        httpClient.Range = (int)fileSize;\r
+                    }\r
+                }\r
+\r
+                httpResp = httpClient.execute();\r
+\r
+                NTDebug.l(httpResp.StatusCode.ToString());\r
+\r
+                WebHeaderCollection headers = httpResp.Headers;\r
+                ifMod = headers.Get("Last-Modified");\r
+\r
+                stream = httpResp.GetResponseStream();\r
+\r
+                //int n = datName.IndexOf(".dat");\r
+                //if (n >= 0)\r
+                //    datName = datName.Substring(0, n);\r
+                //datName = NTFileAccess.ridSuffixFromDatName(datName);\r
+\r
+                bRet = NTFileAccess.storeDatToFile(stream, boardName, datName, title,\r
+                    ifMod, (httpResp.StatusCode == HttpStatusCode.PartialContent));\r
+\r
+            }\r
+            catch (System.Net.WebException e)\r
+            {\r
+                if (e.Status == System.Net.WebExceptionStatus.ProtocolError)\r
+                {\r
+                    HttpWebResponse errres = (HttpWebResponse)e.Response;\r
+                    if (errres.StatusCode == HttpStatusCode.NotModified)\r
+                    {\r
+                        bRet = true;\r
+                    }\r
+                    else\r
+                    {\r
+                        NTDebug.l(e.Message);\r
+                    }\r
+                }\r
+                else\r
+                {\r
+                    NTDebug.l(e.Message);\r
+                }\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+            finally\r
+            {\r
+                if (null != stream)\r
+                    stream.Close();\r
+                if (null != httpResp)\r
+                    httpResp.Close();\r
+            }\r
+\r
+            return bRet;\r
+        }\r
+\r
+    }\r
+}\r
diff --git a/NT2chView45/NtNet/NTHttpAccess_cloud.cs b/NT2chView45/NtNet/NTHttpAccess_cloud.cs
new file mode 100755 (executable)
index 0000000..b2888c8
--- /dev/null
@@ -0,0 +1,1701 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.IO;\r
+using System.Net;\r
+using System.Text;\r
+using System.Web;\r
+using NT2chView.NtFile;\r
+\r
+namespace NT2chView.NtNet\r
+{\r
+    public sealed partial class NTHttpAccess\r
+    {\r
+        enum DOWNLOAD_ID_NG\r
+        {\r
+            WORD,\r
+            ID,\r
+            NAME\r
+        }\r
+\r
+        public static bool getFavoriteBoards()\r
+        {\r
+            string url;\r
+            if (NTUserPreference.NTUserCloudIsEnabled)\r
+            {\r
+                url = NTUserPreference.NTUserCloudFileUrl + NTCloud.USER_CLOUD_FAVORITE_BOARD_LIST;\r
+\r
+            }else if (NTUserPreference.AESEnabled)\r
+                url = \r
+                    NTUserPreference.NTCloudUrl + NTCloud.AES_FAVORITE_BOARD_LIST;\r
+            else\r
+                url =\r
+                    NTUserPreference.NTCloudUrl + NTCloud.FAVORITE_BOARD_LIST;\r
+\r
+\r
+            return getFavorites(url, true, false);\r
+        }\r
+\r
+        public static bool getFavoriteThreads()\r
+        {\r
+            string url;\r
+            if (NTUserPreference.NTUserCloudIsEnabled)\r
+            {\r
+                url = NTUserPreference.NTUserCloudFileUrl + NTCloud.USER_CLOUD_FAVORITE_THREAD_LIST;\r
+\r
+            }\r
+            else if (NTUserPreference.AESEnabled)\r
+                url =\r
+                    NTUserPreference.NTCloudUrl + NTCloud.AES_FAVORITE_THREAD_LIST;\r
+            else\r
+                url =\r
+                    NTUserPreference.NTCloudUrl + NTCloud.FAVORITE_THREAD_LIST;\r
+\r
+            bool b1 = getFavorites(url, false, false);\r
+\r
+            if (NTUserPreference.NTUserCloudIsEnabled)\r
+            {\r
+                url = NTUserPreference.NTUserCloudFileUrl + NTCloud.USER_CLOUD_FAVORITE_THREAD_TAG_LIST;\r
+\r
+            }\r
+            else if (NTUserPreference.AESEnabled)\r
+                url =\r
+                    NTUserPreference.NTCloudUrl + NTCloud.AES_FAVORITE_THREAD_TAG_LIST;\r
+            else\r
+                url =\r
+                    NTUserPreference.NTCloudUrl + NTCloud.FAVORITE_THREAD_TAG_LIST;\r
+\r
+            bool b2 = getFavorites(url, false, true);\r
+            return b1 && b2;\r
+        }\r
+\r
+        public static bool ntGetNgWord()\r
+        {\r
+            string url;\r
+            string filePath;\r
+            string attrPath;\r
+            if (NTUserPreference.AESEnabled)\r
+            {\r
+                url = NTUserPreference.NTCloudUrl + NTCloud.AES_NGWORD_TXT;\r
+                filePath = NTFileAccess.getRootPath() + NTFileAccess.AES_NGWORD_FILE_NAME;\r
+                attrPath = NTFileAccess.getRootPath() + NTFileAccess.AES_NGWORD_ATTR_FILE_NAME;\r
+            }\r
+            else\r
+            {\r
+                url = NTUserPreference.NTCloudUrl + NTCloud.NGWORD_TXT;\r
+                filePath = NTFileAccess.getRootPath() + NTFileAccess.NGWORD_FILE_NAME;\r
+                attrPath = NTFileAccess.getRootPath() + NTFileAccess.NGWORD_ATTR_FILE_NAME;\r
+            }\r
+            return ntGetNgItem(url, filePath, attrPath);\r
+        }\r
+        public static bool ntGetNgId()\r
+        {\r
+            string url;\r
+            string filePath;\r
+            string attrPath;\r
+            if (NTUserPreference.AESEnabled)\r
+            {\r
+                url = NTUserPreference.NTCloudUrl + NTCloud.AES_NGID_TXT;\r
+                filePath = NTFileAccess.getRootPath() + NTFileAccess.AES_NGID_FILE_NAME;\r
+                attrPath = NTFileAccess.getRootPath() + NTFileAccess.AES_NGID_ATTR_FILE_NAME;\r
+            }\r
+            else\r
+            {\r
+                url = NTUserPreference.NTCloudUrl + NTCloud.NGID_TXT;\r
+                filePath = NTFileAccess.getRootPath() + NTFileAccess.NGID_FILE_NAME;\r
+                attrPath = NTFileAccess.getRootPath() + NTFileAccess.NGID_ATTR_FILE_NAME;\r
+            }\r
+            return ntGetNgItem(url, filePath, attrPath);\r
+        }\r
+        public static bool ntGetNgName()\r
+        {\r
+            string url;\r
+            string filePath;\r
+            string attrPath;\r
+            if (NTUserPreference.AESEnabled)\r
+            {\r
+                url = NTUserPreference.NTCloudUrl + NTCloud.AES_NGNAME_TXT;\r
+                filePath = NTFileAccess.getRootPath() + NTFileAccess.AES_NGNAME_FILE_NAME;\r
+                attrPath = NTFileAccess.getRootPath() + NTFileAccess.AES_NGNAME_ATTR_FILE_NAME;\r
+            }\r
+            else\r
+            {\r
+                url = NTUserPreference.NTCloudUrl + NTCloud.NGNAME_TXT;\r
+                filePath = NTFileAccess.getRootPath() + NTFileAccess.NGNAME_FILE_NAME;\r
+                attrPath = NTFileAccess.getRootPath() + NTFileAccess.NGNAME_ATTR_FILE_NAME;\r
+            }\r
+            return ntGetNgItem(url, filePath, attrPath);\r
+        }\r
+\r
+\r
+        private static bool ntGetNgItem(string url, string filePath, string attrFilePath)\r
+        {\r
+            bool bRet = false;\r
+            Stream stream = null;\r
+            HttpWebResponse httpResp = null;\r
+            NTHttpGetClient httpClient = new NTHttpGetClient(url);\r
+\r
+            try\r
+            {\r
+                string ifMod;\r
+                if (NTFileAccess.retrieveAttrFromFile(attrFilePath, out ifMod))\r
+                {\r
+                    if (ifMod != null && ifMod.Length > 0)\r
+                        httpClient.ModifiedSince = ifMod;\r
+                }\r
+\r
+                httpClient.AcceptGZip = true;\r
+\r
+                httpResp = httpClient.execute();\r
+\r
+                NTDebug.l(httpResp.StatusCode.ToString());\r
+\r
+                WebHeaderCollection headers = httpResp.Headers;\r
+\r
+                ifMod = headers.Get("Last-Modified");\r
+\r
+\r
+                stream = httpResp.GetResponseStream();\r
+\r
+                if(NTFileAccess.StreamToFile(filePath, stream))\r
+                    NTFileAccess.storeAttrToFile(attrFilePath, ifMod);\r
+                bRet = true;\r
+            }\r
+            catch (System.Net.WebException e)\r
+            {\r
+                if (e.Status == System.Net.WebExceptionStatus.ProtocolError)\r
+                {\r
+                    HttpWebResponse errres = (HttpWebResponse)e.Response;\r
+                    if (errres.StatusCode == HttpStatusCode.NotModified)\r
+                    {\r
+                        bRet = true;\r
+                    }\r
+                    else\r
+                    {\r
+                        NTDebug.l(e.Message);\r
+                    }\r
+                }\r
+                else\r
+                {\r
+                    NTDebug.l(e.Message);\r
+                }\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+            finally\r
+            {\r
+                if (null != stream)\r
+                    stream.Close();\r
+                if (null != httpResp)\r
+                    httpResp.Close();\r
+            }\r
+\r
+            return bRet;\r
+        }\r
+\r
+        private static bool getFavorites(string address, bool board, bool tag)\r
+        {\r
+            bool bRet = false;\r
+            Stream stream = null;\r
+            HttpWebResponse httpResp = null;\r
+            NTHttpGetClient httpClient = new NTHttpGetClient(address);\r
+\r
+            try\r
+            {\r
+                string ifMod;\r
+                bool b;\r
+                if (board)\r
+                {\r
+                    b = NTFileAccess.retrieveFavoriteBoardAttrFromFile(out ifMod);\r
+                }\r
+                else if (!tag)\r
+                {\r
+                    b = NTFileAccess.retrieveFavoriteThreadAttrFromFile(out ifMod);\r
+                }\r
+                else\r
+                {\r
+                    b = NTFileAccess.retrieveFavoriteThreadTagAttrFromFile(out ifMod);\r
+                }\r
+                if (b)\r
+                {\r
+                    if (ifMod != null && ifMod.Length > 0)\r
+                        httpClient.ModifiedSince = ifMod;\r
+                }\r
+\r
+                httpClient.AcceptGZip = true;\r
+\r
+                httpResp = httpClient.execute();\r
+\r
+                NTDebug.l(httpResp.StatusCode.ToString());\r
+\r
+                WebHeaderCollection headers = httpResp.Headers;\r
+\r
+                ifMod = headers.Get("Last-Modified");\r
+\r
+\r
+                stream = httpResp.GetResponseStream();\r
+\r
+                if (board)\r
+                    bRet = NTFileAccess.storeFavoriteBoardsToFile(stream, ifMod, false);\r
+                else if(!tag)\r
+                    bRet = NTFileAccess.storeFavoriteThreadsToFile(stream, ifMod, false);\r
+                else\r
+                    bRet = NTFileAccess.storeFavoriteThreadTagToFile(stream, ifMod, false);\r
+\r
+            }\r
+            catch (System.Net.WebException e)\r
+            {\r
+                if (e.Status == System.Net.WebExceptionStatus.ProtocolError)\r
+                {\r
+                    HttpWebResponse errres = (HttpWebResponse)e.Response;\r
+                    if (errres.StatusCode == HttpStatusCode.NotModified)\r
+                    {\r
+                        bRet = true;\r
+                    }\r
+                    else\r
+                    {\r
+                        NTDebug.l(e.Message);\r
+                    }\r
+                }\r
+                else\r
+                {\r
+                    NTDebug.l(e.Message);\r
+                }\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+            finally\r
+            {\r
+                if (null != stream)\r
+                    stream.Close();\r
+                if (null != httpResp)\r
+                    httpResp.Close();\r
+            }\r
+\r
+            return bRet;\r
+        }\r
+\r
+        public static bool getExternalBoards()\r
+        \r
+        {\r
+            string address;\r
+\r
+            if (NTUserPreference.NTUserCloudIsEnabled)\r
+            {\r
+                address = NTUserPreference.NTUserCloudFileUrl + NTCloud.USER_CLOUD_EXTERNAL_BOARD_LIST;\r
+\r
+            }\r
+            else if (NTUserPreference.AESEnabled)\r
+                address = NTUserPreference.NTCloudUrl + NTCloud.AES_EXTERNAL_BOARD_LIST;\r
+            else\r
+                address = NTUserPreference.NTCloudUrl + NTCloud.EXTERNAL_BOARD_LIST;\r
+            \r
+\r
+            bool bRet = false;\r
+            Stream stream = null;\r
+            HttpWebResponse httpResp = null;\r
+            NTHttpGetClient httpClient = new NTHttpGetClient(address);\r
+\r
+            try\r
+            {\r
+                string ifMod;\r
+                bool b;\r
+                b = NTFileAccess.retrieveExternalBoardAttrFromFile(out ifMod);\r
+                if (b)\r
+                {\r
+                    if (ifMod != null && ifMod.Length > 0)\r
+                        httpClient.ModifiedSince = ifMod;\r
+                }\r
+\r
+                httpClient.AcceptGZip = true;\r
+\r
+                httpResp = httpClient.execute();\r
+\r
+                NTDebug.l(httpResp.StatusCode.ToString());\r
+\r
+                WebHeaderCollection headers = httpResp.Headers;\r
+\r
+                ifMod = headers.Get("Last-Modified");\r
+\r
+\r
+                stream = httpResp.GetResponseStream();\r
+\r
+                bRet = NTFileAccess.storeExternalBoardsToFile(stream, ifMod);\r
+                \r
+            }\r
+            catch (System.Net.WebException e)\r
+            {\r
+                if (e.Status == System.Net.WebExceptionStatus.ProtocolError)\r
+                {\r
+                    HttpWebResponse errres = (HttpWebResponse)e.Response;\r
+                    if (errres.StatusCode == HttpStatusCode.NotModified)\r
+                    {\r
+                        bRet = true;\r
+                    }\r
+                    else\r
+                    {\r
+                        NTDebug.l(e.Message);\r
+                    }\r
+                }\r
+                else\r
+                {\r
+                    NTDebug.l(e.Message);\r
+                }\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+            finally\r
+            {\r
+                if (null != stream)\r
+                    stream.Close();\r
+                if (null != httpResp)\r
+                    httpResp.Close();\r
+            }\r
+\r
+            return bRet;\r
+        }\r
+\r
+        public static bool getThreadHistoryList()\r
+        {\r
+           // public const string THREAD_HISTORY_LIST_FILE_NAME = @"\ThreadHistory.txt";\r
+           //const string THREAD_HISTORY_LIST_ATTR_FILE_NAME = @"\ThreadHistoryAttr.txt";\r
+\r
+            string address;\r
+            if (NTUserPreference.NTUserCloudIsEnabled)\r
+            {\r
+                address = NTUserPreference.NTUserCloudFileUrl\r
+                    + NTCloud.USER_CLOUD_THREAD_HISTORY_LIST;\r
+\r
+            }\r
+            else if (NTUserPreference.AESEnabled)\r
+                address = NTUserPreference.NTCloudUrl + NTCloud.AES_THREAD_HISTORY_LIST;\r
+            else\r
+                address = NTUserPreference.NTCloudUrl + NTCloud.THREAD_HISTORY_LIST;\r
+            \r
+\r
+            bool bRet = false;\r
+            Stream stream = null;\r
+            HttpWebResponse httpResp = null;\r
+            NTHttpGetClient httpClient = new NTHttpGetClient(address);\r
+\r
+            try\r
+            {\r
+                string ifMod;\r
+                bool b;\r
+                b = NTFileAccess.retrieveThreadHistoryListAttrFromFile(out ifMod);\r
+                if (b)\r
+                {\r
+                    if (ifMod != null && ifMod.Length > 0)\r
+                        httpClient.ModifiedSince = ifMod;\r
+                }\r
+\r
+                httpClient.AcceptGZip = true;\r
+\r
+                httpResp = httpClient.execute();\r
+\r
+                NTDebug.l(httpResp.StatusCode.ToString());\r
+\r
+                WebHeaderCollection headers = httpResp.Headers;\r
+\r
+                ifMod = headers.Get("Last-Modified");\r
+\r
+\r
+                stream = httpResp.GetResponseStream();\r
+\r
+                bRet = NTFileAccess.storeThreadHistoryListToFile(stream, ifMod);\r
+\r
+            }\r
+            catch (System.Net.WebException e)\r
+            {\r
+                if (e.Status == System.Net.WebExceptionStatus.ProtocolError)\r
+                {\r
+                    HttpWebResponse errres = (HttpWebResponse)e.Response;\r
+                    if (errres.StatusCode == HttpStatusCode.NotModified)\r
+                    {\r
+                        bRet = true;\r
+                    }\r
+                    else\r
+                    {\r
+                        NTDebug.l(e.Message);\r
+                    }\r
+                }\r
+                else\r
+                {\r
+                    NTDebug.l(e.Message);\r
+                }\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+            finally\r
+            {\r
+                if (null != stream)\r
+                    stream.Close();\r
+                if (null != httpResp)\r
+                    httpResp.Close();\r
+            }\r
+\r
+            return bRet;\r
+        }\r
+\r
+\r
+        public static String ntUploadNgWord(string uid, string passwd,\r
+            List<string> ngList, bool append)\r
+        {\r
+            String result = null;\r
+            if (null == ngList)\r
+            {\r
+                return null;\r
+            }\r
+\r
+            String url;\r
+            if(NTUserPreference.AESEnabled)\r
+                url = NTCloud.AES_UP_NGWORD_URL;\r
+            else\r
+                url = NTCloud.UP_NGWORD_URL;\r
+\r
+\r
+            NTHttpPostClient client = null;\r
+\r
+\r
+            try\r
+            {\r
+                client = new NTHttpPostClient(url, NTCloud.SERVER_ROOT, NTCloud.SERVER_ROOT);\r
+\r
+\r
+                Encoding enc = Encoding.GetEncoding(NTAppState.HOST_2CH_ENCODING);\r
+\r
+                StringBuilder postData =\r
+                    new StringBuilder(256).Append("nickname=").Append(uid).\r
+                    Append("&passwd=").Append(passwd).\r
+                    Append("&append=").Append((append)?"1":"0").\r
+                    Append("&ngwdnum=").Append(ngList.Count.ToString());\r
+\r
+                int len = ngList.Count;\r
+                for (int i = 0; i < len; i++)\r
+                {\r
+                    String s;\r
+                    if(NTUserPreference.AESEnabled)\r
+                        s= NTTextUtiles.aesEncodeBase64URL(ngList[i]);\r
+                    else\r
+                        s = NTTextUtiles.encodeBase64URL(ngList[i]);\r
+                    postData.Append("&ngwd" + (i + 1).ToString()).Append('=').Append(s);\r
+                }\r
+\r
+                byte[] data = enc.GetBytes(postData.ToString());\r
+                client.setPostData(data);\r
+\r
+                HttpWebResponse httpResp = client.execute();\r
+\r
+                NTDebug.l(httpResp.StatusCode.ToString());\r
+\r
+\r
+                Stream stream = httpResp.GetResponseStream();\r
+\r
+                StreamReader sr = new StreamReader(stream, enc);\r
+\r
+                result = sr.ReadToEnd();\r
+\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+\r
+            return result;\r
+        }\r
+\r
+\r
+        public static String ntUploadNgName(string uid, string passwd,\r
+            List<string> ngList, bool append)\r
+        {\r
+            String result = null;\r
+            if (null == ngList)\r
+            {\r
+                return null;\r
+            }\r
+\r
+            String url;\r
+            if(NTUserPreference.AESEnabled)\r
+                url = NTCloud.AES_UP_NGNAME_URL;\r
+            else\r
+                url = NTCloud.UP_NGNAME_URL;\r
+\r
+\r
+            NTHttpPostClient client = null;\r
+\r
+\r
+            try\r
+            {\r
+                client = new NTHttpPostClient(url, NTCloud.SERVER_ROOT, NTCloud.SERVER_ROOT);\r
+\r
+\r
+                Encoding enc = Encoding.GetEncoding(NTAppState.HOST_2CH_ENCODING);\r
+\r
+                StringBuilder postData =\r
+                    new StringBuilder(256).Append("nickname=").Append(uid).\r
+                    Append("&passwd=").Append(passwd).\r
+                    Append("&append=").Append((append) ? "1" : "0").\r
+                    Append("&ngnmnum=").Append(ngList.Count.ToString());\r
+\r
+                int len = ngList.Count;\r
+                for (int i = 0; i < len; i++)\r
+                {\r
+                    String s;\r
+                    if(NTUserPreference.AESEnabled)\r
+                        s = NTTextUtiles.aesEncodeBase64URL(ngList[i]);\r
+                    else\r
+                        s = NTTextUtiles.encodeBase64URL(ngList[i]);\r
+                    postData.Append("&ngnm" + (i + 1).ToString()).Append('=').Append(s);\r
+                }\r
+\r
+                byte[] data = enc.GetBytes(postData.ToString());\r
+                client.setPostData(data);\r
+\r
+                HttpWebResponse httpResp = client.execute();\r
+\r
+                NTDebug.l(httpResp.StatusCode.ToString());\r
+\r
+\r
+                Stream stream = httpResp.GetResponseStream();\r
+\r
+                StreamReader sr = new StreamReader(stream, enc);\r
+\r
+                result = sr.ReadToEnd();\r
+\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+\r
+            return result;\r
+        }\r
+\r
+\r
+        public static String ntUploadNgId(string uid, string passwd,\r
+            List<string> ngList, bool append)\r
+        {\r
+            String result = null;\r
+            if (null == ngList)\r
+            {\r
+                return null;\r
+            }\r
+\r
+            String url;\r
+            if(NTUserPreference.AESEnabled)\r
+                url = NTCloud.AES_UP_NGID_URL;\r
+            else\r
+                url = NTCloud.UP_NGID_URL;\r
+\r
+\r
+            NTHttpPostClient client = null;\r
+\r
+\r
+            try\r
+            {\r
+                client = new NTHttpPostClient(url, NTCloud.SERVER_ROOT, NTCloud.SERVER_ROOT);\r
+\r
+\r
+                Encoding enc = Encoding.GetEncoding(NTAppState.HOST_2CH_ENCODING);\r
+\r
+                StringBuilder postData =\r
+                    new StringBuilder(256).Append("nickname=").Append(uid).\r
+                    Append("&passwd=").Append(passwd).\r
+                    Append("&append=").Append((append) ? "1" : "0").\r
+                    Append("&ngidnum=").Append(ngList.Count.ToString());\r
+\r
+                int len = ngList.Count;\r
+                for (int i = 0; i < len; i++)\r
+                {\r
+                    String s;\r
+                    if(NTUserPreference.AESEnabled)\r
+                        s = NTTextUtiles.aesEncodeBase64URL(ngList[i]);\r
+                    else\r
+                        s = NTTextUtiles.encodeBase64URL(ngList[i]);\r
+\r
+                    postData.Append("&ngid" + (i + 1).ToString()).Append('=').Append(s);\r
+                }\r
+\r
+                byte[] data = enc.GetBytes(postData.ToString());\r
+                client.setPostData(data);\r
+\r
+                HttpWebResponse httpResp = client.execute();\r
+\r
+                NTDebug.l(httpResp.StatusCode.ToString());\r
+\r
+\r
+                Stream stream = httpResp.GetResponseStream();\r
+\r
+                StreamReader sr = new StreamReader(stream, enc);\r
+\r
+                result = sr.ReadToEnd();\r
+\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+\r
+            return result;\r
+        }\r
+\r
+        public static String ntUploadThreadHistoryList(string uid, string passwd,\r
+            List<string> threadList)\r
+        {\r
+            String result = null;\r
+            if (null == threadList)\r
+            {\r
+                return null;\r
+            }\r
+\r
+            String url;\r
+            if(NTUserPreference.AESEnabled)\r
+                url = NTCloud.AES_UPLOAD_THREAD_HISTORY_LIST_URL;\r
+            else\r
+                url = NTCloud.UPLOAD_THREAD_HISTORY_LIST_URL;\r
+\r
+\r
+            NTHttpPostClient client = null;\r
+\r
+\r
+            try\r
+            {\r
+                client = new NTHttpPostClient(url, NTCloud.SERVER_ROOT, NTCloud.SERVER_ROOT);\r
+\r
+\r
+                Encoding enc = Encoding.GetEncoding(NTAppState.HOST_2CH_ENCODING);\r
+\r
+                StringBuilder postData =\r
+                    new StringBuilder(256).Append("nickname=").Append(uid).\r
+                    Append("&passwd=").Append(passwd).\r
+                    Append("&num=").Append(threadList.Count.ToString());\r
+\r
+                int len = threadList.Count;\r
+                for (int i = 0; i < len; i++)\r
+                {\r
+                    String s;\r
+                    if(NTUserPreference.AESEnabled)\r
+                        s= NTTextUtiles.aesEncodeBase64URL(threadList[i]);\r
+                    else\r
+                        s = NTTextUtiles.encodeBase64URL(threadList[i]);\r
+                    postData.Append("&h" + (i + 1).ToString()).Append('=').Append(s);\r
+                }\r
+\r
+                byte[] data = enc.GetBytes(postData.ToString());\r
+                client.setPostData(data);\r
+\r
+                HttpWebResponse httpResp = client.execute();\r
+\r
+                NTDebug.l(httpResp.StatusCode.ToString());\r
+\r
+\r
+                Stream stream = httpResp.GetResponseStream();\r
+\r
+                StreamReader sr = new StreamReader(stream, enc);\r
+\r
+                result = sr.ReadToEnd();\r
+\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+\r
+            return result;\r
+        }\r
+\r
+\r
+\r
+\r
+        public static String ntUploadFavorites(String uid , String passwd,\r
+                       List<String> boardList,List<String> threadList) {\r
+                   String result = null;\r
+                   if(null == boardList || null == threadList){\r
+                           return null;\r
+                   }\r
+               \r
+                   String url;\r
+            if(NTUserPreference.AESEnabled)\r
+                url = NTCloud.AES_UPLOAD_FAVORITES_URL;\r
+            else\r
+                url = NTCloud.UPLOAD_FAVORITES_URL;\r
+\r
+            \r
+                   NTHttpPostClient client = null;\r
+  \r
+               \r
+           try{\r
+                           client = new NTHttpPostClient( url, NTCloud.SERVER_ROOT , NTCloud.SERVER_ROOT);\r
+\r
+                \r
+                Encoding enc = Encoding.GetEncoding(NTAppState.HOST_2CH_ENCODING);\r
+\r
+                StringBuilder postData = \r
+                    new StringBuilder(256).Append("nickname=").Append(uid).\r
+                    Append("&passwd=").Append(passwd).\r
+                    Append("&bnum=").Append(boardList.Count.ToString()).\r
+                    Append("&tnum=").Append(threadList.Count.ToString());\r
+\r
+                int len = boardList.Count;\r
+                if (NTUserPreference.AESEnabled)\r
+                {\r
+                    for (int i = 0; i < len; i++)\r
+                    {\r
+                        String s = NTTextUtiles.aesEncodeBase64URL(boardList[i]);\r
+                        postData.Append("&b" + (i + 1).ToString()).Append('=').Append(s);\r
+                    }\r
+                    len = threadList.Count;\r
+                    for (int i = 0; i < len; i++)\r
+                    {\r
+                        String s = NTTextUtiles.aesEncodeBase64URL(threadList[i]);\r
+                        postData.Append("&t" + (i + 1).ToString()).Append('=').Append(s);\r
+                    }\r
+                }\r
+                else\r
+                {\r
+                    for (int i = 0; i < len; i++)\r
+                    {\r
+                        String s = NTTextUtiles.encodeBase64URL(boardList[i]);\r
+                        postData.Append("&b" + (i + 1).ToString()).Append('=').Append(s);\r
+                    }\r
+                    len = threadList.Count;\r
+                    for (int i = 0; i < len; i++)\r
+                    {\r
+                        String s = NTTextUtiles.encodeBase64URL(threadList[i]);\r
+                        postData.Append("&t" + (i + 1).ToString()).Append('=').Append(s);\r
+                    }\r
+                }\r
+\r
+                //byte[] data = System.Text.Encoding.ASCII.GetBytes(postData.ToString());\r
+                byte[] data = enc.GetBytes(postData.ToString());\r
+                client.setPostData(data);\r
+\r
+                HttpWebResponse httpResp = client.execute();\r
+\r
+                NTDebug.l(httpResp.StatusCode.ToString());\r
+\r
+                \r
+                Stream stream = httpResp.GetResponseStream();\r
+                \r
+                StreamReader sr = new StreamReader(stream, enc);\r
+\r
+                result = sr.ReadToEnd();\r
+  \r
+            }\r
+            catch(Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+\r
+            return result;\r
+               }\r
+\r
+        public static String ntUpdateFavoriteBoards(String uid, String passwd,\r
+            List<String> boardList)\r
+        {\r
+            String result = null;\r
+            if (null == boardList)\r
+            {\r
+                return null;\r
+            }\r
+\r
+            String url;\r
+            if(NTUserPreference.AESEnabled)\r
+                url= NTCloud.AES_UPDATE_ALL_FAVORITE_BOARDS_URL;\r
+            else\r
+                url = NTCloud.UPDATE_ALL_FAVORITE_BOARDS_URL;\r
+\r
+\r
+\r
+            NTHttpPostClient client = null;\r
+\r
+\r
+            try\r
+            {\r
+                client = new NTHttpPostClient(url, NTCloud.SERVER_ROOT, NTCloud.SERVER_ROOT);\r
+\r
+\r
+                Encoding enc = Encoding.GetEncoding(NTAppState.HOST_2CH_ENCODING);\r
+\r
+                StringBuilder postData =\r
+                    new StringBuilder(256).Append("nickname=").Append(uid).\r
+                    Append("&passwd=").Append(passwd).\r
+                    Append("&bnum=").Append(boardList.Count.ToString());\r
+\r
+                int len = boardList.Count;\r
+                for (int i = 0; i < len; i++)\r
+                {\r
+                    String s;\r
+                    if(NTUserPreference.AESEnabled)\r
+                        s= NTTextUtiles.aesEncodeBase64URL(boardList[i]);\r
+                    else\r
+                        s = NTTextUtiles.encodeBase64URL(boardList[i]);\r
+                    \r
+                    postData.Append("&b" + (i + 1).ToString()).Append('=').Append(s);\r
+                }\r
+\r
+                //byte[] data = System.Text.Encoding.ASCII.GetBytes(postData.ToString());\r
+                byte[] data = enc.GetBytes(postData.ToString());\r
+                client.setPostData(data);\r
+\r
+                HttpWebResponse httpResp = client.execute();\r
+\r
+                NTDebug.l(httpResp.StatusCode.ToString());\r
+\r
+\r
+                Stream stream = httpResp.GetResponseStream();\r
+\r
+                StreamReader sr = new StreamReader(stream, enc);\r
+\r
+                result = sr.ReadToEnd();\r
+\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+\r
+            return result;\r
+        }\r
+\r
+\r
+        public  static String ntUpdateFavoriteThreads(String uid, String passwd,\r
+           List<String> threadList, List<String> tagList)\r
+        {\r
+            String result = null;\r
+            if (null == threadList)\r
+            {\r
+                return null;\r
+            }\r
+\r
+            String url;\r
+            if(NTUserPreference.AESEnabled)\r
+                url = NTCloud.AES_UPDATE_ALL_FAVORITE_THREADS2_URL;\r
+            else\r
+                url = NTCloud.UPDATE_ALL_FAVORITE_THREADS2_URL;\r
+\r
+\r
+            NTHttpPostClient client = null;\r
+\r
+\r
+            try\r
+            {\r
+                client = new NTHttpPostClient(url, NTCloud.SERVER_ROOT, NTCloud.SERVER_ROOT);\r
+\r
+\r
+                Encoding enc = Encoding.GetEncoding(NTAppState.HOST_2CH_ENCODING);\r
+\r
+                StringBuilder postData =\r
+                    new StringBuilder(256).Append("nickname=").Append(uid).\r
+                    Append("&passwd=").Append(passwd).\r
+                    Append("&tnum=").Append(threadList.Count.ToString());\r
+                if(tagList != null)\r
+                    postData.Append("&tabnum=").Append(tagList.Count.ToString());\r
+\r
+                int len = threadList.Count;\r
+                for (int i = 0; i < len; i++)\r
+                {\r
+                    String s;\r
+                    if (NTUserPreference.AESEnabled)\r
+                        s = NTTextUtiles.aesEncodeBase64URL(threadList[i]);\r
+                    else\r
+                        s = NTTextUtiles.encodeBase64URL(threadList[i]);\r
+                    postData.Append("&t" + (i + 1).ToString()).Append('=').Append(s);\r
+                }\r
+                len = tagList.Count;\r
+                for (int i = 0; i < len; i++)\r
+                {\r
+                    String s;\r
+                    if (NTUserPreference.AESEnabled)\r
+                        s = NTTextUtiles.aesEncodeBase64URL(tagList[i]);\r
+                    else\r
+                        s = NTTextUtiles.encodeBase64URL(tagList[i]);\r
+                    postData.Append("&tab" + (i + 1).ToString()).Append('=').Append(s);\r
+                }\r
+\r
+                //byte[] data = System.Text.Encoding.ASCII.GetBytes(postData.ToString());\r
+                byte[] data = enc.GetBytes(postData.ToString());\r
+                client.setPostData(data);\r
+\r
+                HttpWebResponse httpResp = client.execute();\r
+\r
+                NTDebug.l(httpResp.StatusCode.ToString());\r
+\r
+\r
+                Stream stream = httpResp.GetResponseStream();\r
+\r
+                StreamReader sr = new StreamReader(stream, enc);\r
+\r
+                result = sr.ReadToEnd();\r
+\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+\r
+            return result;\r
+        }\r
+\r
+\r
+        public static String ntUploadExternalBoards(string description)\r
+        {\r
+            string uid = NTUserPreference.NTCloudID;\r
+            string passwd = NTUserPreference.NTCloudPSS;\r
+\r
+            string result = null;\r
+            if (null == description || uid == null || passwd == null)\r
+            {\r
+                return null;\r
+            }\r
+\r
+            string url;\r
+            if(NTUserPreference.AESEnabled)\r
+                url = NTCloud.AES_UPLOAD_EXTERNALBOARD_URL;\r
+            else\r
+                url= NTCloud.UPLOAD_EXTERNALBOARD_URL;\r
+\r
+\r
+            NTHttpPostClient client = null;\r
+\r
+\r
+            try\r
+            {\r
+                client = new NTHttpPostClient(url, NTCloud.SERVER_ROOT, NTCloud.SERVER_ROOT);\r
+\r
+\r
+                Encoding enc = Encoding.GetEncoding(NTAppState.HOST_2CH_ENCODING);\r
+                string s;\r
+                if (NTUserPreference.AESEnabled)\r
+                    s = NTTextUtiles.aesEncodeBase64URL(description);\r
+                else\r
+                    s = NTTextUtiles.encodeBase64URL(description);\r
+\r
+\r
+                StringBuilder postData =\r
+                    new StringBuilder(256).Append("nickname=").Append(uid).\r
+                    Append("&passwd=").Append(passwd).\r
+                    Append("&exbnum=1&exb1=").Append(s);\r
+\r
+\r
+                byte[] data = enc.GetBytes(postData.ToString());\r
+                client.setPostData(data);\r
+\r
+                HttpWebResponse httpResp = client.execute();\r
+\r
+                NTDebug.l(httpResp.StatusCode.ToString());\r
+\r
+\r
+                Stream stream = httpResp.GetResponseStream();\r
+\r
+                StreamReader sr = new StreamReader(stream, enc);\r
+\r
+                result = sr.ReadToEnd();\r
+\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+\r
+            return result;\r
+        }\r
+\r
+        public static String ntDeleteExternalBoards(string description)\r
+        {\r
+            string uid = NTUserPreference.NTCloudID;\r
+            string passwd = NTUserPreference.NTCloudPSS;\r
+\r
+            string result = null;\r
+            if (null == description || uid == null || passwd == null)\r
+            {\r
+                return null;\r
+            }\r
+\r
+            string url;\r
+            if(NTUserPreference.AESEnabled)\r
+                url = NTCloud.AES_DELETE_EXTERNALBOARD_URL;\r
+            else\r
+                url = NTCloud.DELETE_EXTERNALBOARD_URL;\r
+\r
+\r
+            NTHttpPostClient client = null;\r
+\r
+\r
+            try\r
+            {\r
+                client = new NTHttpPostClient(url, NTCloud.SERVER_ROOT, NTCloud.SERVER_ROOT);\r
+\r
+\r
+                Encoding enc = Encoding.GetEncoding(NTAppState.HOST_2CH_ENCODING);\r
+\r
+                string s;\r
+                if (NTUserPreference.AESEnabled)\r
+                    s = NTTextUtiles.aesEncodeBase64URL(description);\r
+                else\r
+                    s = NTTextUtiles.encodeBase64URL(description);\r
+\r
+                StringBuilder postData =\r
+                    new StringBuilder(256).Append("nickname=").Append(uid).\r
+                    Append("&passwd=").Append(passwd).\r
+                    Append("&exbnum=1&exb1=").Append(s);\r
+\r
+\r
+                byte[] data = enc.GetBytes(postData.ToString());\r
+                client.setPostData(data);\r
+\r
+                HttpWebResponse httpResp = client.execute();\r
+\r
+                NTDebug.l(httpResp.StatusCode.ToString());\r
+\r
+\r
+                Stream stream = httpResp.GetResponseStream();\r
+\r
+                StreamReader sr = new StreamReader(stream, enc);\r
+\r
+                result = sr.ReadToEnd();\r
+\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+\r
+            return result;\r
+        }\r
+\r
+\r
+        public static String ntDeletedFavoriteBoard(String uid, String passwd,\r
+            List<String> boardList)\r
+        {\r
+            String result = null;\r
+            if (null == boardList || boardList.Count == 0)\r
+            {\r
+                return null;\r
+            }\r
+\r
+            String url;\r
+            if(NTUserPreference.AESEnabled)\r
+                url = NTCloud.AES_DELETE_FAVORITES_BOARD_URL;\r
+            else\r
+                url = NTCloud.DELETE_FAVORITES_BOARD_URL;\r
+            \r
+\r
+\r
+            NTHttpPostClient client = null;\r
+\r
+\r
+            try\r
+            {\r
+                client = new NTHttpPostClient(url, NTCloud.SERVER_ROOT, NTCloud.SERVER_ROOT);\r
+\r
+                \r
+                Encoding enc = Encoding.GetEncoding(NTAppState.HOST_2CH_ENCODING);\r
+\r
+                StringBuilder postData =\r
+                    new StringBuilder(256).Append("nickname=").Append(uid).\r
+                    Append("&passwd=").Append(passwd).\r
+                    Append("&bnum=").Append(boardList.Count.ToString());\r
+\r
+                int len = boardList.Count;\r
+                for (int i = 0; i < len; i++)\r
+                {\r
+                    String s;\r
+                    if(NTUserPreference.AESEnabled)\r
+                        s = NTTextUtiles.aesEncodeBase64URL(boardList[i]);\r
+                    else\r
+                        s = NTTextUtiles.encodeBase64URL(boardList[i]);\r
+                    postData.Append("&b" + (i + 1).ToString()).Append('=').Append(s);\r
+                }\r
+                \r
+\r
+                //byte[] data = System.Text.Encoding.ASCII.GetBytes(postData.ToString());\r
+                byte[] data = enc.GetBytes(postData.ToString());\r
+                client.setPostData(data);\r
+\r
+                HttpWebResponse httpResp = client.execute();\r
+\r
+                NTDebug.l(httpResp.StatusCode.ToString());\r
+\r
+                \r
+                Stream stream = httpResp.GetResponseStream();\r
+               \r
+                StreamReader sr = new StreamReader(stream, enc);\r
+\r
+                result = sr.ReadToEnd();\r
+\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+\r
+            return result;\r
+        }\r
+\r
+        public static String ntDeletedFavoriteThread(String uid, String passwd,\r
+            List<String> threadList)\r
+        {\r
+            String result = null;\r
+            if (null == threadList || threadList.Count == 0)\r
+            {\r
+                return null;\r
+            }\r
+\r
+            String url;\r
+            if(NTUserPreference.AESEnabled)\r
+                url = NTCloud.AES_DELETE_FAVORITES_THREAD_URL;\r
+            else\r
+                url = NTCloud.DELETE_FAVORITES_THREAD_URL;\r
+\r
+\r
+            NTHttpPostClient client = null;\r
+\r
+\r
+            try\r
+            {\r
+                client = new NTHttpPostClient(url, NTCloud.SERVER_ROOT, NTCloud.SERVER_ROOT);\r
+\r
+\r
+                Encoding enc = Encoding.GetEncoding(NTAppState.HOST_2CH_ENCODING);\r
+\r
+                StringBuilder postData =\r
+                    new StringBuilder(256).Append("nickname=").Append(uid).\r
+                    Append("&passwd=").Append(passwd).\r
+                    Append("&tnum=").Append(threadList.Count.ToString());\r
+\r
+                int len = threadList.Count;\r
+                for (int i = 0; i < len; i++)\r
+                {\r
+                    String s;\r
+                    if(NTUserPreference.AESEnabled)\r
+                        s = NTTextUtiles.aesEncodeBase64URL(threadList[i]);\r
+                    else\r
+                        s = NTTextUtiles.encodeBase64URL(threadList[i]);\r
+                    postData.Append("&t" + (i + 1).ToString()).Append('=').Append(s);\r
+                }\r
+\r
+                byte[] data = enc.GetBytes(postData.ToString());\r
+                //byte[] data = System.Text.Encoding.ASCII.GetBytes(postData.ToString());\r
+                client.setPostData(data);\r
+\r
+                HttpWebResponse httpResp = client.execute();\r
+\r
+                NTDebug.l(httpResp.StatusCode.ToString());\r
+\r
+\r
+                Stream stream = httpResp.GetResponseStream();\r
+\r
+                StreamReader sr = new StreamReader(stream, enc);\r
+\r
+                result = sr.ReadToEnd();\r
+\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+\r
+            return result;\r
+        }\r
+       \r
+        public static string ntCheckUser(string userName, string passwd)\r
+        {\r
+\r
+            String result = null;\r
+\r
+            \r
+            NTHttpPostClient client = null;\r
+            HttpWebResponse httpResp = null;\r
+            Stream stream = null;\r
+            StreamReader sr = null;\r
+\r
+\r
+            try\r
+            {\r
+                client = new NTHttpPostClient(NTCloud.CHECK_USER_URL, NTCloud.SERVER_ROOT, NTCloud.SERVER_ROOT);\r
+\r
+                \r
+                Encoding enc = Encoding.GetEncoding(NTAppState.HOST_2CH_ENCODING);\r
+\r
+\r
+\r
+                StringBuilder postData =\r
+                    new StringBuilder(256).Append("nickname=").Append(userName).\r
+                    Append("&passwd=").Append(passwd);\r
+  \r
+                \r
+\r
+                byte[] data = System.Text.Encoding.ASCII.GetBytes(postData.ToString());\r
+                client.setPostData(data);\r
+\r
+                httpResp = client.execute();\r
+\r
+                NTDebug.l(httpResp.StatusCode.ToString());\r
+\r
+                \r
+                stream = httpResp.GetResponseStream();\r
+               \r
+                sr = new StreamReader(stream, enc);\r
+\r
+                result = sr.ReadToEnd();\r
+\r
\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+            finally\r
+            {\r
+                if (sr != null)\r
+                    sr.Close();\r
+                if (stream != null)\r
+                    stream.Close();\r
+                if (httpResp != null)\r
+                    httpResp.Close();\r
+            }\r
+            return result;\r
+        }\r
+\r
+\r
+        public static string ntQueryReadCountList(String uid, String passwd,\r
+            string boardName)\r
+        {\r
+            String result = null;\r
+            \r
+            String url;\r
+            if(NTUserPreference.AESEnabled)\r
+                url = NTCloud.AES_QUERY_READCNT_LIST_URL;\r
+            else\r
+                url = NTCloud.QUERY_READCNT_LIST_URL;\r
+            \r
+\r
+            NTHttpPostClient client = null;\r
+\r
+\r
+            try\r
+            {\r
+                client = new NTHttpPostClient(url, NTCloud.SERVER_ROOT, NTCloud.SERVER_ROOT);\r
+\r
+\r
+                Encoding enc = Encoding.GetEncoding(NTAppState.HOST_2CH_ENCODING);\r
+                String s;\r
+                if(NTUserPreference.AESEnabled)\r
+                    s = NTTextUtiles.aesEncodeBase64URL(boardName);\r
+                else\r
+                    s = NTTextUtiles.encodeBase64URL(boardName);\r
+                \r
+                StringBuilder postData =\r
+                    new StringBuilder(256).Append("nickname=").Append(uid).\r
+                    Append("&passwd=").Append(passwd).\r
+                    Append("&board_name=").Append(s);\r
+\r
+                byte[] data = enc.GetBytes(postData.ToString());\r
+                client.setPostData(data);\r
+\r
+                HttpWebResponse httpResp = client.execute();\r
+\r
+                NTDebug.l(httpResp.StatusCode.ToString());\r
+\r
+\r
+                Stream stream = httpResp.GetResponseStream();\r
+\r
+                StreamReader sr = new StreamReader(stream, enc);\r
+\r
+                result = sr.ReadToEnd();\r
+\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+\r
+            return result;\r
+        }\r
+\r
+        public static string ntQueryReadHistory(String uid, String passwd)\r
+        {\r
+            if(NTUserPreference.AESEnabled)\r
+                return ntQueryHistory(uid, passwd, 4);\r
+            else\r
+                return ntQueryHistory(uid, passwd, 1);\r
+        }\r
+        public static string ntQueryWriteHistory(String uid, String passwd)\r
+        {\r
+            if (NTUserPreference.AESEnabled)\r
+                return ntQueryHistory(uid, passwd, 5);\r
+            else\r
+                return ntQueryHistory(uid, passwd, 2);\r
+        }\r
+        public static string ntQueryBookmarkHistory(String uid, String passwd)\r
+        {\r
+            if (NTUserPreference.AESEnabled)\r
+                return ntQueryHistory(uid, passwd, 6);\r
+            else\r
+                return ntQueryHistory(uid, passwd, 3);\r
+        }\r
+\r
+        private static string ntQueryHistory(String uid, String passwd, int type)\r
+        {\r
+            String result = null;\r
+\r
+            String url;\r
+            if(NTUserPreference.AESEnabled)\r
+                url = NTCloud.AES_QUERY_READ_HISTORY_URL;\r
+            else\r
+                url = NTCloud.QUERY_READ_HISTORY_URL;\r
+\r
+\r
+            NTHttpPostClient client = null;\r
+\r
+\r
+            try\r
+            {\r
+                client = new NTHttpPostClient(url, NTCloud.SERVER_ROOT, NTCloud.SERVER_ROOT);\r
+\r
+\r
+                Encoding enc = Encoding.GetEncoding(NTAppState.HOST_2CH_ENCODING);\r
+                StringBuilder postData =\r
+                    new StringBuilder(256).Append("nickname=").Append(uid).\r
+                    Append("&passwd=").Append(passwd).\r
+                    Append("&type=").Append(type.ToString());\r
+\r
+                byte[] data = enc.GetBytes(postData.ToString());\r
+                client.setPostData(data);\r
+\r
+                HttpWebResponse httpResp = client.execute();\r
+\r
+                NTDebug.l(httpResp.StatusCode.ToString());\r
+\r
+\r
+                Stream stream = httpResp.GetResponseStream();\r
+\r
+                StreamReader sr = new StreamReader(stream, enc);\r
+\r
+                result = sr.ReadToEnd();\r
+\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+\r
+            return result;\r
+        }\r
+\r
+        public static string ntUpdateAttrValue(\r
+           string boardName, string datName, string kind, string value)\r
+        {\r
+\r
+            string uid = NTUserPreference.NTCloudID;\r
+            string passwd = NTUserPreference.NTCloudPSS;\r
+\r
+            String result = null;\r
+\r
+            String url;\r
+            if(NTUserPreference.AESEnabled)\r
+                url = NTCloud.AES_UPDATE_ATTR_VALUE_URL;\r
+            else\r
+                url = NTCloud.UPDATE_ATTR_VALUE_URL;\r
+            \r
+            NTHttpPostClient client = null;\r
+\r
+\r
+            try\r
+            {\r
+                client = new NTHttpPostClient(url, NTCloud.SERVER_ROOT, NTCloud.SERVER_ROOT);\r
+\r
+\r
+                Encoding enc = Encoding.GetEncoding(NTAppState.HOST_2CH_ENCODING);\r
+                if (NTUserPreference.AESEnabled)\r
+                {\r
+                    boardName = NTTextUtiles.aesEncodeBase64URL(boardName);\r
+                    datName = NTTextUtiles.aesEncodeBase64URL(datName);\r
+                }\r
+                else\r
+                {\r
+                    boardName = NTTextUtiles.encodeBase64URL(boardName);\r
+                    datName = NTTextUtiles.encodeBase64URL(datName);\r
+                }\r
+                StringBuilder postData =\r
+                    new StringBuilder(256).Append("nickname=").Append(uid).\r
+                    Append("&passwd=").Append(passwd).\r
+                    Append("&attr_type=").Append(kind).\r
+                    Append("&attr_val=").Append(value).\r
+                    Append("&board_name=").Append(boardName).\r
+                    Append("&dat_name=").Append(datName);\r
+\r
+                byte[] data = enc.GetBytes(postData.ToString());\r
+                client.setPostData(data);\r
+\r
+                HttpWebResponse httpResp = client.execute();\r
+\r
+                NTDebug.l(httpResp.StatusCode.ToString());\r
+\r
+\r
+                Stream stream = httpResp.GetResponseStream();\r
+\r
+                StreamReader sr = new StreamReader(stream, enc);\r
+\r
+                result = sr.ReadToEnd();\r
+\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+\r
+            return result;\r
+        }\r
+\r
+        public static string ntDeleteDatValue(string boardName, string datName)\r
+        {\r
+\r
+            string uid = NTUserPreference.NTCloudID;\r
+            string passwd = NTUserPreference.NTCloudPSS;\r
+\r
+            String result = null;\r
+\r
+            String url;\r
+            if(NTUserPreference.AESEnabled)\r
+                url = NTCloud.AES_DELETE_DAT_VALUE_URL;\r
+            else\r
+                url = NTCloud.DELETE_DAT_VALUE_URL;\r
+            \r
+\r
+            NTHttpPostClient client = null;\r
+\r
+\r
+            try\r
+            {\r
+                client = new NTHttpPostClient(url, NTCloud.SERVER_ROOT, NTCloud.SERVER_ROOT);\r
+\r
+\r
+                Encoding enc = Encoding.GetEncoding(NTAppState.HOST_2CH_ENCODING);\r
+                if (NTUserPreference.AESEnabled)\r
+                {\r
+                    boardName = NTTextUtiles.aesEncodeBase64URL(boardName);\r
+                    if (!("*".Equals(datName)))\r
+                        datName = NTTextUtiles.aesEncodeBase64URL(datName);\r
+                }\r
+                else\r
+                {\r
+                    boardName = NTTextUtiles.encodeBase64URL(boardName);\r
+                    if (!("*".Equals(datName)))\r
+                        datName = NTTextUtiles.encodeBase64URL(datName);\r
+                }\r
+                StringBuilder postData =\r
+                    new StringBuilder(256).Append("nickname=").Append(uid).\r
+                    Append("&passwd=").Append(passwd).\r
+                    Append("&board_name=").Append(boardName).\r
+                    Append("&dat_name=").Append(datName);\r
+\r
+                byte[] data = enc.GetBytes(postData.ToString());\r
+                client.setPostData(data);\r
+\r
+                HttpWebResponse httpResp = client.execute();\r
+\r
+                NTDebug.l(httpResp.StatusCode.ToString());\r
+\r
+\r
+                Stream stream = httpResp.GetResponseStream();\r
+\r
+                StreamReader sr = new StreamReader(stream, enc);\r
+\r
+                result = sr.ReadToEnd();\r
+\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+\r
+            return result;\r
+\r
+\r
+        }\r
+        public static string ntDeleteAttrValue(\r
+           string boardName, string datName, string kind, string value)\r
+        {\r
+\r
+            string uid = NTUserPreference.NTCloudID;\r
+            string passwd = NTUserPreference.NTCloudPSS;\r
+\r
+            String result = null;\r
+\r
+            String url;\r
+            if(NTUserPreference.AESEnabled)\r
+                url = NTCloud.AES_DELETE_ATTR_VALUE_URL;\r
+            else\r
+                url = NTCloud.DELETE_ATTR_VALUE_URL;\r
+            \r
+\r
+            NTHttpPostClient client = null;\r
+\r
+\r
+            try\r
+            {\r
+                client = new NTHttpPostClient(url, NTCloud.SERVER_ROOT, NTCloud.SERVER_ROOT);\r
+\r
+\r
+                Encoding enc = Encoding.GetEncoding(NTAppState.HOST_2CH_ENCODING);\r
+                if (NTUserPreference.AESEnabled)\r
+                {\r
+                    boardName = NTTextUtiles.aesEncodeBase64URL(boardName);\r
+                    datName = NTTextUtiles.aesEncodeBase64URL(datName);\r
+                }\r
+                else\r
+                {\r
+                    boardName = NTTextUtiles.encodeBase64URL(boardName);\r
+                    datName = NTTextUtiles.encodeBase64URL(datName);\r
+                }\r
+                StringBuilder postData =\r
+                    new StringBuilder(256).Append("nickname=").Append(uid).\r
+                    Append("&passwd=").Append(passwd).\r
+                    Append("&attr_type=").Append(kind).\r
+                    Append("&attr_val=").Append(value).\r
+                    Append("&board_name=").Append(boardName).\r
+                    Append("&dat_name=").Append(datName);\r
+\r
+                byte[] data = enc.GetBytes(postData.ToString());\r
+                client.setPostData(data);\r
+\r
+                HttpWebResponse httpResp = client.execute();\r
+\r
+                NTDebug.l(httpResp.StatusCode.ToString());\r
+\r
+\r
+                Stream stream = httpResp.GetResponseStream();\r
+\r
+                StreamReader sr = new StreamReader(stream, enc);\r
+\r
+                result = sr.ReadToEnd();\r
+\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+\r
+            return result;\r
+        }\r
+\r
+        public static string ntQueryAttrValue(/*String uid, String passwd,*/\r
+           string boardName, string datName)\r
+        {\r
+            String result = null;\r
+\r
+            string uid = NTUserPreference.NTCloudID;\r
+            string passwd = NTUserPreference.NTCloudPSS;\r
+\r
+            String url;\r
+            if(NTUserPreference.AESEnabled)\r
+                url = NTCloud.AES_QUERY_ATTR_VALUE_URL;\r
+            else\r
+                url = NTCloud.QUERY_ATTR_VALUE_URL;\r
+            \r
+\r
+            NTHttpPostClient client = null;\r
+\r
+\r
+            try\r
+            {\r
+                client = new NTHttpPostClient(url, NTCloud.SERVER_ROOT, NTCloud.SERVER_ROOT);\r
+\r
+\r
+                Encoding enc = Encoding.GetEncoding(NTAppState.HOST_2CH_ENCODING);\r
+                if (NTUserPreference.AESEnabled)\r
+                {\r
+                    boardName = NTTextUtiles.aesEncodeBase64URL(boardName);\r
+                    datName = NTTextUtiles.aesEncodeBase64URL(datName);\r
+                }\r
+                else\r
+                {\r
+                    boardName = NTTextUtiles.encodeBase64URL(boardName);\r
+                    datName = NTTextUtiles.encodeBase64URL(datName);\r
+                }\r
+                StringBuilder postData =\r
+                    new StringBuilder(256).Append("nickname=").Append(uid).\r
+                    Append("&passwd=").Append(passwd).\r
+                    Append("&board_name=").Append(boardName).\r
+                    Append("&dat_name=").Append(datName);\r
+\r
+                byte[] data = enc.GetBytes(postData.ToString());\r
+                client.setPostData(data);\r
+\r
+                HttpWebResponse httpResp = client.execute();\r
+\r
+                NTDebug.l(httpResp.StatusCode.ToString());\r
+\r
+\r
+                Stream stream = httpResp.GetResponseStream();\r
+\r
+                StreamReader sr = new StreamReader(stream, enc);\r
+\r
+                result = sr.ReadToEnd();\r
+\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+\r
+            return result;\r
+        }\r
+\r
+\r
+        public static string queryThreadFromAllBoard(string sWord)\r
+        {\r
+\r
+\r
+            String result = null;\r
+\r
+            string uid = NTUserPreference.NTCloudID;\r
+            string passwd = NTUserPreference.NTCloudPSS;\r
+\r
+            String url = URL_ALLBOARD_SEARCH;\r
+\r
+\r
+            NTHttpGetClient client = null;\r
+\r
+\r
+            try\r
+            {\r
+                \r
+\r
+                Encoding enc = Encoding.GetEncoding(NTAppState.HOST_2CH_ENCODING);\r
+                sWord = HttpUtility.UrlEncode(sWord, enc);\r
+                string kensaku = HttpUtility.UrlEncode("検索", enc);\r
+                string query = "?STR="+sWord+"&submit="+kensaku+"&COUNT=50";\r
+               \r
+                client = new NTHttpGetClient(url + query);\r
+\r
+                HttpWebResponse httpResp = client.execute();\r
+\r
+                NTDebug.l(httpResp.StatusCode.ToString());\r
+\r
+                    \r
+                Stream stream = httpResp.GetResponseStream();\r
+\r
+                StreamReader sr = new StreamReader(stream, enc);\r
+\r
+                result = sr.ReadToEnd();\r
+\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+\r
+            return result;\r
+        }\r
+       }\r
+}\r
diff --git a/NT2chView45/NtNet/NTHttpAccess_user_cloud.cs b/NT2chView45/NtNet/NTHttpAccess_user_cloud.cs
new file mode 100755 (executable)
index 0000000..7d733a1
--- /dev/null
@@ -0,0 +1,799 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.IO;\r
+using System.Net;\r
+using System.Text;\r
+using NT2chView.NtFile;\r
+\r
+namespace NT2chView.NtNet\r
+{\r
+    public sealed partial class NTHttpAccess\r
+    {\r
+        \r
+        public static string UserCloudCheckUser(string url, string userName, string passwd)\r
+        {\r
+            String result = null;\r
+\r
+            NTHttpPostClient client = null;\r
+            HttpWebResponse httpResp = null;\r
+            Stream stream = null;\r
+            StreamReader sr = null;\r
+\r
+            try\r
+            {\r
+                client = new NTHttpPostClient(url,url,url);\r
+\r
+                Encoding enc = Encoding.GetEncoding("UTF-8");\r
+\r
+                StringBuilder postData =\r
+                    new StringBuilder(256).Append("user=").Append(userName).\r
+                    Append("&passwd=").Append(passwd);\r
+\r
+                byte[] data = System.Text.Encoding.ASCII.GetBytes(postData.ToString());\r
+                client.setPostData(data);\r
+\r
+                httpResp = client.execute();\r
+\r
+                NTDebug.l(httpResp.StatusCode.ToString());\r
+\r
+\r
+                stream = httpResp.GetResponseStream();\r
+\r
+                sr = new StreamReader(stream, enc);\r
+\r
+                result = sr.ReadToEnd();\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+            finally\r
+            {\r
+                if (sr != null)\r
+                    sr.Close();\r
+                if (stream != null)\r
+                    stream.Close();\r
+                if (httpResp != null)\r
+                    httpResp.Close();\r
+            }\r
+            return result;\r
+        }\r
+        \r
+        public static string UserCloudQueryReadCountList(String uid, String passwd,\r
+            string boardName)\r
+        {\r
+            String result = null;\r
+\r
+            String url = NTUserPreference.NTUserCloudScriptUrl + "nc_query_readcnt_list2_db.php"; ;\r
+            //if (NTUserPreference.AESEnabled)\r
+            //    url = NTCloud.AES_QUERY_READCNT_LIST_URL;\r
+           // else\r
+             //   url = NTCloud.QUERY_READCNT_LIST_URL;\r
+\r
+            NTHttpPostClient client = null;\r
+\r
+            try\r
+            {\r
+                client = new NTHttpPostClient(url, url, url);\r
+\r
+\r
+                Encoding enc = Encoding.GetEncoding(NTAppState.HOST_2CH_ENCODING);\r
+                String s;\r
+                if (NTUserPreference.AESEnabled)\r
+                    s = NTTextUtiles.aesEncodeBase64URL(boardName);\r
+                else\r
+                    s = NTTextUtiles.encodeBase64URL(boardName);\r
+\r
+                StringBuilder postData =\r
+                    new StringBuilder(256).Append("user=").Append(uid).\r
+                    Append("&hashed_passwd=").Append(passwd).\r
+                    Append("&board_name=").Append(s);\r
+                if (NTUserPreference.AESEnabled)\r
+                    postData.Append("&aes_enable=1");\r
+\r
+                byte[] data = enc.GetBytes(postData.ToString());\r
+                client.setPostData(data);\r
+\r
+                HttpWebResponse httpResp = client.execute();\r
+\r
+                NTDebug.l(httpResp.StatusCode.ToString());\r
+\r
+\r
+                Stream stream = httpResp.GetResponseStream();\r
+\r
+                StreamReader sr = new StreamReader(stream, Encoding.GetEncoding("UTF-8"));\r
+\r
+                result = sr.ReadToEnd();\r
+\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+\r
+            return result;\r
+        }\r
+\r
+        public static string UserCloudUpdateReadCount(\r
+            string boardName, string datName, string kind, string value)\r
+        {\r
+            String result = null;\r
+\r
+            String url = NTUserPreference.NTUserCloudScriptUrl + "nc_update_readcnt_db.php"; ;\r
+            //if (NTUserPreference.AESEnabled)\r
+            //    url = NTCloud.AES_QUERY_READCNT_LIST_URL;\r
+            // else\r
+            //   url = NTCloud.QUERY_READCNT_LIST_URL;\r
+\r
+            NTHttpPostClient client = null;\r
+\r
+            try\r
+            {\r
+                client = new NTHttpPostClient(url, url, url);\r
+\r
+                string uid = NTUserPreference.NTCloudID;\r
+                string hashed = NTUserPreference.NTUserCloudGetHashedPasswd();\r
+\r
+\r
+                Encoding enc = Encoding.GetEncoding(NTAppState.HOST_2CH_ENCODING);\r
+                String s1, s2;\r
+                if (NTUserPreference.AESEnabled)\r
+                {\r
+                    s1 = NTTextUtiles.aesEncodeBase64URL(boardName);\r
+                    s2 = NTTextUtiles.aesEncodeBase64URL(datName);\r
+                }\r
+                else\r
+                {\r
+                    s1 = NTTextUtiles.encodeBase64URL(boardName);\r
+                    s2 = NTTextUtiles.encodeBase64URL(datName);\r
+                }\r
+                StringBuilder postData =\r
+                    new StringBuilder(256).Append("user=").Append(uid).\r
+                    Append("&hashed_passwd=").Append(hashed).\r
+                    Append("&board_name=").Append(s1).\r
+                    Append("&dat_name=").Append(s2).\r
+                    Append("&res_number=").Append(value).\r
+                    Append("&record_type=").Append(kind);\r
+\r
+                byte[] data = enc.GetBytes(postData.ToString());\r
+                client.setPostData(data);\r
+\r
+                HttpWebResponse httpResp = client.execute();\r
+\r
+                NTDebug.l(httpResp.StatusCode.ToString());\r
+\r
+\r
+                Stream stream = httpResp.GetResponseStream();\r
+\r
+                StreamReader sr = new StreamReader(stream, Encoding.GetEncoding("UTF-8"));\r
+\r
+                result = sr.ReadToEnd();\r
+\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+\r
+            return result;\r
+\r
+        }\r
+\r
+        public static string UserCloudUpdateAttrValue(\r
+            string boardName, string datName, string kind, string value)\r
+        {\r
+            String result = null;\r
+\r
+            String url = NTUserPreference.NTUserCloudScriptUrl + "nc_add_attributes_db.php";\r
+            \r
+            NTHttpPostClient client = null;\r
+\r
+            try\r
+            {\r
+                client = new NTHttpPostClient(url, url, url);\r
+\r
+                string uid = NTUserPreference.NTCloudID;\r
+                string hashed = NTUserPreference.NTUserCloudGetHashedPasswd();\r
+\r
+\r
+                Encoding enc = Encoding.GetEncoding(NTAppState.HOST_2CH_ENCODING);\r
+                String s1, s2;\r
+                if (NTUserPreference.AESEnabled)\r
+                {\r
+                    s1 = NTTextUtiles.aesEncodeBase64URL(boardName);\r
+                    s2 = NTTextUtiles.aesEncodeBase64URL(datName);\r
+                }\r
+                else\r
+                {\r
+                    s1 = NTTextUtiles.encodeBase64URL(boardName);\r
+                    s2 = NTTextUtiles.encodeBase64URL(datName);\r
+                }\r
+                StringBuilder postData =\r
+                    new StringBuilder(256).Append("user=").Append(uid).\r
+                    Append("&hashed_passwd=").Append(hashed).\r
+                    Append("&board_name=").Append(s1).\r
+                    Append("&dat_name=").Append(s2).\r
+                    Append("&res_number=").Append(value).\r
+                    Append("&type1=").Append(kind);\r
+\r
+                byte[] data = enc.GetBytes(postData.ToString());\r
+                client.setPostData(data);\r
+\r
+                HttpWebResponse httpResp = client.execute();\r
+\r
+                NTDebug.l(httpResp.StatusCode.ToString());\r
+\r
+\r
+                Stream stream = httpResp.GetResponseStream();\r
+\r
+                StreamReader sr = new StreamReader(stream, Encoding.GetEncoding("UTF-8"));\r
+\r
+                result = sr.ReadToEnd();\r
+\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+\r
+            return result;\r
+\r
+        }\r
+\r
+        public static string UserCloudDeleteAttrValue(\r
+            string boardName, string datName, string kind, string value)\r
+        {\r
+            String result = null;\r
+\r
+            String url = NTUserPreference.NTUserCloudScriptUrl + "nc_delete_attribute_db.php";\r
+\r
+            NTHttpPostClient client = null;\r
+\r
+            try\r
+            {\r
+                client = new NTHttpPostClient(url, url, url);\r
+\r
+                string uid = NTUserPreference.NTCloudID;\r
+                string hashed = NTUserPreference.NTUserCloudGetHashedPasswd();\r
+\r
+\r
+                Encoding enc = Encoding.GetEncoding(NTAppState.HOST_2CH_ENCODING);\r
+                String s1, s2;\r
+                if (NTUserPreference.AESEnabled)\r
+                {\r
+                    s1 = NTTextUtiles.aesEncodeBase64URL(boardName);\r
+                    s2 = NTTextUtiles.aesEncodeBase64URL(datName);\r
+                }\r
+                else\r
+                {\r
+                    s1 = NTTextUtiles.encodeBase64URL(boardName);\r
+                    s2 = NTTextUtiles.encodeBase64URL(datName);\r
+                }\r
+                StringBuilder postData =\r
+                    new StringBuilder(256).Append("user=").Append(uid).\r
+                    Append("&hashed_passwd=").Append(hashed).\r
+                    Append("&board_name=").Append(s1).\r
+                    Append("&dat_name=").Append(s2).\r
+                    Append("&res_number=").Append(value).\r
+                    Append("&record_type=").Append(kind);\r
+\r
+                byte[] data = enc.GetBytes(postData.ToString());\r
+                client.setPostData(data);\r
+\r
+                HttpWebResponse httpResp = client.execute();\r
+\r
+                NTDebug.l(httpResp.StatusCode.ToString());\r
+\r
+\r
+                Stream stream = httpResp.GetResponseStream();\r
+\r
+                StreamReader sr = new StreamReader(stream, Encoding.GetEncoding("UTF-8"));\r
+\r
+                result = sr.ReadToEnd();\r
+\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+\r
+            return result;\r
+\r
+        }\r
+\r
+        public static string UserCloudQueryAttrValue(string boardName, string datName)\r
+        {\r
+            String result = null;\r
+\r
+            string uid = NTUserPreference.NTCloudID;\r
+            string passwd = NTUserPreference.NTUserCloudGetHashedPasswd();\r
+\r
+            string url = NTUserPreference.NTUserCloudScriptUrl\r
+                + "nc_query_thread_attribute_list_db.php";\r
+            \r
+            NTHttpPostClient client = null;\r
+\r
+            try\r
+            {\r
+                string extraParam;\r
+                client = new NTHttpPostClient(url, NTCloud.SERVER_ROOT, NTCloud.SERVER_ROOT);\r
+\r
+                Encoding enc = Encoding.GetEncoding(NTAppState.HOST_2CH_ENCODING);\r
+                if (NTUserPreference.AESEnabled)\r
+                {\r
+                    boardName = NTTextUtiles.aesEncodeBase64URL(boardName);\r
+                    datName = NTTextUtiles.aesEncodeBase64URL(datName);\r
+                    extraParam = "&type1=5&type2=6";\r
+                }\r
+                else\r
+                {\r
+                    boardName = NTTextUtiles.encodeBase64URL(boardName);\r
+                    datName = NTTextUtiles.encodeBase64URL(datName);\r
+                    extraParam = "&type1=2&type2=3";\r
+                }\r
+                StringBuilder postData =\r
+                    new StringBuilder(256).Append("user=").Append(uid).\r
+                    Append("&hashed_passwd=").Append(passwd).\r
+                    Append("&board_name=").Append(boardName).\r
+                    Append("&dat_name=").Append(datName).\r
+                    Append(extraParam);\r
+\r
+                byte[] data = enc.GetBytes(postData.ToString());\r
+                client.setPostData(data);\r
+\r
+                HttpWebResponse httpResp = client.execute();\r
+\r
+                NTDebug.l(httpResp.StatusCode.ToString());\r
+\r
+\r
+                Stream stream = httpResp.GetResponseStream();\r
+\r
+                StreamReader sr = new StreamReader(stream, Encoding.GetEncoding("UTF-8"));\r
+\r
+                result = sr.ReadToEnd();\r
+\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+\r
+            return result;\r
+        }\r
+\r
+        public static string UserCloudQueryReadHistory(String uid, String passwd)\r
+        {\r
+            if (NTUserPreference.AESEnabled)\r
+                return UserCloudQueryHistory(uid, passwd, 4);\r
+            else\r
+                return UserCloudQueryHistory(uid, passwd, 1);\r
+        }\r
+        public static string UserCloudQueryWriteHistory(String uid, String passwd)\r
+        {\r
+            if (NTUserPreference.AESEnabled)\r
+                return UserCloudQueryHistory(uid, passwd, 5);\r
+            else\r
+                return UserCloudQueryHistory(uid, passwd, 2);\r
+        }\r
+        public static string UserCloudQueryBookmarkHistory(String uid, String passwd)\r
+        {\r
+            if (NTUserPreference.AESEnabled)\r
+                return UserCloudQueryHistory(uid, passwd, 6);\r
+            else\r
+                return UserCloudQueryHistory(uid, passwd, 3);\r
+        }\r
+        private static string UserCloudQueryHistory(String uid, String hashedPasswd, int type)\r
+        {\r
+            String result = null;\r
+            String url = NTUserPreference.NTUserCloudScriptUrl + "nc_query_record_by_type_db.php";\r
+            NTHttpPostClient client = null;\r
+\r
+            try\r
+            {\r
+                client = new NTHttpPostClient(url, NTCloud.SERVER_ROOT, NTCloud.SERVER_ROOT);\r
+\r
+\r
+                Encoding enc = Encoding.GetEncoding(NTAppState.HOST_2CH_ENCODING);\r
+                StringBuilder postData =\r
+                    new StringBuilder(256).Append("user=").Append(uid).\r
+                    Append("&hashed_passwd=").Append(hashedPasswd).\r
+                    Append("&record_type=").Append(type.ToString());\r
+\r
+                byte[] data = enc.GetBytes(postData.ToString());\r
+                client.setPostData(data);\r
+\r
+                HttpWebResponse httpResp = client.execute();\r
+\r
+                NTDebug.l(httpResp.StatusCode.ToString());\r
+\r
+\r
+                Stream stream = httpResp.GetResponseStream();\r
+\r
+                StreamReader sr = new StreamReader(stream, enc);\r
+\r
+                result = sr.ReadToEnd();\r
+\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+\r
+            return result;\r
+        }\r
+\r
+\r
+\r
+        public static bool UserCloudGetNgWord()\r
+        {\r
+            string url = NTUserPreference.NTUserCloudFileUrl + NTCloud.USER_CLOUD_NGWORD_TXT;\r
+            string filePath;\r
+            string attrPath;\r
+            if (NTUserPreference.AESEnabled)\r
+            {\r
+                filePath = NTFileAccess.getRootPath() + NTFileAccess.AES_NGWORD_FILE_NAME;\r
+                attrPath = NTFileAccess.getRootPath() + NTFileAccess.AES_NGWORD_ATTR_FILE_NAME;\r
+            }\r
+            else\r
+            {\r
+                filePath = NTFileAccess.getRootPath() + NTFileAccess.NGWORD_FILE_NAME;\r
+                attrPath = NTFileAccess.getRootPath() + NTFileAccess.NGWORD_ATTR_FILE_NAME;\r
+            }\r
+            return ntGetNgItem(url, filePath, attrPath);\r
+        }\r
+        public static bool UserCloudGetNgId()\r
+        {\r
+            string url = NTUserPreference.NTUserCloudFileUrl + NTCloud.USER_CLOUD_NGID_TXT;\r
+            string filePath;\r
+            string attrPath;\r
+            if (NTUserPreference.AESEnabled)\r
+            {\r
+                filePath = NTFileAccess.getRootPath() + NTFileAccess.AES_NGID_FILE_NAME;\r
+                attrPath = NTFileAccess.getRootPath() + NTFileAccess.AES_NGID_ATTR_FILE_NAME;\r
+            }\r
+            else\r
+            {\r
+                filePath = NTFileAccess.getRootPath() + NTFileAccess.NGID_FILE_NAME;\r
+                attrPath = NTFileAccess.getRootPath() + NTFileAccess.NGID_ATTR_FILE_NAME;\r
+            }\r
+            return ntGetNgItem(url, filePath, attrPath);\r
+        }\r
+        public static bool UserCloudGetNgName()\r
+        {\r
+            string filePath;\r
+            string attrPath;\r
+            string url = NTUserPreference.NTUserCloudFileUrl + NTCloud.USER_CLOUD_NGNAME_TXT;\r
+            if (NTUserPreference.AESEnabled)\r
+            {\r
+                filePath = NTFileAccess.getRootPath() + NTFileAccess.AES_NGNAME_FILE_NAME;\r
+                attrPath = NTFileAccess.getRootPath() + NTFileAccess.AES_NGNAME_ATTR_FILE_NAME;\r
+            }\r
+            else\r
+            {\r
+                 filePath = NTFileAccess.getRootPath() + NTFileAccess.NGNAME_FILE_NAME;\r
+                attrPath = NTFileAccess.getRootPath() + NTFileAccess.NGNAME_ATTR_FILE_NAME;\r
+            }\r
+            return ntGetNgItem(url, filePath, attrPath);\r
+        }\r
+\r
+        public static String UserCloudUpdateFavoriteBoards(String uid, String passwd,\r
+            List<String> boardList)\r
+        {\r
+            return UserCloudUploadLinesFile("fb03.txt", uid, passwd, boardList);\r
+        }\r
+\r
+        public static String UserCloudUpdateFavoriteThreads(String uid, String passwd,\r
+           List<String> threadList, List<String> tagList)\r
+        {\r
+            string result1 = UserCloudUploadLinesFile("ft03.txt", uid, passwd, threadList);\r
+            string result2 = UserCloudUploadLinesFile("ftab03.txt", uid, passwd, tagList);\r
+            //String result = null;\r
+            if (result1 != null)\r
+            {\r
+                if (result2 != null)\r
+                    return result1 + result2;\r
+                else\r
+                    return result1;\r
+            }\r
+            return result2;\r
+\r
+        }\r
+\r
+        public static String UserCloudUploadThreadHistoryList(string uid, string passwd,\r
+            List<string> historyList)\r
+        {\r
+            return UserCloudUploadLinesFile("histab03.txt", uid, passwd, historyList);\r
+        }\r
+\r
+        public static String UserCloudDeleteExternalBoards(string description)\r
+        {\r
+            return UserCloudDeleteLineFromFile("exboard03.txt", description);\r
+        }\r
+\r
+        public static String UserCloudUploadExternalBoards(string description)\r
+        {\r
+            return UserCloudInsertLineIntoFile("exboard03.txt", description);\r
+        }\r
+\r
+        public static String UserCloudUploadNgWord(string uid, string passwd,\r
+            List<string> ngList, bool append)\r
+        {\r
+            if (append)\r
+            {\r
+                return UserCloudInsertLinesIntoFile("ngwd03.txt", uid, passwd, ngList);\r
+            }\r
+            else\r
+            {\r
+                return UserCloudUploadLinesFile("ngwd03.txt", uid, passwd, ngList);\r
+            }\r
+        }\r
+\r
+        public static String UserCloudUploadNgId(string uid, string passwd,\r
+            List<string> ngList, bool append)\r
+        {\r
+            if (append)\r
+            {\r
+                return UserCloudInsertLinesIntoFile("ngid03.txt", uid, passwd, ngList);\r
+            }\r
+            else\r
+            {\r
+                return UserCloudUploadLinesFile("ngid03.txt", uid, passwd, ngList);\r
+            }\r
+        }\r
+\r
+        public static String UserCloudUploadNgName(string uid, string passwd,\r
+            List<string> ngList, bool append)\r
+        {\r
+            if (append)\r
+            {\r
+                return UserCloudInsertLinesIntoFile("ngnm03.txt", uid, passwd, ngList);\r
+            }\r
+            else\r
+            {\r
+                return UserCloudUploadLinesFile("ngnm03.txt", uid, passwd, ngList);\r
+            }\r
+        }\r
+\r
+\r
+        private static String UserCloudUploadLinesFile(string fileName, String uid, String passwd,\r
+            List<String> list)\r
+        {\r
+            String result = null;\r
+            if (null == list)\r
+            {\r
+                return null;\r
+            }\r
+\r
+            String url = NTUserPreference.NTUserCloudScriptUrl + "nc_write_file.php"; ;\r
+\r
+            NTHttpPostClient client = null;\r
+\r
+            try\r
+            {\r
+                client = new NTHttpPostClient(url, url, url);\r
+\r
+\r
+                Encoding enc = Encoding.GetEncoding(NTAppState.HOST_2CH_ENCODING);\r
+\r
+                StringBuilder postData =\r
+                    new StringBuilder(256).Append("user=").Append(uid).\r
+                    Append("&hashed_passwd=").Append(passwd).\r
+                    Append("&file_name=").Append(fileName).Append("&data=");\r
+\r
+                int len = list.Count;\r
+                for (int i = 0; i < len; i++)\r
+                {\r
+                    String s;\r
+                    if (NTUserPreference.AESEnabled)\r
+                        s = NTTextUtiles.aesEncodeBase64URL(list[i]);\r
+                    else\r
+                        s = NTTextUtiles.encodeBase64URL(list[i]);\r
+\r
+                    postData.Append(s).Append('\n');\r
+                }\r
+\r
+                byte[] data = enc.GetBytes(postData.ToString());\r
+                client.setPostData(data);\r
+\r
+                HttpWebResponse httpResp = client.execute();\r
+\r
+                NTDebug.l(httpResp.StatusCode.ToString());\r
+\r
+\r
+                Stream stream = httpResp.GetResponseStream();\r
+\r
+                StreamReader sr = new StreamReader(stream, enc);\r
+\r
+                result = sr.ReadToEnd();\r
+\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+\r
+            return result;\r
+        }\r
+\r
+        private static String UserCloudInsertLineIntoFile(string fileName, string description)\r
+        {\r
+            string uid = NTUserPreference.NTCloudID;\r
+            string hashed = NTUserPreference.NTUserCloudGetHashedPasswd(); \r
+            //NTCrypt.getSHA256Hashed(\r
+              //  NTUserPreference.NTCloudPSS+NTUserPreference.NTUserCloudSeed);\r
+\r
+            string result = null;\r
+            if (null == description || uid == null )//|| passwd == null)\r
+            {\r
+                return null;\r
+            }\r
+\r
+            string url = NTUserPreference.NTUserCloudScriptUrl + "nc_insert_lines_file.php"; ;\r
+\r
+            NTHttpPostClient client = null;\r
+\r
+            try\r
+            {\r
+                client = new NTHttpPostClient(url, url, url);\r
+\r
+\r
+                Encoding enc = Encoding.GetEncoding(NTAppState.HOST_2CH_ENCODING);\r
+                string s;\r
+                if (NTUserPreference.AESEnabled)\r
+                    s = NTTextUtiles.aesEncodeBase64URL(description);\r
+                else\r
+                    s = NTTextUtiles.encodeBase64URL(description);\r
+\r
+\r
+                StringBuilder postData =\r
+                    new StringBuilder(256).Append("user=").Append(uid).\r
+                    Append("&hashed_passwd=").Append(hashed).\r
+                    Append("&file_name=").Append(fileName).Append("&num=1&n1=").Append(s);\r
+\r
+\r
+                byte[] data = enc.GetBytes(postData.ToString());\r
+                client.setPostData(data);\r
+\r
+                HttpWebResponse httpResp = client.execute();\r
+\r
+                NTDebug.l(httpResp.StatusCode.ToString());\r
+\r
+\r
+                Stream stream = httpResp.GetResponseStream();\r
+\r
+                StreamReader sr = new StreamReader(stream, enc);\r
+\r
+                result = sr.ReadToEnd();\r
+\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+\r
+            return result;\r
+        }\r
+\r
+        private static string UserCloudInsertLinesIntoFile(string fileName,\r
+                string uid, string hashed, List<string> list)\r
+        {\r
+            //string uid = NTUserPreference.NTCloudID;\r
+            //string hashed = NTCrypt.getSHA256Hashed(\r
+            //    NTUserPreference.NTCloudPSS + NTUserPreference.NTUserCloudSeed);\r
+\r
+            string result = null;\r
+            if (null == list || 0 == list.Count || uid == null || hashed == null)\r
+            {\r
+                return null;\r
+            }\r
+\r
+            string url = NTUserPreference.NTUserCloudScriptUrl + "nc_insert_lines_file.php"; ;\r
+\r
+            NTHttpPostClient client = null;\r
+\r
+            try\r
+            {\r
+                client = new NTHttpPostClient(url, url, url);\r
+\r
+                int num = list.Count;\r
+\r
+                StringBuilder postData =\r
+                    new StringBuilder(256).Append("user=").Append(uid).\r
+                    Append("&hashed_passwd=").Append(hashed).\r
+                    Append("&file_name=").Append(fileName).Append("&num=").Append(num);\r
+\r
+                Encoding enc = Encoding.GetEncoding(NTAppState.HOST_2CH_ENCODING);\r
+                for (int i = 0; i < num; i++)\r
+                {\r
+                    string s;\r
+                    if (NTUserPreference.AESEnabled)\r
+                        s = NTTextUtiles.aesEncodeBase64URL(list[i]);\r
+                    else\r
+                        s = NTTextUtiles.encodeBase64URL(list[i]);\r
+                    postData.Append("&n").Append(i+1).Append("=").Append(s);\r
+                }\r
+\r
+                byte[] data = enc.GetBytes(postData.ToString());\r
+                client.setPostData(data);\r
+\r
+                HttpWebResponse httpResp = client.execute();\r
+\r
+                NTDebug.l(httpResp.StatusCode.ToString());\r
+\r
+\r
+                Stream stream = httpResp.GetResponseStream();\r
+\r
+                StreamReader sr = new StreamReader(stream, enc);\r
+\r
+                result = sr.ReadToEnd();\r
+\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+\r
+            return result;\r
+        }\r
+\r
+        private static String UserCloudDeleteLineFromFile(string fileName, string description)\r
+        {\r
+            string uid = NTUserPreference.NTCloudID;\r
+            string hashed = NTUserPreference.NTUserCloudGetHashedPasswd(); \r
+            //NTCrypt.getSHA256Hashed(\r
+              //  NTUserPreference.NTCloudPSS + NTUserPreference.NTUserCloudSeed);\r
+\r
+            string result = null;\r
+            if (null == description || uid == null || hashed == null)\r
+            {\r
+                return null;\r
+            }\r
+\r
+            string url = NTUserPreference.NTUserCloudScriptUrl + "nc_delete_lines_file.php"; ;\r
+\r
+            NTHttpPostClient client = null;\r
+\r
+            try\r
+            {\r
+                client = new NTHttpPostClient(url, url, url);\r
+\r
+\r
+                Encoding enc = Encoding.GetEncoding(NTAppState.HOST_2CH_ENCODING);\r
+\r
+                string s;\r
+                if (NTUserPreference.AESEnabled)\r
+                    s = NTTextUtiles.aesEncodeBase64URL(description);\r
+                else\r
+                    s = NTTextUtiles.encodeBase64URL(description);\r
+\r
+                StringBuilder postData =\r
+                   new StringBuilder(256).Append("user=").Append(uid).\r
+                   Append("&hashed_passwd=").Append(hashed).\r
+                   Append("&file_name=").Append(fileName).Append("&num=1&n1=").Append(s);\r
+\r
+\r
+                byte[] data = enc.GetBytes(postData.ToString());\r
+                client.setPostData(data);\r
+\r
+                HttpWebResponse httpResp = client.execute();\r
+\r
+                NTDebug.l(httpResp.StatusCode.ToString());\r
+\r
+\r
+                Stream stream = httpResp.GetResponseStream();\r
+\r
+                StreamReader sr = new StreamReader(stream, enc);\r
+\r
+                result = sr.ReadToEnd();\r
+\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                NTDebug.l(e.Message);\r
+            }\r
+\r
+            return result;\r
+        }\r
+\r
+    }\r
+}\r
diff --git a/NT2chView45/NtNet/NTHttpAccess_util.cs b/NT2chView45/NtNet/NTHttpAccess_util.cs
new file mode 100755 (executable)
index 0000000..6ce6dcf
--- /dev/null
@@ -0,0 +1,159 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Net;\r
+using System.Net.Cache;\r
+\r
+namespace NT2chView.NtNet\r
+{\r
+    public sealed partial class NTHttpAccess\r
+    {\r
+        const string HTTP_HEADER_IF_MODIFIED_SINCE = "If-Modified-Since";\r
+        const string HTTP_HEADER_LAST_MODIFIED = "Last-Modified";\r
+        public const string HTTP_HEADER_USER_AGENT = "Monazilla/1.00 (monaweb/1.00) Neetchanwin";\r
+        //public const string HTTP_HEADER_USER_AGENT = "Monazilla/1.00";\r
+        const string HTTP_HEADER_COOKIE = "Cookie";\r
+        const string HTTP_HEADER_SET_COOKIE = "Set-Cookie";\r
+        const string HTTP_HEADER_CONTENT_TYPE = "application/x-www-form-urlencoded";\r
+        const string HTTP_REQUEST_GET = "GET";\r
+        const string HTTP_REQUEST_POST = "POST";\r
+        const string URL_2CH_BOARDMENU = "http://menu.2ch.net/bbsmenu.html";\r
+        const string URL_ALLBOARD_SEARCH = "http://s.s2ch.net/search/-/";\r
+\r
+        class NTHttpGetClient\r
+        {\r
+            public HttpWebRequest mHttpReq;\r
+            private string mModifiedSince = string.Empty;\r
+            public string ModifiedSince\r
+            {\r
+                get { return mModifiedSince; }\r
+                set\r
+                {\r
+                    DateTime dt;\r
+                    if (DateTime.TryParse(value, out dt))\r
+                    {\r
+                        mHttpReq.IfModifiedSince = dt;\r
+                    }\r
+                }\r
+            }\r
+\r
+            public bool AcceptGZip\r
+            {\r
+                set\r
+                {\r
+                    if (value == true)\r
+                    {\r
+                        mHttpReq.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;\r
+                    }\r
+                    else\r
+                    {\r
+                        mHttpReq.AutomaticDecompression = DecompressionMethods.None;\r
+                    }\r
+                }\r
+            }\r
+\r
+            public int Range\r
+            {\r
+                set { mHttpReq.AddRange(value); }\r
+            }\r
+\r
+            public NTHttpGetClient(string url)\r
+            {\r
+                mHttpReq = (HttpWebRequest)WebRequest.Create(url);\r
+                mHttpReq.Method = HTTP_REQUEST_GET;\r
+                mHttpReq.UserAgent = HTTP_HEADER_USER_AGENT;\r
+                mHttpReq.ReadWriteTimeout = 5 * 1000;\r
+                mHttpReq.Timeout = 5 * 1000;\r
+                mHttpReq.CachePolicy = new RequestCachePolicy(RequestCacheLevel.NoCacheNoStore);\r
+                mHttpReq.KeepAlive = false;\r
+                mHttpReq.ContentType = HTTP_HEADER_CONTENT_TYPE;\r
+            }\r
+\r
+            public HttpWebResponse execute()\r
+            {\r
+                return (HttpWebResponse)mHttpReq.GetResponse();\r
+            }\r
+        }\r
+\r
+        \r
+\r
+        class NTHttpPostClient\r
+        {\r
+            public  HttpWebRequest mHttpReq;\r
+            private string mModifiedSince = string.Empty;\r
+           \r
+            public string ModifiedSince\r
+            {\r
+                get { return mModifiedSince; }\r
+                set\r
+                {\r
+                    DateTime dt;\r
+                    if (DateTime.TryParse(value, out dt))\r
+                    {\r
+                        mHttpReq.IfModifiedSince = dt;\r
+                    }\r
+                }\r
+            }\r
+\r
+            public void setPostData(byte [] data)\r
+            {\r
+                System.IO.Stream reqStream = mHttpReq.GetRequestStream();\r
+                reqStream.Write(data, 0, data.Length);\r
+                reqStream.Close();\r
+            }\r
+\r
+            public NTHttpPostClient(string url, string referer, string host)\r
+                : this(url, referer, host, null, null)\r
+            {\r
+            }\r
+           \r
+            public NTHttpPostClient(string url, string referer, string host,\r
+                List<KeyValuePair<string,string>> headers, string ua)\r
+            {\r
+                mHttpReq = (HttpWebRequest)WebRequest.Create(url);\r
+                mHttpReq.Method = HTTP_REQUEST_POST;\r
+                if(ua == null)\r
+                    mHttpReq.UserAgent = HTTP_HEADER_USER_AGENT;\r
+                else\r
+                    mHttpReq.UserAgent = ua;\r
+                mHttpReq.ReadWriteTimeout = 5 * 1000;\r
+                mHttpReq.Timeout = 5 * 1000;\r
+                mHttpReq.CachePolicy = new RequestCachePolicy(RequestCacheLevel.NoCacheNoStore);\r
+                mHttpReq.KeepAlive = false;\r
+                mHttpReq.ContentType = HTTP_HEADER_CONTENT_TYPE;\r
+                mHttpReq.Accept = "*/*";\r
+                mHttpReq.Referer = referer;\r
+                \r
+                //NTDebug.l("Auto redirect was set : " + mHttpReq.AllowAutoRedirect);\r
+                mHttpReq.AllowAutoRedirect = false;\r
+                \r
+                WebHeaderCollection wHeaderCollection = new WebHeaderCollection();\r
+                wHeaderCollection.Add("Host", host);\r
+                wHeaderCollection.Add("Accept-Language", "ja");\r
+                wHeaderCollection.Add("accept-charset", "Shift_JIS");\r
+                if (headers != null)\r
+                {\r
+                    foreach (KeyValuePair<string, string> pair in headers)\r
+                    {\r
+                        wHeaderCollection.Add(pair.Key, pair.Value);\r
+                    }\r
+                }\r
+                //wHeaderCollection.hea\r
+\r
+                //cc.\r
+                //mHttpReq.CookieContainer = cc;\r
+\r
+               \r
+           }\r
+\r
+            \r
+\r
+            public HttpWebResponse execute()\r
+            {\r
+                return (HttpWebResponse)mHttpReq.GetResponse();\r
+            }\r
+\r
+        }\r
+\r
+    }\r
+}\r
diff --git a/NT2chView45/NtNet/NTHttpUtils.cs b/NT2chView45/NtNet/NTHttpUtils.cs
new file mode 100755 (executable)
index 0000000..f8909f3
--- /dev/null
@@ -0,0 +1,336 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using NT2chView.NtHtml;\r
+\r
+\r
+namespace NT2chView.NtNet\r
+{\r
+    sealed class NTHttpUtils\r
+    {\r
+        public const string HTTP_PROTOCOL = @"http://";\r
+        public const string HTTPS_PROTOCOL = @"https://";\r
+        public const string HTTP_WRITE_CGI_PATH = @"/test/bbs.cgi";\r
+        public const string HTTP_READ_CGI_PATH = @"/test/read.cgi/";\r
+        public const string HTTP_SLASH = @"/";\r
+        public const string DAT_SUFFIX = ".dat";\r
+        public const string CGI_SUFFIX = ".cgi";\r
+        public const string DEFAULT_SUBMIT = "書き込む";\r
+        public const string MACHI_URL = "machi.to/";\r
+        public const string HOST_2CH = ".2ch.net";\r
+        public const string MARU_HOST = "2chv.tora3.net";\r
+        public const string MARU_LOGIN_PATH = "/futen.cgi";\r
+        public const string LOCAL_DAT_TITEL_PREFIX = "[DAT落]";\r
+\r
+\r
+        public static int GetTime(DateTime baseTime)\r
+        {\r
+            TimeSpan t = baseTime.ToUniversalTime().Subtract(new DateTime(1970, 1, 1));\r
+            return ((int)(t.TotalSeconds)) - (60*10);\r
+        }\r
+\r
+\r
+        public static bool TryParseYouTubeId(string source, out string id)\r
+        {\r
+            int len = source.Length;\r
+            int n = source.IndexOf(".youtube.com/");\r
+            if (n > 0)\r
+            {\r
+                int n2 = source.IndexOf("v=", n + 13);\r
+                if (n2+2+11 <= len)\r
+                {\r
+                    id = source.Substring(n2+2, 11);\r
+                    return true;\r
+                }\r
+            }\r
+            n = source.IndexOf("youtu.be/");\r
+            if (n > 0)\r
+            {\r
+                if (len >= (n + 9 + 11))\r
+                {\r
+                    id = source.Substring(n+9, 11);\r
+                    return true;\r
+                }\r
+            }\r
+            id = string.Empty;\r
+            return false;\r
+        }\r
+        public static bool parseBBSAddress(string source, out string boardAddress, out string datName)\r
+        {\r
+            boardAddress = string.Empty;\r
+            datName = string.Empty;\r
+\r
+            int idx = source.IndexOf(HTTP_READ_CGI_PATH);\r
+            if (idx < 0)\r
+                return false;\r
+\r
+\r
+            boardAddress = source.Substring(0, idx + 1);\r
+            idx += HTTP_READ_CGI_PATH.Length;\r
+            if (idx >= source.Length)\r
+                return false;\r
+            while (idx < source.Length)\r
+            {\r
+\r
+                int idx2 = source.IndexOf('/', idx);\r
+                if (idx2 < 0)\r
+                    return false;\r
+                if (isDatKey(source, idx, idx2))\r
+                {\r
+                    datName = source.Substring(idx, idx2 - idx);\r
+                }\r
+                else\r
+                {\r
+                    if (datName.Length > 0)\r
+                        return false;\r
+                    boardAddress += source.Substring(idx, idx2 + 1 - idx);\r
+                }\r
+                idx = idx2 + 1;\r
+            }\r
+            if (datName.Length == 0)\r
+                return false;\r
+\r
+            if (chkMachiBBSAddress(boardAddress))\r
+                datName = datName + CGI_SUFFIX;\r
+            else\r
+                datName = datName + DAT_SUFFIX;\r
+\r
+            return true;\r
+        }\r
+\r
+        public static bool isValid2chAddress(string address)\r
+        {\r
+            if (0 > address.IndexOf(HOST_2CH, \r
+                StringComparison.CurrentCultureIgnoreCase))\r
+                return false;\r
+            else\r
+                return true;\r
+        }\r
+\r
+        public static bool chkMachiBBSAddress(string source)\r
+        {\r
+            if (0 > source.IndexOf(MACHI_URL))\r
+                return false;\r
+            else\r
+                return true;\r
+        }\r
+\r
+        public static string convertMachiAddress(string address)\r
+        {\r
+            int idx = address.IndexOf(MACHI_URL);\r
+            if (idx < 0)\r
+                return null;\r
+\r
+            string result = address.Substring(0, idx + MACHI_URL.Length);\r
+            result += "bbs/offlaw.cgi/";\r
+            result += address.Substring(idx + MACHI_URL.Length);\r
+            return result;\r
+\r
+        }\r
+\r
+        public static bool splitMachiAddress(string source, out string host, out string bbs)\r
+        {\r
+            host = string.Empty;\r
+            bbs = string.Empty;\r
+            int idx = source.IndexOf(MACHI_URL);\r
+            if (idx < 0)\r
+                return false;\r
+            int idx2 = source.IndexOf('/', idx + MACHI_URL.Length);\r
+            if (idx2 < 0)\r
+                return false;\r
+\r
+            host = source.Substring(0, idx + MACHI_URL.Length - 1);\r
+            bbs = source.Substring(idx + MACHI_URL.Length, idx2 - (idx + MACHI_URL.Length));\r
+            return true;\r
+        }\r
+\r
+        public static bool parseHostAddress(string source, out string hostName, out string boardName)\r
+        {\r
+            hostName = string.Empty;\r
+            boardName = string.Empty;\r
+\r
+            int n1 = source.IndexOf(HTTP_PROTOCOL);\r
+            if (n1 < 0)\r
+                return false;\r
+\r
+            n1 += HTTP_PROTOCOL.Length;\r
+\r
+            int n2 = source.IndexOf(HTTP_SLASH, n1);\r
+            if (n2 < 0)\r
+                return false;\r
+\r
+            int n3 = source.IndexOf(HTTP_SLASH, n2 + 1);\r
+            //int n3 = source.LastIndexOf(HTTP_SLASH);//, n2 + 1);\r
+            if (n3 < 0)// || n3 < (n2+1))\r
+                return false;\r
+\r
+            //int n4 = source.IndexOf(HTTP_SLASH, n3 + 1);\r
+            //int n3 = source.LastIndexOf(HTTP_SLASH);//, n2 + 1);\r
+            //if (n4 < 0)\r
+            //{\r
+                hostName = source.Substring(n1, n2 - n1);\r
+                boardName = source.Substring(n2 + 1, n3 - (n2 + 1));\r
+            //}\r
+            //else\r
+            //{\r
+            //    hostName = source.Substring(n1, n3 - n1);\r
+            //    boardName = source.Substring(n3 + 1, n4 - (n3 + 1));\r
+            //}\r
+\r
+            return true;\r
+        }\r
+\r
+        private static bool isDatKey(string source, int start, int end)\r
+        {\r
+            if (start < 0 || end >= source.Length)\r
+                return false;\r
+            for (int i = start; i < end; i++)\r
+            {\r
+                char c = source[i];\r
+                switch (getToken(c))\r
+                {\r
+                    case NTHtmlUtils.TOKEN.NUMBER:\r
+                        break;\r
+                    default:\r
+                        return false;\r
+                }\r
+            }\r
+            return true;\r
+        }\r
+\r
+        public static NTHtmlUtils.TOKEN getToken(char c)\r
+        {\r
+            if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'))\r
+            {\r
+                return NTHtmlUtils.TOKEN.ALPHABET;\r
+            }\r
+            else if ('0' <= c && c <= '9')\r
+            {\r
+                return NTHtmlUtils.TOKEN.NUMBER;\r
+                /*}else if(c == '"'){\r
+                    return NTHtmlUtils.TOKEN.DQUART;\r
+                }else if(c == '\''){\r
+                    return NTHtmlUtils.TOKEN.SQUART;\r
+                }else if(c == '<'){\r
+                    return NTHtmlUtils.TOKEN.LT;\r
+                }else if(c == '>'){\r
+                    return NTHtmlUtils.TOKEN.GT;*/\r
+            }\r
+            else if (c == ' ' || c == '\t' || c == '\n')\r
+            {\r
+                return NTHtmlUtils.TOKEN.WHITESPACE;\r
+            }\r
+            else if (c < 0x21 || 0x7e < c)\r
+            {\r
+                return NTHtmlUtils.TOKEN.CONTROL_CODE;\r
+            }\r
+            else if (c > 0x7f)\r
+            {\r
+                return NTHtmlUtils.TOKEN.NON_ASCII;\r
+            }\r
+            else\r
+            {\r
+                return NTHtmlUtils.TOKEN.OTHER;\r
+            }\r
+        }\r
+\r
+        public static int parseWebHost(string source, int start){\r
+               int charCnt = 0;\r
+           NTHtmlUtils.TOKEN previous =  NTHtmlUtils.TOKEN.NOTHING;\r
+           char previousC = '\0';\r
+           bool hasComma = false; // must has a comma at least one;\r
+           bool initFirstChar = false;\r
+           bool hasAlphabet = false;\r
+           int i;\r
+           //DebugUtil.log(source.substring(start));\r
+           //LABEL:\r
+            bool loop = true;\r
+           for( i = start; i < source.Length; i++){\r
+                   //DebugUtil.log(source.substring(i));\r
+                   char c = source[i];\r
+                   NTHtmlUtils.TOKEN token = getToken(c);\r
+                   switch(token){\r
+                   case NTHtmlUtils.TOKEN.ALPHABET:\r
+                           hasAlphabet = true;\r
+                    initFirstChar = true;\r
+                    charCnt++;\r
+                    break;\r
+                case NTHtmlUtils.TOKEN.NUMBER:\r
+                           initFirstChar = true;\r
+                           charCnt++;\r
+                           break;\r
+                   case NTHtmlUtils.TOKEN.CONTROL_CODE:\r
+                    loop = false;\r
+                           break;// LABEL;\r
+                   case NTHtmlUtils.TOKEN.OTHER:\r
+                   default:\r
+                           if(initFirstChar){\r
+                                   // only hyphen allowed in domain name.\r
+                                   if('-' == c){\r
+                                           charCnt++;\r
+                                           break;\r
+                                   }\r
+                                   // not allowed successive comma\r
+                                   if('.' == c && previousC != '.' && previousC != '-'){\r
+                                           charCnt++;\r
+                                           hasComma = true;\r
+                                           break;\r
+                                   }\r
+                           }\r
+                    loop = false;\r
+                           break;// LABEL;\r
+                   }\r
+                if(!loop)\r
+                    break;\r
+                           previous = token;\r
+                           previousC = c;\r
+           }\r
+\r
+           if('-' == previousC || '.' == previousC){\r
+                   charCnt--;\r
+                   i--;\r
+                   previousC = source[i];\r
+           }\r
+       \r
+           // top domain names haven't degits. \r
+           if(NTHtmlUtils.TOKEN.NUMBER == previous && hasAlphabet == true){\r
+                   bool loop2 = true;//LABEL2:\r
+                   for(i--; i > 0; i--){\r
+                           char c = source[i];\r
+                           NTHtmlUtils.TOKEN token = getToken(c);\r
+                           switch(token){\r
+                           case NTHtmlUtils.TOKEN.NUMBER:\r
+                                   charCnt--;\r
+                                   break;\r
+                           case NTHtmlUtils.TOKEN.ALPHABET:\r
+                           default:\r
+                        loop2 = false;\r
+                           break;// LABEL2; \r
+                           }\r
+                    if(!loop2)\r
+                        break;\r
+                           previous = token;\r
+                   }\r
+           }\r
+           return ((NTHtmlUtils.TOKEN.ALPHABET == previous || NTHtmlUtils.TOKEN.NUMBER == previous) && hasComma) ? charCnt : -1;\r
+        }\r
+\r
+\r
+        public static string ridSuffixFromDatName(string datName)\r
+        {\r
+            int n1 = datName.IndexOf(DAT_SUFFIX);\r
+            if (n1 >= 0)\r
+                datName = datName.Substring(0, n1);\r
+            return datName;\r
+        }\r
+        public static string ridSuffixFromCgiName(string cgiName)\r
+        {\r
+            int n1 = cgiName.IndexOf(CGI_SUFFIX);\r
+            if (n1 >= 0)\r
+                cgiName = cgiName.Substring(0, n1);\r
+            return cgiName;\r
+        }\r
+\r
+\r
+    }\r
+}\r
diff --git a/NT2chView45/Properties/AssemblyInfo.cs b/NT2chView45/Properties/AssemblyInfo.cs
new file mode 100755 (executable)
index 0000000..0de59f3
--- /dev/null
@@ -0,0 +1,55 @@
+using System.Reflection;\r
+using System.Resources;\r
+using System.Runtime.CompilerServices;\r
+using System.Runtime.InteropServices;\r
+using System.Windows;\r
+\r
+// アセンブリに関する一般情報は以下の属性セットをとおして制御されます。\r
+// アセンブリに関連付けられている情報を変更するには、\r
+// これらの属性値を変更してください。\r
+[assembly: AssemblyTitle("NT2chView45")]\r
+[assembly: AssemblyDescription("")]\r
+[assembly: AssemblyConfiguration("")]\r
+[assembly: AssemblyCompany("")]\r
+[assembly: AssemblyProduct("NT2chView45")]\r
+[assembly: AssemblyCopyright("Copyright ©  2012")]\r
+[assembly: AssemblyTrademark("")]\r
+[assembly: AssemblyCulture("")]\r
+\r
+// ComVisible を false に設定すると、その型はこのアセンブリ内で COM コンポーネントから\r
+// 参照不可能になります。COM からこのアセンブリ内の型にアクセスする場合は、\r
+// その型の ComVisible 属性を true に設定してください。\r
+[assembly: ComVisible(false)]\r
+\r
+//ローカライズ可能なアプリケーションのビルドを開始するには、\r
+//.csproj ファイルの <UICulture>CultureYouAreCodingWith</UICulture> を\r
+//<PropertyGroup> 内部で設定します。たとえば、\r
+//ソース ファイルで英語を使用している場合、<UICulture> を en-US に設定します。次に、\r
+//下の NeutralResourceLanguage 属性のコメントを解除します。下の行の "en-US" を\r
+//プロジェクト ファイルの UICulture 設定と一致するよう更新します。\r
+\r
+//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]\r
+\r
+\r
+[assembly: ThemeInfo(\r
+    ResourceDictionaryLocation.None, //テーマ固有のリソース ディクショナリが置かれている場所\r
+    //(リソースがページ、\r
+    //またはアプリケーション リソース ディクショナリに見つからない場合に使用されます)\r
+    ResourceDictionaryLocation.SourceAssembly //汎用リソース ディクショナリが置かれている場所\r
+    //(リソースがページ、\r
+    //アプリケーション、またはいずれのテーマ固有のリソース ディクショナリにも見つからない場合に使用されます)\r
+)]\r
+\r
+\r
+// アセンブリのバージョン情報は、以下の 4 つの値で構成されています:\r
+//\r
+//      Major Version\r
+//      Minor Version \r
+//      Build Number\r
+//      Revision\r
+//\r
+// すべての値を指定するか、下のように '*' を使ってビルドおよびリビジョン番号を \r
+// 既定値にすることができます:\r
+// [assembly: AssemblyVersion("1.0.*")]\r
+[assembly: AssemblyVersion("2.3.6.0")]\r
+[assembly: AssemblyFileVersion("2.3.6.0")]\r
diff --git a/NT2chView45/Properties/Resources.Designer.cs b/NT2chView45/Properties/Resources.Designer.cs
new file mode 100755 (executable)
index 0000000..1b05dd7
--- /dev/null
@@ -0,0 +1,63 @@
+//------------------------------------------------------------------------------\r
+// <auto-generated>\r
+//     このコードはツールによって生成されました。\r
+//     ランタイム バージョン:4.0.30319.17626\r
+//\r
+//     このファイルへの変更は、以下の状況下で不正な動作の原因になったり、\r
+//     コードが再生成されるときに損失したりします。\r
+// </auto-generated>\r
+//------------------------------------------------------------------------------\r
+\r
+namespace NT2chView45.Properties {\r
+    using System;\r
+    \r
+    \r
+    /// <summary>\r
+    ///   ローカライズされた文字列などを検索するための、厳密に型指定されたリソース クラスです。\r
+    /// </summary>\r
+    // このクラスは StronglyTypedResourceBuilder クラスが ResGen\r
+    // または Visual Studio のようなツールを使用して自動生成されました。\r
+    // メンバーを追加または削除するには、.ResX ファイルを編集して、/str オプションと共に\r
+    // ResGen を実行し直すか、または VS プロジェクトをビルドし直します。\r
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]\r
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\r
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]\r
+    internal class Resources {\r
+        \r
+        private static global::System.Resources.ResourceManager resourceMan;\r
+        \r
+        private static global::System.Globalization.CultureInfo resourceCulture;\r
+        \r
+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]\r
+        internal Resources() {\r
+        }\r
+        \r
+        /// <summary>\r
+        ///   このクラスで使用されているキャッシュされた ResourceManager インスタンスを返します。\r
+        /// </summary>\r
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]\r
+        internal static global::System.Resources.ResourceManager ResourceManager {\r
+            get {\r
+                if (object.ReferenceEquals(resourceMan, null)) {\r
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("NT2chView45.Properties.Resources", typeof(Resources).Assembly);\r
+                    resourceMan = temp;\r
+                }\r
+                return resourceMan;\r
+            }\r
+        }\r
+        \r
+        /// <summary>\r
+        ///   厳密に型指定されたこのリソース クラスを使用して、すべての検索リソースに対し、\r
+        ///   現在のスレッドの CurrentUICulture プロパティをオーバーライドします。\r
+        /// </summary>\r
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]\r
+        internal static global::System.Globalization.CultureInfo Culture {\r
+            get {\r
+                return resourceCulture;\r
+            }\r
+            set {\r
+                resourceCulture = value;\r
+            }\r
+        }\r
+    }\r
+}\r
diff --git a/NT2chView45/Properties/Resources.resx b/NT2chView45/Properties/Resources.resx
new file mode 100755 (executable)
index 0000000..ffecec8
--- /dev/null
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<root>\r
+  <!-- \r
+    Microsoft ResX Schema \r
+    \r
+    Version 2.0\r
+    \r
+    The primary goals of this format is to allow a simple XML format \r
+    that is mostly human readable. The generation and parsing of the \r
+    various data types are done through the TypeConverter classes \r
+    associated with the data types.\r
+    \r
+    Example:\r
+    \r
+    ... ado.net/XML headers & schema ...\r
+    <resheader name="resmimetype">text/microsoft-resx</resheader>\r
+    <resheader name="version">2.0</resheader>\r
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\r
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\r
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>\r
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>\r
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">\r
+        <value>[base64 mime encoded serialized .NET Framework object]</value>\r
+    </data>\r
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">\r
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\r
+        <comment>This is a comment</comment>\r
+    </data>\r
+                \r
+    There are any number of "resheader" rows that contain simple \r
+    name/value pairs.\r
+    \r
+    Each data row contains a name, and value. The row also contains a \r
+    type or mimetype. Type corresponds to a .NET class that support \r
+    text/value conversion through the TypeConverter architecture. \r
+    Classes that don't support this are serialized and stored with the \r
+    mimetype set.\r
+    \r
+    The mimetype is used for serialized objects, and tells the \r
+    ResXResourceReader how to depersist the object. This is currently not \r
+    extensible. For a given mimetype the value must be set accordingly:\r
+    \r
+    Note - application/x-microsoft.net.object.binary.base64 is the format \r
+    that the ResXResourceWriter will generate, however the reader can \r
+    read any of the formats listed below.\r
+    \r
+    mimetype: application/x-microsoft.net.object.binary.base64\r
+    value   : The object must be serialized with \r
+            : System.Serialization.Formatters.Binary.BinaryFormatter\r
+            : and then encoded with base64 encoding.\r
+    \r
+    mimetype: application/x-microsoft.net.object.soap.base64\r
+    value   : The object must be serialized with \r
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\r
+            : and then encoded with base64 encoding.\r
+\r
+    mimetype: application/x-microsoft.net.object.bytearray.base64\r
+    value   : The object must be serialized into a byte array \r
+            : using a System.ComponentModel.TypeConverter\r
+            : and then encoded with base64 encoding.\r
+    -->\r
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">\r
+    <xsd:element name="root" msdata:IsDataSet="true">\r
+      <xsd:complexType>\r
+        <xsd:choice maxOccurs="unbounded">\r
+          <xsd:element name="metadata">\r
+            <xsd:complexType>\r
+              <xsd:sequence>\r
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />\r
+              </xsd:sequence>\r
+              <xsd:attribute name="name" type="xsd:string" />\r
+              <xsd:attribute name="type" type="xsd:string" />\r
+              <xsd:attribute name="mimetype" type="xsd:string" />\r
+            </xsd:complexType>\r
+          </xsd:element>\r
+          <xsd:element name="assembly">\r
+            <xsd:complexType>\r
+              <xsd:attribute name="alias" type="xsd:string" />\r
+              <xsd:attribute name="name" type="xsd:string" />\r
+            </xsd:complexType>\r
+          </xsd:element>\r
+          <xsd:element name="data">\r
+            <xsd:complexType>\r
+              <xsd:sequence>\r
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />\r
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />\r
+              </xsd:sequence>\r
+              <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />\r
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />\r
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />\r
+            </xsd:complexType>\r
+          </xsd:element>\r
+          <xsd:element name="resheader">\r
+            <xsd:complexType>\r
+              <xsd:sequence>\r
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />\r
+              </xsd:sequence>\r
+              <xsd:attribute name="name" type="xsd:string" use="required" />\r
+            </xsd:complexType>\r
+          </xsd:element>\r
+        </xsd:choice>\r
+      </xsd:complexType>\r
+    </xsd:element>\r
+  </xsd:schema>\r
+  <resheader name="resmimetype">\r
+    <value>text/microsoft-resx</value>\r
+  </resheader>\r
+  <resheader name="version">\r
+    <value>2.0</value>\r
+  </resheader>\r
+  <resheader name="reader">\r
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\r
+  </resheader>\r
+  <resheader name="writer">\r
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\r
+  </resheader>\r
+</root>
\ No newline at end of file
diff --git a/NT2chView45/Properties/Settings.Designer.cs b/NT2chView45/Properties/Settings.Designer.cs
new file mode 100755 (executable)
index 0000000..977d1e4
--- /dev/null
@@ -0,0 +1,26 @@
+//------------------------------------------------------------------------------\r
+// <auto-generated>\r
+//     このコードはツールによって生成されました。\r
+//     ランタイム バージョン:4.0.30319.17626\r
+//\r
+//     このファイルへの変更は、以下の状況下で不正な動作の原因になったり、\r
+//     コードが再生成されるときに損失したりします。\r
+// </auto-generated>\r
+//------------------------------------------------------------------------------\r
+\r
+namespace NT2chView45.Properties {\r
+    \r
+    \r
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]\r
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]\r
+    internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {\r
+        \r
+        private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));\r
+        \r
+        public static Settings Default {\r
+            get {\r
+                return defaultInstance;\r
+            }\r
+        }\r
+    }\r
+}\r
diff --git a/NT2chView45/Properties/Settings.settings b/NT2chView45/Properties/Settings.settings
new file mode 100755 (executable)
index 0000000..8f2fd95
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version='1.0' encoding='utf-8'?>\r
+<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">\r
+  <Profiles>\r
+    <Profile Name="(Default)" />\r
+  </Profiles>\r
+  <Settings />\r
+</SettingsFile>
\ No newline at end of file
diff --git a/NT2chView45/app.config b/NT2chView45/app.config
new file mode 100755 (executable)
index 0000000..b7a7ef1
--- /dev/null
@@ -0,0 +1,3 @@
+<?xml version="1.0"?>\r
+<configuration>\r
+<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/></startup></configuration>\r
diff --git a/NT2chView45/images/left.png b/NT2chView45/images/left.png
new file mode 100755 (executable)
index 0000000..f1c0738
Binary files /dev/null and b/NT2chView45/images/left.png differ
diff --git a/NT2chView45/images/neetchan2.png b/NT2chView45/images/neetchan2.png
new file mode 100755 (executable)
index 0000000..f75c383
Binary files /dev/null and b/NT2chView45/images/neetchan2.png differ
diff --git a/NT2chView45/images/right.png b/NT2chView45/images/right.png
new file mode 100755 (executable)
index 0000000..4133ab1
Binary files /dev/null and b/NT2chView45/images/right.png differ
diff --git a/NT2chView45/images/search_btn.png b/NT2chView45/images/search_btn.png
new file mode 100755 (executable)
index 0000000..e3c419e
Binary files /dev/null and b/NT2chView45/images/search_btn.png differ
diff --git a/NT2chView45/neetchan6.ico b/NT2chView45/neetchan6.ico
new file mode 100755 (executable)
index 0000000..0b7ed28
Binary files /dev/null and b/NT2chView45/neetchan6.ico differ