4 * Copyright (c) 2009-2010 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
33 #include <btron/btron.h>
35 #include <btron/libapp.h>
37 #include <bsys/queue.h>
39 #ifdef BCHAN_CONFIG_DEBUG
40 # define DP(arg) printf arg
41 # define DP_ER(msg, err) printf("%s (%d/%x)\n", msg, err>>16, err)
44 # define DP_ER(msg, err) /**/
47 typedef W (*iterate_callback_ch)(VP arg, TC ch);
48 typedef W (*iterate_callback_br)(VP arg);
49 typedef W (*iterate_callback_chratio)(VP arg, RATIO w_ratio, RATIO h_ratio);
50 typedef W (*iterate_callback_chcolor)(VP arg, COLOR color);
51 typedef W (*iterate_callback_bchanappl)(VP arg, UB *seg, UB subid);
53 typedef struct iterate_callbacks_t_ iterate_callbacks_t;
54 struct iterate_callbacks_t_ {
55 iterate_callback_chcolor callback_chcolor;
56 iterate_callback_chratio callback_chratio;
57 iterate_callback_ch callback_ch;
58 iterate_callback_br callback_br;
59 iterate_callback_bchanappl callback_bchanappl;
62 LOCAL VOID parse_fusen_chration(UB attr, UB *data, iterate_callbacks_t *callbacks, VP arg)
64 RATIO w_ratio,h_ratio;
66 w_ratio = *(RATIO*)(data + 4);
67 h_ratio = *(RATIO*)(data + 2);
69 (*callbacks->callback_chratio)(arg, w_ratio, h_ratio);
72 LOCAL VOID parse_fusen_chcolor(UB attr, UB *data, iterate_callbacks_t *callbacks, VP arg)
76 color = *(COLOR*)(data + 2);
78 (*callbacks->callback_chcolor)(arg, color);
81 LOCAL VOID parse_fusen_TS_TAPPL(LTADSEG *seg, UB *data, iterate_callbacks_t *callbacks, VP arg)
83 TT_BCHAN *fsn = (TT_BCHAN*)data;
85 if ((fsn->appl[0] == 0x8000)&&(fsn->appl[1] == 0xC053)&&(fsn->appl[2] == 0x8000)) {
86 (*callbacks->callback_bchanappl)(arg, (UB*)seg, fsn->subid);
90 LOCAL VOID parse_fusen(LTADSEG *seg, iterate_callbacks_t *callbacks, VP arg)
97 segid = seg->id & 0xFF;
99 if (seg->len == 0xffff) {
100 data = ((UB*)seg) + 8;
102 data = ((UB*)seg) + 4;
105 subid = *(UH*)data >> 8;
106 attr = *(UH*)data & 0xff;
108 if (segid == TS_TFONT) {
111 parse_fusen_chration(attr, data, callbacks, arg);
114 parse_fusen_chcolor(attr, data, callbacks, arg);
117 } else if (segid == TS_TAPPL) {
118 parse_fusen_TS_TAPPL(seg, data, callbacks, arg);
122 LOCAL W parse_tad(TC *str, W len, iterate_callbacks_t *callbacks, VP arg)
129 for (i=0;i<len;i++) {
132 /* temporary. should be move in convarting sjis? */
137 if ((str[i+1] == TK_b)
139 &&(str[i+3] == TK_GTTN)) {
140 (*callbacks->callback_br)(arg);
148 if ((str[i+1] == TK_l)
150 &&(str[i+3] == TK_SCLN)) {
151 (*callbacks->callback_ch)(arg, TK_LSTN);
154 } else if ((str[i+1] == TK_g)
156 &&(str[i+3] == TK_SCLN)) {
157 (*callbacks->callback_ch)(arg, TK_GTTN);
168 if ((str[i] & 0xFF80) == 0xFF80) {
169 seg = (LTADSEG*)(str + i);
170 if (seg->len == 0xffff) {
171 i += seg->llen / 2 + 3;
173 i += seg->len / 2 + 1;
175 parse_fusen(seg, callbacks, arg);
176 } else if (str[i] == TK_NL) {
177 (*callbacks->callback_br)(arg);
179 (*callbacks->callback_ch)(arg, str[i]);
186 typedef struct actionlist_data_t_ actionlist_data_t;
187 struct actionlist_data_t_ {
195 struct actionlist_t_ {
196 actionlist_data_t sentinel;
199 LOCAL actionlist_data_t* actionlist_data_next(actionlist_data_t *data)
201 return (actionlist_data_t*)data->queue.next;
204 LOCAL actionlist_data_t* actionlist_data_new(RECT r, W type, UB *start, UB *end)
206 actionlist_data_t *alist_data;
208 alist_data = malloc(sizeof(actionlist_data_t));
209 if (alist_data == NULL) {
213 alist_data->type = type;
214 alist_data->start = start;
215 alist_data->end = end;
220 LOCAL VOID actionlist_data_delete(actionlist_data_t *cache_data)
222 QueRemove(&(cache_data->queue));
226 LOCAL W actionlist_appenddata(actionlist_t *alist, RECT r, W type, UB *start, UB *end)
228 actionlist_data_t *alist_data;
230 alist_data = actionlist_data_new(r, type, start, end);
231 if (alist_data == NULL) {
232 return -1; /* TODO */
234 QueInsert(&(alist_data->queue), &(alist->sentinel.queue));
239 EXPORT W actionlist_findboard(actionlist_t *alist, PNT pos, RECT *r, W *type, UB **start, W *len)
241 actionlist_data_t *alist_data;
244 alist_data = &(alist->sentinel);
246 alist_data = actionlist_data_next(alist_data);
247 if (alist_data == &(alist->sentinel)) {
250 n = inrect(alist_data->r, pos);
253 *type = alist_data->type;
254 *start = alist_data->start;
255 *len = alist_data->end - alist_data->start;
263 EXPORT actionlist_t* actionlist_new()
267 alist = (actionlist_t*)malloc(sizeof(actionlist_t));
271 QueInit(&(alist->sentinel.queue));
275 EXPORT VOID actionlist_delete(actionlist_t *alist)
277 actionlist_data_t *alist_data;
281 ok = isQueEmpty(&(alist->sentinel.queue));
285 alist_data = actionlist_data_next(&alist->sentinel);
286 actionlist_data_delete(alist_data);
291 typedef struct tadlib_calcdrawsize_t_ tadlib_calcdrawsize_t;
292 struct tadlib_calcdrawsize_t_ {
302 LOCAL W tadlib_calcdrawsize_ch(VP arg, TC ch)
306 tadlib_calcdrawsize_t *ctx;
307 ctx = (tadlib_calcdrawsize_t*)arg;
309 width = gget_chw(ctx->gid, ch);
313 ctx->ln_width += width;
318 LOCAL W tadlib_calcdrawsize_br(VP arg)
320 tadlib_calcdrawsize_t *ctx;
321 ctx = (tadlib_calcdrawsize_t*)arg;
323 if (ctx->ln_width > ctx->sz.h) {
324 ctx->sz.h = ctx->ln_width;
330 LOCAL W tadlib_calcdrawsize_chratio(VP arg, RATIO w_ratio, RATIO h_ratio)
332 tadlib_calcdrawsize_t *ctx;
337 ctx = (tadlib_calcdrawsize_t*)arg;
340 ratio_a = w_ratio >> 8;
341 ratio_b = w_ratio & 0xFF;
343 if ((ratio_a * 2 > ratio_b)||(ratio_b == 0)) {
344 gget_fon(gid, &spec, NULL);
345 spec.attr |= FT_PROP;
348 gset_fon(gid, &spec);
349 ctx->isHankaku = False;
351 gget_fon(gid, &spec, NULL);
352 spec.attr |= FT_PROP;
355 gset_fon(gid, &spec);
356 ctx->isHankaku = True;
362 LOCAL W tadlib_calcdrawsize_chcolor(VP arg, COLOR color)
367 LOCAL W tadlib_calcdrawsize_bchanappl(VP arg, UB *seg, UB subid)
369 tadlib_calcdrawsize_t *ctx;
373 ctx = (tadlib_calcdrawsize_t*)arg;
376 case TT_BCHAN_SUBID_ANCHOR_START:
377 ctx->astart.x = ctx->ln_width;
378 ctx->astart.y = ctx->sz.v;
381 case TT_BCHAN_SUBID_ANCHOR_END:
382 r.c.left = ctx->astart.x;
383 r.c.top = ctx->astart.y - 16;
384 r.c.right = ctx->ln_width;
385 r.c.bottom = ctx->astart.y;
386 err = actionlist_appenddata(ctx->alist, r, ACTIONLIST_ACTIONTYPE_ANCHOR, ctx->startseg, seg);
388 case TT_BCHAN_SUBID_URL_START:
389 ctx->astart.x = ctx->ln_width;
390 ctx->astart.y = ctx->sz.v;
393 case TT_BCHAN_SUBID_URL_END:
394 r.c.left = ctx->astart.x;
395 r.c.top = ctx->astart.y - 16;
396 r.c.right = ctx->ln_width;
397 r.c.bottom = ctx->astart.y;
398 err = actionlist_appenddata(ctx->alist, r, ACTIONLIST_ACTIONTYPE_URL, ctx->startseg, seg);
405 EXPORT W tadlib_calcdrawsize(TC *str, W len, GID gid, SIZE *sz, actionlist_t **alist)
408 tadlib_calcdrawsize_t ctx;
409 iterate_callbacks_t callbacks;
416 ctx.alist = actionlist_new();
417 if (ctx.alist == NULL) {
418 return -1; /* TODO */
421 callbacks.callback_chcolor = tadlib_calcdrawsize_chcolor;
422 callbacks.callback_chratio = tadlib_calcdrawsize_chratio;
423 callbacks.callback_ch = tadlib_calcdrawsize_ch;
424 callbacks.callback_br = tadlib_calcdrawsize_br;
425 callbacks.callback_bchanappl = tadlib_calcdrawsize_bchanappl;
427 err = parse_tad(str, len, &callbacks, &ctx);
432 if (ctx.ln_width > ctx.sz.h) {
433 ctx.sz.h = ctx.ln_width;
441 typedef struct tadlib_drawtext_t_ tadlib_drawtext_t;
442 struct tadlib_drawtext_t_ {
448 LOCAL W tadlib_drawtext_ch(VP arg, TC ch)
450 tadlib_drawtext_t *ctx;
451 ctx = (tadlib_drawtext_t*)arg;
454 if (ctx->isHankaku == True) {
455 gset_chp(ctx->gid, 4, 0, 0);
457 gdra_chr(ctx->gid, ch, G_STORE);
460 gdra_chr(ctx->gid, ch, G_STORE);
466 LOCAL W tadlib_drawtext_br(VP arg)
469 tadlib_drawtext_t *ctx;
470 ctx = (tadlib_drawtext_t*)arg;
472 gget_chp(ctx->gid, &x, &y);
473 gset_chp(ctx->gid, - ctx->dh, y+16, 1);
478 LOCAL W tadlib_drawtext_chratio(VP arg, RATIO w_ratio, RATIO h_ratio)
480 tadlib_drawtext_t *ctx;
485 ctx = (tadlib_drawtext_t*)arg;
488 ratio_a = w_ratio >> 8;
489 ratio_b = w_ratio & 0xFF;
491 if ((ratio_a * 2 > ratio_b)||(ratio_b == 0)) {
492 gget_fon(gid, &spec, NULL);
493 spec.attr |= FT_PROP;
496 gset_fon(gid, &spec);
497 ctx->isHankaku = False;
499 gget_fon(gid, &spec, NULL);
500 spec.attr |= FT_PROP;
503 gset_fon(gid, &spec);
504 ctx->isHankaku = True;
510 LOCAL W tadlib_drawtext_chcolor(VP arg, COLOR color)
512 tadlib_drawtext_t *ctx;
515 ctx = (tadlib_drawtext_t*)arg;
518 return gset_chc(gid, color, /*tmp*/0x10efefef);
521 LOCAL W tadlib_drawtext_bchanappl(VP arg, UB *seg, UB subid)
523 tadlib_drawtext_t *ctx;
527 ctx = (tadlib_drawtext_t*)arg;
531 case TT_BCHAN_SUBID_ANCHOR_START:
532 err = gset_chc(gid, 0x100000ff, /*tmp*/0x10efefef);
534 case TT_BCHAN_SUBID_ANCHOR_END:
535 err = gset_chc(gid, 0x10000000, /*tmp*/0x10efefef);
537 case TT_BCHAN_SUBID_URL_START:
538 err = gset_chc(gid, 0x100000ff, /*tmp*/0x10efefef);
540 case TT_BCHAN_SUBID_URL_END:
541 err = gset_chc(gid, 0x10000000, /*tmp*/0x10efefef);
547 EXPORT W tadlib_drawtext(TC *str, W len, GID gid, W dh, W dv)
549 tadlib_drawtext_t ctx;
550 iterate_callbacks_t callbacks;
557 callbacks.callback_chcolor = tadlib_drawtext_chcolor;
558 callbacks.callback_chratio = tadlib_drawtext_chratio;
559 callbacks.callback_ch = tadlib_drawtext_ch;
560 callbacks.callback_br = tadlib_drawtext_br;
561 callbacks.callback_bchanappl = tadlib_drawtext_bchanappl;
563 return parse_tad(str, len, &callbacks, &ctx);
566 EXPORT W taditerator_next(taditerator_t *iterator, TC **pos, TC *segment, LTADSEG **seg, W *segsize, UB **data)
571 ch = iterator->bin + iterator->index;
576 if (iterator->index >= iterator->len) {
578 return TADITERATOR_RESULT_END;
581 if ((*ch & 0xFF80) == 0xFF80) {
583 *segment = *ch & 0xFF;
585 if (seg0->len == 0xffff) {
586 iterator->index += 1 + seg0->llen / 2 + 3;
587 *segsize = seg0->llen;
588 *data = ((UB*)seg0) + 8;
591 iterator->index += 1 + seg0->len / 2 + 1;
592 *segsize = seg0->len;
593 *data = ((UB*)seg0) + 4;
596 return TADITERATOR_RESULT_SEGMENT;
604 return TADITERATOR_RESULT_CHARCTOR;
608 EXPORT VOID taditerator_initialize(taditerator_t *iterator, TC *bin, W strlen)
611 iterator->len = strlen;
615 EXPORT VOID taditerator_finalize(taditerator_t *iterator)
619 EXPORT W tadlib_remove_TA_APPL_calcsize(TC *str, W len)
626 TADITERATOR_RESULT_T ret;
629 taditerator_initialize(&iter, str, len);
633 ret = taditerator_next(&iter, NULL, &ch, &seg, &size, &data);
634 if (ret == TADITERATOR_RESULT_CHARCTOR) {
636 } else if (ret == TADITERATOR_RESULT_SEGMENT) {
637 if (ch != TS_TAPPL) {
638 if (seg->len == 0xffff) {
639 allsize += seg->llen + 8;
641 allsize += seg->len + 4;
644 } else if (ret == TADITERATOR_RESULT_END) {
649 taditerator_finalize(&iter);
654 EXPORT W tadlib_remove_TA_APPL(TC *str, W len, TC *data, W data_len)
661 TADITERATOR_RESULT_T ret;
663 taditerator_initialize(&iter, str, len);
668 ret = taditerator_next(&iter, NULL, &ch, &seg, &size, &data0);
669 if (ret == TADITERATOR_RESULT_CHARCTOR) {
670 memcpy(dest + i, &ch, size);
672 } else if (ret == TADITERATOR_RESULT_SEGMENT) {
673 if (ch != TS_TAPPL) {
674 if (seg->len == 0xffff) {
675 size = seg->llen + 8;
679 memcpy(dest + i, seg, size);
682 } else if (ret == TADITERATOR_RESULT_END) {
687 taditerator_finalize(&iter);
692 LOCAL TC dec[] = {TK_0,TK_1,TK_2,TK_3,TK_4,TK_5,TK_6,TK_7,TK_8,TK_9};
694 EXPORT W tadlib_UW_to_str(UW val, TC *dest, W dest_len)
696 W i = 0, digit, draw = 0;
703 digit = val / 1000 % 10;
704 if ((digit != 0)||(draw != 0)) {
705 dest[i++] = dec[digit];
708 digit = val / 100 % 10;
709 if ((digit != 0)||(draw != 0)) {
710 dest[i++] = dec[digit];
713 digit = val / 10 % 10;
714 if ((digit != 0)||(draw != 0)) {
715 dest[i++] = dec[digit];
719 if ((digit != 0)||(draw != 0)) {
720 dest[i++] = dec[digit];
727 EXPORT VOID tadlib_separete_datepart(TC *str, W len, TC **date, W *date_len, TC **id, W *id_len, TC **beid, W *beid_len)
734 TADITERATOR_RESULT_T ret;
735 Bool checktype = False;
740 } target = PARSEDATE_DATE;
749 taditerator_initialize(&iter, str, len);
752 ret = taditerator_next(&iter, &pos, &ch, &seg, &size, &data0);
753 if (ret == TADITERATOR_RESULT_CHARCTOR) {
754 if (checktype == True) {
758 *date_len = pos - *date - 1;
761 *id_len = pos - *id - 1;
764 *beid_len = pos - *beid - 1;
768 target = PARSEDATE_ID;
769 } else if (ch == TK_B) {
772 *date_len = pos - *date - 1;
775 *id_len = pos - *id - 1;
778 *beid_len = pos - *beid - 1;
782 target = PARSEDATE_BEID;
790 } else if (ret == TADITERATOR_RESULT_SEGMENT) {
791 } else if (ret == TADITERATOR_RESULT_END) {
794 *date_len = pos - *date;
800 *beid_len = pos - *beid;
807 taditerator_finalize(&iter);
810 #define TCTOKENCHECKER_FLAG_NOTEXIST 0x00000001
811 #define TCTOKENCHECKER_FLAG_AFTERENDCHAR 0x00000002
813 EXPORT VOID tctokenchecker_clear(tctokenchecker_t *checker)
815 checker->stringindex = 0;
816 checker->listindex_start = 0;
817 checker->listindex_end = checker->namelistnum;
821 EXPORT W tctokenchecker_inputchar(tctokenchecker_t *checker, TC c, W *val)
824 tctokenchecker_valuetuple_t *namelist = checker->namelist;
826 if ((checker->flag & TCTOKENCHECKER_FLAG_AFTERENDCHAR) != 0) {
827 return TCTOKENCHECKER_AFTER_END;
831 if ((checker->endtokens)[i] == TNULL) {
834 if (c == (checker->endtokens)[i]) {
835 checker->flag |= TCTOKENCHECKER_FLAG_AFTERENDCHAR;
836 if ((checker->flag & TCTOKENCHECKER_FLAG_NOTEXIST) != 0) {
837 return TCTOKENCHECKER_NOMATCH;
839 if ((namelist[checker->listindex_start]).name[checker->stringindex] == TNULL) {
840 /*List's Name End and receive EndToken = found match string*/
841 *val = (namelist[checker->listindex_start]).val;
842 return TCTOKENCHECKER_DETERMINE;
844 /*List's Name continue but receive endtoken.*/
845 return TCTOKENCHECKER_NOMATCH;
849 if ((checker->flag & TCTOKENCHECKER_FLAG_NOTEXIST) != 0) {
850 return TCTOKENCHECKER_CONTINUE_NOMATCH;
853 for (i = checker->listindex_start; i < checker->listindex_end; i++) {
854 if ((namelist[i]).name[checker->stringindex] == c) {
858 if (i == checker->listindex_end) { /*receive char is not matched.*/
859 checker->flag &= TCTOKENCHECKER_FLAG_NOTEXIST;
860 return TCTOKENCHECKER_CONTINUE_NOMATCH;
862 checker->listindex_start = i;
863 for (i = i+1; i < checker->listindex_end; i++) {
864 if ((namelist[i]).name[checker->stringindex] != c) {
868 checker->listindex_end = i;
870 if ((namelist[checker->listindex_start]).name[checker->stringindex] == '\0') {
871 /*Don't recive endtoken but List's Name is end.*/
872 checker->flag |= TCTOKENCHECKER_FLAG_NOTEXIST;
873 return TCTOKENCHECKER_CONTINUE_NOMATCH;
875 checker->stringindex++;
877 return TCTOKENCHECKER_CONTINUE;
880 EXPORT VOID tctokenchecker_getlastmatchedstring(tctokenchecker_t *checker, TC **str, W *len)
882 *str = (checker->namelist[checker->listindex_start]).name;
883 *len = checker->stringindex;
886 EXPORT VOID tctokenchecker_initialize(tctokenchecker_t *checker, tctokenchecker_valuetuple_t *namelist, W namelistnum, TC *endchars)
888 checker->namelist = namelist;
889 checker->namelistnum = namelistnum;
890 checker->endtokens = endchars;
891 checker->stringindex = 0;
892 checker->listindex_start = 0;
893 checker->listindex_end = checker->namelistnum;
897 EXPORT VOID tctokenchecker_finalize(tctokenchecker_t *checker)