summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpiaip <piaip@63ad8ddf-47c3-0310-b6dd-a9e9d9715204>2009-10-23 11:53:53 +0800
committerpiaip <piaip@63ad8ddf-47c3-0310-b6dd-a9e9d9715204>2009-10-23 11:53:53 +0800
commiteacf07af33bb5cbedf6c4a103fe90abd5d09965d (patch)
treea8408cc7e7832917bd96d6fddda293f4332647e7
parent8c816c5f2a24b493c477c76fcab4175060ebe9d8 (diff)
downloadpttbbs-eacf07af33bb5cbedf6c4a103fe90abd5d09965d.tar
pttbbs-eacf07af33bb5cbedf6c4a103fe90abd5d09965d.tar.gz
pttbbs-eacf07af33bb5cbedf6c4a103fe90abd5d09965d.tar.bz2
pttbbs-eacf07af33bb5cbedf6c4a103fe90abd5d09965d.tar.lz
pttbbs-eacf07af33bb5cbedf6c4a103fe90abd5d09965d.tar.xz
pttbbs-eacf07af33bb5cbedf6c4a103fe90abd5d09965d.tar.zst
pttbbs-eacf07af33bb5cbedf6c4a103fe90abd5d09965d.zip
* improve ccw design
git-svn-id: http://opensvn.csie.org/pttbbs/trunk@4964 63ad8ddf-47c3-0310-b6dd-a9e9d9715204
-rw-r--r--pttbbs/mbbsd/ccw.c241
-rw-r--r--pttbbs/mbbsd/talk.c10
2 files changed, 135 insertions, 116 deletions
diff --git a/pttbbs/mbbsd/ccw.c b/pttbbs/mbbsd/ccw.c
index 0502c6c2..729da9b2 100644
--- a/pttbbs/mbbsd/ccw.c
+++ b/pttbbs/mbbsd/ccw.c
@@ -34,6 +34,9 @@
// 2. we may move anti-flood and other static variables into context...
// 3. TAB complete...
// 4. add F1 for help?
+// 5. log recovery on crash?
+// 6. use merge all cmd processor into peek_cmd(CCW_REMOTE)
+// 7. better receive buffer
#define CCW_MAX_INPUT_LEN (STRLEN)
#define CCW_INIT_LINE (2)
@@ -82,6 +85,10 @@ typedef struct CCW_CTX {
void (*print_line) (struct CCW_CTX *, const char *buf, int local); // print on screen
void (*log_line) (struct CCW_CTX *, const char *buf, int local); // log to file
void (*post_input) (struct CCW_CTX *, const char *buf, int local); // after valid input
+
+ // session state change
+ void (*init_session)(struct CCW_CTX *);
+ void (*end_session )(struct CCW_CTX *);
} CCW_CTX;
///////////////////////////////////////////////////////////////////////////
@@ -89,6 +96,7 @@ typedef struct CCW_CTX {
// utilities declaration
void ccw_prepare_line(CCW_CTX *ctx);
+int ccw_partial_match(const char *buf, const char *cmd);
// default callback handlers
static void
@@ -120,7 +128,7 @@ ccw_footer(CCW_CTX *ctx)
return;
}
- vs_footer(" CCW ", " (/b) 離開 ");
+ vs_footer(" CCW ", " (PgUp/PgDn)回顧訊息記錄\t(Ctrl-C)離開 ");
}
static void
@@ -161,14 +169,38 @@ ccw_prompt(CCW_CTX *ctx)
prints("%s: ", ctx->local_id);
}
+static void
+ccw_init_session(CCW_CTX *ctx)
+{
+ if (ctx->init_session)
+ {
+ ctx->init_session(ctx);
+ return;
+ }
+}
+
+static void
+ccw_end_session(CCW_CTX *ctx)
+{
+ if (ctx->end_session)
+ {
+ ctx->end_session(ctx);
+ return;
+ }
+}
+
static int
-ccw_peek_cmd(struct CCW_CTX *ctx, const char *buf, int local)
+ccw_peek_cmd(CCW_CTX *ctx, const char *buf, int local)
{
if (ctx->peek_cmd)
return ctx->peek_cmd(ctx, buf, local);
- // sample command: /b
- if (strcasecmp(buf, "/b") == 0)
+ if (buf[0] != '/')
+ return 0;
+ buf++;
+
+ // sample command: bye
+ if (ccw_partial_match(buf, "bye"))
{
ctx->abort = 1;
return 1;
@@ -177,7 +209,7 @@ ccw_peek_cmd(struct CCW_CTX *ctx, const char *buf, int local)
}
static void
-ccw_print_line (struct CCW_CTX *ctx, const char *buf, int local)
+ccw_print_line(CCW_CTX *ctx, const char *buf, int local)
{
ccw_prepare_line(ctx);
if (ctx->print_line)
@@ -202,7 +234,7 @@ ccw_print_line (struct CCW_CTX *ctx, const char *buf, int local)
}
static void
-ccw_log_line (struct CCW_CTX *ctx, const char *buf, int local)
+ccw_log_line(CCW_CTX *ctx, const char *buf, int local)
{
if (!ctx->log)
return;
@@ -215,12 +247,14 @@ ccw_log_line (struct CCW_CTX *ctx, const char *buf, int local)
if (local <= CCW_LOCAL) // local or remote, but not message
{
+ // we don't put ANSI escapes into log now...
fprintf(ctx->log, "%s%s: ",
- local ? "" : ANSI_COLOR(1),
+ "", // local ? "" : ANSI_COLOR(1),
local ? ctx->local_id : ctx->remote_id);
}
fprintf(ctx->log, "%s%s\n",
- buf, local ? "" : ANSI_RESET);
+ buf,
+ ""); // local ? "" : ANSI_RESET);
}
// CCW utilities
@@ -254,7 +288,7 @@ ccw_prepare_line(CCW_CTX *ctx)
// scroll screen buffer
region_scroll_up(CCW_INIT_LINE, CCW_STOP_LINE - CCW_INIT_LINE);
move(ctx->line-1, 0);
- // TODO after resize, we may need to scroll more than once.
+ // XXX after resize, we may need to scroll more than once.
}
clrtoeol();
}
@@ -274,7 +308,7 @@ ccw_partial_match(const char *buf, const char *cmd)
// print and log one line of text.
void
-ccw_add_line (struct CCW_CTX *ctx, const char *buf, int local)
+ccw_add_line(CCW_CTX *ctx, const char *buf, int local)
{
// only print/log local when local_echo is enabled.
if (local != CCW_LOCAL || ctx->local_echo)
@@ -295,14 +329,54 @@ ccw_vgetcb_peek(int key, VGET_RUNTIME *prt GCC_UNUSED, void *instance)
{
CCW_CTX *ctx = (CCW_CTX*) instance;
assert(ctx);
+
if (ctx->peek_key &&
ctx->peek_key(ctx, key))
{
return (ctx->abort_vget || ctx->abort) ? VGETCB_ABORT : VGETCB_NEXT;
}
- return VGETCB_NONE;
+ // early check
+ if (ctx->abort_vget || ctx->abort)
+ return VGETCB_ABORT;
+
+ // common keys
+ switch (key)
+ {
+ case KEY_PGUP:
+ case KEY_PGDN:
+ if (ctx->log && ctx->log_fpath)
+ {
+ VREFSCR scr = vscr_save();
+ add_io(0, 0);
+ fflush(ctx->log);
+ more(ctx->log_fpath, YEA);
+
+ add_io(ctx->fd, 0);
+ vscr_restore(scr);
+ }
+ return VGETCB_NEXT;
+
+ case Ctrl('C'):
+ {
+ VREFSCR scr = vscr_save();
+ add_io(0, 0);
+
+ if (vans("確定要離開嗎? [y/N]: ") == 'y')
+ ctx->abort = YEA;
+
+ add_io(ctx->fd, 0);
+ vscr_restore(scr);
+ // ccw_footer(ctx);
+ }
+ if (ctx->abort_vget || ctx->abort)
+ return VGETCB_ABORT;
+ return VGETCB_NEXT;
+ }
+
+ // normal data.
+ return VGETCB_NONE;
}
// main processor
@@ -315,6 +389,8 @@ ccw_process(CCW_CTX *ctx)
assert( ctx->MAX_INPUT_LEN > 2 &&
ctx->MAX_INPUT_LEN <= CCW_MAX_INPUT_LEN);
+
+ ccw_init_session(ctx);
ccw_reset_scr(ctx);
#ifdef DEBUG
@@ -357,6 +433,7 @@ ccw_process(CCW_CTX *ctx)
// accept this data
ccw_add_line(ctx, inbuf, CCW_LOCAL);
}
+ ccw_end_session(ctx);
if (ctx->log)
fflush(ctx->log);
@@ -464,6 +541,7 @@ ccw_talk_recv(CCW_CTX *ctx, char *buf, size_t szbuf)
{
char len = 0;
buf[0] = 0;
+ // XXX blocking call here...
if (toread(ctx->fd, &len, 1) != 1)
return -1;
if (toread(ctx->fd, buf, len)!= len)
@@ -473,11 +551,11 @@ ccw_talk_recv(CCW_CTX *ctx, char *buf, size_t szbuf)
return len;
}
-static ssize_t
-ccw_talk_send_bye(CCW_CTX *ctx)
+static void
+ccw_talk_end_session(CCW_CTX *ctx)
{
- return ccw_talk_send(ctx,
- CCW_TALK_CMD_PREFIX_STR CCW_TALK_CMD_BYE);
+ // XXX note the target connection may be already closed.
+ ccw_talk_send(ctx, CCW_TALK_CMD_PREFIX_STR CCW_TALK_CMD_BYE);
}
static void
@@ -491,10 +569,8 @@ ccw_talk_header(CCW_CTX *ctx)
static void
ccw_talk_footer(CCW_CTX *ctx)
{
- vs_footer(" 【" CCW_CAP_TALK "】 ", " ( "
- CCW_TALK_CMD_PREFIX_STR CCW_TALK_CMD_BYE " )結束" CCW_CAP_TALK " ( "
- CCW_TALK_CMD_PREFIX_STR CCW_TALK_CMD_CLEAR " )清除畫面"
- "\t(Ctrl-C)離開 ");
+ vs_footer(" 【" CCW_CAP_TALK "】 ",
+ " (PgUp/PgDn)回顧訊息記錄\t(Ctrl-C)離開 ");
}
static int
@@ -504,21 +580,23 @@ ccw_talk_peek_cmd(CCW_CTX *ctx, const char *buf, int local)
return 0;
buf++;
- // process commands
+ // process remote and local commands
+ if (ccw_partial_match(buf, CCW_TALK_CMD_BYE))
+ {
+ ctx->abort = 1;
+ return 1;
+ }
+ // process local commands
+ if (local == CCW_REMOTE)
+ return 0;
if (ccw_partial_match(buf, CCW_TALK_CMD_HELP))
{
- ccw_print_line(ctx, "[說明]: 可輸入 "
+ ccw_print_line(ctx, "[說明] 可輸入 "
CCW_TALK_CMD_PREFIX_STR CCW_TALK_CMD_CLEAR " 清除畫面或 "
CCW_TALK_CMD_PREFIX_STR CCW_TALK_CMD_BYE " 離開。",
CCW_LOCAL_MSG);
return 1;
}
- if (ccw_partial_match(buf, CCW_TALK_CMD_BYE))
- {
- ccw_talk_send_bye(ctx); // notify dest user if he's still online
- ctx->abort = 1;
- return 1;
- }
if (ccw_partial_match(buf, CCW_TALK_CMD_CLEAR) ||
ccw_partial_match(buf, CCW_TALK_CMD_CLS))
{
@@ -551,33 +629,12 @@ ccw_talk_peek_key(CCW_CTX *ctx, int key)
return 1;
}
// process commands
- if (strcasecmp(buf, CCW_TALK_CMD_BYE) == 0)
- {
- ctx->abort = YEA;
+ if (ccw_peek_cmd(ctx, buf, CCW_REMOTE))
return 1;
- }
// received something, let's print it.
ccw_add_line(ctx, buf, CCW_REMOTE);
}
return 1;
-
- case Ctrl('C'):
- {
- VREFSCR scr = vscr_save();
- add_io(0, 0);
-
- if (vans("確定要中止" CCW_CAP_TALK "嗎? [y/N]: ") == 'y')
- ctx->abort = YEA;
-
- add_io(ctx->fd, 0);
- vscr_restore(scr);
-
- // ccw_footer(ctx);
- }
- // notify remote user
- if (ctx->abort)
- ccw_talk_send(ctx, CCW_TALK_CMD_BYE);
- return 1;
}
return 0;
}
@@ -589,16 +646,13 @@ ccw_talk(int fd, int destuid)
char remote_id[IDLEN+1], local_id[IDLEN+1];
CCW_CTX ctx = {
- .fd = fd,
- .abort = NA,
-
- .log = NULL,
- .log_fpath = fpath,
- .local_echo = YEA,
- .MAX_INPUT_LEN = STRLEN - IDLEN - 5, // 5 for ": " and more
- .remote_id = remote_id,
- .local_id = local_id,
- .sep_msg = " /b 離開 /c 清除畫面 ",
+ .fd = fd,
+ .log_fpath = fpath,
+ .local_echo = YEA,
+ .MAX_INPUT_LEN = STRLEN - IDLEN - 5, // 5 for ": " and more
+ .remote_id = remote_id,
+ .local_id = local_id,
+ .sep_msg = " /c 清除畫面 /b 離開 ",
.header = ccw_talk_header,
.footer = ccw_talk_footer,
@@ -606,6 +660,7 @@ ccw_talk(int fd, int destuid)
.peek_key = ccw_talk_peek_key,
.peek_cmd = ccw_talk_peek_cmd,
.post_input = ccw_talk_post_input,
+ .end_session= ccw_talk_end_session,
};
STATINC(STAT_DOTALK);
@@ -705,10 +760,11 @@ ccw_chat_send(CCW_CTX *ctx, const char *buf)
return (send(ctx->fd, genbuf, len, 0) == len);
}
-static int
-ccw_chat_send_bye(CCW_CTX *ctx)
+static void
+ccw_chat_end_session(CCW_CTX *ctx)
{
- return ccw_chat_send(ctx, "/b"); // protocol: bye
+ // XXX note the target connection may be already closed.
+ ccw_chat_send(ctx, "/bye"); // protocol: bye
}
static void
@@ -752,7 +808,7 @@ ccw_chat_prompt(CCW_CTX *ctx)
}
static void
-ccw_chat_print_line (struct CCW_CTX *ctx, const char *buf, int local)
+ccw_chat_print_line(CCW_CTX *ctx, const char *buf, int local)
{
assert(local != CCW_LOCAL);
outs(buf);
@@ -760,7 +816,7 @@ ccw_chat_print_line (struct CCW_CTX *ctx, const char *buf, int local)
}
static void
-ccw_chat_log_line (struct CCW_CTX *ctx, const char *buf, int local)
+ccw_chat_log_line(CCW_CTX *ctx, const char *buf, int local)
{
assert(local != CCW_LOCAL);
fprintf(ctx->log, "%s\n", buf);
@@ -909,7 +965,7 @@ ccw_chat_peek_cmd(CCW_CTX *ctx, const char *buf, int local)
"[/p]ager", "切換呼叫器",
"[/r]oom ", "列出一般" CCW_CAP_CHATROOM,
"[/w]ho", "列出本" CCW_CAP_CHATROOM "使用者",
- " /whoin <room>", "列出" CCW_CAP_CHAT "<room> 的使用者",
+ " /whoin <room>", "列出" CCW_CAP_CHAT " <room> 的使用者",
" /ignore <userid>", "忽略指定使用者的訊息",
" /unignore <userid>", "停止忽略指定使用者的訊息",
NULL,
@@ -958,7 +1014,6 @@ ccw_chat_peek_cmd(CCW_CTX *ctx, const char *buf, int local)
}
if (ccw_partial_match(buf, "bye"))
{
- ccw_chat_send_bye(ctx);
ctx->abort = 1;
return 1;
}
@@ -982,31 +1037,12 @@ ccw_chat_peek_key(CCW_CTX *ctx, int key)
case I_OTHERDATA: // incoming
if (ccw_chat_recv(ctx) == -1)
{
- ccw_chat_send_bye(ctx);
ctx->abort = YEA;
return 1;
}
ccw_chat_check_newmail(ctx);
return 1;
- case Ctrl('C'):
- {
- VREFSCR scr = vscr_save();
- add_io(0, 0);
-
- if (vans("確定要中止" CCW_CAP_CHAT "嗎? [y/N]: ") == 'y')
- ctx->abort = YEA;
-
- add_io(ctx->fd, 0);
- vscr_restore(scr);
-
- // ccw_footer(ctx);
- }
- // notify remote user
- if (ctx->abort)
- ccw_chat_send_bye(ctx);
- return 1;
-
case Ctrl('I'):
{
VREFSCR scr = vscr_save();
@@ -1019,21 +1055,6 @@ ccw_chat_peek_key(CCW_CTX *ctx, int key)
}
return 1;
- case KEY_PGUP:
- case KEY_PGDN:
- if (ctx->log && ctx->log_fpath)
- {
- VREFSCR scr = vscr_save();
- add_io(0, 0);
-
- fflush(ctx->log);
- more(ctx->log_fpath, YEA);
-
- add_io(ctx->fd, 0);
- vscr_restore(scr);
- }
- return 1;
-
// Support ZA because chat is mostly independent and secure.
case Ctrl('Z'):
{
@@ -1063,17 +1084,14 @@ ccw_chat(int fd)
.old_cols = t_columns,
};
CCW_CTX ctx = {
- .fd = fd,
- .abort = NA,
-
- .log = NULL,
- .log_fpath = fpath,
- .local_echo = NA,
- .MAX_INPUT_LEN = STRLEN - CHAT_ID_LEN - 3, // 3 for ": "
- .remote_id = roomid,
- .local_id = chatid,
- .arg = &ext,
- .sep_msg = " /h 查詢指令 /b 離開 ",
+ .fd = fd,
+ .log_fpath = fpath,
+ .local_echo = NA,
+ .MAX_INPUT_LEN = STRLEN - CHAT_ID_LEN - 3, // 3 for ": "
+ .remote_id = roomid,
+ .local_id = chatid,
+ .arg = &ext,
+ .sep_msg = " /h 查詢指令 /b 離開 ",
.header = ccw_chat_header,
.footer = ccw_chat_footer,
@@ -1084,6 +1102,7 @@ ccw_chat(int fd)
.peek_key = ccw_chat_peek_key,
.peek_cmd = ccw_chat_peek_cmd,
.post_input = ccw_chat_post_input,
+ .end_session= ccw_chat_end_session,
};
// initialize nick
diff --git a/pttbbs/mbbsd/talk.c b/pttbbs/mbbsd/talk.c
index 64dfd8b6..efa54e87 100644
--- a/pttbbs/mbbsd/talk.c
+++ b/pttbbs/mbbsd/talk.c
@@ -3406,16 +3406,16 @@ talkreply(void)
// FIXME CRASH here
assert(sig>=0 && sig<sizeof(sig_des)/sizeof(sig_des[0]));
prints(" (Y) 讓我們 %s 吧!"
- " (A) 我現在很忙,請等一會兒再 call 我\n", sig_des[sig]);
+ " (A) 我現在很忙,請等一會兒再 call 我\n", sig_des[sig]);
prints(" (N) 我現在不想 %s"
- " (B) 對不起,我有事情不能跟你 %s\n",
+ " (B) 對不起,我有事情不能跟你 %s\n",
sig_des[sig], sig_des[sig]);
prints(" (C) 請不要吵我好嗎?"
- " (D) 我要離站囉..下次再聊吧.......\n");
+ " (D) 我要離站囉..下次再聊吧.......\n");
prints(" (E) 有事嗎?請先來信"
- " (F) " ANSI_COLOR(1;33) "我自己輸入理由好了..." ANSI_RESET "\n");
+ " (F) " ANSI_COLOR(1;33) "<自行輸入理由>..." ANSI_RESET "\n");
prints(" (1) %s?先拿$100來"
- " (2) %s?先拿$1000來..\n\n", sig_des[sig], sig_des[sig]);
+ " (2) %s?先拿$1000來..\n\n", sig_des[sig], sig_des[sig]);
snprintf(page_requestor, sizeof(page_requestor),
"%s (%s)", uip->userid, uip->nickname);