From 3ae2a44051030c455f61a7458510545e18d62509 Mon Sep 17 00:00:00 2001 From: victor Date: Thu, 4 Sep 2003 07:50:16 +0000 Subject: init of the fav4 git-svn-id: http://opensvn.csie.org/pttbbs/branches/victor.bank@1154 63ad8ddf-47c3-0310-b6dd-a9e9d9715204 --- pttbbs/include/bbs.h | 1 + pttbbs/include/fav.h | 54 ++++ pttbbs/include/proto.h | 70 +++-- pttbbs/mbbsd/Makefile | 2 +- pttbbs/mbbsd/board.c | 435 ++++++-------------------- pttbbs/mbbsd/fav.c | 833 +++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 1024 insertions(+), 371 deletions(-) create mode 100644 pttbbs/include/fav.h create mode 100644 pttbbs/mbbsd/fav.c diff --git a/pttbbs/include/bbs.h b/pttbbs/include/bbs.h index 666d30c7..60e20301 100644 --- a/pttbbs/include/bbs.h +++ b/pttbbs/include/bbs.h @@ -57,6 +57,7 @@ /* our header */ #include "config.h" #include "pttstruct.h" +#include "fav.h" #include "common.h" #include "perm.h" #include "modes.h" diff --git a/pttbbs/include/fav.h b/pttbbs/include/fav.h new file mode 100644 index 00000000..f108b74d --- /dev/null +++ b/pttbbs/include/fav.h @@ -0,0 +1,54 @@ + +#define FAVT_BOARD 1 +#define FAVT_FOLDER 2 +#define FAVT_LINE 3 + +#define FAVH_FAV 1 +#define FAVH_TAG 2 +#define FAVH_UNREAD 4 + +#define TRUE 1 +#define FALSE 0 + +#define ALLOC_NUM 8 +#define FAV_MAXDEPTH 5 +#define MAX_FAV 1024 +#define MAX_LINE 32 +#define MAX_FOLDER 32 + +#define FAV3 ".fav3" +#define FAV4 ".fav4" + +typedef struct { + char type; + char attr; + /* *fp could be *fav_board_t or *fav_folder_t. */ + void *fp; +} fav_type_t; + +typedef struct { + short nAllocs; + short nDatas; + short nBoards; + char nLines; + char nFolders; + + /* record of boards/folders */ + fav_type_t *favh; +} fav_t; + +typedef struct { + short bid; + time_t lastvisit; + char attr; +} fav_board_t; + +typedef struct { + char fid; + char title[BTLEN + 1]; + fav_t *this_folder; +} fav_folder_t; + +typedef struct { + char lid; +} fav_line_t; diff --git a/pttbbs/include/proto.h b/pttbbs/include/proto.h index e11528a2..924fda9c 100644 --- a/pttbbs/include/proto.h +++ b/pttbbs/include/proto.h @@ -72,6 +72,7 @@ int Boards(); int root_board(); void save_brdbuf(void); void init_brdbuf(void); +int validboard(int bid); #ifdef CRITICAL_MEMORY void sigfree(int); #endif @@ -164,38 +165,12 @@ int card_99(); /* chat */ int t_chat(); -/* chc_draw */ -char *getstep(board_t board, rc_t *from, rc_t *to); -void chc_drawline(board_t board, chcusr_t *user1, chcusr_t *user2, int line); -void chc_movecur(int r, int c); -void chc_redraw(chcusr_t *user1, chcusr_t *user2, board_t board); - -/* chc_log */ -int chc_log_open(chcusr_t *user1, chcusr_t *user2, char *file); -int chc_log(char *step); -void chc_log_close(void); -int chc_log_step(board_t board, rc_t *from, rc_t *to); -int chc_log_poem(void); - -/* chc_net */ -//void chc_sendmove(int s); -//int chc_recvmove(int s); -int chc_broadcast_recv(chc_act_list *act_list, board_t board); -void chc_broadcast_send(chc_act_list *act_list, board_t board); - -/* chc_play */ +/* chc */ void chc(int s, int mode); int chc_main(void); int chc_personal(void); int chc_watch(void); -/* chc_rule */ -void chc_movechess(board_t board); -int chc_canmove(board_t board, rc_t from, rc_t to); -int chc_iskfk(board_t board); -int chc_ischeck(board_t board, int turn); -void chc_init_board(board_t board); - /* chicken */ int show_file(char *filename, int y, int lines, int mode); void ch_buyitem(int money, char *picture, int *item, int haveticket); @@ -226,6 +201,43 @@ void editlock(char *fpath); void editunlock(char *fpath); int iseditlocking(char *fpath, char *action); +/* fav */ +fav_type_t *get_current_entry(void); +void fav_set_old_folder(fav_t *fp); +fav_t *get_current_fav(void); +void set_attr(fav_type_t *ft, int bit, int bool); +void fav_sort_by_name(void); +void fav_sort_by_class(void); +int fav_load(void); +int fav_save(void); +void fav_remove_current(void); +void fav_remove_board_from_whole(int bid); +char getbrdattr(short bid); +time_t getbrdtime(short bid); +void setbrdtime(short bid, time_t t); +int fav_getid(fav_type_t *ft); +int fav_add(fav_t *fp, fav_type_t *item); +void move_in_current_folder(int from, int to); +void fav_move(int from, int to); +void fav_set_current_old(void); +int fav_add_line(int place); +int fav_add_folder(int place); +int fav_add_board(int bid, int place); +void fav_tag_current(int bool); +void fav_remove_tagged_item(fav_t *fp); +void fav_add_tagged_item(fav_t *fp); +void fav_remove_all_tagged_item(void); +void fav_remove_all_tagged_item(void); +void fav_add_all_tagged_item(void); +void fav_remove_all_tag(void); +void fav_set_folder_title(char *title); +void fav_folder_in(void); +void fav_folder_out(void); +void fav_cursor_up(void); +void fav_cursor_down(void); +void fav_free(void); +int fav_v3_to_v4(void); + /* friend */ void friend_edit(int type); void friend_load(); @@ -244,10 +256,6 @@ int ticket(int bid); /* gomo */ int gomoku(int fd); -/* gomo1 */ -int getstyle(int x, int y, int color, int limit); -int chkwin(int style, int limit); - /* guess */ int guess_main(); diff --git a/pttbbs/mbbsd/Makefile b/pttbbs/mbbsd/Makefile index 6ca797e6..1d0851ce 100644 --- a/pttbbs/mbbsd/Makefile +++ b/pttbbs/mbbsd/Makefile @@ -9,7 +9,7 @@ LDFLAGS+= -L/usr/local/lib/mysql -lmysqlclient PROG= mbbsd OBJS= admin.o announce.o args.o bbs.o board.o cache.o cal.o card.o\ - chat.o chc.o chicken.o dark.o edit.o friend.o gamble.o gomo.o\ + chat.o chc.o chicken.o dark.o edit.o fav.o friend.o gamble.o gomo.o\ guess.o indict.o io.o kaede.o lovepaper.o mail.o mbbsd.o menu.o\ more.o name.o osdep.o othello.o page.o read.o record.o\ register.o screen.o stuff.o talk.o term.o topsong.o user.o\ diff --git a/pttbbs/mbbsd/board.c b/pttbbs/mbbsd/board.c index eb6a13d4..cac6d6c6 100644 --- a/pttbbs/mbbsd/board.c +++ b/pttbbs/mbbsd/board.c @@ -230,17 +230,15 @@ brc_unread(const char *fname, int bnum, const int *blist) return 0; } -#define BRD_UNREAD 1 -#define BRD_FAV 2 +#define BRD_FAV 1 +#define BRD_BOARD 2 #define BRD_LINE 4 -#define BRD_TAG 8 -#define BRD_GRP_HEADER 16 - -#define MAX_GRP_BRD 16 -#define MAX_GRP +#define BRD_FOLDER 8 +#define BRD_TAG 16 +#define BRD_UNREAD 32 #define FAVNB ".favnb" -#define FAV3 ".fav3" +//#define FAV3 ".fav3" #define B_TOTAL(bptr) (SHM->total[(bptr)->bid - 1]) #define B_LASTPOSTTIME(bptr) (SHM->lastposttime[(bptr)->bid - 1]) @@ -250,28 +248,12 @@ typedef struct { unsigned char myattr; } __attribute__ ((packed)) boardstat_t; -typedef struct { - short bid; - char attr; - time_t lastvisit; -} fav_board_t; - -typedef struct { -#ifdef MEM_CHECK - int memcheck; -#endif - short nDatas; - short nAllocs; - char nLines; - fav_board_t b[0]; -} fav_t; - static boardstat_t *nbrd = NULL; -char favchange = 0, choose_board_depth = 0; -fav_t *fav; +static char choose_board_depth = 0; static short brdnum; static char yank_flag = 1; +//NEWFAV int cmpfav(const void *a, const void *b) { if( *(short *)a > ((fav_board_t *)b)->bid ) @@ -281,131 +263,6 @@ int cmpfav(const void *a, const void *b) return -1; } -fav_board_t *getfav(short bid) -{ - int i; - for(i = 0; i < fav->nDatas; i++) - if(fav->b[i].bid == bid) - break; - return i == fav->nDatas ? NULL : &fav->b[i]; -} - -char getfavattr(short bid) -{ - fav_board_t *ptr = getfav(bid); - if( ptr == NULL ) - return 0; // default here - else - return ptr->attr; -} - -time_t getfavtime(short bid) -{ - fav_board_t *ptr = getfav(bid); - if( ptr == NULL ) - return login_start_time; // default here - else - return ptr->lastvisit; -} - -void basemovefav(int src, int des) -{ - int i; - fav_board_t tmp = fav->b[src]; - - if(src < des){ - for(i = src; i < des; i++) - fav->b[i] = fav->b[i + 1]; - } - else{ // des < src - for(i = src; i > des; i--) - fav->b[i] = fav->b[i - 1]; - } - fav->b[des] = tmp; - - brdnum = -1; -} - -void movefav(int old, int new) -{ - int i, src = -1, des = -1; - favchange = 1; - - for(i = 0; i < fav->nDatas; i++){ - if(nbrd[old].bid == fav->b[i].bid) - src = i; - if(nbrd[new].bid == fav->b[i].bid) - des = i; - } - - if(src == -1 || des == -1) - return; - basemovefav(src, des); -} - -void delfavline(int bid, int num) -{ - int i; - - movefav(num, --brdnum); - fav->nLines++; - fav->nDatas--; - - for(i = 0; i < fav->nDatas; i++) - if(fav->b[i].bid < bid) - fav->b[i].bid++; - for(i = 0; i < brdnum; i++) - if(nbrd[i].bid < bid) - nbrd[i].bid++; -} - -void setfav(short bid, char attr, char mode, time_t t) -{ - /* mode: 0: 設成 off, 1: 設成 on, 2: 反相 */ - fav_board_t *ptr = getfav(bid); - - favchange = 1; - - if( ptr != NULL ){ - if( mode == 2 ) - ptr->attr ^= attr; - else if( mode ) - ptr->attr |= attr; - else - ptr->attr &= ~attr; - if( t ) - ptr->lastvisit = t; - } - else{ - int where; - if( fav->nDatas == fav->nAllocs ){ -#ifdef DEBUG - vmsg("realloc fav"); -#endif - fav = realloc(fav, - sizeof(fav_t) + - sizeof(fav_board_t) * - (16 + fav->nAllocs)); - memset(&fav->b[fav->nDatas], 0, sizeof(fav_board_t) * 16); - fav->nAllocs += 16; - } - - where = fav->nDatas; - - if( attr & BRD_LINE ){ - fav->b[where].bid = --(fav->nLines); - fav->b[where].attr = mode ? (BRD_LINE | BRD_FAV) : 0; - } - else{ - fav->b[where].bid = bid ; - fav->b[where].attr = mode ? attr : 0; - } - - fav->b[where].lastvisit = t ? t : login_start_time; - fav->nDatas++; - } -} - void imovefav(int old) { char buf[5]; @@ -417,7 +274,7 @@ void imovefav(int old) vmsg("輸入範圍有誤!"); return; } - movefav(old, new); + move_in_current_folder(old, new); } #define BRD_OLD 0 @@ -444,7 +301,7 @@ void updatenewfav(int mode) if(brd[i] == BRD_NEW){ if(bcache[i].brdname[0] && Ben_Perm(&bcache[i])){ // check the permission if the board exsits if(mode) - setfav(i + 1, BRD_FAV, 1, 0); + fav_add_board(i + 1, -1); brd[i] = BRD_OLD; } } @@ -457,7 +314,7 @@ void updatenewfav(int mode) for(i-- ; i < numboards; i++){ if(bcache[i].brdname[0] && Ben_Perm(&bcache[i])){ if(mode) - setfav(i + 1, BRD_FAV, 1, 0); + fav_add_board(i + 1, -1); brd[i] = BRD_OLD; } else @@ -473,25 +330,8 @@ void updatenewfav(int mode) } } -void favclean(fav_t *fav){ - int i; - boardheader_t *bptr; - - for(i = 0; i < fav->nDatas; i++){ - if(fav->b[i].attr & BRD_LINE) - continue; - bptr = &bcache[ fav->b[i].bid - 1 ]; - if(!(fav->b[i].attr & BRD_FAV) || !Ben_Perm(bptr)){ - basemovefav(i, fav->nDatas--); - continue; - } - } -} - -void freefav(fav_t *fav){ - free(fav->b); - free(fav); - fav = NULL; +inline int validboard(int bid){ + return bcache[bid].brdname[0]; } void load_brdbuf(void) @@ -500,51 +340,12 @@ void load_brdbuf(void) int fd; char fname[80]; - setuserfile(fname, FAV3); + setuserfile(fname, FAV4); if( (fd = open(fname, O_RDONLY)) == -1 ){ - // not found. - int i; - char favrec; - fav = (fav_t *)malloc(sizeof(fav_t) + - sizeof(fav_board_t) * 16); - fav->nDatas = 0; - fav->nAllocs = 16; - fav->nLines = 0; - favchange = 1; - - setuserfile(fname, ".fav2"); - - if( (fd = open(fname, O_RDONLY)) != -1 ){ - for( i = 1; i <= numboards; i++){ - if(read(fd, &favrec, sizeof(char)) < 0) - break; - if( (favrec & BRD_FAV) ) - setfav(i, BRD_FAV, 1, 0); - } - close(fd); - } - } - else{ - short nDatas, i; - char nLines; - read(fd, &nDatas, sizeof(nDatas)); - read(fd, &nLines, sizeof(nLines)); - fav = (fav_t *)malloc(sizeof(fav_t) + - sizeof(fav_board_t) * (nDatas + 16)); - fav->nDatas = nDatas; - fav->nAllocs = nDatas + 16; - fav->nLines = nLines; - read(fd, fav->b, sizeof(fav_board_t) * fav->nDatas); - for(i = 0; i < fav->nDatas; i++){ - if( !(fav->b[i].attr & BRD_LINE) && !bcache[fav->b[i].bid - 1].brdname[0]) - fav->b[i].attr ^= BRD_FAV; - } - close(fd); + fav_v3_to_v4(); } + fav_load(); updatenewfav(1); -#ifdef MEM_CHECK - fav->memcheck = MEM_CHECK; -#endif firsttime = 0; } @@ -557,40 +358,8 @@ init_brdbuf() void save_brdbuf(void) { - int r, w, fd; - char fname[80]; - if( !fav ) - return; - - if( !favchange ) - return; - -#ifdef MEM_CHECK - if( fav->memcheck != MEM_CHECK ) - return; -#endif - - fav->nLines = 0; - for( r = w = 0 ; r < fav->nDatas ; ++r ){ - if( ( fav->b[r].attr & BRD_LINE ) || - (fav->b[r].attr & BRD_FAV && bcache[fav->b[r].bid - 1].brdname[0])){ - if(fav->b[r].attr & BRD_LINE) - fav->nLines--; - fav->b[w++] = fav->b[r]; - } - } - fav->nDatas = w; - setuserfile(fname, FAV3); - if( (fd = open(fname, O_WRONLY | O_CREAT | O_TRUNC, 0600)) != -1 ){ - int i; - write(fd, &fav->nDatas, sizeof(short)); - write(fd, &fav->nLines, sizeof(char)); - for(i = 0; i < fav->nDatas; i++) - if(fav->b[i].attr & BRD_FAV) - write(fd, &fav->b[i], sizeof(fav_board_t)); - close(fd); - } - freefav(fav); + fav_save(); + fav_free(); } int @@ -720,7 +489,7 @@ addnewbrdstat(int n, int state) //ptr->lastposttime = &(SHM->lastposttime[n]); ptr->bid = n + 1; - ptr->myattr = getfavattr(ptr->bid); + ptr->myattr = getbrdattr(ptr->bid); if ((B_BH(ptr)->brdattr & BRD_HIDE) && state == 1) B_BH(ptr)->brdattr |= BRD_POSTMASK; check_newpost(ptr); @@ -734,35 +503,6 @@ cmpboardfriends(const void *brd, const void *tmp) (B_BH((boardstat_t*)brd)->nuser)); } -static int -favcmpboardname(const void *brd, const void *tmp) -{ - int b1 = ((fav_board_t *)brd)->bid; - int b2 = ((fav_board_t *)tmp)->bid; - - if( b1 <= 0 || b2 <= 0 ) // 分隔線 - return 1; - - return strcasecmp(bcache[b1 - 1].brdname, bcache[b2 - 1].brdname); -} - -static int -favcmpboardclass(const void *brd, const void *tmp) -{ - int b1 = ((fav_board_t *)brd)->bid; - int b2 = ((fav_board_t *)tmp)->bid; - int cmp; - - if( b1 <= 0 || b2 <= 0 ) // 分隔線 - return 1; - - cmp = strncasecmp(bcache[b1 - 1].title, bcache[b2 - 1].title, 4); - if( cmp ) - return cmp; - else - return strcasecmp(bcache[b1 - 1].brdname, bcache[b2 - 1].brdname); -} - static void load_boards(char *key) { @@ -784,16 +524,25 @@ load_boards(char *key) } if (class_bid <= 0) { if( yank_flag == 0 ){ // fav mode + fav_t *fav = get_current_fav(); + nbrd = (boardstat_t *)malloc(sizeof(boardstat_t) * fav->nDatas); for( i = 0 ; i < fav->nDatas ; ++i ){ - if( fav->b[i].attr & BRD_FAV ){ - if( fav->b[i].attr & BRD_LINE && !key[0]) - addnewbrdstat(fav->b[i].bid - 1, BRD_FAV | BRD_LINE); + if( fav->favh[i].attr & BRD_FAV ){ + int state; + + if( fav->favh[i].attr & BRD_LINE && !key[0]) + state = BRD_LINE; + else if( fav->favh[i].attr & BRD_FOLDER && !key[0]) + state = BRD_FOLDER; else{ - bptr = &bcache[ fav->b[i].bid - 1 ]; + bptr = &bcache[ fav_getid(&fav->favh[i]) - 1]; if( (state = Ben_Perm(bptr)) && (!key[0] || strcasestr(bptr->title, key))) - addnewbrdstat(fav->b[i].bid - 1, state); + state = BRD_BOARD; + else + continue; } + addnewbrdstat(fav_getid(&fav->favh[i] - 1), BRD_FAV | BRD_LINE); } } byMALLOC = 0; @@ -830,7 +579,7 @@ load_boards(char *key) bptr = bptr->next[type]) { n = (int)(bptr - bcache); if (!((state = Ben_Perm(bptr)) || (currmode & MODE_MENU)) - || (yank_flag == 0 && !(getfavattr(n) & BRD_FAV)) || + || (yank_flag == 0 && !(getbrdattr(n) & BRD_FAV)) || (key[0] && !strcasestr(bptr->title, key))) continue; addnewbrdstat(n, state); @@ -972,6 +721,10 @@ show_brdlist(int head, int clsflag, int newflag) prints("%5d %c ------------ ------------------------------------------", head, ptr->myattr & BRD_TAG ? 'D' : ' '); continue; } + else if (ptr->myattr & BRD_FOLDER){ + prints("%s%5d %c --- DIR ---- -------- BRD_FOLDER ----------------------\033[m", ptr->myattr & BRD_FAV ? "" : "\033[1;30m", head, ptr->myattr & BRD_TAG ? 'D' : ' '); + continue; + } if (class_bid == 1) prints(" "); if (!newflag) { @@ -1070,7 +823,7 @@ choose_board(int newflag) char keyword[13] = ""; setutmpmode(newflag ? READNEW : READBRD); - if( fav == NULL ) + if( get_current_fav() == NULL ) load_brdbuf(); ++choose_board_depth; brdnum = 0; @@ -1146,6 +899,7 @@ choose_board(int newflag) keyword[0] = 0; brdnum = -1; ch = ' '; + fav_folder_out(); } break; case 'c': @@ -1183,17 +937,19 @@ choose_board(int newflag) case KEY_UP: case 'p': case 'k': + fav_cursor_up(); if (num-- <= 0) num = brdnum - 1; break; case 't': ptr = &nbrd[num]; - setfav(ptr->bid, BRD_TAG, 2, 0); + fav_tag_current(2); ptr->myattr ^= BRD_TAG; head = 9999; case KEY_DOWN: case 'n': case 'j': + fav_cursor_down(); if (++num < brdnum) break; case '0': @@ -1240,15 +996,12 @@ choose_board(int newflag) "排序方式 (1)按照板名排序 (2)按照類別排序 ==> [0]取消 ", input, sizeof(input), DOECHO); if( input[0] == '1' ) - qsort(&fav->b, fav->nDatas, sizeof(fav_board_t), - favcmpboardname); + fav_sort_by_name(); else if( input[0] == '2' ) - qsort(&fav->b, fav->nDatas, sizeof(fav_board_t), - favcmpboardclass); + fav_sort_by_class(); } else cuser.uflag ^= BRDSORT_FLAG; - favchange = 1; brdnum = -1; break; case 'y': @@ -1256,45 +1009,30 @@ choose_board(int newflag) brdnum = -1; break; case Ctrl('D'): - for (tmp = 0; tmp < fav->nDatas; tmp++) { - if (fav->b[tmp].attr & BRD_TAG) { - favchange = 1; - fav->b[tmp].attr &= ~BRD_FAV; - fav->b[tmp].attr &= ~BRD_TAG; - } - } + fav_remove_tagged_item(get_current_fav()); brdnum = -1; break; case Ctrl('A'): - for (tmp = 0; tmp < fav->nDatas; tmp++) { - if (fav->b[tmp].attr & BRD_TAG) { - favchange = 1; - fav->b[tmp].attr |= BRD_FAV; - fav->b[tmp].attr &= ~BRD_TAG; - } - } + fav_add_all_tagged_item(); brdnum = -1; break; case Ctrl('T'): - for (tmp = 0; tmp < fav->nDatas; tmp++) - fav->b[tmp].attr &= ~BRD_TAG; - favchange = 1; + fav_remove_all_tag(); brdnum = -1; break; case Ctrl('P'): if (class_bid != 0 && (HAS_PERM(PERM_SYSOP) || (currmode & MODE_MENU))) { - for (tmp = 0; tmp < fav->nDatas; tmp++) { - short bid = fav->b[tmp].bid; + for (tmp = 0; tmp < brdnum; tmp++) { + short bid = nbrd[tmp].bid; boardheader_t *bh = &bcache[ bid - 1 ]; /* if (!(fav->b[tmp].attr & BRD_TAG) || bh->gid == class_bid) continue; */ - if( !(fav->b[tmp].attr & BRD_TAG) ) + if( !(nbrd[tmp].myattr & BRD_TAG) ) continue; - favchange = 1; - fav->b[tmp].attr &= ~BRD_TAG; + nbrd[tmp].myattr &= ~BRD_TAG; if (bh->gid != class_bid) { bh->gid = class_bid; substitute_record(FN_BOARD, bh, @@ -1308,41 +1046,57 @@ choose_board(int newflag) break; case 'L': if (HAS_PERM(PERM_BASIC)) { - if(fav->nDatas > FAVMAX || fav->nLines <= -127){ + if(fav_add_line(brdnum) < 0){ vmsg("你的最愛太多了啦 真花心"); break; } - setfav(0, BRD_FAV | BRD_LINE, 1, 0); - nbrd[brdnum].bid = fav->nLines; - movefav(brdnum, num); brdnum = -1; head = 9999; } break; case 'm': if (HAS_PERM(PERM_BASIC)) { - if(nbrd[num].myattr & BRD_LINE){ - delfavline(nbrd[num].bid, num); - brdnum = -1; - } - else if(!(nbrd[num].myattr & BRD_FAV) && (fav->nDatas > FAVMAX)){ - vmsg("你的最愛太多了啦 真花心"); + if (yank_flag == 0) { + if (num > brdnum) + break; + if (nbrd[num].myattr & BRD_LINE){ + fav_remove_current(); + brdnum = -1; + } + else{ + set_attr(get_current_entry(), BRD_FAV, 2); + } break; } else{ - setfav(nbrd[num].bid, BRD_FAV, 2, 0); + if (nbrd[num].myattr & BRD_FAV){ + fav_remove_current(); + } + else{ + if (fav_add_board(nbrd[num].bid, -1) < 0) + vmsg("你的最愛太多了啦 真花心"); + } nbrd[num].myattr ^= BRD_FAV; } head = 9999; } break; case 'M': - if (HAS_PERM(PERM_BASIC) && class_bid == 0 && yank_flag == 0){ - imovefav(num); - head = 9999; + if (HAS_PERM(PERM_BASIC)){ + if (class_bid == 0 && yank_flag == 0){ + imovefav(num); + brdnum = -1; + head = 9999; + } + } + break; + case 'g': + if (HAS_PERM(PERM_BASIC)) { + fav_add_folder(num); + fav_set_folder_title("新的目錄"); } break; - case 'K': + case 'K': //NEWFAV if (HAS_PERM(PERM_BASIC)) { char c, fname[80], genbuf[256]; int fd; @@ -1353,10 +1107,10 @@ choose_board(int newflag) break; switch(c){ case '1': - favclean(fav); + //favclean(fav); break; case '2': - setuserfile(fname, FAV3); + setuserfile(fname, FAV4); sprintf(genbuf, "cp -f %s %s.bak", fname, fname); system(genbuf); break; @@ -1370,18 +1124,17 @@ choose_board(int newflag) close(fd); sprintf(genbuf, "cp -f %s.bak %s", fname, fname); system(genbuf); - freefav(fav); + fav_free(); load_brdbuf(); - favchange = 1; break; } brdnum = -1; } break; case 'z': - vmsg("嘿嘿 這個功\能已經被我的最愛取代掉了喔!"); + //vmsg("嘿嘿 這個功\能已經被我的最愛取代掉了喔!"); break; - case 'Z': + case 'Z': //NEWFAV cuser.uflag2 ^= FAVNEW_FLAG; if(cuser.uflag2 & FAVNEW_FLAG){ char fname[80]; @@ -1419,10 +1172,10 @@ choose_board(int newflag) if (ch == 'v') { ptr->myattr &= ~BRD_UNREAD; brc_list[0] = now; - setfav(ptr->bid, 0, 0, now); + setbrdtime(ptr->bid, now); } else { brc_list[0] = 1; - setfav(ptr->bid, 0, 0, 1); + setbrdtime(ptr->bid, 1); ptr->myattr |= BRD_UNREAD; } brc_num = brc_changed = 1; @@ -1475,8 +1228,12 @@ choose_board(int newflag) char buf[STRLEN]; ptr = &nbrd[num]; - if(ptr->myattr & BRD_LINE) + if (ptr->myattr & BRD_LINE) + break; + else if (ptr->myattr & BRD_FOLDER){ + fav_folder_in(); break; + } if (!(B_BH(ptr)->brdattr & BRD_GROUPBOARD)) { /* 非sub class */ if (!(B_BH(ptr)->brdattr & BRD_HIDE) || @@ -1489,7 +1246,7 @@ choose_board(int newflag) head = tmp - t_lines / 2; getkeep(buf, head > 1 ? head : 1, tmp + 1); } - board_visit_time = getfavtime(ptr->bid); + board_visit_time = getbrdtime(ptr->bid); Read(); check_newpost(ptr); head = -1; diff --git a/pttbbs/mbbsd/fav.c b/pttbbs/mbbsd/fav.c new file mode 100644 index 00000000..6d4fe97e --- /dev/null +++ b/pttbbs/mbbsd/fav.c @@ -0,0 +1,833 @@ +#include "bbs.h" + +#ifdef MEM_CHECK +static int memcheck; +#endif + +/* the total number of items */ +static int fav_number; + +/* definition of fav stack, the top one is in use now. */ +static int fav_stack_num = 0; +static fav_t *fav_stack[FAV_MAXDEPTH] = {0}; + +/* current fav_type_t placement */ +static int fav_place; + +/* fav_old is for recordinge while copying, moving, etc. */ +static fav_t *fav_old; +static int fav_old_snum; /* the sequence number in favh in fav_t */ + + +/* "current" means what at the position of the cursor */ +inline fav_t *get_current_fav(void){ + if (fav_stack_num == 0) + return NULL; + return fav_stack[fav_stack_num]; +} + +inline static int get_item_type(fav_type_t *ft){ + return ft->type; +} + +inline fav_type_t *get_current_entry(void){ + return &fav_stack[fav_stack_num]->favh[fav_place]; +} + +inline void fav_set_old_folder(fav_t *fp){ + fav_old = fp; +} + +/* for casting */ +inline static fav_board_t *cast_board(fav_type_t *p){ + return (fav_board_t *)p->fp; +} + +inline static fav_line_t *cast_line(fav_type_t *p){ + return (fav_line_t *)p->fp; +} + +inline static fav_folder_t *cast_folder(fav_type_t *p){ + return (fav_folder_t *)p->fp; +} +/* --- */ + +inline static void line_decrease(fav_t *fp) { +// fp->nLines--; + fav_number--; +} + +inline static void board_decrease(fav_t *fp) { + fp->nBoards--; + fav_number--; +} + +inline static void folder_decrease(fav_t *fp) { +// fp->nFolders--; + fav_number--; +} +/* --- */ + +inline static void line_increase(fav_t *fp) { + fp->nLines++; + fav_number++; +} + +inline static void board_increase(fav_t *fp) { + fp->nBoards++; + fav_number++; +} + +inline static void folder_increase(fav_t *fp) { + fp->nFolders++; + fav_number++; +} +/* --- */ + +inline static int get_folder_num(fav_t *fp) { + return fp->nFolders; +} + +inline static int get_line_num(fav_t *fp) { + return fp->nLines; +} + +/* bool: + * 0: unset 1: set 2: opposite */ +inline void set_attr(fav_type_t *ft, int bit, int bool){ + if (bool == 2) + bool = !(ft->attr & bit); + if (bool) + ft->attr |= bit; + else + ft->attr &= ~bit; +} + +inline int is_set_attr(fav_type_t *ft, int bit){ + return ft->attr & bit; +} +/* --- */ + +static char *get_item_title(fav_type_t *ft) +{ + switch (get_item_type(ft)){ + case FAVT_BOARD: + return bcache[cast_board(ft)->bid - 1].brdname; + case FAVT_FOLDER: + return cast_folder(ft)->title; + case FAVT_LINE: + return "----"; + } + return NULL; +} + +static char *get_item_class(fav_type_t *ft) +{ + switch (get_item_type(ft)){ + case FAVT_BOARD: + return bcache[cast_board(ft)->bid - 1].title; + case FAVT_FOLDER: + return cast_folder(ft)->title; + case FAVT_LINE: + return "----"; + } + return NULL; +} + +#ifdef MEM_CHECK +inline void fav_set_memcheck(int n) { + memcheck = n; +} + +inline int fav_memcheck(void) { + return memcheck; +} +#endif +/* ---*/ + +static int get_type_size(int type) +{ + switch (type){ + case FAVT_BOARD: + return sizeof(fav_board_t); + case FAVT_FOLDER: + return sizeof(fav_folder_t); + case FAVT_LINE: + return sizeof(fav_line_t); + } + return 0; +} + +inline static void* fav_malloc(int size){ + void *p = (void *)malloc(size); + memset(p, 0, size); + return p; +} + +/* allocate the header(fav_type_t) and item it self. */ +static fav_type_t *fav_allocate(int type) +{ + int size = 0; + fav_type_t *ft = (fav_type_t *)fav_malloc(sizeof(fav_type_t)); + + size = get_type_size(type); + if (size) { + ft->fp = fav_malloc(size); + ft->type = type; + } + return ft; +} + +inline static fav_t *get_fav_root(void){ + return fav_stack[0]; +} + +/* return: the exact number after cleaning + * reset the line number, board number, folder number, and total number (number) + */ +static void clean_fav(fav_t *fp) +{ + int i, bid; + fp->nLines = fp->nBoards = fp->nFolders = 0; + for (i = 0; i < fp->nAllocs; i++){ + if (!is_set_attr(&fp->favh[i], FAVH_FAV)) + continue; + switch (get_item_type(&fp->favh[i])){ + case FAVT_BOARD: + bid = cast_board(&fp->favh[i])->bid; + if (!validboard(bid - 1)) + continue; + board_increase(fp); + break; + case FAVT_LINE: + line_increase(fp); + break; + case FAVT_FOLDER: + clean_fav(cast_folder(fp->favh[i].fp)->this_folder); + folder_increase(fp); + break; + default: + continue; + } + } +} + +static void cleanup(void) +{ + fav_number = 0; + clean_fav(get_fav_root()); +} + +/* sort the fav */ +static int favcmp_by_name(const void *a, const void *b) +{ + return strcasecmp(get_item_title((fav_type_t *)a), get_item_title((fav_type_t *)b)); +} + +void fav_sort_by_name(void) +{ + clean_fav(get_current_fav()); + qsort(get_current_fav(), get_current_fav()->nDatas, sizeof(fav_type_t), favcmp_by_name); +} + +static int favcmp_by_class(const void *a, const void *b) +{ + fav_type_t *f1, *f2; + int cmp; + + f1 = (fav_type_t *)a; + f2 = (fav_type_t *)b; + if (f1->type == FAVT_FOLDER || f2->type == FAVT_FOLDER) + return -1; + if (f1->type == FAVT_LINE || f2->type == FAVT_LINE) + return 1; + + cmp = strncasecmp(get_item_class(f1), get_item_class(f2), 4); + if (cmp) + return cmp; + return strcasecmp(get_item_title(f1), get_item_title(f1)); +} + +void fav_sort_by_class(void) +{ + clean_fav(get_current_fav()); + qsort(get_current_fav(), get_current_fav()->nDatas, sizeof(fav_type_t), favcmp_by_class); +} +/* --- */ + +inline static void +fav_item_copy_symbolic(fav_type_t *target, const fav_type_t *source){ + target->type = source->type; + target->attr = source->attr; + target->fp = source->fp; +} + +inline static void +fav_item_copy(fav_type_t *target, const fav_type_t *source){ + target = fav_allocate(source->type); + fav_item_copy_symbolic(target, source); +} + +/* The following is the movement operations in the user interface. */ +inline static void fav_stack_push_fav(fav_t *fp){ + fav_stack[fav_stack_num++] = fp; + fav_place = 0; +} + +inline static void fav_stack_push(fav_type_t *ft){ + if (ft->type != FAVT_FOLDER) + return; + fav_stack_push_fav(cast_folder(ft)->this_folder); +} + +inline static void fav_stack_pop(void){ + fav_stack[--fav_stack_num] = NULL; + fav_place = 0; +} + +void fav_folder_in(void) +{ + fav_type_t *tmp = get_current_entry(); + if (tmp->type == FAVT_FOLDER){ + fav_stack_push(tmp); + } +} + +void fav_folder_out(void) +{ + fav_stack_pop(); +} + +void fav_cursor_up(void) +{ + fav_t *ft = get_current_fav(); + while(1){ + if (fav_place == 0) + fav_place = ft->nBoards - 1; + if (ft->favh[fav_place].attr & FAVH_FAV) + break; + fav_place--; + } +} + +void fav_cursor_down(void) +{ + fav_t *ft = get_current_fav(); + while(1){ + if (fav_place == ft->nBoards - 1) + fav_place = 0; + if (ft->favh[fav_place].attr & FAVH_FAV) + break; + fav_place++; + } +} +/* --- */ + +/* load from the rec file */ +static void read_favrec(int fd, fav_t *fp) +{ + int i, total; + fp = (fav_t *)malloc(sizeof(fav_t)); + read(fd, &fp->nDatas, sizeof(fp->nDatas)); + read(fd, &fp->nBoards, sizeof(fp->nBoards)); + read(fd, &fp->nLines, sizeof(fp->nLines)); + read(fd, &fp->nFolders, sizeof(fp->nFolders)); + total = fp->nBoards + fp->nLines + fp->nFolders; + fp->favh = (fav_type_t *)malloc(sizeof(fav_type_t) * total); + + for(i = 0; i < total; i++){ + read(fd, &fp->favh[i].type, sizeof(fp->favh[i].type)); + read(fd, &fp->favh[i].attr, sizeof(fp->favh[i].attr)); + fp->favh[i].fp = (void *)malloc(get_type_size(fp->favh[i].type)); + read(fd, fp->favh[i].fp, get_type_size(fp->favh[i].type)); + } + + for(i = 0; i < total; i++){ + if (fp->favh[i].type == FAVT_FOLDER) + read_favrec(fd, cast_folder(&fp->favh[i])->this_folder); + } +} + +int fav_load(void) +{ + int fd; + char buf[128]; + fav_t *fp; + if (fav_stack_num > 0) + return -1; + setuserfile(buf, FAV4); + fd = open(buf, O_RDONLY); + if (fd < 0){ + return -1; + } + fp = (fav_t *)fav_malloc(sizeof(fav_t)); + fav_stack_push_fav(fp); + close(fd); + fav_set_memcheck(MEM_CHECK); + return 0; +} +/* --- */ + +/* write to the rec file */ +static void write_favrec(int fd, fav_t *fp) +{ + int i, total; + write(fd, &fp->nDatas, sizeof(fp->nDatas)); + write(fd, &fp->nBoards, sizeof(fp->nBoards)); + write(fd, &fp->nLines, sizeof(fp->nLines)); + write(fd, &fp->nFolders, sizeof(fp->nFolders)); + total = fp->nBoards + fp->nLines + fp->nFolders; + + for(i = 0; i < total; i++){ + write(fd, &fp->favh[i].type, sizeof(fp->favh[i].type)); + write(fd, &fp->favh[i].attr, sizeof(fp->favh[i].attr)); + write(fd, fp->favh[i].fp, get_type_size(fp->favh[i].type)); + } + + for(i = 0; i < total; i++){ + if (fp->favh[i].type == FAVT_FOLDER) + write_favrec(fd, cast_folder(&fp->favh[i])->this_folder); + } +} + +int fav_save(void) +{ + int fd; + char buf[128], buf2[128]; +#ifdef MEM_CHECK + if (fav_memcheck() != MEM_CHECK) + return -1; +#endif + fav_t *fp = get_fav_root(); + if (fp == NULL) + return -1; + cleanup(); + setuserfile(buf, FAV4".tmp"); + setuserfile(buf2, FAV4); + fd = open(buf, O_TRUNC | O_WRONLY); + if (fd < 0) + return -1; + write_favrec(fd, fp); + close(fd); + Rename(buf, buf2); + return 0; +} +/* --- */ + +/* It didn't need to remove it self, just remove all the attributes. + * It'll be remove when it save to the record file. */ +static void fav_free_item(fav_type_t *ft) +{ + free(ft->fp); + set_attr(ft, 0xFFFF, FALSE); + ft = NULL; +} + +static int fav_remove(fav_t *fp, fav_type_t *ft) +{ + switch(get_item_type(ft)){ + case FAVT_BOARD: + board_decrease(fp); + break; + case FAVT_FOLDER: + folder_decrease(fp); + break; + case FAVT_LINE: + line_decrease(fp); + break; + } + fav_free_item(ft); + return 0; +} + +void fav_remove_current(void) +{ + fav_remove(get_current_fav(), get_current_entry()); +} + +void fav_remove_board_from_whole(int bid) +{ + int i; + fav_t *fp = get_current_fav(); + fav_type_t *ft; + for(i = 0; i < fp->nAllocs; i++){ + ft = &fp->favh[i]; + if (ft->attr & FAVT_BOARD && cast_board(ft)->bid == bid) + fav_remove(fp, ft); + else if (ft->attr & FAVT_FOLDER){ + fav_stack_push(ft); + fav_remove_board_from_whole(bid); + fav_stack_pop(); + } + } +} + +static fav_type_t *get_favrec(short bid, int type) +{ + int i; + fav_type_t *ft; + fav_t *fp = get_current_fav(); + + for(i = 0; i < fp->nAllocs; i++){ + ft = &fp->favh[i]; + if (get_item_type(ft) != type) + continue; + if (!is_set_attr(ft, FAVH_FAV)) + continue; + if (cast_board(ft)->bid == bid) + return ft; + } + return NULL; +} + +static fav_type_t *getboard(short bid) +{ + return get_favrec(bid, FAVT_BOARD); +} + + +char getbrdattr(short bid) +{ + fav_type_t *fb = getboard(bid); + if (!fb) + return 0; + return fb->attr; +} + +time_t getbrdtime(short bid) +{ + fav_type_t *fb = getboard(bid); + if (!fb) + return 0; + return cast_board(fb)->lastvisit; +} + +void setbrdtime(short bid, time_t t) +{ + fav_type_t *fb = getboard(bid); + if (fb) + cast_board(fb)->lastvisit = t; +} + +int fav_getid(fav_type_t *ft) +{ + switch(get_item_type(ft)){ + case FAVT_FOLDER: + return cast_folder(ft)->fid; + case FAVT_LINE: + return cast_line(ft)->lid; + case FAVT_BOARD: + return cast_board(ft)->bid; + } + return -1; +} + +/* suppose we don't add too much fav_type_t at the same time. */ +static int enlarge_if_full(fav_t *fp) +{ + /* enlarge the volume if need. */ + if (fp->nDatas >= MAX_FAV) + return -1; + if (fp->nDatas != fp->nAllocs) + return 0; + + fp->nAllocs += ALLOC_NUM; + fav_type_t *tmp = (fav_type_t *)realloc(fp, sizeof(fav_type_t) * ALLOC_NUM); + memset(tmp, 0, ALLOC_NUM); + return 1; +} + +inline int is_maxsize(void){ + return fav_number == MAX_FAV; +} + +int fav_add(fav_t *fp, fav_type_t *item) +{ + if (enlarge_if_full(fp) < 0) + return -1; + fav_item_copy(&fp->favh[fp->nBoards], item); + fp->nDatas++; + return 0; +} + +static void fav_move_into_folder(fav_t *from, int where, fav_t *to) +{ + fav_type_t *tmp = &from->favh[where]; + if (from != to){ + if (enlarge_if_full(to) < 0) + return; + } + fav_add(to, tmp); + fav_remove(from, tmp); +} + +/* just move, in one folder */ +static void move_in_folder(fav_t *fav, int from, int to) +{ + int i; + fav_type_t tmp; + fav_item_copy(&tmp, &fav->favh[to]); + + if (from < to) { + for(i = from; i < to; i++) + fav_item_copy_symbolic(&fav->favh[i], &fav->favh[i + 1]); + } + else { + for(i = to; i > from; i--) + fav_item_copy_symbolic(&fav->favh[i], &fav->favh[i - 1]); + } + fav_item_copy(&fav->favh[to], &tmp); +} + +void move_in_current_folder(int from, int to) +{ + move_in_folder(get_current_fav(), from, to); +} + +void fav_move(int from, int to) +{ + fav_type_t *ft = get_current_entry(); + if (ft->type == FAVT_FOLDER) + fav_move_into_folder(fav_old, fav_old_snum, get_current_fav()); + move_in_folder(get_current_fav(), from, to); +} + +/* set the current fav_t and fav_type to old one. */ +void fav_set_current_old(void) +{ + fav_old = get_current_fav(); + fav_old_snum = fav_place; +} + +/* the following defines the interface of add new fav_XXX */ +static int init_add(fav_type_t *ft, fav_t *fp, int type, int place) +{ + fp = get_current_fav(); + if (is_maxsize()) + return -1; + ft = fav_allocate(type); + set_attr(ft, FAVH_FAV, TRUE); + fav_add(fp, ft); + if (place >= 0) + move_in_folder(fp, fp->nDatas - 1, place); + return 0; +} + +/* if place < 0, just put the item to the tail */ +int fav_add_line(int place) +{ + fav_t *fp = NULL; + fav_type_t *ft = NULL; + if (init_add(ft, fp, FAVT_LINE, place) < 0) + return -1; + cast_line(ft)->lid = get_line_num(fp); + line_increase(fp); + return 0; +} + +int fav_add_folder(int place) +{ + fav_t *fp = NULL; + fav_type_t *ft = NULL; + if (init_add(ft, fp, FAVT_FOLDER, place) < 0) + return -1; + cast_folder(ft)->fid = get_folder_num(fp); + folder_increase(fp); + return 0; +} + +int fav_add_board(int bid, int place) +{ + fav_t *fp = get_current_fav(); + fav_type_t *ft = NULL; + if (init_add(ft, fp, FAVT_BOARD, place) < 0) + return -1; + cast_board(ft)->bid = bid; + board_increase(fp); + return 0; +} +/* --- */ + +/* everything about the tag in fav mode. + * I think we don't have to implement the function 'cross-folder' tag.*/ +void fav_tag_current(int bool) +{ + fav_type_t *ft = get_current_entry(); + set_attr(ft, FAVH_TAG, bool); +} + +static void fav_dosomething_tagged_item(fav_t *fp, int (*act)(fav_t *, fav_type_t *)) +{ + int i; + for(i = 0; i < fp->nAllocs; i++){ + if (is_set_attr(&fp->favh[i], FAVH_TAG)) + (*act)(fp, &fp->favh[i]); + } +} + +void fav_remove_tagged_item(fav_t *fp) +{ + fav_dosomething_tagged_item(fp, fav_remove); +} + +void fav_add_tagged_item(fav_t *fp) +{ + fav_dosomething_tagged_item(fp, fav_remove); +} + +static void fav_dosomething_all_tagged_item(void (*act)(fav_t *)) +{ + int i; + fav_type_t *ft; + fav_t *fp = get_current_fav(); + for(i = 0; i < fp->nAllocs; i++){ + ft = &fp->favh[i]; + if (ft->attr & FAVT_FOLDER){ + fav_stack_push(ft); + fav_dosomething_all_tagged_item(act); + fav_stack_pop(); + } + } + (*act)(get_current_fav()); +} + +void fav_remove_all_tagged_item(void) +{ + fav_dosomething_all_tagged_item(fav_remove_tagged_item); +} + +void fav_add_all_tagged_item(void) +{ + fav_dosomething_all_tagged_item(fav_add_tagged_item); +} + +inline static int remove_tag(fav_t *fp, fav_type_t *ft) +{ + set_attr(ft, FAVH_TAG, FALSE); + return 0; +} + +inline static void remove_tags(fav_t *fp) +{ + fav_dosomething_tagged_item(fp, remove_tag); +} + +void fav_remove_all_tag(void) +{ + fav_dosomething_all_tagged_item(remove_tags); +} +/* --- */ + +void fav_set_folder_title(char *title) +{ + fav_type_t *ft = get_current_entry(); + if (ft->type != FAVT_FOLDER) + return; + strlcpy(cast_folder(ft)->title, title, sizeof(cast_folder(ft)->title)); +} + +/* free the mem of whole fav tree */ +static void fav_free_branch(fav_t *fp) +{ + int i; + fav_type_t *ft; + for(i = 0; i < fp->nAllocs; i++){ + ft = &fp->favh[i]; + if (ft->attr & FAVT_FOLDER) + fav_free_branch(cast_folder(ft)->this_folder); + fav_remove(fp, ft); + } + free(fp); + fp = NULL; +} + +void fav_free(void) +{ + fav_free_branch(get_fav_root()); +} +/* --- */ + +/* old struct */ +#define BRD_UNREAD 1 +#define BRD_FAV 2 +#define BRD_LINE 4 +#define BRD_TAG 8 +#define BRD_GRP_HEADER 16 + +typedef struct { + short bid; + char attr; + time_t lastvisit; +} fav3_board_t; + +typedef struct { + short nDatas; + short nAllocs; + char nLines; + fav_board_t *b; +} fav3_t; + +int fav_v3_to_v4(void) +{ + int i, fd, fdw; + char buf[128]; + + short nDatas; + char nLines; + fav_t fav4; + fav3_board_t *brd; + + setuserfile(buf, FAV4); + fd = open(buf, O_RDONLY); + if (fd >= 0){ + close(fd); + return 0; + } + fdw = open(buf, O_WRONLY | O_CREAT | O_TRUNC, 0600); + if (fdw < 0) + return -1; + setuserfile(buf, FAV3); + fd = open(buf, O_RDONLY); + if (fd < 0) + return -1; + + read(fd, &nDatas, sizeof(nDatas)); + read(fd, &nLines, sizeof(nLines)); + + fav4.nDatas = nDatas; + fav4.nBoards = nDatas - nLines; + fav4.nLines = nLines; + fav4.nFolders = 0; + fav4.favh = (fav_type_t *)malloc(sizeof(fav_type_t) * fav4.nDatas); + memset(fav4.favh, 0, sizeof(fav_type_t) * fav4.nDatas); + + brd = (fav3_board_t *)malloc(sizeof(fav3_board_t) * nDatas); + read(fd, brd, sizeof(fav3_board_t) * nDatas); + + for(i = 0; i < fav4.nDatas; i++){ + fav4.favh[i].type = brd[i].attr & BRD_LINE ? FAVT_LINE : FAVT_BOARD; + + if (brd[i].attr & BRD_UNREAD) + fav4.favh[i].attr |= FAVH_UNREAD; + if (brd[i].attr & BRD_FAV) + fav4.favh[i].attr |= FAVH_FAV; + if (brd[i].attr & BRD_TAG) + fav4.favh[i].attr |= FAVH_TAG; + + fav4.favh[i].fp = (void *)malloc(get_type_size(fav4.favh[i].type)); + if (brd[i].attr & BRD_LINE){ + fav4.favh[i].type = FAVT_LINE; + cast_line(&fav4.favh[i])->lid = -brd[i].bid; + } + else{ + fav4.favh[i].type = FAVT_BOARD; + cast_board(&fav4.favh[i])->bid = brd[i].bid; + cast_board(&fav4.favh[i])->lastvisit = brd[i].lastvisit; + } + } + + write_favrec(fd, &fav4); + fav_free_branch(&fav4); + free(brd); + return 0; +} -- cgit v1.2.3