From 781c220d8e6a5034957473aa308306cc4b7c862f Mon Sep 17 00:00:00 2001 From: victor Date: Sat, 22 Nov 2003 02:16:02 +0000 Subject: merge back from fav4 braches git-svn-id: http://opensvn.csie.org/pttbbs/trunk/pttbbs@1356 63ad8ddf-47c3-0310-b6dd-a9e9d9715204 --- mbbsd/fav.c | 921 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 921 insertions(+) create mode 100644 mbbsd/fav.c (limited to 'mbbsd/fav.c') diff --git a/mbbsd/fav.c b/mbbsd/fav.c new file mode 100644 index 00000000..6590e57e --- /dev/null +++ b/mbbsd/fav.c @@ -0,0 +1,921 @@ +#include "bbs.h" + +#ifdef MEM_CHECK +static int memcheck; +#endif + +/* the total number of items, every level. */ +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}; + +/* fav_tmp is for recordinge while copying, moving, etc. */ +static fav_t *fav_tmp; +//static int fav_tmp_snum; /* the sequence number in favh in fav_t */ + + +/* 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 int get_data_number(fav_t *fp){ + return fp->nBoards + fp->nLines + fp->nFolders; +} + +inline int get_current_fav_level(void){ + return fav_stack_num; +} + +inline fav_t *get_current_fav(void){ + if (fav_stack_num == 0) + return NULL; + return fav_stack[fav_stack_num - 1]; +} + +inline fav_t *get_fav_folder(fav_type_t *ft){ + return cast_folder(ft)->this_folder; +} + +inline int get_item_type(fav_type_t *ft){ + return ft->type; +} + +inline void fav_set_tmp_folder(fav_t *fp){ + fav_tmp = fp; +} + +inline static fav_t *fav_get_tmp_fav(void){ + return fav_tmp; +} +/* --- */ + +static void fav_decrease(fav_t *fp, fav_type_t *ft){ + switch (get_item_type(ft)){ + case FAVT_BOARD: + fp->nBoards--; + break; + case FAVT_LINE: + fp->nLines--; + break; + case FAVT_FOLDER: + fp->nFolders--; + break; + } + fav_number--; +} +/* --- */ + +static void fav_increase(fav_t *fp, fav_type_t *ft) +{ + switch (get_item_type(ft)){ + case FAVT_BOARD: + fp->nBoards++; + break; + case FAVT_LINE: + fp->nLines++; + fp->lineID++; + break; + case FAVT_FOLDER: + fp->nFolders++; + fp->folderID++; + break; + } + fav_number++; + fp->DataTail++; +} +/* --- */ + +inline static int get_folder_num(fav_t *fp) { + return fp->nFolders; +} + +inline static int get_folder_id(fav_t *fp) { + return fp->folderID; +} + +inline static int get_line_id(fav_t *fp) { + return fp->lineID; +} + +inline static int get_line_num(fav_t *fp) { + return fp->nLines; +} + +/* bool: + * 0: unset 1: set 2: opposite */ +void set_attr(fav_type_t *ft, int bit, char bool){ + if (bool == 2) + ft->attr ^= bit; + else if (bool == 1) + ft->attr |= bit; + else + ft->attr &= ~bit; +} + +int is_set_attr(fav_type_t *ft, char bit){ + return ft->attr & bit; +} +/* --- */ + +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 "¥Ø¿ý"; + 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_item_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; +} + +/* symbolic link */ +inline static void +fav_item_copy(fav_type_t *target, const fav_type_t *source){ + target->type = source->type; + target->attr = source->attr; + target->fp = source->fp; +} + +inline static fav_t *get_fav_root(void){ + return fav_stack[0]; +} + +char current_fav_at_root(void) { + return get_current_fav() == get_fav_root(); +} + +/* is it an unvisable entry */ +inline int is_visible_item(fav_type_t *ft){ + if (!(ft->attr & FAVH_FAV)) + return 0; + if (get_item_type(ft) != FAVT_BOARD) + return 1; + return Ben_Perm(&bcache[cast_board(ft)->bid - 1]); +} + +/* return: the exact number after cleaning + * reset the line number, board number, folder number, and total number (number) + */ +static void rebuild_fav(fav_t *fp) +{ + int i, j, nData, bid; + fav_type_t *ft; + fav_number = 0; + fp->lineID = fp->folderID = 0; + fp->nLines = fp->nFolders = fp->nBoards = 0; + nData = fp->DataTail; + for (i = 0, j = 0; i < nData; i++){ + if (!(fp->favh[i].attr & FAVH_FAV)) + continue; + ft = &fp->favh[i]; + switch (get_item_type(ft)){ + case FAVT_BOARD: + bid = cast_board(ft)->bid; + if (!validboard(bid - 1)) + continue; + break; + case FAVT_LINE: + cast_line(ft)->lid = fp->lineID + 1; + break; + case FAVT_FOLDER: + cast_folder(ft)->fid = fp->folderID + 1; + rebuild_fav(get_fav_folder(&fp->favh[i])); + break; + default: + continue; + } + fav_increase(fp, &fp->favh[i]); + if (i != j) + fav_item_copy(&fp->favh[j], &fp->favh[i]); + j++; + } + fp->DataTail = get_data_number(fp); +} + +inline void cleanup(void) +{ + rebuild_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) +{ + rebuild_fav(get_current_fav()); + qsort(get_current_fav()->favh, get_data_number(get_current_fav()), 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 (get_item_type(f1) == FAVT_FOLDER) + return -1; + if (get_item_type(f2) == FAVT_FOLDER) + return 1; + if (get_item_type(f1) == FAVT_LINE) + return 1; + if (get_item_type(f2) == 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) +{ + rebuild_fav(get_current_fav()); + qsort(get_current_fav()->favh, get_data_number(get_current_fav()), sizeof(fav_type_t), favcmp_by_class); +} +/* --- */ + +/* + * The following is the movement operations in the user interface. + */ +inline static int fav_stack_full(void){ + return fav_stack_num >= FAV_MAXDEPTH; +} + +inline int fav_max_folder_level(void){ + return fav_stack_full(); +} + +inline static int fav_stack_push_fav(fav_t *fp){ + if (fav_stack_full()) + return -1; + fav_stack[fav_stack_num++] = fp; + return 0; +} + +inline static int fav_stack_push(fav_type_t *ft){ +// if (ft->type != FAVT_FOLDER) +// return -1; + return fav_stack_push_fav(get_fav_folder(ft)); +} + +inline static void fav_stack_pop(void){ + fav_stack[--fav_stack_num] = NULL; +} + +void fav_folder_in(short fid) +{ + fav_type_t *tmp = getfolder(fid); + if (get_item_type(tmp) == FAVT_FOLDER){ + fav_stack_push(tmp); + } +} + +void fav_folder_out(void) +{ + fav_stack_pop(); +} + +/* --- */ + +/* load from the rec file */ +static void read_favrec(int fd, fav_t *fp) +{ + int i; + fav_type_t *ft; + read(fd, &fp->nBoards, sizeof(fp->nBoards)); + read(fd, &fp->nLines, sizeof(fp->nLines)); + read(fd, &fp->nFolders, sizeof(fp->nFolders)); + fp->DataTail = get_data_number(fp); + fp->nAllocs = fp->DataTail + FAV_PRE_ALLOC; + fp->lineID = fp->folderID = 0; + fp->favh = (fav_type_t *)fav_malloc(sizeof(fav_type_t) * fp->nAllocs); + + for(i = 0; i < fp->DataTail; 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 *)fav_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 < fp->DataTail; i++){ + ft = &fp->favh[i]; + switch (ft->type) { + case FAVT_FOLDER: { + fav_t *p = (fav_t *)fav_malloc(sizeof(fav_t)); + read_favrec(fd, p); + cast_folder(ft)->this_folder = p; + cast_folder(ft)->fid = ++(fp->folderID); + break; + } + case FAVT_LINE: + cast_line(ft)->lid = ++(fp->lineID); + break; + } + } +} + +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)); + read_favrec(fd, fp); + 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; + if (fp == NULL) + return; + write(fd, &fp->nBoards, sizeof(fp->nBoards)); + write(fd, &fp->nLines, sizeof(fp->nLines)); + write(fd, &fp->nFolders, sizeof(fp->nFolders)); + fp->DataTail = get_data_number(fp); + + for(i = 0; i < fp->DataTail; 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 < fp->DataTail; i++){ + if (fp->favh[i].type == FAVT_FOLDER) + write_favrec(fd, get_fav_folder(&fp->favh[i])); + } +} + +int fav_save(void) +{ + int fd; + char buf[128], buf2[128]; + fav_t *fp = get_fav_root(); +#ifdef MEM_CHECK + if (fav_memcheck() != MEM_CHECK) + return -1; +#endif + if (fp == NULL) + return -1; + cleanup(); + setuserfile(buf, FAV4".tmp"); + setuserfile(buf2, FAV4); + fd = open(buf, O_CREAT | O_TRUNC | O_WRONLY, 0600); + 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) +{ + set_attr(ft, 0xFFFF, FALSE); +// ft = NULL; +} + +static int fav_non_recursive_remove(fav_t *fp, fav_type_t *ft) +{ + set_attr(ft, 0xFFFF, FALSE); + fav_decrease(fp, ft); + return 0; +} + +static int fav_remove(fav_t *fp, fav_type_t *ft) +{ + fav_free_item(ft); + fav_decrease(fp, ft); + return 0; +} + +/* free the mem of whole fav tree */ +static void fav_free_branch(fav_t *fp) +{ + int i; + fav_type_t *ft; + if (fp == NULL) + return; + for(i = 0; i < fp->DataTail; i++){ + ft = &fp->favh[i]; + fav_remove(fp, ft); + } + free(fp); + fp = NULL; +} + +void fav_free(void) +{ + fav_free_branch(get_fav_root()); + + /* reset the stack */ + fav_stack_num = 0; +} +/* --- */ + +static fav_type_t *get_fav_item(short id, int type) +{ + int i; + fav_type_t *ft; + fav_t *fp = get_current_fav(); + + for(i = 0; i < fp->DataTail; i++){ + ft = &fp->favh[i]; + if (!is_visible_item(ft) || get_item_type(ft) != type) + continue; + if (fav_getid(ft) == id) + return ft; + } + return NULL; +} + +void fav_remove_item(short id, char type) +{ + fav_remove(get_current_fav(), get_fav_item(id, type)); +} + +fav_type_t *getboard(short bid) +{ + return get_fav_item(bid, FAVT_BOARD); +} + +fav_type_t *getfolder(short fid) +{ + return get_fav_item(fid, FAVT_FOLDER); +} + +char *get_folder_title(int fid) +{ + return get_item_title(get_fav_item(fid, FAVT_FOLDER)); +} + + +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) +{ + fav_type_t * p; + /* enlarge the volume if need. */ + if (fav_number >= MAX_FAV) + return -1; + if (fp->DataTail < fp->nAllocs) + return 1; + + /* realloc and clean the tail */ + p = (fav_type_t *)realloc(fp->favh, sizeof(fav_type_t) * (fp->nAllocs + FAV_PRE_ALLOC)); + if( p == NULL ) + return -1; + + fp->favh = p; + memset(fp->favh + fp->nAllocs, 0, sizeof(fav_type_t) * FAV_PRE_ALLOC); + fp->nAllocs += FAV_PRE_ALLOC; + return 0; +} + +inline int is_maxsize(void){ + return fav_number >= MAX_FAV; +} + +static int fav_add(fav_t *fp, fav_type_t *item) +{ + if (enlarge_if_full(fp) < 0) + return -1; + fav_item_copy(&fp->favh[fp->DataTail], item); + fav_increase(fp, item); + return 0; +} + +/* just move, in one folder */ +static void move_in_folder(fav_t *fav, int from, int to) +{ + int i, count; + fav_type_t tmp; + + /* Find real locations of from and to in fav->favh[] */ + for(count = i = 0; count <= from; i++) + if (is_visible_item(&fav->favh[i])) + count++; + from = i - 1; + for(count = i = 0; count <= to; i++) + if (is_visible_item(&fav->favh[i])) + count++; + to = i - 1; + + fav_item_copy(&tmp, &fav->favh[from]); + + if (from < to) { + for(i = from; i < to; i++) + fav_item_copy(&fav->favh[i], &fav->favh[i + 1]); + } + else { // to < from + for(i = from; i > to; i--) + fav_item_copy(&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); +} + +/* the following defines the interface of add new fav_XXX */ +inline static fav_t *alloc_folder_item(void){ + fav_t *fp = (fav_t *)fav_malloc(sizeof(fav_t)); + fp->nAllocs = FAV_PRE_ALLOC; + fp->favh = (fav_type_t *)fav_malloc(sizeof(fav_type_t) * FAV_PRE_ALLOC); + return fp; +} + +static fav_type_t *init_add(fav_t *fp, int type) +{ + fav_type_t *ft; + if (is_maxsize()) + return NULL; + ft = fav_item_allocate(type); + set_attr(ft, FAVH_FAV, TRUE); + fav_add(fp, ft); + return ft; +} + +/* if place < 0, just put the item to the tail */ +fav_type_t *fav_add_line(void) +{ + fav_t *fp = get_current_fav(); + if (get_line_num(fp) >= MAX_LINE) + return NULL; + fav_type_t *ft = init_add(fp, FAVT_LINE); + if (ft == NULL) + return NULL; + cast_line(ft)->lid = get_line_id(fp); + return ft; +} + +fav_type_t *fav_add_folder(void) +{ + fav_t *fp = get_current_fav(); + fav_type_t *ft; + if (fav_stack_full()) + return NULL; + if (get_folder_num(fp) >= MAX_FOLDER) + return NULL; + ft = init_add(fp, FAVT_FOLDER); + if (ft == NULL) + return NULL; + cast_folder(ft)->this_folder = alloc_folder_item(); + cast_folder(ft)->fid = get_folder_id(fp); // after fav_increase + return ft; +} + +fav_type_t *fav_add_board(int bid) +{ + fav_t *fp = get_current_fav(); + fav_type_t *ft = init_add(fp, FAVT_BOARD); + if (ft == NULL) + return NULL; + cast_board(ft)->bid = bid; + return ft; +} +/* --- */ + +/* everything about the tag in fav mode. + * I think we don't have to implement the function 'cross-folder' tag.*/ + +void fav_tag(short id, char type, char bool) { + fav_type_t *ft = get_fav_item(id, type); + if (ft != NULL) + 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->DataTail; i++){ + if (is_set_attr(&fp->favh[i], FAVH_FAV) && is_set_attr(&fp->favh[i], FAVH_TAG)) + if ((*act)(fp, &fp->favh[i]) < 0) + break; + } +} + +static int remove_tagged_item(fav_t *fp, fav_type_t *ft) +{ + int i; + for(i = 0; i < FAV_MAXDEPTH && fav_stack[i] != NULL; i++) + if (fav_stack[i] == get_fav_folder(ft)){ + set_attr(ft, FAVH_TAG, FALSE); + return 0; + } + return fav_remove(fp, ft); +} + +inline static int fav_remove_tagged_item(fav_t *fp){ + fav_dosomething_tagged_item(fp, remove_tagged_item); + return 0; +} + +/* add an item into a fav_t. + * here we must give the line and foler a new id to prevent an old one is exist. + */ +static int add_and_remove_tag(fav_t *fp, fav_type_t *ft) +{ + int i; + fav_type_t *tmp; + for(i = 0; i < FAV_MAXDEPTH && fav_stack[i] != NULL; i++) + if (fav_stack[i] == get_fav_folder(ft)){ + set_attr(ft, FAVH_TAG, FALSE); + return 0; + } + tmp = fav_malloc(sizeof(fav_type_t)); + fav_item_copy(tmp, ft); + set_attr(tmp, FAVH_TAG, FALSE); + + /* give the new id */ + switch (tmp->type) { + case FAVT_FOLDER: + cast_folder(tmp)->fid = fp->folderID + 1; + break; + case FAVT_LINE: + cast_line(tmp)->lid = fp->lineID + 1; + break; + } + if (fav_add(fav_get_tmp_fav(), tmp) < 0) + return -1; + if (get_item_type(ft) == FAVT_FOLDER) + fav_non_recursive_remove(fp, ft); + else + fav_remove(fp, ft); + return 0; +} + +inline static int fav_add_tagged_item(fav_t *fp){ + if (fp == fav_get_tmp_fav()) + return -1; + fav_dosomething_tagged_item(fp, add_and_remove_tag); + return 0; +} + +static void fav_do_recursively(fav_t *fp, int (*act)(fav_t *)) +{ + int i; + fav_type_t *ft; + for(i = 0; i < fp->DataTail; i++){ + ft = &fp->favh[i]; + if (!is_visible_item(ft)) + continue; + if (get_item_type(ft) == FAVT_FOLDER && get_fav_folder(ft) != NULL){ + fav_do_recursively(get_fav_folder(ft), act); + } + } + (*act)(fp); +} + +static void fav_dosomething_all_tagged_item(int (*act)(fav_t *)) +{ + fav_do_recursively(get_fav_root(), act); +} + +void fav_remove_all_tagged_item(void) +{ + fav_dosomething_all_tagged_item(fav_remove_tagged_item); +} + +void fav_add_all_tagged_item(void) +{ + fav_set_tmp_folder(get_current_fav()); + 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 int remove_tags(fav_t *fp) +{ + fav_dosomething_tagged_item(fp, remove_tag); + return 0; +} + +void fav_remove_all_tag(void) +{ + fav_dosomething_all_tagged_item(remove_tags); +} +/* --- */ + +void fav_set_folder_title(fav_type_t *ft, char *title) +{ + if (get_item_type(ft) != FAVT_FOLDER) + return; + strlcpy(cast_folder(ft)->title, title, sizeof(cast_folder(ft)->title)); +} + +/* 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 = (fav_t *)fav_malloc(sizeof(fav_t)); + 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->DataTail = nDatas; + //fav4->nBoards = nDatas - (-nLines); + //fav4->nLines = -nLines; + fav4->nBoards = fav4->nFolders = fav4->nLines = 0; + fav4->favh = (fav_type_t *)fav_malloc(sizeof(fav_type_t) * fav4->DataTail); + + brd = (fav3_board_t *)fav_malloc(sizeof(fav3_board_t) * nDatas); + read(fd, brd, sizeof(fav3_board_t) * nDatas); + + for(i = 0; i < fav4->DataTail; 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 *)fav_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 = ++fav4->nLines; + } + 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; + fav4->nBoards++; + } + } + + write_favrec(fdw, fav4); + fav_free_branch(fav4); + free(brd); + return 0; +} -- cgit v1.2.3