回精華區
作者TKyo.bbs@cpu.tfcis.org (暗黑貴公子) 看板: plan
標題[功能]新台鐵火車時刻表查詢
時間動力核心 (2006/06/16 Fri 10:01:06) Updated: 2006/06/16
前言

  1.捨棄以往介面, 以 pans() 介面完全取代
  2.pans() 介面以新板台鐵火車時刻表查詢介面為思考模式
  3.產生兩種查詢結果 (簡易速度較快, 完整速度較慢)

------------------------------------------------------------------------------
:src/lib/f_simg.c

/* 原理同 f_img.c, 唯一不同處為 size + 1 (安全搜尋字串用) */

#include <fcntl.h>
#include <sys/stat.h>


char *
f_simg(fpath, fsize)
  char *fpath;
  int *fsize;
{
  int fd, size, len;
  char *fw;
  struct stat st;

  if ((fd = open(fpath, O_RDONLY)) < 0)
    return NULL;

  fpath = NULL;

  if (!fstat(fd, &st) && S_ISREG(st.st_mode) && (size = st.st_size) > 0
    && (fpath = (char *) malloc(size + 1)))
  {
    *fsize = size + 1;
    fw = fpath;

    while (len = read(fd, fw, size))
      fw += len;

    *fw = '\0';

    if (fw - fpath != size)
    {
      free(fpath);
      fpath = NULL;
    }
  }

  close(fd);
  return fpath;
}

:src/include/global.h

/* 適當位置插入 (給網路工具用訊息) */

+ #ifdef HAVE_NETTOOL
+ #define MSG_NET_WAIT    "連接伺服器中,請稍候..."
+ #define MSG_NET_OK      "已連接"
+ #define MSG_NET_SEARCH  "查詢資料中,請稍候..."
+ #define MSG_NET_LOST    "無法連接上伺服器,查詢失敗"
+ #define MSG_NET_ERROR   "資料查詢發生錯誤!"
+ #define MSG_NET_ASK     "您要將查詢結果寄回信箱嗎?[N] "
+ #endif

:src/maple/windows.c:pans()

/* 新增 Page Up / Page Down 支援 */
/* 啟用 : 選單結構 Hotkey 再新增一字元即可 */
/* 傳回值為 'U' / 'D' */

- int cur, old_cur, max, ch;
+ int cur, old_cur, max, ch, page;

 ...

  hotkey = desc[0][0];
+ page = desc[0][2];

 ...

    case KEY_END:
      cur = max;
      break;

+   case KEY_PGUP:
+     if (page)
+     {
+       vs_restore(slt);
+       return 'U';
+     }

+     break;

+   case KEY_PGDN:
+     if (page)
+     {
+       vs_restore(slt);
+       return 'D';
+     }

+     break;

:src/maple/menu.c

/* 自訂選單位置插入 */

  "bin/twrailway.so:twrailway_main", 0, - M_XMODE,
  "Railway Query 台鐵火車時刻表查詢",

新增 :/src/so/twrailway.c

/*-------------------------------------------------------*/
/* twrailway.c  ( NTHU CS MapleBBS Ver 3.10 )            */
/*-------------------------------------------------------*/
/* target : 台鐵火車時刻表查詢                           */
/* create : 06/05/26                                     */
/* update :   /  /                                       */
/* author : kyo@cszone.twbbs.org                         */
/*-------------------------------------------------------*/


#include "bbs.h"

#ifdef HAVE_NETTOOL

#define LYNX_PATH _
  "/usr/local/bin/lynx -useragent=L_y_n_x --source" /* lynx 的絕對路徑 */

#define AUTOB5_PATH _
  "/usr/local/bin/autob5"                           /* autoconvert 絕對路徑 */

#define STATION_PAGE    10
#define CGI_RailWay "\"SBeginStation=%s&SBeginStationName=&SEndStation=%s" _
                    "&SEndStationName=&SClass=%c&SDateTime=%s&STime=0000|2359"
                    "&SearchType=0&SBeginCityCode=&SEndCityCode="
                    "&BStationIndex=&EStationIndex=\""

static char *station_name[] = {
  "基隆", "八堵", "七堵", "五堵", "汐止",
  "南港", "松山", "台北", "萬華", "板橋",
  "樹林", "山佳", "鶯歌", "桃園", "內壢",
  "中壢", "埔心", "楊梅", "富岡", "湖口",
  "新豐", "竹北", "新竹", "香山", "崎頂",
  "竹南", "三坑", "談文", "大山", "後龍",
  "龍港", "白沙屯", "新埔", "通霄", "苑裡",
  "日南", "大甲", "台中港", "清水", "沙鹿",
  "龍井", "大肚", "追分", "彰化", "花壇",
  "員林", "永靖", "社頭", "田中", "二水",
  "林內", "石榴", "斗六", "斗南", "石龜",
  "大林", "民雄", "嘉義", "水上", "南靖",
  "後壁", "新營", "柳營", "林鳳營", "隆田",
  "拔林", "善化", "新市", "永康", "台南",
  "保安", "中洲", "大湖", "路竹", "岡山",
  "橋頭", "楠梓", "左營", "高雄", "大橋",
  "大村", "嘉北", "造橋", "豐富", "苗栗",
  "南勢", "銅鑼", "三義", "泰安", "后里",
  "豐原", "潭子", "台中", "烏日", "成功\",
  "大慶", "太原", "鳳山", "後庄", "九曲堂",
  "六塊厝", "屏東", "歸來", "麟洛", "西勢",
  "竹田", "潮州", "崁頂", "南州", "鎮安",
  "林邊", "佳冬", "東海", "枋寮", "加祿",
  "內獅", "枋山", "古莊", "大武", "瀧溪",
  "多良", "金崙", "太麻里", "知本", "康樂",
  "吉安", "志學", "平和", "壽豐", "豐田",
  "溪口", "南平", "鳳林", "萬榮", "光復",
  "大富", "富源", "瑞穗", "三民", "玉里",
  "安通", "東里", "東竹", "富里", "池上",
  "海端", "關山", "月美", "瑞和", "瑞源",
  "鹿野", "山里", "台東", "永樂", "東澳",
  "南澳", "武塔", "漢本", "和平", "和仁",
  "崇德", "新城", "景美", "北埔", "花蓮",
  "暖暖", "四腳亭", "瑞芳", "侯硐", "三貂嶺",
  "牡丹", "雙溪", "貢寮", "福隆", "石城",
  "大里", "大溪", "龜山", "外澳", "頭城",
  "頂埔", "礁溪", "四城", "宜蘭", "二結",
  "中里", "羅東", "冬山", "新馬", "蘇澳新",
  "蘇澳", "大華", "十分", "望古", "嶺腳",
  "平溪", "菁桐", "竹中", "上員", "竹東",
  "橫山", "九讚頭", "合興", "富貴", "內灣",
  "榮華", "源泉", "濁水", "龍泉", "集集",
  "水里", "車埕", "其他地區", "台北地區", "桃園地區",
  "新竹地區", "苗栗地區", "台中地區", "彰化地區", "南投地區",
  "雲林地區", "嘉義地區", "台南地區", "高雄地區", "屏東地區",
  "台東地區", "花蓮地區", "宜蘭地區", "平溪線", "內灣線",
  "集集線"};

static char *station_num[] = {
  "1001", "1002", "1003", "1004", "1005",
  "1006", "1007", "1008", "1009", "1011",
  "1012", "1013", "1014", "1015", "1016",
  "1017", "1018", "1019", "1020", "1021",
  "1022", "1023", "1025", "1026", "1027",
  "1028", "1029", "1102", "1104", "1105",
  "1106", "1107", "1108", "1109", "1110",
  "1111", "1112", "1113", "1114", "1115",
  "1116", "1117", "1118", "1120", "1202",
  "1203", "1204", "1205", "1206", "1207",
  "1208", "1209", "1210", "1211", "1212",
  "1213", "1214", "1215", "1217", "1218",
  "1219", "1220", "1221", "1222", "1223",
  "1224", "1225", "1226", "1227", "1228",
  "1229", "1230", "1231", "1232", "1233",
  "1234", "1235", "1236", "1238", "1239",
  "1240", "1241", "1302", "1304", "1305",
  "1307", "1308", "1310", "1314", "1315",
  "1317", "1318", "1319", "1320", "1321",
  "1322", "1323", "1402", "1403", "1404",
  "1405", "1406", "1407", "1408", "1409",
  "1410", "1411", "1412", "1413", "1414",
  "1415", "1416", "1417", "1418", "1502",
  "1503", "1504", "1507", "1508", "1510",
  "1511", "1512", "1514", "1516", "1517",
  "1602", "1604", "1605", "1606", "1607",
  "1608", "1609", "1610", "1611", "1612",
  "1613", "1614", "1616", "1617", "1619",
  "1620", "1621", "1622", "1623", "1624",
  "1625", "1626", "1627", "1628", "1629",
  "1630", "1631", "1632", "1703", "1704",
  "1705", "1706", "1708", "1709", "1710",
  "1711", "1712", "1713", "1714", "1715",
  "1802", "1803", "1804", "1805", "1806",
  "1807", "1808", "1809", "1810", "1811",
  "1812", "1813", "1814", "1815", "1816",
  "1817", "1818", "1819", "1820", "1821",
  "1822", "1823", "1824", "1825", "1826",
  "1827", "1903", "1904", "1905", "1906",
  "1907", "1908", "2203", "2204", "2205",
  "2206", "2207", "2208", "2209", "2210",
  "2211", "2702", "2703", "2704", "2705",
  "2706", "2707", "-1", "-2", "-3",
  "-4", "-5", "-6", "-7", "-8",
  "-9", "-10", "-11", "-12", "-13",
  "-14", "-15", "-16", "-17", "-18",
  "-19"};

static int station_from = 0;
static int station_to = 0;

static int
getStation(title)
  char *title;
{
  int menu_main[17] = {16, 7, 9, 13, 15, 22, 92, 43, 52, 57, 69, 78, 101, 183,
                       164, 152, 212};
  int menu_region[19] = {18, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222,
                         223, 224, 225, 226, 227, 228, 229, 230};

  int menu_region1[24] = {23, 173, 172, 171, 170, 169, 168, 167, 166, 165, 0,
                          26, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
  int menu_region2[7] = {6, 13, 14, 15, 16, 17, 18};
  int menu_region3[6] = {5, 19, 20, 21, 22, 23};
  int menu_region4[17] = {16, 24, 25, 27, 28, 29, 30, 31, 32, 33, 34, 82, 83,
                          84, 85, 86, 87};
  int menu_region5[18] = {17, 35, 36, 37, 38, 39, 40, 41, 42, 94, 88, 89, 90,
                          91, 98, 92, 95, 93};
  int menu_region6[9] = {8, 43, 44, 80, 45, 46, 47, 48, 49};
  int menu_region7[8] = {7, 206, 207, 208, 209, 210, 211, 49};
  int menu_region8[6] = {5, 50, 51, 52, 53, 54};
  int menu_region9[7] = {6, 55, 56, 81, 57, 58, 59};
  int menu_region10[14] = {13, 60, 61, 62, 63, 64, 65, 66, 67, 68, 79, 69, 70,
                           71};
  int menu_region11[11] = {10, 72, 73, 74, 75 ,76, 77, 78, 97, 98, 99};
  int menu_region12[18] = {17, 100, 101, 102, 103, 104, 105, 106, 107, 108,
                           109, 110, 111, 112, 113, 114, 115, 116};
  int menu_region13[18] = {17, 117, 118, 119, 120, 121, 122, 123, 124, 152,
                           151, 150, 149, 148, 147, 146, 145, 144};
  int menu_region14[27] = {26, 143, 142, 141, 140, 139, 138, 137, 136, 135,
                           134, 133, 132, 131, 130, 129, 128, 127, 126, 125,
                           164, 163, 162, 161, 160, 159, 158};
  int menu_region15[23] = {22, 157, 156, 155, 154, 153, 190, 189, 188, 187,
                           186, 185, 184, 183, 182, 181, 180, 179, 178, 177,
                           176, 175, 174};
  int menu_region16[8] = {7, 169, 196, 195, 194, 193, 192, 191};
  int menu_region17[11] = {10, 22, 197, 198, 205, 199, 200, 201, 202, 203,
                           204};
  int menu_region18[8] = {7, 206, 207, 208, 209, 210, 211, 49};

  int *event[] = {menu_main, menu_region,
                  menu_region1, menu_region2, menu_region3, menu_region4,
                  menu_region5, menu_region6, menu_region7, menu_region8,
                  menu_region9, menu_region10, menu_region11, menu_region12,
                  menu_region13, menu_region14, menu_region15, menu_region16,
                  menu_region17, menu_region18};

  int event_num, i, j, top, page;
  char buf[100];
  char menu_sub[10][25] = {0};
  char *menu_station[13];
  char menu_main_command[4] = {0}, menu_region_command[4] = {0};
  char buf_command[4] = {0};

  event_num = top = 0;
  strcpy(menu_main_command, "0Q");
  strcpy(menu_region_command, "0R");
  strcpy(buf_command, "0R");

  for(;;)
  {
    if (event_num == 0)
      menu_station[0] = menu_main_command;
    else if (event_num == 1)
      menu_station[0] = menu_region_command;
    else
      menu_station[0] = buf_command;

    page = (event[event_num][0] - 1) / STATION_PAGE;

    if (page)
      menu_station[0][2] =  '1';
    else
    {
      menu_station[0][2] =  '\0';
      strcpy(buf, title);
    }

    for (i = top; i < BMIN(top + STATION_PAGE, event[event_num][0]); i++)
    {
      j = i % STATION_PAGE;
      sprintf(menu_sub[j], "%d  %-s", j,
        station_name[event[event_num][i + 1]]);
      menu_station[j + 1] = menu_sub[j];
    }

    if ((j = i % STATION_PAGE) == 0)
      j = STATION_PAGE;

    menu_station[++j] = "Q  取消";
    menu_station[++j] = NULL;

    if (page)
      sprintf(buf, "%s  [" MENU_COLOR "PgUp" HEAD_ON "/" MENU_COLOR "PgDn"
        HEAD_ON "] 上下頁 ║" FCOLOR "%c" HEAD_ON "║",
        title, (top / STATION_PAGE) + '1');

    i = pans(-1, -1, buf, menu_station);

    if (i >= '0' && i <= '9')
      menu_station[0][0] = (char) i;


    if (i == 'D')
    {
      top += STATION_PAGE;

      if (top > (event[event_num][0] - 1))
        top = 0;

      menu_station[0][0] = '0';
      continue;
    }
    else if (i == 'U')
    {
      top -= STATION_PAGE;

      if (top < 0)
        top = page * STATION_PAGE;

      menu_station[0][0] = '0';
      continue;
    }
    else if (i == 'r')
    {
      if (event_num >= 2)
      {
        top = ((event_num - 2) / STATION_PAGE) * STATION_PAGE;
        event_num = 1;
      }
      else
      {
        event_num = 0;
        top = STATION_PAGE;
      }

      continue;
    }
    else if (i == 'q')
    {
      event_num = -1;
      break;
    }
    else
    {
      i = event[event_num][(top + (i - '0') + 1)];

      if ((event_num = atoi(station_num[i])) < 0)
      {
        event_num = -event_num;
        top = 0;

        continue;
      }
      event_num = i;

      break;
    }
  }

  return event_num;
}

static void
str_alltrim(buf, str, end)
  char *buf;
  char *str;
  char *end;
{
  int i;
  char ch;

  i = 0;
  buf[i] = '\0';

  while (str <= end)
  {
    ch = *str;

    if (!(ch == ' ' || ch == 0x0a || ch == 0x09 || ch == 0x0d))
      buf[i++] = ch;

    str++;
  }

  buf[i] = '\0';
}

static int
html_parser(src, dst, title, qtype)
  char *src, *dst, *title, qtype;
{
  FILE *fpw;
  int fsize, i, max;
  char buf[80];
  char *fimage, *start, *str1, *str2, *str3;
  char *search[9] = {"EStationIndex=\" >", "EStationIndex=\" >",
      "<div align=\"center\">", "<div align=\"center\">",
      "</FONT>", "</FONT>", "</FONT>", "</FONT>",
       "<span class=\"content_font\">"};

  char *search_end[9] = {"</A>", "</A>", "</div>", "</div>",
                      "</div>", "</div>", "</div>", "</div>", "</font>"};

  char *out_fmt[9] = {"│ %4s ", "│%4s", "│%2.2s", "│  %10.10s  ",
                      "│  %5.5s ", "│  %5.5s ", "│%4s", "│%10s│\n",
                      "│ %-69.69s│\n"};

  char *tran_name[4] = {"自強", "莒光", "復興", "電車"};
  char tran_color[4] = {'1', '6', '4', '7'};

  char *other_info[5] = {"加", "餐\", "專", "跨", "天"};
  char *other_desc[5] = {"加班車", "附掛餐\車", "設殘障旅客專用座位車",
                         "跨日車", "每天行駛"};
  char *other_pic[5] = {"addtrain.gif", "food.gif", "people.gif", "mood.gif",
                        "everyday.gif"};
  char *other_search[1] = {"<font color=\"red\">"};

  if (!(fimage = f_simg(src, &fsize)))
    return 0;

  start = fimage;

  if (!(fpw = fopen(dst, "w")))
    return 0;

  fprintf(fpw, "%s\n"
    "┌───┬──┬─┬───────┬────┬────┬──┬───"
    "──┐\n"
    "│ 乘坐 │車次│經│始發站->到達站", title);

  if (strlen(station_name[station_from]) == 4)
    fprintf(fpw, "│  %4s  ", station_name[station_from]);
  else
    fprintf(fpw, "│ %6s ", station_name[station_from]);

  if (strlen(station_name[station_to]) == 4)
    fprintf(fpw, "│  %4s  ", station_name[station_to]);
  else
    fprintf(fpw, "│ %6s ", station_name[station_to]);

  fputs("│全票│ 行駛時間 │\n"
        "│ 車種 │編號│由│              │開車時間│到達時間│價錢│          │\n", fpw);

  if (qtype)
  {
    fputs("├───┼──┼─┼───────┼────┼────┼──┼──"
          "───┤\n", fpw);
    max = 9;
      i = 0;
  }
  else
    max = 8;

  while ((str1 = strstr(start, "<A class=sLINK4")))
  {

    if (qtype && i == max)
      fputs("├───┬──┬─┬───────┬────┬────┬──┬─"
            "────┤\n", fpw);

    for (i = 0; i < max; i++)
    {
      if ((str2 = strstr(str1, search[i])) &&
        (str3 = strstr(str2, search_end[i])))
      {
        str2 += strlen(search[i]);
        *str3 = '\0';
        str1 = str3 + 1;

        str_alltrim(buf, str2, str3);

        if (i == 0)
        {
          if (qtype == 0)
            fputs("├───┼──┼─┼───────┼────┼────┼─"
                  "─┼─────┤\n", fpw);

          for (fsize = 0; fsize < 4; fsize++)
          {
             if (str_ncmp(buf, tran_name[fsize], 4) == 0)
             {
               sprintf(buf, "\033[1;3%cm%s\033[m", tran_color[fsize],
                 tran_name[fsize]);
               break;
             }
          }
        }
        else if (i == (max - 1))
        {
          start = str1;

          if (qtype)
          {
            fputs("├───┴──┴─┴───────┴────┴────┴─"
                  "─┴─────┤\n", fpw);
            *buf = '\0';

            for (fsize = 0; fsize < 5; fsize++)
            {
              if (strstr(str2, other_pic[fsize]))
              {
                if (*buf)
                {
                  strcat(buf, "、");
                  strcat(buf, other_info[fsize]);
                }
                else
                  strcat(buf, other_info[fsize]);
              }
            }

            if ((str2 = strstr(str2, other_search[0])))
            {
              char info[80];

              str2 += strlen(other_search[0]);
              str_alltrim(info, str2, str3);
              if (strlen(info) > 0)
              {
                strcat(buf, ",");
                strcat(buf, info);
              }
            }
          }
        }

        fprintf(fpw, out_fmt[i], buf);
      }
      else
        break;
    }

    if (i != max)
      break;
  }

  if (qtype)
  {
    fputs("└────────────────────────────────"
          "───┘\n\n"
          "說明:\n", fpw);

    for (i = 0; i < 5; i++)
      fprintf(fpw, "      %s - %s\n", other_info[i], other_desc[i]);
  }
  else
    fputs("└───┴──┴─┴───────┴────┴────┴──┴──"
          "───┘\n", fpw);

  fclose(fpw);
  free(fimage);

  return 1;
}

static int
http_conn(query, title, qtype)
  char *query, *title, qtype;
{

  char src[64], dst[64];
  char cmd[768];

  outs(MSG_NET_WAIT);
  refresh();

  sprintf(src, "tmp/%s.rail", cuser.userid);
  sprintf(cmd, LYNX_PATH " -display_charset=utf-8 -nolist -dump "
    "http://new.twtraffic.com.tw/twrail/nonscript_search_result.aspx?"
    "%s > %s.utf8", query, src);
  system(cmd);

  sprintf(cmd, AUTOB5_PATH " -i utf8 -o big5 < %s.utf8 > %s", src, src);
  system(cmd);
  sprintf(cmd, "%s.utf8", src);
  unlink(cmd);

  outs(MSG_NET_OK "\n");
  outs(MSG_NET_SEARCH);
  refresh();

  sprintf(dst, "tmp/%s.way", cuser.userid);

  if (html_parser(src, dst, title, qtype))
  {

    if (more(dst, (char *) -1) >= 0)
    {
      if (vans(MSG_NET_ASK) == 'y')
        mail_self(dst, cuser.userid, "[備 忘 錄] 台鐵火車時刻表查詢結果",
        MAIL_READ);
    }
  }
  else
    vmsg(MSG_NET_ERROR);

  unlink(dst);
  unlink(src);

  return 0;
}

int
twrailway_main(void)
{
  int pos, ch;
  char train_type, num[3], dday[9];
  char *menu_train_type[] = {"0Q",
      "0  對號列車",
      "1  非對號列車",
      "2  所有車種",
      "Q  取消", 0};

  char *menu_dday[] = {"0Q",
      "0  今天",
      "1  明天",
      "2  後天",
      "C  自行輸入",
      "Q  取消", 0};

  char *menu_query_type[] = {"00",
      "0  簡易資訊",
      "1  完整資訊", 0};

  char atrn[512];
  char title[128];
  struct tm *ptime;
  time_t now;

  vs_bar("台鐵火車時刻表查詢");
  pos = 2;

  if ((station_from = getStation("選擇起程站")) > 0)
  {
    move(pos++, 0);
    prints("起程站:%s\n", station_name[station_from]);
    if ((station_to = getStation("選擇到達站")) > 0)
    {
      move(pos++, 0);
      prints("到達站:%s\n", station_name[station_to]);
      if ((train_type = pans(-1, -1, "選擇車種", menu_train_type)) != 'q')
      {
        move(pos++, 0);
        prints("車種:%s\n", &menu_train_type[((train_type - '0') + 1)][3]);
        ch = pans(-1, -1, "選擇時刻表查詢時段", menu_dday);
        if (ch != 'q')
        {
          if (ch == 'c')
          {
            do
            {
              if (vget(5, 0, "請輸入時刻表查詢天數(最多 45 天):", num, 3,
                    DOECHO))
                ch = atoi(num);
              else
              {
                ch = -1;
                break;
              }
            } while (ch < 0 || ch > 45);
          }
          else
          {
            ch -= '0';
            move(pos++, 0);
            prints("時刻表查詢時段:%s\n", &menu_dday[(ch + 1)][3]);
          }

          if (ch >= 0 && ch <= 45)
          {
            time(&now);
            now += 86400 * ch;
            ptime = localtime(&now);
            sprintf(dday, "%02d/%d/%d", (ptime->tm_year - 11 ) % 100 ,
              ptime->tm_mon + 1, ptime->tm_mday);
            sprintf(atrn, CGI_RailWay, station_num[station_from],
              station_num[station_to], train_type, dday);

            ch = pans(-1, -1, "選擇資料顯示模式", menu_query_type);
            move(pos++, 0);
            prints("資料顯示:%s\n", &menu_query_type[((ch - '0') + 1)][3]);

            sprintf(title, "\n  起始站:%s\n  到達站:%s\n查詢車種:%s\n"
             "查詢日期:%10.10s\n資料顯示:%s\n",
              station_name[station_from], station_name[station_to],
              &menu_train_type[((train_type - '0') + 1)][3], BAtime(&now),
              &menu_query_type[((ch - '0') + 1)][3]);
            http_conn(atrn, title, (ch - '0'));
          }
        }
      }
    }
  }

  return XREDRAW;
}

#endif  /* HAVE_NETTOOL */

--
=[:摃�◣�:Origin ]|[  Ocpu.tfcis.org  ]|[�搟說:]=
=[:摃�╱�:Author ]|[     cszone.twbbs.org     ]|[�:]=
精華選讀←離開[主題上]主題下(k)上篇(j)下篇S/a搜尋 G串列 TAB精華 ↑↓捲 Pg/Space翻