• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

タイニー番組ナビゲータ本体


Commit MetaInfo

Revision783555a783ea9612c144ed1585a4da0b92236748 (tree)
Zeit2018-09-07 22:10:32
AutorMasahiko Kimura <mkimura@u01....>
CommiterMasahiko Kimura

Log Message

Ver.1.8 (2018/09/07):

  1. [Web番組表取得]ステータスウインドウ右肩の「×」ボタンで取得処理を中止できるようにする
  2. [Web番組表取得]バックグランドで取得が行えるようにする
  3. [Web番組表取得]決まった時刻(複数指定可)に取得が行えるようにする
  4. [Web番組表取得]エラーになっても表示中の番組表に影響しないようにする

Ändern Zusammenfassung

Diff

Binary files /dev/null and b/TinyBannavi/icon/stop-news-reader.png differ
--- a/TinyBannavi/src/tainavi/AbsPaperView.java
+++ b/TinyBannavi/src/tainavi/AbsPaperView.java
@@ -1342,7 +1342,7 @@ public abstract class AbsPaperView extends JPanel implements TickTimerListener,H
13421342
13431343 // 第1階層のノード、第2階層のノード名を取得する
13441344 JTreeLabel.Nodes node1 = JTreeLabel.Nodes.getNode(path.getPathComponent(1).toString());
1345- String node2 = path.getPathComponent(2).toString();
1345+ String node2 = path.getPathCount() > 2 ? path.getPathComponent(2).toString() : "";
13461346
13471347 // 当日の日付を計算する
13481348 int correct = 0; // 24:00-28:59迄は前日の日付になる
@@ -2441,21 +2441,18 @@ public abstract class AbsPaperView extends JPanel implements TickTimerListener,H
24412441 }
24422442 }
24432443 else if (e.getButton() == MouseEvent.BUTTON1) {
2444- // 過去ログは閲覧のみ
2445- if (tvd.type == ProgType.PASSED) {
2446- if (e.getClickCount() == 2) {
2447- MWin.appendMessage(MSGID+"過去ログでダブルクリックは利用できません");
2448- ringBeep();
2449- }
2450-
2451- return;
2452- }
2453-
24542444 if ( e.getClickCount() == 1 ) {
24552445 // 番組詳細表示のロック or 解除(トグル)
24562446 setDetailInfo(tvd, tvd != detailInfoData);
24572447 }
24582448 else if (e.getClickCount() == 2) {
2449+ // 過去ログは閲覧のみ
2450+ if (tvd.type == ProgType.PASSED) {
2451+ MWin.appendMessage(MSGID+"過去ログでダブルクリックは利用できません");
2452+ ringBeep();
2453+ return;
2454+ }
2455+
24592456 // 左ダブルクリックで予約ウィンドウを開く
24602457 openReserveDialog(tvd);
24612458 }
--- a/TinyBannavi/src/tainavi/AbsSettingView.java
+++ b/TinyBannavi/src/tainavi/AbsSettingView.java
@@ -55,7 +55,7 @@ public abstract class AbsSettingView extends JScrollPane {
5555
5656 private static final long serialVersionUID = 1L;
5757
58- public static String getViewName() { return "各種設定"; }
58+ public static String getViewName() { return "各種設定"; }
5959
6060 public void setDebug(boolean b) { debug = b; }
6161 private static boolean debug = false;
@@ -63,19 +63,19 @@ public abstract class AbsSettingView extends JScrollPane {
6363 /*******************************************************************************
6464 * 抽象メソッド
6565 ******************************************************************************/
66-
66+
6767 protected abstract Env getEnv();
6868 protected abstract ClipboardInfoList getCbItemEnv();
69-
69+
7070 protected abstract VWLookAndFeel getLAFEnv();
7171 protected abstract VWFont getFontEnv();
72-
73- protected abstract StatusWindow getStWin();
72+
73+ protected abstract StatusWindow getStWin();
7474 protected abstract StatusTextArea getMWin();
75-
75+
7676 protected abstract Component getParentComponent();
77- protected abstract VWColorChooserDialog getCcWin();
78-
77+ protected abstract VWColorChooserDialog getCcWin();
78+
7979 protected abstract void lafChanged(String lafname);
8080 protected abstract void fontChanged(String fn, int fontSize);
8181 protected abstract void setEnv(boolean reload_prog);
@@ -83,23 +83,23 @@ public abstract class AbsSettingView extends JScrollPane {
8383 /*******************************************************************************
8484 * 呼び出し元から引き継いだもの
8585 ******************************************************************************/
86-
86+
8787 // オブジェクト
8888 private final Env env = getEnv();
8989 private final ClipboardInfoList cbitems = getCbItemEnv();
90-
90+
9191 private final StatusWindow StWin = getStWin(); // これは起動時に作成されたまま変更されないオブジェクト
9292 private final StatusTextArea MWin = getMWin(); // これは起動時に作成されたまま変更されないオブジェクト
93-
93+
9494 private final Component parent = getParentComponent(); // これは起動時に作成されたまま変更されないオブジェクト
9595 private final VWColorChooserDialog ccwin = getCcWin(); // これは起動時に作成されたまま変更されないオブジェクト
96-
96+
9797 // 雑多なメソッド
9898 private void StdAppendMessage(String message) { System.out.println(message); }
9999 //private void StdAppendError(String message) { System.err.println(message); }
100100 private void StWinSetVisible(boolean b) { StWin.setVisible(b); }
101101 private void StWinSetLocationCenter(Component frame) { CommonSwingUtils.setLocationCenter(frame, (VWStatusWindow)StWin); }
102-
102+
103103 /*******************************************************************************
104104 * 定数
105105 ******************************************************************************/
@@ -112,21 +112,21 @@ public abstract class AbsSettingView extends JScrollPane {
112112 private static final int SEP_HEIGHT = 10;
113113 private static final int SEP_HEIGHT_NALLOW = 5;
114114 private static final int BLOCK_SEP_HEIGHT = 75;
115-
115+
116116 private static final int LABEL_WIDTH = 350;
117117 private static final int CCLABEL_WIDTH = 250;
118118 private static final int DESCRIPTION_WIDTH = LABEL_WIDTH+PARTS_WIDTH;
119119
120120 private static final int UPDATE_WIDTH = 250;
121121 private static final int HINT_WIDTH = 700;
122-
122+
123123 private static final int PANEL_WIDTH = LABEL_WIDTH+PARTS_WIDTH+SEP_WIDTH*3;
124-
124+
125125 //
126-
126+
127127 private static final Color NOTICEMSG_COLOR = new Color(0,153,153);
128128 // テキスト
129-
129+
130130 private static final String TEXT_HINT =
131131 "各項目の詳細はプロジェクトWikiに説明があります(http://sourceforge.jp/projects/tainavi/wiki/)。"+
132132 "ツールバーのヘルプアイコンをクリックするとブラウザで開きます。";
@@ -140,18 +140,18 @@ public abstract class AbsSettingView extends JScrollPane {
140140 private static final String MSGID = "["+getViewName()+"] ";
141141 private static final String ERRID = "[ERROR]"+MSGID;
142142 private static final String DBGID = "[DEBUG]"+MSGID;
143-
143+
144144 /*******************************************************************************
145145 * 部品
146146 ******************************************************************************/
147-
147+
148148 // コンポーネント
149-
149+
150150 private JPanel jPanel_setting = null;
151-
151+
152152 private JPanel jPanel_update = null;
153153 private JButton jButton_update = null;
154-
154+
155155 // リスト形式
156156 private JCheckBoxPanel jCBP_disableFazzySearch = null;
157157 private JCheckBoxPanel jCBP_disableFazzySearchReverse = null;
@@ -180,7 +180,7 @@ public abstract class AbsSettingView extends JScrollPane {
180180 private JComboBoxPanel jCBX_dblClkCmd = null;
181181 private JSliderPanel jSP_searchResultMax = null;
182182 private JSliderPanel jSP_searchResultBufferMax = null;
183-
183+
184184 // 新聞形式
185185 private JRadioButtonPanel jRBP_getPaperRedrawType = null;
186186 private JSliderPanel jSP_centerPerPage = null;
@@ -193,7 +193,7 @@ public abstract class AbsSettingView extends JScrollPane {
193193 private JCheckBoxPanel jCBP_effectComboToPaper = null;
194194 private JComboBoxPanel jCBX_snapshotFmt = null;
195195 private JCheckBoxPanel jCBP_printSnapshot = null;
196-
196+
197197 // リスト・新聞共通
198198 private JCheckBoxPanel jCBP_displayOnlyExecOnEntry = null;
199199 private JCheckBoxPanel jCBP_displayPassedReserve = null;
@@ -219,7 +219,7 @@ public abstract class AbsSettingView extends JScrollPane {
219219 private JButton jButton_midel = null;
220220 private JButton jButton_miup = null;
221221 private JButton jButton_midown = null;
222-
222+
223223 // Web番組表対応
224224 private JCheckBoxPanel jCBP_continueTomorrow = null;
225225 private JSliderPanel jSP_cacheTimeLimit = null;
@@ -242,13 +242,16 @@ public abstract class AbsSettingView extends JScrollPane {
242242 private JCheckBoxPanel jCBP_historyOnlyUpdateOnce = null;
243243 private JCheckBoxPanel jCBP_usePassedProgram = null;
244244 private JSliderPanel jSP_prepPassedProgramCount = null;
245-
245+ private JCheckBoxPanel jCBP_downloadProgramOnFixedTime = null;
246+ private JCheckBoxPanel jCBP_downloadProgramInBackground = null;
247+ private JTextFieldWithPopup jTextField_downloadProgramTimeList = null;
248+
246249 // レコーダ対応
247250 private JRadioButtonPanel jRBP_getRdReserveDetails = null;
248251 private JRadioButtonPanel jRBP_getRdAutoReserves = null;
249252 private JRadioButtonPanel jRBP_getRdRecorded = null;
250253 private JComboBoxPanel jCBX_recordedSaveScope = null;
251-
254+
252255 // 予約
253256 private JSliderPanel jSP_spoex_extend = null;
254257 private JRadioButtonPanel jRBP_overlapUp = null;
@@ -269,7 +272,7 @@ public abstract class AbsSettingView extends JScrollPane {
269272 private JLabel jLabel_rsv_recedcolor = null;
270273 private JCCLabel jCCL_rsv_recedcolor = null;
271274 private JCheckBoxPanel jCBP_useAutocomplete = null;
272-
275+
273276 // その他
274277 private JComboBoxPanel jCBX_updateMethod = null;
275278 private JCheckBoxPanel jCBP_disableBeep = null;
@@ -289,45 +292,45 @@ public abstract class AbsSettingView extends JScrollPane {
289292 private JTextAreaWithPopup jta_help = null;
290293
291294 // コンポーネント以外
292-
295+
293296 /**
294297 * 特定のコンポーネントを操作した時だけ番組表を再取得してほしい
295298 */
296299 private boolean reload_prog_needed = false;
297-
300+
298301 /*******************************************************************************
299302 * コンストラクタ
300303 ******************************************************************************/
301-
304+
302305 public AbsSettingView() {
303-
306+
304307 super();
305-
308+
306309 this.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
307310 this.getVerticalScrollBar().setUnitIncrement(25);
308311 this.setColumnHeaderView(getJPanel_update());
309312 this.setViewportView(getJPanel_setting());
310-
313+
311314 setUpdateButtonEnhanced(false);
312315 }
313-
316+
314317 private JPanel getJPanel_update() {
315318 if (jPanel_update == null)
316319 {
317320 jPanel_update = new JPanel();
318321 jPanel_update.setLayout(new SpringLayout());
319-
322+
320323 jPanel_update.setBorder(new LineBorder(Color.GRAY));
321-
324+
322325 int y = SEP_HEIGHT;
323326 CommonSwingUtils.putComponentOn(jPanel_update, getJButton_update("更新を確定する"), UPDATE_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
324-
327+
325328 int yz = SEP_HEIGHT/2;
326329 int x = UPDATE_WIDTH+50;
327330 CommonSwingUtils.putComponentOn(jPanel_update, getJta_help(), HINT_WIDTH, PARTS_HEIGHT+SEP_HEIGHT, x, yz);
328-
331+
329332 y += (PARTS_HEIGHT + SEP_HEIGHT);
330-
333+
331334 // 画面の全体サイズを決める
332335 Dimension d = new Dimension(PANEL_WIDTH,y);
333336 jPanel_update.setPreferredSize(d);
@@ -352,14 +355,14 @@ public abstract class AbsSettingView extends JScrollPane {
352355 {
353356 jPanel_setting = new JPanel();
354357 jPanel_setting.setLayout(new SpringLayout());
355-
358+
356359 //
357360 int y = SEP_HEIGHT;
358-
361+
359362 /*
360- * リスト形式
363+ * リスト形式
361364 */
362-
365+
363366 y+=0;
364367 CommonSwingUtils.putComponentOn(jPanel_setting, new JLabel("<<<リスト形式>>>"), LABEL_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
365368
@@ -368,7 +371,7 @@ public abstract class AbsSettingView extends JScrollPane {
368371 CommonSwingUtils.putComponentOn(jPanel_setting, jCBP_disableFazzySearch = new JCheckBoxPanel("番組追跡であいまい検索をしない",LABEL_WIDTH), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
369372 jCBP_disableFazzySearch.setSelected( ! env.getDisableFazzySearch());
370373 // RELOADリスナー不要
371-
374+
372375 y+=(PARTS_HEIGHT+SEP_HEIGHT);
373376 CommonSwingUtils.putComponentOn(jPanel_setting, jCBP_disableFazzySearchReverse = new JCheckBoxPanel("┗ あいまい検索の逆引きを省略(非推奨)",LABEL_WIDTH), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
374377 jCBP_disableFazzySearchReverse.setSelected(env.getDisableFazzySearchReverse());
@@ -378,11 +381,11 @@ public abstract class AbsSettingView extends JScrollPane {
378381 CommonSwingUtils.putComponentOn(jPanel_setting, jSP_defaultFazzyThreshold = new JSliderPanel("┗ あいまい検索のデフォルト閾値",LABEL_WIDTH,1,99,200), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
379382 jSP_defaultFazzyThreshold.setValue(env.getDefaultFazzyThreshold());
380383 // RELOADリスナー不要
381-
384+
382385 // 連動設定(Fire!がキモイ…)
383-
386+
384387 jCBP_disableFazzySearch.addItemListener(al_fazzysearch);
385-
388+
386389 jCBP_disableFazzySearch.setSelected( ! jCBP_disableFazzySearch.isSelected());
387390 }
388391
@@ -394,12 +397,12 @@ public abstract class AbsSettingView extends JScrollPane {
394397 CommonSwingUtils.putComponentOn(jPanel_setting, getNoticeMsg(" 逆順を有効にすると、正順でNG判定になった場合に前者と後者を入れ替えて再判定を行います。取りこぼしが減る場合がある反面、検索ノイズが増える場合もあります。"), DESCRIPTION_WIDTH, PARTS_HEIGHT, SEP_WIDTH*2, y);
395398 y+=(PARTS_HEIGHT);
396399 CommonSwingUtils.putComponentOn(jPanel_setting, getNoticeMsg(" 閾値を大きくすると判定が厳しくなります。キーワードが短いためにヒットしまくりで検索ノイズが多くなった場合に、値を大きくしてみてください。"), DESCRIPTION_WIDTH, PARTS_HEIGHT, SEP_WIDTH*2, y);
397-
400+
398401 y+=(PARTS_HEIGHT+SEP_HEIGHT);
399402 CommonSwingUtils.putComponentOn(jPanel_setting, jCBP_traceOnlyTitle = new JCheckBoxPanel("タイトル中に含まれるサブタイトルは番組追跡の対象にしない",LABEL_WIDTH), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
400403 jCBP_traceOnlyTitle.setSelected(env.getTraceOnlyTitle());
401404 jCBP_traceOnlyTitle.addItemListener(IL_RELOAD_PROG_NEEDED);
402-
405+
403406 y+=(PARTS_HEIGHT+SEP_HEIGHT);
404407 CommonSwingUtils.putComponentOn(jPanel_setting, jCBP_syoboFilterByCenters = new JCheckBoxPanel("しょぼかるの検索結果も有効な放送局のみに絞る",LABEL_WIDTH), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
405408 jCBP_syoboFilterByCenters.setSelected(env.getSyoboFilterByCenters());
@@ -440,14 +443,14 @@ public abstract class AbsSettingView extends JScrollPane {
440443 CommonSwingUtils.putComponentOn(jPanel_setting, jLabel_pickedLineColor = new JLabel("┗ ピックアップ行の背景色"), LABEL_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
441444 CommonSwingUtils.putComponentOn(jPanel_setting, jCCL_pickedLineColor = new JCCLabel("ピックアップ行の背景色",env.getPickedLineColor(),true,parent,ccwin), CCLABEL_WIDTH, PARTS_HEIGHT, LABEL_WIDTH+SEP_WIDTH, y);
442445 // RELOADリスナー不要
443-
446+
444447 // 連動設定
445-
448+
446449 jCBP_rsvdLineEnhance.addItemListener(al_rsvdlineenhance);
447-
450+
448451 jCBP_rsvdLineEnhance.setSelected( ! jCBP_rsvdLineEnhance.isSelected());
449452 }
450-
453+
451454 {
452455 y+=(PARTS_HEIGHT+SEP_HEIGHT);
453456 CommonSwingUtils.putComponentOn(jPanel_setting, jCBP_currentLineEnhance = new JCheckBoxPanel("現在放送中の行の背景色を変えて強調する",LABEL_WIDTH), LABEL_WIDTH+PARTS_HEIGHT, PARTS_HEIGHT, SEP_WIDTH, y);
@@ -458,50 +461,50 @@ public abstract class AbsSettingView extends JScrollPane {
458461 CommonSwingUtils.putComponentOn(jPanel_setting, jLabel_currentLineColor = new JLabel("┗ 現在放送中行の背景色"), LABEL_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
459462 CommonSwingUtils.putComponentOn(jPanel_setting, jCCL_currentLineColor = new JCCLabel("現在放送中行の背景色",env.getCurrentLineColor(),true,parent,ccwin), CCLABEL_WIDTH, PARTS_HEIGHT, LABEL_WIDTH+SEP_WIDTH, y);
460463 // RELOADリスナー不要
461-
464+
462465 // 連動設定
463-
466+
464467 jCBP_currentLineEnhance.addItemListener(al_currentlineenhance);
465-
468+
466469 jCBP_currentLineEnhance.setSelected( ! jCBP_currentLineEnhance.isSelected());
467470 }
468-
471+
469472 y+=(PARTS_HEIGHT+SEP_HEIGHT);
470473 CommonSwingUtils.putComponentOn(jPanel_setting, jSP_currentAfter = new JSliderPanel("現在放送中ノードに終了後何分までの番組を表示するか",LABEL_WIDTH,0,60,200), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
471474 jSP_currentAfter.setValue(env.getCurrentAfter()/60);
472475 // RELOADリスナー不要
473-
476+
474477 y+=(PARTS_HEIGHT+SEP_HEIGHT);
475478 CommonSwingUtils.putComponentOn(jPanel_setting, jSP_currentBefore = new JSliderPanel("現在放送中ノードに開始前何分までの番組を表示するか",LABEL_WIDTH,0,120,200), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
476479 jSP_currentBefore.setValue(env.getCurrentBefore()/60);
477480 // RELOADリスナー不要
478-
481+
479482 //
480483 y+=(PARTS_HEIGHT+SEP_HEIGHT);
481484 CommonSwingUtils.putComponentOn(jPanel_setting, new JLabel("タイトル中のキーワードにマッチした箇所の強調色"), LABEL_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
482485 CommonSwingUtils.putComponentOn(jPanel_setting, jCCL_matchedKeywordColor = new JCCLabel("強調色",env.getMatchedKeywordColor(),false,parent,ccwin), CCLABEL_WIDTH, PARTS_HEIGHT, LABEL_WIDTH+SEP_WIDTH, y);
483486 // RELOADリスナー不要
484-
487+
485488 y+=(PARTS_HEIGHT+SEP_HEIGHT);
486489 CommonSwingUtils.putComponentOn(jPanel_setting, jCBP_showWarnDialog = new JCheckBoxPanel("キーワード削除時に確認ダイアログを表示",LABEL_WIDTH), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
487490 jCBP_showWarnDialog.setSelected(env.getShowWarnDialog());
488491 // RELOADリスナー不要
489-
492+
490493 y+=(PARTS_HEIGHT+SEP_HEIGHT);
491494 CommonSwingUtils.putComponentOn(jPanel_setting, jCBP_splitMarkAndTitle = new JCheckBoxPanel("オプション表示を個別欄に分離表示",LABEL_WIDTH), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
492495 jCBP_splitMarkAndTitle.setSelected(env.getSplitMarkAndTitle());
493496 // RELOADリスナー不要
494-
497+
495498 y+=(PARTS_HEIGHT+SEP_HEIGHT);
496499 CommonSwingUtils.putComponentOn(jPanel_setting, jCBP_showDetailOnList = new JCheckBoxPanel("番組詳細列を表示",LABEL_WIDTH), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
497500 jCBP_showDetailOnList.setSelected(env.getShowDetailOnList());
498501 // RELOADリスナー不要
499-
502+
500503 y+=(PARTS_HEIGHT+SEP_HEIGHT);
501504 CommonSwingUtils.putComponentOn(jPanel_setting, jCBP_rowHeaderVisible = new JCheckBoxPanel("行番号を表示",LABEL_WIDTH), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
502505 jCBP_rowHeaderVisible.setSelected(env.getRowHeaderVisible());
503506 // RELOADリスナー不要
504-
507+
505508 y+=(PARTS_HEIGHT+SEP_HEIGHT);
506509 CommonSwingUtils.putComponentOn(jPanel_setting, jSP_rsvTargets = new JSliderPanel("予約待機の予約番組自動選択数",LABEL_WIDTH,1,99,200), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
507510 jSP_rsvTargets.setValue(env.getRsvTargets());
@@ -514,7 +517,7 @@ public abstract class AbsSettingView extends JScrollPane {
514517 }
515518 jCBX_dblClkCmd.setSelectedItem(env.getDblClkCmd());
516519 // RELOADリスナー不要
517-
520+
518521 y+=(PARTS_HEIGHT+SEP_HEIGHT);
519522 CommonSwingUtils.putComponentOn(jPanel_setting, jSP_searchResultMax = new JSliderPanel("過去ログ検索件数の上限",LABEL_WIDTH,10,500,200), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
520523 jSP_searchResultMax.setValue(env.getSearchResultMax());
@@ -526,12 +529,12 @@ public abstract class AbsSettingView extends JScrollPane {
526529 // RELOADリスナー不要
527530
528531 /*
529- * 新聞形式
532+ * 新聞形式
530533 */
531-
534+
532535 y+=(PARTS_HEIGHT+BLOCK_SEP_HEIGHT);
533536 CommonSwingUtils.putComponentOn(jPanel_setting, new JLabel("<<<新聞形式>>>"), LABEL_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
534-
537+
535538 {
536539 y+=(PARTS_HEIGHT+SEP_HEIGHT);
537540 int paperredraw_h = PARTS_HEIGHT*3+SEP_HEIGHT_NALLOW*2;
@@ -540,20 +543,20 @@ public abstract class AbsSettingView extends JScrollPane {
540543 jRBP_getPaperRedrawType.add(PARER_REDRAW_CACHE, false);
541544 jRBP_getPaperRedrawType.add(PARER_REDRAW_PAGER, false);
542545 // RELOADリスナー不要
543-
546+
544547 y+=(paperredraw_h+SEP_HEIGHT);
545548 CommonSwingUtils.putComponentOn(jPanel_setting, jSP_centerPerPage = new JSliderPanel("┗ ページあたりの放送局数",LABEL_WIDTH,1,99,200), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
546549 jSP_centerPerPage.setValue(env.getCenterPerPage());
547550 // RELOADリスナー不要
548-
551+
549552 y+=(PARTS_HEIGHT+SEP_HEIGHT);
550553 CommonSwingUtils.putComponentOn(jPanel_setting, jCBP_allPageSnapshot = new JCheckBoxPanel("┗ スナップショットを全ページ連続で実行",LABEL_WIDTH), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
551554 jCBP_allPageSnapshot.setSelected(env.getAllPageSnapshot());
552555 // RELOADリスナー不要
553-
556+
554557 // 連動設定(1)
555558 jRBP_getPaperRedrawType.addItemListener(il_paperredrawtype);
556-
559+
557560 if ( env.isPagerEnabled() ) {
558561 jRBP_getPaperRedrawType.setSelectedItem(PARER_REDRAW_PAGER);
559562 }
@@ -583,19 +586,19 @@ public abstract class AbsSettingView extends JScrollPane {
583586 CommonSwingUtils.putComponentOn(jPanel_setting, jSP_tooltipDismissDelay = new JSliderPanel("┗ 消去までの遅延(ミリ秒)",LABEL_WIDTH,1000,60000,100,200), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
584587 jSP_tooltipDismissDelay.setValue(env.getTooltipDismissDelay());
585588 // RELOADリスナー不要
586-
589+
587590 // 連動設定
588591
589592 jCBP_tooltipEnable.addItemListener(al_tooltipenable);
590-
593+
591594 jCBP_tooltipEnable.setSelected( ! jCBP_tooltipEnable.isSelected());
592595 }
593-
596+
594597 y+=(PARTS_HEIGHT+SEP_HEIGHT);
595598 CommonSwingUtils.putComponentOn(jPanel_setting, jCBP_timerbarScrollEnable = new JCheckBoxPanel("現在時刻線を固定し番組表側をスクロール",LABEL_WIDTH), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
596599 jCBP_timerbarScrollEnable.setSelected(env.getTimerbarScrollEnable());
597600 // RELOADリスナー不要
598-
601+
599602 y+=(PARTS_HEIGHT+SEP_HEIGHT);
600603 CommonSwingUtils.putComponentOn(jPanel_setting, jSP_passedLogLimit = new JSliderPanel("過去ログの日付ノードの表示数",LABEL_WIDTH,7,180,200), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
601604 jSP_passedLogLimit.setValue(env.getPassedLogLimit());
@@ -605,12 +608,12 @@ public abstract class AbsSettingView extends JScrollPane {
605608 CommonSwingUtils.putComponentOn(jPanel_setting, jCBP_effectComboToPaper = new JCheckBoxPanel("レコーダコンボボックスを新聞形式でも有効に",LABEL_WIDTH), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
606609 jCBP_effectComboToPaper.setSelected(env.getEffectComboToPaper());
607610 // RELOADリスナー不要
608-
609-
611+
612+
610613 /*
611- * リスト・新聞形式共通
614+ * リスト・新聞形式共通
612615 */
613-
616+
614617 y+=(PARTS_HEIGHT+BLOCK_SEP_HEIGHT);
615618 CommonSwingUtils.putComponentOn(jPanel_setting, new JLabel("<<<リスト・新聞形式共通>>>"), LABEL_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
616619
@@ -618,7 +621,7 @@ public abstract class AbsSettingView extends JScrollPane {
618621 CommonSwingUtils.putComponentOn(jPanel_setting, jCBP_displayOnlyExecOnEntry = new JCheckBoxPanel("実行ONの予約のみ予約マークを表示する",LABEL_WIDTH), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
619622 jCBP_displayOnlyExecOnEntry.setSelected(env.getDisplayOnlyExecOnEntry());
620623 // RELOADリスナー不要
621-
624+
622625 y+=(PARTS_HEIGHT+SEP_HEIGHT);
623626 CommonSwingUtils.putComponentOn(jPanel_setting, jCBP_displayPassedReserve = new JCheckBoxPanel("当日の終了済み予約も表示する",LABEL_WIDTH), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
624627 jCBP_displayPassedReserve.setSelected(env.getDisplayPassedReserve());
@@ -633,7 +636,7 @@ public abstract class AbsSettingView extends JScrollPane {
633636 CommonSwingUtils.putComponentOn(jPanel_setting, jCBP_adjLateNight = new JCheckBoxPanel("【RD】深夜の帯予約を前にずらす(火~土→月~金)",LABEL_WIDTH), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
634637 jCBP_adjLateNight.setSelected(env.getAdjLateNight());
635638 // RELOADリスナー不要
636-
639+
637640 y+=(PARTS_HEIGHT+SEP_HEIGHT);
638641 CommonSwingUtils.putComponentOn(jPanel_setting, getNoticeMsg("※月~金26:00の帯番組は、実際には火~土AM2:00に放送されますので鯛ナビでもそのように帯予約を処理しています。"), DESCRIPTION_WIDTH, PARTS_HEIGHT, SEP_WIDTH*2, y);
639642 y+=(PARTS_HEIGHT);
@@ -643,17 +646,17 @@ public abstract class AbsSettingView extends JScrollPane {
643646 CommonSwingUtils.putComponentOn(jPanel_setting, jCBP_rootNodeVisible = new JCheckBoxPanel("ツリーペーンにrootノードを表示させる",LABEL_WIDTH), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
644647 jCBP_rootNodeVisible.setSelected(env.getRootNodeVisible());
645648 // RELOADリスナー不要
646-
649+
647650 y+=(PARTS_HEIGHT+SEP_HEIGHT);
648651 CommonSwingUtils.putComponentOn(jPanel_setting, jCBP_syncTreeWidth = new JCheckBoxPanel("リスト形式と新聞形式のツリーペーンの幅を同期する",LABEL_WIDTH), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
649652 jCBP_syncTreeWidth.setSelected(env.getSyncTreeWidth());
650653 // RELOADリスナー不要
651-
654+
652655 y+=(PARTS_HEIGHT+SEP_HEIGHT);
653656 CommonSwingUtils.putComponentOn(jPanel_setting, jCBP_shortExtMark = new JCheckBoxPanel("「★延長注意★」を「(延)」に短縮表示",LABEL_WIDTH), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
654657 jCBP_shortExtMark.setSelected(env.getShortExtMark());
655658 // RELOADリスナー不要
656-
659+
657660 y+=(PARTS_HEIGHT+SEP_HEIGHT);
658661 CommonSwingUtils.putComponentOn(jPanel_setting, jCBX_snapshotFmt = new JComboBoxPanel("スナップショットの画像形式",LABEL_WIDTH,250,true), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
659662 for ( SnapshotFmt s : SnapshotFmt.values() ) {
@@ -661,18 +664,18 @@ public abstract class AbsSettingView extends JScrollPane {
661664 }
662665 jCBX_snapshotFmt.setSelectedItem(env.getSnapshotFmt());
663666 // RELOADリスナー不要
664-
667+
665668 y+=(PARTS_HEIGHT+SEP_HEIGHT);
666669 CommonSwingUtils.putComponentOn(jPanel_setting, jCBP_printSnapshot = new JCheckBoxPanel("スナップショットボタンで印刷を実行する",LABEL_WIDTH), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
667670 jCBP_printSnapshot.setSelected(env.getPrintSnapshot());
668671 // RELOADリスナー不要
669-
672+
670673 y+=(PARTS_HEIGHT+SEP_HEIGHT);
671- int marks_h = PARTS_HEIGHT*12;
674+ int marks_h = PARTS_HEIGHT*12;
672675 CommonSwingUtils.putComponentOn(jPanel_setting, getJLabel_showmarks("表示マークの選択"), LABEL_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
673676 CommonSwingUtils.putComponentOn(jPanel_setting, getJScrollPane_showmarks(), 320, marks_h, LABEL_WIDTH+SEP_WIDTH, y);
674677 // ★★★ RELOADリスナーは getJScrollPane_showmarks()内でつける
675-
678+
676679 y+=(marks_h+SEP_HEIGHT);
677680 int cbitems_w = 320;
678681 int cbitems_h = PARTS_HEIGHT*8;
@@ -681,7 +684,7 @@ public abstract class AbsSettingView extends JScrollPane {
681684 CommonSwingUtils.putComponentOn(jPanel_setting, getJButton_clipboard_down("↓"), 50, PARTS_HEIGHT, LABEL_WIDTH+SEP_WIDTH+10+cbitems_w, y+PARTS_HEIGHT+SEP_WIDTH);
682685 CommonSwingUtils.putComponentOn(jPanel_setting, getJScrollPane_clipboard(), cbitems_w, cbitems_h, LABEL_WIDTH+SEP_WIDTH, y);
683686 // RELOADリスナー不要
684-
687+
685688 y += (cbitems_h + SEP_HEIGHT);
686689 int mitable_h = PARTS_HEIGHT*8;
687690 {
@@ -702,17 +705,17 @@ public abstract class AbsSettingView extends JScrollPane {
702705 }
703706
704707 /*
705- * Web番組表対応
708+ * Web番組表対応
706709 */
707-
710+
708711 y+=(mitable_h+BLOCK_SEP_HEIGHT);
709712 CommonSwingUtils.putComponentOn(jPanel_setting, new JLabel("<<<Web番組表対応>>>"), LABEL_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
710-
713+
711714 y+=(PARTS_HEIGHT+SEP_HEIGHT);
712715 CommonSwingUtils.putComponentOn(jPanel_setting, jCBP_continueTomorrow = new JCheckBoxPanel("29時をまたぐ番組を検出し同一視する",LABEL_WIDTH), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
713716 jCBP_continueTomorrow.setSelected(env.getContinueTomorrow());
714717 jCBP_continueTomorrow.addItemListener(IL_RELOAD_PROG_NEEDED);
715-
718+
716719 {
717720 y+=(PARTS_HEIGHT+SEP_HEIGHT);
718721 CommonSwingUtils.putComponentOn(jPanel_setting, jSP_cacheTimeLimit = new JSliderPanel("番組表キャッシュの有効時間(0:無制限)",LABEL_WIDTH,0,72,200), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
@@ -729,17 +732,17 @@ public abstract class AbsSettingView extends JScrollPane {
729732 // RELOADリスナー不要
730733
731734 // 連動設定
732-
735+
733736 jSP_cacheTimeLimit.addChangeListener(cl_cachetimelimit);
734-
737+
735738 jSP_cacheTimeLimit.setValue(env.getCacheTimeLimit());
736739 }
737-
740+
738741 y+=(PARTS_HEIGHT+SEP_HEIGHT);
739742 CommonSwingUtils.putComponentOn(jPanel_setting, getNoticeMsg("※起動時に、Web番組表の再取得を自動で「実行させたくない」場合は0にしてください。"), DESCRIPTION_WIDTH, PARTS_HEIGHT, SEP_WIDTH*2, y);
740743 y+=(PARTS_HEIGHT);
741744 CommonSwingUtils.putComponentOn(jPanel_setting, getNoticeMsg("※シャットダウンコマンドを設定すると、Web番組表取得メニューに「CSのみ取得(取得後シャットダウン)」が追加されます。"), DESCRIPTION_WIDTH, PARTS_HEIGHT, SEP_WIDTH*2, y);
742-
745+
743746 y+=(PARTS_HEIGHT+SEP_HEIGHT);
744747 CommonSwingUtils.putComponentOn(jPanel_setting, jCBP_expandTo8 = new JCheckBoxPanel("可能なら番組表を8日分取得する",LABEL_WIDTH), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
745748 jCBP_expandTo8.setSelected(env.getExpandTo8());
@@ -754,85 +757,107 @@ public abstract class AbsSettingView extends JScrollPane {
754757 CommonSwingUtils.putComponentOn(jPanel_setting, jCBP_splitEpno = new JCheckBoxPanel("タイトルに話数が含まれる場合に以降を分離する",LABEL_WIDTH), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
755758 jCBP_splitEpno.setSelected(env.getSplitEpno());
756759 jCBP_splitEpno.addItemListener(IL_RELOAD_PROG_NEEDED);
757-
760+
758761 y+=(PARTS_HEIGHT+SEP_HEIGHT);
759762 CommonSwingUtils.putComponentOn(jPanel_setting, jCBP_fixTitle = new JCheckBoxPanel("タイトル先頭の「アニメ 」を削除(NHKのみ)",LABEL_WIDTH), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
760763 jCBP_fixTitle.setSelected(env.getFixTitle());
761764 jCBP_fixTitle.addItemListener(IL_RELOAD_PROG_NEEDED);
762-
765+
763766 y +=(PARTS_HEIGHT+SEP_HEIGHT);
764767 CommonSwingUtils.putComponentOn(jPanel_setting, getJLabel_ngword("NGワード(;区切りで複数指定可)"), LABEL_WIDTH,PARTS_HEIGHT, SEP_WIDTH, y);
765768 CommonSwingUtils.putComponentOn(jPanel_setting, getJTextField_ngword(CommonUtils.joinStr(";", env.getNgword())),600, PARTS_HEIGHT, LABEL_WIDTH+SEP_WIDTH, y);
766769 jTextField_ngword.getDocument().addDocumentListener(DL_RELOAD_PROG_NEEDED);
767-
768-
770+
771+
769772 y+=(PARTS_HEIGHT+SEP_HEIGHT);
770773 CommonSwingUtils.putComponentOn(jPanel_setting, getJLabel_userAgent("User-Agent"), LABEL_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
771774 CommonSwingUtils.putComponentOn(jPanel_setting, getJTextField_userAgent(env.getUserAgent()), 600, PARTS_HEIGHT, LABEL_WIDTH+SEP_WIDTH, y);
772775 // RELOADリスナー不要
773-
776+
774777 {
775778 y+=(PARTS_HEIGHT+SEP_HEIGHT);
776779 CommonSwingUtils.putComponentOn(jPanel_setting, jCBP_useProxy = new JCheckBoxPanel("HTTPプロキシを有効にする",LABEL_WIDTH), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
777780 jCBP_useProxy.setSelected( ! env.getUseProxy());
778781 // RELOADリスナー不要
779-
782+
780783 y+=(PARTS_HEIGHT+SEP_HEIGHT);
781784 CommonSwingUtils.putComponentOn(jPanel_setting, getJLabel_proxy("┗ HTTPプロキシ/ポート"), LABEL_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
782785 CommonSwingUtils.putComponentOn(jPanel_setting, getJTextField_proxyAddr(env.getProxyAddr()), 200, PARTS_HEIGHT, LABEL_WIDTH+SEP_WIDTH, y);
783786 CommonSwingUtils.putComponentOn(jPanel_setting, getJTextField_proxyPort(env.getProxyPort()), 100, PARTS_HEIGHT, LABEL_WIDTH+SEP_WIDTH+210, y);
784787 // RELOADリスナー不要
785-
788+
786789 // 連動設定
787790
788791 jCBP_useProxy.addItemListener(al_useproxy);
789792
790793 jCBP_useProxy.setSelected( ! jCBP_useProxy.isSelected());
791794 }
792-
795+
793796 y+=(PARTS_HEIGHT+SEP_HEIGHT);
794797 CommonSwingUtils.putComponentOn(jPanel_setting, jCBP_useSyobocal = new JCheckBoxPanel("【アニメ】しょぼいカレンダーを利用する",LABEL_WIDTH), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
795798 jCBP_useSyobocal.setSelected(env.getUseSyobocal());
796799 jCBP_useSyobocal.addItemListener(IL_RELOAD_PROG_NEEDED);
797-
800+
798801 y+=(PARTS_HEIGHT+SEP_HEIGHT);
799802 CommonSwingUtils.putComponentOn(jPanel_setting, getNoticeMsg("※アニメなんか興味ないよ!という場合はチェックを外して再起動してください。"), DESCRIPTION_WIDTH, PARTS_HEIGHT, SEP_WIDTH*2, y);
800-
803+
801804 y+=(PARTS_HEIGHT+SEP_HEIGHT);
802805 CommonSwingUtils.putComponentOn(jPanel_setting, jCBP_historyOnlyUpdateOnce = new JCheckBoxPanel("日に一回しか新着履歴を更新しない",LABEL_WIDTH), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
803806 jCBP_historyOnlyUpdateOnce.setSelected(env.getHistoryOnlyUpdateOnce());
804807 // RELOADリスナー不要
805-
808+
806809 {
807810 y+=(PARTS_HEIGHT+SEP_HEIGHT);
808811 CommonSwingUtils.putComponentOn(jPanel_setting, jCBP_usePassedProgram = new JCheckBoxPanel("過去ログを記録する",LABEL_WIDTH), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
809812 jCBP_usePassedProgram.setSelected( ! env.getUsePassedProgram());
810813 // RELOADリスナー不要
811-
814+
812815 y+=(PARTS_HEIGHT+SEP_HEIGHT);
813816 CommonSwingUtils.putComponentOn(jPanel_setting, jSP_prepPassedProgramCount = new JSliderPanel("┗ 何日先のログまで過去ログ用に保存するか",LABEL_WIDTH,1,8,200), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
814817 jSP_prepPassedProgramCount.setValue(env.getPrepPassedProgramCount());
815818 // RELOADリスナー不要
816-
819+
817820 y+=(PARTS_HEIGHT+SEP_HEIGHT);
818821 CommonSwingUtils.putComponentOn(jPanel_setting, getNoticeMsg("※保存期間を4日先までにして1週間旅行に出かけると7日-4日=3日分の過去ログがロストすることになります。"), DESCRIPTION_WIDTH, PARTS_HEIGHT, SEP_WIDTH*2, y);
819-
822+
820823 // 連動設定
821-
824+
822825 jCBP_usePassedProgram.addItemListener(al_usepassedprogram);
823-
826+
824827 jCBP_usePassedProgram.setSelected( ! jCBP_usePassedProgram.isSelected());
825828 }
826-
829+
830+ {
831+ y+=(PARTS_HEIGHT+SEP_HEIGHT);
832+ CommonSwingUtils.putComponentOn(jPanel_setting, jCBP_downloadProgramOnFixedTime = new JCheckBoxPanel("決まった時刻に番組表を取得する",LABEL_WIDTH), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
833+ jCBP_downloadProgramOnFixedTime.setSelected( ! env.getDownloadProgramOnFixedTime());
834+ // RELOADリスナー不要
835+
836+ y+=(PARTS_HEIGHT+SEP_HEIGHT);
837+ CommonSwingUtils.putComponentOn(jPanel_setting, new JLabel("┗ 取得時刻(HH:MM形式 ;区切りで複数指定可)"), LABEL_WIDTH,PARTS_HEIGHT, SEP_WIDTH, y);
838+ CommonSwingUtils.putComponentOn(jPanel_setting, getJTextField_downloadProgramTimeList(CommonUtils.joinStr(";", env.getDownloadProgramTimeList())),600, PARTS_HEIGHT, LABEL_WIDTH+SEP_WIDTH, y);
839+ // RELOADリスナー不要
840+
841+ y+=(PARTS_HEIGHT+SEP_HEIGHT);
842+ CommonSwingUtils.putComponentOn(jPanel_setting, jCBP_downloadProgramInBackground = new JCheckBoxPanel("バックグランドで取得する",LABEL_WIDTH), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
843+ jCBP_downloadProgramInBackground.setSelected(env.getDownloadProgramInBackground());
844+ // RELOADリスナー不要
845+
846+ // 連動設定
847+ jCBP_downloadProgramOnFixedTime.addItemListener(al_downloadProgramOnFixedTime);
848+ jCBP_downloadProgramOnFixedTime.setSelected( ! jCBP_downloadProgramOnFixedTime.isSelected());
849+ }
850+
851+
827852 /*
828- * レコーダ対応
853+ * レコーダ対応
829854 */
830855
831856 y+=(PARTS_HEIGHT+BLOCK_SEP_HEIGHT);
832857 CommonSwingUtils.putComponentOn(jPanel_setting, new JLabel("<<<レコーダ対応>>>"), LABEL_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
833-
858+
834859 int getdetail_h = PARTS_HEIGHT*3+SEP_HEIGHT_NALLOW*2;
835-
860+
836861 {
837862 y+=(PARTS_HEIGHT+SEP_HEIGHT);
838863 CommonSwingUtils.putComponentOn(jPanel_setting, jRBP_getRdReserveDetails = new JRadioButtonPanel("予約一覧取得時に詳細情報も取得する",LABEL_WIDTH), PARTS_WIDTH, getdetail_h, SEP_WIDTH, y);
@@ -840,28 +865,28 @@ public abstract class AbsSettingView extends JScrollPane {
840865 jRBP_getRdReserveDetails.add("常に取得する",false);
841866 jRBP_getRdReserveDetails.add("常に取得しない",false);
842867 // RELOADリスナー不要
843-
868+
844869 y+=(getdetail_h+SEP_HEIGHT);
845870 CommonSwingUtils.putComponentOn(jPanel_setting, jRBP_getRdAutoReserves = new JRadioButtonPanel("予約一覧取得時に自動予約一覧も取得する",LABEL_WIDTH), PARTS_WIDTH, getdetail_h, SEP_WIDTH, y);
846871 jRBP_getRdAutoReserves.add("毎回確認する",true);
847872 jRBP_getRdAutoReserves.add("常に取得する",false);
848873 jRBP_getRdAutoReserves.add("常に取得しない",false);
849874 // RELOADリスナー不要
850-
875+
851876 y+=(getdetail_h+SEP_HEIGHT);
852877 CommonSwingUtils.putComponentOn(jPanel_setting, jRBP_getRdRecorded = new JRadioButtonPanel("予約一覧取得時に録画結果一覧も取得する",LABEL_WIDTH), PARTS_WIDTH, getdetail_h, SEP_WIDTH, y);
853878 jRBP_getRdRecorded.add("毎回確認する",true);
854879 jRBP_getRdRecorded.add("常に取得する",false);
855880 jRBP_getRdRecorded.add("常に取得しない",false);
856881 // RELOADリスナー不要
857-
882+
858883 // 選択肢
859884 updateSelections();
860-
885+
861886 y+=(getdetail_h+SEP_HEIGHT);
862887 CommonSwingUtils.putComponentOn(jPanel_setting, getNoticeMsg("※「常に取得しない」を選択した場合でも、ツールバーのプルダウンメニューから強制的に取得を実行できます。"), DESCRIPTION_WIDTH, PARTS_HEIGHT, SEP_WIDTH*2, y);
863888 }
864-
889+
865890 y+=(PARTS_HEIGHT+SEP_HEIGHT);
866891 CommonSwingUtils.putComponentOn(jPanel_setting, jCBX_recordedSaveScope = new JComboBoxPanel("録画結果一覧の保存期間",LABEL_WIDTH,250,true), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
867892 jCBX_recordedSaveScope.addItem("保存しない");
@@ -870,22 +895,22 @@ public abstract class AbsSettingView extends JScrollPane {
870895 }
871896 jCBX_recordedSaveScope.setSelectedIndex(env.getRecordedSaveScope());
872897 // RELOADリスナー不要
873-
898+
874899 y+=(getdetail_h+SEP_HEIGHT);
875900 CommonSwingUtils.putComponentOn(jPanel_setting, new JLabel("NULLプラグインでのカレンダ連携設定はレコーダ設定に移動しました"), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
876-
901+
877902 /*
878903 * 予約
879904 */
880905
881906 y+=(75+BLOCK_SEP_HEIGHT);
882907 CommonSwingUtils.putComponentOn(jPanel_setting, new JLabel("<<<予約>>>"), LABEL_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
883-
908+
884909 y+=(PARTS_HEIGHT+SEP_HEIGHT);
885910 CommonSwingUtils.putComponentOn(jPanel_setting, jSP_spoex_extend = new JSliderPanel("延長警告の録画時間延長幅(分)",LABEL_WIDTH,0,180,200), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
886911 jSP_spoex_extend.setValue(Integer.valueOf(env.getSpoexLength()));
887912 // RELOADリスナー不要
888-
913+
889914 y+=(PARTS_HEIGHT+SEP_HEIGHT);
890915 int ovarlap_h = PARTS_HEIGHT*2+SEP_HEIGHT_NALLOW*1;
891916 CommonSwingUtils.putComponentOn(jPanel_setting, jRBP_overlapUp = new JRadioButtonPanel("録画時間の前",LABEL_WIDTH), PARTS_WIDTH, ovarlap_h, SEP_WIDTH, y);
@@ -910,12 +935,12 @@ public abstract class AbsSettingView extends JScrollPane {
910935 CommonSwingUtils.putComponentOn(jPanel_setting, getJLabel_enableCHAVsetting("AV自動設定キーをジャンルからCHに"), LABEL_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
911936 CommonSwingUtils.putComponentOn(jPanel_setting, getJCheckBox_enableCHAVsetting(env.getEnableCHAVsetting()), 100, PARTS_HEIGHT, LABEL_WIDTH+SEP_WIDTH, y);
912937 // RELOADリスナー不要
913-
938+
914939 y+=(PARTS_HEIGHT+SEP_HEIGHT);
915940 CommonSwingUtils.putComponentOn(jPanel_setting, jSP_rangeLikeRsv = new JSliderPanel("類似予約の検索時間範囲(0:無制限)",LABEL_WIDTH,0,24,200), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
916941 jSP_rangeLikeRsv.setValue(env.getRangeLikeRsv());
917942 // RELOADリスナー不要
918-
943+
919944 {
920945 y+=(PARTS_HEIGHT+SEP_HEIGHT);
921946 CommonSwingUtils.putComponentOn(jPanel_setting, jCBP_givePriorityToReserved = new JCheckBoxPanel("類似予約がある場合は情報を引き継ぐ",LABEL_WIDTH), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
@@ -926,58 +951,58 @@ public abstract class AbsSettingView extends JScrollPane {
926951 CommonSwingUtils.putComponentOn(jPanel_setting, jCBP_givePriorityToReservedTitle = new JCheckBoxPanel("┗ 類似予約のタイトルを引き継ぐ",LABEL_WIDTH), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
927952 jCBP_givePriorityToReservedTitle.setSelected(env.getGivePriorityToReservedTitle());
928953 // RELOADリスナー不要
929-
954+
930955 // 連動設定
931956
932957 jCBP_givePriorityToReserved.addItemListener(al_giveprioritytoreserved);
933-
958+
934959 jCBP_givePriorityToReserved.setSelected( ! jCBP_givePriorityToReserved.isSelected());
935960 }
936-
961+
937962 y+=(PARTS_HEIGHT+SEP_HEIGHT);
938963 CommonSwingUtils.putComponentOn(jPanel_setting, jCBP_adjoiningNotRepetition = new JCheckBoxPanel("終了時刻と開始時刻が重なる番組でも重複扱いしない",LABEL_WIDTH), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
939964 jCBP_adjoiningNotRepetition.setSelected(env.getAdjoiningNotRepetition());
940965 // RELOADリスナー不要
941-
966+
942967 {
943968 y+=(PARTS_HEIGHT+SEP_HEIGHT);
944969 CommonSwingUtils.putComponentOn(jPanel_setting, jCBP_rsv_showallite = new JCheckBoxPanel("予約一覧で繰り返し予約を展開する",LABEL_WIDTH), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
945970 jCBP_rsv_showallite.setSelected( ! env.getShowAllIterationItem());
946971 // RELOADリスナー不要
947-
972+
948973 y+=(PARTS_HEIGHT+SEP_HEIGHT);
949974 CommonSwingUtils.putComponentOn(jPanel_setting, jLabel_rsv_itecolor = new JLabel("┗ 展開した繰り返し予約の2回目以降の文字色"), LABEL_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
950975 CommonSwingUtils.putComponentOn(jPanel_setting, jCCL_rsv_itecolor = new JCCLabel("文字色",env.getIterationItemForeground(),false,parent,ccwin), CCLABEL_WIDTH, PARTS_HEIGHT, LABEL_WIDTH+SEP_WIDTH, y);
951976 // RELOADリスナー不要
952-
977+
953978 jCBP_rsv_showallite.addItemListener(al_showallite);
954-
979+
955980 // Fire!
956981 jCBP_rsv_showallite.setSelected( ! jCBP_rsv_showallite.isSelected());
957982 }
958-
983+
959984 y+=(PARTS_HEIGHT+SEP_HEIGHT);
960985 CommonSwingUtils.putComponentOn(jPanel_setting, jLabel_rsv_tunshortcolor = new JLabel("チューナー不足警告の背景色"), LABEL_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
961986 CommonSwingUtils.putComponentOn(jPanel_setting, jCCL_rsv_tunshortcolor = new JCCLabel("チューナー不足警告の背景色",env.getTunerShortColor(),true,parent,ccwin), CCLABEL_WIDTH, PARTS_HEIGHT, LABEL_WIDTH+SEP_WIDTH, y);
962987 // RELOADリスナー不要
963-
988+
964989 y+=(PARTS_HEIGHT+SEP_HEIGHT);
965990 CommonSwingUtils.putComponentOn(jPanel_setting, getNoticeMsg("※チューナー不足警告は、レコーダの予約一覧上に表示される警告情報を反映しています。"), DESCRIPTION_WIDTH, PARTS_HEIGHT, SEP_WIDTH*2, y);
966991 y+=(PARTS_HEIGHT);
967992 CommonSwingUtils.putComponentOn(jPanel_setting, getNoticeMsg("※EDCBの場合、チューナー不足警告は鯛ナビからの予約アクションでは更新されませんので、必要に応じて予約一覧の再取得を行って更新してください。"), DESCRIPTION_WIDTH, PARTS_HEIGHT, SEP_WIDTH*2, y);
968-
993+
969994 y+=(PARTS_HEIGHT+SEP_HEIGHT);
970995 CommonSwingUtils.putComponentOn(jPanel_setting, jLabel_rsv_recedcolor = new JLabel("正常録画済み(と思われる)予約の背景色"), LABEL_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
971996 CommonSwingUtils.putComponentOn(jPanel_setting, jCCL_rsv_recedcolor = new JCCLabel("正常録画済み(と思われる)予約の背景色",env.getRecordedColor(),true,parent,ccwin), CCLABEL_WIDTH, PARTS_HEIGHT, LABEL_WIDTH+SEP_WIDTH, y);
972997 // RELOADリスナー不要
973-
998+
974999 y+=(PARTS_HEIGHT+SEP_HEIGHT);
9751000 CommonSwingUtils.putComponentOn(jPanel_setting, jCBP_useAutocomplete = new JCheckBoxPanel("【RD】タイトル自動補完機能を使用する",LABEL_WIDTH), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
9761001 jCBP_useAutocomplete.setSelected(env.getUseAutocomplete());
9771002 // RELOADリスナー不要
978-
1003+
9791004 /*
980- * その他
1005+ * その他
9811006 */
9821007
9831008 y+=(PARTS_HEIGHT+BLOCK_SEP_HEIGHT);
@@ -990,7 +1015,7 @@ public abstract class AbsSettingView extends JScrollPane {
9901015 }
9911016 jCBX_updateMethod.setSelectedItem(env.getUpdateMethod());
9921017 // RELOADリスナー不要
993-
1018+
9941019 y+=(PARTS_HEIGHT+SEP_HEIGHT);
9951020 CommonSwingUtils.putComponentOn(jPanel_setting, jCBP_disableBeep = new JCheckBoxPanel("beep禁止",LABEL_WIDTH), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
9961021 jCBP_disableBeep.setSelected(env.getDisableBeep());
@@ -1006,11 +1031,11 @@ public abstract class AbsSettingView extends JScrollPane {
10061031 CommonSwingUtils.putComponentOn(jPanel_setting, jCBP_hideToTray = new JCheckBoxPanel("┗ 最小化時はシステムトレイに隠す",LABEL_WIDTH), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
10071032 jCBP_hideToTray.setSelected(env.getHideToTray());
10081033 // RELOADリスナー不要
1009-
1034+
10101035 // 連動設定
10111036
10121037 jCBP_showSysTray.addItemListener(al_showsystray);
1013-
1038+
10141039 jCBP_showSysTray.setSelected( ! jCBP_showSysTray.isSelected());
10151040 }
10161041
@@ -1018,69 +1043,69 @@ public abstract class AbsSettingView extends JScrollPane {
10181043 CommonSwingUtils.putComponentOn(jPanel_setting, jCBP_onlyOneInstance = new JCheckBoxPanel("多重起動禁止(要再起動)",LABEL_WIDTH), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
10191044 jCBP_onlyOneInstance.setSelected(env.getOnlyOneInstance());
10201045 // RELOADリスナー不要
1021-
1046+
10221047 y+=(PARTS_HEIGHT+SEP_HEIGHT);
10231048 CommonSwingUtils.putComponentOn(jPanel_setting, getJLabel_lookAndFeel("ルック&フィール"), LABEL_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
10241049 CommonSwingUtils.putComponentOn(jPanel_setting, getJComboBox_lookAndFeel(), 250, PARTS_HEIGHT, LABEL_WIDTH+SEP_WIDTH, y);
10251050 // RELOADリスナー不要
1026-
1051+
10271052 y+=(PARTS_HEIGHT+SEP_HEIGHT);
10281053 CommonSwingUtils.putComponentOn(jPanel_setting, getJLabel_font("表示フォント"), LABEL_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
10291054 CommonSwingUtils.putComponentOn(jPanel_setting, getJComboBox_font(), 250, PARTS_HEIGHT, LABEL_WIDTH+SEP_WIDTH, y);
10301055 CommonSwingUtils.putComponentOn(jPanel_setting, getJComboBox_fontSize(), 100, PARTS_HEIGHT, LABEL_WIDTH+SEP_WIDTH+260, y);
10311056 // RELOADリスナー不要
1032-
1057+
10331058 y+=(PARTS_HEIGHT+SEP_HEIGHT);
10341059 CommonSwingUtils.putComponentOn(jPanel_setting, new JLabel("┗ 表示サンプル"), LABEL_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
10351060 CommonSwingUtils.putComponentOn(jPanel_setting, getJLabel_fontSample(""), 360, PARTS_HEIGHT, LABEL_WIDTH+SEP_WIDTH, y);
1036-
1061+
10371062 y+=(PARTS_HEIGHT+SEP_HEIGHT);
10381063 CommonSwingUtils.putComponentOn(jPanel_setting, jCBP_useGTKRC = new JCheckBoxPanel("鯛ナビ専用のgtkrcを使う",LABEL_WIDTH), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
10391064 jCBP_useGTKRC.setSelected(env.getUseGTKRC());
1040-
1065+
10411066 y+=(PARTS_HEIGHT+SEP_HEIGHT);
10421067 CommonSwingUtils.putComponentOn(jPanel_setting, getNoticeMsg("※ルック&フィールがGTKの場合は再起動するまで表示フォントの設定は反映されません(@see env/_gtkrc-2.0)"), DESCRIPTION_WIDTH, PARTS_HEIGHT, SEP_WIDTH*2, y);
1043-
1068+
10441069 y+=(PARTS_HEIGHT+SEP_HEIGHT);
10451070 CommonSwingUtils.putComponentOn(jPanel_setting, jCBP_useRundll32 = new JCheckBoxPanel("【Win】ファイルオープンにrundll32を使用する",LABEL_WIDTH), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
10461071 jCBP_useRundll32.setSelected(env.getUseRundll32());
10471072 // RELOADリスナー不要
1048-
1073+
10491074 y+=(PARTS_HEIGHT+SEP_HEIGHT);
10501075 CommonSwingUtils.putComponentOn(jPanel_setting, jCBP_debug = new JCheckBoxPanel("【注意】デバッグログ出力を有効にする",LABEL_WIDTH), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
10511076 jCBP_debug.setSelected(env.getDebug());
10521077 // RELOADリスナー不要
10531078
10541079 y += (PARTS_HEIGHT + 50);
1055-
1080+
10561081 // 画面の全体サイズを決める
10571082 Dimension d = new Dimension(PANEL_WIDTH,y);
10581083 jPanel_setting.setPreferredSize(d);
10591084 }
1060-
1085+
10611086 return jPanel_setting;
10621087 }
1063-
1088+
10641089 /*******************************************************************************
10651090 * アクション
10661091 ******************************************************************************/
1067-
1092+
10681093 // 更新確定ボタン押下時の処理
10691094 private void updateEnvs() {
1070-
1095+
10711096 TatCount tc = new TatCount();
1072-
1097+
10731098 StWin.clear();
1074-
1099+
10751100 new SwingBackgroundWorker(false) {
1076-
1101+
10771102 @Override
10781103 protected Object doWorks() throws Exception {
1079-
1104+
10801105 StWin.appendMessage(MSGID+"設定を保存します");
1081-
1106+
10821107 int idx;
1083-
1108+
10841109 // リスト形式
10851110 env.setDisableFazzySearch(jCBP_disableFazzySearch.isSelected());
10861111 env.setDisableFazzySearchReverse(jCBP_disableFazzySearchReverse.isSelected());
@@ -1106,7 +1131,7 @@ public abstract class AbsSettingView extends JScrollPane {
11061131 env.setDblClkCmd((DblClkCmd) jCBX_dblClkCmd.getSelectedItem());
11071132 env.setSearchResultMax(jSP_searchResultMax.getValue());
11081133 env.setSearchResultBufferMax(jSP_searchResultBufferMax.getValue());
1109-
1134+
11101135 // 新聞形式関連
11111136 {
11121137 String selected = jRBP_getPaperRedrawType.getSelectedItem().getText();
@@ -1132,7 +1157,7 @@ public abstract class AbsSettingView extends JScrollPane {
11321157 env.setEffectComboToPaper(jCBP_effectComboToPaper.isSelected());
11331158 env.setSnapshotFmt((SnapshotFmt) jCBX_snapshotFmt.getSelectedItem());
11341159 env.setPrintSnapshot(jCBP_printSnapshot.isSelected());
1135-
1160+
11361161 // リスト・新聞形式共通
11371162 env.setDisplayOnlyExecOnEntry(jCBP_displayOnlyExecOnEntry.isSelected());
11381163 env.setDisplayPassedReserve(jCBP_displayPassedReserve.isSelected());
@@ -1156,7 +1181,7 @@ public abstract class AbsSettingView extends JScrollPane {
11561181 tv.setValue((String) jTable_mitable.getValueAt(row, 1));
11571182 env.getTvCommand().add(tv);
11581183 }
1159-
1184+
11601185 // Web番組表対応
11611186 env.setContinueTomorrow(jCBP_continueTomorrow.isSelected());
11621187 env.setCacheTimeLimit(jSP_cacheTimeLimit.getValue());
@@ -1182,13 +1207,16 @@ public abstract class AbsSettingView extends JScrollPane {
11821207 env.setHistoryOnlyUpdateOnce(jCBP_historyOnlyUpdateOnce.isSelected());
11831208 env.setUsePassedProgram(jCBP_usePassedProgram.isSelected());
11841209 env.setPrepPassedProgramCount(jSP_prepPassedProgramCount.getValue());
1185-
1210+ env.setDownloadProgramOnFixedTime(jCBP_downloadProgramOnFixedTime.isSelected());
1211+ env.setDownloadProgramInBackground(jCBP_downloadProgramInBackground.isSelected());
1212+ env.setDownloadProgramTimeList(jTextField_downloadProgramTimeList.getText());
1213+
11861214 // レコーダ対応
11871215 env.setForceLoadReserveDetails(jRBP_getRdReserveDetails.getSelectedIndex());
11881216 env.setForceLoadAutoReserves(jRBP_getRdAutoReserves.getSelectedIndex());
11891217 env.setForceLoadRecorded(jRBP_getRdRecorded.getSelectedIndex());
11901218 env.setRecordedSaveScope(jCBX_recordedSaveScope.getSelectedIndex());
1191-
1219+
11921220 // 予約
11931221 env.setSpoexLength(String.format("%d",jSP_spoex_extend.getValue()));
11941222 idx = jRBP_overlapUp.getSelectedIndex();
@@ -1226,7 +1254,7 @@ public abstract class AbsSettingView extends JScrollPane {
12261254 env.setTunerShortColor(jCCL_rsv_tunshortcolor.getChoosed());
12271255 env.setRecordedColor(jCCL_rsv_recedcolor.getChoosed());
12281256 env.setUseAutocomplete(jCBP_useAutocomplete.isSelected());
1229-
1257+
12301258 // その他の設定
12311259 env.setUpdateMethod((UpdateOn) jCBX_updateMethod.getSelectedItem());
12321260 env.setDisableBeep(jCBP_disableBeep.isSelected());
@@ -1239,14 +1267,14 @@ public abstract class AbsSettingView extends JScrollPane {
12391267 env.setUseGTKRC(jCBP_useGTKRC.isSelected());
12401268 env.setUseRundll32(jCBP_useRundll32.isSelected());
12411269 env.setDebug(jCBP_debug.isSelected());
1242-
1270+
12431271 // 設定保存
12441272 setEnv(reload_prog_needed);
12451273 setUpdateButtonEnhanced(false);
1246-
1274+
12471275 return null;
12481276 }
1249-
1277+
12501278 @Override
12511279 protected void doFinally() {
12521280 StWinSetVisible(false);
@@ -1255,10 +1283,10 @@ public abstract class AbsSettingView extends JScrollPane {
12551283
12561284 StWinSetLocationCenter(parent);
12571285 StWinSetVisible(true);
1258-
1286+
12591287 MWin.appendMessage(String.format(MSGID+"更新が完了しました。所要時間: %.2f秒",tc.end()));
12601288 }
1261-
1289+
12621290 /**
12631291 * 各種設定タブ以外で変更したenvの内容をタブに反映する
12641292 */
@@ -1267,19 +1295,19 @@ public abstract class AbsSettingView extends JScrollPane {
12671295 jRBP_getRdAutoReserves.setSelectedIndex(env.getForceLoadAutoReserves());
12681296 jRBP_getRdRecorded.setSelectedIndex(env.getForceLoadRecorded());
12691297 }
1270-
1298+
12711299 /*******************************************************************************
12721300 * リスナー
12731301 ******************************************************************************/
1274-
1302+
12751303 /*
12761304 * 連動
12771305 */
1278-
1306+
12791307 /**
12801308 * 変更があった場合に番組表のリロードを要求するコンポーネントにつけるリスナー
12811309 */
1282-
1310+
12831311 private void setUpdateButtonEnhanced(boolean b) {
12841312 if (b) {
12851313 jButton_update.setText("更新時番組表再取得あり");
@@ -1291,7 +1319,7 @@ public abstract class AbsSettingView extends JScrollPane {
12911319 }
12921320 reload_prog_needed = b;
12931321 }
1294-
1322+
12951323 private final ItemListener IL_RELOAD_PROG_NEEDED = new ItemListener() {
12961324 @Override
12971325 public void itemStateChanged(ItemEvent e) {
@@ -1322,7 +1350,7 @@ public abstract class AbsSettingView extends JScrollPane {
13221350 if (debug) System.err.println(DBGID+"MODIFIED");
13231351 setUpdateButtonEnhanced(true);
13241352 }
1325-
1353+
13261354 @Override
13271355 public void editingCanceled(ChangeEvent e) {
13281356 }
@@ -1354,7 +1382,7 @@ public abstract class AbsSettingView extends JScrollPane {
13541382 jCCL_rsvdLineColor.setEnabled(true);
13551383 jLabel_pickedLineColor.setEnabled(true);
13561384 jCCL_pickedLineColor.setEnabled(true);
1357-
1385+
13581386 }
13591387 else {
13601388 jLabel_rsvdLineColor.setEnabled(false);
@@ -1364,7 +1392,7 @@ public abstract class AbsSettingView extends JScrollPane {
13641392 }
13651393 }
13661394 };
1367-
1395+
13681396 // 現在放送中行の背景色
13691397 ItemListener al_currentlineenhance = new ItemListener() {
13701398 @Override
@@ -1373,7 +1401,7 @@ public abstract class AbsSettingView extends JScrollPane {
13731401 if (jCBP_currentLineEnhance.isSelected()) {
13741402 jLabel_currentLineColor.setEnabled(true);
13751403 jCCL_currentLineColor.setEnabled(true);
1376-
1404+
13771405 }
13781406 else {
13791407 jLabel_currentLineColor.setEnabled(false);
@@ -1414,7 +1442,7 @@ public abstract class AbsSettingView extends JScrollPane {
14141442 jCBP_pagerEnable.removeItemListener(il_pagerenable);
14151443 jCBP_pagerEnable.setEnabled(false);
14161444 jCBP_pagerEnable.addItemListener(il_pagerenable);
1417-
1445+
14181446 jSP_centerPerPage.setEnabled(false);
14191447 jCBP_allPageSnapshot.setEnabled(false);
14201448 }
@@ -1422,7 +1450,7 @@ public abstract class AbsSettingView extends JScrollPane {
14221450 jCBP_pagerEnable.removeItemListener(il_pagerenable);
14231451 jCBP_pagerEnable.setEnabled(true);
14241452 jCBP_pagerEnable.addItemListener(il_pagerenable);
1425-
1453+
14261454 if (jCBP_pagerEnable.isSelected()) {
14271455 jSP_centerPerPage.setEnabled(true);
14281456 jCBP_allPageSnapshot.setEnabled(true);
@@ -1455,7 +1483,7 @@ public abstract class AbsSettingView extends JScrollPane {
14551483 }
14561484 };
14571485 */
1458-
1486+
14591487 ItemListener al_tooltipenable = new ItemListener() {
14601488 @Override
14611489 public void itemStateChanged(ItemEvent e) {
@@ -1555,7 +1583,7 @@ public abstract class AbsSettingView extends JScrollPane {
15551583 }
15561584 }
15571585 };
1558-
1586+
15591587 ItemListener al_showsystray = new ItemListener() {
15601588 @Override
15611589 public void itemStateChanged(ItemEvent e) {
@@ -1568,39 +1596,54 @@ public abstract class AbsSettingView extends JScrollPane {
15681596 }
15691597 }
15701598 };
1571-
1599+
15721600 ActionListener al_fontChanged = new ActionListener() {
15731601 @Override
15741602 public void actionPerformed(ActionEvent e) {
1575-
1603+
15761604 String fn = (String) jComboBox_font.getSelectedItem();
15771605 int fs = Integer.valueOf((String) jComboBox_fontSize.getSelectedItem());
1578-
1606+
15791607 fontChanged(fn, fs);
1580-
1608+
15811609 if ( jLabel_fontSample != null ) {
15821610 Font f = jLabel_fontSample.getFont();
15831611 jLabel_fontSample.setFont(new Font(fn,f.getStyle(),fs));
15841612 }
15851613 }
15861614 };
1587-
1588-
1615+
1616+ ItemListener al_downloadProgramOnFixedTime = new ItemListener() {
1617+ @Override
1618+ public void itemStateChanged(ItemEvent e) {
1619+ if (debug) System.out.println("Fire! al_downloadProgramOnFixedTime");
1620+ if (jCBP_downloadProgramOnFixedTime.isSelected()) {
1621+ jTextField_downloadProgramTimeList.setEnabled(true);
1622+// jCBP_downloadProgramInBackground.setEnabled(true);
1623+ }
1624+ else {
1625+ jTextField_downloadProgramTimeList.setEnabled(false);
1626+// jCBP_downloadProgramInBackground.setEnabled(false);
1627+ }
1628+ }
1629+ };
1630+
1631+
15891632 /*******************************************************************************
15901633 * コンポーネント
15911634 ******************************************************************************/
1592-
1635+
15931636 private JLabel getNoticeMsg(String text) {
15941637 JLabel l = new JLabel(text);
15951638 l.setForeground(NOTICEMSG_COLOR);
15961639 return l;
15971640 }
1598-
1641+
15991642 // 更新確定ボタン
16001643 private JButton getJButton_update(String s) {
16011644 if (jButton_update == null) {
16021645 jButton_update = new JButton(s);
1603-
1646+
16041647 jButton_update.addActionListener(new ActionListener() {
16051648 public void actionPerformed(ActionEvent e) {
16061649 updateEnvs();
@@ -1609,7 +1652,7 @@ public abstract class AbsSettingView extends JScrollPane {
16091652 }
16101653 return(jButton_update);
16111654 }
1612-
1655+
16131656 //
16141657 private JLabel getJLabel_userAgent(String s)
16151658 {
@@ -1626,7 +1669,7 @@ public abstract class AbsSettingView extends JScrollPane {
16261669 }
16271670 return jTextField_userAgent;
16281671 }
1629-
1672+
16301673 //
16311674 private JLabel getJLabel_proxy(String s)
16321675 {
@@ -1651,7 +1694,7 @@ public abstract class AbsSettingView extends JScrollPane {
16511694 }
16521695 return jTextField_proxyPort;
16531696 }
1654-
1697+
16551698 // 表示マークの選択
16561699 private JLabel getJLabel_showmarks(String s) {
16571700 if (jLabel_showmarks == null) {
@@ -1672,7 +1715,7 @@ public abstract class AbsSettingView extends JScrollPane {
16721715 // ヘッダの設定
16731716 String[] colname = {"チェック", "マーク", "ID"};
16741717 int[] colwidth = {50,250,0};
1675-
1718+
16761719 //
16771720 DefaultTableModel model = new DefaultTableModel(colname, 0);
16781721 jTable_showmarks = new JNETable(model, false) {
@@ -1691,10 +1734,10 @@ public abstract class AbsSettingView extends JScrollPane {
16911734 column = columnModel.getColumn(i);
16921735 column.setPreferredWidth(colwidth[i]);
16931736 }
1694-
1737+
16951738 // にゃーん
16961739 jTable_showmarks.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
1697-
1740+
16981741 // エディタに手を入れる
16991742 DefaultCellEditor editor = new DefaultCellEditor(new JCheckBox() {
17001743
@@ -1705,12 +1748,12 @@ public abstract class AbsSettingView extends JScrollPane {
17051748 return JCheckBox.CENTER;
17061749 }
17071750 });
1708-
1751+
17091752 editor.addCellEditorListener(CEL_RELOAD_PROG_NEEDED);
1710-
1753+
17111754 //
17121755 jTable_showmarks.getColumn("チェック").setCellEditor(editor);
1713-
1756+
17141757 // レンダラに手を入れる
17151758 DefaultTableCellRenderer renderer = new DefaultTableCellRenderer() {
17161759
@@ -1736,7 +1779,7 @@ public abstract class AbsSettingView extends JScrollPane {
17361779 }
17371780 };
17381781 jTable_showmarks.getColumn("チェック").setCellRenderer(renderer);
1739-
1782+
17401783 //
17411784 for (Object[] obj : TVProgram.optMarks) {
17421785 Entry<ProgOption,Boolean> entry = null;
@@ -1779,15 +1822,15 @@ public abstract class AbsSettingView extends JScrollPane {
17791822 Object b = jTable_clipboard.getValueAt(row, 0);
17801823 Object item = jTable_clipboard.getValueAt(row, 1);
17811824 Object id = jTable_clipboard.getValueAt(row, 2);
1782-
1825+
17831826 jTable_clipboard.setValueAt(jTable_clipboard.getValueAt(row-1, 0), row, 0);
17841827 jTable_clipboard.setValueAt(jTable_clipboard.getValueAt(row-1, 1), row, 1);
17851828 jTable_clipboard.setValueAt(jTable_clipboard.getValueAt(row-1, 2), row, 2);
1786-
1829+
17871830 jTable_clipboard.setValueAt(b, row-1, 0);
17881831 jTable_clipboard.setValueAt(item, row-1, 1);
17891832 jTable_clipboard.setValueAt(id, row-1, 2);
1790-
1833+
17911834 jTable_clipboard.setRowSelectionInterval(row-1, row-1);
17921835 }
17931836 });
@@ -1807,15 +1850,15 @@ public abstract class AbsSettingView extends JScrollPane {
18071850 Object b = jTable_clipboard.getValueAt(row, 0);
18081851 Object item = jTable_clipboard.getValueAt(row, 1);
18091852 Object id = jTable_clipboard.getValueAt(row, 2);
1810-
1853+
18111854 jTable_clipboard.setValueAt(jTable_clipboard.getValueAt(row+1, 0), row, 0);
18121855 jTable_clipboard.setValueAt(jTable_clipboard.getValueAt(row+1, 1), row, 1);
18131856 jTable_clipboard.setValueAt(jTable_clipboard.getValueAt(row+1, 2), row, 2);
1814-
1857+
18151858 jTable_clipboard.setValueAt(b, row+1, 0);
18161859 jTable_clipboard.setValueAt(item, row+1, 1);
18171860 jTable_clipboard.setValueAt(id, row+1, 2);
1818-
1861+
18191862 jTable_clipboard.setRowSelectionInterval(row+1, row+1);
18201863 }
18211864 });
@@ -1835,7 +1878,7 @@ public abstract class AbsSettingView extends JScrollPane {
18351878 // ヘッダの設定
18361879 String[] colname = {"チェック", "アイテム", "ID"};
18371880 int[] colwidth = {50,250,0};
1838-
1881+
18391882 //
18401883 DefaultTableModel model = new DefaultTableModel(colname, 0);
18411884 jTable_clipboard = new JNETable(model, false) {
@@ -1854,10 +1897,10 @@ public abstract class AbsSettingView extends JScrollPane {
18541897 column = columnModel.getColumn(i);
18551898 column.setPreferredWidth(colwidth[i]);
18561899 }
1857-
1900+
18581901 // にゃーん
18591902 jTable_clipboard.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
1860-
1903+
18611904 // エディタに手を入れる
18621905 DefaultCellEditor editor = new DefaultCellEditor(new JCheckBox() {
18631906
@@ -1894,7 +1937,7 @@ public abstract class AbsSettingView extends JScrollPane {
18941937 }
18951938 };
18961939 jTable_clipboard.getColumn("チェック").setCellRenderer(renderer);
1897-
1940+
18981941 //
18991942 for (ClipboardInfo cb : getCbItemEnv()) {
19001943 Object[] data = { cb.getB(), cb.getItem(), cb.getId() };
@@ -1903,7 +1946,7 @@ public abstract class AbsSettingView extends JScrollPane {
19031946 }
19041947 return(jTable_clipboard);
19051948 }
1906-
1949+
19071950 // 右クリックメニューの実行コマンドの追加
19081951 private JLabel getJLabel_menuitem(String s) {
19091952 if (jLabel_menuitem == null) {
@@ -1971,13 +2014,13 @@ public abstract class AbsSettingView extends JScrollPane {
19712014 }
19722015 Object name = jTable_mitable.getValueAt(row, 0);
19732016 Object cmd = jTable_mitable.getValueAt(row, 1);
1974-
2017+
19752018 jTable_mitable.setValueAt(jTable_mitable.getValueAt(row-1, 0), row, 0);
19762019 jTable_mitable.setValueAt(jTable_mitable.getValueAt(row-1, 1), row, 1);
1977-
2020+
19782021 jTable_mitable.setValueAt(name, row-1, 0);
19792022 jTable_mitable.setValueAt(cmd, row-1, 1);
1980-
2023+
19812024 jTable_mitable.setRowSelectionInterval(row-1, row-1);
19822025 }
19832026 });
@@ -1996,13 +2039,13 @@ public abstract class AbsSettingView extends JScrollPane {
19962039 }
19972040 Object name = jTable_mitable.getValueAt(row, 0);
19982041 Object cmd = jTable_mitable.getValueAt(row, 1);
1999-
2042+
20002043 jTable_mitable.setValueAt(jTable_mitable.getValueAt(row+1, 0), row, 0);
20012044 jTable_mitable.setValueAt(jTable_mitable.getValueAt(row+1, 1), row, 1);
2002-
2045+
20032046 jTable_mitable.setValueAt(name, row+1, 0);
20042047 jTable_mitable.setValueAt(cmd, row+1, 1);
2005-
2048+
20062049 jTable_mitable.setRowSelectionInterval(row+1, row+1);
20072050 }
20082051 });
@@ -2022,7 +2065,7 @@ public abstract class AbsSettingView extends JScrollPane {
20222065 // ヘッダの設定
20232066 String[] colname = {"コマンド名", "実行するコマンド"};
20242067 int[] colwidth = {col1_w,col2_w};
2025-
2068+
20262069 //
20272070 DefaultTableModel model = new DefaultTableModel(colname, 0);
20282071 jTable_mitable = new JNETable(model, false) {
@@ -2041,10 +2084,10 @@ public abstract class AbsSettingView extends JScrollPane {
20412084 column = columnModel.getColumn(i);
20422085 column.setPreferredWidth(colwidth[i]);
20432086 }
2044-
2087+
20452088 // にゃーん
20462089 jTable_mitable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
2047-
2090+
20482091 //
20492092 for (TextValueSet tv : env.getTvCommand()) {
20502093 Object[] data = { tv.getText(), tv.getValue() };
@@ -2053,7 +2096,7 @@ public abstract class AbsSettingView extends JScrollPane {
20532096 }
20542097 return(jTable_mitable);
20552098 }
2056-
2099+
20572100 //
20582101 private JLabel getJLabel_ngword(String s) {
20592102 if (jLabel_ngword == null) {
@@ -2098,7 +2141,7 @@ public abstract class AbsSettingView extends JScrollPane {
20982141 else {
20992142 model.setSelectedItem(UIManager.getLookAndFeel().getName());
21002143 }
2101-
2144+
21022145 //
21032146 jComboBox_lookAndFeel.addActionListener(new ActionListener() {
21042147 public void actionPerformed(ActionEvent e) {
@@ -2110,7 +2153,7 @@ public abstract class AbsSettingView extends JScrollPane {
21102153 }
21112154 return jComboBox_lookAndFeel;
21122155 }
2113-
2156+
21142157 private JLabel getJLabel_font(String s) {
21152158 if (jLabel_font == null) {
21162159 jLabel_font = new JLabel();
@@ -2136,7 +2179,7 @@ public abstract class AbsSettingView extends JScrollPane {
21362179 else {
21372180 model.setSelectedItem(jComboBox_font.getFont().getFontName());
21382181 }
2139-
2182+
21402183 //
21412184 jComboBox_font.addActionListener(al_fontChanged);
21422185
@@ -2154,7 +2197,7 @@ public abstract class AbsSettingView extends JScrollPane {
21542197 if ( env.getFontSize() > 0) {
21552198 jComboBox_fontSize.setSelectedItem(String.valueOf(env.getFontSize()));
21562199 }
2157-
2200+
21582201 jComboBox_fontSize.addActionListener(al_fontChanged);
21592202 }
21602203 return(jComboBox_fontSize);
@@ -2171,7 +2214,7 @@ public abstract class AbsSettingView extends JScrollPane {
21712214 }
21722215 return jLabel_fontSample;
21732216 }
2174-
2217+
21752218 private JLabel getJLabel_enableCHAVsetting(String s)
21762219 {
21772220 if (jLabel_enableCHAVsetting == null) {
@@ -2187,7 +2230,7 @@ public abstract class AbsSettingView extends JScrollPane {
21872230 }
21882231 return(jCheckBox_enableCHAVsetting);
21892232 }
2190-
2233+
21912234 private JLabel getJLabel_autoFolderSelect(String s)
21922235 {
21932236 if (jLabel_autoFolderSelect == null) {
@@ -2213,4 +2256,13 @@ public abstract class AbsSettingView extends JScrollPane {
22132256 }
22142257 return jta_help;
22152258 }
2259+
2260+ private JTextField getJTextField_downloadProgramTimeList(String s) {
2261+ if (jTextField_downloadProgramTimeList == null) {
2262+ jTextField_downloadProgramTimeList = new JTextFieldWithPopup();
2263+ jTextField_downloadProgramTimeList.setText(s);
2264+ jTextField_downloadProgramTimeList.setCaretPosition(0);
2265+ }
2266+ return jTextField_downloadProgramTimeList;
2267+ }
22162268 }
--- a/TinyBannavi/src/tainavi/AbsToolBar.java
+++ b/TinyBannavi/src/tainavi/AbsToolBar.java
@@ -126,6 +126,7 @@ public abstract class AbsToolBar extends JToolBar implements HDDRecorderSelectab
126126 private static final String ICONFILE_SEARCH = "icon/system-search-2.png";
127127 private static final String ICONFILE_ADDKEYWORD = "icon/bookmark-new-list-4.png";
128128 private static final String ICONFILE_RELOADPROG = "icon/internet-news-reader.png";
129+ private static final String ICONFILE_STOPRELOADPROG = "icon/stop-news-reader.png";
129130 private static final String ICONFILE_BATCHCMD = "icon/checkbox.png";
130131 private static final String ICONFILE_RELOADRSV = "icon/video-television.png";
131132 private static final String ICONFILE_WAKEUP = "icon/system-shutdown-2.png";
@@ -152,6 +153,7 @@ public abstract class AbsToolBar extends JToolBar implements HDDRecorderSelectab
152153 private static final String TIPS_ADDKEYWORD = "キーワードリストに登録(Ctrl+K)";
153154 private static final String TIPS_PAGER = "ページャー";
154155 private static final String TIPS_RELOADPROG = "Webから番組情報を再取得(Ctrl+W)";
156+ private static final String TIPS_STOPRELOADPROG = "バックグランドで実行中の番組情報の取得を中止";
155157 private static final String TIPS_BATCHRESERVATION = "一括予約(Ctrl+B)";
156158 private static final String TIPS_RECORDERSEL = "操作するレコーダを選択する";
157159 private static final String TIPS_RELOADRSVED = "レコーダから予約情報を再取得&レコーダの各種設定情報の収集(Ctrl+R)";
@@ -436,6 +438,24 @@ public abstract class AbsToolBar extends JToolBar implements HDDRecorderSelectab
436438 jButton_addkeyword.setEnabled(b);
437439 }
438440
441+ /*
442+ * TVプログラムの再取得
443+ */
444+ public void setReloadTVProgramsInProgress(boolean b){
445+ if (jButton_reloadprogs != null){
446+ ImageIcon icon = new ImageIcon(b ? ICONFILE_STOPRELOADPROG : ICONFILE_RELOADPROG);
447+ jButton_reloadprogs.setIcon(icon);
448+ jButton_reloadprogs.setToolTipText(b ? TIPS_STOPRELOADPROG : TIPS_RELOADPROG);
449+ }
450+
451+ if (jButton_reloadprogmenu != null){
452+ jButton_reloadprogmenu.setEnabled(!b);
453+ if (b)
454+ jButton_reloadprogmenu.removeMouseListener(ma_reloadProgramExtension);
455+ else
456+ jButton_reloadprogmenu.addMouseListener(ma_reloadProgramExtension);
457+ }
458+ }
439459 /**
440460 * ばちー
441461 */
--- a/TinyBannavi/src/tainavi/CommonUtils.java
+++ b/TinyBannavi/src/tainavi/CommonUtils.java
@@ -26,6 +26,7 @@ import java.net.HttpURLConnection;
2626 import java.net.Socket;
2727 import java.nio.channels.FileChannel;
2828 import java.nio.channels.FileLock;
29+import java.text.ParseException;
2930 import java.text.SimpleDateFormat;
3031 import java.util.ArrayList;
3132 import java.util.Calendar;
@@ -772,6 +773,34 @@ public class CommonUtils {
772773 }
773774 }
774775
776+ /*
777+ * 日時を文字列に変換
778+ */
779+ public static String getCalendarAsString(GregorianCalendar c){
780+ if (c == null)
781+ c = new GregorianCalendar();
782+
783+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss:SSS z");
784+ return sdf.format(c.getTime());
785+ }
786+
787+ /*
788+ * 日時を文字列から変換
789+ */
790+ public static GregorianCalendar getCalendarFromString(String s){
791+ if (s == null)
792+ return null;
793+
794+ GregorianCalendar c = new GregorianCalendar();
795+ try {
796+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss:SSS z");
797+ c.setTime(sdf.parse(s));
798+ } catch (ParseException e) {
799+ return null;
800+ }
801+
802+ return c;
803+ }
775804
776805 /*******************************************************************************
777806 * Color関連
--- a/TinyBannavi/src/tainavi/Env.java
+++ b/TinyBannavi/src/tainavi/Env.java
@@ -660,7 +660,25 @@ public class Env {
660660 public void setPrepPassedProgramCount(int w) { prepPassedProgramCount = w; }
661661 private int prepPassedProgramCount = 4;
662662
663-
663+ // 決まった時間に番組表を取得する
664+ public boolean getDownloadProgramOnFixedTime() { return downloadProgramOnFixedTime; }
665+ public void setDownloadProgramOnFixedTime(boolean b) { downloadProgramOnFixedTime = b; }
666+ private boolean downloadProgramOnFixedTime = false;
667+
668+ // 番組表を取得する時刻の一覧
669+ public String getDownloadProgramTimeList() { return downloadProgramTimeList; }
670+ public void setDownloadProgramTimeList(String s) { downloadProgramTimeList = s; }
671+ private String downloadProgramTimeList = "08:30";
672+
673+ // 番組表をバックグランドで取得するか
674+ public boolean getDownloadProgramInBackground() { return downloadProgramInBackground; }
675+ public void setDownloadProgramInBackground(boolean b) { downloadProgramInBackground = b; }
676+ private boolean downloadProgramInBackground = false;
677+
678+ // 最後に番組表を取得した時刻
679+ public String getLastDownloadTime(){ return lastDownloadTime; }
680+ public void setLastDownloadTime(String s){ lastDownloadTime = s; }
681+ private String lastDownloadTime = null;
664682
665683 /*
666684 * レコーダ対応
--- a/TinyBannavi/src/tainavi/GetEventId.java
+++ b/TinyBannavi/src/tainavi/GetEventId.java
@@ -222,7 +222,8 @@ public class GetEventId extends TVProgramUtils implements TVProgram,Cloneable {
222222 }
223223
224224 @Override
225- public void loadProgram(String areaCode, boolean force) {
225+ public boolean loadProgram(String areaCode, boolean force) {
226+ return true;
226227 }
227228
228229 @Override
--- a/TinyBannavi/src/tainavi/HDDRecorderUtils.java
+++ b/TinyBannavi/src/tainavi/HDDRecorderUtils.java
@@ -1064,6 +1064,9 @@ public class HDDRecorderUtils implements HDDRecorder,Cloneable {
10641064 // ちょっと時刻順に整理しよう
10651065 ArrayList<ReserveList> s = new ArrayList<ReserveList>();
10661066 for ( ReserveList o : r ) {
1067+ if (o.getAhh().isEmpty() || o.getAmm().isEmpty() || o.getZhh().isEmpty() || o.getZmm().isEmpty())
1068+ continue;
1069+
10671070 int idx = -1;
10681071 for ( int i=0; i<s.size(); i++ ) {
10691072 if ( o.getStartDateTime().compareTo(s.get(i).getStartDateTime()) < 0 ) {
--- a/TinyBannavi/src/tainavi/PassedProgram.java
+++ b/TinyBannavi/src/tainavi/PassedProgram.java
@@ -17,65 +17,65 @@ import tainavi.TVProgramIterator.IterationType;
1717 public class PassedProgram extends TVProgramUtils implements TVProgram,Cloneable {
1818
1919 //private static final String thisEncoding = "UTF-8";
20-
20+
2121 public void setDebug(boolean b) { debug = b; }
2222 private static boolean debug = false;
23-
23+
2424 /* 必須コード - ここから */
25-
25+
2626 /*******************************************************************************
2727 * 種族の特性
2828 ******************************************************************************/
29-
29+
3030 @Override
3131 public String getTVProgramId() { return tvProgId; }
3232 private static final String tvProgId = "PassedProgram";
33-
33+
3434 @Override
3535 public boolean isAreaSelectSupported() { return false; }
36-
36+
3737 @Override
3838 public ProgType getType() { return ProgType.PASSED; }
3939 @Override
4040 public ProgSubtype getSubtype() { return ProgSubtype.NONE; }
41-
41+
4242 public PassedProgram clone() {
4343 return (PassedProgram) super.clone();
4444 }
45-
45+
4646 // リフレッシュされないようにする
4747 @Override
4848 public void refresh() {}
49-
49+
5050 /*******************************************************************************
5151 * 個体の特性
5252 ******************************************************************************/
53-
53+
5454 @Override
5555 public int getTimeBarStart() {return 5;}
56-
56+
5757 //private int getDogDays() { return 7; }
58-
58+
5959 public void setUseXML(boolean b) { useXML = b; }
6060 private static boolean useXML = false;
61-
62-
61+
62+
6363 /*******************************************************************************
6464 * 定数
6565 ******************************************************************************/
66-
66+
6767 public static final String SEARCH_RESULT_CENTER = "$SRCRESCNT$";
68-
68+
6969 private static final String MSGID = "[過去ログ] ";
7070 private static final String ERRID = "[ERROR]"+MSGID;
7171 private static final String DBGID = "[DEBUG]"+MSGID;
72-
72+
7373 /*******************************************************************************
7474 * 部品
7575 ******************************************************************************/
76-
76+
7777 // コンポーネント以外
78-
78+
7979 /**
8080 * 保存先のディレクトリを設定する
8181 * @param s
@@ -84,15 +84,15 @@ public class PassedProgram extends TVProgramUtils implements TVProgram,Cloneable
8484 dname = s;
8585 }
8686 private static String dname = "passed";
87-
87+
8888 public int getProgCount() { return progcount; }
8989 private int progcount = 0;
90-
90+
9191
9292 /*******************************************************************************
9393 * コンストラクタ
9494 ******************************************************************************/
95-
95+
9696 public PassedProgram() {
9797 super();
9898 cleanup();
@@ -102,20 +102,20 @@ public class PassedProgram extends TVProgramUtils implements TVProgram,Cloneable
102102 * 情報を全部破棄
103103 */
104104 private void cleanup() {
105-
105+
106106 crlist = new ArrayList<Center>(); // 番組情報を全部破棄
107107 sortedcrlist = new ArrayList<Center>(); // 番組情報を全部破棄
108108 pcenter = new ArrayList<ProgList>(); // 番組情報を全部破棄
109-
109+
110110 }
111111
112-
112+
113113 /*******************************************************************************
114114 * 本体
115115 ******************************************************************************/
116-
117- public void loadProgram(String areaCode, boolean force) {} // 使用しない。ダミー。
118-
116+
117+ public boolean loadProgram(String areaCode, boolean force) { return true; } // 使用しない。ダミー。
118+
119119 /**
120120 * 指定の日付のすべての過去ログを取得する
121121 * @param date
@@ -124,10 +124,10 @@ public class PassedProgram extends TVProgramUtils implements TVProgram,Cloneable
124124 public boolean loadAllCenters(String date) {
125125 return loadByCenter(date,null);
126126 }
127-
127+
128128 final String expr_a = "^(\\d)_(\\d+)_(.+)\\.";
129129 final String expr_z = "(xml|txt)$";
130-
130+
131131 /**
132132 * 指定の日付の指定の放送局の過去ログを取得する
133133 * @param date
@@ -135,18 +135,18 @@ public class PassedProgram extends TVProgramUtils implements TVProgram,Cloneable
135135 * @return
136136 */
137137 public boolean loadByCenter(String date, String center) {
138-
138+
139139 progcount = 0;
140-
140+
141141 final String ymname = dname+File.separator+date.substring(0,7).replace("/", "_");
142142 final String ddname = ymname+File.separator+date.replace("/", "_");
143-
143+
144144 File f = new File(ymname);
145145 if ( ! f.exists() && ! f.isDirectory()) {
146146 System.out.println(MSGID+"年ディレクトがみつかりません: "+f.getAbsolutePath());
147147 return false;
148148 }
149-
149+
150150 File g = new File(ddname);
151151 if ( ! g.exists() && ! g.isDirectory()) {
152152 System.out.println(MSGID+"月日ディレクトがみつかりません: "+g.getAbsolutePath());
@@ -154,12 +154,12 @@ public class PassedProgram extends TVProgramUtils implements TVProgram,Cloneable
154154 }
155155
156156 // 取得開始
157-
157+
158158 TatCount tc = new TatCount();
159-
159+
160160 // 番組情報を全部破棄
161161 this.cleanup();
162-
162+
163163 String[] flist = g.list();
164164 Arrays.sort(flist);
165165 ArrayList<String> fxlist = new ArrayList<String>();
@@ -170,27 +170,27 @@ public class PassedProgram extends TVProgramUtils implements TVProgram,Cloneable
170170 if (debug) System.out.println(DBGID+"Invalid file name: "+flist[i]);
171171 continue; // ファイル名の書式が合わないものは無視
172172 }
173-
173+
174174 String base = flist[i].replaceFirst(expr_z, "");
175175 if ( ! fxlist.contains(base) )
176176 {
177177 fxlist.add(base);
178178 }
179179 }
180-
180+
181181 for ( String fx : fxlist ) {
182-
182+
183183 Matcher ma = Pattern.compile(expr_a,Pattern.DOTALL).matcher(fx);
184184 ma.find();
185-
185+
186186 String fcenter = CommonUtils.unEscape(ma.group(3));
187-
187+
188188 if ( center != null && ! center.equals(fcenter) )
189189 {
190190 if (debug) System.out.println(DBGID+"not selected: "+fx);
191191 continue; // 放送局指定がされている場合はその局のみ
192192 }
193-
193+
194194 int order = Integer.valueOf(ma.group(2));
195195 if ( order == 0 )
196196 {
@@ -208,18 +208,18 @@ public class PassedProgram extends TVProgramUtils implements TVProgram,Cloneable
208208 cr.setOrder(order);
209209 crlist.add(cr);
210210 sortedcrlist.add(cr);
211-
211+
212212 // 番組表局リストの追加
213213 ProgList pl = new ProgList();
214214 pl.Center = fcenter;
215215 pl.enabled = true;
216216 pcenter.add(pl);
217-
217+
218218 // 日付リストの追加
219219 ProgDateList pcl = new ProgDateList();
220220 pcl.Date = date;
221221 pl.pdate.add(pcl);
222-
222+
223223 TatCount tx = new TatCount();
224224 if ( new File(txtname).exists() ) {
225225 progcount += readTXT(pl.Center,pcl,txtname);
@@ -257,14 +257,14 @@ public class PassedProgram extends TVProgramUtils implements TVProgram,Cloneable
257257
258258 return true;
259259 }
260-
260+
261261 private int readTXT(String center, ProgDateList pcl, String txtname) {
262-
262+
263263 String txt = CommonUtils.read4file(txtname, false);
264264 if ( txt == null ) {
265265 return -1;
266266 }
267-
267+
268268 int index = 0;
269269 while ( index < txt.length() )
270270 {
@@ -274,30 +274,30 @@ public class PassedProgram extends TVProgramUtils implements TVProgram,Cloneable
274274 break;
275275 }
276276 newtop += WrHeader.STARTMARK.toString().length()+1;
277-
277+
278278 // 番組フッタを探す
279279 int newtail = txt.indexOf(WrHeader.ENDMARK.toString(),newtop);
280280 if ( newtail == -1 ) {
281281 break;
282282 }
283283 index = newtail+WrHeader.ENDMARK.toString().length()+1;
284-
284+
285285 // 解析する
286286 ProgDetailList pdl = new ProgDetailList(txt.substring(newtop,newtail));
287-
287+
288288 // サブタイトル分離
289289 doSplitSubtitle(pdl);
290-
290+
291291 pcl.pdetail.add(pdl);
292292
293293 // 情報を追加
294294 pdl.center = center;
295295 pdl.type = this.getType();
296296 }
297-
297+
298298 return pcl.pdetail.size();
299299 }
300-
300+
301301 private int readXML(String center, ProgDateList pcl, String date, String xmlname) {
302302 try {
303303
@@ -308,7 +308,7 @@ public class PassedProgram extends TVProgramUtils implements TVProgram,Cloneable
308308 System.err.println(ERRID+"読み込みに失敗しました: "+xmlname);
309309 return -1;
310310 }
311-
311+
312312 GregorianCalendar cal = CommonUtils.getCalendar(date);
313313 for ( int j=0; j<da.size(); j++ )
314314 {
@@ -334,27 +334,27 @@ public class PassedProgram extends TVProgramUtils implements TVProgram,Cloneable
334334 }
335335 }
336336 }
337-
337+
338338 // クソバグ対応(番組詳細のない情報があった)
339339 if (data.detail == null)
340340 {
341341 data.detail="";
342342 }
343-
343+
344344 // 後方互換(EDCB番組表で追加された追加番組詳細情報への対応)
345345 if (data.addedDetail == null)
346346 {
347347 data.addedDetail = "";
348348 }
349-
349+
350350 //
351351 data.splitted_title = data.title;
352352 data.splitted_detail = data.detail;
353-
353+
354354 // 検索用インデックスを生成
355355 data.titlePop = TraceProgram.replacePop(data.title);
356356 data.detailPop = TraceProgram.replacePop(data.detail);
357-
357+
358358 // 終了時刻・実日付を生成
359359 String[] Ahm = data.start.split(":",2);
360360 if ( Ahm.length == 2 )
@@ -363,7 +363,7 @@ public class PassedProgram extends TVProgramUtils implements TVProgram,Cloneable
363363 GregorianCalendar cale = (GregorianCalendar) cal.clone();
364364 int hh = Integer.valueOf(Ahm[0]);
365365 int mm = Integer.valueOf(Ahm[1]);
366-
366+
367367 if ( j == 0 )
368368 {
369369 if ( CommonUtils.isLateNight(hh) )
@@ -383,38 +383,38 @@ public class PassedProgram extends TVProgramUtils implements TVProgram,Cloneable
383383 // 2個目以降で00-05時は翌日だ
384384 cale.add(Calendar.DATE, 1);
385385 }
386-
386+
387387 data.accurateDate = CommonUtils.getDate(cale);
388-
388+
389389 cale.set(Calendar.HOUR_OF_DAY, hh);
390390 cale.set(Calendar.MINUTE, mm);
391391 data.startDateTime = CommonUtils.getDateTime(cale);
392392 data.start = CommonUtils.getTime(cale);
393-
393+
394394 cale.add(Calendar.MINUTE, prelength+data.length);
395395 data.end = CommonUtils.getTime(cale);
396396 data.endDateTime = CommonUtils.getDateTime(cale);
397-
397+
398398 data.recmin = CommonUtils.getRecMinVal(data.start,data.end);
399399 }
400-
400+
401401 pcl.pdetail.add(data);
402402
403403 // 情報を追加
404404 data.center = center;
405405 data.type = this.getType();
406406 }
407-
407+
408408 return pcl.pdetail.size();
409409 }
410410 catch ( Exception e )
411411 {
412412 System.err.println(ERRID+"過去ログの読み込みに失敗しました: "+xmlname);
413413 e.printStackTrace();
414- }
414+ }
415415 return -1;
416416 }
417-
417+
418418 /**
419419 * プログラムリストをファイルに保存する
420420 * @param tviterator
@@ -423,11 +423,11 @@ public class PassedProgram extends TVProgramUtils implements TVProgram,Cloneable
423423 * @return
424424 */
425425 public boolean save(TVProgramIterator tviterator, ArrayList<Center> clst, int prepCount) {
426-
426+
427427 TVProgramIterator pli = tviterator.build(clst, IterationType.ALL);
428-
428+
429429 String curDate = CommonUtils.getDate529(0,true);
430-
430+
431431 // 古いログは削除
432432 {
433433 ArrayList<String> dirs = new ArrayList<String>();
@@ -457,7 +457,7 @@ public class PassedProgram extends TVProgramUtils implements TVProgram,Cloneable
457457 }
458458 }
459459 }
460-
460+
461461 // 削除
462462 for (String dir : dirs)
463463 {
@@ -475,21 +475,21 @@ public class PassedProgram extends TVProgramUtils implements TVProgram,Cloneable
475475 }
476476 }
477477 }
478-
478+
479479 // 放送局名をキーにプログラムリストをなめる
480480 TatCount tc = new TatCount();
481-
481+
482482 pli.rewind(); // まきもどせ
483-
483+
484484 int centerid = 0;
485485 for ( ProgList pl : pli )
486486 {
487487 ++centerid;
488-
488+
489489 tc.restart();
490490 String firstD = "";
491491 String lastD = "";
492-
492+
493493 int count = 1;
494494 for ( ProgDateList cl : pl.pdate )
495495 {
@@ -497,21 +497,21 @@ public class PassedProgram extends TVProgramUtils implements TVProgram,Cloneable
497497 {
498498 continue; // 過去日のログは不要
499499 }
500-
500+
501501 if ( count++ > prepCount )
502502 {
503503 break; // 指定日数以上は保存しない
504504 }
505-
505+
506506 if ( firstD.length() == 0 ) firstD = cl.Date;
507507 lastD = cl.Date;
508-
508+
509509 // 出力先の決定
510510 String ymname = dname+File.separator+cl.Date.substring(0,7).replace("/", "_");
511511 String ddname = ymname+File.separator+cl.Date.replace("/", "_");
512512 String xmlname = ddname+File.separator+String.format("%d_%04d_%s.xml", 1, centerid, CommonUtils.escapeFilename(pl.Center));
513513 String txtname = ddname+File.separator+String.format("%d_%04d_%s.txt", 1, centerid, CommonUtils.escapeFilename(pl.Center));
514-
514+
515515 for ( String xname : new String[] { dname,ymname,ddname } )
516516 {
517517 File f = new File(xname);
@@ -532,13 +532,13 @@ public class PassedProgram extends TVProgramUtils implements TVProgram,Cloneable
532532 if (debug) System.err.println(String.format(DBGID+"XML形式での保存にかかった時間(%.4f秒): %s->%s %s",tx.end(),firstD,lastD,pl.Center));
533533 }
534534 }
535-
535+
536536 reportProgress(String.format(MSGID+"保存しました(%.2f秒): %s->%s %s",tc.end(),firstD,lastD,pl.Center));
537537 }
538538 return true;
539-
539+
540540 }
541-
541+
542542 private boolean writeTXT(ProgDateList pcl, String txtname) {
543543 StringBuilder sb = new StringBuilder();
544544 for ( ProgDetailList d : pcl.pdetail ) {
@@ -569,13 +569,13 @@ public class PassedProgram extends TVProgramUtils implements TVProgram,Cloneable
569569 data.setOption(d.option);
570570 da.add(data);
571571 }
572-
572+
573573 // 出力
574574 if ( ! CommonUtils.writeXML(xmlname, da) )
575575 {
576576 return false;
577577 }
578-
578+
579579 return true;
580580 }
581581
@@ -587,20 +587,20 @@ public class PassedProgram extends TVProgramUtils implements TVProgram,Cloneable
587587 * ディレクトリ一覧を取得する(日に一回しか検索しない)
588588 */
589589 public String[] getDateList(int maxCnt) {
590-
590+
591591 String getdate = CommonUtils.getDate529(0,true);
592592 if ( getdate.compareTo(pregetdate) <= 0 )
593593 {
594594 return dd;
595595 }
596596 pregetdate = getdate;
597-
597+
598598 System.out.println(MSGID+"フォルダを検索して過去ログをリストアップします. "+getdate);
599-
599+
600600 // 最初のエントリーはダミー
601601 ArrayList<String> da = new ArrayList<String>();
602602 da.add("過去ログ");
603-
603+
604604 // 過去日のディレクトリのみが対象
605605 GregorianCalendar cal = CommonUtils.getCalendar(0);
606606 if ( CommonUtils.isLateNight(cal) )
@@ -608,7 +608,7 @@ public class PassedProgram extends TVProgramUtils implements TVProgram,Cloneable
608608 cal.add(Calendar.DAY_OF_MONTH, -1);
609609 }
610610 String date = String.format("%04d_%02d_%02d", cal.get(Calendar.YEAR), cal.get(Calendar.MONTH)+1, cal.get(Calendar.DAY_OF_MONTH));
611-
611+
612612 // トップディレクトリは存在するかな?
613613 File d = new File(dname);
614614 if ( ! d.exists() && ! d.isDirectory())
@@ -616,7 +616,7 @@ public class PassedProgram extends TVProgramUtils implements TVProgram,Cloneable
616616 System.out.println(MSGID+"ディレクトリがみつかりません: "+d.getAbsolutePath());
617617 return da.toArray(new String[0]);
618618 }
619-
619+
620620 // 日付降順に処理する
621621 int cnt = 0;
622622 String[] dlist = d.list();
@@ -629,7 +629,7 @@ public class PassedProgram extends TVProgramUtils implements TVProgram,Cloneable
629629 {
630630 continue;
631631 }
632-
632+
633633 // ディレクトリだよね?
634634 final String ddname = d.getName()+File.separator+dlist[j];
635635 File f = new File(ddname);
@@ -638,7 +638,7 @@ public class PassedProgram extends TVProgramUtils implements TVProgram,Cloneable
638638 System.out.println(MSGID+"ディレクトリがみつかりません: "+f.getAbsolutePath());
639639 return null;
640640 }
641-
641+
642642 // 日付降順に処理する
643643 String[] flist = f.list();
644644 Arrays.sort(flist);
@@ -661,55 +661,55 @@ public class PassedProgram extends TVProgramUtils implements TVProgram,Cloneable
661661 dd = da.toArray(new String[0]);
662662 return dd;
663663 }
664-
664+
665665 /* ここまで */
666-
667-
668-
666+
667+
668+
669669 /*
670670 * ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
671671 * ★★★★★ 放送地域を取得する(TVAreaから降格)-ここから ★★★★★
672672 * ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
673673 */
674-
674+
675675 /*
676676 * 公開メソッド
677677 */
678-
678+
679679 //
680680 @Override
681681 public String getDefaultArea() {return "東京";}
682-
682+
683683 //
684684 public void loadAreaCode() {}
685-
685+
686686 //
687687 public void saveAreaCode() {}
688-
688+
689689 /*
690690 * ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
691691 * ★★★★★ 放送地域を取得する(TVAreaから降格)-ここまで ★★★★★
692692 * ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
693693 */
694-
695-
696-
694+
695+
696+
697697 /*
698698 * ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
699699 * ★★★★★ 放送局を選択する(TVCenterから降格)-ここから ★★★★★
700700 * ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
701701 */
702-
702+
703703 /*
704704 * 公開メソッド
705705 */
706-
706+
707707 // 設定ファイルがなければWebから取得
708708 public void loadCenter(String code, boolean force) {}
709-
709+
710710 // 設定ファイルへ書き出し
711711 public boolean saveCenter() { return false; }
712-
712+
713713 /*
714714 * ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
715715 * ★★★★★ 放送局を選択する(TVCenterから降格)-ここまで ★★★★★
--- a/TinyBannavi/src/tainavi/PickedProgram.java
+++ b/TinyBannavi/src/tainavi/PickedProgram.java
@@ -12,33 +12,33 @@ import java.util.GregorianCalendar;
1212 public class PickedProgram extends TVProgramUtils implements TVProgram,Cloneable {
1313
1414 //private static final String thisEncoding = "UTF-8";
15-
15+
1616 public void setDebug(boolean b) { debug = b; }
1717 private static boolean debug = false;
18-
18+
1919 /* 必須コード - ここから */
20-
20+
2121 /*******************************************************************************
2222 * 種族の特性
2323 ******************************************************************************/
24-
24+
2525 @Override
2626 public String getTVProgramId() { return tvProgId; }
2727 private static final String tvProgId = "PickedProgram";
28-
28+
2929 @Override
3030 public boolean isAreaSelectSupported() { return false; }
31-
31+
3232 @Override
3333 public ProgType getType() { return ProgType.PICKED; }
3434 @Override
3535 public ProgSubtype getSubtype() { return ProgSubtype.NONE; }
36-
36+
3737 @Override
3838 public PickedProgram clone() {
3939 return (PickedProgram) super.clone();
4040 }
41-
41+
4242 /*******************************************************************************
4343 * 個体の特性
4444 ******************************************************************************/
@@ -49,85 +49,85 @@ public class PickedProgram extends TVProgramUtils implements TVProgram,Cloneable
4949 /*******************************************************************************
5050 * 定数
5151 ******************************************************************************/
52-
52+
5353 public static enum WrHeader {
54-
54+
5555 // 順番をかえなければ、どこに追加してもいい
56-
56+
5757 CENTER ( "$CH$", true ),
5858 DATE ( "$DT$", true ),
59-
59+
6060 // ここから下は別の領域なので追加はNG
61-
61+
6262 BEND ( "$PI#YY$", false ), // 項目ごとのフッタ
6363 STARTMARK ( "$PI#AA$", false ), // ヘッダ
6464 ENDMARK ( "$PI#ZZ$", false ), // フッタ
65-
65+
6666 ;
67-
67+
6868 private String hdr;
6969 private boolean marker;
70-
70+
7171 private WrHeader(String hdr, boolean marker) {
7272 this.hdr = hdr;
7373 this.marker = marker;
7474 }
75-
75+
7676 // ここはtoString()をOverrideしてよい
7777 @Override
7878 public String toString() { return hdr; }
7979 }
80-
80+
8181 // 区切り文字
8282 private static final String S_CR = "\n";
83-
83+
8484 private final static String txtname = "env"+File.separator+"picked.txt";
85-
85+
8686 private static final String MSGID = "[ピックアップ] ";
8787 private static final String DBGID = "[DEBUG]"+MSGID;
8888 private static final String ERRID = "[ERROR]"+MSGID;
89-
89+
9090 /*******************************************************************************
9191 * 部品
9292 ******************************************************************************/
93-
93+
9494 /*******************************************************************************
9595 * 本体
9696 ******************************************************************************/
97-
97+
9898 @Override
99- public void loadProgram(String areaCode, boolean force) {
100-
99+ public boolean loadProgram(String areaCode, boolean force) {
100+
101101 //
102102 if ( ! new File(txtname).exists() ) {
103103 System.out.println(MSGID+"ピックアップリストのファイルがありませんでした: "+txtname);
104- return;
104+ return true;
105105 }
106-
106+
107107 // 番組リストの追加
108108 int cnt = load();
109109 System.out.println(MSGID+"ピックアップリストを取得しました: "+cnt);
110-
110+ return true;
111111 }
112-
113-
114-
115-
112+
113+
114+
115+
116116 // 内部的な
117-
117+
118118 /*
119119 * プログラムリストをファイルに保存する
120120 */
121121 public boolean save() {
122-
122+
123123 StringBuilder sb = new StringBuilder();
124-
124+
125125 for (ProgList pl : pcenter) {
126126 for (ProgDateList cl : pl.pdate) {
127127 if ( cl.pdetail.size() == 0 ) {
128128 continue;
129129 }
130-
130+
131131 sb.append(WrHeader.STARTMARK);
132132 sb.append(S_CR);
133133 sb.append(WrHeader.CENTER);
@@ -136,7 +136,7 @@ public class PickedProgram extends TVProgramUtils implements TVProgram,Cloneable
136136 sb.append(WrHeader.DATE);
137137 sb.append(cl.Date);
138138 sb.append(WrHeader.BEND);
139-
139+
140140 // 詳細をコピーする
141141 for (ProgDetailList d : cl.pdetail) {
142142 sb.append(d.toString());
@@ -146,18 +146,18 @@ public class PickedProgram extends TVProgramUtils implements TVProgram,Cloneable
146146 sb.append(S_CR);
147147 }
148148 }
149-
149+
150150 // 出力
151151 if ( ! CommonUtils.write2file(txtname, sb.toString()) ) {
152152 System.err.println(ERRID+"保存に失敗しました: "+txtname);
153153 return false;
154154 }
155-
155+
156156 return true;
157157 }
158-
158+
159159 private int load() {
160-
160+
161161 String txt = CommonUtils.read4file(txtname, false);
162162 if ( txt == null ) {
163163 return -1;
@@ -166,7 +166,7 @@ public class PickedProgram extends TVProgramUtils implements TVProgram,Cloneable
166166 ArrayList<ProgList> newplist = new ArrayList<ProgList>();
167167
168168 int cnt = 0;
169-
169+
170170 while ( txt.length() > 0 )
171171 {
172172 if ( ! txt.startsWith(WrHeader.STARTMARK.toString()+S_CR) ) {
@@ -176,24 +176,24 @@ public class PickedProgram extends TVProgramUtils implements TVProgram,Cloneable
176176 if ( newtail == -1 ) {
177177 break;
178178 }
179-
179+
180180 // 今回の情報
181181 String data = txt.substring(WrHeader.STARTMARK.toString().length()+1, newtail+1);
182-
182+
183183 // 次回に続く
184184 txt = txt.substring(newtail+WrHeader.STARTMARK.toString().length()+1);
185-
185+
186186 // 放送局名
187187 String center = null;
188-
188+
189189 {
190190 int btail = 0;
191-
191+
192192 if ( ! data.startsWith(WrHeader.CENTER.toString()) ) {
193193 break;
194194 }
195195 data = data.substring(WrHeader.CENTER.toString().length());
196-
196+
197197 btail = data.indexOf(WrHeader.BEND.toString());
198198 if ( btail == -1 ) {
199199 break;
@@ -204,15 +204,15 @@ public class PickedProgram extends TVProgramUtils implements TVProgram,Cloneable
204204
205205 // 日付
206206 String date =null;
207-
207+
208208 {
209209 int btail = 0;
210-
210+
211211 if ( ! data.startsWith(WrHeader.DATE.toString()) ) {
212212 break;
213213 }
214214 data = data.substring(WrHeader.DATE.toString().length());
215-
215+
216216 btail = data.indexOf(WrHeader.BEND.toString());
217217 if ( btail == -1 ) {
218218 break;
@@ -222,7 +222,7 @@ public class PickedProgram extends TVProgramUtils implements TVProgram,Cloneable
222222 }
223223
224224 // 番組詳細へ
225-
225+
226226 // 解析する
227227 ProgList pcenter = null;
228228 for ( ProgList p : newplist ) {
@@ -237,7 +237,7 @@ public class PickedProgram extends TVProgramUtils implements TVProgram,Cloneable
237237 pcenter.pdate = new ArrayList<ProgDateList>();
238238 newplist.add(pcenter);
239239 }
240-
240+
241241 ProgDateList pdate = null;
242242 for ( ProgDateList p : pcenter.pdate ) {
243243 if ( p.Date.equals(date) ) {
@@ -251,15 +251,15 @@ public class PickedProgram extends TVProgramUtils implements TVProgram,Cloneable
251251 pdate.pdetail = new ArrayList<ProgDetailList>();
252252 pcenter.pdate.add(pdate);
253253 }
254-
254+
255255 cnt += loadDetail(pdate.pdetail,data);
256256 }
257-
257+
258258 pcenter = newplist;
259-
259+
260260 return cnt;
261261 }
262-
262+
263263 private int loadDetail(ArrayList<ProgDetailList> pdetail, String txt) {
264264 int index = 0;
265265 while ( index < txt.length() )
@@ -270,33 +270,33 @@ public class PickedProgram extends TVProgramUtils implements TVProgram,Cloneable
270270 break;
271271 }
272272 newtop += ProgDetailList.WrHeader.STARTMARK.toString().length()+1;
273-
273+
274274 // 番組フッタを探す
275275 int newtail = txt.indexOf(ProgDetailList.WrHeader.ENDMARK.toString(),newtop);
276276 if ( newtail == -1 ) {
277277 break;
278278 }
279279 index = newtail+ProgDetailList.WrHeader.ENDMARK.toString().length()+1;
280-
280+
281281 // 解析する
282282 ProgDetailList pdl = new ProgDetailList(txt.substring(newtop,newtail));
283283 pdetail.add(pdl);
284284
285285 }
286-
286+
287287 return pdetail.size();
288288 }
289289
290290 /*
291- * 日付でリフレッシュ
291+ * 日付でリフレッシュ
292292 */
293293 public void refresh() {
294-
294+
295295 GregorianCalendar cs = CommonUtils.getCalendar(0);
296296 if (CommonUtils.isLateNight(cs.get(Calendar.HOUR_OF_DAY))) {
297297 cs.add(Calendar.DATE, -1);
298298 }
299-
299+
300300 ArrayList<ProgList> tPlist = new ArrayList<ProgList>();
301301 for (ProgList tPl : pcenter) {
302302 GregorianCalendar c = (GregorianCalendar)cs.clone();
@@ -322,7 +322,7 @@ public class PickedProgram extends TVProgramUtils implements TVProgram,Cloneable
322322 }
323323 tPlist.add(pl);
324324 }
325-
325+
326326 pcenter = tPlist;
327327 }
328328
@@ -330,7 +330,7 @@ public class PickedProgram extends TVProgramUtils implements TVProgram,Cloneable
330330 * 追加しよう
331331 */
332332 public boolean add(ProgDetailList tvd) {
333-
333+
334334 ProgList pl = null;
335335 for (ProgList tPl : pcenter) {
336336 if (tPl.Center.equals(tvd.center)) {
@@ -360,7 +360,7 @@ public class PickedProgram extends TVProgramUtils implements TVProgram,Cloneable
360360 }
361361 pcenter.add(pl);
362362 }
363-
363+
364364 ProgDateList pcl = null;
365365 for (ProgDateList tPcl : pl.pdate) {
366366 if (tPcl.Date.equals(tvd.accurateDate)) {
@@ -378,19 +378,19 @@ public class PickedProgram extends TVProgramUtils implements TVProgram,Cloneable
378378 return false;
379379 }
380380 }
381-
381+
382382 // clone()する必要はあるのか?
383383 pcl.pdetail.add(tvd);
384-
384+
385385 return true;
386386 }
387387
388-
388+
389389 /*
390390 * 削除しよう
391391 */
392392 public boolean remove(ProgDetailList data, String center, String date, boolean force) {
393-
393+
394394 ProgList pl = null;
395395 for (ProgList tPl : pcenter) {
396396 if (tPl.Center.equals(center)) {
@@ -402,7 +402,7 @@ public class PickedProgram extends TVProgramUtils implements TVProgram,Cloneable
402402 // なんかおかしくねー
403403 return false;
404404 }
405-
405+
406406 ProgDateList pcl = null;
407407 for (ProgDateList tPcl : pl.pdate) {
408408 if (tPcl.Date.equals(date)) {
@@ -414,7 +414,7 @@ public class PickedProgram extends TVProgramUtils implements TVProgram,Cloneable
414414 // 過去ログとかね…
415415 return false;
416416 }
417-
417+
418418 for (ProgDetailList tPdl : pcl.pdetail) {
419419 if (tPdl.title.equals(data.title) && tPdl.start.equals(data.start) && tPdl.end.equals(data.end)) {
420420 if (force) {
@@ -425,22 +425,22 @@ public class PickedProgram extends TVProgramUtils implements TVProgram,Cloneable
425425 }
426426 return false;
427427 }
428-
428+
429429 /**
430430 * 指定した番組情報に対応するピックアップ情報を返す
431431 */
432432 public ProgDetailList find(ProgDetailList srctvd) {
433-
433+
434434 for ( ProgList tvpl : pcenter ) {
435435 if ( ! tvpl.Center.equals(srctvd.center) ) {
436436 continue;
437437 }
438-
438+
439439 for ( ProgDateList tvc : tvpl.pdate ) {
440440 if ( ! tvc.Date.equals(srctvd.accurateDate) ) {
441441 continue;
442442 }
443-
443+
444444 for ( ProgDetailList tvd : tvc.pdetail ) {
445445 if ( tvd.startDateTime.equals(srctvd.startDateTime) && tvd.endDateTime.equals(srctvd.endDateTime) ) {
446446 return tvd;
@@ -450,55 +450,55 @@ public class PickedProgram extends TVProgramUtils implements TVProgram,Cloneable
450450 }
451451 return null;
452452 }
453-
453+
454454 /* ここまで */
455-
456-
457-
455+
456+
457+
458458 /*
459459 * ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
460460 * ★★★★★ 放送地域を取得する(TVAreaから降格)-ここから ★★★★★
461461 * ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
462462 */
463-
463+
464464 /*
465465 * 公開メソッド
466466 */
467-
467+
468468 //
469469 @Override
470470 public String getDefaultArea() {return "東京";}
471-
471+
472472 //
473473 public void loadAreaCode() {}
474-
474+
475475 //
476476 public void saveAreaCode() {}
477-
477+
478478 /*
479479 * ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
480480 * ★★★★★ 放送地域を取得する(TVAreaから降格)-ここまで ★★★★★
481481 * ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
482482 */
483-
484-
485-
483+
484+
485+
486486 /*
487487 * ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
488488 * ★★★★★ 放送局を選択する(TVCenterから降格)-ここから ★★★★★
489489 * ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
490490 */
491-
491+
492492 /*
493493 * 公開メソッド
494494 */
495-
495+
496496 // 設定ファイルがなければWebから取得
497497 public void loadCenter(String code, boolean force) {}
498-
498+
499499 // 設定ファイルへ書き出し
500500 public boolean saveCenter() { return false; }
501-
501+
502502 /*
503503 * ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
504504 * ★★★★★ 放送局を選択する(TVCenterから降格)-ここまで ★★★★★
--- a/TinyBannavi/src/tainavi/SearchResult.java
+++ b/TinyBannavi/src/tainavi/SearchResult.java
@@ -11,104 +11,105 @@ public class SearchResult extends TVProgramUtils implements TVProgram,Cloneable
1111 /*******************************************************************************
1212 * 種族の特性
1313 ******************************************************************************/
14-
14+
1515 @Override
1616 public String getTVProgramId() { return tvProgId; }
1717 private static final String tvProgId = "SearchResult";
18-
18+
1919 @Override
2020 public boolean isAreaSelectSupported() { return false; }
21-
21+
2222 @Override
2323 public ProgType getType() { return ProgType.SEARCHED; }
24-
24+
2525 @Override
2626 public ProgSubtype getSubtype() { return ProgSubtype.NONE; }
27-
27+
2828 public PassedProgram clone() {
2929 return (PassedProgram) super.clone();
3030 }
31-
32-
31+
32+
3333 /*******************************************************************************
3434 * 個体の特性
3535 ******************************************************************************/
36-
36+
3737 @Override
3838 public int getTimeBarStart() { return 5; }
39-
39+
4040 // 検索結果を何件保存するか
4141 public void setResultBufferMax(int n) { resultBufferMax = n; }
4242 private int resultBufferMax = 5;
43-
44-
43+
44+
4545 /*******************************************************************************
4646 * 定数
4747 ******************************************************************************/
48-
49-
48+
49+
5050 /*******************************************************************************
5151 * コンストラクタ
5252 ******************************************************************************/
53-
53+
5454 public SearchResult() {
55-
55+
5656 super();
57-
57+
5858 // ガワ
5959 crlist = new ArrayList<Center>(); // 番組情報を全部破棄
6060 sortedcrlist = new ArrayList<Center>(); // 番組情報を全部破棄
6161 pcenter = new ArrayList<ProgList>(); // 番組情報を全部破棄
62-
62+
6363 }
6464
6565
6666 /*******************************************************************************
6767 * 検索結果固有
6868 ******************************************************************************/
69-
69+
7070 public ArrayList<ProgDetailList> getResultBuffer(final String label) {
71-
71+
7272 // 履歴保存先を指定サイズまで縮小
7373 for ( int i=pcenter.size(); i>=resultBufferMax && i>1; i-- ) {
7474 crlist.remove(i-1);
7575 pcenter.remove(i-1);
7676 }
77-
77+
7878 // 追加
7979 {
8080 Center srchcr = new Center();
8181 srchcr.setCenter(label);
82-
82+
8383 ProgList srchpl = new ProgList();
8484 srchpl.enabled = true;
8585 srchpl.Center = srchcr.getCenter();
8686 srchpl.pdate = new ArrayList<ProgDateList>();
87-
87+
8888 ProgDateList srchpdt = new ProgDateList();
8989 srchpdt.Date = CommonUtils.getDateTime(CommonUtils.getCalendar("2999/12/31 23:59"));
9090 srchpl.pdate.add(srchpdt);
91-
91+
9292 crlist.add(0,srchcr);
9393 //sortedcrlist.add(srchcr);
9494 pcenter.add(0,srchpl);
9595 }
96-
96+
9797 return pcenter.get(0).pdate.get(0).pdetail;
9898 }
9999
100100 public int getResultBufferSize() { return pcenter.size(); }
101-
101+
102102 public String getLabel(int index) { return pcenter.get(index).Center; }
103-
103+
104104 public ArrayList<ProgDetailList> getResult(int index) { return pcenter.get(index).pdate.get(0).pdetail; }
105-
105+
106106 /*******************************************************************************
107107 * 本体
108108 ******************************************************************************/
109-
109+
110110 @Override
111- public void loadProgram(String areaCode, boolean force) {
111+ public boolean loadProgram(String areaCode, boolean force) {
112+ return true;
112113 }
113114
114115 @Override
--- a/TinyBannavi/src/tainavi/StatusWindow.java
+++ b/TinyBannavi/src/tainavi/StatusWindow.java
@@ -1,9 +1,9 @@
11 package tainavi;
22
33 public interface StatusWindow {
4-
4+
55 public void clear();
6-
6+
77 /**
88 * 基本形
99 * @see #appendMessage(String)
@@ -12,6 +12,10 @@ public interface StatusWindow {
1212 public void append(String message);
1313 public void appendMessage(String message);
1414 public void appendError(String message);
15-
15+
1616 public void setVisible(boolean b);
17+
18+ public void setWindowCloseRequested(boolean b);
19+ public boolean isWindowCloseRequested();
20+ public void resetWindowCloseRequested();
1721 }
--- a/TinyBannavi/src/tainavi/TVProgram.java
+++ b/TinyBannavi/src/tainavi/TVProgram.java
@@ -21,15 +21,15 @@ public interface TVProgram {
2121 */
2222 public enum ProgOption { HIDDEN_NEW, HIDDEN_LAST, HIDDEN_NOSCRUMBLE, FIRST, REPEAT, LIVE, SPECIAL, NOSYOBO, SUBTITLE, BILINGUAL, STANDIN, PV, MULTIVOICE, DATA, SURROUND, NEWARRIVAL, MODIFIED, NONREPEATED, MOVED, PRECEDING, RATING };
2323
24- public static enum ProgGenre {
24+ public static enum ProgGenre {
2525 NEWS ("ニュース/報道", "0"),
2626 SPORTS ("スポーツ", "1"),
2727 VARIETYSHOW ("情報/ワイドショー", "2"),
28- DORAMA ("ドラマ", "3"),
28+ DORAMA ("ドラマ", "3"),
2929 MUSIC ("音楽", "4"),
3030 VARIETY ("バラエティー", "5"),
31- MOVIE ("映画", "6"),
32- ANIME ("アニメ/特撮", "7"),
31+ MOVIE ("映画", "6"),
32+ ANIME ("アニメ/特撮", "7"),
3333 DOCUMENTARY ("ドキュメンタリー/教養", "8"),
3434 THEATER ("劇場/公演", "9"),
3535 HOBBY ("趣味/教育", "A"),
@@ -37,24 +37,24 @@ public interface TVProgram {
3737 //KIDS ("キッズ", "ZZZ"), // もとからなかったらしい
3838 //EXTENTION ("拡張", "E"), // 非対応とする
3939 NOGENRE ("その他", "F");
40-
40+
4141 private String name;
4242 private String iepg;
43-
43+
4444 private ProgGenre(String name, String iepg) {
4545 this.name = name;
4646 this.iepg = iepg;
4747 }
48-
48+
4949 @Override
5050 public String toString() {
5151 return(name);
5252 }
53-
53+
5454 public String toIEPG() {
5555 return(iepg);
5656 }
57-
57+
5858 /**
5959 * ジャンル名文字列に一致するものを返す
6060 */
@@ -66,7 +66,7 @@ public interface TVProgram {
6666 }
6767 return null;
6868 }
69-
69+
7070 /**
7171 * IEPGで
7272 */
@@ -79,7 +79,7 @@ public interface TVProgram {
7979 return null;
8080 }
8181 };
82-
82+
8383 public static enum ProgSubgenre {
8484 NEWS_TEIJI (ProgGenre.NEWS, "定時・総合", "0"),
8585 NEWS_TENKI (ProgGenre.NEWS, "天気", "1"),
@@ -93,7 +93,7 @@ public interface TVProgram {
9393 NEWS_LOCAL (ProgGenre.NEWS, "ローカル・地域", "9"),
9494 NEWS_KOTSU (ProgGenre.NEWS, "交通", "A"),
9595 NEWS_ETC (ProgGenre.NEWS, "その他", "F"),
96-
96+
9797 SPORTS_NEWS (ProgGenre.SPORTS, "スポーツニュース", "0"),
9898 SPORTS_BASEBALL (ProgGenre.SPORTS, "野球", "1"),
9999 SPORTS_FOOTBALL (ProgGenre.SPORTS, "サッカー", "2"),
@@ -106,7 +106,7 @@ public interface TVProgram {
106106 SPORTS_MARINE (ProgGenre.SPORTS, "マリン・ウィンタースポーツ","9"),
107107 SPORTS_KEIBA (ProgGenre.SPORTS, "競馬・公営競技", "A"),
108108 SPORTS_ETC (ProgGenre.SPORTS, "その他", "F"),
109-
109+
110110 VSHOW_GEINO (ProgGenre.VARIETYSHOW, "芸能・ワイドショー", "0"),
111111 VSHOW_FASHION (ProgGenre.VARIETYSHOW, "ファッション", "1"),
112112 VSHOW_LIFE (ProgGenre.VARIETYSHOW, "暮らし・住まい", "2"),
@@ -116,12 +116,12 @@ public interface TVProgram {
116116 VSHOW_EVENT (ProgGenre.VARIETYSHOW, "イベント", "6"),
117117 VSHOW_INFO (ProgGenre.VARIETYSHOW, "番組紹介・お知らせ", "7"),
118118 VSHOW_ETC (ProgGenre.VARIETYSHOW, "その他", "F"),
119-
119+
120120 DRAMA_KOKUNAI (ProgGenre.DORAMA, "国内ドラマ", "0"),
121121 DRAMA_KAIGAI (ProgGenre.DORAMA, "海外ドラマ", "1"),
122122 DRAMA_JIDAI (ProgGenre.DORAMA, "時代劇", "2"),
123123 DRAMA_ETC (ProgGenre.DORAMA, "その他", "F"),
124-
124+
125125 MUSIC_KOKUNAI (ProgGenre.MUSIC, "国内ロック・ポップス", "0"),
126126 MUSIC_KAIGAI (ProgGenre.MUSIC, "海外ロック・ポップス", "1"),
127127 MUSIC_CLASSIC (ProgGenre.MUSIC, "クラシック・オペラ", "2"),
@@ -134,7 +134,7 @@ public interface TVProgram {
134134 MUSIC_DOYO (ProgGenre.MUSIC, "童謡・キッズ", "9"),
135135 MUSIC_MINZOKU (ProgGenre.MUSIC, "民族音楽・ワールドミュージック", "A"),
136136 MUSIC_ETC (ProgGenre.MUSIC, "その他", "F"),
137-
137+
138138 VARIETY_QUIZ (ProgGenre.VARIETY, "クイズ", "0"),
139139 VARIETY_GAME (ProgGenre.VARIETY, "ゲーム", "1"),
140140 VARIETY_TALK (ProgGenre.VARIETY, "トークバラエティ", "2"),
@@ -143,17 +143,17 @@ public interface TVProgram {
143143 VARIETY_TABI (ProgGenre.VARIETY, "旅バラエティ", "5"),
144144 VARIETY_RYORI (ProgGenre.VARIETY, "料理バラエティ", "6"),
145145 VARIETY_ETC (ProgGenre.VARIETY, "その他", "F"),
146-
146+
147147 MOVIE_YOGA (ProgGenre.MOVIE, "洋画", "0"),
148148 MOVIE_HOGA (ProgGenre.MOVIE, "邦画", "1"),
149149 MOVIE_ANIME (ProgGenre.MOVIE, "アニメ", "2"),
150150 MOVIE_ETC (ProgGenre.MOVIE, "その他", "F"),
151-
151+
152152 ANIME_KOKUNAI (ProgGenre.ANIME, "国内アニメ", "0"),
153153 ANIME_KAIGAI (ProgGenre.ANIME, "海外アニメ", "1"),
154154 ANIME_TOKUSATSU (ProgGenre.ANIME, "特撮", "2"),
155155 ANIME_ETC (ProgGenre.ANIME, "その他", "F"),
156-
156+
157157 DOC_SOCIAL (ProgGenre.DOCUMENTARY, "社会・時事", "0"),
158158 DOC_HISTORY (ProgGenre.DOCUMENTARY, "歴史・紀行", "1"),
159159 DOC_NATURE (ProgGenre.DOCUMENTARY, "自然・動物・環境", "2"),
@@ -164,14 +164,14 @@ public interface TVProgram {
164164 DOC_DOCUMENTARY (ProgGenre.DOCUMENTARY, "ドキュメンタリー全般", "7"),
165165 DOC_INTERVIEW (ProgGenre.DOCUMENTARY, "インタビュー・討論", "8"),
166166 DOC_ETC (ProgGenre.DOCUMENTARY, "その他", "F"),
167-
167+
168168 THEATER_GENDAI (ProgGenre.THEATER, "現代劇・新劇", "0"),
169169 THEATER_MUSICAL (ProgGenre.THEATER, "ミュージカル", "1"),
170170 THEATER_DANCE (ProgGenre.THEATER, "ダンス・バレエ", "2"),
171171 THEATER_RAKUGO (ProgGenre.THEATER, "落語・演芸", "3"),
172172 THEATER_KABUKI (ProgGenre.THEATER, "歌舞伎・古典", "4"),
173173 THEATER_ETC (ProgGenre.THEATER, "その他", "F"),
174-
174+
175175 HOBBY_TABI (ProgGenre.HOBBY, "旅・釣り・アウトドア", "0"),
176176 HOBBY_ENGEI (ProgGenre.HOBBY, "園芸・ペット・手芸", "1"),
177177 HOBBY_MUSIC (ProgGenre.HOBBY, "音楽・美術・工芸", "2"),
@@ -186,7 +186,7 @@ public interface TVProgram {
186186 HOBBY_SHOGAI (ProgGenre.HOBBY, "生涯教育・資格", "B"),
187187 HOBBY_KYOIKU (ProgGenre.HOBBY, "教育問題", "C"),
188188 HOBBY_ETC (ProgGenre.HOBBY, "その他", "F"),
189-
189+
190190 WELFARE_KOUREI (ProgGenre.WELFARE, "高齢者", "0"),
191191 WELFARE_SHOGAI (ProgGenre.WELFARE, "障害者", "1"),
192192 WELFARE_HUKUSHI (ProgGenre.WELFARE, "社会福祉", "2"),
@@ -195,38 +195,38 @@ public interface TVProgram {
195195 WELFARE_MOJI (ProgGenre.WELFARE, "文字(字幕)", "5"),
196196 WELFARE_ONSEI (ProgGenre.WELFARE, "音声解説", "6"),
197197 WELFARE_ETC (ProgGenre.WELFARE, "その他", "F"),
198-
198+
199199 NOGENRE_ETC (ProgGenre.NOGENRE, "その他", "F"),
200-
200+
201201 ;
202-
202+
203203 private ProgGenre genre;
204204 private String name;
205205 private String iepg;
206-
206+
207207 private ProgSubgenre(ProgGenre genre, String name, String iepg) {
208208 this.genre = genre;
209209 this.name = name;
210210 this.iepg = iepg;
211211 }
212-
212+
213213 @Override
214214 public String toString() {
215215 return(name);
216216 }
217-
217+
218218 public String toFullString() {
219219 return genre.toString()+" - "+name;
220220 }
221-
221+
222222 public String toIEPG() {
223223 return(iepg);
224224 }
225-
225+
226226 public ProgGenre getGenre() {
227227 return(genre);
228228 }
229-
229+
230230 public static ArrayList<ProgSubgenre> values(ProgGenre gr) {
231231 ArrayList<ProgSubgenre> ga = new ArrayList<TVProgram.ProgSubgenre>();
232232 for ( ProgSubgenre g : ProgSubgenre.values() ) {
@@ -256,7 +256,7 @@ public interface TVProgram {
256256 }
257257 return null;
258258 }
259-
259+
260260 public static ProgSubgenre getByIEPG(ProgGenre gr, String iepg) {
261261 for ( ProgSubgenre g : ProgSubgenre.values(gr) ) {
262262 if ( g.iepg.equals(iepg) ) {
@@ -266,7 +266,7 @@ public interface TVProgram {
266266 return null;
267267 }
268268 };
269-
269+
270270 public static final Object[][] optMarks = {
271271 { ProgOption.HIDDEN_NEW, "【新】新番組" },
272272 { ProgOption.HIDDEN_LAST, "【終】最終回" },
@@ -290,7 +290,7 @@ public interface TVProgram {
290290 { ProgOption.MODIFIED, "(更)番組詳細に更新あり - 予約待機分のみ" },
291291 { ProgOption.MOVED, "(移)先週無かったか時間が違う" },
292292 };
293-
293+
294294 public static final String[] OKINIIRI = {"★★★★★","★★★★","★★★","★★","★",""};
295295
296296 // エリアコード
@@ -298,7 +298,7 @@ public interface TVProgram {
298298 public static final String trCode = "tr";
299299 public static final String bsCode = "bs";
300300 public static final String csCode = "cs";
301-
301+
302302 // タイトルの頭の邪魔な文字
303303 public static final String titlePrefixRemoveExpr = "^(\\[(新|無|字|終|HV|SS|二|映|無料)\\]|無料≫|【無料】|【アニメ】)+\\s*";
304304 public static final String epnoNormalizeExpr = "([第#(])(\\d\\D|\\d$)";
@@ -311,7 +311,7 @@ public interface TVProgram {
311311
312312 // 個体の特性
313313 // なし
314-
314+
315315 /*
316316 * TVProgramRefreshクラスを継承する部分 ←そんなクラスあったっけ…?
317317 */
@@ -323,24 +323,24 @@ public interface TVProgram {
323323 public void setExtension(String spoexSearchStart, String spoexSearchEnd, boolean spoexLimitation, ArrayList<SearchKey> extKeys);
324324 public void abon(ArrayList<String> ngword);
325325 public String chkComplete();
326-
326+
327327 //public void setAbnormal(boolean b);
328328 //public boolean getAbnormal();
329-
329+
330330 public ProgType getType();
331331 public ProgSubtype getSubtype();
332332
333333 public void setDebug(boolean b);
334334 //public boolean setProxy(String host, String port);
335-
335+
336336 /*
337337 * 公開メソッドP(番組表)
338338 */
339- public void loadProgram(String areaCode, boolean force);
339+ public boolean loadProgram(String areaCode, boolean force);
340340 public int getTimeBarStart();
341341 public void setExpandTo8(boolean b);
342342 public void setUseDetailCache(boolean b);
343-
343+
344344 /*
345345 * 公開メソッドA(地域設定)
346346 */
@@ -354,16 +354,16 @@ public interface TVProgram {
354354 public String setSelectedAreaByCode(String code);
355355 public String getSelectedArea();
356356 public String getSelectedCode();
357-
357+
358358 /*
359359 * 公開メソッドC(放送局設定)
360360 */
361361 //public void loadCenter();
362362 public void loadCenter(String code, boolean force);
363363 public boolean saveCenter();
364-
364+
365365 /*
366- *
366+ *
367367 */
368368 public void setUserAgent(String s);
369369 public void setProgDir(String s);
@@ -373,10 +373,10 @@ public interface TVProgram {
373373 public void setContinueTomorrow(boolean b);
374374 public void setSplitEpno(boolean b);
375375 //public String[] doSplitEpno(ProgGenre genre, String title);
376-
376+
377377 // 拡張機能!
378378 public boolean setOptString(String s);
379379 public String getOptString();
380-
381-
380+
381+
382382 }
--- a/TinyBannavi/src/tainavi/TVProgramUtils.java
+++ b/TinyBannavi/src/tainavi/TVProgramUtils.java
@@ -40,30 +40,30 @@ public class TVProgramUtils implements Cloneable {
4040 /*******************************************************************************
4141 * ディープコピーが意外と大変
4242 ******************************************************************************/
43-
43+
4444 @Override
4545 public TVProgramUtils clone() {
4646 try {
4747 TVProgramUtils p = (TVProgramUtils) super.clone();
48-
48+
4949 // フィールドコピーしてもらいたくないもの
5050 p.pcenter = null;
51-
51+
5252 // static化したのでコピー抑制を必要としなくなったものたち
5353 //p.setProgressArea(null);
5454 //p.setChConv(null);
55-
55+
5656 FieldUtils.deepCopy(p, this); // ディープコピーするよ
57-
57+
5858 p.pcenter = new ArrayList<ProgList>();
59-
59+
6060 /*
6161 // 地域設定をコピー
6262 p.aclist = new ArrayList<AreaCode>();
6363 for ( AreaCode ac : aclist ) {
6464 p.aclist.add(ac.clone());
6565 }
66-
66+
6767 // 放送局設定をコピー
6868 p.crlist = new ArrayList<Center>();
6969 for ( Center cr : crlist ) {
@@ -74,17 +74,17 @@ public class TVProgramUtils implements Cloneable {
7474 p.setSortedCRlist();
7575
7676 return p;
77-
77+
7878 } catch (CloneNotSupportedException e) {
7979 throw new InternalError(e.toString());
8080 }
8181 }
82-
83-
82+
83+
8484 /*******************************************************************************
8585 * 共通情報
8686 ******************************************************************************/
87-
87+
8888 /**
8989 * Proxy
9090 */
@@ -102,72 +102,86 @@ public class TVProgramUtils implements Cloneable {
102102 proxy = newproxy;
103103 return true;
104104 }
105-
105+
106106 private Proxy getProxy() { return proxy; }
107-
107+
108108 private static Proxy proxy = null;
109-
109+
110110 /**
111111 * ChannelConvert.dat
112112 */
113113 public static void setChConv(ChannelConvert cc) { chconv = cc; }
114-
114+
115115 private ChannelConvert getChConv() { return chconv; }
116-
116+
117117 private static ChannelConvert chconv = null;
118-
118+
119119 /**
120120 * ログと進捗ダイアログ
121121 */
122122 public static void setProgressArea(StatusWindow o) { stw = o; }
123-
124- protected void reportProgress(String msg) {
125- if (stw != null) {
123+ public static void setProgressAreaBackground(StatusTextArea o){ mwinBackground = o; }
124+
125+ public static void reportProgress(String msg) {
126+ if (mwinBackground != null){
127+ mwinBackground.appendMessage(msg);
128+ }
129+ else if (stw != null) {
126130 stw.append(msg);
127131 }
128132 System.out.println(msg);
129133 }
130134
131135 private static StatusWindow stw = null;
132-
133-
136+ private static StatusTextArea mwinBackground = null;
137+
138+ public static void setCancelRequested(boolean b){ cancelRequested = b; }
139+ public static boolean isCancelRequested(){
140+ if (stw != null && stw.isWindowCloseRequested())
141+ return true;
142+
143+ return cancelRequested;
144+ }
145+
146+ private static boolean cancelRequested = false;
147+
134148 /*******************************************************************************
135149 * オプション確認
136150 ******************************************************************************/
137-
151+
138152 public boolean isAreaSelectSupported() { return true; } // デフォルトはエリアを選べる
139-
140-
153+
154+
141155 /*******************************************************************************
142156 * 定数
143157 ******************************************************************************/
144-
158+
145159 // コネクションタイムアウト
146160 private static final int conntout = 5;
147-
161+
148162 // read()タイムアウト
149163 private static final int readtout = 30;
150164
151165 // 番組表が複数ページに跨っている場合、何ページまで追いかけるか
152166 protected static final int REFPAGESMAX = 10;
153-
167+
154168 // 番組詳細に情報をconcatする時のセパレータ
155169 protected final String DETAIL_SEP = "\n\n";
156-
170+
157171 // メッセージID
158172 private static final String MSGID = "[番組表共通] ";
159173 private static final String DBGID = "[DEBUG]"+MSGID;
160174 private static final String ERRID = "[ERROR]"+MSGID;
161-
175+
162176 /*******************************************************************************
163177 * メンバ変数関連
164178 ******************************************************************************/
165-
179+
166180 // デバッグフラグ
167181 public void setDebug(boolean b) { debug = b; }
168182 protected boolean getDebug() { return debug; } // 参照はサブクラスのみに許可
169183 private boolean debug = false;
170-
184+
171185 // 通信エラー時のリトライ回数
172186 protected void setRetryCount(int n) { retrycount = n; } // サブクラスのみに許可(特殊)
173187 private int retrycount = 1;
@@ -181,65 +195,65 @@ public class TVProgramUtils implements Cloneable {
181195 public String getProgDir() { return progDir; }
182196 public void setProgDir(String s) { progDir = s; }
183197 private String progDir = "progcache";
184-
198+
185199 // 番組表キャッシュの有効時間(H)
186200 public int getCacheExpired() { return cacheExpired; }
187201 public void setCacheExpired(int h) { cacheExpired = h; }
188202 private int cacheExpired = 6;
189-
203+
190204 // 番組詳細取得を行なうかどうか
191205 public boolean getUseDetailCache() { return useDetailCache; }
192206 public void setUseDetailCache(boolean b) { useDetailCache = b; }
193207 private boolean useDetailCache = true;
194-
208+
195209 // 29時跨ぎで2つに分かれた番組情報をくっつけるかどうか
196210 public boolean getContinueTomorrow() { return continueTomorrow; }
197211 public void setContinueTomorrow(boolean b) { continueTomorrow = b; }
198212 private boolean continueTomorrow = false;
199-
213+
200214 // タイトルから話数以降を分離する
201215 public void setSplitEpno(boolean b) { splitEpno = b; }
202216 public boolean isSplitEpno() { return splitEpno; }
203217 private boolean splitEpno = true;
204-
218+
205219 // 可能なら8日分取得する
206220 public boolean getExpandTo8() { return expandTo8; }
207221 public void setExpandTo8(boolean b) { expandTo8 = b; }
208222 private boolean expandTo8 = false;
209-
223+
210224 // 番組詳細キャッシュをオンライン取得するかどうか
211225 @Deprecated
212226 protected boolean isForceLoadDetInfo() { return forceLoadDetInfo; }
213227 @Deprecated
214228 private boolean forceLoadDetInfo = false;
215-
229+
216230 // もう使っていないようだ
217231 //public void setAbnormal(boolean b) { abnormal = b; }
218232 //public boolean getAbnormal() { return abnormal; }
219233 //private boolean abnormal = false;
220234
221-
235+
222236 /*******************************************************************************
223237 * 番組表固有の情報
224238 ******************************************************************************/
225239
226-
240+
227241 /*******************************************************************************
228242 * 番組情報
229243 ******************************************************************************/
230-
244+
231245 /**
232246 * <P>番組表が格納される場所
233247 * <P>上から順の{@link ProgList}(pcenter/放送局別)->{@link ProgDateList}(pdate/日付別)→{@link ProgDetailList}pdetail/(番組詳細)
234248 */
235249 public ArrayList<ProgList> getCenters() { return(pcenter); }
236250 public ArrayList<ProgList> pcenter = new ArrayList<ProgList>();
237-
238-
251+
252+
239253 /*******************************************************************************
240254 * 放送局情報
241255 ******************************************************************************/
242-
256+
243257 /**
244258 * 放送局名リスト
245259 * @see ProgList#Center
@@ -247,7 +261,7 @@ public class TVProgramUtils implements Cloneable {
247261 */
248262 public ArrayList<Center> getCRlist() { return(crlist); }
249263 public ArrayList<Center> crlist = new ArrayList<Center>();
250-
264+
251265 /**
252266 * ソート済み放送局名リスト
253267 * @see ProgList#Center
@@ -266,7 +280,7 @@ public class TVProgramUtils implements Cloneable {
266280 }
267281 }
268282 public ArrayList<Center> sortedcrlist = new ArrayList<Center>();
269-
283+
270284 // 設定ファイルへ書き出し
271285 public boolean saveCenter() {
272286 String centerListFile = getCenterListFile(getTVProgramId(), getSelectedCode());
@@ -277,12 +291,12 @@ public class TVProgramUtils implements Cloneable {
277291 System.out.println("放送局リストを保存しました: "+centerListFile+", "+getSelectedCode());
278292 return true;
279293 }
280-
294+
281295 // 放送局リストファイル名
282296 protected String getCenterListFile(String id, String code) {
283297 return String.format("env%scenter.%s.%s.xml", File.separator, id, code);
284298 }
285-
299+
286300 // 放送局名に一括してフィルタをかける
287301 protected void attachChFilters() {
288302 for ( Center c : crlist ) {
@@ -292,7 +306,7 @@ public class TVProgramUtils implements Cloneable {
292306 c.setCenter(getChConv().get(c.getCenterOrig()));
293307 }
294308 }
295-
309+
296310 // 放送局名個別にフィルタをかけたい
297311 protected String getChName(String chorig) {
298312 return getChConv().get(chorig);
@@ -302,13 +316,13 @@ public class TVProgramUtils implements Cloneable {
302316 /*******************************************************************************
303317 * 地域情報
304318 ******************************************************************************/
305-
319+
306320 /**
307321 * 地域コード のリストを取得する
308322 */
309323 public ArrayList<AreaCode> getAClist() { return(aclist); }
310324 public ArrayList<AreaCode> aclist = new ArrayList<AreaCode>();
311-
325+
312326 /**
313327 * 地域コードから地域名を取得
314328 */
@@ -332,7 +346,7 @@ public class TVProgramUtils implements Cloneable {
332346 }
333347 return(null);
334348 }
335-
349+
336350 /**
337351 * 地域名を指定して選択中の地域を変更し、ついでにその地域コードを返す
338352 * @see #getSelectedCode()
@@ -353,7 +367,7 @@ public class TVProgramUtils implements Cloneable {
353367 }
354368 return(null);
355369 }
356-
370+
357371 /**
358372 * 地域コードを指定して選択中の地域を変更し、ついでにその地域名を返す
359373 * @see #getSelectedArea()
@@ -374,7 +388,7 @@ public class TVProgramUtils implements Cloneable {
374388 }
375389 return(null);
376390 }
377-
391+
378392 /**
379393 * 選択中の地域名を返す
380394 */
@@ -398,7 +412,7 @@ public class TVProgramUtils implements Cloneable {
398412 }
399413 return(getCode(getDefaultArea()));
400414 }
401-
415+
402416 // 設定ファイルへ書き出し
403417 public void saveAreaCode() {
404418 if ( CommonUtils.writeXML(getAreaSelectedFile(), aclist) ) {
@@ -408,17 +422,17 @@ public class TVProgramUtils implements Cloneable {
408422 System.err.println(ERRID+"地域リストの保存に失敗しました: "+getAreaSelectedFile());
409423 }
410424 }
411-
425+
412426 // 地域情報ファイル名
413427 protected String getAreaSelectedFile() {
414428 return String.format("env%sarea.%s.xml", File.separator, getTVProgramId());
415429 }
416-
417-
430+
431+
418432 /*******************************************************************************
419433 * タイトル操作関連
420434 ******************************************************************************/
421-
435+
422436 /**
423437 * 話数重複排除
424438 */
@@ -428,7 +442,7 @@ public class TVProgramUtils implements Cloneable {
428442 if ( ! md.find() ) {
429443 return title;
430444 }
431-
445+
432446 ArrayList<String> tnoa = new ArrayList<String>();
433447 {
434448 Matcher me = Pattern.compile("(\\d+)").matcher(md.group(1));
@@ -439,7 +453,7 @@ public class TVProgramUtils implements Cloneable {
439453 return title;
440454 }
441455 }
442-
456+
443457 // 番組詳細と重複しているかな?
444458 {
445459 ArrayList<String> dnoa = new ArrayList<String>();
@@ -455,7 +469,7 @@ public class TVProgramUtils implements Cloneable {
455469 if ( dnoa.size() == 0 ) {
456470 return title;
457471 }
458-
472+
459473 for ( String tno : tnoa ) {
460474 for ( String dno : dnoa ) {
461475 if ( dno.equals(tno) ) {
@@ -468,22 +482,22 @@ public class TVProgramUtils implements Cloneable {
468482 title = md.replaceFirst("");
469483 }
470484 }
471-
485+
472486 return title;
473487 }
474-
488+
475489 /**
476490 * サブタイトルの分離
477491 * @param pdl
478492 */
479493 protected void doSplitSubtitle(ProgDetailList pdl) {
480-
494+
481495 pdl.splitted_title = doCutDupEpno(pdl.title, pdl.detail); // タイトルと番組詳細中の話数の重複排除
482-
496+
483497 String [] d = doSplitEpno(pdl.genre, pdl.splitted_title); // 分離!
484-
498+
485499 pdl.splitted_title = pdl.title.substring(0,d[0].length());
486-
500+
487501 if ( d[1].length() > 0 ) {
488502 // 番組詳細はサブタイトル分離番組詳細へのポインタでいいよ
489503 pdl.splitted_detail = d[1]+DETAIL_SEP+pdl.detail;
@@ -493,7 +507,7 @@ public class TVProgramUtils implements Cloneable {
493507 // サブタイトルが分離されなかったから同じでいいよ
494508 pdl.splitted_detail = pdl.detail;
495509 }
496-
510+
497511 // タイトル&番組詳細のキーワード検索情報の設定
498512 String key_title;
499513 String key_detail;
@@ -508,11 +522,11 @@ public class TVProgramUtils implements Cloneable {
508522 }
509523 pdl.titlePop = TraceProgram.replacePop(key_title);
510524 pdl.detailPop = TraceProgram.replacePop(key_detail);
511-
525+
512526 // 分離しない場合でも、番組追跡はサブタイトル抜きでの検索ができるようにしたい
513527 pdl.splitted_titlePop = TraceProgram.replacePop(pdl.splitted_title);
514528 }
515-
529+
516530 /**
517531 * サブタイトル分離(Part.11 444-)
518532 */
@@ -559,14 +573,14 @@ public class TVProgramUtils implements Cloneable {
559573 }
560574 return(new String[] { title,"" });
561575 }
562-
576+
563577 // サブタイトル判定条件
564578 private static final String SPEP_EXPR = "(([<<]?[((##♯第全「][第]?[12345678901234567890一二三四五六七八九十百千]+?[回話章]?|「).*)$";
565-
579+
566580 // サブタイトル判定条件(ジャンル=ドラマ専用)
567581 private static final String SPEP_EXPR_DORAMA = "^(.+?)[  ]*?(([<<]?[((##♯第全「][第]?[12345678901234567890一二三四五六七八九十百千]+?[回話章]?).*)$";
568-
569-
582+
583+
570584 /**
571585 * NGワード
572586 */
@@ -588,13 +602,13 @@ public class TVProgramUtils implements Cloneable {
588602 }
589603 }
590604 }
591-
592-
593-
605+
606+
607+
594608 /*******************************************************************************
595609 * 番組情報キャッシュ
596610 ******************************************************************************/
597-
611+
598612 // キャッシュファイルが有効期限内か確認する
599613 public boolean isCacheOld(String fname) {
600614 // キャッシュ期限が無期限の場合はDL禁止
@@ -619,7 +633,7 @@ public class TVProgramUtils implements Cloneable {
619633 }
620634 }
621635 else {
622- // ファイルを作成
636+ // ファイルを作成
623637 f.createNewFile();
624638 return(true);
625639 }
@@ -630,12 +644,12 @@ public class TVProgramUtils implements Cloneable {
630644 }
631645 return(false);
632646 }
633-
634-
647+
648+
635649 /*******************************************************************************
636650 * 番組詳細キャッシュ(現在は使われていない)
637651 ******************************************************************************/
638-
652+
639653 /**
640654 * 番組詳細をオンライン取得するかどうか
641655 */
@@ -657,11 +671,11 @@ public class TVProgramUtils implements Cloneable {
657671 forceLoadDetInfo = false;
658672 }
659673 }
660-
674+
661675 // 番組詳細キャッシュのLOAD
662676 @Deprecated
663677 protected HashMap<String,String> loadDetCache(){
664-
678+
665679 // 設定ファイルが存在していればファイルから
666680 File f = new File(getDetCacheFile());
667681 if (f.exists() == true) {
@@ -670,14 +684,14 @@ public class TVProgramUtils implements Cloneable {
670684 if ( cache != null ) {
671685 return cache;
672686 }
673-
687+
674688 System.out.println(ERRID+"【致命的エラー】番組詳細キャッシュが読み込めません: "+getDetCacheFile());
675689 }
676-
690+
677691 // キャッシュなし&エラーは空配列を返す
678692 return new HashMap<String, String>();
679693 }
680-
694+
681695 // 番組詳細キャッシュのSAVE
682696 @Deprecated
683697 protected void saveDetCache(HashMap<String,String> cache) {
@@ -685,18 +699,18 @@ public class TVProgramUtils implements Cloneable {
685699 System.err.println(ERRID+"【致命的エラー】番組詳細キャッシュが書き込めません: "+getDetCacheFile());
686700 }
687701 }
688-
689-
702+
703+
690704 /*******************************************************************************
691705 * 番組情報のリフレッシュ関連
692706 ******************************************************************************/
693-
707+
694708 /**
695709 * 日付変更線(29:00)をまたいだら過去のデータはカットする
696710 * <B> PassedProgramでは使わない
697711 */
698712 public void refresh() {
699-
713+
700714 String critDate = CommonUtils.getDate529(0, true);
701715 for ( ProgList p : pcenter ) {
702716 int i = 0;
@@ -711,7 +725,7 @@ public class TVProgramUtils implements Cloneable {
711725 }
712726 }
713727 }
714-
728+
715729 /**
716730 * 24時間分番組枠が埋まっているかどうか確認する
717731 */
@@ -739,30 +753,30 @@ public class TVProgramUtils implements Cloneable {
739753 }
740754 return null;
741755 }
742-
756+
743757 /**
744758 * 開始終了日時の整理
745759 */
746760 public void setAccurateDate(ArrayList<ProgDateList> pcenter) {
747-
761+
748762 // 先頭のエントリの開始時刻が 5:00 以前の場合
749763 for ( ProgDateList pcl : pcenter ) {
750764 if (pcl.pdetail.size() <= 0) {
751765 continue;
752766 }
753-
767+
754768 ProgDetailList pd = pcl.pdetail.get(0);
755769 Matcher ma = Pattern.compile("(\\d\\d):(\\d\\d)").matcher(pd.start);
756770 if (ma.find()) {
757771 int prelength = 0;
758772 int ahh = Integer.valueOf(ma.group(1));
759773 int amm = Integer.valueOf(ma.group(2));
760-
774+
761775 GregorianCalendar c = new GregorianCalendar();
762776 c.setTime(new Date());
763777 c.set(Calendar.HOUR_OF_DAY, ahh);
764778 c.set(Calendar.MINUTE, amm);
765-
779+
766780 if ( pd.start.compareTo("05:00") < 0 ) {
767781 // 5:00以前
768782 prelength = (5*60+0)-(ahh*60+amm);
@@ -779,20 +793,20 @@ public class TVProgramUtils implements Cloneable {
779793 }
780794
781795 for ( ProgDateList pcl : pcenter ) {
782-
796+
783797 GregorianCalendar c = CommonUtils.getCalendar(pcl.Date);
784-
798+
785799 boolean extend = false;
786800 boolean overtwodays = false;
787801 for ( int i=0; i<pcl.pdetail.size(); i++ ) {
788-
802+
789803 ProgDetailList pdl = pcl.pdetail.get(i);
790-
804+
791805 // 番組情報がありません
792806 if (pdl.start.compareTo("") == 0) {
793807 continue;
794808 }
795-
809+
796810 // 表示上の開始日時
797811 if ( i == 0 ) {
798812 if ( pdl.start.compareTo("18:00") >= 0 && pdl.start.compareTo("24:00") < 0 ) {
@@ -808,10 +822,10 @@ public class TVProgramUtils implements Cloneable {
808822 }
809823 }
810824 pdl.startDateTime = String.format("%s %s", CommonUtils.getDate(c,false), pdl.start);
811-
825+
812826 // 正確な開始日
813827 pdl.accurateDate = CommonUtils.getDate(c);
814-
828+
815829 // 表示上の終了日時
816830 if ( overtwodays ) {
817831 c.add(Calendar.DAY_OF_MONTH, 1);
@@ -823,11 +837,11 @@ public class TVProgramUtils implements Cloneable {
823837 extend = true;
824838 }
825839 }
826-
840+
827841 pdl.endDateTime = String.format("%s %s", CommonUtils.getDate(c,false), pdl.end);
828842 }
829843 }
830-
844+
831845 // 29時をまたいで同タイトルが続いている場合は同一番組とみなす
832846 if ( continueTomorrow ) {
833847 for (int w=0; w<pcenter.size()-1; w++) {
@@ -837,7 +851,7 @@ public class TVProgramUtils implements Cloneable {
837851 if (pd1.title.equals(pd2.title)) {
838852 pd1.end = pd2.end;
839853 pd1.endDateTime = pd2.endDateTime;
840-
854+
841855 pd2.start = pd1.start;
842856 pd2.startDateTime = pd1.startDateTime;
843857 pd2.accurateDate = pd1.accurateDate;
@@ -845,11 +859,11 @@ public class TVProgramUtils implements Cloneable {
845859 else if (pd2.title.equals("承前")) {
846860 pd1.end = pd2.end;
847861 pd1.endDateTime = pd2.endDateTime;
848-
862+
849863 pd2.start = pd1.start;
850864 pd2.startDateTime = pd1.startDateTime;
851865 pd2.accurateDate = pd1.accurateDate;
852-
866+
853867 pd2.title = pd1.title;
854868 pd2.detail = pd1.detail;
855869 pd2.setAddedDetail(pd1.getAddedDetail());
@@ -865,37 +879,37 @@ public class TVProgramUtils implements Cloneable {
865879 }
866880 }
867881 }
868-
882+
869883 // 以前に取得したデータから当日の取得不能領域のデータを補完する
870884 protected void CompensatesPrograms(ArrayList<ProgList> newplist) {
871885 //
872886 for ( ProgList newpl : newplist ) {
873-
887+
874888 if ( newpl.enabled != true ) {
875889 // 無効局は処理なし
876890 continue;
877891 }
878-
879- ArrayList<ProgDateList> newpcla = newpl.pdate;
892+
893+ ArrayList<ProgDateList> newpcla = newpl.pdate;
880894 if ( newpcla.size() == 0 ) {
881895 // 日付リストが存在しない場合は処理なし
882896 continue;
883897 }
884898 ProgDateList newpcl = newpcla.get(0);
885-
899+
886900 ArrayList<ProgDetailList> newpdla = newpcl.pdetail;
887901 if ( newpdla.size() == 0 ) {
888902 // 番組情報が存在しない場合は処理なし
889903 if (debug) System.out.println(DBGID+"番組表情報がないので過去ログは参照しない: "+newpcl.Date+" "+newpl.Center);
890904 continue;
891905 }
892-
906+
893907 if ( newpdla.get(0).start.length() != 0 ) {
894908 // 先頭の番組情報が「番組情報がありません」以外の場合は処理なし
895909 if (debug) System.out.println(DBGID+"先頭から有効な情報なので過去ログは参照しない: "+newpcl.Date+" "+newpl.Center+" "+newpdla.get(0).start+" "+newpdla.get(0).title);
896910 continue;
897911 }
898-
912+
899913 PassedProgram oldplist = new PassedProgram();
900914 if ( ! oldplist.loadByCenter(newpcl.Date, newpl.Center) || oldplist.getProgCount() == 0 ) {
901915 // 過去情報が取得できなければ処理なし
@@ -903,7 +917,7 @@ public class TVProgramUtils implements Cloneable {
903917 continue;
904918 }
905919 ProgDateList oldpcl = oldplist.pcenter.get(0).pdate.get(0);
906-
920+
907921 // 補填候補抽出
908922 ArrayList<ProgDetailList> tmppdla = new ArrayList<ProgDetailList>();
909923 if ( newpdla.size() == 1 ) {
@@ -930,7 +944,7 @@ public class TVProgramUtils implements Cloneable {
930944 idx++;
931945 }
932946 }
933-
947+
934948 // 先頭の「番組情報はありません」と差し替えて補填
935949 newpdla.remove(0);
936950 for ( int i=0; i<tmppdla.size(); i++ ) {
@@ -949,11 +963,11 @@ public class TVProgramUtils implements Cloneable {
949963 pcl.pdetail.add(pdl);
950964 pcl.row += pdl.length;
951965 }
952-
966+
953967 /*******************************************************************************
954968 * フラグ処理関連
955969 ******************************************************************************/
956-
970+
957971 /**
958972 * 延長警告を設定する
959973 */
@@ -961,10 +975,10 @@ public class TVProgramUtils implements Cloneable {
961975 //
962976 for ( ProgList p : pcenter ) {
963977 // 局ごと
964-
978+
965979 // キーワード検索用
966980 String centerPop = TraceProgram.replacePop(p.Center);
967-
981+
968982 for ( ProgDateList c : p.pdate ) {
969983 // 日ごと
970984 boolean poisoned = false;
@@ -989,23 +1003,23 @@ public class TVProgramUtils implements Cloneable {
9891003 if (soi) {
9901004 poisoned = true;
9911005 }
992-
1006+
9931007 d.extension = poisoned;
9941008 }
9951009 }
9961010 }
9971011 }
998-
1012+
9991013 /*
10001014 * タイトルからフラグを抽出する
10011015 */
10021016 protected void doSplitFlags(ProgDetailList pdl, HashMap<String, String> nf) {
1003-
1017+
10041018 Matcher md = Pattern.compile("(#1|第1話)\\b").matcher(pdl.title);
10051019 if ( md.find() ) {
10061020 pdl.flag = ProgFlags.NEW;
10071021 }
1008-
1022+
10091023 md = Pattern.compile("([  ]?[<<]新[>>]| 新$| NEW$)").matcher(pdl.title);
10101024 if ( md.find() ) {
10111025 pdl.flag = ProgFlags.NEW;
@@ -1014,7 +1028,7 @@ public class TVProgramUtils implements Cloneable {
10141028 md = Pattern.compile("([  ]?[<<]終[>>]| 終$| END$)").matcher(pdl.title);
10151029 if ( md.find() ) {
10161030 pdl.flag = ProgFlags.LAST;
1017- pdl.title = md.replaceAll("");
1031+ pdl.title = md.replaceAll("");
10181032 }
10191033 md = Pattern.compile("[((]終[))]",Pattern.DOTALL).matcher(pdl.detail);
10201034 if ( md.find() ) {
@@ -1023,9 +1037,9 @@ public class TVProgramUtils implements Cloneable {
10231037 md = Pattern.compile("^無料≫").matcher(pdl.title);
10241038 if ( md.find() ) {
10251039 pdl.noscrumble = ProgScrumble.NOSCRUMBLE;
1026- pdl.title = md.replaceAll("");
1040+ pdl.title = md.replaceAll("");
10271041 }
1028-
1042+
10291043 Pattern pat = Pattern.compile("初放送",Pattern.DOTALL);
10301044 if ( pat.matcher(pdl.detail).find() ) {
10311045 pdl.addOption(ProgOption.FIRST);
@@ -1041,13 +1055,13 @@ public class TVProgramUtils implements Cloneable {
10411055 else if ( pat.matcher(pdl.title).find() ) {
10421056 pdl.addOption(ProgOption.RATING);
10431057 }
1044-
1058+
10451059 if ( pdl.detail.indexOf("5.1サラウンド") != -1 ) {
10461060 pdl.addOption(ProgOption.SURROUND);
10471061 }
10481062
10491063 HashMap<String, String> xf = new HashMap<String, String>();
1050-
1064+
10511065 String flagExpr = "[\\[[((【](.{1,3})[\\]]))】]";
10521066 Matcher mx = Pattern.compile(flagExpr).matcher(pdl.title);
10531067 while (mx.find()) {
@@ -1066,7 +1080,7 @@ public class TVProgramUtils implements Cloneable {
10661080 else if (mx.group(1).equals("生")) {
10671081 pdl.addOption(ProgOption.LIVE);
10681082 }
1069-
1083+
10701084 else if (mx.group(1).equals("二/吹")) {
10711085 pdl.addOption(ProgOption.BILINGUAL);
10721086 pdl.addOption(ProgOption.STANDIN);
@@ -1093,7 +1107,7 @@ public class TVProgramUtils implements Cloneable {
10931107 //pdl.addOption(ProgOption.NOSCRUMBLE);
10941108 pdl.noscrumble = ProgScrumble.NOSCRUMBLE;
10951109 }
1096-
1110+
10971111 else if (mx.group(1).matches("^(S|N|B|映|双|解|手|天|英|日|録|HV)$")) {
10981112 // 無視するフラグ
10991113 if ( mx.group(1).equals("日") && ( ! pdl.title.matches(String.format("^(%s)*[((]日[))].*", flagExpr)) && ! pdl.title.matches(".*[\\[[]日[\\]]].*")) ) {
@@ -1105,13 +1119,13 @@ public class TVProgramUtils implements Cloneable {
11051119 // 削除しないフラグ
11061120 continue;
11071121 }
1108-
1122+
11091123 else {
11101124 // 未知のフラグ
11111125 nf.put(mx.group(1),null);
11121126 continue;
11131127 }
1114-
1128+
11151129 // 削除するフラグ
11161130 xf.put(mx.group(1), null);
11171131 }
@@ -1126,7 +1140,7 @@ public class TVProgramUtils implements Cloneable {
11261140 pdl.title = pdl.title.replaceAll(repExpr, "");
11271141 }
11281142 }
1129-
1143+
11301144 if ( pdl.title.matches("^特[::].*") ) {
11311145 pdl.option.add(ProgOption.SPECIAL);
11321146 pdl.title = pdl.title.substring(2);
@@ -1138,7 +1152,7 @@ public class TVProgramUtils implements Cloneable {
11381152 pdl.option.add(ProgOption.SPECIAL);
11391153 }
11401154 }
1141-
1155+
11421156 /**
11431157 * マルチジャンル処理
11441158 */
@@ -1148,17 +1162,17 @@ public class TVProgramUtils implements Cloneable {
11481162
11491163 // ここに入ってこない限り genrelist == null なので対応プラグイン以外ではマルチジャンルは機能しない
11501164 pdl.genrelist = new ArrayList<TVProgram.ProgGenre>();
1151- pdl.subgenrelist = new ArrayList<TVProgram.ProgSubgenre>();
1152-
1165+ pdl.subgenrelist = new ArrayList<TVProgram.ProgSubgenre>();
1166+
11531167 String gcode = ProgGenre.NOGENRE.toIEPG();
11541168 String subgcode = ProgSubgenre.NOGENRE_ETC.toIEPG();
1155-
1169+
11561170 // マルチジャンルコードを設定する
11571171 for ( String gstr : genrelist ) {
11581172 // ジャンルコードが複数ある場合は基本的に最初のものを代表にするが、一部例外をもうける(ニュースよりドキュメンタリー優先、など)
11591173 // 鯛ナビの一覧で表示されるジャンルは代表のものだけである
1160- String gv = gstr.substring(0,1);
1161- String subgv = gstr.substring(1,2);
1174+ String gv = gstr.substring(0,1);
1175+ String subgv = gstr.substring(1,2);
11621176 if ( gcode.equals(ProgGenre.NOGENRE.toIEPG()) ) {
11631177 gcode = gv;
11641178 subgcode = subgv;
@@ -1173,7 +1187,7 @@ public class TVProgramUtils implements Cloneable {
11731187 subgcode = md.group(2);
11741188 }
11751189 */
1176-
1190+
11771191 // 3.14.12βでマルチジャンル対応を追加した
11781192 // 一覧では代表しか見えないが、検索処理ではすべてのジャンルコードが対象になる
11791193 {
@@ -1201,7 +1215,7 @@ public class TVProgramUtils implements Cloneable {
12011215 pdl.subgenrelist.add(ProgSubgenre.NOGENRE_ETC);
12021216 }
12031217 }
1204-
1218+
12051219 // 代表ジャンルコードを設定する
12061220 for ( ProgGenre g : ProgGenre.values() ) {
12071221 if ( g.toIEPG().equals(gcode) ) {
@@ -1216,19 +1230,19 @@ public class TVProgramUtils implements Cloneable {
12161230 }
12171231 }
12181232 }
1219-
1220-
1233+
1234+
12211235 /*******************************************************************************
12221236 * 通信系
12231237 ******************************************************************************/
1224-
1238+
12251239 // Web上から取得してファイルにキャッシュする
1226-
1240+
12271241 // GET型
12281242 public void webToFile(String uri, String fname, String thisEncoding) {
12291243 webToFile(uri, null, null, null, fname, thisEncoding);
12301244 }
1231-
1245+
12321246 // POST型
12331247 public void webToFile(String uri, String pstr, String cookie, String referer, String fname, String thisEncoding) {
12341248 int retry = 0;
@@ -1243,10 +1257,10 @@ public class TVProgramUtils implements Cloneable {
12431257 CommonUtils.milSleep(1000);
12441258 }
12451259 }
1246-
1260+
12471261 // GET/POST本体
12481262 private boolean _webToFile(String uri, String pstr, String cookie, String referer, String fname, String thisEncoding) {
1249-
1263+
12501264 HttpURLConnection ucon = null;
12511265 BufferedWriter filewriter = null;
12521266 BufferedReader filereader = null;
@@ -1257,7 +1271,7 @@ public class TVProgramUtils implements Cloneable {
12571271 if (ucon == null) {
12581272 return false;
12591273 }
1260-
1274+
12611275 // 一時ファイルに書き出し
12621276 if (thisEncoding != null) {
12631277 filewriter = new BufferedWriter(new FileWriter(fname+".tmp"));
@@ -1287,9 +1301,9 @@ public class TVProgramUtils implements Cloneable {
12871301 }
12881302 ucon.disconnect();
12891303 ucon = null;
1290-
1291- // クローズしてからじゃないと失敗するよ
1292-
1304+
1305+ // クローズしてからじゃないと失敗するよ
1306+
12931307 // キャッシュファイルに変換
12941308 File o = new File(fname);
12951309 if ( o.exists() && ! o.delete() ) {
@@ -1300,7 +1314,7 @@ public class TVProgramUtils implements Cloneable {
13001314 System.err.println("リネームできないよ: "+fname+".tmp to "+fname);
13011315 return false;
13021316 }
1303-
1317+
13041318 return true;
13051319 }
13061320 catch (Exception e) {
@@ -1318,17 +1332,17 @@ public class TVProgramUtils implements Cloneable {
13181332 }
13191333
13201334 // Web上から取得してバッファに格納する
1321-
1335+
13221336 // GET型
13231337 public String webToBuffer(String uri, String thisEncoding, boolean nocr) {
13241338 return webToBuffer(uri, null, null, null, thisEncoding, nocr);
13251339 }
1326-
1340+
13271341 // POST型
13281342 public String webToBuffer(String uri, String pstr, String cookie, String referer, String thisEncoding, boolean nocr) {
13291343 int retry = 0;
13301344 while (true) {
1331- String response = _webToBuffer(uri, pstr, cookie, referer, thisEncoding, nocr);
1345+ String response = _webToBuffer(uri, pstr, cookie, referer, thisEncoding, nocr);
13321346 if ( response != null ) {
13331347 return response;
13341348 }
@@ -1340,14 +1354,14 @@ public class TVProgramUtils implements Cloneable {
13401354 }
13411355 return null;
13421356 }
1343-
1357+
13441358 // 本体
13451359 private String _webToBuffer(String uri, String pstr, String cookie, String referer, String thisEncoding, boolean nocr) {
13461360
13471361 if ( thisEncoding == null ) {
13481362 return null;
13491363 }
1350-
1364+
13511365 try {
13521366 HttpURLConnection ucon = null;
13531367 BufferedReader reader = null;
@@ -1356,7 +1370,7 @@ public class TVProgramUtils implements Cloneable {
13561370 if (ucon == null) {
13571371 return null;
13581372 }
1359-
1373+
13601374 // バッファ作成
13611375 StringBuilder sb = new StringBuilder();
13621376 reader = new BufferedReader(new InputStreamReader(ucon.getInputStream(), thisEncoding));
@@ -1387,11 +1401,11 @@ public class TVProgramUtils implements Cloneable {
13871401 }
13881402 return null;
13891403 }
1390-
1404+
13911405 /*
13921406 * File/Bufferの共通部品
13931407 */
1394-
1408+
13951409 private HttpURLConnection _webToXXX(String uri, String pstr, String cookie, String referer, String thisEncoding) {
13961410 try {
13971411 URL url = new URL(uri);
@@ -1404,17 +1418,17 @@ public class TVProgramUtils implements Cloneable {
14041418 }
14051419 ucon.setConnectTimeout(conntout*1000);
14061420 ucon.setReadTimeout(readtout*1000);
1407-
1421+
14081422 ucon.addRequestProperty("User-Agent", getUserAgent());
1409-
1423+
14101424 if ( referer != null ) {
14111425 ucon.addRequestProperty("Referer", referer);
14121426 }
1413-
1427+
14141428 if ( cookie != null ) {
14151429 ucon.addRequestProperty("Cookie", cookie);
14161430 }
1417-
1431+
14181432 // Cookie処理(CookieManagerはなぜうまく動かないんだ…orz)
14191433 if ( cookie_cache.size() > 0 ) {
14201434 String cStr = "";
@@ -1423,7 +1437,7 @@ public class TVProgramUtils implements Cloneable {
14231437 }
14241438 ucon.addRequestProperty("Cookie", cStr);
14251439 }
1426-
1440+
14271441 if (pstr != null) {
14281442 ucon.setRequestMethod("POST");
14291443 ucon.setDoOutput(true);
@@ -1441,7 +1455,7 @@ public class TVProgramUtils implements Cloneable {
14411455 writer.flush();
14421456 writer.close();
14431457 }
1444-
1458+
14451459 // Cookie処理
14461460 if ( uri.matches(".*dimora.jp.*") || uri.matches(".*\\.yahoo\\.co\\.jp.*") ) {
14471461 List<String> hf = ucon.getHeaderFields().get("Set-Cookie");
@@ -1453,18 +1467,18 @@ public class TVProgramUtils implements Cloneable {
14531467 }
14541468 }
14551469 }
1456-
1470+
14571471 return ucon;
1458-
1472+
14591473 } catch (MalformedURLException e) {
14601474 e.printStackTrace();
14611475 } catch (IOException e) {
14621476 e.printStackTrace();
14631477 }
1464-
1478+
14651479 return null;
14661480 }
1467-
1481+
14681482 protected String getCookie(String key) {
14691483 return cookie_cache.get(key);
14701484 }
@@ -1477,22 +1491,22 @@ public class TVProgramUtils implements Cloneable {
14771491 protected void clrCookie() {
14781492 cookie_cache.clear();
14791493 }
1480-
1494+
14811495 // Cookieの情報をキャッシュするよ
14821496 private HashMap<String,String> cookie_cache = new HashMap<String, String>();
1483-
1484-
1497+
1498+
14851499 /*******************************************************************************
14861500 * ここから下は該当機能が無効なプラグイン用のダミー
14871501 ******************************************************************************/
1488-
1502+
14891503 public String getTVProgramId() { return "DUMMY"; }
1490-
1504+
14911505 public String getDefaultArea() { return "東京"; }
1492-
1506+
14931507 // 番組詳細キャッシュファイル名
14941508 protected String getDetCacheFile() { return ""; }
1495-
1509+
14961510 // 番組詳細をattachする
14971511 protected void attachDetails(ArrayList<ProgList> plist, HashMap<String,String> oldcache, HashMap<String,String> newcache) {
14981512 // ダミー
@@ -1501,5 +1515,5 @@ public class TVProgramUtils implements Cloneable {
15011515 // フリーテキストによるオプション指定
15021516 public boolean setOptString(String s) { return true; } // ダミー
15031517 public String getOptString() { return null; } // ダミー
1504-
1518+
15051519 }
--- a/TinyBannavi/src/tainavi/VWStatusWindow.java
+++ b/TinyBannavi/src/tainavi/VWStatusWindow.java
@@ -17,15 +17,17 @@ import javax.swing.WindowConstants;
1717 public class VWStatusWindow extends JDialog implements StatusWindow,Cloneable {
1818
1919 private static final long serialVersionUID = 1L;
20-
20+
2121 private static final int WIN_COLS = 70;
2222 private static final int WIN_ROWS = 8;
2323
2424 private final JScrollPane jsp = new JScrollPane();
2525 private final JTextArea jta = new JTextAreaWithPopup();
26-
26+
2727 private WindowAdapter wl_closing = null;
28-
28+
29+ private boolean window_close_requested = false;
30+
2931 /**
3032 * 鯛ナビでは1個インスタンスを作ったらずっと使いまわすので自身を返す。まあ、特殊。
3133 */
@@ -40,14 +42,14 @@ public class VWStatusWindow extends JDialog implements StatusWindow,Cloneable {
4042 jta.setColumns(WIN_COLS);
4143 jta.setLineWrap(false);
4244 jta.setEditable(false);
43-
45+
4446 jsp.setViewportView(jta);
4547 jsp.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
4648 jsp.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
47-
49+
4850 return jsp;
4951 }
50-
52+
5153 // デフォルトコンストラクタ
5254 public VWStatusWindow() {
5355 //
@@ -55,23 +57,24 @@ public class VWStatusWindow extends JDialog implements StatusWindow,Cloneable {
5557 //
5658 this.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
5759 this.setModal(true);
58-
60+
5961 setClosingEnabled(true);
60-
62+
6163 this.setContentPane(getJScrollPane());
6264 this.pack();
63-
65+
6466 // this.setResizable(false);
6567
6668 //this.setLocationRelativeTo(owner); // 画面の真ん中に
67-
69+
6870 //
6971 this.setTitle("タイニー番組ナビゲータ ステータスウィンドウ");
7072 }
71-
73+
7274 private final WindowAdapter wl_closing_exitdisabled = new WindowAdapter() {
7375 @Override
7476 public void windowClosing(WindowEvent e) {
77+ window_close_requested = true;
7578 jta.append("処理中です。しばらくお待ちください…\n");
7679 }
7780 };
@@ -79,6 +82,7 @@ public class VWStatusWindow extends JDialog implements StatusWindow,Cloneable {
7982 private final WindowAdapter wl_closing_exitenabled = new WindowAdapter() {
8083 @Override
8184 public void windowClosing(WindowEvent e) {
85+ window_close_requested = true;
8286 System.out.println("強制終了します。");
8387 System.exit(1);
8488 }
@@ -87,7 +91,7 @@ public class VWStatusWindow extends JDialog implements StatusWindow,Cloneable {
8791 /*
8892 * StatusWindow用のメソッド
8993 */
90-
94+
9195 public void setClosingEnabled(boolean b) {
9296 if ( wl_closing != null ) this.removeWindowListener(wl_closing);
9397 if ( b ) {
@@ -97,30 +101,30 @@ public class VWStatusWindow extends JDialog implements StatusWindow,Cloneable {
97101 this.addWindowListener(wl_closing = wl_closing_exitdisabled);
98102 }
99103 }
100-
104+
101105 @Override
102106 public void clear() {
103107 jta.setText("");
104108 }
105-
109+
106110 @Override
107111 public void append(String message) {
108112 jta.append(message+"\n");
109113 jta.setCaretPosition(jta.getText().length());
110114 }
111-
115+
112116 @Override
113117 public void appendMessage(String message) {
114118 this.append(message);
115119 System.out.println(message);
116120 }
117-
121+
118122 @Override
119123 public void appendError(String message) {
120124 this.append(message);
121125 System.err.println(message);
122126 }
123-
127+
124128 @Override
125129 public void setVisible(boolean b) {
126130 try {
@@ -130,4 +134,14 @@ public class VWStatusWindow extends JDialog implements StatusWindow,Cloneable {
130134 System.err.println("HOGEHOEG");
131135 }
132136 }
137+
138+ /*
139+ * 画面の「×」ボタンが押されたか
140+ */
141+ @Override
142+ public void setWindowCloseRequested(boolean b){ window_close_requested = b; }
143+ @Override
144+ public boolean isWindowCloseRequested(){ return window_close_requested; }
145+ @Override
146+ public void resetWindowCloseRequested(){ setWindowCloseRequested(false); }
133147 }
--- a/TinyBannavi/src/tainavi/VersionInfo.java
+++ b/TinyBannavi/src/tainavi/VersionInfo.java
@@ -5,7 +5,7 @@ import java.util.regex.Pattern;
55
66
77 public class VersionInfo {
8- private static final String Version = "タイニー番組ナビゲータ for DBR-T2007 3.22.18β+1.7";
8+ private static final String Version = "タイニー番組ナビゲータ for DBR-T2007 3.22.18β+1.8";
99
1010 private static final String OSname = System.getProperty("os.name");
1111 private static final String OSvers = System.getProperty("os.version");
--- a/TinyBannavi/src/tainavi/Viewer.java
+++ b/TinyBannavi/src/tainavi/Viewer.java
@@ -47,6 +47,7 @@ import java.util.GregorianCalendar;
4747 import java.util.HashMap;
4848 import java.util.LinkedHashMap;
4949 import java.util.ServiceLoader;
50+import java.util.TimeZone;
5051 import java.util.regex.Matcher;
5152 import java.util.regex.Pattern;
5253
@@ -145,6 +146,7 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
145146 private String pxaddr = null; // ProxyAddress指定
146147 private String pxport = null; // ProxtPort指定
147148
149+ private boolean downloadInProgress = false; // TVプログラムを取得中か
148150
149151 /*******************************************************************************
150152 * 定数
@@ -1426,7 +1428,7 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
14261428 chdatsetting.updateChannelDatTable();
14271429
14281430 // 番組情報の再取得
1429- loadTVProgram(false,LoadFor.ALL); // 部品呼び出し
1431+ loadTVProgram(false,LoadFor.ALL, false); // 部品呼び出し
14301432
14311433 // ツールバーに反映
14321434 toolBar.setPagerItems();
@@ -1924,19 +1926,16 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
19241926
19251927 @Override
19261928 protected boolean doLoadTVProgram(String selected) {
1927- timer_now.pause();
1928-
19291929 LoadFor lf = (selected != null) ? LoadFor.get(selected) : LoadFor.ALL;
1930- boolean b = Viewer.this.doLoadTVProgram(true, lf);
1930+ boolean b = Viewer.this.doLoadTVProgram(true, lf, env.getDownloadProgramInBackground());
19311931
19321932 if ( b && lf == LoadFor.CSwSD ) {
19331933 // ロード後シャットダウン
19341934 CommonUtils.executeCommand(env.getShutdownCmd());
19351935 }
19361936
1937- Viewer.this.doRedrawTVProgram(); // か き な お し
1937+// Viewer.this.doRedrawTVProgram(); // か き な お し
19381938
1939- timer_now.start();
19401939 return b;
19411940 }
19421941
@@ -2015,6 +2014,7 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
20152014 public void timerRised(TickTimerRiseEvent e) {
20162015 if (env.getDebug()) System.out.println("Timer Rised: now="+CommonUtils.getDateTimeYMDx(e.getCalendar()));
20172016 setTitleBar();
2017+ checkDownloadProgramTime(e.getCalendar());
20182018 }
20192019
20202020
@@ -3792,18 +3792,41 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
37923792 * <P>部品実行の場合はこちらを呼び出す:{@link #loadTVProgram(boolean, LoadFor)}
37933793 * @see #doRedrawTVProgram()
37943794 */
3795- private boolean doLoadTVProgram(final boolean force, final LoadFor lf) {
3795+ private boolean doLoadTVProgram(final boolean force, final LoadFor lf, boolean background) {
3796+ if (downloadInProgress){
3797+ mwin.appendError("[Web番組表取得]実行中の取得処理を中止します。");
3798+ TVProgramUtils.setCancelRequested(true);
3799+ return false;
3800+ }
3801+
3802+ if (force){
3803+ GregorianCalendar c = new GregorianCalendar();
3804+ c.setTimeZone(TimeZone.getDefault());
3805+
3806+ if (env != null){
3807+ env.setLastDownloadTime(CommonUtils.getCalendarAsString(c));
3808+ env.save();
3809+ }
3810+ }
3811+
37963812 //
3797- StWinClear();
3813+ downloadInProgress = true;
3814+ toolBar.setReloadTVProgramsInProgress(true);
3815+
3816+ if (background){
3817+ TVProgramUtils.setProgressAreaBackground(mwin);
3818+ }
3819+ else{
3820+ StWinClear();
3821+ }
37983822
37993823 new SwingBackgroundWorker(false) {
38003824
38013825 @Override
38023826 protected Object doWorks() throws Exception {
3803-
38043827 TatCount tc = new TatCount();
38053828
3806- loadTVProgram(force, lf);
3829+ loadTVProgram(force, lf, background);
38073830
38083831 mwin.appendMessage(String.format("[Web番組表取得] 【完了しました】 所要時間: %.2f秒",tc.end()));
38093832 return null;
@@ -3811,12 +3834,26 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
38113834
38123835 @Override
38133836 protected void doFinally() {
3814- StWinSetVisible(false);
3837+ timer_now.pause();
3838+
3839+ if (background){
3840+ TVProgramUtils.setProgressAreaBackground(null);
3841+ }
3842+ else{
3843+ StWinSetVisible(false);
3844+ }
3845+ downloadInProgress = false;
3846+ toolBar.setReloadTVProgramsInProgress(false);
3847+ doRedrawTVProgram();
3848+
3849+ timer_now.start();
38153850 }
38163851 }.execute();
38173852
3818- StWinSetLocationCenter(this);
3819- StWinSetVisible(true);
3853+ if (!background){
3854+ StWinSetLocationCenter(this);
3855+ StWinSetVisible(true);
3856+ }
38203857
38213858 return true;
38223859 }
@@ -3847,56 +3884,87 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
38473884 * 自クラス内呼び出しによる
38483885 **************************************/
38493886
3887+ /*
3888+ * Web番組表のDLの進捗を報告する
3889+ */
3890+ private void reportTVProgramProgress(String msg){
3891+ TVProgramUtils.reportProgress(msg);
3892+ }
3893+
38503894 /**
38513895 * Web番組表をDLする
38523896 * <P>単体実行の場合はこちらを呼び出す:{@link #doLoadTVProgram(boolean, tainavi.Viewer.LoadFor)}
38533897 * <P>部品実行の場合はこちらを呼び出す
38543898 */
3855- private boolean loadTVProgram(final boolean force, final LoadFor lf) {
3899+ private boolean loadTVProgram(final boolean force, final LoadFor lf, boolean background) {
38563900
38573901 final String FUNCID = "[Web番組表取得] ";
38583902 final String ERRID = "[ERROR]"+FUNCID;
38593903
38603904 try {
3905+ stwin.resetWindowCloseRequested();
3906+ TVProgramUtils.setCancelRequested(false);
3907+
38613908 String msg;
38623909 TVProgram tvp;
38633910
3911+ if (TVProgramUtils.isCancelRequested()){
3912+ return false;
3913+ }
3914+
38643915 tvp = tvprograms.getTvProgPlugin(null);
38653916 if ( tvp != null )
38663917 {
38673918 String sType = "地上波&BS番組表";
38683919 if (lf == LoadFor.ALL || lf == LoadFor.TERRA) {
3869- loadTVProgramOnce(tvp, sType, tvp.getSelectedArea(), false, force);
3920+ if (!loadTVProgramOnce(tvp, sType, tvp.getSelectedArea(), false, force)){
3921+ return false;
3922+ }
38703923 }
38713924 else {
3872- stwin.appendMessage(FUNCID+sType+"へのアクセスはスキップされました: "+tvp.getTVProgramId());
3925+ reportTVProgramProgress(FUNCID+sType+"へのアクセスはスキップされました: "+tvp.getTVProgramId());
38733926 }
38743927 }
38753928
3929+ if (TVProgramUtils.isCancelRequested()){
3930+ return false;
3931+ }
38763932 tvp = tvprograms.getCsProgPlugin(null);
38773933 if ( tvp != null )
38783934 {
38793935 String sType = "CS番組表[プライマリ]";
38803936 if (lf == LoadFor.ALL || lf == LoadFor.CS || lf == LoadFor.CSo1 || lf == LoadFor.CSwSD) {
3881- loadTVProgramOnce(tvp, sType, tvp.getSelectedArea(), false, force);
3937+ if (!loadTVProgramOnce(tvp, sType, tvp.getSelectedArea(), false, force)){
3938+ return false;
3939+ }
38823940 }
38833941 else {
3884- stwin.appendMessage(FUNCID+sType+"へのアクセスはスキップされました: "+tvp.getTVProgramId());
3942+ reportTVProgramProgress(FUNCID+sType+"へのアクセスはスキップされました: "+tvp.getTVProgramId());
38853943 }
38863944 }
38873945
3946+ if (TVProgramUtils.isCancelRequested()){
3947+ return false;
3948+ }
3949+
38883950 tvp = tvprograms.getCs2ProgPlugin(null);
38893951 if ( tvp != null )
38903952 {
38913953 String sType = "CS番組表[セカンダリ]";
38923954 if (lf == LoadFor.ALL || lf == LoadFor.CS || lf == LoadFor.CSo2 || lf == LoadFor.CSwSD) {
3893- loadTVProgramOnce(tvp, sType, tvp.getSelectedArea(), false, force);
3955+ if (!loadTVProgramOnce(tvp, sType, tvp.getSelectedArea(), false, force)){
3956+ return false;
3957+ }
38943958 }
38953959 else {
3896- stwin.appendMessage(FUNCID+sType+"へのアクセスはスキップされました: "+tvp.getTVProgramId());
3960+ reportTVProgramProgress(FUNCID+sType+"へのアクセスはスキップされました: "+tvp.getTVProgramId());
38973961 }
38983962 }
38993963
3964+ if (TVProgramUtils.isCancelRequested()){
3965+ return false;
3966+ }
3967+
39003968 tvp = tvprograms.getSyobo();
39013969 if ( tvp != null ) {
39023970 String sType = "しょぼかる";
@@ -3905,13 +3973,17 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
39053973 loadTVProgramOnce(tvp, sType, null, true, force);
39063974 }
39073975 else {
3908- stwin.appendMessage(FUNCID+sType+"へのアクセスはスキップされました.");
3976+ reportTVProgramProgress(FUNCID+sType+"へのアクセスはスキップされました.");
39093977 }
39103978
39113979 // しょぼかるの新番組マークを引き継ぐ
39123980 attachSyoboNew();
39133981 }
39143982
3983+ if (TVProgramUtils.isCancelRequested()){
3984+ return false;
3985+ }
3986+
39153987 PickedProgram pickup = tvprograms.getPickup();
39163988 if ( tvp != null ) {
39173989 pickup.refresh();
@@ -3923,23 +3995,26 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
39233995 fixDetail();
39243996
39253997 // 検索結果の再構築
3926- stwin.appendMessage(FUNCID+"検索結果を生成します.");
3998+ reportTVProgramProgress(FUNCID+"検索結果を生成します.");
39273999 mpList.clear(env.getDisableFazzySearch(), env.getDisableFazzySearchReverse());
39284000 mpList.build(tvprograms, trKeys.getTraceKeys(), srKeys.getSearchKeys());
39294001
39304002 // 過去ローグ
3931- if ( env.getUsePassedProgram() ) {
4003+ if ( !env.getUsePassedProgram()) {
4004+ reportTVProgramProgress(FUNCID+"過去ログは記録されません.");
4005+ }
4006+ else if (!force){
4007+ reportTVProgramProgress(FUNCID+"キャッシュからの読み込み時は過去ログは記録されません.");
4008+ }
4009+ else {
39324010 TatCount tc = new TatCount();
3933- stwin.appendMessage(FUNCID+"過去ログを生成します.");
4011+ reportTVProgramProgress(FUNCID+"過去ログを生成します.");
39344012 if ( tvprograms.getPassed().save(tvprograms.getIterator(), chsort.getClst(), env.getPrepPassedProgramCount()) ) {
39354013 msg = String.format(FUNCID+"過去ログを生成しました [%.2f秒].",tc.end());
3936- StdAppendMessage(msg);
4014+ reportTVProgramProgress(msg);
39374015 }
39384016 //PassedProgramList.getDateList(env.getPassedLogLimit());
39394017 }
3940- else {
3941- stwin.appendMessage(FUNCID+"過去ログは記録されません.");
3942- }
39434018 }
39444019 catch (Exception e) {
39454020 e.printStackTrace();
@@ -3952,22 +4027,25 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
39524027 }
39534028
39544029 // 分割
3955- private void loadTVProgramOnce(TVProgram tvp, String sType, String aName, boolean loadonly, boolean force) {
4030+ private boolean loadTVProgramOnce(TVProgram tvp, String sType, String aName, boolean loadonly, boolean force) {
39564031
39574032 final String FUNCID = "[Web番組表取得] ";
39584033 // final String ERRID = "[ERROR]"+FUNCID;
39594034
39604035 // ログ
39614036 String msg = FUNCID+sType+"を取得します: "+tvp.getTVProgramId();
3962- stwin.appendMessage(msg);
3963- if (aName!=null) stwin.appendMessage(FUNCID+"+選択されているエリア="+aName);
4037+ reportTVProgramProgress(msg);
4038+ if (aName!=null) reportTVProgramProgress(FUNCID+"+選択されているエリア="+aName);
39644039
39654040 // 読み込み
39664041 //tvp.setProgressArea(stwin);
3967- tvp.loadProgram(tvp.getSelectedCode(), force);
4042+ if (!tvp.loadProgram(tvp.getSelectedCode(), force)){
4043+ if (mwin!=null) mwin.appendMessage(FUNCID+"番組情報の取得に失敗しました。");
4044+ return false;
4045+ }
39684046
39694047 if (loadonly) {
3970- return;
4048+ return true;
39714049 }
39724050
39734051 // 延長警告
@@ -3977,10 +4055,14 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
39774055 // 抜けチェック
39784056 String errmsg = tvp.chkComplete();
39794057 if (errmsg != null) {
3980- stwin.appendError(FUNCID+"取得した情報が不正です:"+errmsg);
4058+ msg = FUNCID+"取得した情報が不正です:"+errmsg;
4059+ reportTVProgramProgress(msg);
39814060 if (mainWindow!=null) mwin.appendMessage(msg);
39824061 ringBeep();
4062+ return false;
39834063 }
4064+
4065+ return true;
39844066 }
39854067
39864068 // しょぼかるの番組詳細を番組表に反映する
@@ -4456,7 +4538,7 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
44564538
44574539 // 番組情報の再取得
44584540 if ( reload_prog ) {
4459- loadTVProgram(false, LoadFor.ALL); // 部品呼び出し
4541+ loadTVProgram(false, LoadFor.ALL, false); // 部品呼び出し
44604542 }
44614543
44624544 // Web番組表の再構築
@@ -5517,6 +5599,7 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
55175599 final String SELECT_ACTION_RECEDTAB = "recedtab";
55185600 final String SELECT_ACTION_AUTORESTAB = "autorestab";
55195601 final String SELECT_ACTION_TITLETAB = "titletab";
5602+ final String SELECT_ACTION_SETTINGTAB = "settingtab";
55205603
55215604 final String BUTTON_ACTION_KEYWORD_ADDED = "keyword_added";
55225605 final String BUTTON_ACTION_RELOAD_PROGRAM = "reload_program";
@@ -5581,6 +5664,12 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
55815664 mainWindow.setSelectedTab(MWinTab.TITLED);
55825665 }
55835666 };
5667+ final Action select_action_settingtab = new AbstractAction() {
5668+ @Override
5669+ public void actionPerformed(ActionEvent e) {
5670+ mainWindow.setSelectedTab(MWinTab.SETTING);
5671+ }
5672+ };
55845673
55855674 final Action sc_keyword_added = new AbstractAction() {
55865675 @Override
@@ -5720,6 +5809,7 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
57205809 sca.add(new ShortCut(SELECT_ACTION_RECEDTAB, KeyEvent.VK_4, KeyEvent.ALT_DOWN_MASK, select_action_recedtab));
57215810 sca.add(new ShortCut(SELECT_ACTION_AUTORESTAB, KeyEvent.VK_5, KeyEvent.ALT_DOWN_MASK, select_action_autorestab));
57225811 sca.add(new ShortCut(SELECT_ACTION_TITLETAB, KeyEvent.VK_6, KeyEvent.ALT_DOWN_MASK, select_action_titletab));
5812+ sca.add(new ShortCut(SELECT_ACTION_SETTINGTAB, KeyEvent.VK_7, KeyEvent.ALT_DOWN_MASK, select_action_settingtab));
57235813
57245814 sca.add(new ShortCut(BUTTON_ACTION_KEYWORD_ADDED, KeyEvent.VK_K, KeyEvent.CTRL_DOWN_MASK, sc_keyword_added));
57255815
@@ -5778,6 +5868,40 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
57785868 }
57795869 }
57805870
5871+ private void checkDownloadProgramTime( GregorianCalendar gc){
5872+ if (! env.getDownloadProgramOnFixedTime())
5873+ return;
5874+
5875+ GregorianCalendar c = (GregorianCalendar)gc.clone();
5876+ c.setTimeZone(TimeZone.getDefault());
5877+
5878+ String timeLast = "00:00";
5879+ GregorianCalendar cl = CommonUtils.getCalendarFromString(env.getLastDownloadTime());
5880+
5881+ if (cl != null){
5882+ if (cl.get(Calendar.DAY_OF_YEAR) == c.get(Calendar.DAY_OF_YEAR) &&
5883+ cl.get(Calendar.HOUR_OF_DAY) == c.get(Calendar.HOUR_OF_DAY) &&
5884+ cl.get(Calendar.MINUTE) == c.get(Calendar.MINUTE)){
5885+ return;
5886+ }
5887+
5888+ if (cl.get(Calendar.DAY_OF_YEAR) == c.get(Calendar.DAY_OF_YEAR))
5889+ timeLast = String.format("%02d:%02d", cl.get(Calendar.HOUR_OF_DAY), cl.get(Calendar.MINUTE));
5890+ }
5891+
5892+ String timeNow = String.format("%02d:%02d", c.get(Calendar.HOUR_OF_DAY), c.get(Calendar.MINUTE));
5893+
5894+ for (String time : env.getDownloadProgramTimeList().split(";")){
5895+ if (time.compareTo(timeLast) <= 0)
5896+ continue;
5897+
5898+ if (time.compareTo(timeNow) <= 0){
5899+ doLoadTVProgram(true, LoadFor.ALL, env.getDownloadProgramInBackground());
5900+ return;
5901+ }
5902+ }
5903+ }
5904+
57815905 /*******************************************************************************
57825906 * main()
57835907 ******************************************************************************/
@@ -5968,7 +6092,7 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
59686092 // 検索結果リストの初期化(loadTVProgram()中で使うので)
59696093 initMpList();
59706094 // データのロード
5971- loadTVProgram(true,LoadFor.ALL);
6095+ loadTVProgram(true,LoadFor.ALL, false);
59726096 stwin.appendMessage("番組表を取得したので終了します");
59736097 CommonUtils.milSleep(3000);
59746098 System.exit(1);
@@ -5993,7 +6117,7 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
59936117 initMpList();
59946118
59956119 // データのロード
5996- loadTVProgram(false,LoadFor.ALL);
6120+ loadTVProgram(false,LoadFor.ALL, false);
59976121
59986122 // 放送局の並び順もロード
59996123 chsort.load();
--- a/TinyBannavi/src/tainavi/plugintv/PlugIn_CSPTVKingdom110.java
+++ b/TinyBannavi/src/tainavi/plugintv/PlugIn_CSPTVKingdom110.java
@@ -75,26 +75,39 @@ public class PlugIn_CSPTVKingdom110 extends PlugIn_TVPTVKingdom implements TVPro
7575 * 番組情報を取得する
7676 ******************************************************************************/
7777 @Override
78- public void loadProgram(String areaCode, boolean force) {
78+ public boolean loadProgram(String areaCode, boolean force) {
7979
8080 // 入れ物を空にする
81- newplist.clear();
81+ newplist = new ArrayList<ProgList>();
8282 nf.clear();
8383
8484 //
8585 int counterMax = getSortedCRlist().size();
8686 int counter=1;
8787 for ( Center c : getSortedCRlist() ) {
88- _loadProgram(c, force, counter++, counterMax);
88+ if (!_loadProgram(c, force, counter++, counterMax)){
89+ newplist = null;
90+ return false;
91+ }
92+
93+ if (isCancelRequested()){
94+ reportProgress(ERRID+"中止要求があったので番組表の取得にを中止します。");
95+ newplist = null;
96+ return false;
97+ }
8998 }
9099
91100 debugNF();
92101
93102 // 古い番組データを置き換える
103+ if (pcenter != null)
104+ pcenter.clear();
94105 pcenter = newplist;
106+ newplist = null;
107+ return true;
95108 }
96109
97- private void _loadProgram(Center cr, boolean force, int counter, int counterMax) {
110+ private boolean _loadProgram(Center cr, boolean force, int counter, int counterMax) {
98111 //
99112 try {
100113 // 局リストの追加
@@ -129,7 +142,7 @@ public class PlugIn_CSPTVKingdom110 extends PlugIn_TVPTVKingdom implements TVPro
129142
130143 response = webToBuffer(url, thisEncoding, true);
131144 if ( response == null ) {
132- return;
145+ return false;
133146 }
134147 CommonUtils.write2file(progCacheFile, response);
135148
@@ -141,14 +154,14 @@ public class PlugIn_CSPTVKingdom110 extends PlugIn_TVPTVKingdom implements TVPro
141154 else if (f.exists()) {
142155 response = CommonUtils.read4file(progCacheFile, true);
143156 if ( response == null ) {
144- return;
157+ return false;
145158 }
146159
147160 reportProgress(String.format("%s (キャッシュ)を取得しました: (%d/%d) %s %s",getTVProgramId(),counter,counterMax,pl.Center,progCacheFile));
148161 }
149162 else {
150163 reportProgress(String.format("%s (キャッシュ)がみつかりません: (%d/%d) %s %s",getTVProgramId(),counter,counterMax,pl.Center,progCacheFile));
151- return;
164+ return false;
152165 }
153166
154167 // 日付リストの追加
@@ -164,7 +177,10 @@ public class PlugIn_CSPTVKingdom110 extends PlugIn_TVPTVKingdom implements TVPro
164177 // 例外
165178 System.out.println("Exception: _loadProgram()");
166179 e.printStackTrace();
180+ return false;
167181 }
182+
183+ return true;
168184 }
169185
170186 //
--- a/TinyBannavi/src/tainavi/plugintv/PlugIn_CSPtheTelevisionA.java
+++ b/TinyBannavi/src/tainavi/plugintv/PlugIn_CSPtheTelevisionA.java
@@ -8,24 +8,22 @@ import tainavi.Center;
88 import tainavi.CommonUtils;
99 import tainavi.ProgList;
1010 import tainavi.TVProgram;
11-import tainavi.TVProgram.ProgSubtype;
12-import tainavi.TVProgram.ProgType;
1311
1412
1513
1614 public class PlugIn_CSPtheTelevisionA extends PlugIn_TVPtheTelevision implements TVProgram,Cloneable {
1715
1816 final String thisEncoding = "UTF-8";
19-
17+
2018 /* 必須コード - ここから */
21-
19+
2220 // 種族の特性
2321 @Override
2422 public String getTVProgramId() { return "webザテレビジョン(CSアナ)"; }
25-
23+
2624 @Override
2725 public boolean isAreaSelectSupported() { return false; }
28-
26+
2927 @Override
3028 public ProgType getType() { return ProgType.PROG; }
3129 @Override
@@ -39,38 +37,39 @@ public class PlugIn_CSPtheTelevisionA extends PlugIn_TVPtheTelevision implements
3937 private final String MSGID = "["+getTVProgramId()+"] ";
4038 private final String ERRID = "[ERROR]"+MSGID;
4139 private final String DBGID = "[DEBUG]"+MSGID;
42-
40+
4341 //
44- public void loadProgram(String areaCode, boolean force) {
45-
42+ public boolean loadProgram(String areaCode, boolean force) {
43+
4644 // 新しい入れ物(トップ)を用意する
4745 newplist = new ArrayList<ProgList>();
48-
46+
4947 //
5048 int counterMax = getSortedCRlist().size();
5149 int counter=1;
5250 for ( Center c : getSortedCRlist() ) {
5351 _loadProgram(c, force, counter++, counterMax);
5452 }
55-
53+
5654 // 古い番組データを置き換える
5755 pcenter = newplist;
56+ return true;
5857 }
59-
60-
58+
59+
6160 /*
6261 * ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
6362 * ★★★★★ 放送地域を取得する(TVAreaから降格)-ここから ★★★★★
6463 * ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
6564 */
66-
65+
6766 /*
6867 * 公開メソッド
6968 */
70-
69+
7170 public String getDefaultArea() {return "全国";}
7271 public String getDefaultCode() {return "tokyo";}
73-
72+
7473 public void loadAreaCode() {
7574 aclist = new ArrayList<AreaCode>();
7675 AreaCode ac = new AreaCode();
@@ -80,55 +79,55 @@ public class PlugIn_CSPtheTelevisionA extends PlugIn_TVPtheTelevision implements
8079 aclist.add(ac);
8180 }
8281 public void saveAreaCode() {}
83-
82+
8483 public String getArea(String code) { return(getDefaultArea()); }
8584 public String getCode(String area) { return(getDefaultCode()); }
8685 public String setSelectedAreaByName(String area) { return(getDefaultCode()); }
8786 public String getSelectedArea() { return(getDefaultArea()); }
8887 public String getSelectedCode() { return(getDefaultCode()); }
89-
88+
9089 /*
9190 * ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
9291 * ★★★★★ 放送地域を取得する(TVAreaから降格)-ここまで ★★★★★
9392 * ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
9493 */
95-
96-
97-
94+
95+
96+
9897 /*
9998 * ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
10099 * ★★★★★ 放送局を選択する(TVCenterから降格)-ここから ★★★★★
101100 * ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
102101 */
103-
102+
104103 /*
105104 * 公開メソッド
106105 */
107106
108107 // 設定ファイルがなければWebから取得
109108 public void loadCenter(String code, boolean force) {
110-
109+
111110 if ( code == null ) {
112111 System.out.println(ERRID+"地域コードがnullです.");
113112 return;
114113 }
115-
114+
116115 String centerListFile = getCenterListFile(getTVProgramId(), code);
117-
116+
118117 if (force) {
119118 File f = new File(centerListFile);
120119 f.delete();
121120 }
122-
121+
123122 File f = new File(centerListFile);
124123 if (f.exists() == true) {
125124 @SuppressWarnings("unchecked")
126125 ArrayList<Center> tmp = (ArrayList<Center>) CommonUtils.readXML(centerListFile);
127126 if ( tmp != null ) {
128-
127+
129128 crlist = tmp;
130129 attachChFilters(); // 放送局名変換
131-
130+
132131 System.out.println("放送局リストを読み込みました: "+centerListFile);
133132 return;
134133 }
@@ -136,15 +135,15 @@ public class PlugIn_CSPtheTelevisionA extends PlugIn_TVPtheTelevision implements
136135 System.err.println("放送局リストの読み込みに失敗しました: "+centerListFile);
137136 }
138137 }
139-
138+
140139 // Web上から放送局の一覧を取得する
141140 ArrayList<Center> newcrlist = new ArrayList<Center>();
142-
141+
143142 String url = "http://www.television.co.jp/programlist/guide.php?type=cs&page=1";
144143 if ( _loadCenter(newcrlist, code,"csa",url) ) {
145144 reportProgress("放送局情報を取得しました: (1/1) "+url);
146145 }
147-
146+
148147 if ( newcrlist.size() == 0 ) {
149148 System.err.println(ERRID+"放送局情報の取得結果が0件だったため情報を更新しません");
150149 return;
@@ -162,12 +161,12 @@ public class PlugIn_CSPtheTelevisionA extends PlugIn_TVPtheTelevision implements
162161 }
163162 tmpcrlist.add(idx, cr);
164163 }
165-
164+
166165 crlist = tmpcrlist;
167166 attachChFilters(); // 放送局名変換
168167 saveCenter();
169168 }
170-
169+
171170 /*
172171 * ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
173172 * ★★★★★ 放送局を選択する(TVCenterから降格)-ここまで ★★★★★
--- a/TinyBannavi/src/tainavi/plugintv/PlugIn_CSPtheTelevisionD.java
+++ b/TinyBannavi/src/tainavi/plugintv/PlugIn_CSPtheTelevisionD.java
@@ -8,24 +8,22 @@ import tainavi.Center;
88 import tainavi.CommonUtils;
99 import tainavi.ProgList;
1010 import tainavi.TVProgram;
11-import tainavi.TVProgram.ProgSubtype;
12-import tainavi.TVProgram.ProgType;
1311
1412
1513
1614 public class PlugIn_CSPtheTelevisionD extends PlugIn_TVPtheTelevision implements TVProgram,Cloneable {
1715
1816 final String thisEncoding = "UTF-8";
19-
17+
2018 /* 必須コード - ここから */
21-
19+
2220 // 種族の特性
2321 @Override
2422 public String getTVProgramId() { return "webザテレビジョン(CSデジ)"; }
25-
23+
2624 @Override
2725 public boolean isAreaSelectSupported() { return false; }
28-
26+
2927 @Override
3028 public ProgType getType() { return ProgType.PROG; }
3129 public ProgSubtype getSubtype() { return ProgSubtype.CS2; }
@@ -38,10 +36,10 @@ public class PlugIn_CSPtheTelevisionD extends PlugIn_TVPtheTelevision implements
3836 private final String MSGID = "["+getTVProgramId()+"] ";
3937 private final String ERRID = "[ERROR]"+MSGID;
4038 private final String DBGID = "[DEBUG]"+MSGID;
41-
39+
4240 //
43- public void loadProgram(String areaCode, boolean force) {
44-
41+ public boolean loadProgram(String areaCode, boolean force) {
42+
4543 // 新しい入れ物(トップ)を用意する
4644 newplist = new ArrayList<ProgList>();
4745
@@ -51,25 +49,26 @@ public class PlugIn_CSPtheTelevisionD extends PlugIn_TVPtheTelevision implements
5149 for ( Center c : getSortedCRlist() ) {
5250 _loadProgram(c, force, counter++, counterMax);
5351 }
54-
52+
5553 // 古い番組データを置き換える
5654 pcenter = newplist;
55+ return true;
5756 }
58-
59-
57+
58+
6059 /*
6160 * ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
6261 * ★★★★★ 放送地域を取得する(TVAreaから降格)-ここから ★★★★★
6362 * ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
6463 */
65-
64+
6665 /*
6766 * 公開メソッド
6867 */
69-
68+
7069 public String getDefaultArea() {return "全国";}
7170 public String getDefaultCode() {return "tokyo";}
72-
71+
7372 public void loadAreaCode() {
7473 aclist = new ArrayList<AreaCode>();
7574 AreaCode ac = new AreaCode();
@@ -79,55 +78,55 @@ public class PlugIn_CSPtheTelevisionD extends PlugIn_TVPtheTelevision implements
7978 aclist.add(ac);
8079 }
8180 public void saveAreaCode() {}
82-
81+
8382 public String getArea(String code) { return(getDefaultArea()); }
8483 public String getCode(String area) { return(getDefaultCode()); }
8584 public String setSelectedAreaByName(String area) { return(getDefaultCode()); }
8685 public String getSelectedArea() { return(getDefaultArea()); }
8786 public String getSelectedCode() { return(getDefaultCode()); }
88-
87+
8988 /*
9089 * ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
9190 * ★★★★★ 放送地域を取得する(TVAreaから降格)-ここまで ★★★★★
9291 * ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
9392 */
94-
95-
96-
93+
94+
95+
9796 /*
9897 * ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
9998 * ★★★★★ 放送局を選択する(TVCenterから降格)-ここから ★★★★★
10099 * ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
101100 */
102-
101+
103102 /*
104103 * 公開メソッド
105104 */
106105
107106 // 設定ファイルがなければWebから取得
108107 public void loadCenter(String code, boolean force) {
109-
108+
110109 if ( code == null ) {
111110 System.out.println(ERRID+"地域コードがnullです.");
112111 return;
113112 }
114-
113+
115114 String centerListFile = getCenterListFile(getTVProgramId(), code);
116-
115+
117116 if (force) {
118117 File f = new File(centerListFile);
119118 f.delete();
120119 }
121-
120+
122121 File f = new File(centerListFile);
123122 if (f.exists() == true) {
124123 @SuppressWarnings("unchecked")
125124 ArrayList<Center> tmp = (ArrayList<Center>) CommonUtils.readXML(centerListFile);
126125 if ( tmp != null ) {
127-
126+
128127 crlist = tmp;
129128 attachChFilters(); // 放送局名変換
130-
129+
131130 System.out.println("放送局リストを読み込みました: "+centerListFile);
132131 return;
133132 }
@@ -135,15 +134,15 @@ public class PlugIn_CSPtheTelevisionD extends PlugIn_TVPtheTelevision implements
135134 System.out.println("放送局リストの読み込みに失敗しました: "+centerListFile);
136135 }
137136 }
138-
137+
139138 // Web上から放送局の一覧を取得する
140139 ArrayList<Center> newcrlist = new ArrayList<Center>();
141-
140+
142141 String url = "http://www.television.co.jp/digitalguide/guide.php?type=cs&page=1";
143142 if ( _loadCenter(newcrlist, code,"csd",url) ) {
144143 reportProgress("放送局情報を取得しました: (1/1) "+url);
145144 }
146-
145+
147146 if ( newcrlist.size() == 0 ) {
148147 System.err.println(ERRID+"放送局情報の取得結果が0件だったため情報を更新しません");
149148 return;
@@ -161,12 +160,12 @@ public class PlugIn_CSPtheTelevisionD extends PlugIn_TVPtheTelevision implements
161160 }
162161 tmpcrlist.add(idx, cr);
163162 }
164-
163+
165164 crlist = tmpcrlist;
166165 attachChFilters(); // 放送局名変換
167166 saveCenter();
168167 }
169-
168+
170169 /*
171170 * ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
172171 * ★★★★★ 放送局を選択する(TVCenterから降格)-ここまで ★★★★★
--- a/TinyBannavi/src/tainavi/plugintv/PlugIn_TVPDimora.java
+++ b/TinyBannavi/src/tainavi/plugintv/PlugIn_TVPDimora.java
@@ -26,78 +26,78 @@ public class PlugIn_TVPDimora extends TVProgramUtils implements TVProgram,Clonea
2626 public PlugIn_TVPDimora clone() {
2727 return (PlugIn_TVPDimora) super.clone();
2828 }
29-
29+
3030 private static final String thisEncoding = "UTF-8";
31-
32-
31+
32+
3333 /*******************************************************************************
3434 * 種族の特性
3535 ******************************************************************************/
36-
36+
3737 @Override
3838 public String getTVProgramId() { return "Dimora"; }
39-
39+
4040 @Override
4141 public ProgType getType() { return ProgType.PROG; }
4242 @Override
4343 public ProgSubtype getSubtype() { return ProgSubtype.TERRA; }
4444
45-
45+
4646 /*******************************************************************************
4747 * 個体の特性
4848 ******************************************************************************/
49-
49+
5050 @Override
5151 public int getTimeBarStart() {return 5;}
52-
52+
5353 private int getDogDays() { return ((getExpandTo8())?(8):(7)); }
5454
55-
55+
5656 /*******************************************************************************
5757 * 定数
5858 ******************************************************************************/
59-
59+
6060 private final String MSGID = "["+getTVProgramId()+"] ";
6161 private final String ERRID = "[ERROR]"+MSGID;
6262 private final String DBGID = "[DEBUG]"+MSGID;
63-
64-
63+
64+
6565 /*******************************************************************************
6666 * 部品
6767 ******************************************************************************/
6868
6969 // 新しい入れ物の臨時格納場所
70- protected final ArrayList<ProgList> newplist = new ArrayList<ProgList>();
71-
70+ protected ArrayList<ProgList> newplist = new ArrayList<ProgList>();
71+
7272 // 未定義のフラグの回収場所
7373 private final HashMap<String,String> nf = new HashMap<String, String>();
7474
7575 protected String getCenterInfoId() { return "ChannelTypeDB"; }
7676 protected String getChType() { return "6"; }
7777 protected String getCenterCode(String id, String code) { return id.matches("^3.*$")?(bsCode):(code); }
78-
78+
7979 protected String getProgCacheFile(String areacode, String adate) { return String.format(getProgDir()+File.separator+"Dimora_%s_%s.html", areacode, adate.substring(6,8)); }
8080
81-
81+
8282 /*******************************************************************************
8383 * コンストラクタ
8484 ******************************************************************************/
85-
86-
85+
86+
8787 /*******************************************************************************
8888 * 番組情報を取得する
8989 ******************************************************************************/
9090
9191 @Override
92- public void loadProgram(String areaCode, boolean force) {
93-
92+ public boolean loadProgram(String areaCode, boolean force) {
93+
9494 // 入れ物を空にする
95- newplist.clear();
96- nf.clear();
97-
95+ newplist = new ArrayList<ProgList>();
96+ nf.clear();
97+
9898 // 地域コードごとの参照ページ数の入れ物を用意する
9999 LinkedHashMap<String,Integer> pages = new LinkedHashMap<String, Integer>();
100-
100+
101101 // 参照する地域コードをまとめる
102102 if ( areaCode.equals(allCode) ) {
103103 // 「全国」
@@ -119,7 +119,7 @@ public class PlugIn_TVPDimora extends TVProgramUtils implements TVProgram,Clonea
119119 }
120120 }
121121 }
122-
122+
123123 // トップの下に局ごとのリストを生やす
124124 for ( String ac : pages.keySet() ) {
125125 for ( Center cr : crlist ) {
@@ -134,12 +134,12 @@ public class PlugIn_TVPDimora extends TVProgramUtils implements TVProgram,Clonea
134134 pl.Center = cr.getCenter();
135135 pl.BgColor = cr.getBgColor();
136136 pl.enabled = true;
137-
137+
138138 newplist.add(pl);
139139 }
140140 }
141141 }
142-
142+
143143 // 局の下に日付ごとのリストを生やす
144144 GregorianCalendar cal = CommonUtils.getCalendar(0);
145145 if ( CommonUtils.isLateNight(cal) ) {
@@ -156,7 +156,7 @@ public class PlugIn_TVPDimora extends TVProgramUtils implements TVProgram,Clonea
156156 }
157157 cale.add(Calendar.DATE, 1);
158158 }
159-
159+
160160 // 参照する総ページ数を計算
161161 int counterMax = 0;
162162 for ( String ac : pages.keySet() ) {
@@ -165,9 +165,9 @@ public class PlugIn_TVPDimora extends TVProgramUtils implements TVProgram,Clonea
165165 }
166166 counterMax += pages.get(ac)*getDogDays();
167167 }
168-
168+
169169 clrCookie();
170-
170+
171171 // 日付の下に番組情報ごとのリストを生やす
172172 int counter = 1;
173173 for ( String ac : pages.keySet() ) {
@@ -179,38 +179,51 @@ public class PlugIn_TVPDimora extends TVProgramUtils implements TVProgram,Clonea
179179 String adate = CommonUtils.getDateYMD(cale);
180180 cale.add(Calendar.DATE, 1);
181181 String edate = CommonUtils.getDateYMD(cale);
182- _loadProgram(ac, adate, edate, force, i, counter++, counterMax);
182+ if (!_loadProgram(ac, adate, edate, force, i, counter++, counterMax)){
183+ newplist = null;
184+ return false;
185+ }
186+
187+ if (isCancelRequested()){
188+ newplist = null;
189+ reportProgress(ERRID+"中止要求があったので番組表の取得にを中止します。");
190+ return false;
191+ }
183192 }
184193 }
185-
194+
186195 // 開始・終了日時を正しい値に計算しなおす
187196 for ( ProgList pl : newplist ) {
188197 setAccurateDate(pl.pdate);
189198 }
190-
199+
191200 // 古いデータから補完できないかな?
192201 CompensatesPrograms(newplist);
193-
202+
194203 // 解析用
195204 {
196205 for ( String f : nf.keySet() ) {
197206 System.out.println(String.format(DBGID+"未定義のフラグです: [%s]",f));
198207 }
199208 }
200-
209+
201210 // 古い番組データを置き換える
211+ if (pcenter != null)
212+ pcenter.clear();
202213 pcenter = newplist;
214+ newplist = null;
215+ return true;
203216 }
204-
217+
205218 /* ここまで */
206219
207-
208-
220+
221+
209222 /*
210223 * 非公開メソッド
211224 */
212-
213- protected void _loadProgram(String areacode, String adate, String edate, boolean force, int wdaycol, int counter, int counterMax) {
225+
226+ protected boolean _loadProgram(String areacode, String adate, String edate, boolean force, int wdaycol, int counter, int counterMax) {
214227 //
215228 final String progCacheFile = getProgCacheFile(areacode,adate);
216229 String dt = adate.substring(6,8);
@@ -223,10 +236,10 @@ public class PlugIn_TVPDimora extends TVProgramUtils implements TVProgram,Clonea
223236 if (force == true ||
224237 (f.exists() == true && isCacheOld(progCacheFile) == true) ||
225238 (f.exists() == false && isCacheOld(null) == true)) {
226-
239+
227240 GregorianCalendar c = new GregorianCalendar();
228241 c.setTime(new Date());
229-
242+
230243 String hh = String.valueOf(CommonUtils.getCalendar(0).get(Calendar.HOUR_OF_DAY));
231244 String tvParam = "1%2C1%2C1%2CDR%2C10%2C1%2C1%2C1%2C1%2C1%2C1";
232245 String url = "http://dimora.jp/dc/pc/P4501.do";
@@ -240,7 +253,7 @@ public class PlugIn_TVPDimora extends TVProgramUtils implements TVProgram,Clonea
240253 "%2C"+hh+"%2C",
241254 getChType(),
242255 "%2C0%2C"+tvParam);
243-
256+
244257 // 本体
245258 //clrCookie(); -> もっと上に
246259 addCookie("KEY_AREA", areacode);
@@ -252,14 +265,19 @@ public class PlugIn_TVPDimora extends TVProgramUtils implements TVProgram,Clonea
252265 url,
253266 pstr,
254267 null,
255- url,
268+ url,
256269 thisEncoding,
257270 false);
258-
271+
272+ if ( response == null ){
273+ reportProgress(ERRID+"番組表(オンライン)の取得に失敗しました["+dt+"日/"+aname+"]: ("+counter+"/"+counterMax+") "+url+"?"+pstr+"("+areacode+")");
274+ return false;
275+ }
276+
259277 if ( ! CommonUtils.write2file(progCacheFile, "<!-- "+url+"?"+pstr+" -->\n"+response) ) {
260278 reportProgress(ERRID+"番組表(キャッシュ)の保存に失敗しました: ("+counter+"/"+counterMax+") "+progCacheFile);
261279 }
262-
280+
263281 reportProgress(MSGID+"番組表(オンライン)を取得しました["+dt+"日/"+aname+"]: ("+counter+"/"+counterMax+") "+url+"?"+pstr+"("+areacode+")");
264282 }
265283 else if (CommonUtils.isFileAvailable(f,10)) {
@@ -267,38 +285,41 @@ public class PlugIn_TVPDimora extends TVProgramUtils implements TVProgram,Clonea
267285 response = CommonUtils.read4file(progCacheFile, false);
268286 if ( response == null ) {
269287 reportProgress(ERRID+"番組表(キャッシュ)の取得に失敗しました["+dt+"日/"+aname+"]: ("+counter+"/"+counterMax+") "+progCacheFile);
270- return;
288+ return false;
271289 }
272290 reportProgress(MSGID+"番組表(キャッシュ)を取得しました["+dt+"日/"+aname+"]: ("+counter+"/"+counterMax+") "+progCacheFile);
273291 }
274292 else {
275293 reportProgress(ERRID+"番組表(キャッシュ)がみつかりません["+dt+"日/"+aname+"]: ("+counter+"/"+counterMax+") "+progCacheFile);
276- return;
294+ return false;
277295 }
278-
296+
279297 // 番組リストの追加
280298 getPrograms(areacode, wdaycol, response);
281299 }
282300 catch (Exception e) {
283301 reportProgress(ERRID+"番組表の取得で例外が発生しました: "+e.toString());
284302 e.printStackTrace();
303+ return false;
285304 }
305+
306+ return true;
286307 }
287-
308+
288309 //
289310 private void getPrograms(String areacode, int wdaycol, String src) {
290-
311+
291312 for ( Center cr : crlist ) {
292-
313+
293314 if ( ! cr.getAreaCode().equals(areacode) && ! cr.getAreaCode().equals(bsCode) ) {
294315 continue;
295316 }
296-
317+
297318 Matcher ma = Pattern.compile(String.format("<div\\s+id=\"%s\">([\\s\\S]*?)</div>",cr.getLink())).matcher(src);
298319 if ( ! ma.find() ) {
299320 continue;
300321 }
301-
322+
302323 ProgDateList pcl = null;
303324 for ( ProgList pl : newplist ) {
304325 if ( (pl.Area.equals(areacode)||pl.Area.equals(bsCode)) && pl.Center.equals(cr.getCenter()) ) {
@@ -310,20 +331,20 @@ public class PlugIn_TVPDimora extends TVProgramUtils implements TVProgram,Clonea
310331 // 複数地域を同時に選択していると、BSの番組情報が重複して取得されるので、既得(pcl.row>0)ならスキップ
311332 continue;
312333 }
313-
334+
314335 String sdat = String.format("%s %02d:00",pcl.Date,getTimeBarStart());
315336 GregorianCalendar cx = CommonUtils.getCalendar(sdat);
316337 GregorianCalendar cy = (GregorianCalendar) cx.clone();
317338 cy.add(Calendar.DAY_OF_MONTH, 1);
318-
339+
319340 GregorianCalendar pcz = null;
320341 Matcher mb = Pattern.compile("([\\s\\S]+?)\\|").matcher(ma.group(1));
321342 while ( mb.find() && pcl.row < 1440 ) {
322-
343+
323344 String[] dat = mb.group(1).split(",");
324-
345+
325346 ProgDetailList pdl = new ProgDetailList();
326-
347+
327348 // 開始・終了日時
328349 GregorianCalendar ca = CommonUtils.getCalendar(dat[1]);
329350 if ( ca == null ) {
@@ -334,13 +355,13 @@ public class PlugIn_TVPDimora extends TVProgramUtils implements TVProgram,Clonea
334355 continue;
335356 }
336357 pdl.start = CommonUtils.getTime(ca);
337-
358+
338359 GregorianCalendar cz = CommonUtils.getCalendar(dat[2]);
339360 if ( cz == null ) {
340361 continue;
341362 }
342363 pdl.end = CommonUtils.getTime(cz);
343-
364+
344365 pdl.length = (int)(CommonUtils.getDiffDateTime(dat[1], dat[2])/60000L);
345366
346367 if ( pcz == null ) {
@@ -363,12 +384,12 @@ public class PlugIn_TVPDimora extends TVProgramUtils implements TVProgram,Clonea
363384 addEmptyInfo(pcl, CommonUtils.getDateTime(pcz), dat[1]);
364385 }
365386 }
366-
387+
367388 pcz = (GregorianCalendar) cz.clone();
368-
389+
369390 // タイトル&番組詳細
370391 pdl.title = CommonUtils.unEscape(dat[3]);
371-
392+
372393 dat[4] = CommonUtils.unEscape(dat[4]).trim();
373394 dat[5] = CommonUtils.unEscape(dat[5]).trim();
374395 dat[6] = CommonUtils.unEscape(dat[6]).trim();
@@ -379,10 +400,10 @@ public class PlugIn_TVPDimora extends TVProgramUtils implements TVProgram,Clonea
379400 pdl.detail = pdl.detail.replaceAll("\\^", " ");
380401 // 改行が挟まっているサブタイトルを1行にしたい
381402 pdl.detail = Pattern.compile("(#\\s*\\d+\\s*「[^」]*?)[\r\n]+[  ]*(.*?」)",Pattern.DOTALL).matcher(pdl.detail).replaceAll("$1 $2");
382-
403+
383404 // タイトルから各種フラグを分離する
384405 doSplitFlags(pdl, nf);
385-
406+
386407 // ジャンル
387408 {
388409 ArrayList<String> genrelist = new ArrayList<String>();
@@ -395,23 +416,23 @@ public class PlugIn_TVPDimora extends TVProgramUtils implements TVProgram,Clonea
395416
396417 // サブタイトル分離
397418 doSplitSubtitle(pdl);
398-
419+
399420 // 検索対象外領域にこっそりジャンル文字列を入れる
400421 pdl.setGenreStr();
401-
422+
402423 // プログラムID?
403424 String chid = ContentIdDIMORA.getChId(cr.getLink());
404425 ContentIdDIMORA.decodeChId(chid);
405426 pdl.progid = ContentIdDIMORA.getContentId(0,dat[8]);
406-
427+
407428 // その他フラグ
408429 pdl.extension = false;
409430 //pdl.flag = ProgFlags.NOFLAG;
410431 pdl.nosyobo = false;
411-
432+
412433 //
413434 pcl.pdetail.add(pdl);
414-
435+
415436 //
416437 pcl.row += pdl.length;
417438 }
@@ -425,20 +446,20 @@ public class PlugIn_TVPDimora extends TVProgramUtils implements TVProgram,Clonea
425446 }
426447 }
427448 }
428-
429-
449+
450+
430451 /*******************************************************************************
431452 * 地域情報を取得する
432453 ******************************************************************************/
433-
454+
434455 // 普通は東京
435456 @Override
436457 public String getDefaultArea() {return "東京";}
437-
458+
438459 //
439460 @Override
440461 public void loadAreaCode() {
441-
462+
442463 // 設定ファイルが存在していればファイルから
443464 File f = new File(getAreaSelectedFile());
444465 if (f.exists() == true) {
@@ -464,7 +485,7 @@ public class PlugIn_TVPDimora extends TVProgramUtils implements TVProgram,Clonea
464485
465486 // 地域一覧の作成
466487 ArrayList<AreaCode> newaclist = new ArrayList<AreaCode>();
467-
488+
468489 Matcher ma = Pattern.compile("<div\\s+id=\"includeAreaList\">(.+?)</div>").matcher(response);
469490 if ( ma.find() ) {
470491 Matcher mb = Pattern.compile("(.+?),(.+?)\\|").matcher(ma.group(1));
@@ -475,12 +496,12 @@ public class PlugIn_TVPDimora extends TVProgramUtils implements TVProgram,Clonea
475496 newaclist.add(ac);
476497 }
477498 }
478-
499+
479500 if ( newaclist.size() == 0 ) {
480501 System.err.println(ERRID+"地域一覧の取得結果が0件だったため情報を更新しません");
481502 return;
482503 }
483-
504+
484505 {
485506 AreaCode ac = new AreaCode();
486507 ac.setArea("全国");
@@ -493,12 +514,12 @@ public class PlugIn_TVPDimora extends TVProgramUtils implements TVProgram,Clonea
493514 ac.setCode(bsCode);
494515 newaclist.add(ac);
495516 }
496-
517+
497518 aclist = newaclist;
498519 saveAreaCode();
499520 }
500-
501-
521+
522+
502523 /*******************************************************************************
503524 * 放送局情報を取得する
504525 ******************************************************************************/
@@ -506,28 +527,28 @@ public class PlugIn_TVPDimora extends TVProgramUtils implements TVProgram,Clonea
506527 // 設定ファイルがなければWebから取得
507528 @Override
508529 public void loadCenter(String code, boolean force) {
509-
530+
510531 if ( code == null ) {
511532 System.out.println(ERRID+"地域コードがnullです.");
512533 return;
513534 }
514-
535+
515536 String centerListFile = getCenterListFile(getTVProgramId(), code);
516-
537+
517538 if (force) {
518539 File f = new File(centerListFile);
519540 f.delete();
520541 }
521-
542+
522543 File f = new File(centerListFile);
523544 if (f.exists() == true) {
524545 @SuppressWarnings("unchecked")
525546 ArrayList<Center> tmp = (ArrayList<Center>) CommonUtils.readXML(centerListFile);
526547 if ( tmp != null ) {
527-
548+
528549 crlist = tmp;
529550 attachChFilters(); // 放送局名変換
530-
551+
531552 System.out.println(MSGID+"放送局リストを読み込みました: "+centerListFile);
532553 return;
533554 }
@@ -535,13 +556,13 @@ public class PlugIn_TVPDimora extends TVProgramUtils implements TVProgram,Clonea
535556 System.err.println(ERRID+"放送局リストの読み込みに失敗しました: "+centerListFile);
536557 }
537558 }
538-
559+
539560 // Web上から放送局の一覧を取得する
540561 ArrayList<Center> newcrlist = new ArrayList<Center>();
541-
562+
542563 int cntMax = ((code.equals(allCode))?(aclist.size()-2):(1));
543564 int cnt = 1;
544-
565+
545566 if ( code.equals(allCode) ) {
546567 for ( AreaCode ac : aclist ) {
547568 if ( ! ac.getCode().equals(allCode) && ! ac.getCode().equals(bsCode) ) {
@@ -556,7 +577,7 @@ public class PlugIn_TVPDimora extends TVProgramUtils implements TVProgram,Clonea
556577 reportProgress(MSGID+"放送局情報を取得しました: ("+cnt+"/"+cntMax+") ");
557578 cnt++;
558579 }
559-
580+
560581 if ( newcrlist.size() == 0 ) {
561582 System.err.println(ERRID+"放送局情報の取得結果が0件だったため情報を更新しません");
562583 return;
@@ -566,17 +587,17 @@ public class PlugIn_TVPDimora extends TVProgramUtils implements TVProgram,Clonea
566587 attachChFilters(); // 放送局名変換
567588 saveCenter();
568589 }
569-
590+
570591 private boolean _loadCenter(ArrayList<Center> newcrlist, String code, boolean bsexist) {
571592 // 本体
572593 String uri = "http://dimora.jp/dc/pc/P4501.do";
573-
594+
574595 GregorianCalendar c = CommonUtils.getCalendar(0);
575596 String cdate = CommonUtils.getDateTimeYMD(c);
576597 String adate = CommonUtils.getDateYMD(c);
577598 c.add(Calendar.DAY_OF_MONTH, 1);
578599 String edate = CommonUtils.getDateYMD(c);
579-
600+
580601 clrCookie();
581602 addCookie("KEY_AREA", code);
582603 String response = webToBuffer(
@@ -595,12 +616,12 @@ public class PlugIn_TVPDimora extends TVProgramUtils implements TVProgram,Clonea
595616 thisEncoding,
596617 true);
597618 if ( response == null ) {
598- System.err.println(ERRID+"放送局情報の取得に失敗しました: "+uri);
619+ reportProgress(ERRID+"番組表の取得に失敗しました: "+uri);
599620 return false;
600621 }
601-
622+
602623 //CommonUtils.write2file("TMP.htm", response);
603-
624+
604625 String expr = String.format("<div\\s+id=\"%s\"\\s*>(.+?)</div>", getCenterInfoId());
605626 Matcher ma = Pattern.compile(expr).matcher(response);
606627 if ( ma.find() ) {
@@ -609,13 +630,13 @@ public class PlugIn_TVPDimora extends TVProgramUtils implements TVProgram,Clonea
609630 String centerName = CommonUtils.unEscape(mb.group(3));
610631 String chNo = mb.group(2);
611632 String centerId = mb.group(1);
612-
633+
613634 String areacode = getCenterCode(centerId,code);
614635 if ( bsexist && areacode.equals(bsCode) ) {
615636 // 重複するBSは排除
616637 continue;
617638 }
618-
639+
619640 // NHK関連
620641 if ( areacode.equals(bsCode) ) {
621642 if ( centerName.startsWith("NHK") ) {
@@ -643,7 +664,7 @@ public class PlugIn_TVPDimora extends TVProgramUtils implements TVProgram,Clonea
643664 }
644665 }
645666 }
646-
667+
647668 Center cr = new Center();
648669 cr.setAreaCode(areacode);
649670 cr.setCenterOrig(centerName);
@@ -655,7 +676,7 @@ public class PlugIn_TVPDimora extends TVProgramUtils implements TVProgram,Clonea
655676 }
656677 }
657678 }
658-
679+
659680 return true;
660681 }
661682
--- a/TinyBannavi/src/tainavi/plugintv/PlugIn_TVPEDCB.java
+++ b/TinyBannavi/src/tainavi/plugintv/PlugIn_TVPEDCB.java
@@ -10,24 +10,21 @@ import java.util.HashMap;
1010 import java.util.regex.Matcher;
1111 import java.util.regex.Pattern;
1212
13+import epgdump.EIT_CONTROL;
14+import epgdump.Epgdump;
15+import epgdump.SVT_CONTROL;
1316 import tainavi.AreaCode;
1417 import tainavi.Center;
1518 import tainavi.CommonUtils;
1619 import tainavi.ContentIdEDCB;
1720 import tainavi.MapCtrl;
21+import tainavi.MapCtrl.KeyType;
1822 import tainavi.ProgDateList;
1923 import tainavi.ProgDetailList;
2024 import tainavi.ProgList;
2125 import tainavi.TVProgram;
2226 import tainavi.TVProgramUtils;
2327 import tainavi.TatCount;
24-import tainavi.MapCtrl.KeyType;
25-import tainavi.TVProgram.ProgSubtype;
26-import tainavi.TVProgram.ProgType;
27-
28-import epgdump.EIT_CONTROL;
29-import epgdump.Epgdump;
30-import epgdump.SVT_CONTROL;
3128
3229
3330 public class PlugIn_TVPEDCB extends TVProgramUtils implements TVProgram,Cloneable {
@@ -37,44 +34,44 @@ public class PlugIn_TVPEDCB extends TVProgramUtils implements TVProgram,Cloneabl
3734 }
3835
3936 private static final String thisEncoding = "UTF-8";
40-
41-
37+
38+
4239 /*******************************************************************************
4340 * 種族の特性
4441 ******************************************************************************/
45-
42+
4643 @Override
4744 public String getTVProgramId() { return "EDCB"; }
48-
45+
4946 @Override
5047 public ProgType getType() { return ProgType.PROG; }
5148 @Override
5249 public ProgSubtype getSubtype() { return ProgSubtype.TERRA; }
5350
54-
51+
5552 /*******************************************************************************
5653 * 個体の特性
5754 ******************************************************************************/
58-
55+
5956 @Override
6057 public int getTimeBarStart() {return 5;}
61-
58+
6259 private int getDogDays() { return ((getExpandTo8())?(8):(7)); }
63-
64-
60+
61+
6562 /*******************************************************************************
6663 * 定数
6764 ******************************************************************************/
68-
65+
6966 private static final String OPTKEY_DIR = "datdir";
7067 private static final String OPTVAL_DIR_DEFAULT = "D:/PT2/EpgDataCap_Bon/Setting/EpgData/";
7168 private static final String fnext = "_epg.dat";
7269
7370 private static final String OPTKEY_URL = "url";
7471 private static final String OPTVAL_URL_DEFAULT = "http://127.0.0.1:5510/(dat参照をやめる場合はこのコメントを削除)";
75-
72+
7673 private static final String TEXT_NANSHICHO_HEADER = "臨)";
77-
74+
7875 private final String MSGID = "["+getTVProgramId()+"] ";
7976 private final String ERRID = "[ERROR]"+MSGID;
8077 private final String DBGID = "[DEBUG]"+MSGID;
@@ -82,22 +79,22 @@ public class PlugIn_TVPEDCB extends TVProgramUtils implements TVProgram,Cloneabl
8279 /*******************************************************************************
8380 * 部品
8481 ******************************************************************************/
85-
82+
8683 // 新しい入れ物の臨時格納場所
8784 private ArrayList<ProgList> newplist;
8885 private ArrayList<SVT_CONTROL> svtlist;
89-
86+
9087 // 未定義のフラグの回収場所
9188 private HashMap<String,String> nf = null;
92-
89+
9390 private String getProgCacheFile() { return getProgDir()+File.separator+"EDCB.xml"; }
94-
91+
9592 /*
9693 * フリーオプション用のクラス
9794 */
9895
9996 private OptMap opts = null;
100-
97+
10198 private class OptMap extends MapCtrl {
10299 @Override
103100 protected boolean chkOptString() {
@@ -127,11 +124,11 @@ public class PlugIn_TVPEDCB extends TVProgramUtils implements TVProgram,Cloneabl
127124 System.out.println(MSGID+"[EDCB番組表未使用の方は無視してください] EDCBのURLは設定値になります: "+optval);
128125 }
129126 }
130-
127+
131128 return true;
132129 }
133130 }
134-
131+
135132 // datファイルをリストアップする
136133 private ArrayList<String> getDatFiles(String path, String ext) {
137134 ArrayList<String> dfiles = new ArrayList<String>();
@@ -150,30 +147,30 @@ public class PlugIn_TVPEDCB extends TVProgramUtils implements TVProgram,Cloneabl
150147 return new ArrayList<String>();
151148 }
152149 }
153-
150+
154151
155152 /*******************************************************************************
156153 * コンストラクタ
157154 ******************************************************************************/
158-
155+
159156 public PlugIn_TVPEDCB() {
160-
157+
161158 super();
162-
159+
163160 opts = new OptMap();
164-
161+
165162 // 保存先の設定
166163 opts.setFilename("env"+File.separator+"options_"+getTVProgramId()+".xml");
167-
164+
168165 // オプションキーリストの設定
169166 opts.putdef(OPTKEY_DIR, KeyType.DIR);
170167 opts.putdef(OPTKEY_URL, KeyType.URL);
171168
172169 //
173170 opts.initOptString();
174-
171+
175172 }
176-
173+
177174 @Override
178175 public boolean setOptString(String s) {
179176 if ( s == null ) {
@@ -182,34 +179,34 @@ public class PlugIn_TVPEDCB extends TVProgramUtils implements TVProgram,Cloneabl
182179 }
183180 return opts.setOptString(s);
184181 }
185-
182+
186183 @Override
187184 public String getOptString() {
188185 // ちょっとちょーだい
189186 return opts.toString();
190187 }
191-
192-
188+
189+
193190 /*******************************************************************************
194191 * 番組情報を取得する
195192 ******************************************************************************/
196-
193+
197194 @Override
198- public void loadProgram(String areaCode, boolean force) {
199-
195+ public boolean loadProgram(String areaCode, boolean force) {
196+
200197 // 新しい入れ物(トップ)を用意する
201198 newplist = new ArrayList<ProgList>();
202199 svtlist = new ArrayList<SVT_CONTROL>();
203200 nf = new HashMap<String, String>();
204-
201+
205202 // トップの下に局ごとのリストを生やす
206203 for ( Center cr : crlist ) {
207-
204+
208205 if ( cr.getOrder() <= 0 ) {
209206 // 設定上無効な局はいらない
210207 continue;
211208 }
212-
209+
213210 // ProgList
214211 ProgList pl = new ProgList();
215212 pl.Area = cr.getAreaCode();
@@ -219,17 +216,17 @@ public class PlugIn_TVPEDCB extends TVProgramUtils implements TVProgram,Cloneabl
219216 pl.CenterId = cr.getLink();
220217 pl.enabled = true;
221218 newplist.add(pl);
222-
219+
223220 // SVT
224221 SVT_CONTROL svt = new SVT_CONTROL();
225222 svt.setServicename(pl.Center);
226223 setCenterLink(svt,cr.getLink());
227224 svt.setEnabled(true);
228225 svtlist.add(svt);
229-
226+
230227 if (getDebug()) System.err.println(DBGID+"Center added: "+pl.Center+"("+pl.CenterId+")");
231228 }
232-
229+
233230 // 局の下に日付ごとのリストを生やす(当日前日からの日跨りを考慮して、前日から7+1日分)
234231 GregorianCalendar cal = new GregorianCalendar();
235232 cal.setTime(new Date());
@@ -248,7 +245,7 @@ public class PlugIn_TVPEDCB extends TVProgramUtils implements TVProgram,Cloneabl
248245 }
249246 cale.add(Calendar.DATE, 1);
250247 }
251-
248+
252249 // 日付の下に番組情報ごとのリストを生やす
253250 if ( opts.get(OPTKEY_URL) != null && opts.get(OPTKEY_URL).matches("^https?://[^/]+?:\\d+/$") ) {
254251 //
@@ -261,49 +258,50 @@ public class PlugIn_TVPEDCB extends TVProgramUtils implements TVProgram,Cloneabl
261258 else {
262259 _loadProgramFromDAT(force);
263260 }
264-
261+
265262 // 隙間を埋める
266263 for ( ProgList pl : newplist ) {
267264 refreshList(pl.pdate);
268265 }
269-
266+
270267 // 余分に作成した前日分はカット
271268 for ( ProgList pl : newplist ) {
272269 pl.pdate.remove(0);
273270 }
274-
271+
275272 // 開始・終了日時を正しい値に計算しなおす
276273 for ( ProgList pl : newplist ) {
277274 setAccurateDate(pl.pdate);
278275 }
279-
276+
280277 // 古いデータから補完できないかな?
281278 CompensatesPrograms(newplist);
282-
279+
283280 // 解析用
284281 {
285282 for ( String f : nf.keySet() ) {
286283 System.err.println(String.format(DBGID+"未定義のフラグです: [%s]",f));
287284 }
288285 }
289-
286+
290287 // 古い番組データを置き換える
291288 pcenter = newplist;
292289 svtlist = null;
290+ return true;
293291 }
294-
292+
295293 /* ここまで */
296294
297-
298-
295+
296+
299297 /*
300298 * 非公開メソッド
301299 */
302-
300+
303301 private void _loadProgramFromAPI(Center cr, boolean force, int counter, int counterMax) {
304302 //
305303 try {
306-
304+
307305 // いれるところ
308306 SVT_CONTROL svt = new SVT_CONTROL();
309307 ContentIdEDCB.decodeChId(cr.getLink());
@@ -312,28 +310,28 @@ public class PlugIn_TVPEDCB extends TVProgramUtils implements TVProgram,Cloneabl
312310 svt.setServive_id(ContentIdEDCB.getSId());
313311 svt.setServicename(cr.getCenterOrig());
314312 svt.setEnabled(true);
315-
313+
316314 svtlist = new ArrayList<SVT_CONTROL>();
317315 svtlist.add(svt);
318-
316+
319317 final String progCacheFile = String.format(getProgDir()+File.separator+"TVEDCB_%s.xml.zip", cr.getLink()); // getLink()はCHコード
320318 String response = null;
321-
319+
322320 File f = new File(progCacheFile);
323321 if (force == true ||
324322 (f.exists() == true && isCacheOld(progCacheFile) == true) ||
325323 (f.exists() == false && isCacheOld(null) == true)) {
326-
324+
327325 String url = opts.get(OPTKEY_URL)+"api/EnumEventInfo?ONID="+svt.getOriginal_network_id()+"&TSID="+svt.getTransport_stream_id()+"&SID="+svt.getServive_id()+"&basic=0&count=2000";
328-
326+
329327 // Web番組表の読み出し
330328 response = webToBuffer(url, thisEncoding, true);
331-
329+
332330 // キャッシュファイルの保存
333331 if ( ! CommonUtils.write2file(progCacheFile, response) ) {
334332 reportProgress(ERRID+"番組表(キャッシュ)の保存に失敗しました: ("+counter+"/"+counterMax+") "+progCacheFile);
335333 }
336-
334+
337335 reportProgress(MSGID+"(オンライン)を取得しました: ("+counter+"/"+counterMax+") "+cr.getCenter()+" "+url);
338336 }
339337 else if (f.exists()) {
@@ -350,7 +348,7 @@ public class PlugIn_TVPEDCB extends TVProgramUtils implements TVProgram,Cloneabl
350348 }
351349
352350 //
353-
351+
354352 Matcher ma = Pattern.compile("<eventinfo>(.+?)</eventinfo>", Pattern.DOTALL).matcher(response);
355353 while ( ma.find() ) {
356354
@@ -361,9 +359,9 @@ public class PlugIn_TVPEDCB extends TVProgramUtils implements TVProgram,Cloneabl
361359 Integer length = null;
362360 String title = null;
363361 String subtitle = null;
364- String detail = null;
362+ String detail = null;
365363 ArrayList<String> content_type = new ArrayList<String>();
366-
364+
367365 Matcher mb = Pattern.compile("<(.+?)>(.+?)</\\1>", Pattern.DOTALL).matcher(ma.group(1));
368366 while ( mb.find() ) {
369367 if ( mb.group(1).equals("eventID") ) {
@@ -416,45 +414,45 @@ public class PlugIn_TVPEDCB extends TVProgramUtils implements TVProgram,Cloneabl
416414 }
417415 }
418416 }
419-
417+
420418 //
421-
419+
422420 EIT_CONTROL eit = new EIT_CONTROL();
423-
421+
424422 eit.setEvent_id(evid);
425-
423+
426424 eit.setYy(cal.get(Calendar.YEAR));
427425 eit.setMm(cal.get(Calendar.MONTH)+1);
428426 eit.setDd(cal.get(Calendar.DAY_OF_MONTH));
429-
427+
430428 cal.set(Calendar.HOUR, hh);
431429 cal.set(Calendar.MINUTE, hm);
432430 eit.setHh(hh);
433431 eit.setHm(hm);
434432 eit.setSs(0);
435-
433+
436434 int dhm = length % 60;
437435 int dhh = (length-dhm) / 60;
438-
436+
439437 eit.setDhh(dhh);
440438 eit.setDhm(dhm);
441-
439+
442440 /* - 使わないので要らない -
443441 cal.add(Calendar.MINUTE, length);
444442 eit.setEhh(cal.get(Calendar.HOUR));
445443 eit.setEhm(cal.get(Calendar.DAY_OF_MONTH));
446444 eit.setEss(0);
447445 */
448-
446+
449447 eit.setTitle(title);
450448 eit.setSubtitle(subtitle);
451449 eit.setDetail(detail);
452450 eit.setContent_type(content_type);
453-
451+
454452 /* - 使わないので要らない -
455453 eit.setPerformer(null)
456454 */
457-
455+
458456 int n = 0;
459457 for ( EIT_CONTROL etmp : svt.getEittop() ) {
460458 String a = String.format("%04d%02d%02d%02d%02d", etmp.getYy(), etmp.getMm(), etmp.getDd(), etmp.getHh(), etmp.getHm());
@@ -464,10 +462,10 @@ public class PlugIn_TVPEDCB extends TVProgramUtils implements TVProgram,Cloneabl
464462 }
465463 n++;
466464 }
467-
465+
468466 svt.getEittop().add(n,eit);
469467 }
470-
468+
471469 // データ形式の変換
472470 convEpg2Programs();
473471 }
@@ -476,7 +474,7 @@ public class PlugIn_TVPEDCB extends TVProgramUtils implements TVProgram,Cloneabl
476474 e.printStackTrace();
477475 }
478476 }
479-
477+
480478 private void _loadProgramFromDAT(boolean force) {
481479 //
482480 final String progCacheFile = getProgCacheFile();
@@ -487,10 +485,10 @@ public class PlugIn_TVPEDCB extends TVProgramUtils implements TVProgram,Cloneabl
487485 if (force == true ||
488486 (f.exists() == true && isCacheOld(progCacheFile) == true) ||
489487 (f.exists() == false && isCacheOld(null) == true)) {
490-
488+
491489 // 参照するファイルの一覧
492490 ArrayList<String> dfiles = getDatFiles(opts.get(OPTKEY_DIR),fnext);
493-
491+
494492 // 参照する総ファイル数
495493 int counterMax = dfiles.size();
496494
@@ -513,11 +511,11 @@ public class PlugIn_TVPEDCB extends TVProgramUtils implements TVProgram,Cloneabl
513511 }
514512 reportProgress(String.format("%s(EPGデータ)を取得しました[%5.1fMB,%.2f秒]: (%d/%d) %s",getTVProgramId(),new File(dfiles.get(i)).length()/1000000.0D,tc.end(),i+1,counterMax,dfiles.get(i)));
515513 }
516-
514+
517515 reportProgress(String.format("%s(EPGデータ)をすべて取得しました[%.2f秒]",getTVProgramId(),tcall.end()));
518-
516+
519517 epg = null;
520-
518+
521519 tc.restart();
522520 reportProgress(String.format("%s(キャッシュ)を保存します: %s",getTVProgramId(),progCacheFile));
523521 if ( ! CommonUtils.writeXML(progCacheFile, svtlist) ) {
@@ -545,16 +543,16 @@ public class PlugIn_TVPEDCB extends TVProgramUtils implements TVProgram,Cloneabl
545543 reportProgress(getTVProgramId()+"(キャッシュ)がみつかりません: "+progCacheFile);
546544 return;
547545 }
548-
546+
549547 if (getDebug()) {
550548 for ( SVT_CONTROL svt : svtlist ) {
551549 System.err.println("[DEBUG] programs loaded: "+svt.getServicename()+" ("+svt.getEittop().size()+")");
552550 }
553551 }
554-
552+
555553 // データ形式の変換
556554 convEpg2Programs();
557-
555+
558556 }
559557 catch (Exception e) {
560558 // 例外
@@ -562,20 +560,20 @@ public class PlugIn_TVPEDCB extends TVProgramUtils implements TVProgram,Cloneabl
562560 e.printStackTrace();
563561 }
564562 }
565-
563+
566564 //
567565 private void convEpg2Programs() {
568-
566+
569567 for ( SVT_CONTROL svt : svtlist ) {
570-
568+
571569 // 不要になる領域は早々に処分する
572570 ArrayList<EIT_CONTROL> eittop = svt.getEittop();
573571 svt.setEittop(null);
574-
572+
575573 if ( eittop.size() == 0 ) {
576574 continue;
577575 }
578-
576+
579577 // 登録先の放送局をみつける
580578 ProgList pl = null;
581579 for ( int i=0; i<newplist.size(); i++ ) {
@@ -587,11 +585,11 @@ public class PlugIn_TVPEDCB extends TVProgramUtils implements TVProgram,Cloneabl
587585 if ( pl == null ) {
588586 continue;
589587 }
590-
588+
591589 for ( EIT_CONTROL eit : eittop ) {
592-
590+
593591 ProgDetailList pdl = new ProgDetailList();
594-
592+
595593 // 開始日時
596594 GregorianCalendar ca = new GregorianCalendar();
597595 ca.set(Calendar.YEAR, eit.getYy());
@@ -602,7 +600,7 @@ public class PlugIn_TVPEDCB extends TVProgramUtils implements TVProgram,Cloneabl
602600 ca.set(Calendar.SECOND, 0);
603601 pdl.start = CommonUtils.getTime(ca);
604602 pdl.startDateTime = CommonUtils.getDateTime(ca);
605-
603+
606604 // 登録先の日付をみつける
607605 GregorianCalendar ct = (GregorianCalendar) ca.clone();
608606 if ( CommonUtils.isLateNight(ca) ) {
@@ -619,10 +617,10 @@ public class PlugIn_TVPEDCB extends TVProgramUtils implements TVProgram,Cloneabl
619617 if ( pcl == null ) {
620618 continue;
621619 }
622-
620+
623621 // 長さ
624622 pdl.length = eit.getDhh()*60 + eit.getDhm();
625-
623+
626624 // 終了日時
627625 GregorianCalendar cz = (GregorianCalendar) ca.clone();
628626 cz.add(Calendar.MINUTE, pdl.length);
@@ -631,44 +629,44 @@ public class PlugIn_TVPEDCB extends TVProgramUtils implements TVProgram,Cloneabl
631629
632630 // 番組ID
633631 pdl.progid = ContentIdEDCB.getContentId(pl.CenterId,eit.getEvent_id());
634-
632+
635633 // タイトル&番組詳細
636634 pdl.title = (eit.getTitle() == null) ? "" : eit.getTitle();
637- pdl.detail =
635+ pdl.detail =
638636 ((eit.getSubtitle() != null) ? (eit.getSubtitle()+DETAIL_SEP):(""))
639637 +((eit.getDetail() != null) ? (eit.getDetail()+DETAIL_SEP):(""))
640638 +((eit.getPerformer() != null) ? (eit.getPerformer()+DETAIL_SEP):(""));
641639 pdl.detail = pdl.detail.replaceFirst("[\r\n]+$", "");
642-
640+
643641 // タイトルから各種フラグを分離する
644642 doSplitFlags(pdl, nf);
645-
643+
646644 // ジャンル
647645 setMultiGenre(pdl,eit.getContent_type());
648-
646+
649647 // サブタイトル分離
650648 doSplitSubtitle(pdl);
651-
649+
652650 // 検索対象外領域にこっそりジャンル文字列を入れる
653651 pdl.setGenreStr();
654-
652+
655653 // 検索対象外領域にこっそりID文字列を入れる(progidもここで入る)
656654 pdl.setContentIdStr();
657-
655+
658656 // その他フラグ
659657 pdl.extension = false;
660658 //pdl.flag = ProgFlags.NOFLAG;
661659 pdl.nosyobo = false;
662-
660+
663661 //
664662 pcl.pdetail.add(pdl);
665-
663+
666664 //
667665 pcl.row += pdl.length;
668666 }
669667 }
670668 }
671-
669+
672670 //
673671 private void refreshList(ArrayList<ProgDateList> pcenter) {
674672 // 日付(29時)をまたいでいるものをコピーする
@@ -689,7 +687,7 @@ public class PlugIn_TVPEDCB extends TVProgramUtils implements TVProgram,Cloneabl
689687 pdl = pdl.clone();
690688 pdl.length = (int) ((cz.getTimeInMillis() - tbca.getTimeInMillis())/60000L);
691689 pcenter.get(i+1).pdetail.add(0,pdl);
692-
690+
693691 if (getDebug()) System.err.println("[DEBUG] copy "+pdl.startDateTime+" - "+pdl.endDateTime+" to "+pcenter.get(i+1).Date);
694692 }
695693 }
@@ -712,7 +710,7 @@ public class PlugIn_TVPEDCB extends TVProgramUtils implements TVProgram,Cloneabl
712710 }
713711 pl.pdetail = cur;
714712 }
715-
713+
716714 // 総時間数等を整理する
717715 for ( ProgDateList pl : pcenter ) {
718716 // 1日の合計分数を足し合わせる
@@ -731,16 +729,16 @@ public class PlugIn_TVPEDCB extends TVProgramUtils implements TVProgram,Cloneabl
731729 }
732730 }
733731 }
734-
735-
732+
733+
736734 /*******************************************************************************
737735 * 地域情報を取得する
738736 ******************************************************************************/
739-
737+
740738 // EDCBは地元というか実際に視聴できる局しか情報がとれないね
741739 @Override
742740 public String getDefaultArea() { return "すべて"; }
743-
741+
744742 //
745743 @Override
746744 public void loadAreaCode() {
@@ -771,38 +769,38 @@ public class PlugIn_TVPEDCB extends TVProgramUtils implements TVProgram,Cloneabl
771769 aclist.add(ac);
772770 }
773771 }
774-
772+
775773 @Override
776774 public void saveAreaCode() {
777775 }
778-
779-
776+
777+
780778 /*******************************************************************************
781779 * 放送局情報を取得する
782780 ******************************************************************************/
783-
781+
784782 // 設定ファイルがなければWebから取得
785783 @SuppressWarnings("unchecked")
786784 @Override
787785 public void loadCenter(String code, boolean force) {
788-
786+
789787 String centerListFile = getCenterListFile(getTVProgramId(), code);
790-
788+
791789 if (force) {
792790 File f = new File(centerListFile);
793791 f.delete();
794792 }
795-
793+
796794 File f = new File(centerListFile);
797795 if (f.exists() == true) {
798796 ArrayList<Center> tmp = (ArrayList<Center>) CommonUtils.readXML(centerListFile);
799797 if ( tmp != null ) {
800-
798+
801799 crlist = tmp;
802-
800+
803801 // 放送局名変換
804802 attachChFilters();
805-
803+
806804 System.out.println(MSGID+"放送局リストを読み込みました: "+centerListFile);
807805 return;
808806 }
@@ -810,25 +808,25 @@ public class PlugIn_TVPEDCB extends TVProgramUtils implements TVProgram,Cloneabl
810808 System.out.println(ERRID+"放送局リストの読み込みに失敗しました: "+centerListFile);
811809 }
812810 }
813-
811+
814812 // Web上から放送局の一覧を取得する
815813 ArrayList<Center> tmpCrList = new ArrayList<Center>();
816814 ArrayList<Center> trCrList = new ArrayList<Center>();
817815 ArrayList<Center> bsCrList = new ArrayList<Center>();
818816 ArrayList<Center> csCrList = new ArrayList<Center>();
819817 ArrayList<Center> otCrList = new ArrayList<Center>();
820-
818+
821819 if ( opts.get(OPTKEY_URL) != null && opts.get(OPTKEY_URL).matches("^https?://[^/]+?:\\d+/$") ) {
822820 // APIを使う
823- String url = opts.get(OPTKEY_URL)+"api/EnumService";
821+ String url = opts.get(OPTKEY_URL)+"api/EnumService";
824822 String response = webToBuffer(url,thisEncoding,true);
825823 if ( response == null ) {
826824 System.err.println(ERRID+"放送局情報の取得に失敗しました: "+url);
827825 return;
828826 }
829-
827+
830828 reportProgress(MSGID+"放送局情報を取得しました: "+url);
831-
829+
832830 Matcher ma = Pattern.compile("<serviceinfo>(.+?)</serviceinfo>", Pattern.DOTALL).matcher(response);
833831 while ( ma.find() ) {
834832 Integer onid = null;
@@ -840,7 +838,7 @@ public class PlugIn_TVPEDCB extends TVProgramUtils implements TVProgram,Cloneabl
840838 /*
841839 * 解析
842840 */
843-
841+
844842 if ( mb.group(1).equals("service_name") ) {
845843 ch_name = mb.group(2);
846844 }
@@ -854,24 +852,24 @@ public class PlugIn_TVPEDCB extends TVProgramUtils implements TVProgram,Cloneabl
854852 sid = Integer.valueOf(mb.group(2));
855853 }
856854 }
857-
855+
858856 String chid = ContentIdEDCB.getChId(onid, tsid, sid);
859-
857+
860858 Center cr = new Center();
861859 cr.setLink(chid);
862860 cr.setAreaCode(getCenterCode(cr.getLink()));
863-
861+
864862 if ( tsid == 0x4310 || tsid == 0x4311 ) {
865863 cr.setCenterOrig(TEXT_NANSHICHO_HEADER+ch_name);
866864 }
867865 else {
868866 cr.setCenterOrig(ch_name);
869867 }
870-
868+
871869 cr.setCenter(null);
872870 cr.setType("");
873871 cr.setEnabled(true);
874-
872+
875873 tmpCrList.add(cr);
876874 }
877875 }
@@ -881,9 +879,9 @@ public class PlugIn_TVPEDCB extends TVProgramUtils implements TVProgram,Cloneabl
881879 System.out.println(ERRID+".datファイルの場所が正しくないため放送局リストの読み込みはキャンセルされました: "+opts.get(OPTKEY_DIR));
882880 return;
883881 }
884-
882+
885883 Epgdump epg = new Epgdump();
886-
884+
887885 ArrayList<String> dfiles = getDatFiles(opts.get(OPTKEY_DIR),fnext);
888886 if ( dfiles != null ) {
889887 // SVT
@@ -901,18 +899,18 @@ public class PlugIn_TVPEDCB extends TVProgramUtils implements TVProgram,Cloneabl
901899 Center cr = new Center();
902900 cr.setLink(getCenterLink(svt));
903901 cr.setAreaCode(getCenterCode(cr.getLink()));
904-
902+
905903 if ( svt.getTransport_stream_id() == 0x4310 || svt.getTransport_stream_id() == 0x4311 ) {
906904 cr.setCenterOrig(TEXT_NANSHICHO_HEADER+svt.getServicename());
907905 }
908906 else {
909907 cr.setCenterOrig(svt.getServicename());
910908 }
911-
909+
912910 cr.setCenter(null);
913911 cr.setType("");
914912 cr.setEnabled(true);
915-
913+
916914 int n = 0;
917915 for ( Center ctmp : tmpCrList ) {
918916 if ( ctmp.getLink().compareTo(cr.getLink()) < 0 ) {
@@ -943,9 +941,9 @@ public class PlugIn_TVPEDCB extends TVProgramUtils implements TVProgram,Cloneabl
943941 //otCrList.add(cr);
944942 }
945943 }
946-
944+
947945 ArrayList<Center> newcrlist = new ArrayList<Center>();
948-
946+
949947 for ( Center cr : trCrList ) {
950948 newcrlist.add(cr);
951949 }
@@ -958,18 +956,18 @@ public class PlugIn_TVPEDCB extends TVProgramUtils implements TVProgram,Cloneabl
958956 for ( Center cr : otCrList ) {
959957 newcrlist.add(cr);
960958 }
961-
959+
962960 if ( newcrlist.size() == 0 ) {
963961 System.err.println(ERRID+"放送局情報の取得結果が0件だったため情報を更新しません");
964962 return;
965963 }
966-
967- crlist = newcrlist;
964+
965+ crlist = newcrlist;
968966 chkCrNameDuped(crlist); // 放送局名の重複排除
969967 attachChFilters(); // 放送局名変換
970968 saveCenter();
971969 }
972-
970+
973971 private void addCenter(ArrayList<Center> newcrlist, Center cr) {
974972 int n=0;
975973 for ( ; n<newcrlist.size(); n++ ) {
@@ -979,12 +977,12 @@ public class PlugIn_TVPEDCB extends TVProgramUtils implements TVProgram,Cloneabl
979977 }
980978 newcrlist.add(n,cr);
981979 }
982-
980+
983981 //
984982 private String getCenterLink(SVT_CONTROL svt) {
985983 return ContentIdEDCB.getChId(svt.getOriginal_network_id(),svt.getTransport_stream_id(),svt.getServive_id());
986984 }
987-
985+
988986 //
989987 private void setCenterLink(SVT_CONTROL svt, String link) {
990988 if ( ContentIdEDCB.decodeChId(link) ) {
@@ -993,7 +991,7 @@ public class PlugIn_TVPEDCB extends TVProgramUtils implements TVProgram,Cloneabl
993991 svt.setServive_id(ContentIdEDCB.getSId());
994992 }
995993 }
996-
994+
997995 //
998996 private void chkCrNameDuped(ArrayList<Center> crList) {
999997 HashMap<String,String> crNameMap = new HashMap<String, String>();
@@ -1013,7 +1011,7 @@ public class PlugIn_TVPEDCB extends TVProgramUtils implements TVProgram,Cloneabl
10131011 }
10141012 }
10151013 }
1016-
1014+
10171015 //
10181016 private String getCenterCode(String id) {
10191017 Matcher ma = Pattern.compile("^(..)(..)").matcher(id);
--- a/TinyBannavi/src/tainavi/plugintv/PlugIn_TVPTVKingdom.java
+++ b/TinyBannavi/src/tainavi/plugintv/PlugIn_TVPTVKingdom.java
@@ -71,7 +71,7 @@ public class PlugIn_TVPTVKingdom extends TVProgramUtils implements TVProgram,Clo
7171 ******************************************************************************/
7272
7373 // 新しい入れ物の臨時格納場所
74- protected final ArrayList<ProgList> newplist = new ArrayList<ProgList>();
74+ protected ArrayList<ProgList> newplist = new ArrayList<ProgList>();
7575
7676 // 未定義のフラグの回収場所
7777 protected final HashMap<String,String> nf = new HashMap<String, String>();
@@ -97,10 +97,10 @@ public class PlugIn_TVPTVKingdom extends TVProgramUtils implements TVProgram,Clo
9797 ******************************************************************************/
9898
9999 @Override
100- public void loadProgram(String areaCode, boolean force) {
100+ public boolean loadProgram(String areaCode, boolean force) {
101101
102102 // 入れ物を空にする
103- newplist.clear();
103+ newplist = new ArrayList<ProgList>();
104104 nf.clear();
105105
106106 // 地域コードごとの参照ページ数の入れ物を用意する
@@ -210,8 +210,18 @@ public class PlugIn_TVPTVKingdom extends TVProgramUtils implements TVProgram,Clo
210210 }
211211 }
212212 if ( url != null ) {
213- _loadProgram(ac, d, dMax, url, cookie, force, i, cale.get(Calendar.MONTH)+1, cale.get(Calendar.DATE), counter++, counterMax);
213+ if (!_loadProgram(ac, d, dMax, url, cookie, force, i, cale.get(Calendar.MONTH)+1, cale.get(Calendar.DATE), counter++, counterMax)){
214+ newplist = null;
215+ return false;
216+ }
217+ }
218+
219+ if (isCancelRequested()){
220+ newplist = null;
221+ reportProgress(ERRID+"中止要求があったので番組表の取得にを中止します。");
222+ return false;
214223 }
224+
215225 }
216226
217227 cale.add(Calendar.DATE, 1);
@@ -227,7 +237,11 @@ public class PlugIn_TVPTVKingdom extends TVProgramUtils implements TVProgram,Clo
227237 debugNF();
228238
229239 // 古い番組データを置き換える
240+ if (pcenter != null)
241+ pcenter.clear();
230242 pcenter = newplist;
243+ newplist = null;
244+ return true;
231245 }
232246
233247 /* ここまで */
@@ -239,7 +253,7 @@ public class PlugIn_TVPTVKingdom extends TVProgramUtils implements TVProgram,Clo
239253 */
240254
241255 //
242- private void _loadProgram(String ac, int page, int pmax, String url, String cookie, boolean force, int wdaycol, int month, int day, int counter, int counterMax) {
256+ private boolean _loadProgram(String ac, int page, int pmax, String url, String cookie, boolean force, int wdaycol, int month, int day, int counter, int counterMax) {
243257 // progfilesの読み出し
244258 //
245259 final String progCacheFile = String.format(getProgDir()+File.separator+"TVK_%s_%s_%04d.html", ac, page, day);
@@ -258,17 +272,21 @@ public class PlugIn_TVPTVKingdom extends TVProgramUtils implements TVProgram,Clo
258272 }
259273 else {
260274 reportProgress(String.format("%s (キャッシュ)がみつかりません: (%d/%d) %s - %d日[%d/%d] %s",getTVProgramId(),counter,counterMax,getArea(ac),day,page,pmax,progCacheFile));
261- return;
275+ return false;
262276 }
263277
264278 // キャッシュファイルの読み込み
265279 String response = CommonUtils.read4file(progCacheFile, true);
280+ if ( response == null ) {
281+ reportProgress(ERRID+"番組表の取得に失敗しました: "+url);
282+ return false;
283+ }
266284
267285 // キャッシュが不整合を起こしていたら投げ捨てる
268286 Matcher ma = Pattern.compile(String.format("<title>%d月 %d日",month,day)).matcher(response);
269287 if ( ! ma.find() ) {
270288 reportProgress(String.format("%s (キャッシュ)が無効です: (%d/%d) %s - %d日[%d/%d] %s",getTVProgramId(),counter,counterMax,getArea(ac),day,page,pmax,progCacheFile));
271- return;
289+ return false;
272290 }
273291
274292 // 番組リストの追加
@@ -278,7 +296,11 @@ public class PlugIn_TVPTVKingdom extends TVProgramUtils implements TVProgram,Clo
278296 // 例外
279297 System.out.println("Exception: _loadProgram()");
280298 e.printStackTrace();
299+ reportProgress(ERRID+"番組表の取得に失敗しました: "+url);
300+ return false;
281301 }
302+
303+ return true;
282304 }
283305
284306 //
--- a/TinyBannavi/src/tainavi/plugintv/PlugIn_TVPtheTelevision.java
+++ b/TinyBannavi/src/tainavi/plugintv/PlugIn_TVPtheTelevision.java
@@ -18,12 +18,6 @@ import tainavi.ProgDetailList;
1818 import tainavi.ProgList;
1919 import tainavi.TVProgram;
2020 import tainavi.TVProgramUtils;
21-import tainavi.TVProgram.ProgFlags;
22-import tainavi.TVProgram.ProgGenre;
23-import tainavi.TVProgram.ProgOption;
24-import tainavi.TVProgram.ProgScrumble;
25-import tainavi.TVProgram.ProgSubtype;
26-import tainavi.TVProgram.ProgType;
2721
2822
2923 public class PlugIn_TVPtheTelevision extends TVProgramUtils implements TVProgram,Cloneable {
@@ -31,33 +25,33 @@ public class PlugIn_TVPtheTelevision extends TVProgramUtils implements TVProgram
3125 public PlugIn_TVPtheTelevision clone() {
3226 return (PlugIn_TVPtheTelevision) super.clone();
3327 }
34-
28+
3529 private static final String thisEncoding = "UTF-8";
36-
37-
30+
31+
3832 /*******************************************************************************
3933 * 種族の特性
4034 ******************************************************************************/
41-
35+
4236 @Override
4337 public String getTVProgramId() { return "webザテレビジョン"; }
44-
38+
4539 @Override
4640 public ProgType getType() { return ProgType.PROG; }
4741 @Override
4842 public ProgSubtype getSubtype() { return ProgSubtype.TERRA; }
4943
50-
44+
5145 /*******************************************************************************
5246 * 個体の特性
5347 ******************************************************************************/
5448
5549 @Override
5650 public int getTimeBarStart() {return 5;}
57-
51+
5852 //private int getDogDays() { return 7; }
59-
60-
53+
54+
6155 /*******************************************************************************
6256 * 定数
6357 ******************************************************************************/
@@ -65,58 +59,59 @@ public class PlugIn_TVPtheTelevision extends TVProgramUtils implements TVProgram
6559 private final String MSGID = "["+getTVProgramId()+"] ";
6660 private final String ERRID = "[ERROR]"+MSGID;
6761 private final String DBGID = "[DEBUG]"+MSGID;
68-
69-
62+
63+
7064 /*******************************************************************************
7165 * 部品
7266 ******************************************************************************/
73-
67+
7468 // 新しい入れ物の臨時格納場所
7569 protected ArrayList<ProgList> newplist = new ArrayList<ProgList>();
76-
70+
7771 // 未定義のフラグの回収場所
7872 private final HashMap<String,String> nf = new HashMap<String, String>();
79-
80-
73+
74+
8175 /*******************************************************************************
8276 * コンストラクタ
8377 ******************************************************************************/
84-
85-
78+
79+
8680 /*******************************************************************************
8781 * 番組情報を取得する
8882 ******************************************************************************/
89-
90- public void loadProgram(String areaCode, boolean force) {
91-
83+
84+ public boolean loadProgram(String areaCode, boolean force) {
85+
9286 // 入れ物を空にする
9387 newplist.clear();
94- nf.clear();
95-
88+ nf.clear();
89+
9690 //
9791 int counterMax = getSortedCRlist().size();
9892 int counter=1;
9993 for ( Center c : getSortedCRlist() ) {
10094 _loadProgram(c, force, counter++, counterMax);
10195 }
102-
96+
10397 // 古い番組データを置き換える
10498 pcenter = newplist;
99+ return true;
105100 }
106-
101+
107102 /* ここまで */
108103
109-
110-
104+
105+
111106 /*
112107 * 非公開メソッド
113108 */
114-
109+
115110 protected void _loadProgram(Center cr, boolean force, int counter, int counterMax) {
116111 //
117112 try {
118113 // progfilesの読み出し
119-
114+
120115 // 局リストの追加
121116 ProgList pl = new ProgList();
122117 pl.Center = cr.getCenter();
@@ -147,15 +142,15 @@ public class PlugIn_TVPtheTelevision extends TVProgramUtils implements TVProgram
147142 else {
148143 url = "http://www.television.co.jp/digitalguide/guide24.php?area_pref_key="+pl.Area+"&range=24&type="+pl.Type+"&channel="+pl.CenterId;
149144 }
150-
145+
151146 // Web番組表の読み出し
152147 response = webToBuffer(url, thisEncoding, true);
153-
148+
154149 // キャッシュファイルの保存
155150 if ( ! CommonUtils.write2file(progCacheFile, response) ) {
156151 reportProgress(ERRID+"番組表(キャッシュ)の保存に失敗しました: ("+counter+"/"+counterMax+") "+pl.Center+" "+progCacheFile);
157152 }
158-
153+
159154 reportProgress(MSGID+"(オンライン)を取得しました: ("+counter+"/"+counterMax+") "+pl.Center+" "+url);
160155 }
161156 else if (f.exists()) {
@@ -173,10 +168,10 @@ public class PlugIn_TVPtheTelevision extends TVProgramUtils implements TVProgram
173168
174169 // 日付リストの追加
175170 getDateList(pl, response);
176-
171+
177172 // 番組リストの追加
178173 getPrograms(pl, response);
179-
174+
180175 // 日付の調整
181176 setAccurateDate(pl.pdate);
182177 }
@@ -185,7 +180,7 @@ public class PlugIn_TVPtheTelevision extends TVProgramUtils implements TVProgram
185180 e.printStackTrace();
186181 }
187182 }
188-
183+
189184 //
190185 private void getDateList(ProgList pl, String response) {
191186 // 日付の処理
@@ -195,24 +190,24 @@ public class PlugIn_TVPtheTelevision extends TVProgramUtils implements TVProgram
195190 while ( mb.find() ) {
196191 ProgDateList cl = new ProgDateList();
197192 cl.row = 0;
198-
193+
199194 int month = Integer.valueOf(mb.group(1));
200195 int day = Integer.valueOf(mb.group(2));
201196 int wday = CommonUtils.getWday(mb.group(3));
202197 cl.Date = CommonUtils.getDateByMD(month, day, wday, true);
203-
198+
204199 pl.pdate.add(cl);
205200 }
206-
201+
207202 // 8日目は取得できない
208203 }
209204 }
210-
205+
211206 //
212207 private void getPrograms(ProgList pl, String src) {
213208
214209 ArrayList<ProgDateList> pdate = pl.pdate;
215-
210+
216211 HashMap<String,ProgOption> marks = new HashMap<String,ProgOption>();
217212 marks.put("/function-50.", ProgOption.FIRST);
218213 marks.put("/function-201.", ProgOption.BILINGUAL);
@@ -222,15 +217,15 @@ public class PlugIn_TVPtheTelevision extends TVProgramUtils implements TVProgram
222217 marks.put("/function-601.", ProgOption.DATA);
223218 marks.put("/function-711.", ProgOption.PV);
224219 marks.put("/function-nama.", ProgOption.LIVE);
225-
220+
226221 Matcher ma = Pattern.compile("<td class=\"program (category-(\\d*?)|overhead)\" rowspan=\"(\\d+?)\">(.+?)</td>").matcher(src);
227222 while ( ma.find() ) {
228223
229224 ProgDetailList pdl = new ProgDetailList();
230-
225+
231226 // 番組長
232227 pdl.length = Integer.valueOf(ma.group(3));
233-
228+
234229 // 挿入位置決定
235230 int col = -1;
236231 int rowMin = 9999;
@@ -244,10 +239,10 @@ public class PlugIn_TVPtheTelevision extends TVProgramUtils implements TVProgram
244239 System.err.println(ERRID+"番組情報の挿入先がみつかりません");
245240 return;
246241 }
247-
242+
248243 pdate.get(col).pdetail.add(pdl);
249244 pdate.get(col).row += pdl.length;
250-
245+
251246 // 詳細設定
252247 if ( ma.group(2) == null ) {
253248 pdl.title = pdl.splitted_title = "番組情報がありません";
@@ -291,7 +286,7 @@ public class PlugIn_TVPtheTelevision extends TVProgramUtils implements TVProgram
291286 pdl.genre = ProgGenre.WELFARE;
292287 }
293288 else if (ma.group(2).equals("14")) {
294- // 拡張エリア - 広帯域CS デジタル放送拡張用情報  映画 - 邦画
289+ // 拡張エリア - 広帯域CS デジタル放送拡張用情報  映画 - 邦画
295290 pdl.genre = ProgGenre.MOVIE;
296291 }
297292 else if (ma.group(2).equals("15")) {
@@ -303,13 +298,13 @@ public class PlugIn_TVPtheTelevision extends TVProgramUtils implements TVProgram
303298 }
304299 pdl.genre = ProgGenre.NOGENRE;
305300 }
306-
301+
307302 // 番組タイトル+α
308303 // 1 : dummy
309304 // 2 : id-a
310305 // 3 : id-b
311306 // 4 : title
312-
307+
313308 // マークを取り出してみる
314309 Matcher mb = Pattern.compile("(/function-.+?\\.)").matcher(ma.group(4));
315310 while ( mb.find() ) {
@@ -320,14 +315,14 @@ public class PlugIn_TVPtheTelevision extends TVProgramUtils implements TVProgram
320315 }
321316 }
322317 }
323-
318+
324319 // 番組詳細
325320 {
326321 mb = Pattern.compile("<div class=\"subtitle\">(.*?)</div>").matcher(ma.group(4));
327322 if ( mb.find() ) {
328323 pdl.detail = mb.group(1);
329324 }
330-
325+
331326 mb = Pattern.compile("<div name=\"programcontent\" class=\"content\">((【.+?】)*)(.*?)</div>").matcher(ma.group(4));
332327 if ( mb.find() ) {
333328 // 番組詳細の「先頭」に新番組マークなどがある場合がある。ない場合もある。
@@ -350,7 +345,7 @@ public class PlugIn_TVPtheTelevision extends TVProgramUtils implements TVProgram
350345 // マーク以降
351346 pdl.detail += mb.group(3);
352347 }
353-
348+
354349 // 記号を文字化する
355350 pdl.detail = Pattern.compile("(<img .+? alt=\"(.+?)\"/>)",Pattern.DOTALL).matcher(pdl.detail).replaceAll("$2").trim();
356351 }
@@ -363,7 +358,7 @@ public class PlugIn_TVPtheTelevision extends TVProgramUtils implements TVProgram
363358 while ( mc.find() ) {
364359 pdl.title = pdl.title.replace(mc.group(1),mc.group(3));
365360 }
366-
361+
367362 if (mb.group(2) != null) {
368363 pdl.link = "http://www.television.co.jp/digitalguide/detail.php?id="+mb.group(2);
369364 }
@@ -380,30 +375,30 @@ public class PlugIn_TVPtheTelevision extends TVProgramUtils implements TVProgram
380375
381376 // サブタイトル分離
382377 doSplitSubtitle(pdl);
383-
378+
384379 if ( ma.group(4).indexOf("\"再放送\"") >= 0 ) {
385380 pdl.addOption(ProgOption.REPEAT);
386381 }
387-
382+
388383 if ( ma.group(4).indexOf("\"生放送\"") >= 0 ) {
389384 pdl.addOption(ProgOption.LIVE);
390385 }
391-
386+
392387 if ( ma.group(4).indexOf("\"無料放送\"") >= 0 ) {
393388 pdl.noscrumble = ProgScrumble.NOSCRUMBLE;
394389 }
395-
390+
396391 if ( ma.group(4).indexOf("function-a.") >= 0 ) {
397392 pdl.flag = ProgFlags.NEW;
398393 }
399394 else if ( ma.group(4).indexOf("function-l.") >= 0 ) {
400395 pdl.flag = ProgFlags.LAST;
401396 }
402-
397+
403398 if ( ma.group(4).indexOf("function-50.") >= 0 ) {
404399 pdl.addOption(ProgOption.FIRST);
405400 }
406-
401+
407402 // 番組ID
408403 try {
409404 int hdr = 0;
@@ -424,22 +419,22 @@ public class PlugIn_TVPtheTelevision extends TVProgramUtils implements TVProgram
424419 catch (NumberFormatException e) {
425420 System.err.println("[ERROR] invalid chcode format "+pl.Center+" "+pl.CenterId+" "+e.toString());
426421 }
427-
422+
428423 // 開始・終了時刻
429424 mb = Pattern.compile("<b>(\\d+):(\\d+)</b>").matcher(ma.group(4));
430425 if ( mb.find() ) {
431426 GregorianCalendar c = new GregorianCalendar(Locale.JAPAN);
432-
427+
433428 int ahh = Integer.valueOf(mb.group(1));
434429 int amm = Integer.valueOf(mb.group(2));
435430 pdl.start = String.format("%02d:%02d", ahh, amm);
436-
431+
437432 c.set(Calendar.HOUR_OF_DAY, ahh);
438433 c.set(Calendar.MINUTE, amm);
439434 c.add(Calendar.MINUTE,pdl.length);
440435 pdl.end = String.format("%02d:%02d", c.get(Calendar.HOUR_OF_DAY), c.get(Calendar.MINUTE));
441436 }
442-
437+
443438 //
444439 pdl.extension = false;
445440 //pdl.flag = ProgFlags.NOFLAG;
@@ -447,28 +442,28 @@ public class PlugIn_TVPtheTelevision extends TVProgramUtils implements TVProgram
447442 }
448443 }
449444 }
450-
451-
445+
446+
452447 /*******************************************************************************
453448 * 地域情報を取得する
454449 ******************************************************************************/
455-
450+
456451 // 普通は東京
457452 @Override
458453 public String getDefaultArea() {return "東京";}
459-
454+
460455 //
461456 public void loadAreaCode() {
462-
457+
463458 // 設定ファイルが存在していればファイルから
464459 File f = new File(getAreaSelectedFile());
465460 if (f.exists() == true) {
466461 @SuppressWarnings("unchecked")
467462 ArrayList<AreaCode> tmp = (ArrayList<AreaCode>) CommonUtils.readXML(getAreaSelectedFile());
468463 if ( tmp != null ) {
469-
464+
470465 aclist = tmp;
471-
466+
472467 // 後方互換
473468 {
474469 boolean bsflg = false;
@@ -483,11 +478,11 @@ public class PlugIn_TVPtheTelevision extends TVProgramUtils implements TVProgram
483478 ac.setArea("BS");
484479 ac.setCode(bsCode);
485480 aclist.add(ac);
486-
481+
487482 saveAreaCode();
488483 }
489484 }
490-
485+
491486 System.out.println("地域リストを読み込みました: "+getAreaSelectedFile());
492487 return;
493488 }
@@ -498,7 +493,7 @@ public class PlugIn_TVPtheTelevision extends TVProgramUtils implements TVProgram
498493
499494 // 地域一覧の作成
500495 ArrayList<AreaCode> newaclist = new ArrayList<AreaCode>();
501-
496+
502497 // 存在していなければWeb上から
503498 String uri = "http://www.television.co.jp/digitalguide/map.html";
504499 String response = webToBuffer(uri,thisEncoding,true);
@@ -506,7 +501,7 @@ public class PlugIn_TVPtheTelevision extends TVProgramUtils implements TVProgram
506501 System.out.println("地域情報の取得に失敗しました: "+uri);
507502 return;
508503 }
509-
504+
510505 {
511506 // 北海道
512507 Matcher ma = Pattern.compile("<option value=\"([^\"]+?)\">(.+?)</option>").matcher(response);
@@ -516,7 +511,7 @@ public class PlugIn_TVPtheTelevision extends TVProgramUtils implements TVProgram
516511 ac.setCode(ma.group(1));
517512 newaclist.add(ac);
518513 }
519-
514+
520515 // 北海道以外
521516 ma = Pattern.compile("\"javascript:setPref\\('(.+?)'\\)\">(.+?)</a>").matcher(response);
522517 while (ma.find()) {
@@ -526,12 +521,12 @@ public class PlugIn_TVPtheTelevision extends TVProgramUtils implements TVProgram
526521 newaclist.add(ac);
527522 }
528523 }
529-
524+
530525 if ( newaclist.size() == 0 ) {
531526 System.err.println(ERRID+"地域一覧の取得結果が0件だったため情報を更新しません");
532527 return;
533528 }
534-
529+
535530 {
536531 {
537532 AreaCode ac = new AreaCode();
@@ -546,11 +541,11 @@ public class PlugIn_TVPtheTelevision extends TVProgramUtils implements TVProgram
546541 newaclist.add(ac);
547542 }
548543 }
549-
544+
550545 aclist = newaclist;
551546 saveAreaCode();
552547 }
553-
548+
554549
555550 /*******************************************************************************
556551 * 放送局情報を取得する
@@ -558,28 +553,28 @@ public class PlugIn_TVPtheTelevision extends TVProgramUtils implements TVProgram
558553
559554 // 設定ファイルがなければWebから取得
560555 public void loadCenter(String code, boolean force) {
561-
556+
562557 if ( code == null ) {
563558 System.out.println(ERRID+"地域コードがnullです.");
564559 return;
565560 }
566-
561+
567562 String centerListFile = getCenterListFile(getTVProgramId(), code);
568-
563+
569564 if (force) {
570565 File f = new File(centerListFile);
571566 f.delete();
572567 }
573-
568+
574569 File f = new File(centerListFile);
575570 if (f.exists() == true) {
576571 @SuppressWarnings("unchecked")
577572 ArrayList<Center> tmp = (ArrayList<Center>) CommonUtils.readXML(centerListFile);
578573 if ( tmp != null ) {
579-
574+
580575 crlist = tmp;
581576 attachChFilters(); // 放送局名変換
582-
577+
583578 // 後方互換
584579 for (Center c : crlist) {
585580 if ( c.getType().equals(bsCode) && ! c.getAreaCode().equals(bsCode)) {
@@ -594,13 +589,13 @@ public class PlugIn_TVPtheTelevision extends TVProgramUtils implements TVProgram
594589 System.err.println("放送局リストの読み込みに失敗しました: "+centerListFile);
595590 }
596591 }
597-
592+
598593 // Web上から放送局の一覧を取得する
599594 ArrayList<Center> newcrlist = new ArrayList<Center>();
600-
595+
601596 int cntMax = ((code.equals(allCode))?(aclist.size()-2):(1)) + 1;
602597 int cnt = 1;
603-
598+
604599 // 地上波
605600 if (code.equals(allCode)) {
606601 for (AreaCode ac : aclist) {
@@ -620,7 +615,7 @@ public class PlugIn_TVPtheTelevision extends TVProgramUtils implements TVProgram
620615 }
621616 cnt++;
622617 }
623-
618+
624619 // BS
625620 {
626621 String url = "http://www.television.co.jp/digitalguide/guide.php?type=bs";
@@ -629,34 +624,34 @@ public class PlugIn_TVPtheTelevision extends TVProgramUtils implements TVProgram
629624 }
630625 cnt++;
631626 }
632-
627+
633628 if ( newcrlist.size() == 0 ) {
634629 System.err.println(ERRID+"放送局情報の取得結果が0件だったため情報を更新しません");
635630 return;
636631 }
637-
632+
638633 crlist = newcrlist;
639634 attachChFilters(); // 放送局名変換
640635 saveCenter(); // 保存
641636 }
642-
637+
643638 protected boolean _loadCenter(ArrayList<Center> newcrlist, String code, String type, String uri) {
644-
639+
645640 String response = webToBuffer(uri,thisEncoding,true);
646641 if ( response == null ) {
647642 System.err.println("放送局情報の取得に失敗しました: "+uri);
648643 return false;
649644 }
650-
645+
651646 // 局名リストに追加する
652-
647+
653648 Matcher ma = Pattern.compile("<td><select(.+?)</select>").matcher(response);
654649 if (ma.find()) {
655650 Matcher mb = Pattern.compile("<option value=\"([^\"]+?)\">\\s*(&nbsp;)*(.+?)\\s*</option>").matcher(ma.group(1));
656651 while (mb.find()) {
657652 String centerName = CommonUtils.unEscape(mb.group(3));
658653 String centerId = mb.group(1);
659-
654+
660655 // NHK総合・NHK教育
661656 if ( type.equals("tv") ) {
662657 Matcher mc = Pattern.compile("^NHK(総合|Eテレ)(\\d+)・?(.+)$").matcher(centerName);
@@ -679,7 +674,7 @@ public class PlugIn_TVPtheTelevision extends TVProgramUtils implements TVProgram
679674 }
680675 }
681676 }
682-
677+
683678 Center cr = new Center();
684679 cr.setAreaCode(code);
685680 cr.setCenterOrig(centerName);
@@ -689,8 +684,8 @@ public class PlugIn_TVPtheTelevision extends TVProgramUtils implements TVProgram
689684 newcrlist.add(cr);
690685 }
691686 }
692-
687+
693688 return true;
694689 }
695-
690+
696691 }
--- a/TinyBannavi/src/tainavi/plugintv/Syobocal.java
+++ b/TinyBannavi/src/tainavi/plugintv/Syobocal.java
@@ -1,7 +1,5 @@
11 package tainavi.plugintv;
22
3-import tainavi.*;
4-
53 import java.io.File;
64 import java.util.ArrayList;
75 import java.util.Calendar;
@@ -9,37 +7,47 @@ import java.util.GregorianCalendar;
97 import java.util.regex.Matcher;
108 import java.util.regex.Pattern;
119
10+import tainavi.Center;
11+import tainavi.CommonUtils;
12+import tainavi.ContentIdSyobo;
13+import tainavi.ProgDateList;
14+import tainavi.ProgDetailList;
15+import tainavi.ProgList;
16+import tainavi.TVProgram;
17+import tainavi.TVProgramUtils;
18+import tainavi.TraceProgram;
19+
1220 /**
1321 * しょぼかるから番組表と放送局リストを取得する。プラグインではないよ。
1422 */
1523 public class Syobocal extends TVProgramUtils implements TVProgram,Cloneable {
1624
1725 private final String thisEncoding = "UTF-8";
18-
26+
1927 public void setDebug(boolean b) { debug = b; }
20-
28+
2129 private boolean debug = false;
22-
30+
2331 private boolean rss2 = false;
2432
2533 /* 必須コード - ここから */
26-
34+
2735 // 種族の特性
2836 private static final String tvProgId = "Syobocal";
29-
37+
3038 //private final String progCacheFile = getProgDir()+File.separator+"syobocal.xml";
31- private final String centerFile = "env"+File.separator+"center."+getTVProgramId()+".xml";
32-
39+ private final String centerFile = "env"+File.separator+"center."+getTVProgramId()+".xml";
40+
3341 private final String MSGID = "[しょぼかる] ";
3442 private final String ERRID = "[ERROR]"+MSGID;
3543 private final String DBGID = "[DEBUG]"+MSGID;
36-
44+
3745 @Override
3846 public String getTVProgramId() { return tvProgId; }
39-
47+
4048 @Override
4149 public boolean isAreaSelectSupported() { return false; }
42-
50+
4351 @Override
4452 public ProgType getType() { return ProgType.SYOBO; }
4553 public ProgSubtype getSubtype() { return ProgSubtype.NONE; }
@@ -50,16 +58,16 @@ public class Syobocal extends TVProgramUtils implements TVProgram,Cloneable {
5058 }
5159
5260 // 個体の特性
53-
61+
5462 //
5563 @Override
5664 public int getTimeBarStart() {return 5;}
5765
5866 private int getDogDays() { return ((getExpandTo8())?(8):(7)); }
59-
67+
6068 //
6169 @Override
62- public void loadProgram(String areaCode, boolean force) {
70+ public boolean loadProgram(String areaCode, boolean force) {
6371
6472 String progCacheFile = null;
6573 if ( rss2 ) {
@@ -68,22 +76,22 @@ public class Syobocal extends TVProgramUtils implements TVProgram,Cloneable {
6876 else {
6977 progCacheFile = getProgDir()+File.separator+"syobocal.rss";
7078 }
71-
79+
7280 // 新しい番組データの入れ物を作る
7381 ArrayList<ProgList> newplist = new ArrayList<ProgList>();
7482
7583 int cnt = 0;
76-
84+
7785 try {
7886 String response = null;
79-
87+
8088 String cirtDateTimeYMD = CommonUtils.getCritDateTime().replaceAll("[/: ]", "");
81-
89+
8290 File f = new File(progCacheFile);
8391 if (force == true ||
8492 (f.exists() == true && isCacheOld(progCacheFile) == true) ||
8593 (f.exists() == false && isCacheOld(null) == true)) {
86-
94+
8795 String url = null;
8896 if ( rss2 ) {
8997 url = "http://cal.syoboi.jp/rss2.php?start="+cirtDateTimeYMD+"&days="+getDogDays()+"&titlefmt=$(Flag)^^^$(FlagW)^^^$(Cat)^^^$(ChName)^^^$(EdTime)^^^$(Title)^^^$(SubTitleB)";
@@ -94,9 +102,9 @@ public class Syobocal extends TVProgramUtils implements TVProgram,Cloneable {
94102 response = webToBuffer(url, thisEncoding, true);
95103 if ( response == null ) {
96104 reportProgress(ERRID+"RSS2.0(オンライン)の取得に失敗しました: "+url);
97- return;
105+ return false;
98106 }
99-
107+
100108 reportProgress(MSGID+"RSS2.0(オンライン)を取得しました: "+url);
101109 CommonUtils.write2file(progCacheFile, response);
102110 }
@@ -105,42 +113,42 @@ public class Syobocal extends TVProgramUtils implements TVProgram,Cloneable {
105113 response = CommonUtils.read4file(progCacheFile, true);
106114 if ( response == null ) {
107115 reportProgress(ERRID+"RSS2.0(キャッシュ)の取得に失敗しました: "+progCacheFile);
108- return;
116+ return false;
109117 }
110118 reportProgress(MSGID+"RSS2.0(キャッシュ)を取得しました: "+progCacheFile);
111119 }
112120 else {
113121 reportProgress(ERRID+"RSS2.0(キャッシュ)がみつかりません: "+progCacheFile);
114- return;
122+ return false;
115123 }
116-
124+
117125 // 情報解析
118-
126+
119127 Matcher ma = Pattern.compile("<item(.+?)</item>",Pattern.DOTALL).matcher(response);
120128 while (ma.find()) {
121129
122130 // 入れ物
123131 ProgDetailList pDetail = new ProgDetailList();
124-
125- // <title>金曜ロードショー ヱヴァンゲリヲン新劇場版:破 TV版</title>
132+
133+ // <title>金曜ロードショー ヱヴァンゲリヲン新劇場版:破 TV版</title>
126134 Matcher mb = Pattern.compile("<title>(.+?)</title>",Pattern.DOTALL).matcher(ma.group(1));
127135 if ( ! mb.find()) {
128136 continue;
129137 }
130-
138+
131139 String[] t = mb.group(1).split("\\^\\^\\^",7);
132-
140+
133141 if (t.length < 7) {
134142 System.err.println(ERRID+"書式が不正: "+mb.group(1));
135143 }
136-
144+
137145 pDetail.title = CommonUtils.unEscape(t[5]);
138-
146+
139147 pDetail.detail = CommonUtils.unEscape(t[6]);
140148 if ( pDetail.detail.matches("^#1$|^#1[^0-9].*$") ) {
141149 // まあなにもしなくていいか
142150 }
143-
151+
144152 if (t[0] != null && t[0].length() > 0) {
145153 int flag = Integer.valueOf(t[0]);
146154 if (flag != 0) {
@@ -185,7 +193,7 @@ public class Syobocal extends TVProgramUtils implements TVProgram,Cloneable {
185193 pDetail.genrelist = new ArrayList<TVProgram.ProgGenre>();
186194 pDetail.subgenrelist = new ArrayList<TVProgram.ProgSubgenre>();
187195 boolean anime_etc = true;
188-
196+
189197 if (t[2] != null && t[2].length() > 0) {
190198 // ジャンル
191199 if (t[2].equals("1") || t[2].equals("10") || t[2].equals("5")) {
@@ -226,7 +234,7 @@ public class Syobocal extends TVProgramUtils implements TVProgram,Cloneable {
226234 else {
227235 System.out.println(DBGID+"未対応のジャンル: "+t[2]);
228236 }
229-
237+
230238 // 最後に
231239 if (pDetail.genre == null) {
232240 pDetail.genre = ProgGenre.ANIME;
@@ -237,13 +245,13 @@ public class Syobocal extends TVProgramUtils implements TVProgram,Cloneable {
237245 pDetail.subgenrelist.add(ProgSubgenre.ANIME_ETC);
238246 }
239247 }
240-
248+
241249 // <dc:publisher>日本テレビ</dc:publisher>
242250 if ( t[3] == null || t[3].length() == 0) {
243251 System.err.println(ERRID+"放送局名がない: "+mb.group(1));
244252 continue;
245253 }
246-
254+
247255 // ベアな放送局名と、ChannelConvert.datを適用した結果の放送局名
248256 String location = CommonUtils.unEscape(t[3]);
249257 String modifiedloc = getChName(location);
@@ -264,32 +272,32 @@ public class Syobocal extends TVProgramUtils implements TVProgram,Cloneable {
264272 System.err.println(ERRID+"開始日時が不正: "+mb.group(1));
265273 continue;
266274 }
267-
275+
268276 pDetail.startDateTime = CommonUtils.getDateTime(ca);
269277 pDetail.start = pDetail.startDateTime.substring(11, 16);
270278 pDetail.accurateDate = CommonUtils.getDate(ca);
271-
279+
272280 if ( t[4] == null || t[4].length() == 0) {
273281 System.err.println(ERRID+"終了時刻がない: "+mb.group(1));
274282 continue;
275283 }
276-
284+
277285 GregorianCalendar cz = CommonUtils.getCalendar(CommonUtils.getDate(ca)+" "+t[4]);
278286 if (ca.compareTo(cz) > 0) {
279287 cz.add(Calendar.DAY_OF_MONTH, 1);
280288 }
281-
289+
282290 pDetail.endDateTime = CommonUtils.getDateTime(cz);
283291 pDetail.end = pDetail.endDateTime.substring(11, 16);
284-
292+
285293 // 24:00~28:59までは前日なんだニャー
286294 if (CommonUtils.isLateNight(ca.get(Calendar.HOUR_OF_DAY))) {
287295 ca.add(Calendar.DAY_OF_MONTH, -1);
288296 }
289-
297+
290298 // 番組情報を入れるべき日付
291299 String progdate = CommonUtils.getDate(ca);
292-
300+
293301 // <description>HD放送</description>
294302 mb = Pattern.compile("<description>(.+?)</description>").matcher(ma.group(1));
295303 if (mb.find()) {
@@ -310,8 +318,8 @@ public class Syobocal extends TVProgramUtils implements TVProgram,Cloneable {
310318 pDetail.addOption(ProgOption.MULTIVOICE);
311319 }
312320 }
313-
314- // <link>http://cal.syoboi.jp/tid/44#198593</link>
321+
322+ // <link>http://cal.syoboi.jp/tid/44#198593</link>
315323 mb = Pattern.compile("<link>(.+?)</link>",Pattern.DOTALL).matcher(ma.group(1));
316324 if (mb.find()) {
317325 pDetail.link = mb.group(1);
@@ -319,10 +327,10 @@ public class Syobocal extends TVProgramUtils implements TVProgram,Cloneable {
319327 System.out.println(DBGID+"TIDとPIDが取得できない: "+pDetail.link);
320328 }
321329 }
322-
330+
323331 // 追加詳細
324332 pDetail.setGenreStr();
325-
333+
326334 // 統合
327335 {
328336 // 放送局が存在するか
@@ -339,10 +347,10 @@ public class Syobocal extends TVProgramUtils implements TVProgram,Cloneable {
339347 prog.Center = modifiedloc;
340348 prog.enabled = true;
341349 prog.pdate = new ArrayList<ProgDateList>();
342-
350+
343351 newplist.add(prog);
344352 }
345-
353+
346354 // 日付が存在するか
347355 ProgDateList pCenter = null;
348356 for (ProgDateList pcl : prog.pdate) {
@@ -357,17 +365,17 @@ public class Syobocal extends TVProgramUtils implements TVProgram,Cloneable {
357365 pCenter.pdetail = new ArrayList<ProgDetailList>();
358366 prog.pdate.add(pCenter);
359367 }
360-
368+
361369 // 連結
362370 pCenter.pdetail.add(pDetail);
363-
371+
364372 cnt++;
365373 }
366-
374+
367375 //
368376 pDetail.splitted_title = pDetail.title;
369377 pDetail.splitted_detail = pDetail.detail;
370-
378+
371379 // 詳細を登録する
372380 pDetail.titlePop = TraceProgram.replacePop(pDetail.title);
373381 pDetail.splitted_titlePop = pDetail.titlePop;
@@ -377,11 +385,12 @@ public class Syobocal extends TVProgramUtils implements TVProgram,Cloneable {
377385 }
378386 catch (Exception e) {
379387 e.printStackTrace();
380- return;
388+ return false;
381389 }
382-
390+
383391 pcenter = newplist;
384392 System.out.println(DBGID+"番組の数: "+cnt);
393+ return true;
385394 }
386395
387396 /* ここまで */
@@ -399,7 +408,7 @@ public class Syobocal extends TVProgramUtils implements TVProgram,Cloneable {
399408 @Override
400409 public void saveAreaCode() {
401410 }
402-
411+
403412 @Override
404413 public String getCode(String area) {
405414 return "1";
@@ -419,7 +428,7 @@ public class Syobocal extends TVProgramUtils implements TVProgram,Cloneable {
419428 public String getSelectedCode() {
420429 return "1";
421430 }
422-
431+
423432 /*
424433 * ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
425434 * ★★★★★ 放送地域を取得する(TVAreaから降格)-ここまで ★★★★★
@@ -434,12 +443,12 @@ public class Syobocal extends TVProgramUtils implements TVProgram,Cloneable {
434443
435444 @Override
436445 public void loadCenter(String code, boolean force) {
437-
446+
438447 if ( code == null ) {
439448 System.out.println(ERRID+"地域コードがnullです.");
440449 return;
441450 }
442-
451+
443452 if ( ! force && new File(centerFile).exists() ) {
444453 // NOT FORFCEならキャッシュからどうぞ
445454 @SuppressWarnings("unchecked")
@@ -449,7 +458,7 @@ public class Syobocal extends TVProgramUtils implements TVProgram,Cloneable {
449458 return;
450459 }
451460 }
452-
461+
453462 String uri = "http://cal.syoboi.jp/mng?Action=ShowChList";
454463 String response = webToBuffer(uri,thisEncoding,true);
455464 if ( response == null ) {
@@ -457,16 +466,16 @@ public class Syobocal extends TVProgramUtils implements TVProgram,Cloneable {
457466 return;
458467 }
459468 System.out.println(MSGID+"放送局リストを取得: "+uri);
460-
469+
461470 Matcher ma = Pattern.compile("<table class=\"tframe output\".*?>(.+?)</table>",Pattern.DOTALL).matcher(response);
462471 if ( ! ma.find() ) {
463472 System.err.println(ERRID+"放送局情報がない: "+uri);
464473 return;
465474 }
466-
475+
467476 // 新しい放送局リストの入れ物を作る
468477 ArrayList<Center> newcrlist = new ArrayList<Center>();
469-
478+
470479 int cnt = 1;
471480 Matcher mb = Pattern.compile("<tr>(.+?)</tr>",Pattern.DOTALL).matcher(ma.group(1));
472481 while ( mb.find() ) {
@@ -478,7 +487,7 @@ public class Syobocal extends TVProgramUtils implements TVProgram,Cloneable {
478487 if ( ! d[1].matches("^\\d+$") ) {
479488 continue;
480489 }
481-
490+
482491 // 放送局リスト
483492 Center cr = new Center();
484493 cr.setLink(d[5]);
@@ -488,30 +497,30 @@ public class Syobocal extends TVProgramUtils implements TVProgram,Cloneable {
488497 cr.setType("");
489498 cr.setEnabled(true);
490499 cr.setOrder(cnt++);
491-
500+
492501 newcrlist.add(cr);
493-
502+
494503 if (debug) System.out.println(MSGID+"放送局を追加: "+cr.getCenterOrig()+" -> "+cr.getCenter());
495504 }
496-
505+
497506 if ( newcrlist.size() == 0 ) {
498507 System.err.println(ERRID+"放送局情報の取得結果が0件だったため情報を更新しません");
499508 return;
500509 }
501510
502511 System.out.println(DBGID+"放送局の数: "+newcrlist.size());
503-
512+
504513 crlist = newcrlist;
505514 attachChFilters();
506515 setSortedCRlist();
507516 CommonUtils.writeXML(centerFile, crlist);
508517 }
509-
518+
510519 @Override
511520 public boolean saveCenter() {
512521 return false;
513522 }
514-
523+
515524 /*
516525 * ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
517526 * ★★★★★ 放送局を選択する(TVCenterから降格)-ここまで ★★★★★