1 /* $Id: frame.c,v 1.34 2003/09/26 17:59:51 ukai Exp $ */
8 static JMP_BUF AbortLoading;
9 struct frameset *renderFrameSet = NULL;
11 static MySignalHandler
14 LONGJMP(AbortLoading, 1);
18 parseFrameSetLength(char *s, char ***ret)
26 for (p = s; (p = strchr(p, ',')); ++p)
31 lv = New_N(char *, i);
33 for (i = 0, p = s;; ++p) {
35 len = strtol(p, &q, 10);
39 lv[i++] = Sprintf("%d%%", len)->ptr;
45 lv[i++] = Sprintf("%d", len)->ptr;
49 if (!(p = strchr(q, ',')))
58 newFrameSet(struct parsed_tag *tag)
62 char *cols = NULL, *rows = NULL;
64 f = New(struct frameset);
68 parsedtag_get_value(tag, ATTR_COLS, &cols);
69 parsedtag_get_value(tag, ATTR_ROWS, &rows);
70 f->col = parseFrameSetLength(cols, &f->width);
71 f->row = parseFrameSetLength(rows, &f->height);
74 f->frame = New_N(union frameset_element, i);
76 f->frame[--i].element = NULL;
82 newFrame(struct parsed_tag *tag, Buffer *buf)
84 struct frame_body *body;
87 body = New(struct frame_body);
88 bzero((void *)body, sizeof(*body));
89 body->attr = F_UNLOADED;
91 body->baseURL = baseURL(buf);
93 if (parsedtag_get_value(tag, ATTR_SRC, &p))
94 body->url = url_quote_conv(remove_space(p), buf->document_charset);
95 if (parsedtag_get_value(tag, ATTR_NAME, &p) && *p != '_')
96 body->name = url_quote_conv(p, buf->document_charset);
102 unloadFrame(struct frame_body *b)
104 b->attr = F_UNLOADED;
108 deleteFrame(struct frame_body *b)
113 bzero((void *)b, sizeof(*b));
117 addFrameSetElement(struct frameset *f, union frameset_element element)
124 if (i >= f->col * f->row)
126 f->frame[i] = element;
131 deleteFrameSet(struct frameset *f)
137 for (i = 0; i < f->col * f->row; i++) {
138 deleteFrameSetElement(f->frame[i]);
141 f->currentURL = NULL;
146 deleteFrameSetElement(union frameset_element e)
148 if (e.element == NULL)
150 switch (e.element->attr) {
157 deleteFrameSet(e.set);
165 static struct frame_body *
166 copyFrame(struct frame_body *ob)
168 struct frame_body *rb;
170 rb = New(struct frame_body);
171 bcopy((const void *)ob, (void *)rb, sizeof(struct frame_body));
176 copyFrameSet(struct frameset *of)
181 rf = New(struct frameset);
182 n = of->col * of->row;
183 bcopy((const void *)of, (void *)rf, sizeof(struct frameset));
184 rf->width = New_N(char *, rf->col);
185 bcopy((const void *)of->width,
186 (void *)rf->width, sizeof(char *) * rf->col);
187 rf->height = New_N(char *, rf->row);
188 bcopy((const void *)of->height,
189 (void *)rf->height, sizeof(char *) * rf->row);
190 rf->frame = New_N(union frameset_element, n);
193 if (!of->frame[n].element)
195 switch (of->frame[n].element->attr) {
198 rf->frame[n].body = copyFrame(of->frame[n].body);
201 rf->frame[n].set = copyFrameSet(of->frame[n].set);
205 rf->frame[n].element = NULL;
213 flushFrameSet(struct frameset *fs)
219 if (!fs->frame[n].element)
221 switch (fs->frame[n].element->attr) {
224 fs->frame[n].body->nameList = NULL;
227 flushFrameSet(fs->frame[n].set);
238 pushFrameTree(struct frameset_queue **fqpp, struct frameset *fs, Buffer *buf)
240 struct frameset_queue *rfq, *cfq = *fqpp;
245 rfq = New(struct frameset_queue);
246 rfq->linenumber = (buf
247 && buf->currentLine) ? buf->currentLine->linenumber : 1;
248 rfq->top_linenumber = (buf && buf->topLine) ? buf->topLine->linenumber : 1;
249 rfq->pos = buf ? buf->pos : 0;
250 rfq->currentColumn = buf ? buf->currentColumn : 0;
251 rfq->formitem = buf ? buf->formitem : NULL;
255 rfq->next = cfq->next;
257 cfq->next->back = rfq;
268 popFrameTree(struct frameset_queue **fqpp)
270 struct frameset_queue *rfq = NULL, *cfq = *fqpp;
271 struct frameset *rfs = NULL;
278 (rfq = cfq->next)->back = cfq->back;
281 (rfq = cfq->back)->next = cfq->next;
284 bzero((void *)cfq, sizeof(struct frameset_queue));
289 resetFrameElement(union frameset_element *f_element,
290 Buffer *buf, char *referer, FormList *request)
293 struct frame_body *f_body;
295 f_name = f_element->element->name;
298 deleteFrameSetElement(*f_element);
299 f_element->set = buf->frameset;
300 f_element->set->currentURL = New(ParsedURL);
301 copyParsedURL(f_element->set->currentURL, &buf->currentURL);
302 buf->frameset = popFrameTree(&(buf->frameQ));
303 f_element->set->name = f_name;
306 f_body = newFrame(NULL, buf);
307 f_body->attr = F_BODY;
308 f_body->name = f_name;
309 f_body->url = parsedURL2Str(&buf->currentURL)->ptr;
310 f_body->source = buf->sourcefile;
311 buf->sourcefile = NULL;
312 if (buf->mailcap_source) {
313 f_body->source = buf->mailcap_source;
314 buf->mailcap_source = NULL;
316 f_body->type = buf->type;
317 f_body->referer = referer;
318 f_body->request = request;
319 deleteFrameSetElement(*f_element);
320 f_element->body = f_body;
324 static struct frameset *
325 frame_download_source(struct frame_body *b, ParsedURL *currentURL,
326 ParsedURL *baseURL, int flag)
329 struct frameset *ret_frameset = NULL;
332 if (b == NULL || b->url == NULL || b->url[0] == '\0')
335 baseURL = b->baseURL;
336 parseURL2(b->url, &url, currentURL);
337 switch (url.scheme) {
340 b->source = url.real_file;
345 w3m_dump |= DUMP_FRAME;
346 buf = loadGeneralFile(b->url,
347 baseURL ? baseURL : currentURL,
348 b->referer, flag | RG_FRAME_SRC, b->request);
350 /* XXX certificate? */
351 if (buf && buf != NO_BUFFER)
352 b->ssl_certificate = buf->ssl_certificate;
354 w3m_dump &= ~DUMP_FRAME;
355 is_redisplay = FALSE;
359 if (buf == NULL || buf == NO_BUFFER) {
361 b->flags = (buf == NO_BUFFER) ? FB_NO_BUFFER : 0;
364 b->url = parsedURL2Str(&buf->currentURL)->ptr;
366 b->source = buf->sourcefile;
367 buf->sourcefile = NULL;
368 if (buf->mailcap_source) {
369 b->source = buf->mailcap_source;
370 buf->mailcap_source = NULL;
374 ret_frameset = buf->frameset;
375 ret_frameset->name = b->name;
376 ret_frameset->currentURL = New(ParsedURL);
377 copyParsedURL(ret_frameset->currentURL, &buf->currentURL);
378 buf->frameset = popFrameTree(&(buf->frameQ));
384 #define CASE_TABLE_TAG \
398 case HTML_N_COLGROUP:\
402 createFrameFile(struct frameset *f, FILE * f1, Buffer *current, int level,
408 wc_ces charset, doc_charset;
410 char *d_target, *p_target, *s_target, *t_target;
411 ParsedURL *currentURL, base;
412 MySignalHandler(*volatile prevtrap) (SIGNAL_ARG) = NULL;
419 if (SETJMP(AbortLoading) != 0) {
428 fputs("Too many frameset tasked.\n", f1);
433 fprintf(f1, "<html><head><title>%s</title></head><body>\n",
434 html_quote(current->buffername));
435 fputs("<table hborder width=\"100%\">\n", f1);
438 fputs("<table hborder>\n", f1);
440 currentURL = f->currentURL ? f->currentURL : ¤t->currentURL;
441 for (r = 0; r < f->row; r++) {
442 fputs("<tr valign=top>\n", f1);
443 for (c = 0; c < f->col; c++) {
444 union frameset_element frame;
445 struct frameset *f_frameset;
446 int i = c + r * f->col;
448 int status = R_ST_NORMAL;
455 if (frame.element == NULL) {
456 fputs("<td>\n</td>\n", f1);
461 if (frame.element->name)
462 fprintf(f1, " id=\"_%s\"", html_quote(frame.element->name));
464 fprintf(f1, " width=\"%s\"", f->width[c]);
470 if (frame.element->attr == F_BODY)
471 unloadFrame(frame.body);
473 switch (frame.element->attr) {
475 /* FIXME: gettextize? */
476 fprintf(f1, "Frameset \"%s\" frame %d: type unrecognized",
477 html_quote(f->name), i + 1);
480 if (!frame.body->name && f->name) {
481 frame.body->name = Sprintf("%s_%d", f->name, i)->ptr;
484 f_frameset = frame_download_source(frame.body,
486 current->baseURL, flag);
488 deleteFrame(frame.body);
489 f->frame[i].set = frame.set = f_frameset;
490 goto render_frameset;
494 init_stream(&f2, SCM_LOCAL, NULL);
495 if (frame.body->source) {
497 examineFile(frame.body->source, &f2);
499 if (f2.stream == NULL) {
500 frame.body->attr = F_UNLOADED;
501 if (frame.body->flags & FB_NO_BUFFER)
502 /* FIXME: gettextize? */
503 fprintf(f1, "Open %s with other method",
504 html_quote(frame.body->url));
505 else if (frame.body->url)
506 /* FIXME: gettextize? */
507 fprintf(f1, "Can't open %s",
508 html_quote(frame.body->url));
510 /* FIXME: gettextize? */
512 "This frame (%s) contains no src attribute",
513 frame.body->name ? html_quote(frame.body->name)
517 parseURL2(frame.body->url, &base, currentURL);
519 s_target = frame.body->name;
521 d_target = TargetSelf ? s_target : t_target;
523 charset = WC_CES_US_ASCII;
524 if (current->document_charset != WC_CES_US_ASCII)
525 doc_charset = current->document_charset;
527 doc_charset = DocumentCharset;
530 if (frame.body->type &&
531 !strcasecmp(frame.body->type, "text/plain")) {
533 fprintf(f1, "<pre>\n");
534 while ((tmp = StrmyUFgets(&f2))->length) {
535 tmp = convertLine(NULL, tmp, HTML_MODE, &charset,
537 fprintf(f1, "%s", html_quote(tmp->ptr));
539 fprintf(f1, "</pre>\n");
546 struct parsed_tag *tag;
550 Str tmp = StrmyUFgets(&f2);
551 if (tmp->length == 0)
553 tmp = convertLine(NULL, tmp, HTML_MODE, &charset,
557 read_token(tok, &p, &status, 1, status != R_ST_NORMAL);
558 } while (status != R_ST_NORMAL);
560 if (tok->length == 0)
563 if (tok->ptr[0] == '<') {
565 REALLY_THE_BEGINNING_OF_A_TAG(tok->ptr))
567 else if (!(pre_mode & (RB_PLAIN | RB_INTXTA |
568 RB_SCRIPT | RB_STYLE))) {
569 p = Strnew_m_charp(tok->ptr + 1, p, NULL)->ptr;
570 tok = Strnew_charp("<");
574 if (pre_mode & (RB_PLAIN | RB_INTXTA | RB_SCRIPT |
577 if ((tag = parse_tag(&q, FALSE)) &&
578 tag->tagid == end_tag) {
579 if (pre_mode & RB_PLAIN) {
580 fputs("</PRE_PLAIN>", f1);
589 if (strncmp(tok->ptr, "<!--", 4) &&
590 (q = strchr(tok->ptr + 1, '<'))) {
591 tok = Strnew_charp_n(tok->ptr, q - tok->ptr);
592 p = Strnew_m_charp(q, p, NULL)->ptr;
593 status = R_ST_NORMAL;
597 else if (pre_mode & RB_INSELECT) {
599 if ((tag = parse_tag(&q, FALSE))) {
600 if ((tag->tagid == end_tag) ||
601 (tag->tagid == HTML_N_FORM)) {
602 if (tag->tagid == HTML_N_FORM)
603 fputs("</SELECT>", f1);
609 switch (tag->tagid) {
613 fputs("</SELECT>", f1);
629 if (!(tag = parse_tag(&q, FALSE)))
632 switch (tag->tagid) {
634 fputs("<!-- title:", f1);
640 /* "BASE" is prohibit tag */
641 if (parsedtag_get_value(tag, ATTR_HREF, &q)) {
642 q = url_quote_conv(remove_space(q), charset);
643 parseURL(q, &base, NULL);
645 if (parsedtag_get_value(tag, ATTR_TARGET, &q)) {
646 if (!strcasecmp(q, "_self"))
648 else if (!strcasecmp(q, "_parent"))
651 d_target = url_quote_conv(q, charset);
653 Strshrinkfirst(tok, 1);
655 fprintf(f1, "<!-- %s -->", html_quote(tok->ptr));
658 if (parsedtag_get_value(tag, ATTR_HTTP_EQUIV, &q)
659 && !strcasecmp(q, "refresh")) {
660 if (parsedtag_get_value(tag, ATTR_CONTENT, &q)
663 int refresh_interval =
664 getMetaRefreshParam(q, &s_tmp);
666 q = html_quote(s_tmp->ptr);
668 "Refresh (%d sec) <a href=\"%s\">%s</a>\n",
669 refresh_interval, q, q);
674 if (UseContentCharset &&
675 parsedtag_get_value(tag, ATTR_HTTP_EQUIV, &q)
676 && !strcasecmp(q, "Content-Type")
677 && parsedtag_get_value(tag, ATTR_CONTENT, &q)
678 && (q = strcasestr(q, "charset")) != NULL) {
685 if ((c = wc_guess_charset(q, 0)) != 0) {
687 charset = WC_CES_US_ASCII;
692 /* fall thru, "META" is prohibit tag */
699 Strshrinkfirst(tok, 1);
701 fprintf(f1, "<!-- %s -->", html_quote(tok->ptr));
710 Strshrinkfirst(tok, 1);
713 "<!-- table stack underflow: %s -->",
714 html_quote(tok->ptr));
719 /* table_tags MUST be in table stack */
721 Strshrinkfirst(tok, 1);
723 fprintf(f1, "<!-- %s -->",
724 html_quote(tok->ptr));
730 pre_mode = RB_INSELECT;
731 end_tag = HTML_N_SELECT;
734 pre_mode = RB_INTXTA;
735 end_tag = HTML_N_TEXTAREA;
738 pre_mode = RB_SCRIPT;
739 end_tag = HTML_N_SCRIPT;
743 end_tag = HTML_N_STYLE;
747 end_tag = HTML_N_LISTING;
748 fputs("<PRE_PLAIN>", f1);
752 end_tag = HTML_N_XMP;
753 fputs("<PRE_PLAIN>", f1);
757 end_tag = MAX_HTMLTAG;
758 fputs("<PRE_PLAIN>", f1);
763 for (j = 0; j < TagMAP[tag->tagid].max_attribute; j++) {
764 switch (tag->attrid[j]) {
771 url_quote_conv(remove_space(tag->value[j]),
773 tag->need_reconstruct = TRUE;
774 parseURL2(tag->value[j], &url, &base);
775 if (url.scheme == SCM_UNKNOWN ||
776 #ifndef USE_W3MMAILER
777 url.scheme == SCM_MAILTO ||
779 url.scheme == SCM_MISSING)
782 tag->value[j] = parsedURL2Str(&url)->ptr;
783 parsedtag_set_value(tag,
785 parsedURL2Str(&base)->ptr);
787 if (tag->attrid[j] == ATTR_ACTION &&
788 charset != WC_CES_US_ASCII)
789 parsedtag_set_value(tag,
799 if (!strcasecmp(tag->value[j], "_self")) {
800 parsedtag_set_value(tag,
801 ATTR_TARGET, s_target);
803 else if (!strcasecmp(tag->value[j], "_parent")) {
804 parsedtag_set_value(tag,
805 ATTR_TARGET, p_target);
812 parsedtag_set_value(tag,
813 ATTR_FRAMENAME, s_target);
818 /* there is HREF attribute and no TARGET
820 parsedtag_set_value(tag, ATTR_TARGET, d_target);
822 if (parsedtag_need_reconstruct(tag))
823 tok = parsedtag2str(tag);
827 if (pre_mode & RB_PLAIN)
828 fprintf(f1, "%s", html_quote(tok->ptr));
829 else if (pre_mode & RB_INTXTA)
831 html_quote(html_unquote(tok->ptr)));
837 } while (*p != '\0' || !iseos(f2.stream));
838 if (pre_mode & RB_PLAIN)
839 fputs("</PRE_PLAIN>\n", f1);
840 else if (pre_mode & RB_INTXTA)
841 fputs("</TEXTAREA></FORM>\n", f1);
842 else if (pre_mode & RB_INSELECT)
843 fputs("</SELECT></FORM>\n", f1);
844 else if (pre_mode & (RB_SCRIPT | RB_STYLE)) {
845 if (status != R_ST_NORMAL)
846 fputs(correct_irrtag(status)->ptr, f1);
847 if (pre_mode & RB_SCRIPT)
848 fputs("</SCRIPT>\n", f1);
849 else if (pre_mode & RB_STYLE)
850 fputs("</STYLE>\n", f1);
853 fputs("</TABLE>\n", f1);
858 if (!frame.set->name && f->name) {
859 frame.set->name = Sprintf("%s_%d", f->name, i)->ptr;
861 createFrameFile(frame.set, f1, current, level + 1,
865 fputs("</td>\n", f1);
867 fputs("</tr>\n", f1);
870 fputs("</table>\n", f1);
872 fputs("</body></html>\n", f1);
879 renderFrame(Buffer *Cbuf, int force_reload)
885 struct frameset *fset;
887 wc_ces doc_charset = DocumentCharset;
890 tmp = tmpfname(TMPF_FRAME, ".html");
891 f = fopen(tmp->ptr, "w");
895 * if (Cbuf->frameQ != NULL) fset = Cbuf->frameQ->frameset; else */
896 fset = Cbuf->frameset;
897 if (fset == NULL || createFrameFile(fset, f, Cbuf, 0, force_reload) < 0)
901 if ((Cbuf->currentURL).is_nocache)
903 renderFrameSet = Cbuf->frameset;
904 flushFrameSet(renderFrameSet);
906 DocumentCharset = InnerCharset;
908 buf = loadGeneralFile(tmp->ptr, NULL, NULL, flag, NULL);
910 DocumentCharset = doc_charset;
912 renderFrameSet = NULL;
913 if (buf == NULL || buf == NO_BUFFER)
915 buf->sourcefile = tmp->ptr;
917 buf->document_charset = Cbuf->document_charset;
919 copyParsedURL(&buf->currentURL, &Cbuf->currentURL);
920 preFormUpdateBuffer(buf);
924 union frameset_element *
925 search_frame(struct frameset *fset, char *name)
928 union frameset_element *e = NULL;
930 for (i = 0; i < fset->col * fset->row; i++) {
931 e = &(fset->frame[i]);
932 if (e->element != NULL) {
933 if (e->element->name && !strcmp(e->element->name, name)) {
936 else if (e->element->attr == F_FRAMESET &&
937 (e = search_frame(e->set, name))) {