#include #include #include #include #include "xwchar.h" #include "parse.h" #include "style.h" static void frame_parse_string(Frame *f, Tag *tag) { XCharStruct all; wchar_t *start, *wp, *p; /* int xlen;*/ BlockFormatInfo *bfi = frame_get_blockformatinfo(f); BlockStyleInfo *bsi = frame_get_blockstyleinfo(f); ParseInfo *pi = f->pinfo; /* in pre tag */ if (bfi->pre == TAG_OPEN) { start = p = tag->data; while (*p) { if (*p == '\n') { if (bfi->after_lf && bfi->next_linesep > 0) frame_add_vspace(f, bfi->next_linesep); bfi->after_lf = 0; if (p != start) { frame_add_string(f, start, p - start, 0); } else { bfi->max_ascent = bfi->prev_ascent; bfi->max_descent = bfi->prev_descent; } frame_add_lf(f,BR_NORMAL); start = ++p; continue; } p++; } if (p != start) { if (bfi->after_lf && bfi->next_linesep > 0) frame_add_vspace(f, bfi->next_linesep); bfi->after_lf = 0; frame_add_string(f, start, p - start, 0); } return; } /* normal string */ start = wp = p = tag->data; while (*start) { #if 0 fprintf(stderr,"start[%p] [%p] %d\n",start,bfi,bfi->cur_x); #endif p = start; /* xlen = 0;*/ word: /* paragraph */ if (bfi->paragraph) { if (bsi->text_align == ALIGN_NONE) { /* 字下げ */ if (IS_MB(*p)) bfi->cur_x += WcWidth(pi->istyle->oc, *p); else bfi->cur_x += 20; } bfi->paragraph = 0; } /* 単語の切り出し */ while (*p && *p != ' ' && !IS_MB(*p)) p++; /* xlen += WcWidth(f->istyle->oc,*p++);*/ if (*p && (*p == ' ' || wp == p)) p++; /* xlen += WcWidth(f->istyle->oc,*p++);*/ WcExtents(pi->istyle->oc, start, p - start, &all); if (bfi->cur_x + all.rbearing < WIDTH) { /* 行間空白処理 */ if (bfi->after_lf && bfi->next_linesep > 0) { frame_add_vspace(f, bfi->next_linesep); } bfi->after_lf = 0; if (!*p) { frame_add_string(f, start, p - start, 0); break; } #if 0 frame_add_string(f, start, p - start, 0); wp = start = p; continue; #else wp = p; goto word; #endif } /* 改行直後は禁則を無視 */ if (bfi->after_lf) { frame_add_string(f, start, p - start, 0); frame_add_lf(f,BR_NORMAL); wp = start = p; continue; } /* 行末禁則処理 (2文字まで) */ if (wp-1 >= start && gyomatsu_kinsoku(*(wp-1))) { wp--; if (wp-1 >= start && gyomatsu_kinsoku(*(wp-1))) wp--; } if (wp == start) { frame_add_lf(f, BR_NORMAL); continue; } /* 行頭禁則処理 (2文字まで) */ if (*wp && gyoto_kinsoku(*wp)) { wp++; if (*wp && gyoto_kinsoku(*wp)) wp++; } frame_add_string(f, start, wp - start, 0); start = wp; frame_add_lf(f, BR_NORMAL); continue; } } static void frame_parse_open(Frame *f, Tag *tag) { TagInfo *ommit; int ret; while (f->pinfo && f->pinfo->taginfo && /* no tag info */ (ret = frame_check_dtd(f, tag->ti, &ommit))) { if (ret == 1) { /* insert ommited tag */ Tag *tag = tag_new(TAG_normal); tag->ti = ommit; frame_push_parseinfo(f, tag); /* fprintf(stderr, "insert ommited tag![%s]\n", ommit->name); */ } else { if (tag->ti->block == TAG_BLOCK) { /* 開きタグの強制閉じ */ if (!(f->pinfo->taginfo->ommit & 0x02)) fprintf(stderr, "forcely close tag: %s\n", f->pinfo->taginfo->name); frame_pop_parseinfo(f); } else { /* fprintf(stderr, "warning: invalid tag:[%s]\n", tag->ti->name); */ break; } } } if (tag->ti->dtd != NULL) { frame_push_parseinfo(f, tag); /* not empty */ if (tag->ti->parse_func) tag->ti->parse_func(f, tag); } else { if (tag->ti->block == TAG_BLOCK) { frame_push_parseinfo(f, tag); /* empty */ if (tag->ti->parse_func) tag->ti->parse_func(f, tag); frame_pop_parseinfo(f); /* empty */ } else if (tag->ti->parse_func) tag->ti->parse_func(f, tag); } } static void frame_parse_close(Frame *f, Tag *tag) { if (!frame_find_parseinfo(f,tag->ti->id) || tag->ti->dtd == NULL) { fprintf(stderr,"Closing without open:[]\n", tag->ti->name); } else { while (f->pinfo->taginfo->id != tag->ti->id) { if (!(f->pinfo->taginfo->ommit & 0x02)) fprintf(stderr, "forcely close tag: %s\n", f->pinfo->taginfo->name); frame_pop_parseinfo(f); } frame_pop_parseinfo(f); } } #ifdef DEBUG void tag_showinfo(Tag *p); #endif void frame_parse(Frame *f) { Tag *tag; BlockFormatInfo *bfi; int ret = 0; if (f->tagwork == NULL) { f->eof = 1; return; } do { ret = f->tagwork->main(f->tagwork); while ((tag = tagwork_gettag(f->tagwork))) { #ifdef DEBUG tag_showinfo(tag); #endif switch (tag->type) { case TAG_normal: if (tag->mode == TAG_OPEN) frame_parse_open(f,tag); else frame_parse_close(f,tag); break; case TAG_string: frame_parse_string(f, tag); break; default: break; } } bfi = frame_get_blockformatinfo(f); /* } while (!ret);*/ } while (!ret && bfi->after_lf == 0); if (ret) { frame_add_lf(f, BR_ALL); while (f->pinfo->next) frame_pop_parseinfo(f); f->eof = ret; } bfi = frame_get_blockformatinfo(f); f->formatted_height = bfi->cur_y; }