From ae31e19f92e717919ac8e3db9039eb38d2b89aae Mon Sep 17 00:00:00 2001 From: in2 Date: Thu, 7 Mar 2002 15:13:44 +0000 Subject: Initial revision git-svn-id: http://opensvn.csie.org/pttbbs/pttbbs/trunk/pttbbs@1 63ad8ddf-47c3-0310-b6dd-a9e9d9715204 --- mbbsd/read.c | 998 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 998 insertions(+) create mode 100644 mbbsd/read.c (limited to 'mbbsd/read.c') diff --git a/mbbsd/read.c b/mbbsd/read.c new file mode 100644 index 00000000..b92f95e7 --- /dev/null +++ b/mbbsd/read.c @@ -0,0 +1,998 @@ +/* $Id: read.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include +#include +#include +#include +#include +#include +#include +#include +#include "config.h" +#include "pttstruct.h" +#include "modes.h" +#include "common.h" +#include "perm.h" +#include "proto.h" + +#define MAXPATHLEN 256 + +extern int p_lines; /* a Page of Screen line numbers: tlines-4 */ +extern int b_lines; /* Screen bottom line number: t_lines-1 */ +extern char currowner[IDLEN + 2]; +extern char currtitle[44]; +extern char currauthor[IDLEN + 2]; +extern char *str_reply; +extern char *msg_fwd_ok; +extern char *msg_fwd_err1; +extern char *msg_fwd_err2; +extern int currmode; +extern unsigned int currstat; +extern char currboard[]; /* name of currently selected board */ +extern int KEY_ESC_arg; +extern int curredit; +extern char *msg_mailer; +extern int currbid; +extern bcache_t *brdshm; + +char currdirect[64]; +static fileheader_t *headers = NULL; +static int last_line; +static int hit_thread; + +/* rocker.011018: add new tag */ + +extern int rget(); +extern char getans(); +extern void touchdircache(); +extern int get_fileheader_cache(); + +/* rocker.011018: 新的tag方式 */ + +#define MAXTAGS 256 + +#include + +typedef struct +{ + time_t chrono; + int recno; +} TagItem; + + +/* ----------------------------------------------------- */ +/* Tag List 標籤 */ +/* ----------------------------------------------------- */ + + +int TagNum; /* tag's number */ +TagItem TagList[MAXTAGS]; /* ascending list */ + +void +UnTagger (int locus) +{ + if (locus > TagNum) return; + + TagNum--; + + if (TagNum > locus) + memcpy(&TagList[locus], &TagList[locus + 1], + (TagNum - locus) * sizeof(TagItem)); +} + +int +Tagger(time_t chrono, int recno, int mode) +{ + int head, tail, posi = 0, comp; + + for (head = 0, tail = TagNum - 1, comp = 1; head <= tail;) + { + posi = (head + tail) >> 1; + comp = TagList[posi].chrono - chrono; + if (!comp) + { + break; + } + else if (comp < 0) + { + head = posi + 1; + } + else + { + tail = posi - 1; + } + } + + if (mode == TAG_NIN) + { + if (!comp && recno) /* 絕對嚴謹:連 recno 一起比對 */ + comp = recno - TagList[posi].recno; + return comp; + + } + + if (!comp) + { + if (mode != TAG_TOGGLE) + return NA; + + TagNum--; + memcpy(&TagList[posi], &TagList[posi + 1], + (TagNum - posi) * sizeof(TagItem)); + } + else if (TagNum < MAXTAGS) + { + TagItem *tagp, buf[MAXTAGS]; + + tail = (TagNum - head) * sizeof(TagItem); + tagp = &TagList[head]; + memcpy(buf, tagp, tail); + tagp->chrono = chrono; + tagp->recno = recno; + memcpy(++tagp, buf, tail); + TagNum++; + } + else + { + bell(); + return 0; /* full */ + } + return YEA; +} + + +void +EnumTagName( char *fname, int locus) +{ + sprintf(fname, "M.%d.A", (int) TagList[locus].chrono); +} + +void +EnumTagFhdr(fileheader_t *fhdr, char *direct, int locus) +{ + get_record(direct, fhdr, sizeof(fileheader_t), TagList[locus].recno); +} + +/* -1 : 取消 */ +/* 0 : single article */ +/* ow: whole tag list */ + +int +AskTag(char *msg) +{ + char buf[80]; + int num; + + num = TagNum; + sprintf(buf, "◆ %s A)文章 T)標記 Q)uit?", msg); + switch (rget(b_lines-1, buf)) + { + case 'q': + num = -1; + break; + case 'a': + num = 0; + } + return num; +} + + +#include + +#define BATCH_SIZE 65536 + +char * +f_map (char *fpath, int *fsize) +{ + int fd, size; + struct stat st; + + if ((fd = open(fpath, O_RDONLY)) < 0) + return (char *) -1; + + if (fstat(fd, &st) || !S_ISREG(st.st_mode) || (size = st.st_size) <= 0) + { + close(fd); + return (char *) -1; + } + + fpath = (char *) mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); + close(fd); + *fsize = size; + return fpath; +} + + +static int +TagThread(char *direct) +{ + int fsize, count; + char *title, *fimage; + fileheader_t *head, *tail; + + fimage = f_map(direct, &fsize); + if ( fimage == (char *) -1) + return DONOTHING; + + head = (fileheader_t *) fimage; + tail = (fileheader_t *) (fimage + fsize); + count = 0; + do + { + count++; + title = subject(head->title); + if (!strncmp( currtitle, title,TTLEN)) + { + if (!Tagger(atoi (head->filename + 2), count, TAG_INSERT)) + break; + } + } while (++head < tail); + + munmap(fimage, fsize); + return FULLUPDATE; +} + + +int +TagPruner(int bid) +{ + if (TagNum && ((currstat != READING) || (currmode & MODE_BOARD))) + { + if(getans("刪除所有標記[N]?") != 'y') + return FULLUPDATE; + delete_range(currdirect, 0, 0); + TagNum = 0; + if(bid>0); + setbtotal(bid); + return NEWDIRECT; + } + return DONOTHING; +} + + +/* ----------------------------------------------------- */ +/* cursor & reading record position control */ +/* ----------------------------------------------------- */ +keeploc_t *getkeep(char *s, int def_topline, int def_cursline) { + static struct keeploc_t *keeplist = NULL; + struct keeploc_t *p; + void *malloc(); + + if(def_cursline >= 0) + for(p = keeplist; p; p = p->next) { + if(!strcmp(s, p->key)) { + if(p->crs_ln < 1) + p->crs_ln = 1; + return p; + } + } + else + def_cursline = -def_cursline; + p = (keeploc_t *)malloc(sizeof(keeploc_t)); + p->key = (char *)malloc(strlen(s) + 1); + strcpy(p->key, s); + p->top_ln = def_topline; + p->crs_ln = def_cursline; + p->next = keeplist; + return (keeplist = p); +} + +void fixkeep(char *s, int first) { + keeploc_t *k; + + k = getkeep(s, 1, 1); + if(k->crs_ln >= first) { + k->crs_ln = (first == 1 ? 1 : first - 1); + k->top_ln = (first < 11 ? 1 : first - 10); + } +} + +/* calc cursor pos and show cursor correctly */ +static int cursor_pos(keeploc_t *locmem, int val, int from_top) { + int top; + + if(val > last_line) { + bell(); + val = last_line; + } + if(val <= 0) { + bell(); + val = 1; + } + + top = locmem->top_ln; + if(val >= top && val < top + p_lines) { + cursor_clear(3 + locmem->crs_ln - top, 0); + locmem->crs_ln = val; + cursor_show(3 + val - top, 0); + return DONOTHING; + } + locmem->top_ln = val - from_top; + if(locmem->top_ln <= 0) + locmem->top_ln = 1; + locmem->crs_ln = val; + return PARTUPDATE; +} + +static int move_cursor_line(keeploc_t *locmem, int mode) { + int top, crs; + int reload = 0; + + top = locmem->top_ln; + crs = locmem->crs_ln; + if(mode == READ_PREV) { + if(crs <= top) { + top -= p_lines - 1; + if(top < 1) + top = 1; + reload = 1; + } + if(--crs < 1) { + crs = 1; + reload = -1; + } + } else if(mode == READ_NEXT) { + if(crs >= top + p_lines - 1) { + top += p_lines - 1; + reload = 1; + } + if(++crs > last_line) { + crs = last_line; + reload = -1; + } + } + locmem->top_ln = top; + locmem->crs_ln = crs; + return reload; +} + +static int thread(keeploc_t *locmem, int stype) { + static char a_ans[32], t_ans[32]; + char ans[32], s_pmt[64]; + register char *tag, *query = NULL; + register int now, pos, match, near = 0; + fileheader_t fh; + int circulate_flag = 1; /* circulate at end or begin */ + + match = hit_thread = 0; + now = pos = locmem->crs_ln; + if(stype == 'A') { + if(!*currowner) + return DONOTHING; + str_lower(a_ans, currowner); + query = a_ans; + circulate_flag = 0; + stype = 0; + } else if(stype == 'a') { + if(!*currowner) + return DONOTHING; + str_lower(a_ans, currowner); + query = a_ans; + circulate_flag = 0; + stype = RS_FORWARD; + } else if(stype == '/') { + if(!*t_ans) + return DONOTHING; + query = t_ans; + circulate_flag = 0; + stype = RS_TITLE | RS_FORWARD; + } else if(stype == '?') { + if(!*t_ans) + return DONOTHING; + circulate_flag = 0; + query = t_ans; + stype = RS_TITLE; + } else if(stype & RS_RELATED) { + tag = headers[pos - locmem->top_ln].title; + if(stype & RS_CURRENT) { + if(stype & RS_FIRST) { + if(!strncmp(currtitle, tag, 40)) + return DONOTHING; + near = 0; + } + query = currtitle; + } else { + query = subject(tag); + if(stype & RS_FIRST) { + if(query == tag) + return DONOTHING; + near = 0; + } + } + } else if(!(stype & RS_THREAD)) { + query = (stype & RS_TITLE) ? t_ans : a_ans; + if(!*query && query == a_ans) { + if(*currowner) + strcpy(a_ans, currowner); + else if (*currauthor) + strcpy(a_ans, currauthor); + } + sprintf(s_pmt, "%s搜尋%s [%s] ",(stype & RS_FORWARD) ? "往後":"往前", + (stype & RS_TITLE) ? "標題" : "作者", query); + getdata(b_lines - 1, 0, s_pmt, ans, 30, DOECHO); + if(*ans) + strcpy(query, ans); + else if(*query == '\0') + return DONOTHING; + } + + tag = fh.owner; + + do { + if(!circulate_flag || stype & RS_RELATED) { + if(stype & RS_FORWARD) { + if(++now > last_line) + return DONOTHING; + } else { + if(--now <= 0) { + if((stype & RS_FIRST) && (near)) { + hit_thread = 1; + return cursor_pos(locmem, near, 10); + } + return DONOTHING; + } + } + } else { + if(stype & RS_FORWARD) { + if(++now > last_line) + now = 1; + } else if(--now <= 0) + now = last_line; + } + + get_record(currdirect, &fh, sizeof(fileheader_t), now); + + if(fh.owner[0] == '-') + continue; + + if(stype & RS_THREAD) { + if(strncasecmp(fh.title, str_reply, 3)) { + hit_thread = 1; + return cursor_pos(locmem, now, 10); + } + continue; + } + + if(stype & RS_TITLE) + tag = subject(fh.title); + + if(((stype & RS_RELATED) && !strncmp(tag, query, 40)) || + (!(stype & RS_RELATED) && ((query == currowner) ? + !strcmp(tag, query) : + strstr_lower(tag, query)))) { + if((stype & RS_FIRST) && tag != fh.title) { + near = now; + continue; + } + + hit_thread = 1; + match = cursor_pos(locmem, now, 10); + if((!(stype & RS_CURRENT)) && + (stype & RS_RELATED) && + strncmp(currtitle, query, 40)) { + strncpy(currtitle, query, 40); + match = PARTUPDATE; + } + break; + } + } while(now != pos); + + return match; +} + + +#ifdef INTERNET_EMAIL +static void mail_forward(fileheader_t *fhdr, char *direct, int mode) { + int i; + char buf[STRLEN]; + char *p; + + strncpy(buf, direct, sizeof(buf)); + if((p = strrchr(buf, '/'))) + *p = '\0'; + switch(i = doforward(buf, fhdr, mode)) { + case 0: + outmsg(msg_fwd_ok); + break; + case -1: + outmsg(msg_fwd_err1); + break; + case -2: + outmsg(msg_fwd_err2); + break; + default: + break; + } + refresh(); + sleep(1); +} +#endif + +extern userec_t cuser; + +static int select_read(keeploc_t *locmem, int sr_mode) { + register char *tag,*query,*temp; + fileheader_t fh; + char fpath[80], genbuf[MAXPATHLEN], buf3[5]; + char static t_ans[TTLEN+1]=""; + char static a_ans[IDLEN+1]=""; + int fd, fr, size = sizeof(fileheader_t); + struct stat st; +/* rocker.011018: make a reference number for process article */ + int reference = 0; + + if((currmode & MODE_SELECT)) + return -1; + if(sr_mode == RS_TITLE) + query = subject(headers[locmem->crs_ln - locmem->top_ln].title); + else if(sr_mode == RS_NEWPOST) + { + strcpy(buf3, "Re: "); + query = buf3; + } + else + { + char buff[80]; + + query = (sr_mode == RS_RELATED) ? t_ans : a_ans; + sprintf(buff, "搜尋%s [%s] ", + (sr_mode == RS_RELATED) ? "標題" : "作者", query); + getdata(b_lines, 0,buff, query, 30, DOECHO); + if(!(*query)) + return DONOTHING; + } + + if((fd = open(currdirect, O_RDONLY, 0)) != -1) { + sprintf(genbuf,"SR.%s",cuser.userid); + if(currstat==RMAIL) + sethomefile(fpath,cuser.userid,genbuf); + else + setbfile(fpath,currboard,genbuf); + if(((fr = open(fpath,O_WRONLY | O_CREAT | O_TRUNC,0600)) != -1)) { + switch(sr_mode) { + case RS_TITLE: + while(read(fd,&fh,size) == size) { + ++reference; + tag = subject(fh.title); + if(!strncmp(tag, query, 40)) + { + fh.money = reference | FHR_REFERENCE; + write(fr,&fh,size); + } + } + break; + case RS_RELATED: + while(read(fd,&fh,size) == size) { + ++reference; + tag = fh.title; + if(strcasestr(tag,query)) + { + fh.money = reference | FHR_REFERENCE; + write(fr,&fh,size); + } + } + break; + case RS_NEWPOST: + while(read(fd, &fh, size) == size) { + ++reference; + tag = fh.title; + temp = strstr(tag, query); + if(temp == NULL || temp != tag) + { + write(fr, &fh, size); + fh.money = reference | FHR_REFERENCE; + } + } + case RS_AUTHOR: + while(read(fd,&fh,size) == size) { + ++reference; + tag = fh.owner; + if(strcasestr(tag,query)) + { + write(fr,&fh,size); + fh.money = reference | FHR_REFERENCE; + } + } + break; + } + fstat(fr,&st); + close(fr); + } + close(fd); + if(st.st_size) { + currmode |= MODE_SELECT; + strcpy(currdirect,fpath); + } + } + return st.st_size; +} + +extern userec_t xuser; + +static int i_read_key(onekey_t *rcmdlist, keeploc_t *locmem, int ch, int bid) { + int i, mode = DONOTHING; + + switch(ch) { + case 'q': + case 'e': + case KEY_LEFT: + return (currmode & MODE_SELECT) ? board_select() : + (currmode & MODE_ETC) ? board_etc() : + (currmode & MODE_DIGEST) ? board_digest() : DOQUIT; + case Ctrl('L'): + redoscr(); + break; +/* + case Ctrl('C'): + cal(); + return FULLUPDATE; + break; +*/ + case KEY_ESC: + if(KEY_ESC_arg == 'i') { + t_idle(); + return FULLUPDATE; + } + break; + case Ctrl('H'): + if(select_read(locmem, RS_NEWPOST)) + return NEWDIRECT; + else + return READ_REDRAW; + case 'a': + case 'A': + if(select_read(locmem,RS_AUTHOR)) + return NEWDIRECT; + else + return READ_REDRAW; + case '/': + case '?': + if(select_read(locmem,RS_RELATED)) + return NEWDIRECT; + else + return READ_REDRAW; + case 'S': + if(select_read(locmem,RS_TITLE)) + return NEWDIRECT; + else + return READ_REDRAW; + /* quick search title first */ + case '=': + return thread(locmem, RELATE_FIRST); + case '\\': + return thread(locmem, CURSOR_FIRST); + /* quick search title forword */ + case ']': + return thread(locmem, RELATE_NEXT); + case '+': + return thread(locmem, CURSOR_NEXT); + /* quick search title backword */ + case '[': + return thread(locmem, RELATE_PREV); + case '-': + return thread(locmem, CURSOR_PREV); + case '<': + case ',': + return thread(locmem, THREAD_PREV); + case '.': + case '>': + return thread(locmem, THREAD_NEXT); + case 'p': + case 'k': + case KEY_UP: + return cursor_pos(locmem, locmem->crs_ln - 1, p_lines - 2); + case 'n': + case 'j': + case KEY_DOWN: + return cursor_pos(locmem, locmem->crs_ln + 1, 1); + case ' ': + case KEY_PGDN: + case 'N': + case Ctrl('F'): + if(last_line >= locmem->top_ln + p_lines) { + if(last_line > locmem->top_ln + p_lines) + locmem->top_ln += p_lines; + else + locmem->top_ln += p_lines - 1; + locmem->crs_ln = locmem->top_ln; + return PARTUPDATE; + } + cursor_clear(3 + locmem->crs_ln - locmem->top_ln, 0); + locmem->crs_ln = last_line; + cursor_show(3 + locmem->crs_ln - locmem->top_ln, 0); + break; + case KEY_PGUP: + case Ctrl('B'): + case 'P': + if(locmem->top_ln > 1) { + locmem->top_ln -= p_lines; + if(locmem->top_ln <= 0) + locmem->top_ln = 1; + locmem->crs_ln = locmem->top_ln; + return PARTUPDATE; + } + break; + case KEY_END: + case '$': + if(last_line >= locmem->top_ln + p_lines) { + locmem->top_ln = last_line - p_lines + 1; + if(locmem->top_ln <= 0) + locmem->top_ln = 1; + locmem->crs_ln = last_line; + return PARTUPDATE; + } + cursor_clear(3 + locmem->crs_ln - locmem->top_ln, 0); + locmem->crs_ln = last_line; + cursor_show(3 + locmem->crs_ln - locmem->top_ln, 0); + break; + case 'F': + case 'U': + if(HAS_PERM(PERM_FORWARD)) { + mail_forward(&headers[locmem->crs_ln - locmem->top_ln], + currdirect, ch /*== 'U'*/); + /*by CharlieL*/ + return FULLUPDATE; + } + break; + case Ctrl('Q'): + return my_query(headers[locmem->crs_ln - locmem->top_ln].owner); + case Ctrl('S'): + if(HAS_PERM(PERM_ACCOUNTS)) { + int id; + userec_t muser; + + strcpy(currauthor, headers[locmem->crs_ln - locmem->top_ln].owner); + stand_title("使用者設定"); + move(1, 0); + if((id = getuser(headers[locmem->crs_ln - locmem->top_ln].owner))){ + memcpy(&muser, &xuser, sizeof(muser)); + user_display(&muser, 1); + uinfo_query(&muser, 1, id); + } + return FULLUPDATE; + } + break; + +/* rocker.011018: 採用新的tag模式 */ + case 't': +/* rocker.011112: 解決再select mode標記文章的問題 */ + if (Tagger(atoi(headers[locmem->crs_ln - locmem->top_ln].filename + 2), + (currmode & MODE_SELECT) ? + (headers[locmem->crs_ln - locmem->top_ln].money & ~FHR_REFERENCE) : + locmem->crs_ln, TAG_TOGGLE)) + return POS_NEXT; + return DONOTHING; + + case Ctrl('C'): + if (TagNum) + { + TagNum = 0; + return FULLUPDATE; + } + return DONOTHING; + + case Ctrl('T'): + return TagThread(currdirect); + case Ctrl('D'): + return TagPruner(bid); + case '\n': + case '\r': + case 'l': + case KEY_RIGHT: + ch = 'r'; + default: + for(i = 0; rcmdlist[i].fptr; i++) { + if(rcmdlist[i].key == ch) { + mode = (*(rcmdlist[i].fptr))(locmem->crs_ln, + &headers[locmem->crs_ln - + locmem->top_ln], currdirect); + break; + } + if(rcmdlist[i].key == 'h') + if(currmode & (MODE_ETC | MODE_DIGEST)) + return DONOTHING; + } + } + return mode; +} + +void i_read(int cmdmode, char *direct, void (*dotitle)(), void (*doentry)(), onekey_t *rcmdlist, int bidcache) { + keeploc_t *locmem = NULL; + int recbase = 0, mode, ch; + int num = 0, entries = 0; + int i; + int jump = 0; + char genbuf[4]; + char currdirect0[64]; + int last_line0 = last_line; + int hit_thread0 = hit_thread; + fileheader_t *headers0 = headers; + + strcpy(currdirect0 ,currdirect); +#define FHSZ sizeof(fileheader_t) +// Ptt:這邊headers 可以針對看板的最後60篇做cache + headers = (fileheader_t *)calloc(p_lines, FHSZ); + strcpy(currdirect, direct); + mode = NEWDIRECT; + +/* rocker.011018: 加入新的tag機制 */ + TagNum = 0; + + do { + /* 依據 mode 顯示 fileheader */ + setutmpmode(cmdmode); + switch(mode) { + case NEWDIRECT: /* 第一次載入此目錄 */ + case DIRCHANGED: + if(bidcache>0 && !(currmode & (MODE_SELECT| MODE_DIGEST)) ) + last_line=getbtotal(currbid); + else + last_line= get_num_records(currdirect, FHSZ); + + if(mode == NEWDIRECT) { + if(last_line == 0) { + if(curredit & EDIT_ITEM) { + outs("沒有物品"); + refresh(); + goto return_i_read; + } else if(curredit & EDIT_MAIL) { + outs("沒有來信"); + refresh(); + goto return_i_read; + } else if(currmode & MODE_ETC) { + board_etc(); /* Kaede */ + outmsg("尚未收錄其它文章"); + refresh(); + } else if(currmode & MODE_DIGEST) { + board_digest(); /* Kaede */ + outmsg("尚未收錄文摘"); + refresh(); + } else if(currmode & MODE_SELECT) { + board_select(); /* Leeym */ + outmsg("沒有此系列的文章"); + refresh(); + } else { + getdata(b_lines - 1, 0, + "看板新成立 (P)發表文章 (Q)離開?[Q] ", + genbuf, 4, LCECHO); + if(genbuf[0] == 'p') + do_post(); + goto return_i_read; + } + } + num = last_line - p_lines + 1; + locmem = getkeep(currdirect, num < 1 ? 1 : num, last_line); + } + recbase = -1; + + case FULLUPDATE: + (*dotitle)(); + + case PARTUPDATE: + if(last_line < locmem->top_ln + p_lines) { + if(bidcache>0 && !(currmode & (MODE_SELECT| MODE_DIGEST))) + num=getbtotal(currbid); + else + num = get_num_records(currdirect, FHSZ); + + if(last_line != num) { + last_line = num; + recbase = -1; + } + } + + if(last_line == 0) + goto return_i_read; + else if(recbase != locmem->top_ln) { + recbase = locmem->top_ln; + if(recbase > last_line) { + recbase = (last_line - p_lines) >> 1; + if(recbase < 1) + recbase = 1; + locmem->top_ln = recbase; + } + if(bidcache>0 && !(currmode & (MODE_SELECT| MODE_DIGEST)) + && (last_line - recbase) < DIRCACHESIZE ) + entries = get_fileheader_cache(currbid, currdirect, headers, + recbase, p_lines); + else + entries = get_records(currdirect, headers, FHSZ, recbase, + p_lines); + } + if(locmem->crs_ln > last_line) + locmem->crs_ln = last_line; + move(3, 0); + clrtobot(); + case PART_REDRAW: + move(3, 0); + for (i = 0; i < entries; i++) + (*doentry) (locmem->top_ln + i, &headers[i]); + case READ_REDRAW: + outmsg(curredit & EDIT_ITEM ? + "\033[44m 私人收藏 \033[30;47m 繼續? \033[m" : + curredit & EDIT_MAIL ? msg_mailer : MSG_POSTER); + break; + case READ_PREV: + case READ_NEXT: + case RELATE_PREV: + case RELATE_NEXT: + case RELATE_FIRST: + case POS_NEXT: + case 'A': + case 'a': + case '/': + case '?': + jump = 1; + break; + } + + /* 讀取鍵盤,加以處理,設定 mode */ + if(!jump) { + cursor_show(3 + locmem->crs_ln - locmem->top_ln, 0); + ch = egetch(); + mode = DONOTHING; + } else + ch = ' '; + + if(mode == POS_NEXT) { + mode = cursor_pos(locmem, locmem->crs_ln + 1, 1); + if(mode == DONOTHING) + mode = PART_REDRAW; + jump = 0; + } else if(ch >= '0' && ch <= '9') { + if((i = search_num(ch, last_line)) != -1) + mode = cursor_pos(locmem, i + 1, 10); + } else { + if(!jump) + mode = i_read_key(rcmdlist, locmem, ch, currbid); + while(mode == READ_NEXT || mode == READ_PREV || + mode == RELATE_FIRST || mode == RELATE_NEXT || + mode == RELATE_PREV || mode == THREAD_NEXT || + mode == THREAD_PREV || mode == 'A' || mode == 'a' || + mode == '/' || mode == '?') { + int reload; + + if(mode == READ_NEXT || mode == READ_PREV) + reload = move_cursor_line(locmem, mode); + else { + reload = thread(locmem, mode); + if(!hit_thread) { + mode = FULLUPDATE; + break; + } + } + + if(reload == -1) { + mode = FULLUPDATE; + break; + } else if(reload) { + recbase = locmem->top_ln; + + if(bidcache>0 && !(currmode &(MODE_SELECT| MODE_DIGEST)) + && last_line-recbasecrs_ln - locmem->top_ln; + if(headers[num].owner[0] != '-') + mode = i_read_key(rcmdlist, locmem, ch, bidcache); + } + } + } while(mode != DOQUIT); +#undef FHSZ + + return_i_read: + free(headers); + last_line = last_line0; + hit_thread = hit_thread0; + headers = headers0; + strcpy(currdirect ,currdirect0); + return; +} -- cgit v1.2.3