#include #include #include #include #include "xwchar.h" #include "text.h" #include "image.h" #include "frame.h" #include "href.h" #include "parse.h" #ifndef MAX #define MAX(a,b) (((a)>(b))?(a):(b)) #endif static ColorList * colorlist_new(void) { ColorList *p; if ((p = malloc(sizeof(*p))) == NULL) { perror("colorlist_new"); exit(1); } return p; } static void colorlistlist_delete(Frame *f, ColorList *p) { ColorList *q; while(p) { q = p; XFreeColors(f->dpy, f->colormap, &p->pixel, 1, 0); p = p->next; free(q); } } void frame_alloc_color(Frame *f, char *name, u_long *ret) { XColor scr, exact; XrmQuark n; ColorList *p; p = f->pixels; while (p != NULL) { if ((n = XrmStringToQuark(name)) == p->name) { *ret = p->pixel; return; } p = p->next; } if (XAllocNamedColor(f->dpy, f->colormap, name, &scr, &exact)) { p = colorlist_new(); p->name = n; *ret = p->pixel = scr.pixel; p->next = f->pixels; f->pixels = p; } } static BlockFormatInfo * blockformatinfo_new(void) { BlockFormatInfo *p; if ((p = malloc(sizeof(*p))) == NULL) { perror("blockformatinfo_new"); exit(1); } p->cur_x = 0; p->cur_y = 0; p->after_lf = 1; p->paragraph = 0; p->pre = TAG_CLOSE; p->li_cnt = 0; p->linkmode = 0; p->left = htmlobj_new(); p->right = htmlobj_new(); p->left_image_margin = 0; p->right_image_height = 0; p->right_image_margin = 0; p->left_image_height = 0; p->max_ascent = p->max_descent = 0; p->prev_ascent = p->prev_descent = 0; p->next_linesep = 0; p->obj = p->line = p->line_p = htmlobj_new(); return p; } static void blockformatinfo_delete(BlockFormatInfo *p) { if (p) { htmlobjlist_delete(p->left); htmlobjlist_delete(p->right); htmlobjlist_delete(p->obj); free(p); } } BlockFormatInfo * frame_get_blockformatinfo(Frame *f) { ParseInfo *p = f->pinfo; while (p != NULL) { if (p->type == FORMAT_BLOCK) return p->bfinfo; p = p->next; } return NULL; } BlockStyleInfo * frame_get_blockstyleinfo(Frame *f) { ParseInfo *p = f->pinfo; while (p != NULL) { if (p->type == FORMAT_BLOCK) return p->bstyle; p = p->next; } return NULL; } BlockFormatInfo * frame_get_parent_blockformatinfo(Frame *f) { ParseInfo *p = f->pinfo->next; while (p != NULL) { if (p->type == FORMAT_BLOCK) return p->bfinfo; p = p->next; } return NULL; } static ParseInfo * parseinfo_new(Frame *f) { ParseInfo *p; if ((p = malloc(sizeof(*p))) == NULL) { perror("parseinfo_new"); exit(1); } p->next = NULL; p->taginfo = NULL; p->istyle = NULL; p->bstyle = NULL; p->styleset = NULL; p->dtdcur = dtdcur_new(); return p; } static void parseinfo_delete(ParseInfo *p) { if (p) { dtdcur_delete(p->dtdcur); stylesheetset_delete(p->styleset); inlinestyleinfo_delete(p->istyle); if (p->type == FORMAT_BLOCK) { blockformatinfo_delete(p->bfinfo); blockstyleinfo_delete(p->bstyle); } free(p); } } Frame * frame_new(Display *dpy, Window win, FontFaceTableList fftl, FontNameList fnl, FontNameList fnlm, u_int width, u_int height, int off_x, int off_y) { int i; Frame *p; if ((p = malloc(sizeof(*p))) == NULL) { perror("frame_new"); exit(1); } p->name = NULL; p->path = NULL; p->dpy = dpy; p->win = win; p->width = width; p->height = height; p->off_x = off_x; p->off_y = off_y; p->scr_x = 0; p->scr_y = 0; { XWindowAttributes attr; XGetWindowAttributes(p->dpy, p->win, &attr); p->colormap = attr.colormap; p->r_w = attr.width; p->r_h = attr.height; p->foreground = BlackPixelOfScreen(attr.screen); p->background = WhitePixelOfScreen(attr.screen); p->backup = XCreatePixmap(p->dpy, p->win, p->r_w, p->r_h, attr.depth); p->gc = XCreateGC(p->dpy, p->win, 0, NULL); XSetGraphicsExposures(p->dpy, p->gc, False); } p->stylesheet = NULL; p->basefont = 3; for (i=0;i<7;i++) { double factor = (1 + (i-2)*0.2); p->font[FONTTYPE_NORMAL][i] = oc_new(fftl, fnl, FONTTYPE_NORMAL, factor); p->font[FONTTYPE_BOLD][i] = oc_new(fftl, fnl, FONTTYPE_BOLD, factor); p->font[FONTTYPE_ITALIC][i] = oc_new(fftl, fnl, FONTTYPE_ITALIC, factor); p->font[FONTTYPE_BOLDITALIC][i] = oc_new(fftl, fnl, FONTTYPE_BOLDITALIC, factor); p->font[FONTTYPE_PRE][i] = oc_new(fftl, fnlm, FONTTYPE_NORMAL, factor); } p->bg_image = NULL; p->pinfo = NULL; p->tagwork = NULL; p->eof = 0; p->body = NULL; p->images = NULL; p->pixels = NULL; p->links = NULL; p->names = NULL; return p; } static void frame_clean(Frame *f) { mytimerlist_delete(f->images); f->images = NULL; while (f->pinfo && f->pinfo->next) frame_pop_parseinfo(f); parseinfo_delete(f->pinfo); f->pinfo = NULL; stylesheetlist_delete(f->stylesheet); f->stylesheet = NULL; /* clear objects */ htmlhrefinfolist_delete(f->links); f->links = NULL; colorlistlist_delete(f, f->pixels); f->pixels = NULL; image_delete(f->bg_image); f->bg_image = NULL; } void frame_delete(Frame *f) { int i, j; if (f) { frame_clean(f); XFreePixmap(f->dpy, f->backup); XFreeGC(f->dpy, f->gc); if (f->path) free(f->path); if (f->name) free(f->name); tagwork_delete(f->tagwork); for (i=0;i<7;i++) for (j=0;jfont[j][i]); free(f); } } void frame_push_parseinfo(Frame *f, Tag *tag) { char *val; ParseInfo *pi; BlockFormatInfo *bfi = frame_get_blockformatinfo(f); BlockFormatInfo *bf; BlockStyleInfo *bs; pi = parseinfo_new(f); /* init parseinfomation */ pi->taginfo = tag->ti; pi->dtdcur->cur = tag->ti->dtd; pi->sel = StringToSSID(tag->ti->name); pi->id = ((val = tag_get_opt_value(tag, OPT_id)))? StringToSSID(val): None; pi->class = ((val = tag_get_opt_value(tag, OPT_class)))? StringToSSID(val): None; /* XXX pseudo class ... (a:link etc) */ pi->pseudoclass = 0; /* get styleset */ pi->styleset = frame_get_stylesheetsetlist(f, pi); pi->istyle = inlinestyleinfo_new(f); #if 0 *p->istyle = *f->pinfo->istyle; /* copy inline styleinfo from parent */ inlinestyleinfo_get_stylesheet(pi->styleset, p->istyle); #endif if (tag->ti->block == TAG_BLOCK) { int tm, lm, rm; if (bfi && !bfi->after_lf) frame_add_lf(f, BR_NORMAL); pi->type = FORMAT_BLOCK; pi->bstyle = bs = frame_blockstyleinfo_new(f, pi->styleset); pi->bfinfo = bf = blockformatinfo_new(); tm = bs->border_top_width + bs->padding_top + bs->margin_top; lm = bs->border_left_width + bs->padding_left + bs->margin_left; rm = bs->border_right_width + bs->padding_right + bs->margin_right; bf->off_x = ((bfi == NULL)? 0:(bfi->off_x + CUR_X)) + lm; bf->off_y = ((bfi == NULL)? 0:(bfi->off_y + CUR_Y)) + tm; bf->width = ((bfi == NULL)? f->width : WIDTH) - (lm + rm); if (bf->width < 20) /* minumum XXX */ bf->width = 20; bf->formatted_width = bf->width; bf->li_level = (bfi == NULL)? 0: bfi->li_level; /* push */ pi->next = f->pinfo; f->pinfo = pi; /* option's align check XXX */ frame_parse_align(f,tag); } else { pi->type = FORMAT_INLINE; /* push */ pi->next = f->pinfo; f->pinfo = pi; } } void frame_pop_parseinfo(Frame *f) { ParseInfo *oldpi = f->pinfo; if (oldpi) { TagInfo *ti = oldpi->taginfo; if (ti) { if (ti->block == TAG_BLOCK) { BlockFormatInfo *bfi = frame_get_blockformatinfo(f); if (!bfi->after_lf || bfi->left_image_margin || bfi->right_image_margin) { frame_add_lf(f,BR_ALL); } /* pop */ f->pinfo = oldpi->next; frame_add_blockobj(f, oldpi); frame_add_lf(f,BR_NORMAL); /* XXX */ bfi = frame_get_blockformatinfo(f); bfi->next_linesep = 0; } else { f->pinfo = oldpi->next; } #ifdef DEBUG fprintf(stderr, "pop_finfo: %s\n", ti->name); #endif } else f->pinfo = oldpi->next; parseinfo_delete(oldpi); } #ifdef DEBUG else fprintf(stderr, "pop_finfo: pop_overrun\n"); #endif } int frame_find_parseinfo(Frame *f, TAGS tag) { ParseInfo *p = f->pinfo; while (p != NULL) { if (p->taginfo && p->taginfo->id == tag) /* XXX */ break; p = p->next; } return (p == NULL)?0:1; } void frame_expose(Frame *f, int x, int y, int w, int h) { XCopyArea(f->dpy, f->backup, f->win, f->gc, x, y, w, h, x, y); } void frame_expose_region(Frame *f, Region reg) { XSetRegion(f->dpy, f->gc, reg); XCopyArea(f->dpy, f->backup, f->win, f->gc, 0, 0, f->r_w, f->r_h, 0, 0); XSetClipMask(f->dpy, f->gc, None); } static void frame_init_params(Frame *f) { f->formatted_width = 0; f->formatted_height = 0; f->scr_x = 0; f->scr_y = 0; f->link_style = inlinestyleinfo_new(f); inlinestyleinfo_setcolor(f,f->link_style,"red"); { Tag *tag = tag_new(TAG_normal); tag->ti = GetTagInfo("_start_"); frame_push_parseinfo(f, tag); tag_delete(tag); } f->body = NULL; f->links = NULL; f->names = NULL; f->images = mytimer_new(); f->bg_image = NULL; f->pixels = NULL; f->basefont = 3; f->eof = 0; } void frame_resize(Frame *f, int width, int height, int off_x, int off_y) { frame_clean(f); f->width = width; f->height = height; f->off_x = off_x; f->off_y = off_y; f->scr_x = 0; frame_init_params(f); tagwork_reset(f->tagwork); { XWindowAttributes attr; XGetWindowAttributes(f->dpy, f->win, &attr); if (f->r_w != attr.width || f->r_h != attr.height) { f->r_w = attr.width; f->r_h = attr.height; XFreePixmap(f->dpy, f->backup); f->backup = XCreatePixmap(f->dpy, f->win, f->r_w, f->r_h, attr.depth); } } } int frame_open(Frame *f, int fd, char *name) { char *p; int len; frame_clean(f); frame_init_params(f); if (f->path) free(f->path); if (f->name) free(f->name); if (name == NULL) name = "./"; if ((p = strrchr(name,'/'))) { p++; f->name = strdup(p); if ((f->path = malloc((len=(p - name))+1)) == NULL) { perror("tagwork_open"); exit(1); } strncpy(f->path, name, len); f->path[len] = '\0'; } else { f->path = NULL; f->name = strdup(name); } f->fd = fd; tagwork_delete(f->tagwork); f->tagwork = tagwork_open(f->fd); return f->fd; } FILE * frame_file_open(Frame *f, char *name) { FILE *fp; char *buf; if (*name == '/' || f->path == NULL) { fp = fopen(name, "r"); }else { if ((buf = malloc(strlen(name) + strlen(f->path) + 1)) == NULL) return NULL; sprintf(buf, "%s%s", f->path, name); fp = fopen(buf, "r"); free(buf); } return fp; }