新聞閱讀工具 V1.1 (newspaper.c)
/*
新增了許多的熱鍵,如 F轉寄 ^X轉錄 ^Z 還有閱讀時將與一般閱讀文章時所預設按鍵
相符合。 也稍微把一些地方做了美化(如標題過長會出現"未完"的字樣等),此外於
takenews.c 中抓新聞時由於沒有判定要抓多長,所以有些標題過長新聞可能會導至
head 的 title 部份變二行,本來想要在 newspaper.c 中做判定的,但後來還是覺得
在 takenews.c 中做判定比較治本,至於判定方法目前還沒寫,以後有空再加了 :p
*/
/*-------------------------------------------------------*/
/* newspaper.c */
/*-------------------------------------------------------*/
/* author : kenshieh.bbs@bbs.ntit.edu.tw */
/* target : 新聞閱讀工具 */
/* create : 2002/01/19 */
/*-------------------------------------------------------*/
#include "bbs.h"
#define NEWS_PAGE 12 /* 一頁新聞筆數 */
#define mouts(y, x, s) { move(y, x); outs(s); }
static int x, y, z;
static int class_name; /* 記錄 news_class 的第幾筆 */
static int news_class[10] = {NEWS_UDN, NEWS_CTNEWS, NEWS_TWDAILY,
NEWS_REUTERS, NEWS_CNA, NEWS_FTV, NEWS_PNN, NEWS_CNYES, NEWS_ZDNET, NEWS_GREAT
};
static char *newsname[4][3] =
{
{"聯合新聞網","中時電子報","台灣 日報"},
{"路 透 社","中央 新聞","民視 新聞"},
{"勁 報","鉅 亨 網","資 傳 網"},
{"大成報影報","離 開",""}
};
static char newsname2[][10] = {"udn", "ctnews", "twdaily", "reuters", "cna",
"ftv","pnn", "cnyes", "2dnet", "great"};
static char newsclass2[][15] = {"polity", "realtime", "society",
"international","twoshore", "finance", "entertain", "sports", "leisure",
"health", "technology"};
static char *newsclass[] = {"政治","即時","社會","國際","兩岸","財經","影視",
"體育","生活","健康","科技"};
static int
news_neck()
{
clear();
mouts(0, 9, "\033[37m◢\033[44m \
\033[m");
mouts(1, 9, "\033[1;36;44m 碧海藍天新聞閱\讀工具 v1.1 資料來源:雅虎奇\
摩新聞 \033[m");
mouts(2, 9, "\033[1;36;44m http://tw.news.yahoo.com/ \
\033[m");
mouts(3, 9, "\033[1;36;44m Designed By kenshieh.bbs@bbs.ntit.edu.tw\
\033[m");
mouts(4, 0, "\033[45m \
[類別選擇] \033[m");
}
static void
news_mainmenu_title(n_y, o_y, n_x)
int n_y;
int o_y;
int n_x;
{
int i;
if (o_y != n_y)
{
for (i = 0; i < 3; i++)
{
move(8 + o_y, 6 + 36 * i);
prints("\033[0;37;00m %s \033[m", newsname[o_y][i]);
move(8 + n_y, 6 + 36 * i);
if (n_x == i)
prints("\033[1;37;43m %s \033[m", newsname[n_y][i]);
else
prints("\033[0;37;00m %s \033[m", newsname[n_y][i]);
}
}
else
{
for (i = 0; i < 3; i++)
{
move(8 + n_y, 6 + 36 * i);
if (n_x == i)
prints("\033[1;37;43m %s \033[m", newsname[n_y][i]);
else
prints("\033[0;37;00m %s \033[m", newsname[n_y][i]);
}
}
}
static int
news_mainmenu(maxy, sum)
int maxy;
int sum;
{
int cmd;
int n_x, n_y, o_x, o_y;
o_x = o_y = 0;
n_x = x;
n_y = y;
for (;;)
{
news_mainmenu_title(n_y, o_y, n_x);
o_x = n_x;
o_y = n_y;
cmd = vkey();
switch (cmd)
{
case KEY_DOWN:
if (n_y < maxy - 1)
{
n_y++;
if (newsname[n_y][n_x] == "")
n_y = 0;
}
else
n_y = 0;
break;
case KEY_UP:
if (n_y > 0)
n_y--;
else
{
n_y = maxy - 1;
while (newsname[n_y][n_x] == "")
n_y--;
}
break;
case '\n':
x = n_x;
y = n_y;
class_name = news_class[y * 3 + x];
break;
case KEY_RIGHT:
if (n_x < 2)
{
n_x++;
if (newsname[n_y][n_x] == "")
n_x = 0;
}
else
n_x = 0;
break;
case KEY_LEFT:
if (n_x > 0)
n_x--;
else
{
n_x = 2;
while (newsname[n_y][n_x] == "")
n_x--;
}
break;
case 'q':
case 'Q':
y = maxy;
break;
default:
break;
}
if (cmd == '\n' || cmd == 'q' || cmd == 'Q')
return ((y * 3 + x) < sum) ? 1 : 2;
}
}
static void
news_mainmsg()
{
move(6, 0);
clrtobot();
refresh();
mouts(b_lines, 0, "\033[46m 操作說明 \033[31;47m (↑↓←→) \033[30m選擇\
\033[31m(Enter)\033[30m確定 \033[31m(Q) \033[30m離開 \
\033[m");
}
static int
news_showmenu()
{
int i, p;
int maxy, sum;
news_mainmsg();
i = maxy = sum = 0;
/* 計算有幾筆 */
sum = maxy = sizeof(newsname2) / (sizeof(char) * 10);
if (maxy % 3)
maxy = (maxy / 3) + 1;
else
maxy = maxy / 3;
for (p = 0; p < maxy; p++)
for (i = 0; i < 3; i++)
{
move (8 + p, 6 + 36 * i);
prints("\033[0;37;00m %s \033[m", newsname[p][i]);
}
return news_mainmenu(maxy, sum);
}
static int
news_classmenu_title(pos)
int pos;
{
int i, j;
int max, sum;
char a;
struct tm *btime;
time_t now;
a = 65;
time(&now);
btime = localtime(&now);
move (6, 18);
clrtobot();
prints("\033[1;37m今天為 \033[32m%d \033[37m月 \033[32m%d\
\033[37m日 您目前正閱\讀\033[1;32m%s\033[37m新聞",
btime -> tm_mon + 1, btime -> tm_mday, newsname[y][x]);
move(8, 2);
/* 算有幾筆 */
sum = sizeof(newsclass2) / (sizeof(char) * 15);
for (i = 0, j = 1, max = 0; i < sum; i++)
{
if (class_name & j)
{
if (pos == max)
{
prints("\033[1;37;44m%c)%s\033[m ", a, newsclass[i]);
z = i;
}
else
prints("\033[m%c)%s\033[m ", a, newsclass[i]);
max++;
a++;
}
j <<= 1;
}
return max;
}
static int
news_article(file, pos)
char *file;
int pos;
{
char fpath[64];
takeALL takeall;
rec_get(file, &takeall, sizeof(takeALL), pos);
sprintf(fpath, ""NEWSHOME"/%s/%s/%s",
newsname2[y * 3 + x], newsclass2[z], takeall.file);
if (more(fpath, NULL) < 0)
{
vmsg("此文正在抓取中或者讀取錯誤");
return 0;
}
return 1;
}
static void
news_mainnews_msg()
{
outz("\033[46m 操作說明 \033[31;47m (↑↓) \033[30m選擇 \033[31m(Enter )\
\033[30m確定 \033[31m(Q ←) \033[30m離開 (1~n) \033[31m(F)\033[30m轉寄 \033[31m\
(^X)\033[30m轉錄\033[m");
}
static void
news_mainnews_titleprint(take, pos, mode)
takeALL *take;
int pos;
int mode; /* 0: 印光棒 1: No 光棒 */
{
move(10 + ((pos - 1) % NEWS_PAGE), 10);
if (!mode)
prints("\033[1;37;44m%3d %-50.50s\033[1;33m%8.8s\033[m", pos,
take->title, (strlen(take -> title) < 50) ? "" : "[..未完]");
else
prints("\033[0;00;00m%3d %-50.50s\033[1;33m%8.8s\033[m", pos,
take->title, (strlen(take -> title) < 50) ? "" : "[..未完]");
}
static int
news_mainnews_title(file, max, n_pos, o_pos, n_y, o_y, mode)
char *file;
int max;
int n_pos;
int o_pos;
int n_y;
int o_y;
int mode; /* 1:翻頁 0:不翻*/
{
takeALL takeall, ntakeall;
if (mode)
{
int top, i;
i = 0;
move (10, 0);
clrtobot();
top = (n_pos / NEWS_PAGE) * NEWS_PAGE;
while (rec_get(file, &takeall, sizeof(takeALL), top) != -1 &&
i < NEWS_PAGE)
{
if (i == n_y)
news_mainnews_titleprint(&takeall, top + 1, 0);
else
news_mainnews_titleprint(&takeall, top + 1, 1);
top++;
i++;
}
news_mainnews_msg();
}
else
{
rec_get(file, &takeall, sizeof(takeALL), o_pos);
news_mainnews_titleprint(&takeall, o_pos + 1, 1);
rec_get(file, &ntakeall, sizeof(takeALL), n_pos);
news_mainnews_titleprint(&ntakeall, n_pos + 1, 0);
}
}
static int
news_forward(file, pos)
char *file;
int pos;
{
static char rcpt[64];
char fpath[64], folder[80], *userid, *title;
int cc, userno;
usint method;
takeALL takeall;
if (cuser.userlevel & PERM_DENYMAIL)
return 0;
if (!rcpt[0])
strcpy(rcpt, cuser.email);
if (!vget(b_lines, 0, "目的地:", rcpt, sizeof(rcpt), GCARRY))
return 0;
userid = cuser.userid;
/* 參考 struct.h 之 MQ_UUENCODE / MQ_JUSTIFY */
#define MF_SELF 0x04
#define MF_USER 0x08
userno = 0;
if (!mail_external(rcpt)) /* 中途攔截 */
{
if (!str_cmp(rcpt, userid))
{
method = MF_SELF;
}
else
{
if ((userno = acct_userno(rcpt)) <= 0)
{
sprintf(fpath, "查無此人:%s", rcpt);
zmsg(fpath);
return 0;
}
method = MF_USER;
}
usr_fpath(folder, rcpt, fn_dir);
}
else
{
if (not_addr(rcpt))
return 0;
method = 0;
}
rec_get(file, &takeall, sizeof(takeALL), pos);
sprintf(fpath, ""NEWSHOME"/%s/%s/%s",
newsname2[y * 3 + x], newsclass2[z], takeall.file);
title = takeall.title;
if (method >= MF_SELF)
{
HDR mhdr;
if ((cc = hdr_stamp(folder, HDR_LINK, &mhdr, fpath)) < 0)
return 0;
if (method == MF_SELF)
{
strcpy(mhdr.owner, "[新 聞]");
mhdr.xmode = MAIL_READ | MAIL_NOREPLY;
}
else
{
strcpy(mhdr.owner, userid);
}
strcpy(mhdr.nick, cuser.username);
memcpy(mhdr.title, title, sizeof(mhdr.title));
if ((cc = rec_add(folder, &mhdr, sizeof(HDR))) < 0)
{
zmsg("部份信件無法寄達");
return 0;
}
}
else
{
if ((cc = bsmtp(fpath, title, rcpt, method)) < 0)
zmsg("部份信件無法寄達");
return 0;
}
if (userno > 0)
m_biff(userno);
zmsg("寄信完畢");
return 1;
}
static int
news_cross(file, pos)
char *file;
int pos;
{
int rc;
char xboard[20], fpath[128], xfolder[80], buf[80], buf2[80], title[73];
HDR xpost;
takeALL takeall;
FILE *fp;
if(!HAS_PERM(PERM_POST))
return 0;
if (ask_board(xboard, BRD_W_BIT,
"\n\n\033[1;33m請挑選適當的看板,切勿轉貼超過三板。\033[m\n\n")
&& *xboard)
{
rc = vget(2, 0, "(S)存檔 (Q)取消?[Q] ", buf, 3, LCECHO);
if (rc != 's' && rc != 'S')
return 0;
rec_get(file, &takeall, sizeof(takeALL), pos);
sprintf(fpath, ""NEWSHOME"/%s/%s/%s",
newsname2[y * 3 + x], newsclass2[z], takeall.file);
brd_fpath(xfolder, xboard, fn_dir);
if(!(fp = fdopen(hdr_stamp(xfolder, 'A', &xpost, buf), "w")))
return 0;
strcpy(buf2,ve_title);
strcpy(ve_title, takeall.title);
strcpy(buf, currboard);
strcpy(currboard, xboard);
ve_header(fp);
strcpy(currboard, buf);
strcpy(ve_title, buf2);
fprintf(fp, "※ 本文轉錄自碧海藍天新聞閱\讀系統 ※\n\n");
fprintf(fp, "轉自 Yahoo!Kimo 之 %s 報\n\n", newsname[y][x]);
f_suck(fp, fpath);
fclose(fp);
strcpy(xpost.owner, cuser.userid);
strcpy(xpost.nick, cuser.username);
memcpy(title, takeall.title, sizeof(title));
sprintf(xpost.title,"[轉貼]%-54.54s", title);
rec_add(xfolder, &xpost, sizeof(xpost));
vmsg("轉錄完成");
}
return 1;
}
static int
news_mainnews(file, max, z_pos)
char *file;
int max;
int z_pos;
{
int n_y, o_y, max_y;
int pos, o_pos;
int cmd, mode, page;
n_y = o_y = pos = o_pos = page = mode = 0;
for (;;)
{
/* 判斷是否有翻頁 */
if (o_y == 0 && (pos == max - 1 || pos == ((page + 1) * NEWS_PAGE) - 1))
{
mode = 1;
n_y = max_y = (pos == max - 1) ?
(max <= NEWS_PAGE) ? max - 1 : max % NEWS_PAGE == 0 ? NEWS_PAGE - 1 :
max % NEWS_PAGE - 1 : NEWS_PAGE - 1;
}
else if ((o_y == max_y && n_y == 0) || (pos == 0 && o_pos != pos + 1))
{
mode = 1;
max_y = (max - pos > NEWS_PAGE) ? NEWS_PAGE - 1 : max - pos - 1;
n_y = o_y = 0;
}
news_mainnews_title(file, max_y, pos, o_pos, n_y, o_y, mode);
o_y = n_y;
o_pos = pos;
cmd = vkey();
if (cmd >= '1' && cmd <= '9')
{
int opage, num;
char buf[6];
buf[0] = cmd;
buf[1] = '\0';
vget(b_lines, 0, "跳至第幾項:", buf, sizeof(buf), GCARRY);
num = atoi(buf);
if (num > max)
num = max;
opage = page;
pos = num - 1;
n_y = pos - (pos / NEWS_PAGE * NEWS_PAGE);
page = pos / NEWS_PAGE;
if (page > opage || page < opage)
mode = 1;
continue;
}
switch (cmd)
{
case KEY_DOWN:
if (n_y < max_y)
n_y++;
else
{
n_y = 0;
if (page < max / NEWS_PAGE)
page++;
else
page = 0;
}
if (pos < max - 1)
pos++;
else
pos = 0;
break;
case KEY_UP:
if (n_y > 0)
n_y--;
else
{
n_y = max_y - 1;
if (page > 0)
page--;
else
page = max / NEWS_PAGE;
}
if (pos > 0)
pos--;
else
pos = max - 1;
case KEY_LEFT:
case 'q':
case 'Q':
break;
case KEY_RIGHT:
case '\n':
mode = 1;
break;
case KEY_PGDN:
case ' ':
pos += NEWS_PAGE;
if (pos > max - 1)
{
pos = max - 1;
n_y = max % NEWS_PAGE == 0 ? NEWS_PAGE - 1 :
max % NEWS_PAGE - 1;
page = max / NEWS_PAGE;
}
else
page++;
mode = 1;
break;
case KEY_PGUP:
pos -= NEWS_PAGE;
if (pos < 0)
pos = n_y = page = 0;
else
page--;
mode = 1;
break;
case KEY_HOME:
case '0':
pos = n_y = page = 0;
mode = 1;
break;
case KEY_END:
case '$':
pos = max - 1;
n_y = max % NEWS_PAGE == 0 ? NEWS_PAGE - 1 :
max % NEWS_PAGE - 1;
page = max / NEWS_PAGE;
mode = 1;
break;
case 'F':
news_forward(file, pos);
cmd = '\n'; /* 配合下面 */
mode = 0;
break;
case Ctrl('X'):
news_cross(file, pos);
cmd = '\n'; /* 配合下面 */
mode = 0;
break;
case Ctrl('Z'):
every_Z();
break;
default:
continue;
}
if (cmd == KEY_LEFT || cmd == 'q' || cmd == 'Q')
return 0;
else if (cmd == '\n' || cmd == KEY_RIGHT)
{
if (mode)
{
if (!news_article(file, pos))
break;
}
/* 重印一次 */
news_neck();
news_classmenu_title(z_pos);
mode = 1;
}
else if (cmd == KEY_PGDN || cmd == KEY_PGUP || cmd == KEY_END
|| cmd == '$' || cmd == KEY_HOME || cmd == '0' ||
cmd == ' ')
continue;
else
mode = 0;
}
}
static void
news_class_msg()
{
mouts(b_lines, 0, "\033[46m 操作說明 \033[31;47m (←→) \033[30m選擇 \
\033[31m(Enter↓)\033[30m確定 \033[31m(Q) \033[30m離開 \
\033[m");
}
static void
news_printbody(take, pos, num)
takeALL *take;
int pos;
int num; /* 0: 印 title 1: Empty */
{
if (!num)
{
move(10 + pos, 10);
prints("\033[m%3d %-50.50s\033[1;33m%8.8s\033[m", pos + 1, take -> title,
(strlen(take -> title) < 50) ? "" : "[..未完]");
}
else
{
move(14, 29);
prints("\033[1;37;41m 目前尚無新聞 \033[m");
}
}
static int
news_printnews(file)
char *file;
{
int i, max;
takeALL takeall;
i = max = 0;
move(10, 0);
clrtobot();
while (rec_get(file, &takeall, sizeof(takeall), i) != -1)
{
max++;
if (i < NEWS_PAGE)
news_printbody(&takeall, i, 0);
i++;
}
news_class_msg();
if (i <= 0)
{
news_printbody(&takeall, i, 1);
return 0;
}
return max;
}
static void
news_fpath(fpath, x, z)
char *fpath;
int x;
int z;
{
sprintf(fpath, "/home/bbs/news/%s/%s/@class", newsname2[x], newsclass2[z]);
}
static int
news_classmenu()
{
int n_x, max_x;
int max, cmd, a;
char fpath[64];
max_x = n_x = max = 0;
for (;;)
{
max_x = news_classmenu_title(n_x);
max_x--;
news_fpath(fpath, (y * 3 + x), z);
max = news_printnews(fpath);
cmd = vkey();
switch (cmd)
{
case KEY_RIGHT:
if (n_x < max_x)
n_x++;
else
n_x = 0;
break;
case KEY_LEFT:
if (n_x > 0)
n_x--;
else
n_x = max_x;
break;
case '\n':
case KEY_DOWN:
break;
case 'Q':
case 'q':
break;
default:
/* 鍵入 a(A) ~ z(Z) 直接跳 */
if (cmd >= 65 && cmd <= 65 + max_x)
{
a = cmd - 65;
n_x = a;
}
else if (cmd >= 97 && cmd <= 97 + max_x)
{
a = cmd - 97;
n_x = a;
}
break;
}
if ((cmd == '\n' || cmd == KEY_DOWN) && max > 0)
news_mainnews(fpath, max, n_x);
else if (cmd == 'q' || cmd == 'Q')
return 0;
}
}
int
main_news()
{
int i;
x = y = z = 0;
i = 0;
news_neck();
while (1)
{
if (!i)
i = news_showmenu();
else if(i == 1)
i = news_classmenu();
else
break;
}
return 0;
}
--
◢ ◢/ ◣ ╭┬╮╭╮ ╭┐╭─╯ ╰┼─┼╯ ╭─┬─╮
◥ | ◤◤▏◤╰┼╮├┤ └╯╭─╮ ╭┬╮╭╮ ◢█◣◢◥◣◢◥◣◢◥◣
▉| d ; ;│ ╰┴╯╰╯ ╭┐│●╭ ├● ┼╮ ╰─◥◢▉▋◢▉▋◢▉▋◢█
▁ ◢◥▊ _◤ ◣╰┬──╮ └╯│╭╯ ╰┴╯╰┘ ╭◢█◤█▊◤█▊◤█▋◤
◢ ◢ ▆ ◣ ╭╯──┐ ╭┐╯●│ ╭┬─┬╮ │ │▔ ─163.17.132.1─╮
◥◤▉\\▇//▏ ╰───╯ └╯╰└╯ ┴┴─┴┴ ╰╯ ╰╯ bbs.ntit.edu.tw
--
※ Origin: 碧海藍天 <bbs.ntit.edu.tw>
◆ From: 61-216-129-25.hinet-ip.hinet.net
推
09/09 11:51, , 1F
09/09 11:51, 1F
討論串 (同標題文章)
完整討論串 (本文為第 1 之 2 篇):
Maple 近期熱門文章
PTT數位生活區 即時熱門文章