public void run() {
            long sTime = System.currentTimeMillis();
            if ( 1 == funcType ) {
                FoxDBHelper.all2Ebook(transType, bookid, oDB);
            }
            if ( 2 == funcType ) {
                FoxDBHelper.all2Ebook(transType, pageids, oDB);
            }
            final long eTime = System.currentTimeMillis() - sTime;
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    msg.setForeground(Color.BLUE);
                    msg("★　转换完毕，耗时(ms): " + eTime);
                }
            });
        }
    }
    private void mBook2TxtActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mBook2TxtActionPerformed
        int nRow = uBook.getSelectedRow();
        String nBookID = uBook.getValueAt(nRow, 2).toString();

        tPage.setRowCount(0);
        msg("★　开始转换本书为 txt");
        new Thread(new book2ebook(9, Integer.valueOf(nBookID))).start();
    }//GEN-LAST:event_mBook2TxtActionPerformed

    private void mPages2txtActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mPages2txtActionPerformed
        int[] nRow = uPage.getSelectedRows(); // 选中的所有行号

        StringBuilder ids = new StringBuilder(10240);
        int nMax = nRow.length - 1;
        for (int n = 0; n < nMax; n++) {  // 删除数据库，并更新dellist
            ids.append(uPage.getValueAt(nRow[n], 2)).append(", ");
        }
        ids.append(uPage.getValueAt(nRow[nMax], 2));
        //       System.out.println(ids.toString());

        tPage.setRowCount(0);
        msg("★　开始转换选定章节为 txt");
        new Thread(new book2ebook(9, ids.toString())).start();
    }//GEN-LAST:event_mPages2txtActionPerformed

    private void mBook2MobiActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mBook2MobiActionPerformed
        int nRow = uBook.getSelectedRow();
        String nBookID = uBook.getValueAt(nRow, 2).toString();

        tPage.setRowCount(0);
        msg("★　开始转换本书为 mobi");
        new Thread(new book2ebook(1, Integer.valueOf(nBookID))).start();
    }//GEN-LAST:event_mBook2MobiActionPerformed

    private void mPages2MobiActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mPages2MobiActionPerformed
        int[] nRow = uPage.getSelectedRows(); // 选中的所有行号

        StringBuilder ids = new StringBuilder(10240);
        int nMax = nRow.length - 1;
        for (int n = 0; n < nMax; n++) {  // 删除数据库，并更新dellist
            ids.append(uPage.getValueAt(nRow[n], 2)).append(", ");
        }
        ids.append(uPage.getValueAt(nRow[nMax], 2));
        //       System.out.println(ids.toString());

        tPage.setRowCount(0);
        msg("★　开始转换选定章节为 mobi");
        new Thread(new book2ebook(1, ids.toString())).start();
    }//GEN-LAST:event_mPages2MobiActionPerformed

    private void mBook2EpubActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mBook2EpubActionPerformed
        int nRow = uBook.getSelectedRow();
        String nBookID = uBook.getValueAt(nRow, 2).toString();

        tPage.setRowCount(0);
        msg("★　开始转换本书为 epub");
        new Thread(new book2ebook(2, Integer.valueOf(nBookID))).start();
    }//GEN-LAST:event_mBook2EpubActionPerformed

    private void mPages2EpubActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mPages2EpubActionPerformed
        int[] nRow = uPage.getSelectedRows(); // 选中的所有行号

        StringBuilder ids = new StringBuilder(10240);
        int nMax = nRow.length - 1;
        for (int n = 0; n < nMax; n++) {  // 删除数据库，并更新dellist
            ids.append(uPage.getValueAt(nRow[n], 2)).append(", ");
        }
        ids.append(uPage.getValueAt(nRow[nMax], 2));
        tPage.setRowCount(0);
        msg("★　开始转换选定章节为 epub");
        new Thread(new book2ebook(2, ids.toString())).start();
    }//GEN-LAST:event_mPages2EpubActionPerformed
    
    private void fAll2Mobi() { // 转换为mobi
        tPage.setRowCount(0);
        msg.setForeground(Color.red);
        msg("★　开始转换所有章节为 mobi");
        new Thread(new book2ebook(1, 0)).start();
    }
    
    private void mAll2MobiActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mAll2MobiActionPerformed
        fAll2Mobi(); // 转换为mobi
    }//GEN-LAST:event_mAll2MobiActionPerformed

    private void mAll2EpubActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mAll2EpubActionPerformed
        tPage.setRowCount(0);
        msg("★　开始转换所有章节为 epub");
        new Thread(new book2ebook(2, 0)).start();
    }//GEN-LAST:event_mAll2EpubActionPerformed

    private void mAll2TxtActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mAll2TxtActionPerformed
        tPage.setRowCount(0);
        msg("★　开始转换所有章节为 txt");
        new Thread(new book2ebook(9, 0)).start();
    }//GEN-LAST:event_mAll2TxtActionPerformed

    private void fQuickDBDesc() { // 快捷: 顺序排序并压缩
         long sTime = System.currentTimeMillis();
        msg("★　开始倒序所有书籍...");
        FoxDBHelper.regenID(2, oDB);
        refreshBookList();
        tPage.setRowCount(0);
        msg("★　开始重新生成pageID");
        FoxDBHelper.regenID(9, oDB);
        msg("★　开始精简所有DelList");
        FoxDBHelper.simplifyAllDelList(oDB);
        msg("★　开始缩小数据库...");
        double subSize = oDB.vacuumDB();
        long eTime = System.currentTimeMillis() - sTime;
        msg("★　已完成倒序并缩小数据库: " + subSize + " K   耗时(ms): " + eTime);       
    }
    private void mDBQuickDActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mDBQuickDActionPerformed
        fQuickDBDesc() ; // 快捷: 顺序排序并压缩
    }//GEN-LAST:event_mDBQuickDActionPerformed

    private void mDBSimpAllDelListActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mDBSimpAllDelListActionPerformed
        msg("★　开始精简所有DelList");
        long sTime = System.currentTimeMillis();
        FoxDBHelper.simplifyAllDelList(oDB);
        long eTime = System.currentTimeMillis() - sTime;
        msg("★　已精简所有DelList   耗时(ms): " + eTime);
    }//GEN-LAST:event_mDBSimpAllDelListActionPerformed
    
    private void fQuickDBAsc() { // 快捷: 顺序排序并压缩
         long sTime = System.currentTimeMillis();
        msg("★　开始顺序所有书籍...");
        FoxDBHelper.regenID(1, oDB);
        refreshBookList();
        tPage.setRowCount(0);
        msg("★　开始重新生成pageID");
        FoxDBHelper.regenID(9, oDB);
        msg("★　开始精简所有DelList");
        FoxDBHelper.simplifyAllDelList(oDB);
        msg("★　开始缩小数据库...");
        double subSize = oDB.vacuumDB();
        long eTime = System.currentTimeMillis() - sTime;
        msg("★　已完成顺序并缩小数据库: " + subSize + " K   耗时(ms): " + eTime);       
    }
    private void mDBQuickAActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mDBQuickAActionPerformed
        fQuickDBAsc() ; // 快捷: 顺序排序并压缩
    }//GEN-LAST:event_mDBQuickAActionPerformed

    private void mBookShowLessLenActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mBookShowLessLenActionPerformed
        tPage.setRowCount(0);
        List rsdata = oDB.getList("select page.name as name, page.CharCount as cc, page.ID as id, book.name as bname, page.url as url from book,Page where book.id=page.bookid and (length(Content) < 1000 or Content is null) order by page.bookid,page.ID");
        Iterator itr = rsdata.iterator();
        while (itr.hasNext()) {
            HashMap item = (HashMap) itr.next();
            tPage.addRow(new Object[]{item.get("name"), item.get("cc"), item.get("id"), item.get("bname"), item.get("url")});
        }
        msg("★　字数少于1K的章节总数: " + rsdata.size());
    }//GEN-LAST:event_mBookShowLessLenActionPerformed

    private void mBookShowSizeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mBookShowSizeActionPerformed
        tPage.setRowCount(0);
        List rsdata = oDB.getList("select sum(length(p.content)) * 3 / 1024 as ss, p.bookid as bid, b.name as bname from page as p, book as b where b.id=p.bookid group by p.bookid order by ss, p.bookid");
        Iterator itr = rsdata.iterator();
        int allSize = 0;
        int nowSize = 0;
        while (itr.hasNext()) {
            HashMap item = (HashMap) itr.next();
            nowSize = Integer.valueOf(item.get("ss").toString());
            allSize += nowSize ;
            tPage.addRow(new Object[]{item.get("bname"), nowSize + " k", 0, item.get("bid"), 0});
        }
        msg("★　共占用空间(K): " + allSize);
    }//GEN-LAST:event_mBookShowSizeActionPerformed

    private void mBookImportFromQidianTxtActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mBookImportFromQidianTxtActionPerformed
        int returnVal = chooseTxt.showOpenDialog(this);
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            String txtPath = chooseTxt.getSelectedFile().getAbsolutePath();
            msg("★　开始导入起点Txt文件: " + txtPath);
            FoxDBHelper.importQidianTxt(txtPath, oDB);
            msg("★　导入起点Txt文件完毕: " + txtPath);
            refreshBookList();
        }
    }//GEN-LAST:event_mBookImportFromQidianTxtActionPerformed

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed
        fShowAllPages();  // 显示所有章节
    }//GEN-LAST:event_jButton1ActionPerformed

    private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton2ActionPerformed
        fAll2Mobi(); // 转换为mobi
    }//GEN-LAST:event_jButton2ActionPerformed

    private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton3ActionPerformed
        msg.setForeground(Color.red);
        new Thread(new UpdateAllBook()).start();  // 更新所有
    }//GEN-LAST:event_jButton3ActionPerformed

    private void jButton4ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton4ActionPerformed
        fQuickDBAsc() ; // 快捷: 顺序排序并压缩
    }//GEN-LAST:event_jButton4ActionPerformed

    private void jButton5ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton5ActionPerformed
        fQuickDBDesc() ; // 快捷: 顺序排序并压缩
    }//GEN-LAST:event_jButton5ActionPerformed

    private void jButton6ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton6ActionPerformed
        fSwitchDB() ; // 切换数据库
    }//GEN-LAST:event_jButton6ActionPerformed

    private void uBookSearchActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_uBookSearchActionPerformed
        uSearchString.insertItemAt(uBookName.getText(), 0); // 设置要搜索的书名
        uSearchString.setSelectedIndex(0);
        jdSearchBook.setVisible(true);
    }//GEN-LAST:event_uBookSearchActionPerformed

    private void uQidianIDProcActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_uQidianIDProcActionPerformed
        int qidianid = site_qidian.qidian_getBookID_FromURL(uQidianID.getText());
        uQidianID.setText(String.valueOf(qidianid));
    }//GEN-LAST:event_uQidianIDProcActionPerformed

    private void jButton7ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton7ActionPerformed
        uDelList.setText(FoxBookLib.simplifyDelList(uDelList.getText()));
    }//GEN-LAST:event_jButton7ActionPerformed

    private void jButton8ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton8ActionPerformed
        uDelList.setText("");
    }//GEN-LAST:event_jButton8ActionPerformed

    // 退出保存到数据库
    private void FoxDialogEditBookInfoSaveInfo() {
        String bookid = uBookID.getText();
        if ( bookid.equalsIgnoreCase("0") ) { // 添加书籍
            oDB.execPreOne("insert into book (DelURL, Name, QidianID, URL) values(?, \"" + uBookName.getText() + "\", \"" + uQidianID.getText() + "\", \"" + uBookURL.getText() + "\")", uDelList.getText());
        } else {
            oDB.execPreOne("update book set DelURL=?, name=\"" + uBookName.getText() + "\", qidianid=\"" + uQidianID.getText() + "\", url=\"" + uBookURL.getText() + "\" where id=" + bookid, uDelList.getText());
        }
        jdEditBookInfo.dispose();
        refreshBookList();
    }
    
    private void jButton9ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton9ActionPerformed
        FoxDialogEditBookInfoSaveInfo(); // 退出保存到数据库
    }//GEN-LAST:event_jButton9ActionPerformed

    private void uSearchItActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_uSearchItActionPerformed
        String siteType = uSearchType.getSelectedItem().toString();
        String SearchString = uSearchString.getSelectedItem().toString();

        String html = "";
        String seURL = "";
        if (siteType.contains("E:")) { // 搜索引擎
            try {
                if (siteType.equalsIgnoreCase("E:SoGou")) {
                    seURL = "http://www.sogou.com/web?query=" + URLEncoder.encode(SearchString, "GB2312") + "&num=50";
                }
                if (siteType.equalsIgnoreCase("E:Yahoo")) {
                    seURL = "http://search.yahoo.com/search?n=40&p=" + URLEncoder.encode(SearchString, "UTF-8");
                }
                if (siteType.equalsIgnoreCase("E:Bing")) {
                    seURL = "http://cn.bing.com/search?q=" + URLEncoder.encode(SearchString, "UTF-8");
                }
                if (siteType.equalsIgnoreCase("E:soso")) {
                    seURL = "http://www.soso.com/q?w=" + URLEncoder.encode(SearchString, "GB2312");
                }
                if (siteType.equalsIgnoreCase("E:so")) {
                    seURL = "http://www.so.com/s?q=" + URLEncoder.encode(SearchString, "UTF-8");
                }
                if (siteType.equalsIgnoreCase("E:ZhongSou")) {
                    seURL = "http://www.zhongsou.com/third.cgi?w=" + URLEncoder.encode(SearchString, "UTF-8") + "&kid=&y=5&stag=1&dt=0&pt=0&utf=1";
                }
                if (siteType.equalsIgnoreCase("E:youdao")) {
                    seURL = "http://www.youdao.com/search?q=" + URLEncoder.encode(SearchString, "UTF-8") + "&ue=utf8&keyfrom=web.index";
                }
                if (siteType.equalsIgnoreCase("E:360")) {
                    seURL = "http://www.haosou.com/s?ie=utf-8&shb=1&src=360sou_newhome&q=" + URLEncoder.encode(SearchString, "UTF-8");
                }
                if (siteType.equalsIgnoreCase("E:GotoHell")) {
                    seURL = "http://devilfinder.com/search.php?q=" + URLEncoder.encode(SearchString, "UTF-8");
                }
                // 下载页面，分析链接
                html = FoxBookLib.downhtml(seURL);
                List<Map<String, Object>> seo = FoxBookLib.getSearchEngineHref(html, SearchString);
                // 输出到列表
                tList.setRowCount(0); // 清空列表
                Iterator<Map<String, Object>> itr = seo.iterator();
                while (itr.hasNext()) {
                    HashMap<String, Object> mm = (HashMap<String, Object>) itr.next();
                    tList.addRow(new Object[]{TYPE_SE_SITE_LIST, mm.get("url"), mm.get("name")});
                }
            } catch (Exception e) {
                e.toString();
            }
        }
        if (siteType.contains("S:")) {  // 特殊站点
            if (siteType.equalsIgnoreCase("S:起点中文手机")) {
                seURL = site_qidian.qidian_getSearchURL_Mobile(SearchString);
                String json = FoxBookLib.downhtml(seURL, "utf-8");
                List<Map<String, Object>> qds = site_qidian.json2BookList(json);
                // 输出到列表
                tList.setRowCount(0); // 清空列表
                Iterator<Map<String, Object>> itr = qds.iterator();
                while (itr.hasNext()) {
                    HashMap<String, Object> mm = (HashMap<String, Object>) itr.next();
                    tList.addRow(new Object[]{TYPE_QIDIAN_MOBILE_INDEX_LIST, mm.get("url"), mm.get("name")});
                }
            }
            if (siteType.equalsIgnoreCase("S:追书神器")) {
                seURL = site_zssq.getUrlSE(SearchString);
                String json = site_zssq.json2BookID(FoxBookLib.downhtml(seURL, "utf-8"));
                uSearchBookURL.setText("&bid=" + json);
                uBookURL.setText("&bid=" + json);
                seURL = site_zssq.getUrlSL(json);
                json = FoxBookLib.downhtml(seURL, "utf-8");
                List<Map<String, Object>> ddl = site_zssq.json2SiteList(json);
                // 输出到列表
                tList.setRowCount(0); // 清空列表
                Iterator<Map<String, Object>> itr = ddl.iterator();
                while (itr.hasNext()) {
                    HashMap<String, Object> mm = (HashMap<String, Object>) itr.next();
                    tList.addRow(new Object[]{TYPE_ZSSQ_SITE_LIST, mm.get("url"), mm.get("name")});
                }
            }
            if (siteType.equalsIgnoreCase("S:快读")) {
                seURL = site_qreader.qreader_Search(SearchString);
                uSearchBookURL.setText(seURL);
                uBookURL.setText(seURL);
                List<Map<String, Object>> kds = site_qreader.qreader_GetIndex(seURL, 22, 0);
                // 输出到列表
                tList.setRowCount(0); // 清空列表
                Iterator<Map<String, Object>> itr = kds.iterator();
                while (itr.hasNext()) {
                    HashMap<String, Object> mm = (HashMap<String, Object>) itr.next();
                    tList.addRow(new Object[]{TYPE_QREADER_PAGE_LIST, mm.get("url"), mm.get("name")});
                }
            }
            if (siteType.equalsIgnoreCase("S:宜搜")) {
                seURL = site_easou.getUrlSE(SearchString);
                String json = FoxBookLib.downhtml(seURL, "utf-8");
                seURL = site_easou.getUrlSL(site_easou.json2IDs(json, 1));
                json = FoxBookLib.downhtml(seURL, "utf-8");
                List<Map<String, Object>> ddl = site_easou.json2SiteList(json);
                // 输出到列表
                tList.setRowCount(0); // 清空列表
                Iterator<Map<String, Object>> itr = ddl.iterator();
                while (itr.hasNext()) {
                    HashMap<String, Object> mm = (HashMap<String, Object>) itr.next();
                    tList.addRow(new Object[]{TYPE_EASOU_SITE_LIST, mm.get("url"), mm.get("name")});
                }

            }

        }
    }//GEN-LAST:event_uSearchItActionPerformed

    private void uListMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_uListMouseClicked
        String RootURL = "" ;
        
        if (2 == evt.getClickCount()) {
            int nRow = uList.getSelectedRow();
            String nowResultType = uList.getValueAt(nRow, 0).toString();
            String nowURL = uList.getValueAt(nRow, 1).toString();
            //System.out.println(uList.getValueAt(nRow, 0));

            String html = "";
            if (nowResultType.equalsIgnoreCase(TYPE_SE_SITE_LIST)) { // 处理:搜索引擎返回的站点列表
                uSearchBookURL.setText(nowURL);
                uBookURL.setText(nowURL);
                RootURL = nowURL; // 作为后面子目录的根路径
                html = FoxBookLib.downhtml(nowURL);
                List<Map<String, Object>> srt = FoxBookLib.tocHref(html, 22);
                // 输出到列表
                tList.setRowCount(0); // 清空列表
                Iterator<Map<String, Object>> itr = srt.iterator();
                while (itr.hasNext()) {
                    HashMap<String, Object> mm = (HashMap<String, Object>) itr.next();
                    tList.addRow(new Object[]{TYPE_SE_PAGE_LIST, mm.get("url"), mm.get("name")});
                }
            }
            if (nowResultType.equalsIgnoreCase(TYPE_SE_PAGE_LIST)) { // 处理:章节列表
                if (RootURL.length() > 3) { // 获取完整路径
                    nowURL = FoxBookLib.getFullURL(RootURL, nowURL);
                }
                html = FoxBookLib.downhtml(nowURL);
                html = FoxBookLib.pagetext(html);
                if (html != null && html.length() > 200) {
                    JOptionPane.showMessageDialog(null, html.substring(0, 200));
                }
            }

            if (nowResultType.equalsIgnoreCase(TYPE_QIDIAN_MOBILE_INDEX_LIST)) { // 处理: 起点 站点列表
                uSearchBookURL.setText(nowURL);
                uBookURL.setText(nowURL);
                uQidianID.setText(String.valueOf(site_qidian.qidian_getBookID_FromURL(nowURL))); // 设置QiDianID
                html = FoxBookLib.downhtml(nowURL, "utf-8");
                List<Map<String, Object>> dtl = site_qidian.json2PageList(html);
                // 输出到列表
                tList.setRowCount(0); // 清空列表
                Iterator<Map<String, Object>> itr = dtl.iterator();
                while (itr.hasNext()) {
                    HashMap<String, Object> mm = (HashMap<String, Object>) itr.next();
                    tList.addRow(new Object[]{TYPE_QIDIAN_MOBILE_PAGE_LIST, mm.get("url"), mm.get("name")});
                }
            }
            if (nowResultType.equalsIgnoreCase(TYPE_QIDIAN_MOBILE_PAGE_LIST)) { // 处理: 起点 内容
                html = FoxBookLib.downhtml(nowURL, "GBK");
                html = site_qidian.qidian_getTextFromPageJS(html);
                if (html != null && html.length() > 200) {
                    JOptionPane.showMessageDialog(null, html.substring(0, 200));
                }
            }
            
            if (nowResultType.equalsIgnoreCase(TYPE_ZSSQ_SITE_LIST)) { // 处理: 追书神器 站点列表
                String oldBID = uBookURL.getText();
                if (oldBID.contains("&bid=")) {
                    uSearchBookURL.setText(nowURL + oldBID);
                    uBookURL.setText(nowURL + oldBID);
                } else {
                    uSearchBookURL.setText(nowURL);
                    uBookURL.setText(nowURL);
                }
                html = FoxBookLib.downhtml(nowURL, "utf-8");
                List<Map<String, Object>> dtl = site_zssq.json2PageList(html, 22);
                // 输出到列表
                tList.setRowCount(0); // 清空列表
                Iterator<Map<String, Object>> itr = dtl.iterator();
                while (itr.hasNext()) {
                    HashMap<String, Object> mm = (HashMap<String, Object>) itr.next();
                    tList.addRow(new Object[]{TYPE_ZSSQ_PAGE_LIST, mm.get("url"), mm.get("name")});
                }
            }
            if (nowResultType.equalsIgnoreCase(TYPE_ZSSQ_PAGE_LIST)) { // 处理: 追书神器 章节列表
                html = FoxBookLib.downhtml(nowURL, "utf-8");
                html = site_zssq.json2Text(html);
                if (html != null && html.length() > 200) {
                    JOptionPane.showMessageDialog(null, html.substring(0, 200));
                }
            }
            if (nowResultType.equalsIgnoreCase(TYPE_QREADER_PAGE_LIST)) { // 处理: 快读 章节列表
                html = site_qreader.qreader_GetContent(nowURL);
                if (html != null && html.length() > 200) {
                    JOptionPane.showMessageDialog(null, html.substring(0, 200));
                }
            }
            if (nowResultType.equalsIgnoreCase(TYPE_EASOU_SITE_LIST)) { // 处理: 宜搜 站点列表
                uSearchBookURL.setText(nowURL);
                uBookURL.setText(nowURL);
                String sGIDNID = "";
                Matcher m = Pattern.compile("(?i).*(gid=[0-9]+&nid=[0-9]+)&").matcher(nowURL);
                while (m.find()) {
                    sGIDNID = m.group(1);
                }
                html = FoxBookLib.downhtml(nowURL, "utf-8");
                List<Map<String, Object>> dtl = site_easou.json2PageList(html, sGIDNID, 22);
                // 输出到列表
                tList.setRowCount(0); // 清空列表
                Iterator<Map<String, Object>> itr = dtl.iterator();
                while (itr.hasNext()) {
                    HashMap<String, Object> mm = (HashMap<String, Object>) itr.next();
                    tList.addRow(new Object[]{TYPE_EASOU_PAGE_LIST, mm.get("url"), mm.get("name")});
                }
            }
            if (nowResultType.equalsIgnoreCase(TYPE_EASOU_PAGE_LIST)) { // 处理: 宜搜 章节列表
                html = FoxBookLib.downhtml(nowURL, "utf-8");
                html = site_easou.json2Text(html);
                if (html != null && html.length() > 200) {
                    JOptionPane.showMessageDialog(null, html.substring(0, 200));
                }
            }
        }
        if (java.awt.event.MouseEvent.BUTTON3 == evt.getButton()) {
            int nRow = uList.rowAtPoint(evt.getPoint());
            uList.setRowSelectionInterval(nRow, nRow);
            //           jPopupMenuBook.show(evt.getComponent(), evt.getX(), evt.getY());
        }
    }//GEN-LAST:event_uListMouseClicked

    private void mPageEditInfoActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mPageEditInfoActionPerformed
        int nRow = uPage.getSelectedRow();
        String nPageID = uPage.getValueAt(nRow, 2).toString();

        jlPID.setText(nPageID);
        ArrayList<HashMap<String, Object>> list = (ArrayList<HashMap<String, Object>>) oDB.getList("select bookid as bid, name as name, url as url, CharCount as cc, Content as ct from page where id=" + nPageID);
        jtfBID.setText(list.get(0).get("bid").toString());
        jtfPName.setText(list.get(0).get("name").toString());
        jtfCharCount.setText(list.get(0).get("cc").toString());
        jtfPURL.setText(list.get(0).get("url").toString());
        jtaPageContent.setText(list.get(0).get("ct").toString());
        jtaPageContent.setCaretPosition(0); // 跳到头部

        jdEditPageInfo.setVisible(true);
        jbLeanPage.requestFocusInWindow(); // 设置焦点到按钮上
    }//GEN-LAST:event_mPageEditInfoActionPerformed

    // 精简章节内容按钮
    private void jbLeanPageActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jbLeanPageActionPerformed
        String pc = jtaPageContent.getText();
        pc = pc.replace("\r", "").replace("\n\n", "\n").replace("　", "").replace("\n ", "\n");
        jtaPageContent.setText(pc);
        jtaPageContent.setCaretPosition(0); // 跳到头部
    }//GEN-LAST:event_jbLeanPageActionPerformed

    // Page保存退出按钮
    private void jbSavePageActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jbSavePageActionPerformed
        String pageid = jlPID.getText();
        oDB.execPreOne("update page set Content=?, name=\"" + jtfPName.getText() + "\", BookID=" + jtfBID.getText() + ", CharCount=" + jtfCharCount.getText()  + ", url=\"" + jtfPURL.getText() + "\" where id=" + pageid, jtaPageContent.getText());
        jdEditPageInfo.dispose();
    }//GEN-LAST:event_jbSavePageActionPerformed

    private void jButton11ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton11ActionPerformed
        // 查找
        String src = jtaReplaceSrc.getText();
        String tar = jtaReplaceTar.getText();
        
        tPage.setRowCount(0);
        List rsdata = oDB.getList("select page.name as name, page.CharCount as cc, page.ID as id, book.name as bname, page.url as url from book,Page where book.id=page.bookid and page.content like '%" + src + "%' order by page.bookid,page.ID");
        Iterator itr = rsdata.iterator();
        while (itr.hasNext()) {
            HashMap item = (HashMap) itr.next();
            tPage.addRow(new Object[]{item.get("name"), item.get("cc"), item.get("id"), item.get("bname"), item.get("url")});
        }
        msg("★　搜索到的章节数: " + rsdata.size());
    }//GEN-LAST:event_jButton11ActionPerformed

    private void jButton12ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton12ActionPerformed
        // 替换
        String src = jtaReplaceSrc.getText();
        String tar = jtaReplaceTar.getText();
        
        tPage.setRowCount(0);
        List rsdata = oDB.getList("select page.name as name, page.CharCount as cc, page.ID as id, book.name as bname, page.url as url, page.content as pc from book,Page where book.id=page.bookid and page.content like '%" + src + "%' order by page.bookid,page.ID");
        Iterator itr = rsdata.iterator();
        while (itr.hasNext()) {
            HashMap item = (HashMap) itr.next();
            oDB.execPreOne("update page set content=? where id=" + item.get("id").toString(), item.get("pc").toString().replace(src, tar)); // 替换内容
            tPage.addRow(new Object[]{item.get("name"), item.get("cc"), item.get("id"), item.get("bname"), item.get("url")});
        }
        msg("★　替换的章节数: " + rsdata.size());
        jdFindnReplace.dispose();
    }//GEN-LAST:event_jButton12ActionPerformed

    private void mPageFindnReplaceActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mPageFindnReplaceActionPerformed
        jdFindnReplace.setVisible(true);
    }//GEN-LAST:event_mPageFindnReplaceActionPerformed

    private void jButton10ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton10ActionPerformed
        jtaReplaceSrc.setText("");
        jtaReplaceTar.setText("");
    }//GEN-LAST:event_jButton10ActionPerformed

    private void formComponentResized(java.awt.event.ComponentEvent evt) {//GEN-FIRST:event_formComponentResized
        
        jSplitPane1.setDividerLocation((int)(( evt.getComponent().getWidth() - 75 ) * Float.parseFloat(config.getProperty("UI.DiverderLocPer", "0.31")))); // 自动调整分割栏    
    }//GEN-LAST:event_formComponentResized

    private void uPageContentMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_uPageContentMouseClicked
        // 以纵向30%为分割线，上面的区域向上翻页，下面的区域向下翻页，翻页高度=一屏-字体大小
        JScrollBar ss = jScrollPane2.getVerticalScrollBar();
        int scrollHeight = jScrollPane2.getHeight() - uPageContent.getFont().getSize();
//      System.out.println(ss.getBlockIncrement(JScrollBar.VERTICAL) + "==" + uPageContent.getVisibleRect().height + "==" + jScrollPane2.getHeight() + "  Font:" + uPageContent.getFont().getSize());
        if (jScrollPane2.getMousePosition().getY() > jScrollPane2.getHeight() * 0.3) { // 下一屏
//          System.out.println(ss.getValue() + "+" + scrollHeight + "=" + (ss.getValue() + scrollHeight));
            ss.setValue(ss.getValue() + scrollHeight);
//          uPageContent.setFont(new java.awt.Font("微软雅黑", 0, uPageContent.getFont().getSize() + 1));
        } else { // 上一屏
//          System.out.println(ss.getValue() + "-" + scrollHeight + "=" + (ss.getValue() - scrollHeight));
            ss.setValue(ss.getValue() - scrollHeight);
        }
        // 以上的输出真的是个奇葩问题，在win10平板上 鼠标点击和手指点击的计算结果不同
    }//GEN-LAST:event_uPageContentMouseClicked

    private void uPageContentMouseDragged(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_uPageContentMouseDragged
        // 页面拖动效果
        jScrollPane2.getVerticalScrollBar().setValue(jScrollPane2.getVerticalScrollBar().getValue() - evt.getY() + DragStartY);
    }//GEN-LAST:event_uPageContentMouseDragged

    private void uPageContentMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_uPageContentMousePressed
        // 页面拖动起点
        DragStartY = evt.getY();
    }//GEN-LAST:event_uPageContentMousePressed

    private void jButton13ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton13ActionPerformed
        deleteSelectedPages(true); // 删除选定章节
    }//GEN-LAST:event_jButton13ActionPerformed

    private void mPageSelectAllActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mPageSelectAllActionPerformed
        uPage.selectAll();
    }//GEN-LAST:event_mPageSelectAllActionPerformed

    private void mPageSelectUpActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mPageSelectUpActionPerformed
        uPage.setRowSelectionInterval(0, uPage.getSelectedRow());
    }//GEN-LAST:event_mPageSelectUpActionPerformed

    private void mPageSelectDownActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mPageSelectDownActionPerformed
        uPage.setRowSelectionInterval(uPage.getSelectedRow(), uPage.getRowCount()-1);
    }//GEN-LAST:event_mPageSelectDownActionPerformed

    private void jButton14ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton14ActionPerformed
        uPage.setRowSelectionInterval(0, uPage.getSelectedRow());
    }//GEN-LAST:event_jButton14ActionPerformed

    private void jButton15ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton15ActionPerformed
        uPage.selectAll();
    }//GEN-LAST:event_jButton15ActionPerformed

    private void jButton16ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton16ActionPerformed
        uPage.setRowSelectionInterval(uPage.getSelectedRow(), uPage.getRowCount()-1);
    }//GEN-LAST:event_jButton16ActionPerformed

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        // 程序最先走这里，然后GUI开始
        if (args.length > 0) { // 参数数大于0时，为命令行模式
            FoxMainCMD.main(args);
            return;
        }

    /* Set the Nimbus look and feel */
        /*
         private static Set<String> NIMBUS_PRIMARY_COLORS = new HashSet<String>(Arrays.asList(
         "text", "control", "nimbusBase", "nimbusOrange", "nimbusGreen", "nimbusRed", "nimbusInfoBlue",
         "nimbusAlertYellow", "nimbusFocus", "nimbusSelectedText", "nimbusSelectionBackground",
         "nimbusDisabledText", "nimbusLightBackground", "info"));
         private static Set<String> NIMBUS_SECONDARY_COLORS = new HashSet<String>(Arrays.asList(
         "textForeground", "textBackground", "background",
         "nimbusBlueGrey", "nimbusBorder", "nimbusSelection", "infoText", "menuText", "menu", "scrollbar",
         "controlText", "controlHighlight", "controlLHighlight", "controlShadow", "controlDkShadow", "textHighlight",
         "textHighlightText", "textInactiveText", "desktop", "activeCaption", "inactiveCaption"));
         private static String[] NIMBUS_COMPONENTS = new String[]{
         "ArrowButton", "Button", "ToggleButton", "RadioButton", "CheckBox", "ColorChooser", "ComboBox",
         "\"ComboBox.scrollPane\"", "FileChooser", "InternalFrameTitlePane", "InternalFrame", "DesktopIcon",
         "DesktopPane", "Label", "List", "MenuBar", "MenuItem", "RadioButtonMenuItem", "CheckBoxMenuItem", "Menu",
         "PopupMenu", "PopupMenuSeparator", "OptionPane", "Panel", "ProgressBar", "Separator", "ScrollBar",
         "ScrollPane", "Viewport", "Slider", "Spinner", "SplitPane", "TabbedPane", "Table", "TableHeader",
         "\"Table.editor\"", "\"Tree.cellEditor\"", "TextField", "FormattedTextField", "PasswordField", "TextArea",
         "TextPane", "EditorPane", "ToolBar", "ToolBarSeparator", "ToolTip", "Tree", "RootPane"};
         */
        javax.swing.UIManager.put("control", new Color(228, 242, 228));               // 控件背景色
        javax.swing.UIManager.put("nimbusLightBackground", new Color(228, 242, 228)); // 文本背景色
        javax.swing.UIManager.put("nimbusSelectionBackground", new Color( 129, 193, 115 ));          // 选定文本 129, 193, 115    55, 165, 55    64, 128, 128 

        javax.swing.UIManager.put("nimbusBlueGrey", new Color(179, 219, 179));        //控件色
        javax.swing.UIManager.put("nimbusBase", new Color(70, 140, 60));              //滚动条，基础颜色

        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {  //Metal, Nimbus,CDE/Motif,Windows,Windows Classic
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (Exception ex) {
            ex.toString();
        }

  
/*
         // 显示所有值
        UIManager.LookAndFeelInfo looks[] = UIManager.getInstalledLookAndFeels();

        for (UIManager.LookAndFeelInfo info : looks) {
            try {
                if ("Nimbus".equals(info.getName())) {
                    UIManager.setLookAndFeel(info.getClassName());

                    UIDefaults defaults = UIManager.getDefaults();
                    Enumeration newKeys = defaults.keys();

                    while (newKeys.hasMoreElements()) {
                        Object obj = newKeys.nextElement();
                        System.out.printf("%50s : %s\n", obj, UIManager.get(obj));
                    }
                }
            } catch (Exception ex) {
                ex.toString();
            }
        }
*/
        
        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new FoxMainFrame().setVisible(true);
            }
        }