4 * Copyright (c) 2012 project bchan
6 * This software is provided 'as-is', without any express or implied
7 * warranty. In no event will the authors be held liable for any damages
8 * arising from the use of this software.
10 * Permission is granted to anyone to use this software for any purpose,
11 * including commercial applications, and to alter it and redistribute it
12 * freely, subject to the following restrictions:
14 * 1. The origin of this software must not be misrepresented; you must not
15 * claim that you wrote the original software. If you use this software
16 * in a product, an acknowledgment in the product documentation would be
17 * appreciated but is not required.
19 * 2. Altered source versions must be plainly marked as such, and must not be
20 * misrepresented as being the original software.
22 * 3. This notice may not be removed or altered from any source
34 #include <btron/btron.h>
36 #include <bsys/queue.h>
40 #include "extbbslist.h"
42 #include <tad/taditerator.h>
43 #include <tad/tadtsvparser.h>
45 #ifdef BCHANL_CONFIG_DEBUG
46 # define DP(arg) printf arg
47 # define DP_ER(msg, err) printf("%s (%d/%x)\n", msg, err>>16, err)
50 # define DP_ER(msg, err) /**/
53 struct extbbslist_item_t_ {
64 typedef struct extbbslist_item_t_ extbbslist_item_t;
66 LOCAL extbbslist_item_t* extbbslist_item_nextnode(extbbslist_item_t *item)
68 return (extbbslist_item_t*)item->que.next;
71 LOCAL VOID extbbslist_item_QueInsert(extbbslist_item_t *entry, extbbslist_item_t *que)
73 QueInsert(&entry->que, &que->que);
76 LOCAL VOID extbbslist_item_QueRemove(extbbslist_item_t *entry)
78 QueRemove(&entry->que);
82 LOCAL Bool extbbslist_item_isQueEmpty(extbbslist_item_t *entry)
84 return isQueEmpty(&entry->que);
87 LOCAL Bool extbbslist_item_titlecheck(extbbslist_item_t *entry, TC *title, W title_len)
91 if (entry->title_len != title_len) {
94 cmp = tc_strncmp(entry->title, title, title_len);
101 LOCAL VOID extbbslist_item_replacetitle(extbbslist_item_t *item, TC *title, W title_len)
103 if (item->title != NULL) {
107 item->title_len = title_len;
110 LOCAL VOID extbbslist_item_replaceTCurl(extbbslist_item_t *item, TC *url, W url_len)
112 if (item->url.tc != NULL) {
116 item->url.tc_len = url_len;
119 LOCAL VOID extbbslist_item_replaceascurl(extbbslist_item_t *item, UB *url, W url_len)
121 if (item->url.asc != NULL) {
125 item->url.asc_len = url_len;
128 LOCAL W extbbslist_item_assigntitle(extbbslist_item_t *item, CONST TC *title, W title_len)
131 str = malloc(sizeof(TC)*(title_len+1));
133 return -1; /* TODO */
135 memcpy(str, title, sizeof(TC)*title_len);
136 str[title_len] = TNULL;
137 extbbslist_item_replacetitle(item, str, title_len);
141 LOCAL W extbbslist_item_assignurl(extbbslist_item_t *item, CONST TC *url, W url_len)
147 str = malloc(sizeof(TC)*(url_len+1));
149 return -1; /* TODO */
151 memcpy(str, url, sizeof(TC)*url_len);
152 str[url_len] = TNULL;
154 len = tcstosjs(NULL, str);
155 str_ac = malloc(sizeof(UB)*(len+1));
156 if (str_ac == NULL) {
158 return -1; /* TODO */
160 tcstosjs(str_ac, str);
163 extbbslist_item_replaceTCurl(item, str, url_len);
164 extbbslist_item_replaceascurl(item, str_ac, len);
169 LOCAL W extbbslist_item_initialize(extbbslist_item_t *item)
175 item->url.tc_len = 0;
176 item->url.asc = NULL;
177 item->url.asc_len = 0;
182 LOCAL VOID extbbslist_item_finalize(extbbslist_item_t *item)
184 if (item->url.asc != NULL) {
187 if (item->url.tc != NULL) {
190 if (item->title != NULL) {
193 QueRemove(&item->que);
196 LOCAL extbbslist_item_t* extbbslist_item_new()
198 extbbslist_item_t *item;
201 item = malloc(sizeof(extbbslist_item_t));
205 err = extbbslist_item_initialize(item);
213 LOCAL VOID extbbslist_item_delete(extbbslist_item_t *item)
215 extbbslist_item_finalize(item);
219 struct extbbslist_t_ {
221 extbbslist_readcontext_t *ctx;
222 extbbslist_editcontext_t *edit;
230 LOCAL extbbslist_item_t* extbbslist_sentinelnode(extbbslist_t *list)
232 return (extbbslist_item_t*)&list->sentinel;
235 LOCAL extbbslist_item_t* extbbslist_searchitem(extbbslist_t *list, TC *title, W title_len)
237 extbbslist_item_t *entry, *senti;
240 senti = extbbslist_sentinelnode(list);
241 entry = extbbslist_item_nextnode(senti);
243 if (entry == senti) {
246 ok = extbbslist_item_titlecheck(entry, title, title_len);
250 entry = extbbslist_item_nextnode(entry);
256 EXPORT W extbbslist_appenditem(extbbslist_t *list, TC *title, W title_len, UB *url, W url_len)
258 extbbslist_item_t *item, *senti;
263 if (list->ctx != NULL) {
264 return -1; /* TODO */
267 item = extbbslist_searchitem(list, title, title_len);
269 return -1; /* TODO */
272 item = extbbslist_item_new();
274 return -1; /* TODO */
277 str = malloc(sizeof(TC)*(title_len+1));
279 extbbslist_item_delete(item);
280 return -1; /* TODO */
282 memcpy(str, title, sizeof(TC)*title_len);
283 str[title_len] = TNULL;
284 extbbslist_item_replacetitle(item, str, title_len);
286 str_ac = malloc(sizeof(UB)*(url_len+1));
287 if (str_ac == NULL) {
288 extbbslist_item_delete(item);
289 return -1; /* TODO */
291 memcpy(str_ac, url, sizeof(UB)*url_len);
292 str_ac[url_len] = '\0';
293 extbbslist_item_replaceascurl(item, str_ac, url_len);
295 len = sjstotcs(NULL, url);
296 str = malloc(sizeof(TC)*(len+1));
298 extbbslist_item_delete(item);
303 extbbslist_item_replaceTCurl(item, str, len);
305 senti = extbbslist_sentinelnode(list);
306 extbbslist_item_QueInsert(item, senti);
308 list->changed = True;
313 EXPORT W extbbslist_deleteitem(extbbslist_t *list, TC *title, W title_len)
315 extbbslist_item_t *item;
317 if (list->ctx != NULL) {
318 return -1; /* TODO */
321 item = extbbslist_searchitem(list, title, title_len);
323 return -1; /* TODO */
326 extbbslist_item_delete(item);
328 list->changed = True;
333 LOCAL VOID extbbslist_clear(extbbslist_t *list)
335 extbbslist_item_t *item;
339 empty = isQueEmpty(&list->sentinel);
343 item = (extbbslist_item_t*)list->sentinel.prev;
344 extbbslist_item_delete(item);
346 list->changed = True;
349 EXPORT W extbbslist_number(extbbslist_t *list)
354 EXPORT W extbbslist_writefile(extbbslist_t *list)
358 TADSEG *base = (TADSEG*)bin;
359 INFOSEG *infoseg = (INFOSEG*)(bin + 4);
360 TEXTSEG *textseg = (TEXTSEG*)(bin + 4);
361 extbbslist_item_t *senti, *item;
362 TC tab[] = {0xFE21, TK_TAB};
363 TC nl[] = {0xFE21, TK_NL};
365 if (list->lnk == NULL) {
366 return -1; /* TODO */
369 if (list->changed == False) {
373 fd = opn_fil(list->lnk, F_UPDATE, NULL);
375 DP_ER("opn_fil", fd);
379 err = fnd_rec(fd, F_TOPEND, 1 << list->rectype, list->subtype, NULL);
381 err = ins_rec(fd, NULL, 0, list->rectype, list->subtype, 0);
383 DP_ER("ins_rec", err);
387 err = see_rec(fd, -1, 0, NULL);
389 DP_ER("see_rec", err);
393 } else if (err < 0) {
394 DP_ER("fnd_rec", err);
398 err = trc_rec(fd, 0);
400 DP_ER("trc_rec", err);
409 infoseg->data[0] = 0x0122;
410 err = wri_rec(fd, -1, bin, 4+6, NULL, NULL, 0);
412 DP_ER("wri_rec:infoseg error", err);
418 textseg->view = (RECT){{0, 0, 0, 0}};
419 textseg->draw = (RECT){{0, 0, 0, 0}};
420 textseg->h_unit = -120;
421 textseg->v_unit = -120;
422 textseg->lang = 0x21;
424 err = wri_rec(fd, -1, bin, 4+24, NULL, NULL, 0);
426 DP_ER("wri_rec:textseg error", err);
431 senti = extbbslist_sentinelnode(list);
432 item = extbbslist_item_nextnode(senti);
438 err = wri_rec(fd, -1, (UB*)item->title, item->title_len*sizeof(TC), NULL, NULL, 0);
440 DP_ER("wri_rec:textseg error", err);
444 err = wri_rec(fd, -1, (UB*)tab, 2*sizeof(TC), NULL, NULL, 0);
446 DP_ER("wri_rec:textseg error", err);
450 err = wri_rec(fd, -1, (UB*)item->url.tc, item->url.tc_len*sizeof(TC), NULL, NULL, 0);
452 DP_ER("wri_rec:textseg error", err);
456 err = wri_rec(fd, -1, (UB*)nl, 2*sizeof(TC), NULL, NULL, 0);
458 DP_ER("wri_rec:textseg error", err);
463 item = extbbslist_item_nextnode(item);
468 err = wri_rec(fd, -1, bin, 4, NULL, NULL, 0);
470 DP_ER("wri_rec:textend error", err);
480 struct extbbslist_parsetsv_ctx_t_ {
492 typedef struct extbbslist_parsetsv_ctx_t_ extbbslist_parsetsv_ctx_t;
494 LOCAL W extbbslist_parsetsv_ctx_input(extbbslist_parsetsv_ctx_t *ctx, TADSTACK_RESULT psr_result, taditerator_result *seg_result)
497 extbbslist_item_t *item, *senti;
501 if (psr_result == TADTSVPARSER_RESULT_FORMAT_ERROR) {
504 if (psr_result == TADTSVPARSER_RESULT_IGNORE_SEGMENT) {
508 if (psr_result == TADTSVPARSER_RESULT_FIELD) {
509 if (seg_result == NULL) {
510 DP(("seg_result == NULL\n"));
511 return -1; /* TODO */
513 if (seg_result->type != TADITERATOR_RESULTTYPE_CHARCTOR) {
517 if (ctx->n_field == 0) {
519 p = (TC*)realloc(ctx->title.str, (ctx->title.len+1)*sizeof(TC));
521 DP_ER("realloc:title", -1);
522 return -1; /* TODO */
525 ctx->title.str[ctx->title.len - 1] = seg_result->segment;
526 ctx->title.str[ctx->title.len] = TNULL;
527 } else if (ctx->n_field == 1) {
529 p = (TC*)realloc(ctx->url.str, (ctx->url.len+1)*sizeof(TC));
531 DP_ER("realloc:url", -1);
532 return -1; /* TODO */
535 ctx->url.str[ctx->url.len - 1] = seg_result->segment;
536 ctx->url.str[ctx->url.len] = TNULL;
538 } else if (psr_result == TADTSVPARSER_RESULT_FIELD_END) {
540 } else if (psr_result == TADTSVPARSER_RESULT_RECORD_END) {
541 if (ctx->n_field < 1) {
545 free(ctx->title.str);
546 ctx->title.str = NULL;
553 ctx->title.len = mtc_unique(ctx->title.str, ctx->title.str, ctx->title.len);
554 ctx->url.len = mtc_unique(ctx->url.str, ctx->url.str, ctx->url.len);
556 item = extbbslist_item_new();
558 DP_ER("extbbslist_item_new", -1);
559 return -1; /* TODO */
562 len = tcstosjs(NULL, ctx->url.str);
563 str_ac = malloc(sizeof(UB)*(len+1));
564 if (str_ac == NULL) {
566 return -1; /* TODO */
568 tcstosjs(str_ac, ctx->url.str);
571 extbbslist_item_replacetitle(item, ctx->title.str, ctx->title.len);
572 ctx->title.str = NULL;
575 extbbslist_item_replaceTCurl(item, ctx->url.str, ctx->url.len);
579 extbbslist_item_replaceascurl(item, str_ac, len);
581 senti = extbbslist_sentinelnode(ctx->list);
582 extbbslist_item_QueInsert(item, senti);
589 LOCAL VOID extbbslist_parsetsv_ctx_initialize(extbbslist_parsetsv_ctx_t *ctx, extbbslist_t *list)
593 ctx->title.str = NULL;
599 LOCAL VOID extbbslist_parsetsv_ctx_finalize(extbbslist_parsetsv_ctx_t *ctx)
601 if (ctx->title.str != NULL) {
602 free(ctx->title.str);
604 if (ctx->url.str != NULL) {
609 LOCAL W extbbslist_parserecord(extbbslist_t *list, UB *rec, W len)
611 tadtsvparser_t parser;
613 taditerator_result result;
614 TADSTACK_RESULT psr_result;
616 extbbslist_parsetsv_ctx_t ctx;
618 tadtsvparser_initialize(&parser);
619 taditerator_initialize(&iter, (TC*)rec, len/sizeof(TC));
620 extbbslist_parsetsv_ctx_initialize(&ctx, list);
623 taditerator_next2(&iter, &result);
624 if (result.type == TADITERATOR_RESULTTYPE_END) {
628 if (result.type == TADITERATOR_RESULTTYPE_CHARCTOR) {
629 psr_result = tadtsvparser_inputcharactor(&parser, result.segment);
630 } else if (result.type == TADITERATOR_RESULTTYPE_SEGMENT) {
631 psr_result = tadtsvparser_inputvsegment(&parser, result.segment, result.data, result.segsize);
633 psr_result = TADTSVPARSER_RESULT_IGNORE_SEGMENT;
636 err = extbbslist_parsetsv_ctx_input(&ctx, psr_result, &result);
638 DP_ER("extbbslist_parsetsv_ctx_input", err);
642 psr_result = tadtsvparser_inputendofdata(&parser);
643 err = extbbslist_parsetsv_ctx_input(&ctx, psr_result, NULL);
645 extbbslist_parsetsv_ctx_finalize(&ctx);
646 taditerator_finalize(&iter);
647 tadtsvparser_finalize(&parser);
652 EXPORT W extbbslist_readfile(extbbslist_t *list)
657 fd = opn_fil(list->lnk, F_UPDATE, NULL);
659 DP_ER("opn_fil", fd);
663 err = fnd_rec(fd, F_TOPEND, 1 << list->rectype, list->subtype, NULL);
672 err = rea_rec(fd, 0, NULL, 0, &rec_len, NULL);
677 rec = (UB*)malloc(rec_len);
682 err = rea_rec(fd, 0, rec, rec_len, NULL, NULL);
689 err = extbbslist_parserecord(list, rec, rec_len);
697 struct extbbslist_editcontext_t_ {
699 W view_l, view_t, view_r, view_b;
702 extbbslist_item_t *item;
708 #define EXTBBSLIST_ENTRY_HEIGHT 20
709 #define EXTBBSLIST_ENTRY_PADDING_TOP 1
711 #define EXTBBSLIST_TITLE_WIDTH 128
713 LOCAL extbbslist_item_t* extbbslist_editcontext_sentinelnode(extbbslist_editcontext_t *ctx)
715 return (extbbslist_item_t*)&ctx->sentinel;
718 LOCAL extbbslist_item_t *extbbslist_editcontext_searchitembyindex(extbbslist_editcontext_t *ctx, W index)
721 extbbslist_item_t *senti, *item;
723 senti = extbbslist_editcontext_sentinelnode(ctx);
724 item = extbbslist_item_nextnode(senti);
725 for (i = 0; item != senti; i++) {
729 item = extbbslist_item_nextnode(item);
734 LOCAL W extbbslist_editcontext_append_common(extbbslist_editcontext_t *ctx, CONST TC *title, W title_len, CONST TC *url, W url_len)
736 extbbslist_item_t *item, *senti;
739 item = extbbslist_item_new();
741 return -1; /* TODO */
744 err = extbbslist_item_assigntitle(item, title, title_len);
746 extbbslist_item_delete(item);
750 err = extbbslist_item_assignurl(item, url, url_len);
752 extbbslist_item_delete(item);
756 senti = extbbslist_editcontext_sentinelnode(ctx);
757 extbbslist_item_QueInsert(item, senti);
763 EXPORT W extbbslist_editcontext_append(extbbslist_editcontext_t *ctx, CONST TC *title, W title_len, CONST TC *url, W url_len)
767 err = extbbslist_editcontext_append_common(ctx, title, title_len, url, url_len);
775 EXPORT W extbbslist_editcontext_update(extbbslist_editcontext_t *ctx, W i, CONST TC *title, W title_len, CONST TC *url, W url_len)
777 extbbslist_item_t *item;
780 item = extbbslist_editcontext_searchitembyindex(ctx, i);
782 return -1; /* TODO */
787 err = extbbslist_item_assigntitle(item, title, title_len);
792 err = extbbslist_item_assignurl(item, url, url_len);
800 LOCAL W extbbslist_editcontext_drawcolseparater(extbbslist_editcontext_t *ctx, GID target, W x_start, W y, W height, PAT *lnpat)
805 p2.y = p1.y + height - 1;
807 p1.x = x_start + EXTBBSLIST_TITLE_WIDTH + 4;
809 gdra_lin(target, p1, p2, 1, lnpat, G_STORE);
813 p2.x = ctx->view_r - ctx->view_l;
814 gdra_lin(target, p1, p2, 1, lnpat, G_STORE);
819 LOCAL W extbbslist_editcontext_drawitemtext(extbbslist_editcontext_t *ctx, GID target, W x_start, W y, PAT *lnpat, extbbslist_item_t *item)
825 gset_scr(target, 0x21);
827 gget_fon(target, &fspec, NULL);
829 fspec.size.h = fspec.size.v;
830 gset_fon(target, &fspec);
832 y2 = y + sz.v + EXTBBSLIST_ENTRY_PADDING_TOP;
833 gdra_stp(target, x_start, y2, item->title, item->title_len, G_STORE);
835 gset_scr(target, 0x21);
837 fspec.size.h = fspec.size.v / 2;
838 gset_fon(target, &fspec);
840 gdra_stp(target, x_start + EXTBBSLIST_TITLE_WIDTH + 8 , y2, item->url.tc, item->url.tc_len, G_STORE);
842 extbbslist_editcontext_drawcolseparater(ctx, target, x_start, y, EXTBBSLIST_ENTRY_HEIGHT, lnpat);
847 EXPORT W extbbslist_editcontext_draw(extbbslist_editcontext_t *ctx, GID target, RECT *r)
850 extbbslist_item_t *senti, *item;
867 senti = extbbslist_editcontext_sentinelnode(ctx);
868 item = extbbslist_item_nextnode(senti);
873 if ((ctx->view_t <= (i + 1) * EXTBBSLIST_ENTRY_HEIGHT)&&(i * EXTBBSLIST_ENTRY_HEIGHT <= ctx->view_b)) {
874 if (ctx->selected.item == item) {
875 bgpat.spat.fgcol = 0x10000000;
876 lnpat.spat.fgcol = 0x10FFFFFF;
877 gset_chc(target, 0x10FFFFFF, 0x10000000);
879 bgpat.spat.fgcol = 0x10FFFFFF;
880 lnpat.spat.fgcol = 0x10000000;
881 gset_chc(target, 0x10000000, 0x10FFFFFF);
883 bgr.c.left = ctx->view_l;
884 bgr.c.top = i * EXTBBSLIST_ENTRY_HEIGHT - ctx->view_t;
885 bgr.c.right = ctx->view_r;
886 bgr.c.bottom = (i+1) * EXTBBSLIST_ENTRY_HEIGHT - ctx->view_t;
887 gfil_rec(target, bgr, &bgpat, 0, G_STORE);
890 y = i * EXTBBSLIST_ENTRY_HEIGHT - ctx->view_t;
891 extbbslist_editcontext_drawitemtext(ctx, target, x, y, &lnpat, item);
894 item = extbbslist_item_nextnode(item);
900 EXPORT Bool extbbslist_editcontext_finditem(extbbslist_editcontext_t *ctx, PNT rel_pos, W *index)
903 n = (rel_pos.y + ctx->view_t) / EXTBBSLIST_ENTRY_HEIGHT;
911 IMPORT W extbbslist_editcontext_swapitem(extbbslist_editcontext_t *ctx, W i0, W i1)
913 extbbslist_item_t *item0, *item1, *item0_next, *item1_next;
925 item0 = extbbslist_editcontext_searchitembyindex(ctx, i0);
929 item0_next = extbbslist_item_nextnode(item0);
930 item1 = extbbslist_editcontext_searchitembyindex(ctx, i1);
934 item1_next = extbbslist_item_nextnode(item1);
936 if (ctx->selected.index == i0) {
937 ctx->selected.index = i1;
938 } else if (ctx->selected.index == i1) {
939 ctx->selected.index = i0;
944 extbbslist_item_QueRemove(item1);
945 extbbslist_item_QueInsert(item1, item0);
949 extbbslist_item_QueRemove(item1);
950 extbbslist_item_QueInsert(item1, item0_next);
951 extbbslist_item_QueRemove(item0);
952 extbbslist_item_QueInsert(item0, item1_next);
957 IMPORT W extbbslist_editcontext_deleteitem(extbbslist_editcontext_t *ctx, W i)
959 extbbslist_item_t *item;
961 item = extbbslist_editcontext_searchitembyindex(ctx, i);
963 return -1; /* TODO */
965 extbbslist_item_delete(item);
968 if (ctx->selected.index == i) {
969 ctx->selected.item = NULL;
970 ctx->selected.index = -1;
972 if (ctx->selected.index > i) {
973 ctx->selected.index--;
978 IMPORT VOID extbbslist_editcontext_setselect(extbbslist_editcontext_t *ctx, W i)
980 extbbslist_item_t *item;
982 item = extbbslist_editcontext_searchitembyindex(ctx, i);
984 ctx->selected.item = NULL;
985 ctx->selected.index = -1;
988 ctx->selected.item = item;
989 ctx->selected.index = i;
992 EXPORT W extbbslist_editcontext_getselect(extbbslist_editcontext_t *ctx)
994 return ctx->selected.index;
997 EXPORT Bool extbbslist_editcontext_ischanged(extbbslist_editcontext_t *ctx)
1002 EXPORT VOID extbbslist_editcontext_setviewrect(extbbslist_editcontext_t *ctx, W l, W t, W r, W b)
1010 EXPORT VOID extbbslist_editcontext_getviewrect(extbbslist_editcontext_t *ctx, W *l, W *t, W *r, W *b)
1018 EXPORT VOID extbbslist_editcontext_scrollviewrect(extbbslist_editcontext_t *ctx, W dh, W dv)
1026 EXPORT VOID extbbslist_editcontext_getdrawrect(extbbslist_editcontext_t *ctx, GID gid, W *l, W *t, W *r, W *b)
1028 extbbslist_item_t *senti, *item;
1032 gget_fon(gid, &fspec, NULL);
1033 fspec.size.h = fspec.size.v / 2;
1034 gset_fon(gid, &fspec);
1036 senti = extbbslist_editcontext_sentinelnode(ctx);
1037 item = extbbslist_item_nextnode(senti);
1039 if (item == senti) {
1043 width = gget_stw(gid, item->url.tc, item->url.tc_len, NULL, NULL);
1051 item = extbbslist_item_nextnode(item);
1056 *r = EXTBBSLIST_TITLE_WIDTH + 8 + max + 4;
1057 *b = EXTBBSLIST_ENTRY_HEIGHT * ctx->num;
1060 LOCAL extbbslist_editcontext_t* extbbslist_editcontext_new()
1062 extbbslist_editcontext_t *ctx;
1064 ctx = (extbbslist_editcontext_t*)malloc(sizeof(extbbslist_editcontext_t));
1068 QueInit(&ctx->sentinel);
1074 ctx->selected.item = NULL;
1075 ctx->selected.index = -1;
1076 ctx->changed = False;
1081 LOCAL VOID extbbslist_editcontext_delete(extbbslist_editcontext_t *ctx)
1083 extbbslist_item_t *item;
1087 empty = isQueEmpty(&ctx->sentinel);
1088 if (empty == True) {
1091 item = (extbbslist_item_t*)ctx->sentinel.prev;
1092 extbbslist_item_delete(item);
1097 EXPORT extbbslist_editcontext_t* extbbslist_startedit(extbbslist_t *list)
1099 extbbslist_editcontext_t *ctx;
1100 extbbslist_item_t *senti, *item;
1103 if (list->ctx != NULL) {
1106 if (list->edit != NULL) {
1110 ctx = extbbslist_editcontext_new();
1115 senti = extbbslist_sentinelnode(list);
1116 item = extbbslist_item_nextnode(senti);
1117 for (; item != senti;) {
1118 err = extbbslist_editcontext_append_common(ctx, item->title, item->title_len, item->url.tc, item->url.tc_len);
1120 extbbslist_editcontext_delete(ctx);
1123 item = extbbslist_item_nextnode(item);
1131 EXPORT VOID extbbslist_endedit(extbbslist_t *list, extbbslist_editcontext_t *ctx, Bool update)
1133 extbbslist_item_t *sentinel, *next;
1136 if ((update != False)&&(ctx->changed != False)) {
1137 extbbslist_clear(list);
1139 sentinel = extbbslist_editcontext_sentinelnode(ctx);
1141 empty = extbbslist_item_isQueEmpty(sentinel);
1142 if (empty == False) {
1143 next = extbbslist_item_nextnode(sentinel);
1144 extbbslist_item_QueRemove(sentinel);
1146 sentinel = extbbslist_sentinelnode(list);
1147 extbbslist_item_QueInsert(sentinel, next);
1149 list->num = ctx->num;
1153 list->changed = True;
1157 extbbslist_editcontext_delete(ctx);
1160 struct extbbslist_readcontext_t_ {
1161 extbbslist_item_t *sentinel;
1162 extbbslist_item_t *curr;
1165 EXPORT Bool extbbslist_readcontext_getnext(extbbslist_readcontext_t *ctx, TC **title, W *title_len, UB **url, W *url_len)
1167 if (ctx->curr == ctx->sentinel) {
1170 *title = ctx->curr->title;
1171 *title_len = ctx->curr->title_len;
1172 *url = ctx->curr->url.asc;
1173 *url_len = ctx->curr->url.asc_len;
1174 ctx->curr = extbbslist_item_nextnode(ctx->curr);
1178 LOCAL extbbslist_readcontext_t* extbbslist_readcontext_new(extbbslist_item_t *senti, extbbslist_item_t *curr)
1180 extbbslist_readcontext_t *ctx;
1182 ctx = (extbbslist_readcontext_t*)malloc(sizeof(extbbslist_readcontext_t));
1186 ctx->sentinel = senti;
1192 LOCAL VOID extbbslist_readcontext_delete(extbbslist_readcontext_t *ctx)
1197 EXPORT extbbslist_readcontext_t* extbbslist_startread(extbbslist_t *list)
1199 extbbslist_readcontext_t *ctx;
1200 extbbslist_item_t *senti, *curr;
1202 senti = extbbslist_sentinelnode(list);
1203 curr = extbbslist_item_nextnode(senti);
1204 ctx = extbbslist_readcontext_new(senti, curr);
1212 EXPORT VOID extbbslist_endread(extbbslist_t *list, extbbslist_readcontext_t *ctx)
1215 extbbslist_readcontext_delete(ctx);
1218 LOCAL VOID extbbslist_initialize(extbbslist_t *list, LINK *db_link, W rectype, UH subtype)
1220 QueInit(&list->sentinel);
1224 list->lnk = db_link;
1225 list->rectype = rectype;
1226 list->subtype = subtype;
1227 list->changed = False;
1230 LOCAL VOID extbbslist_finalize(extbbslist_t *list)
1232 extbbslist_clear(list);
1235 EXPORT extbbslist_t* extbbslist_new(LINK *db_link, W rectype, UH subtype)
1239 list = malloc(sizeof(extbbslist_t));
1243 extbbslist_initialize(list, db_link, rectype, subtype);
1247 EXPORT VOID extbbslist_delete(extbbslist_t *list)
1249 extbbslist_finalize(list);