diff options
-rw-r--r-- | pttbbs/common/sys/string.c | 18 | ||||
-rw-r--r-- | pttbbs/include/cmsys.h | 8 | ||||
-rw-r--r-- | pttbbs/include/common.h | 6 | ||||
-rw-r--r-- | pttbbs/include/proto.h | 3 | ||||
-rw-r--r-- | pttbbs/mbbsd/bbs.c | 125 | ||||
-rw-r--r-- | pttbbs/mbbsd/mail.c | 34 | ||||
-rw-r--r-- | pttbbs/mbbsd/stuff.c | 42 | ||||
-rw-r--r-- | pttbbs/mbbsd/var.c | 5 |
8 files changed, 166 insertions, 75 deletions
diff --git a/pttbbs/common/sys/string.c b/pttbbs/common/sys/string.c index 1d0aa3a9..80dda509 100644 --- a/pttbbs/common/sys/string.c +++ b/pttbbs/common/sys/string.c @@ -26,6 +26,24 @@ str_lower(char *t, const char *s) } while (ch); } +int +str_starts_with(const char *str, const char *prefix) { + while (*prefix) { + if (*prefix++ != *str++) + return 0; + } + return 1; +} + +int +str_case_starts_with(const char *str, const char *prefix) { + while (*prefix) { + if (tolower(*prefix++) != tolower(*str++)) + return 0; + } + return 1; +} + /** * 移除字串 buf 後端多餘的空白。 * @param buf diff --git a/pttbbs/include/cmsys.h b/pttbbs/include/cmsys.h index 81783c62..17f9fbe6 100644 --- a/pttbbs/include/cmsys.h +++ b/pttbbs/include/cmsys.h @@ -97,6 +97,8 @@ extern unsigned int *uintbsearch(const unsigned int key, const unsigned int *bas /* string.h */ extern void str_lower(char *t, const char *s); +extern int str_starts_with(const char *str, const char *prefix); +extern int str_case_starts_with(const char *str, const char *prefix); extern void trim(char *buf); extern void chomp(char *src); extern int strlen_noansi(const char *s); @@ -300,9 +302,9 @@ extern int ucs2utf(uint16_t ucs2, uint8_t *utf8); extern int utf2ucs(uint8_t *utf8, uint16_t *pucs); /* big5.c */ -extern const uint16_t const b2u_table[]; -extern const uint16_t const u2b_table[]; -extern const uint8_t const b2u_ambiguous_width[]; +extern const uint16_t b2u_table[]; +extern const uint16_t u2b_table[]; +extern const uint8_t b2u_ambiguous_width[]; #endif #endif diff --git a/pttbbs/include/common.h b/pttbbs/include/common.h index fa614eba..0861235b 100644 --- a/pttbbs/include/common.h +++ b/pttbbs/include/common.h @@ -192,6 +192,12 @@ #define WB_OFO_MSG_BOTTOM 22 #define WB_OFO_MSG_LEFT 4 +/* ----------------------------------------------------- */ +/* 標題類形 */ +/* ----------------------------------------------------- */ +#define SUBJECT_NORMAL 0 +#define SUBJECT_REPLY 1 +#define SUBJECT_FORWARD 2 /* ----------------------------------------------------- */ /* 群組名單模式 Ptt */ diff --git a/pttbbs/include/proto.h b/pttbbs/include/proto.h index 716fac1e..ee79ffd3 100644 --- a/pttbbs/include/proto.h +++ b/pttbbs/include/proto.h @@ -613,7 +613,8 @@ int show_80x24_screen(const char *filename); void show_help(const char * const helptext[]); void show_helpfile(const char * helpfile); int search_num(int ch, int max); -char*subject(char *title); +const char* subject(const char *title); +const char* subject_ex(const char *title, int *ptype); int str_checksum(const char *str); int userid_is_BM(const char *userid, const char *list); int is_uBM(const char *list, const char *id); diff --git a/pttbbs/mbbsd/bbs.c b/pttbbs/mbbsd/bbs.c index fde50827..5e1b0b66 100644 --- a/pttbbs/mbbsd/bbs.c +++ b/pttbbs/mbbsd/bbs.c @@ -575,11 +575,12 @@ tn_safe_strip(char *title) static void readdoent(int num, fileheader_t * ent) { - int type = ' '; - char *mark, *title, - color, special = 0, isonline = 0, recom[8]; + int type = ' ', title_type = SUBJECT_NORMAL; + const char *title; + char *mark, color, special = 0, isonline = 0, recom[8]; char *typeattr = ""; char isunread = 0, oisunread = 0; + int w = 0; #ifdef SAFE_ARTICLE_DELETE // TODO maybe we should also check .filename because admin can't change that @@ -658,7 +659,7 @@ readdoent(int num, fileheader_t * ent) type = '+'; } - title = ent->filename[0]!='L' ? subject(ent->title) : "<本文鎖定>"; + title = ent->filename[0]!='L' ? subject_ex(ent->title, &title_type) : "<本文鎖定>"; #ifdef SAFE_ARTICLE_DELETE if (iscorpse) color = '0', mark = "□"; @@ -667,29 +668,17 @@ readdoent(int num, fileheader_t * ent) #endif if (ent->filemode & FILE_VOTE) color = '2', mark = "ˇ"; - else if (title == ent->title) - color = '1', mark = "□"; - else if (ent->title[0] == str_forward[0]) - color = '6', mark = "轉"; - else // if (ent->title[0] == str_reply[0]) - color = '3', mark = "R:"; - - /* 把過長的 title 砍掉。 前面約有 33 個字元。 */ - { - int l = t_columns - 34; /* 33+1, for trailing one more space */ - unsigned char *p = (unsigned char*)title; - - /* strlen 順便做 safe print checking */ - while (*p && l > 0) - { - /* 本來應該做 DBCS checking, 懶得寫了 */ - if(*p < ' ') - *p = ' '; - p++, l--; - } - - if (*p && l <= 0) - strcpy((char*)p-3, " …"); + else switch(title_type) { + case SUBJECT_REPLY: + color = '3', mark = "R:"; + break; + case SUBJECT_FORWARD: + color = '6', mark = "轉"; + break; + case SUBJECT_NORMAL: + default: + color = '1', mark = "□"; + break; } // TN_ANNOUNCE: [公告] @@ -745,13 +734,42 @@ readdoent(int num, fileheader_t * ent) if(isonline) outs(ANSI_COLOR(1)); prints("%-13.12s", ent->owner); if(isonline) outs(ANSI_RESET); - - if (strncmp(currtitle, title, TTLEN)) - prints("%s " ANSI_COLOR(1) "%.*s" ANSI_RESET "%s\n", - mark, special ? 6 : 0, title, special ? title + 6 : title); - else - prints(ANSI_COLOR(1;3%c) "%s %s" ANSI_RESET "\n", - color, mark, title); + + // TODO calculate correct width. 前面約有 33 個字元。 */ + w = t_columns - 34; /* 33+1, for trailing one more space */ + + // print subject prefix + ent->title[sizeof(ent->title)-1] = 0; + if (strcmp(currtitle, title) == 0) { + prints(ANSI_COLOR(1;3%c), color); + outs(mark); + outc(' '); + } else { + outs(mark); + outc(' '); + if (special) { + int len_announce = strlen(TN_ANNOUNCE); + outs(ANSI_COLOR(1)); + outs(TN_ANNOUNCE); + outs(ANSI_RESET); + title += len_announce; + w -= len_announce; + } + } + + // strip unsafe characters + strip_nonebig5((char*)title, INT_MAX); + + // print subject, bounded by w. + if (strlen(title) > w) { + if (DBCS_Status(title, w-2) == DBCS_TRAILING) + w--; + outns(title, w-2); + outs("…"); + } else { + outs(title); + } + outc('\n'); } int @@ -1014,12 +1032,12 @@ do_reply_title(int row, const char *title, char result[STRLEN]) char genbuf[200]; char genbuf2[4]; - snprintf(result, STRLEN, "%s%s", str_reply, subject(title)); + snprintf(result, STRLEN, "%s %s", str_reply, subject(title)); result[TTLEN - 1] = '\0'; - snprintf(genbuf, sizeof(genbuf), "採用原標題《%.60s》嗎?[Y] ", result); - getdata(row, 0, genbuf, genbuf2, 4, LCECHO); + mvouts(row++, 0, "原標題: "); outs(result); + getdata(row, 0, "採用原標題[Y/n]? ", genbuf2, 3, LCECHO); if (genbuf2[0] == 'n') - getdata(++row, 0, "標題:", result, TTLEN, DOECHO); + getdata(row, 0, "新標題:", result, TTLEN, DOECHO); } void @@ -1051,7 +1069,7 @@ log_crosspost_in_allpost(const char *brd, const fileheader_t *postfile) { strcat(genbuf, "…"); } snprintf(fh.title, sizeof(fh.title), - "%s%-*.*s.%s板", str_forward, len, len, genbuf, brd); + "%s %-*.*s.%s板", str_forward, len, len, genbuf, brd); setbdir(genbuf, BN_ALLPOST); if (append_record(genbuf, &fh, sizeof(fileheader_t)) != -1) { @@ -1069,13 +1087,20 @@ do_crosspost(const char *brd, fileheader_t *postfile, const char *fpath, int len = 42-strlen(currboard); fileheader_t fh; int bid = getbnum(brd); + char *title, *prefix = ""; + int title_type = SUBJECT_NORMAL; if(bid <= 0 || bid > MAX_BOARD) return; - - if(!strncasecmp(postfile->title, str_reply, 3)) - len=len+4; - else if(!strncasecmp(postfile->title, str_forward, 3)) - len=len+4; + title = subject_ex(postfile->title, &title_type); + switch (title_type) { + case SUBJECT_REPLY: + prefix = str_reply; + break; + case SUBJECT_FORWARD: + // is this a real case? + prefix = str_forward; + break; + } memcpy(&fh, postfile, sizeof(fileheader_t)); if(isstamp) { @@ -1088,7 +1113,9 @@ do_crosspost(const char *brd, fileheader_t *postfile, const char *fpath, if(!strcasecmp(brd, BN_UNANONYMOUS)) strcpy(fh.owner, cuser.userid); - sprintf(fh.title,"%-*.*s.%s板", len, len, postfile->title, currboard); + // TODO improve this in future (see log_crosspost_in_allpost) + snprintf(fh.title, sizeof(fh.title), "%s%s%-*.*s.%s板", + prefix, *prefix ? " " : "", len, len, title, currboard); unlink(genbuf); Copy((char *)fpath, genbuf); fh.filemode = FILE_LOCAL; @@ -1999,13 +2026,13 @@ cross_post(int ent, fileheader_t * fhdr, const char *direct) if (ans[0] != 'n') author = '1'; }; - snprintf(xtitle, sizeof(xtitle), "%s%.66s", + snprintf(xtitle, sizeof(xtitle), "%s %.66s", str_forward, subject(fhdr->title)); - snprintf(genbuf, sizeof(genbuf), "採用原標題《%.60s》嗎?[Y] ", xtitle); - getdata(2, 0, genbuf, genbuf2, 4, LCECHO); + mvouts(2, 0, "原標題: "); outs(xtitle); + getdata(3, 0, "採用原標題[Y/n]? ", genbuf2, 3, LCECHO); if (genbuf2[0] == 'n') { - if (getdata_str(2, 0, "標題:", genbuf, TTLEN, DOECHO, xtitle)) + if (getdata_str(3, 0, "新標題:", genbuf, TTLEN, DOECHO, xtitle)) strlcpy(xtitle, genbuf, sizeof(xtitle)); } // FIXME 這裡可能會有人偷偷生出保留標題(如[公告]) diff --git a/pttbbs/mbbsd/mail.c b/pttbbs/mbbsd/mail.c index 78dbb833..475c9060 100644 --- a/pttbbs/mbbsd/mail.c +++ b/pttbbs/mbbsd/mail.c @@ -1123,6 +1123,7 @@ maildoent(int num, fileheader_t * ent) char *title, *mark, *color = NULL, type = ' '; char datepart[6]; char isonline = 0; + int title_type = SUBJECT_NORMAL; if (ent->filemode & FILE_MARKED) { @@ -1143,13 +1144,21 @@ maildoent(int num, fileheader_t * ent) if (FindTaggedItem(ent)) type = 'D'; - title = subject(mark = ent->title); - if (title == mark) { - color = ANSI_COLOR(1;31); - mark = "◇"; - } else { - color = ANSI_COLOR(1;33); - mark = "R:"; + title = subject_ex(ent->title, &title_type); + switch (title_type) { + case SUBJECT_REPLY: + mark = "轉"; + color = ANSI_COLOR(1;36); + break; + case SUBJECT_FORWARD: + mark = "R:"; + color = ANSI_COLOR(1;33); + break; + default: + case SUBJECT_NORMAL: + mark = "◇"; + color = ANSI_COLOR(1;31); + break; } strlcpy(datepart, ent->date, sizeof(datepart)); @@ -1578,14 +1587,15 @@ mail_cross_post(int unused_arg, fileheader_t * fhdr, const char *direct) if (ans[0] != 'n') author = '1'; } - snprintf(xtitle, sizeof(xtitle), "%s%.66s", + snprintf(xtitle, sizeof(xtitle), "%s %.66s", str_forward, fhdr->title); - snprintf(genbuf, sizeof(genbuf), "採用原標題《%.60s》嗎?[Y] ", xtitle); - getdata(2, 0, genbuf, genbuf2, sizeof(genbuf2), LCECHO); - if (*genbuf2 == 'n') - if (getdata(2, 0, "標題:", genbuf, TTLEN, DOECHO)) + mvouts(2, 0, "原標題: "); outs(xtitle); + getdata(3, 0, "採用原標題[Y/n]? ", genbuf2, 3, LCECHO); + if (genbuf2[0] == 'n') { + if (getdata(3, 0, "新標題:", genbuf, TTLEN, DOECHO)) strlcpy(xtitle, genbuf, sizeof(xtitle)); + } getdata(2, 0, "(S)存檔 (L)站內 (Q)取消?[Q] ", genbuf, 3, LCECHO); if (genbuf[0] == 'l' || genbuf[0] == 's') { diff --git a/pttbbs/mbbsd/stuff.c b/pttbbs/mbbsd/stuff.c index 09eb8fee..4e1740b2 100644 --- a/pttbbs/mbbsd/stuff.c +++ b/pttbbs/mbbsd/stuff.c @@ -26,22 +26,48 @@ setbdir(char *buf, const char *boardname) (currmode & MODE_DIGEST ? fn_mandex : str_dotdir)); } +static int * +_set_ptype(int *ptype, int type) { + if (ptype) { + *ptype = type; + } + return NULL; +} + /** * 給定文章標題 title,傳回指到主題的部分的指標。 * @param title */ -char * -subject(char *title) +const char* +subject_ex(const char *title, int *ptype) { - if (strncasecmp(title, str_reply, 3) == 0 || - strncasecmp(title, str_forward, 3) == 0) { - title += 3; - if (*title == ' ') - title++; - } + do { + if (str_starts_with(title, str_reply)) { + title += strlen(str_reply); + ptype = _set_ptype(ptype, SUBJECT_REPLY); + } + else if (str_starts_with(title, str_forward)) { + title += strlen(str_forward); + ptype = _set_ptype(ptype, SUBJECT_FORWARD); + } + else if (str_starts_with(title, str_legacy_forward)) { + title += strlen(str_legacy_forward); + ptype = _set_ptype(ptype, SUBJECT_FORWARD); + } else { + ptype = _set_ptype(ptype, SUBJECT_NORMAL); + break; + } + while (*title == ' ') + title ++; + } while (1); return title; } +const char * +subject(const char *title) { + return subject_ex(title, NULL); +} + int is_uBM(const char *list, const char *id) { diff --git a/pttbbs/mbbsd/var.c b/pttbbs/mbbsd/var.c index 3da09dbe..d5f24d4f 100644 --- a/pttbbs/mbbsd/var.c +++ b/pttbbs/mbbsd/var.c @@ -177,8 +177,9 @@ char * const err_uid = ERR_UID; char * const err_filename = ERR_FILENAME; char * const str_mail_address = "." BBSUSER "@" MYHOSTNAME; -char * const str_reply = "Re: "; -char * const str_forward = "Fw: "; +char * const str_reply = "Re:"; +char * const str_forward = "Fw:"; +char * const str_legacy_forward = "[轉錄]"; char * const str_space = " \t\n\r"; char * const str_sysop = "SYSOP"; char * const str_author1 = STR_AUTHOR1; |