#include "fm.h"
#include "parsetagx.h"
#include "myctype.h"
#include <signal.h>
#include <setjmp.h>
#include <errno.h>
#include <math.h>

static int
parseFrameSetLength(char *s, char ***ret)
{
    int i, len;
    char *p, *q, **lv;

    i = 1;

    if (s)
	for (p = s ; (p = strchr(p, ',')) ; ++p)
	    ++i;
    else
	s = "*";

    lv = New_N(char *, i);

    for (i = 0, p = s ;; ++p) {
	SKIP_BLANKS(p);

	if ((len = strtol(p, &q, 10)) < 0)
	    len = 0;

	switch (*q) {
	case '%':
	    lv[i++] = Sprintf("%d%%", len)->ptr;
	    break;
	case '*':
	    lv[i++] = Sprintf("%d*", len > 0 ? len : 1)->ptr;
	    break;
	default:
	    lv[i++] = Sprintf("%d", len)->ptr;
	    break;
	}

	if (!(p = strchr(q, ',')))
	    break;
    }

    *ret = lv;
    return i;
}

struct frameset *
newFrameSet(struct parsed_tag *tag)
{
    struct frameset *f;
    int i;
    char *cols = NULL, *rows = NULL;

    f = New(struct frameset);
    f->attr = F_FRAMESET;
    f->name = NULL;
    f->origin = NULL;
    parsedtag_get_value(tag, ATTR_COLS, &cols);
    parsedtag_get_value(tag, ATTR_ROWS, &rows);
    f->col = parseFrameSetLength(cols, &f->width);
    f->row = parseFrameSetLength(rows, &f->height);
    f->i = 0;
    i = f->row * f->col;
    f->frame = New_N(union frameset_element, i);
    do {
	f->frame[--i].element = NULL;
    } while (i);
    return f;
}

struct frame_body *
newFrame(struct parsed_tag *tag, Buffer *buf)
{
    struct frame_body *body;
    char *p;

    body = New(struct frame_body);
    memset(body, 0, sizeof(*body));
    body->attr = F_BODY;
    body->baseURL = baseURL(buf);
    if (tag) {
	if (parsedtag_get_value(tag, ATTR_SRC, &p))
	    body->url = url_quote_conv_for_buf(p, buf);
	if (parsedtag_get_value(tag, ATTR_NAME, &p) && *p != '_')
	    body->name = url_quote_conv_for_buf(p, buf);
    }
    return body;
}

void
addFrameSetElement(struct frameset *f, union frameset_element element)
{
    int i;

    if (f == NULL)
	return;
    i = f->i;
    if (i >= f->col * f->row)
	return;
    f->frame[i] = element;
    f->i++;
}

Buffer *
frameOrigin(BufferView *v)
{
    if (v) {
	if (v->frameset) {
	    int i, n;
	    Buffer *buf;

	    for (i = 0, n = v->ncols * v->nrows ; i < n ;)
		if ((buf = frameOrigin(v->subv[i++].top)))
		    return buf;
	}
	else
	    return v->top;
    }

    return NULL;
}

Buffer *
frameCorner(BufferView *v)
{
    if (v) {
	if (v->frameset) {
	    int i;
	    Buffer *buf;

	    for (i = v->ncols * v->nrows ; i > 0 ;)
		if ((buf = frameCorner(v->subv[--i].top)))
		    return buf;
	}
	else
	    return v->top;
    }

    return NULL;
}

struct renderFrame_arg {
    BufferView *root;
    Buffer *origin;
    char need_view;
};

static void renderFrame_receiver(Buffer *buf, int nlines);
static void renderFrameLoop(BufferView *v, Buffer *Cbuf, Phase0Env *p0env_root);

static void
renderFrame_post(Buffer *buf, Phase0Env *p0env, int nlines)
{
    struct renderFrame_arg *arg;

    arg = p0env->receiver_arg;

    if (buf->view->rootX == arg->root->rootX &&
	buf->view->rootY == arg->root->rootY)
	arg->origin = buf;

    if (arg->origin && arg->origin != Currentbuf) {
	if (Currentbuf) {
	    BufferView *v;

	    for (v = Currentbuf->view ; v ; v = v->sup)
		if (v == arg->root) {
		    pushBuffer(arg->origin);
		    break;
		}
	}
	else
	    pushBuffer(arg->origin);

	arg->need_view = fmInitialized;
    }

    if (arg->need_view) {
	displayCurrentView(NULL);
	arg->need_view = FALSE;
    }

    if (nlines < 0 && buf->frameset) {
	Phase0Env p0env_frame;
	BufferView *v;

	p0env_frame = main_p0env;
	p0env_frame.RenderFrame = FALSE;
	p0env_frame.receiver = renderFrame_receiver;
	p0env_frame.receiver_arg = arg;
	arg->need_view = fmInitialized;
	buf->bufferprop |= BP_FRAMESET;
	buf->frameset->origin = buf;
	v = buf->view;
	renderFrameLoop(initBufferView(NULL, buf->frameset, v->sup, v->rootX, v->rootY, v->width, v->height, v->x, v->y),
			buf, &p0env_frame);
    }
}

static void
renderFrame_receiver(Buffer *buf, int nlines)
{
    if (fmInitialized)
	displayBufferMaybe(buf, nlines);

    renderFrame_post(buf, buf->async_buf->p2env->p1env->p0env, nlines);
}

static void
renderFrameLoop(BufferView *v, Buffer *Cbuf, Phase0Env *p0env_root)
{
    if (v->frameset) {
	int i;
	short col, row;

	for (i = v->nrows * v->ncols, row = v->nrows ; row > 0 ;) {
	    if (!v->rowv[--row]) {
		i -= v->ncols;
		continue;
	    }

	    for (col = v->ncols ; col > 0 ;) {
		--i;

		if (v->colv[--col])
		    renderFrameLoop(v->subv[i].top, Cbuf, p0env_root);
	    }
	}
    }
    else {
	Phase0Env p0env;
	struct frameset *fset;
	struct frame_body *b;
	Buffer *buf;

	p0env = *p0env_root;
	p0env.view = v;
	fset = v->sup->frameset;

	if ((buf =
	     !(b = fset->frame[v->y * v->sup->ncols + v->x].body) ?
	     loadHTMLString(Strnew_charp("No frame element"), NULL, &p0env) :
	     b->url ? loadGeneralFile(b->url,
				      b->baseURL ? b->baseURL :
				      Cbuf->baseURL ? Cbuf->baseURL :
				      fset->origin ? &fset->origin->currentURL :
				      &Cbuf->currentURL,
				      b->referer,
				      &p0env,
				      b->request) :
	     loadHTMLString(Sprintf("This frame (%s) contains no src attribute",
				    b->name ? b->name : "no name"),
			    NULL,
			    &p0env)) &&
	    buf != NO_BUFFER && !buf->async_buf) {
	    pushBuffer(buf);
	    renderFrame_post(buf, &p0env, -1);
	}
    }
}

BufferView *
renderFrameOnView(BufferView *nv, Buffer *Cbuf, Phase0Env *p0env_orig)
{
    Phase0Env p0env;
    struct renderFrame_arg *arg;

    p0env = *p0env_orig;
    p0env.RenderFrame = FALSE;
    p0env.receiver = renderFrame_receiver;
    p0env.receiver_arg = arg = New(struct renderFrame_arg);
    arg->root = nv;
    arg->origin = NULL;
    arg->need_view = fmInitialized;
    renderFrameLoop(nv, Cbuf, &p0env);
    return nv;
}

BufferView *
renderFrame(struct frameset *fset, Buffer *Cbuf, Phase0Env *p0env_orig)
{
    BufferView *v;

    v = Cbuf->view;

    if (!fset->origin)
	fset->origin = Cbuf;

    return renderFrameOnView(initBufferView(NULL, fset, v->sup, v->rootX, v->rootY, v->width, v->height, v->x, v->y),
			     Cbuf, p0env_orig);
}

static BufferView *
newSelfBufferView(BufferView *v)
{
    return v->frameset ? initBufferView(NULL, NULL, v->sup, v->rootX, v->rootY, v->width, v->height, v->x, v->y) : v;
}

static BufferView *
searchBufferViewLoop(BufferView *ov, char *name)
{
    if (ov->frameset) {
	int i;
	short col, row;
	union frameset_element *e;
	BufferView *v;

	for (i = 0, row = 0 ; row < ov->nrows ; ++row) {
	    if (!ov->rowv[row]) {
		i += ov->ncols;
		continue;
	    }

	    for (col = 0 ; col < ov->ncols ; ++col, ++i) {
		if (!ov->colv[col])
		    continue;

		e = &(ov->frameset->frame[i]);

		if (e->element) {
		    if (e->element->name && !strcmp(e->element->name, name))
			return newSelfBufferView(ov->subv[i].top);
		    else if ((v = searchBufferViewLoop(ov->subv[i].top, name)))
			return v;
		}
	    }
	}
    }

    return NULL;
}

BufferView *
searchBufferView(BufferView *ov, char *name)
{
    if (!name)
	return TargetSelf ? newSelfBufferView(ov) : NULL;
    else if (*name == '_') {
	if (!strcmp(name + 1, "self"))
	    return newSelfBufferView(ov);
	else if (!strcmp(name + 1, "parent")) {
	    if (ov->sup)
		ov = ov->sup;

	    return newSelfBufferView(ov);
	}
	else
	    return NULL;
    }

    return searchBufferViewLoop(ov->root, name);
}

#define DELTA (0.5)

#if 0
typedef double volatile debug_double;
#else
typedef double debug_double;
#endif

static int
comp2Longs(const void *a, const void *b)
{
    long delta;

    delta = *(const long *)a - *(const long *)b;
    return delta > 0 ? 1 : delta < 0 ? -1 : 0;
}

void
parse_frame_colrow(short ctotal, short cmin, int rulesize, double ppc, char **sv, int n, short *cwv)
{
    long ast, ast_min, isum, *nv;
    char *cv, *e;
    int i, zn, nast;
    debug_double total, vir_total, sum, fixed_sum, scale, *wv, t, dmin, for_ast;

    dmin = cmin * ppc;

    while ((total = (double)((ctotal - rulesize * (n - 1)) / cmin * cmin) * ppc) < dmin)
	cwv[--n] = 0;

    ctotal -= rulesize * (n - 1);
    ctotal = ctotal / cmin * cmin;
    nv = NewAtom_N(long, n);
    cv = NewAtom_N(char, n);
    wv = NewAtom_N(double, n);
    i = n;
    nast = 0;
    ast = ast_min = 0;

    for (i = n ; i > 0 ;) {
	--i;

	if ((nv[i] = strtoul(sv[i], &e, 10)) < 0) {
	    nv[i] = 0;
	    e = sv[i];
	}

	switch (cv[i] = *e) {
	case '*':
	    if (!nv[i])
		nv[i] = 1;

	    ast += nv[i];
	    ++nast;
	    break;
	default:
	    cv[i] = '\0';
	case '\0':
	case '%':
	    break;
	}
    }

    if (ast > nast) {
	long *astv, *p, *q, *r, *s, x;

	p = astv = NewAtom_N(long, nast);
	i = n;
	x = 1;

	do {
	    if (cv[--i] == '*')
		*p++ = nv[i];
	} while (i > 0);

	qsort(astv, nast, sizeof(long), comp2Longs);
	q = astv;

	for (r = s = astv + 1 ; s < p ; ++s)
	    if (*q < *s) {
		ast_min += (r - q) * x++;
		q = s;
		r = s + 1;
	    }

	ast_min += (p - q) * x;
    }
    else
	ast_min = ast;

    if ((for_ast = dmin * ast_min + rulesize * ppc * (nast - 1)) >= total) {
	/* We should give up any hope */
	for (i = n ; i > 0 ;)
	    cwv[--i] = 0;

	return;
    }

    if (nast < n) {
	vir_total = total;
	scale = 1.0;

	for (;;) {
	    fixed_sum = sum = 0.0;
	    i = n;

	    do {
		switch (cv[--i]) {
		case '*':
		    continue;
		case '%':
		    t = (total * (double)nv[i]) / 100.0;
		    break;
		default:
		    t = (double)nv[i];
		    break;
		}

		t *= scale;
		sum += t;
		wv[i] = t / vir_total * total;
		fixed_sum += wv[i];
	    } while (i > 0);

	    if (ast) {
		if (total - fixed_sum < for_ast) {
		    scale *= 1.0 + sqrt(for_ast / vir_total);
		    sum *= scale;
		}
		else
		    break;
	    }
	    else if (fixed_sum + DELTA > total && total + DELTA > fixed_sum)
		break;

	    vir_total = sum;
	}
    }
    else
	fixed_sum = 0;

    if (ast) {
	i = n;

	do {
	    if (cv[--i] == '*')
		wv[i] = (total - fixed_sum) / ast * (double)nv[i];
	} while (i > 0);
    }

    i = n;
    isum = 0;
    zn = 0;
    total = 0.0;

    do {
	if (wv[--i] > 0.0) {
	    total += wv[i];
	    cwv[i] = cmin;
	    isum += cmin;
	}
	else {
	    cwv[i] = 0;
	    ++zn;
	}
    } while (i > 0);

    while (isum < ctotal) {
	i = n;

	do {
	    --i;

	    if (cwv[i] && cwv[i] * ppc < wv[i]) {
		cwv[i] += cmin;

		if ((isum += cmin) >= ctotal)
		    break;
	    }
	} while (i > 0);
    }
}

static int
createFrameFile(BufferView *v, FILE *f1, ParsedURL *current, int nest)
{
    int r, c, t_stack, i;
    URLFile f2;
#ifdef MANY_CHARSET
    const char *code;
#endif
#ifdef JP_CHARSET
    char code, ic, charset[2];
#endif				/* JP_CHARSET */
    char *d_target, *p_target, *s_target, *t_target;
    ParsedURL base;

    if (!v)
	return -1;

    if (!nest)
	fprintf(f1,
		"<html><head>"
#ifdef MANY_CHARSET
		"<meta http-equiv=\"Content-Type\" content=\"text/html; charset=x-moe-internal\">\n"
#endif
		"<title>%s</title></head><body>\n"
		"<table hborder width=\"100%%\">\n",
		v->frameset->origin ? html_quote(v->frameset->origin->buffername) : "");
    else
	fputs("<table hborder>\n", f1);

#ifdef JP_CHARSET
    charset[1] = '\0';
#endif

    for (i = r = 0 ; r < v->nrows ; ++r) {
	if (!v->rowv[r]) {
	    i += v->ncols;
	    continue;
	}

	fputs("<tr valign=top>\n", f1);

	for (c = 0 ; c < v->ncols ; ++c, ++i) {
	    BufferView *sub;
	    union frameset_element frame;
	    char *p;
	    Str tok;
	    int status;

	    if (!v->colv[c])
		continue;

	    if (!(sub = v->subv[i].top) || !(frame = v->frameset->frame[i]).element) {
		fputs("<td>\n</td>\n", f1);
		continue;
	    }

	    p = "";
	    tok = Strnew();
	    fputs("<td", f1);

	    if (frame.element->name)
		fprintf(f1, " id=\"_%s\"", html_quote(frame.element->name));

	    if (!r) {
		char *q, *r;

		q = v->frameset->width[c];
		strtoul(q, &r, 10);
		fprintf(f1, " width=\"%s\"", *r == '*' ? "*" : q);
	    }

	    fputs(">\n", f1);

	    if (sub->frameset) {
		if (!sub->frameset->name && v->frameset->name)
		    sub->frameset->name = Sprintf("%s_%d", v->frameset->name, i)->ptr;

		createFrameFile(sub, f1,
				sub->frameset->origin ? &sub->frameset->origin->currentURL : current,
				nest + 1);
	    }
	    else if (sub->top) {
		init_stream(&f2, SCM_TMPFILE, NULL);

		if (!sub->top->sourcefile) {
		    if (frame.body->url)
			fprintf(f1, "Source of %s was lost", html_quote(frame.body->url));
		    else
			fprintf(f1, "This frame (%s) contains no src attribute",
				frame.body->name ? html_quote(frame.body->name) : "(no name)");
		}
		else {
		    Phase0Env p0env;

		    fflush(f1);
		    p0env = main_p0env;
		    p0env.flag &= ~(RG_DUMP_MASK | RG_HALFDUMP_MASK | RG_PROC_MASK | RG_DO_DOWNLOAD);
		    examineFile(sub->top->sourcefile, &f2, &p0env);

		    if (!f2.stream)
			fprintf(f1, "Can't open %s (%s)", html_quote(frame.body->url), strerror(errno));
		}

		if (f2.stream) {
		    parseURL2(frame.body->url, &base, current);
		    p_target = v->frameset->name;
		    s_target = frame.body->name;
		    t_target = "_blank";
		    d_target = TargetSelf ? s_target : t_target;
#if defined(MANY_CHARSET) || defined(JP_CHARSET)
		    code = sub->top->document_encoding;
#endif
		    t_stack = 0;

		    if (sub->top->type &&
			!strcasecmp(sub->top->type, "text/plain")) {
			Str tmp;

			fprintf(f1, "<pre>\n");

			while ((tmp = StrmyUFgets(&f2))->length) {
#ifdef MANY_CHARSET
			    tmp = conv_Str2mbStr(tmp, NULL, "@", code);
#endif
#ifdef JP_CHARSET
			    if ((ic = checkShiftCode(tmp, code)) != '\0')
				tmp = conv_str(tmp, (code = ic), InnerCode);
#endif                /* JP_CHARSET */

			    cleanup_line(tmp, HTML_MODE);
			    fprintf(f1, "%s", html_quote(tmp->ptr));
			}

			fprintf(f1, "</pre>\n");
		    }
		    else {
			do {
			    status = R_ST_NORMAL;

			    do {
				if (*p == '\0') {
				    Str tmp = StrmyUFgets(&f2);

				    if (tmp->length == 0 && status != R_ST_NORMAL)
					tmp = correct_irrtag(status);

				    if (tmp->length == 0)
					break;

#ifdef MANY_CHARSET
				    tmp = conv_Str2mbStr(tmp, &code, "");
#endif

#ifdef JP_CHARSET
				    if ((ic = checkShiftCode(tmp, code)) != '\0')
					tmp = conv_str(tmp, (code = ic), InnerCode);
#endif				/* JP_CHARSET */

				    cleanup_line(tmp, HTML_MODE);
				    p = tmp->ptr;
				}

				if (status == R_ST_NORMAL || ST_IS_COMMENT(status))
				    read_token(tok, &p, p + strlen(p), &status, RT_PRE | RT_EOL);
				else
				    read_token(tok, &p, p + strlen(p), &status, RT_PRE | RT_APPEND | RT_EOL);
			    } while (status != R_ST_NORMAL);

			    if (tok->length == 0)
				continue;

			    if (tok->ptr[0] == '<') {
				char *q = tok->ptr;
				int j, a_target = 0;
				struct parsed_tag *tag;
				ParsedURL url;

				if (!(tag = parse_tag(&q, FALSE)))
				    goto token_end;

				switch (tag->tagid) {
				case HTML_TITLE:
				    fputs("<!-- title:", f1);
				    goto token_end;
				case HTML_N_TITLE:
				    fputs("-->", f1);
				    goto token_end;
				case HTML_BASE:
				    if (parsedtag_get_value(tag, ATTR_HREF, &q)) {
					q = url_quote_conv(q, code);
					parseURL(q, &base, NULL);
				    }

				    if (parsedtag_get_value(tag, ATTR_TARGET, &q)) {
					if (!strcasecmp(q, "_self"))
					    d_target = s_target;
					else if (!strcasecmp(q, "_parent"))
					    d_target = p_target;
					else
					    d_target = url_quote_conv(q, code);
				    }
				    /* fall thru, "BASE" is prohibit tag */
				case HTML_HEAD:
				case HTML_N_HEAD:
				case HTML_BODY:
				case HTML_N_BODY:
				case HTML_META:
				case HTML_DOCTYPE:
				    /* prohibit_tags */
				    Strshrinkfirst(tok, 1);
				    Strshrink(tok, 1);
				    fprintf(f1, "<!-- %s -->", html_quote(tok->ptr));
				    goto token_end;
				case HTML_TABLE:
				    t_stack++;
				    break;
				case HTML_N_TABLE:
				    t_stack--;

				    if (t_stack < 0) {
					t_stack = 0;
					Strshrinkfirst(tok, 1);
					Strshrink(tok, 1);
					fprintf(f1, "<!-- table stack underflow: %s -->", html_quote(tok->ptr));
					goto token_end;
				    }

				    break;
				case HTML_THEAD:
				case HTML_N_THEAD:
				case HTML_TBODY:
				case HTML_N_TBODY:
				case HTML_TFOOT:
				case HTML_N_TFOOT:
				case HTML_TD:
				case HTML_N_TD:
				case HTML_TR:
				case HTML_N_TR:
				case HTML_TH:
				case HTML_N_TH:
				    /* table_tags MUST be in table stack */
				    if (!t_stack) {
					Strshrinkfirst(tok, 1);
					Strshrink(tok, 1);
					fprintf(f1, "<!-- %s -->", html_quote(tok->ptr));
					goto token_end;

				    }

				    break;
				default:
				    break;
				}

				for (j = 0; j < TagMAP[tag->tagid].nattributes; j++)
				    switch (tag->attrid[j]) {
				    case ATTR_SRC:
				    case ATTR_HREF:
				    case ATTR_ACTION:
					if (!tag->value[j]) {
					    if (tag->tagid == HTML_FORM)
						parseURL2(frame.body->url, &url, current);
					    else
						break;
					}
					else {
					    tag->value[j] = url_quote_conv(tag->value[j], code);
					    parseURL2(tag->value[j], &url, &base);
					}
					if (url.scheme == SCM_MAILTO ||
					    url.scheme == SCM_UNKNOWN ||
					    url.scheme == SCM_MISSING)
					    break;
					a_target |= 1;
					tag->value[j] = parsedURL2Str(&url)->ptr;
					tag->need_reconstruct = TRUE;
					parsedtag_set_value(tag,
							    ATTR_REFERER,
							    parsedURL2Str(&base)->ptr);
#ifdef MANY_CHARSET
					if (code)
					    parsedtag_set_value(tag,
								ATTR_CHARSET, (char *)code);
#endif
#ifdef JP_CHARSET
					if (code != '\0') {
					    charset[0] = code;
					    parsedtag_set_value(tag,
								ATTR_CHARSET, charset);
					}
#endif
					break;
				    case ATTR_TARGET:
					if (!tag->value[j])
					    break;
					a_target |= 2;
					if (!strcasecmp(tag->value[j], "_self")) {
					    parsedtag_set_value(tag,
								ATTR_TARGET, s_target);
					}
					else if (!strcasecmp(tag->value[j], "_parent")) {
					    parsedtag_set_value(tag,
								ATTR_TARGET, p_target);
					}
					break;
				    }

				if (a_target == 1) {
				    /* there is HREF attribute and no TARGET
				     * attribute */
				    parsedtag_set_value(tag, ATTR_TARGET, d_target);
				}

				if (parsedtag_need_reconstruct(tag)) {
				    Str tagstr = parsedtag2str(tag);

				    Strfputs(tagstr, f1);
				}
				else
				    Strfputs(tok, f1);
			    }
			    else
				Strfputs(tok, f1);
			token_end:
			    Strclear(tok);
			} while (*p != '\0' || !iseos(f2.stream));

			while (t_stack--)
			    fputs("</TABLE>\n", f1);
		    }

		    UFclose(&f2);
		}
	    }

	    fputs("</td>\n", f1);
	}

	fputs("</tr>\n", f1);
    }

    fputs("</table>\n", f1);

    if (!nest)
	fputs("</body></html>\n", f1);

    return 0;
}

Buffer *
frameViewBuffer(BufferView *v)
{
    if (v->frameset) {
	Str tmp, tmp1;
	FILE *f;
	URLFile uf;
	Phase0Env p0env;
	Buffer *newBuf;

	tmp = tmpfname(TMPF_SRC, ".html");
	pushFileToDelete(tmp->ptr, main_p0env.flag);

	if (!(f = fopen(tmp->ptr, "w")) ||
	    createFrameFile(v, f,
			    v->frameset->origin ? &v->frameset->origin->currentURL : NULL,
			    0) < 0)
	    return NULL;

	fclose(f);
	init_stream(&uf, SCM_TMPFILE, NULL);
	p0env = main_p0env;
	p0env.flag &= ~(RG_DUMP_MASK | RG_HALFDUMP_MASK | RG_PROC_MASK | RG_DO_DOWNLOAD);
	examineFile(tmp->ptr, &uf, &p0env);
	p0env = main_p0env;
	p0env.SearchHeader = FALSE;
#ifdef MANY_CHARSET
	p0env.default_content_charset = "x-moe-internal";
#endif
#ifdef JP_CHARSET
	p0env.DocumentCode = CODE_INNER_EUC;
#endif
	newBuf = newBuffer(initBufferView(NULL, NULL, v->sup, v->rootX, v->rootY, v->width, v->height, v->x, v->y));

	if (v->frameset->origin) {
	    copyParsedURL(&newBuf->currentURL, &v->frameset->origin->currentURL);
	    newBuf->real_type = v->frameset->origin->real_type;
	    newBuf->type = "text/html";
	    newBuf->buffername = v->frameset->origin->buffername;
	    newBuf->document_header = v->frameset->origin->document_header;
	    newBuf->document_header_table = v->frameset->origin->document_header_table;
#ifdef MANY_CHARSET
	    newBuf->document_charset = v->frameset->origin->document_charset;
#endif
#ifdef JP_CHARSET
	    newBuf->document_code = v->frameset->origin->document_code;
#endif
	}

	loadHTMLstream(&uf, newBuf, NULL, TRUE, &p0env);
	UFclose(&uf);
	tmp1 = tmpfname(TMPF_FRAME, ".html");
	newBuf->filename = newBuf->sourcefile = rename(tmp->ptr, tmp1->ptr) ? tmp->ptr : tmp1->ptr;
	return newBuf;
    }
    else
	return v->top;
}

/* Local Variables:    */
/* c-basic-offset: 4   */
/* tab-width: 8        */
/* End:                */
