OSDN Git Service

fix copyright year.
[bbk/bchan.git] / src / tadlib.c
1 /*
2  * tadlib.c
3  *
4  * Copyright (c) 2009-2010 project bchan
5  *
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.
9  *
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:
13  *
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.
18  *
19  * 2. Altered source versions must be plainly marked as such, and must not be
20  *    misrepresented as being the original software.
21  *
22  * 3. This notice may not be removed or altered from any source
23  *    distribution.
24  *
25  */
26
27 #include    "tadlib.h"
28
29 #include        <bstdio.h>
30 #include        <bstdlib.h>
31 #include        <tstring.h>
32 #include        <tcode.h>
33 #include        <btron/btron.h>
34 #include        <btron/dp.h>
35 #include        <btron/libapp.h>
36 #include        <tad.h>
37 #include        <bsys/queue.h>
38
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)
42 #else
43 # define DP(arg) /**/
44 # define DP_ER(msg, err) /**/
45 #endif
46
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);
52
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;
60 };
61
62 LOCAL VOID parse_fusen_chration(UB attr, UB *data, iterate_callbacks_t *callbacks, VP arg)
63 {
64         RATIO w_ratio,h_ratio;
65
66         w_ratio = *(RATIO*)(data + 4);
67         h_ratio = *(RATIO*)(data + 2);
68
69         (*callbacks->callback_chratio)(arg, w_ratio, h_ratio);
70 }
71
72 LOCAL VOID parse_fusen_chcolor(UB attr, UB *data, iterate_callbacks_t *callbacks, VP arg)
73 {
74         COLOR color;
75
76         color = *(COLOR*)(data + 2);
77
78         (*callbacks->callback_chcolor)(arg, color);
79 }
80
81 LOCAL VOID parse_fusen_TS_TAPPL(LTADSEG *seg, UB *data, iterate_callbacks_t *callbacks, VP arg)
82 {
83         TT_BCHAN *fsn = (TT_BCHAN*)data;
84
85         if ((fsn->appl[0] == 0x8000)&&(fsn->appl[1] == 0xC053)&&(fsn->appl[2] == 0x8000)) {
86                 (*callbacks->callback_bchanappl)(arg, (UB*)seg, fsn->subid);            
87         }
88 }
89
90 LOCAL VOID parse_fusen(LTADSEG *seg, iterate_callbacks_t *callbacks, VP arg)
91 {
92         UB *data;
93         UB segid;
94         UB subid;
95         UB attr;
96
97         segid = seg->id & 0xFF;
98
99         if (seg->len == 0xffff) {
100                 data = ((UB*)seg) + 8;
101         } else {
102                 data = ((UB*)seg) + 4;
103         }
104
105         subid = *(UH*)data >> 8;
106         attr = *(UH*)data & 0xff;
107
108         if (segid == TS_TFONT) {
109                 switch (subid) {
110                 case 3:
111                         parse_fusen_chration(attr, data, callbacks, arg);
112                         break;
113                 case 6:
114                         parse_fusen_chcolor(attr, data, callbacks, arg);
115                         break;
116                 }
117         } else if (segid == TS_TAPPL) {
118                 parse_fusen_TS_TAPPL(seg, data, callbacks, arg);
119         }
120 }
121
122 LOCAL W parse_tad(TC *str, W len, iterate_callbacks_t *callbacks, VP arg)
123 {
124         W i;
125         TC ch;
126         LTADSEG *seg;
127         Bool skip;
128
129         for (i=0;i<len;i++) {
130                 ch = str[i];
131
132                 /* temporary. should be move in convarting sjis? */
133                 skip = False;
134                 switch(ch) {
135                 case TK_LSTN:
136                         if (i + 3 <= len) {
137                                 if ((str[i+1] == TK_b)
138                                         &&(str[i+2] == TK_r)
139                                         &&(str[i+3] == TK_GTTN)) {
140                                         (*callbacks->callback_br)(arg);
141                                         i+=3;
142                                         skip = True;
143                                 }
144                         }
145                         break;
146                 case TK_AND:
147                         if (i + 3 <= len) {
148                                 if ((str[i+1] == TK_l)
149                                         &&(str[i+2] == TK_t)
150                                         &&(str[i+3] == TK_SCLN)) {
151                                         (*callbacks->callback_ch)(arg, TK_LSTN);
152                                         i+=3;
153                                         skip = True;
154                                 } else if ((str[i+1] == TK_g)
155                                                    &&(str[i+2] == TK_t)
156                                                    &&(str[i+3] == TK_SCLN)) {
157                                         (*callbacks->callback_ch)(arg, TK_GTTN);
158                                         i+=3;
159                                         skip = True;
160                                 } 
161                         }
162                 }
163
164                 if (skip != False) {
165                         continue;
166                 }
167
168                 if ((str[i] & 0xFF80) == 0xFF80) {
169                         seg = (LTADSEG*)(str + i);
170                         if (seg->len == 0xffff) {
171                                 i += seg->llen / 2 + 3;
172                         } else {
173                                 i += seg->len / 2 + 1;
174                         }
175                         parse_fusen(seg, callbacks, arg);
176                 } else if (str[i] == TK_NL) {
177                         (*callbacks->callback_br)(arg);
178                 } else {
179                         (*callbacks->callback_ch)(arg, str[i]);
180                 }
181         }
182
183         return 0;
184 }
185
186 typedef struct actionlist_data_t_ actionlist_data_t;
187 struct actionlist_data_t_ {
188         QUEUE queue;
189         RECT r;
190         W type;
191         UB *start;
192         UB *end;
193 };
194
195 struct actionlist_t_ {
196         actionlist_data_t sentinel;
197 };
198
199 LOCAL actionlist_data_t* actionlist_data_next(actionlist_data_t *data)
200 {
201         return (actionlist_data_t*)data->queue.next;
202 }
203
204 LOCAL actionlist_data_t* actionlist_data_new(RECT r, W type, UB *start, UB *end)
205 {
206         actionlist_data_t *alist_data;
207
208         alist_data = malloc(sizeof(actionlist_data_t));
209         if (alist_data == NULL) {
210                 return NULL;
211         }
212         alist_data->r = r;
213         alist_data->type = type;
214         alist_data->start = start;
215         alist_data->end = end;
216
217         return alist_data;
218 }
219
220 LOCAL VOID actionlist_data_delete(actionlist_data_t *cache_data)
221 {
222         QueRemove(&(cache_data->queue));
223         free(cache_data);
224 }
225
226 LOCAL W actionlist_appenddata(actionlist_t *alist, RECT r, W type, UB *start, UB *end)
227 {
228         actionlist_data_t *alist_data;
229
230         alist_data = actionlist_data_new(r, type, start, end);
231         if (alist_data == NULL) {
232                 return -1; /* TODO */
233         }
234         QueInsert(&(alist_data->queue), &(alist->sentinel.queue));
235
236         return 0; /* TODO */
237 }
238
239 EXPORT W actionlist_findboard(actionlist_t *alist, PNT pos, RECT *r, W *type, UB **start, W *len)
240 {
241         actionlist_data_t *alist_data;
242         W n;
243
244         alist_data = &(alist->sentinel);
245         for (;;) {
246                 alist_data = actionlist_data_next(alist_data);
247                 if (alist_data == &(alist->sentinel)) {
248                         break;
249                 }
250                 n = inrect(alist_data->r, pos);
251                 if (n == 1) {
252                         *r = alist_data->r;
253                         *type = alist_data->type;
254                         *start = alist_data->start;
255                         *len = alist_data->end - alist_data->start;
256                         return 1;
257                 }
258         }
259
260         return 0;
261 }
262
263 EXPORT actionlist_t* actionlist_new()
264 {
265         actionlist_t *alist;
266
267         alist = (actionlist_t*)malloc(sizeof(actionlist_t));
268         if (alist == NULL) {
269                 return NULL;
270         }
271         QueInit(&(alist->sentinel.queue));
272         return alist;
273 }
274
275 EXPORT VOID actionlist_delete(actionlist_t *alist)
276 {
277         actionlist_data_t *alist_data;
278         Bool ok;
279
280         for (;;) {
281                 ok = isQueEmpty(&(alist->sentinel.queue));
282                 if (ok == True) {
283                         break;
284                 }
285                 alist_data = actionlist_data_next(&alist->sentinel);
286                 actionlist_data_delete(alist_data);
287         }
288         free(alist);
289 }
290
291 typedef struct tadlib_calcdrawsize_t_ tadlib_calcdrawsize_t;
292 struct tadlib_calcdrawsize_t_ {
293         GID gid;
294         SIZE sz;
295         H ln_width;
296         Bool isHankaku;
297         actionlist_t *alist;
298         PNT astart;
299         UB *startseg;
300 };
301
302 LOCAL W tadlib_calcdrawsize_ch(VP arg, TC ch)
303 {
304         W width;
305
306         tadlib_calcdrawsize_t *ctx;
307         ctx = (tadlib_calcdrawsize_t*)arg;
308
309         width = gget_chw(ctx->gid, ch);
310         if (width < 0) {
311                 return 0;
312         }
313         ctx->ln_width += width;
314
315         return 0;
316 }
317
318 LOCAL W tadlib_calcdrawsize_br(VP arg)
319 {
320         tadlib_calcdrawsize_t *ctx;
321         ctx = (tadlib_calcdrawsize_t*)arg;
322         ctx->sz.v += 16;
323         if (ctx->ln_width > ctx->sz.h) {
324                 ctx->sz.h = ctx->ln_width;
325         }
326         ctx->ln_width = 0;
327         return 0;
328 }
329
330 LOCAL W tadlib_calcdrawsize_chratio(VP arg, RATIO w_ratio, RATIO h_ratio)
331 {
332         tadlib_calcdrawsize_t *ctx;
333         GID gid;
334         FSSPEC spec;
335         W ratio_a, ratio_b;
336
337         ctx = (tadlib_calcdrawsize_t*)arg;
338         gid = ctx->gid;
339
340         ratio_a = w_ratio >> 8;
341         ratio_b = w_ratio & 0xFF;
342
343         if ((ratio_a * 2 > ratio_b)||(ratio_b == 0)) {
344                 gget_fon(gid, &spec, NULL);
345                 spec.attr |= FT_PROP;
346                 spec.size.h = 16;
347                 spec.size.v = 16;
348                 gset_fon(gid, &spec);
349                 ctx->isHankaku = False;
350         } else {
351                 gget_fon(gid, &spec, NULL);
352                 spec.attr |= FT_PROP;
353                 spec.size.h = 8;
354                 spec.size.v = 16;
355                 gset_fon(gid, &spec);
356                 ctx->isHankaku = True;
357         }
358
359         return 0;
360 }
361
362 LOCAL W tadlib_calcdrawsize_chcolor(VP arg, COLOR color)
363 {
364         return 0;
365 }
366
367 LOCAL W tadlib_calcdrawsize_bchanappl(VP arg, UB *seg, UB subid)
368 {
369         tadlib_calcdrawsize_t *ctx;
370         RECT r;
371         W err = 0;
372
373         ctx = (tadlib_calcdrawsize_t*)arg;
374
375         switch (subid) {
376         case TT_BCHAN_SUBID_ANCHOR_START:
377                 ctx->astart.x = ctx->ln_width;
378                 ctx->astart.y = ctx->sz.v;
379                 ctx->startseg = seg;
380                 break;
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);
387                 break;
388         case TT_BCHAN_SUBID_URL_START:
389                 ctx->astart.x = ctx->ln_width;
390                 ctx->astart.y = ctx->sz.v;
391                 ctx->startseg = seg;
392                 break;
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);
399                 break;
400         }
401
402         return err;
403 }
404
405 EXPORT W tadlib_calcdrawsize(TC *str, W len, GID gid, SIZE *sz, actionlist_t **alist)
406 {
407         W err;
408         tadlib_calcdrawsize_t ctx;
409         iterate_callbacks_t callbacks;
410
411         ctx.gid = gid;
412         ctx.isHankaku = 0;
413         ctx.sz.v = 16;
414         ctx.sz.h = 0;
415         ctx.ln_width = 0;
416         ctx.alist = actionlist_new();
417         if (ctx.alist == NULL) {
418                 return -1; /* TODO */
419         }
420
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;
426
427         err = parse_tad(str, len, &callbacks, &ctx);
428         if (err < 0) {
429                 return err;
430         }
431
432         if (ctx.ln_width > ctx.sz.h) {
433                 ctx.sz.h = ctx.ln_width;
434         }
435         *sz = ctx.sz;
436         *alist = ctx.alist;
437
438         return 0;
439 }
440
441 typedef struct tadlib_drawtext_t_ tadlib_drawtext_t;
442 struct tadlib_drawtext_t_ {
443         GID gid;
444         Bool isHankaku;
445         W dh,dv;
446 };
447
448 LOCAL W tadlib_drawtext_ch(VP arg, TC ch)
449 {
450         tadlib_drawtext_t *ctx;
451         ctx = (tadlib_drawtext_t*)arg;
452
453         if (ch == TK_USCR) {
454                 if (ctx->isHankaku == True) {
455                         gset_chp(ctx->gid, 4, 0, 0);
456                 } else {
457                         gdra_chr(ctx->gid, ch, G_STORE);
458                 }
459         } else {
460                 gdra_chr(ctx->gid, ch, G_STORE);
461         }
462
463         return 0;
464 }
465
466 LOCAL W tadlib_drawtext_br(VP arg)
467 {
468         W x,y;
469         tadlib_drawtext_t *ctx;
470         ctx = (tadlib_drawtext_t*)arg;
471
472         gget_chp(ctx->gid, &x, &y);
473         gset_chp(ctx->gid, - ctx->dh, y+16, 1);
474
475         return 0;
476 }
477
478 LOCAL W tadlib_drawtext_chratio(VP arg, RATIO w_ratio, RATIO h_ratio)
479 {
480         tadlib_drawtext_t *ctx;
481         GID gid;
482         FSSPEC spec;
483         W ratio_a, ratio_b;
484
485         ctx = (tadlib_drawtext_t*)arg;
486         gid = ctx->gid;
487
488         ratio_a = w_ratio >> 8;
489         ratio_b = w_ratio & 0xFF;
490
491         if ((ratio_a * 2 > ratio_b)||(ratio_b == 0)) {
492                 gget_fon(gid, &spec, NULL);
493                 spec.attr |= FT_PROP;
494                 spec.size.h = 16;
495                 spec.size.v = 16;
496                 gset_fon(gid, &spec);
497                 ctx->isHankaku = False;
498         } else {
499                 gget_fon(gid, &spec, NULL);
500                 spec.attr |= FT_PROP;
501                 spec.size.h = 8;
502                 spec.size.v = 16;
503                 gset_fon(gid, &spec);
504                 ctx->isHankaku = True;
505         }
506
507         return 0;
508 }
509
510 LOCAL W tadlib_drawtext_chcolor(VP arg, COLOR color)
511 {
512         tadlib_drawtext_t *ctx;
513         GID gid;
514
515         ctx = (tadlib_drawtext_t*)arg;
516         gid = ctx->gid;
517
518         return gset_chc(gid, color, /*tmp*/0x10efefef);
519 }
520
521 LOCAL W tadlib_drawtext_bchanappl(VP arg, UB *seg, UB subid)
522 {
523         tadlib_drawtext_t *ctx;
524         GID gid;
525         W err = 0;
526
527         ctx = (tadlib_drawtext_t*)arg;
528         gid = ctx->gid;
529
530         switch (subid) {
531         case TT_BCHAN_SUBID_ANCHOR_START:
532                 err = gset_chc(gid, 0x100000ff, /*tmp*/0x10efefef);
533                 break;
534         case TT_BCHAN_SUBID_ANCHOR_END:
535                 err = gset_chc(gid, 0x10000000, /*tmp*/0x10efefef);
536                 break;
537         case TT_BCHAN_SUBID_URL_START:
538                 err = gset_chc(gid, 0x100000ff, /*tmp*/0x10efefef);
539                 break;
540         case TT_BCHAN_SUBID_URL_END:
541                 err = gset_chc(gid, 0x10000000, /*tmp*/0x10efefef);
542                 break;
543         }
544         return err;
545 }
546
547 EXPORT W tadlib_drawtext(TC *str, W len, GID gid, W dh, W dv)
548 {
549         tadlib_drawtext_t ctx;
550         iterate_callbacks_t callbacks;
551
552         ctx.gid = gid;
553         ctx.isHankaku = 0;
554         ctx.dh = dh;
555         ctx.dv = dv;
556
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;
562
563         return parse_tad(str, len, &callbacks, &ctx);
564 }
565
566 EXPORT W taditerator_next(taditerator_t *iterator, TC **pos, TC *segment, LTADSEG **seg, W *segsize, UB **data)
567 {
568         TC *ch, *dummy_pos;
569         LTADSEG *seg0;
570
571         ch = iterator->bin + iterator->index;
572         if (pos == NULL) {
573                 pos = &dummy_pos;
574         }
575
576         if (iterator->index >= iterator->len) {
577                 *pos = ch;
578                 return TADITERATOR_RESULT_END;
579         }
580
581         if ((*ch & 0xFF80) == 0xFF80) {
582                 *pos = ch;
583                 *segment = *ch & 0xFF;
584                 seg0 = (LTADSEG*)ch;
585                 if (seg0->len == 0xffff) {
586                         iterator->index += 1 + seg0->llen / 2 + 3;
587                         *segsize = seg0->llen;
588                         *data = ((UB*)seg0) + 8;
589                         *seg = seg0;
590                 } else {
591                         iterator->index += 1 + seg0->len / 2 + 1;
592                         *segsize = seg0->len;
593                         *data = ((UB*)seg0) + 4;
594                         *seg = seg0;
595                 }
596                 return TADITERATOR_RESULT_SEGMENT;
597         } else {
598                 *pos = ch;
599                 *segment = *ch;
600                 *seg = NULL;
601                 *segsize = 2;
602                 *data = NULL;
603                 iterator->index++;
604                 return TADITERATOR_RESULT_CHARCTOR;
605         }
606 }
607
608 EXPORT VOID taditerator_initialize(taditerator_t *iterator, TC *bin, W strlen)
609 {
610         iterator->bin = bin;
611         iterator->len = strlen;
612         iterator->index = 0;
613 }
614
615 EXPORT VOID taditerator_finalize(taditerator_t *iterator)
616 {
617 }
618
619 EXPORT W tadlib_remove_TA_APPL_calcsize(TC *str, W len)
620 {
621         taditerator_t iter;
622         TC ch;
623         LTADSEG *seg;
624         W size;
625         UB *data;
626         TADITERATOR_RESULT_T ret;
627         W allsize;
628
629         taditerator_initialize(&iter, str, len);
630
631         allsize = 0;
632         for (;;) {
633                 ret = taditerator_next(&iter, NULL, &ch, &seg, &size, &data);
634                 if (ret == TADITERATOR_RESULT_CHARCTOR) {
635                         allsize += size;
636                 } else if (ret == TADITERATOR_RESULT_SEGMENT) {
637                         if (ch != TS_TAPPL) {
638                                 if (seg->len == 0xffff) {
639                                         allsize += seg->llen + 8;
640                                 } else {
641                                         allsize += seg->len + 4;
642                                 }
643                         }
644                 } else if (ret == TADITERATOR_RESULT_END) {
645                         break;
646                 }
647         }
648
649         taditerator_finalize(&iter);
650
651         return allsize;
652 }
653
654 EXPORT W tadlib_remove_TA_APPL(TC *str, W len, TC *data, W data_len)
655 {
656         taditerator_t iter;
657         TC ch;
658         LTADSEG *seg;
659         W size, i;
660         UB *data0, *dest;
661         TADITERATOR_RESULT_T ret;
662
663         taditerator_initialize(&iter, str, len);
664
665         i = 0;
666         dest = (UB*)data;
667         for (;;) {
668                 ret = taditerator_next(&iter, NULL, &ch, &seg, &size, &data0);
669                 if (ret == TADITERATOR_RESULT_CHARCTOR) {
670                         memcpy(dest + i, &ch, size);
671                         i += size;
672                 } else if (ret == TADITERATOR_RESULT_SEGMENT) {
673                         if (ch != TS_TAPPL) {
674                                 if (seg->len == 0xffff) {
675                                         size = seg->llen + 8;
676                                 } else {
677                                         size = seg->len + 4;
678                                 }
679                                 memcpy(dest + i, seg, size);
680                                 i += size;
681                         }
682                 } else if (ret == TADITERATOR_RESULT_END) {
683                         break;
684                 }
685         }
686
687         taditerator_finalize(&iter);
688
689         return i;
690 }
691
692 LOCAL TC dec[] = {TK_0,TK_1,TK_2,TK_3,TK_4,TK_5,TK_6,TK_7,TK_8,TK_9};
693
694 EXPORT W tadlib_UW_to_str(UW val, TC *dest, W dest_len)
695 {
696         W i = 0, digit, draw = 0;
697         TC dummy_str[10];
698
699         if (dest == NULL) {
700                 dest = dummy_str;
701         }
702
703         digit = val / 1000 % 10;
704         if ((digit != 0)||(draw != 0)) {
705                 dest[i++] = dec[digit];
706                 draw = 1;
707         }
708         digit = val / 100 % 10;
709         if ((digit != 0)||(draw != 0)) {
710                 dest[i++] = dec[digit];
711                 draw = 1;
712         }
713         digit = val / 10 % 10;
714         if ((digit != 0)||(draw != 0)) {
715                 dest[i++] = dec[digit];
716                 draw = 1;
717         }
718         digit = val % 10;
719         if ((digit != 0)||(draw != 0)) {
720                 dest[i++] = dec[digit];
721                 draw = 1;
722         }
723
724         return i;
725 }
726
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)
728 {
729         taditerator_t iter;
730         TC ch, *pos;
731         LTADSEG *seg;
732         W size;
733         UB *data0;
734         TADITERATOR_RESULT_T ret;
735         Bool checktype = False;
736         enum {
737                 PARSEDATE_DATE,
738                 PARSEDATE_ID,
739                 PARSEDATE_BEID
740         } target = PARSEDATE_DATE;
741
742         *date = str;
743         *date_len = 0;
744         *id = NULL;
745         *id_len = 0;
746         *beid = NULL;
747         *beid_len = 0;
748
749         taditerator_initialize(&iter, str, len);
750
751         for (;;) {
752                 ret = taditerator_next(&iter, &pos, &ch, &seg, &size, &data0);
753                 if (ret == TADITERATOR_RESULT_CHARCTOR) {
754                         if (checktype == True) {
755                                 if (ch == TK_I) {
756                                         switch (target) {
757                                         case PARSEDATE_DATE:
758                                                 *date_len = pos - *date - 1;
759                                                 break;
760                                         case PARSEDATE_ID:
761                                                 *id_len = pos - *id - 1;
762                                                 break;
763                                         case PARSEDATE_BEID:
764                                                 *beid_len = pos - *beid - 1;
765                                                 break;
766                                         }
767                                         *id = pos;
768                                         target = PARSEDATE_ID;
769                                 } else if (ch == TK_B) {
770                                         switch (target) {
771                                         case PARSEDATE_DATE:
772                                                 *date_len = pos - *date - 1;
773                                                 break;
774                                         case PARSEDATE_ID:
775                                                 *id_len = pos - *id - 1;
776                                                 break;
777                                         case PARSEDATE_BEID:
778                                                 *beid_len = pos - *beid - 1;
779                                                 break;
780                                         }
781                                         *beid = pos;
782                                         target = PARSEDATE_BEID;
783                                 }
784                                 checktype = False;
785                         } else {
786                                 if (ch == TK_KSP) {
787                                         checktype = True;
788                                 }
789                         }
790                 } else if (ret == TADITERATOR_RESULT_SEGMENT) {
791                 } else if (ret == TADITERATOR_RESULT_END) {
792                         switch (target) {
793                         case PARSEDATE_DATE:
794                                 *date_len = pos - *date;
795                                 break;
796                         case PARSEDATE_ID:
797                                 *id_len = pos - *id;
798                                 break;
799                         case PARSEDATE_BEID:
800                                 *beid_len = pos - *beid;
801                                 break;
802                         }
803                         break;
804                 }
805         }
806
807         taditerator_finalize(&iter);
808 }
809
810 #define TCTOKENCHECKER_FLAG_NOTEXIST 0x00000001
811 #define TCTOKENCHECKER_FLAG_AFTERENDCHAR 0x00000002
812
813 EXPORT VOID tctokenchecker_clear(tctokenchecker_t *checker)
814 {
815         checker->stringindex = 0;
816         checker->listindex_start = 0;
817         checker->listindex_end = checker->namelistnum;
818         checker->flag = 0;
819 }
820
821 EXPORT W tctokenchecker_inputchar(tctokenchecker_t *checker, TC c, W *val)
822 {
823         W i;
824         tctokenchecker_valuetuple_t *namelist = checker->namelist;
825
826         if ((checker->flag & TCTOKENCHECKER_FLAG_AFTERENDCHAR) != 0) {
827                 return TCTOKENCHECKER_AFTER_END;
828         }
829
830         for (i = 0;; i++) {
831                 if ((checker->endtokens)[i] == TNULL) {
832                         break;
833                 }
834                 if (c == (checker->endtokens)[i]) {
835                         checker->flag |= TCTOKENCHECKER_FLAG_AFTERENDCHAR;
836                         if ((checker->flag & TCTOKENCHECKER_FLAG_NOTEXIST) != 0) {
837                                 return TCTOKENCHECKER_NOMATCH;
838                         }
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;
843                         }
844                         /*List's Name continue but receive endtoken.*/
845                         return TCTOKENCHECKER_NOMATCH;
846                 }
847         }
848
849         if ((checker->flag & TCTOKENCHECKER_FLAG_NOTEXIST) != 0) {
850                 return TCTOKENCHECKER_CONTINUE_NOMATCH;
851         }
852
853         for (i = checker->listindex_start; i < checker->listindex_end; i++) {
854                 if ((namelist[i]).name[checker->stringindex] == c) {
855                         break;
856                 }
857         }
858         if (i == checker->listindex_end) { /*receive char is not matched.*/
859                 checker->flag &= TCTOKENCHECKER_FLAG_NOTEXIST;
860                 return TCTOKENCHECKER_CONTINUE_NOMATCH;
861         }
862         checker->listindex_start = i;
863         for (i = i+1; i < checker->listindex_end; i++) {
864                 if ((namelist[i]).name[checker->stringindex] != c) {
865                         break;
866                 }
867         }
868         checker->listindex_end = i;
869
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;
874         }
875         checker->stringindex++;
876
877         return TCTOKENCHECKER_CONTINUE;
878 }
879
880 EXPORT VOID tctokenchecker_getlastmatchedstring(tctokenchecker_t *checker, TC **str, W *len)
881 {
882         *str = (checker->namelist[checker->listindex_start]).name;
883         *len = checker->stringindex;
884 }
885
886 EXPORT VOID tctokenchecker_initialize(tctokenchecker_t *checker, tctokenchecker_valuetuple_t *namelist, W namelistnum, TC *endchars)
887 {
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;
894         checker->flag = 0;
895 }
896
897 EXPORT VOID tctokenchecker_finalize(tctokenchecker_t *checker)
898 {
899 }