1 /* General element handlers */
8 #define _GNU_SOURCE /* strcasestr() */
18 #include "config/options.h"
19 #include "document/css/apply.h"
20 #include "document/html/frames.h"
21 #include "document/html/parser/general.h"
22 #include "document/html/parser/link.h"
23 #include "document/html/parser/stack.h"
24 #include "document/html/parser/parse.h"
25 #include "document/html/parser.h"
26 #include "document/html/renderer.h"
27 #include "document/html/tables.h"
28 #include "document/options.h"
29 #include "intl/charsets.h"
30 #include "protocol/uri.h"
31 #include "terminal/draw.h"
32 #include "util/align.h"
34 #include "util/color.h"
35 #include "util/conv.h"
36 #include "util/error.h"
37 #include "util/memdebug.h"
38 #include "util/memory.h"
39 #include "util/string.h"
42 #include "document/html/internal.h"
46 html_span(struct html_context
*html_context
, unsigned char *a
,
47 unsigned char *xxx3
, unsigned char *xxx4
, unsigned char **xxx5
)
52 html_bold(struct html_context
*html_context
, unsigned char *a
,
53 unsigned char *xxx3
, unsigned char *xxx4
, unsigned char **xxx5
)
55 format
.style
.attr
|= AT_BOLD
;
59 html_italic(struct html_context
*html_context
, unsigned char *a
,
60 unsigned char *xxx3
, unsigned char *xxx4
, unsigned char **xxx5
)
62 format
.style
.attr
|= AT_ITALIC
;
66 html_underline(struct html_context
*html_context
, unsigned char *a
,
67 unsigned char *xxx3
, unsigned char *xxx4
, unsigned char **xxx5
)
69 format
.style
.attr
|= AT_UNDERLINE
;
73 html_fixed(struct html_context
*html_context
, unsigned char *a
,
74 unsigned char *xxx3
, unsigned char *xxx4
, unsigned char **xxx5
)
76 format
.style
.attr
|= AT_FIXED
;
80 html_subscript(struct html_context
*html_context
, unsigned char *a
,
81 unsigned char *xxx3
, unsigned char *xxx4
, unsigned char **xxx5
)
83 put_chrs(html_context
, "[", 1);
87 html_subscript_close(struct html_context
*html_context
, unsigned char *a
,
88 unsigned char *xxx3
, unsigned char *xxx4
, unsigned char **xxx5
)
90 put_chrs(html_context
, "]", 1);
94 html_superscript(struct html_context
*html_context
, unsigned char *a
,
95 unsigned char *xxx3
, unsigned char *xxx4
, unsigned char **xxx5
)
97 put_chrs(html_context
, "^", 1);
100 /* TODO: Add more languages. */
101 static unsigned char *quote_char
[2] = { "\"", "'" };
104 html_quote(struct html_context
*html_context
, unsigned char *a
,
105 unsigned char *xxx3
, unsigned char *xxx4
, unsigned char **xxx5
)
107 /* An HTML document containing extremely many repetitions of
108 * "<q>" could cause @html_context->quote_level to overflow.
109 * Because it is unsigned, it then wraps around to zero, and
110 * we don't get a negative array index here. If the document
111 * then tries to close the quotes with "</q>", @html_quote_close
112 * won't let the quote level wrap back, so it will render the
113 * quotes incorrectly, but such a document probably doesn't
114 * make sense anyway. */
115 unsigned char *q
= quote_char
[html_context
->quote_level
++ % 2];
117 put_chrs(html_context
, q
, 1);
121 html_quote_close(struct html_context
*html_context
, unsigned char *a
,
122 unsigned char *xxx3
, unsigned char *xxx4
,
123 unsigned char **xxx5
)
127 if (html_context
->quote_level
> 0)
128 html_context
->quote_level
--;
130 q
= quote_char
[html_context
->quote_level
% 2];
132 put_chrs(html_context
, q
, 1);
136 html_font(struct html_context
*html_context
, unsigned char *a
,
137 unsigned char *xxx3
, unsigned char *xxx4
, unsigned char **xxx5
)
139 unsigned char *al
= get_attr_val(a
, "size", html_context
->doc_cp
);
144 unsigned char *nn
= al
;
147 if (*al
== '+') p
= 1, nn
++;
148 else if (*al
== '-') p
= -1, nn
++;
151 s
= strtoul(nn
, (char **) &end
, 10);
152 if (!errno
&& *nn
&& !*end
) {
154 if (!p
) format
.fontsize
= s
;
155 else format
.fontsize
+= p
* s
;
156 if (format
.fontsize
< 1) format
.fontsize
= 1;
157 else if (format
.fontsize
> 7) format
.fontsize
= 7;
161 get_color(html_context
, a
, "color", &format
.style
.fg
);
165 html_body(struct html_context
*html_context
, unsigned char *a
,
166 unsigned char *xxx3
, unsigned char *xxx4
, unsigned char **xxx5
)
168 get_color(html_context
, a
, "text", &format
.style
.fg
);
169 get_color(html_context
, a
, "link", &format
.clink
);
170 get_color(html_context
, a
, "vlink", &format
.vlink
);
172 if (get_bgcolor(html_context
, a
, &format
.style
.bg
) != -1)
173 html_context
->was_body_background
= 1;
175 html_context
->was_body
= 1; /* this will be used by "meta inside body" */
176 html_apply_canvas_bgcolor(html_context
);
180 html_apply_canvas_bgcolor(struct html_context
*html_context
)
183 /* If there are any CSS twaks regarding bgcolor, make sure we will get
184 * it _and_ prefer it over bgcolor attribute. */
185 if (html_context
->options
->css_enable
)
186 css_apply(html_context
, html_top
, &html_context
->css_styles
,
187 &html_context
->stack
);
190 if (par_format
.bgcolor
!= format
.style
.bg
) {
191 /* Modify the root HTML element - format_html_part() will take
192 * this from there. */
193 struct html_element
*e
= html_bottom
;
195 html_context
->was_body_background
= 1;
196 e
->parattr
.bgcolor
= e
->attr
.style
.bg
= par_format
.bgcolor
= format
.style
.bg
;
199 if (html_context
->has_link_lines
200 && par_format
.bgcolor
!= html_context
->options
->default_bg
201 && !search_html_stack(html_context
, "BODY")) {
202 html_context
->special_f(html_context
, SP_COLOR_LINK_LINES
);
207 html_script(struct html_context
*html_context
, unsigned char *a
,
208 unsigned char *html
, unsigned char *eof
, unsigned char **end
)
210 #ifdef CONFIG_ECMASCRIPT
211 /* TODO: <noscript> processing. Well, same considerations apply as to
212 * CSS property display: none processing. */
213 /* TODO: Charsets for external scripts. */
214 unsigned char *type
, *language
, *src
;
218 html_skip(html_context
, a
);
220 #ifdef CONFIG_ECMASCRIPT
221 /* We try to process nested <script> if we didn't process the parent
222 * one. That's why's all the fuzz. */
224 * http://www.ietf.org/internet-drafts/draft-hoehrmann-script-types-03.txt
226 type
= get_attr_val(a
, "type", html_context
->doc_cp
);
228 unsigned char *pos
= type
;
230 if (!strncasecmp(type
, "text/", 5)) {
233 } else if (!strncasecmp(type
, "application/", 12)) {
239 /* Permit nested scripts and retreat. */
240 html_top
->invisible
++;
244 if (!strncasecmp(pos
, "javascript", 10)) {
245 int len
= strlen(pos
);
247 if (len
> 10 && !isdigit(pos
[10])) {
252 } else if (strcasecmp(pos
, "ecmascript")
253 && strcasecmp(pos
, "jscript")
254 && strcasecmp(pos
, "livescript")
255 && strcasecmp(pos
, "x-javascript")
256 && strcasecmp(pos
, "x-ecmascript")) {
264 /* Check that the script content is ecmascript. The value of the
265 * language attribute can be JavaScript with optional version digits
266 * postfixed (like: ``JavaScript1.1'').
267 * That attribute is deprecated in favor of type by HTML 4.01 */
268 language
= get_attr_val(a
, "language", html_context
->doc_cp
);
270 int languagelen
= strlen(language
);
273 || (languagelen
> 10 && !isdigit(language
[10]))
274 || strncasecmp(language
, "javascript", 10)) {
282 if (html_context
->part
->document
283 && (src
= get_attr_val(a
, "src", html_context
->doc_cp
))) {
284 /* External reference. */
286 unsigned char *import_url
;
289 if (!get_opt_bool("ecmascript.enable")) {
294 /* HTML <head> urls should already be fine but we can.t detect them. */
295 import_url
= join_urls(html_context
->base_href
, src
);
297 if (!import_url
) goto imported
;
299 uri
= get_uri(import_url
, URI_BASE
);
300 if (!uri
) goto imported
;
302 /* Request the imported script as part of the document ... */
303 html_context
->special_f(html_context
, SP_SCRIPT
, uri
);
306 /* Create URL reference onload snippet. */
307 insert_in_string(&import_url
, 0, "^", 1);
308 add_to_string_list(&html_context
->part
->document
->onload_snippets
,
312 /* Retreat. Do not permit nested scripts, tho'. */
313 if (import_url
) mem_free(import_url
);
317 /* Positive, grab the rest and interpret it. */
319 /* First position to the real script start. */
320 while (html
< eof
&& *html
<= ' ') html
++;
321 if (eof
- html
> 4 && !strncmp(html
, "<!--", 4)) {
323 /* We either skip to the end of line or to -->. */
324 for (; *html
!= '\n' && *html
!= '\r' && eof
- html
>= 3; html
++) {
325 if (!strncmp(html
, "-->", 3)) {
326 /* This means the document is probably broken.
327 * We will now try to process the rest of
328 * <script> contents, which is however likely
329 * to be empty. Should we try to process the
330 * comment too? Currently it seems safer but
331 * less tolerant to broken pages, if there are
342 /* Now look ahead for the script end. The <script> contents is raw
343 * CDATA, so we just look for the ending tag and need not care for
344 * any quote marks counting etc - YET, we are more tolerant and permit
345 * </script> stuff inside of the script if the whole <script> element
346 * contents is wrapped in a comment. See i.e. Mozilla bug 26857 for fun
347 * reading regarding this. */
348 for (; *end
< eof
; (*end
)++) {
353 /* TODO: If we ever get some standards-quirk mode
354 * distinction, this should be disabled in the
355 * standards mode (and we should just look for CDATA
356 * end, which is "</"). --pasky */
357 if (eof
- *end
>= 3 && !strncmp(*end
, "-->", 3)) {
358 /* Next iteration will jump passed the ending '>' */
363 /* XXX: Scan for another comment? That's admittelly
364 * already stretching things a little bit to an
370 /* We want to land before the closing element, that's why we
371 * don't pass @end also as the appropriate parse_element()
373 if (parse_element(*end
, eof
, &name
, &namelen
, NULL
, NULL
))
375 if (strlcasecmp(name
, namelen
, "/script", 7))
381 /* Either the document is not completely loaded yet or it's
382 * broken. At any rate, run away screaming. */
383 *end
= eof
; /* Just for sanity. */
387 if (html_context
->part
->document
&& *html
!= '^') {
388 add_to_string_list(&html_context
->part
->document
->onload_snippets
,
395 html_style(struct html_context
*html_context
, unsigned char *a
,
396 unsigned char *xxx3
, unsigned char *xxx4
, unsigned char **xxx5
)
398 html_context
->was_style
= 1;
399 html_skip(html_context
, a
);
403 html_style_close(struct html_context
*html_context
, unsigned char *a
,
404 unsigned char *xxx3
, unsigned char *xxx4
, unsigned char **xxx5
)
406 html_context
->was_style
= 0;
410 html_html(struct html_context
*html_context
, unsigned char *a
,
411 unsigned char *xxx3
, unsigned char *xxx4
, unsigned char **xxx5
)
413 /* This is here just to get CSS stuff applied. */
415 /* Modify the root HTML element - format_html_part() will take
416 * this from there. */
417 struct html_element
*e
= html_bottom
;
419 if (par_format
.bgcolor
!= format
.style
.bg
)
420 e
->parattr
.bgcolor
= e
->attr
.style
.bg
= par_format
.bgcolor
= format
.style
.bg
;
424 html_html_close(struct html_context
*html_context
, unsigned char *a
,
425 unsigned char *xxx3
, unsigned char *xxx4
, unsigned char **xxx5
)
427 if (html_top
->type
>= ELEMENT_KILLABLE
428 && !html_context
->was_body_background
)
429 html_apply_canvas_bgcolor(html_context
);
433 html_head(struct html_context
*html_context
, unsigned char *a
,
434 unsigned char *xxx3
, unsigned char *xxx4
, unsigned char **xxx5
)
436 /* This makes sure it gets to the stack and helps tame down unclosed
441 html_meta(struct html_context
*html_context
, unsigned char *a
,
442 unsigned char *xxx3
, unsigned char *xxx4
, unsigned char **xxx5
)
444 /* html_handle_body_meta() does all the work. */
447 /* Handles meta tags in the HTML body. */
449 html_handle_body_meta(struct html_context
*html_context
, unsigned char *meta
,
454 if (!init_string(&head
)) return;
456 scan_http_equiv(meta
, eof
, &head
, NULL
, html_context
->options
);
457 process_head(html_context
, head
.source
);
462 html_title(struct html_context
*html_context
, unsigned char *a
,
463 unsigned char *xxx3
, unsigned char *xxx4
, unsigned char **xxx5
)
465 html_top
->invisible
= 1;
466 html_top
->type
= ELEMENT_WEAK
;
470 html_center(struct html_context
*html_context
, unsigned char *a
,
471 unsigned char *xxx3
, unsigned char *xxx4
, unsigned char **xxx5
)
473 par_format
.align
= ALIGN_CENTER
;
474 if (!html_context
->table_level
)
475 par_format
.leftmargin
= par_format
.rightmargin
= 0;
479 html_linebrk(struct html_context
*html_context
, unsigned char *a
,
480 unsigned char *xxx3
, unsigned char *xxx4
, unsigned char **xxx5
)
482 unsigned char *al
= get_attr_val(a
, "align", html_context
->doc_cp
);
485 if (!strcasecmp(al
, "left")) par_format
.align
= ALIGN_LEFT
;
486 else if (!strcasecmp(al
, "right")) par_format
.align
= ALIGN_RIGHT
;
487 else if (!strcasecmp(al
, "center")) {
488 par_format
.align
= ALIGN_CENTER
;
489 if (!html_context
->table_level
)
490 par_format
.leftmargin
= par_format
.rightmargin
= 0;
491 } else if (!strcasecmp(al
, "justify")) par_format
.align
= ALIGN_JUSTIFY
;
497 html_br(struct html_context
*html_context
, unsigned char *a
,
498 unsigned char *html
, unsigned char *eof
, unsigned char **end
)
500 html_linebrk(html_context
, a
, html
, eof
, end
);
501 if (html_context
->was_br
)
502 ln_break(html_context
, 2);
504 html_context
->was_br
= 1;
508 html_p(struct html_context
*html_context
, unsigned char *a
,
509 unsigned char *html
, unsigned char *eof
, unsigned char **end
)
511 int_lower_bound(&par_format
.leftmargin
, html_context
->margin
);
512 int_lower_bound(&par_format
.rightmargin
, html_context
->margin
);
513 /*par_format.align = ALIGN_LEFT;*/
514 html_linebrk(html_context
, a
, html
, eof
, end
);
518 html_address(struct html_context
*html_context
, unsigned char *a
,
519 unsigned char *xxx3
, unsigned char *xxx4
, unsigned char **xxx5
)
521 par_format
.leftmargin
++;
522 par_format
.align
= ALIGN_LEFT
;
526 html_blockquote(struct html_context
*html_context
, unsigned char *a
,
527 unsigned char *xxx3
, unsigned char *xxx4
, unsigned char **xxx5
)
529 par_format
.leftmargin
+= 2;
530 par_format
.align
= ALIGN_LEFT
;
534 html_h(int h
, unsigned char *a
,
535 enum format_align default_align
, struct html_context
*html_context
,
536 unsigned char *html
, unsigned char *eof
, unsigned char **end
)
538 if (!par_format
.align
) par_format
.align
= default_align
;
539 html_linebrk(html_context
, a
, html
, eof
, end
);
544 switch (par_format
.align
) {
546 par_format
.leftmargin
= h
* 2;
547 par_format
.rightmargin
= 0;
550 par_format
.leftmargin
= 0;
551 par_format
.rightmargin
= h
* 2;
554 par_format
.leftmargin
= par_format
.rightmargin
= 0;
557 par_format
.leftmargin
= par_format
.rightmargin
= h
* 2;
563 html_h1(struct html_context
*html_context
, unsigned char *a
,
564 unsigned char *html
, unsigned char *eof
, unsigned char **end
)
566 format
.style
.attr
|= AT_BOLD
;
567 html_h(1, a
, ALIGN_CENTER
, html_context
, html
, eof
, end
);
571 html_h2(struct html_context
*html_context
, unsigned char *a
,
572 unsigned char *html
, unsigned char *eof
, unsigned char **end
)
574 html_h(2, a
, ALIGN_LEFT
, html_context
, html
, eof
, end
);
578 html_h3(struct html_context
*html_context
, unsigned char *a
,
579 unsigned char *html
, unsigned char *eof
, unsigned char **end
)
581 html_h(3, a
, ALIGN_LEFT
, html_context
, html
, eof
, end
);
585 html_h4(struct html_context
*html_context
, unsigned char *a
,
586 unsigned char *html
, unsigned char *eof
, unsigned char **end
)
588 html_h(4, a
, ALIGN_LEFT
, html_context
, html
, eof
, end
);
592 html_h5(struct html_context
*html_context
, unsigned char *a
,
593 unsigned char *html
, unsigned char *eof
, unsigned char **end
)
595 html_h(5, a
, ALIGN_LEFT
, html_context
, html
, eof
, end
);
599 html_h6(struct html_context
*html_context
, unsigned char *a
,
600 unsigned char *html
, unsigned char *eof
, unsigned char **end
)
602 html_h(6, a
, ALIGN_LEFT
, html_context
, html
, eof
, end
);
606 html_pre(struct html_context
*html_context
, unsigned char *a
,
607 unsigned char *xxx3
, unsigned char *xxx4
, unsigned char **xxx5
)
609 format
.style
.attr
|= AT_PREFORMATTED
;
610 par_format
.leftmargin
= (par_format
.leftmargin
> 1);
611 par_format
.rightmargin
= 0;
615 html_xmp(struct html_context
*html_context
, unsigned char *a
,
616 unsigned char *html
, unsigned char *eof
, unsigned char **end
)
618 html_context
->was_xmp
= 1;
619 html_pre(html_context
, a
, html
, eof
, end
);
623 html_xmp_close(struct html_context
*html_context
, unsigned char *a
,
624 unsigned char *html
, unsigned char *eof
, unsigned char **end
)
626 html_context
->was_xmp
= 0;
630 html_hr(struct html_context
*html_context
, unsigned char *a
,
631 unsigned char *html
, unsigned char *eof
, unsigned char **end
)
633 int i
/* = par_format.width - 10*/;
634 unsigned char r
= (unsigned char) BORDER_DHLINE
;
635 int q
= get_num(a
, "size", html_context
->doc_cp
);
637 if (q
>= 0 && q
< 2) r
= (unsigned char) BORDER_SHLINE
;
638 html_stack_dup(html_context
, ELEMENT_KILLABLE
);
639 par_format
.align
= ALIGN_CENTER
;
640 mem_free_set(&format
.link
, NULL
);
642 html_linebrk(html_context
, a
, html
, eof
, end
);
643 if (par_format
.align
== ALIGN_JUSTIFY
) par_format
.align
= ALIGN_CENTER
;
644 par_format
.leftmargin
= par_format
.rightmargin
= html_context
->margin
;
646 i
= get_width(a
, "width", 1, html_context
);
647 if (i
== -1) i
= get_html_max_width();
648 format
.style
.attr
= AT_GRAPHICS
;
649 html_context
->special_f(html_context
, SP_NOWRAP
, 1);
651 put_chrs(html_context
, &r
, 1);
653 html_context
->special_f(html_context
, SP_NOWRAP
, 0);
654 ln_break(html_context
, 2);
655 pop_html_element(html_context
);
659 html_table(struct html_context
*html_context
, unsigned char *attr
,
660 unsigned char *html
, unsigned char *eof
, unsigned char **end
)
662 if (html_context
->options
->tables
663 && html_context
->table_level
< HTML_MAX_TABLE_LEVEL
) {
664 format_table(attr
, html
, eof
, end
, html_context
);
665 ln_break(html_context
, 2);
670 par_format
.leftmargin
= par_format
.rightmargin
= html_context
->margin
;
671 par_format
.align
= ALIGN_LEFT
;
672 html_linebrk(html_context
, attr
, html
, eof
, end
);
673 format
.style
.attr
= 0;
677 html_tt(struct html_context
*html_context
, unsigned char *a
,
678 unsigned char *xxx3
, unsigned char *xxx4
, unsigned char **xxx5
)
683 html_tr(struct html_context
*html_context
, unsigned char *a
,
684 unsigned char *html
, unsigned char *eof
, unsigned char **end
)
686 html_linebrk(html_context
, a
, html
, eof
, end
);
690 html_th(struct html_context
*html_context
, unsigned char *a
,
691 unsigned char *xxx3
, unsigned char *xxx4
, unsigned char **xxx5
)
693 /*html_linebrk(html_context, a, html, eof, end);*/
694 kill_html_stack_until(html_context
, 1,
695 "TD", "TH", "", "TR", "TABLE", NULL
);
696 format
.style
.attr
|= AT_BOLD
;
697 put_chrs(html_context
, " ", 1);
701 html_td(struct html_context
*html_context
, unsigned char *a
,
702 unsigned char *xxx3
, unsigned char *xxx4
, unsigned char **xxx5
)
704 /*html_linebrk(html_context, a, html, eof, end);*/
705 kill_html_stack_until(html_context
, 1,
706 "TD", "TH", "", "TR", "TABLE", NULL
);
707 format
.style
.attr
&= ~AT_BOLD
;
708 put_chrs(html_context
, " ", 1);
712 html_base(struct html_context
*html_context
, unsigned char *a
,
713 unsigned char *xxx3
, unsigned char *xxx4
, unsigned char **xxx5
)
717 al
= get_url_val(a
, "href", html_context
->doc_cp
);
719 unsigned char *base
= join_urls(html_context
->base_href
, al
);
720 struct uri
*uri
= base
? get_uri(base
, 0) : NULL
;
726 done_uri(html_context
->base_href
);
727 html_context
->base_href
= uri
;
731 al
= get_target(html_context
->options
, a
);
732 if (al
) mem_free_set(&html_context
->base_target
, al
);
736 html_ul(struct html_context
*html_context
, unsigned char *a
,
737 unsigned char *xxx3
, unsigned char *xxx4
, unsigned char **xxx5
)
741 /* dump_html_stack(html_context); */
742 par_format
.list_level
++;
743 par_format
.list_number
= 0;
744 par_format
.flags
= P_STAR
;
746 al
= get_attr_val(a
, "type", html_context
->doc_cp
);
748 if (!strcasecmp(al
, "disc") || !strcasecmp(al
, "circle"))
749 par_format
.flags
= P_O
;
750 else if (!strcasecmp(al
, "square"))
751 par_format
.flags
= P_PLUS
;
754 par_format
.leftmargin
+= 2 + (par_format
.list_level
> 1);
755 if (!html_context
->table_level
)
756 int_upper_bound(&par_format
.leftmargin
, par_format
.width
/ 2);
758 par_format
.align
= ALIGN_LEFT
;
759 html_top
->type
= ELEMENT_DONT_KILL
;
763 html_ol(struct html_context
*html_context
, unsigned char *a
,
764 unsigned char *xxx3
, unsigned char *xxx4
, unsigned char **xxx5
)
769 par_format
.list_level
++;
770 st
= get_num(a
, "start", html_context
->doc_cp
);
771 if (st
== -1) st
= 1;
772 par_format
.list_number
= st
;
773 par_format
.flags
= P_NUMBER
;
775 al
= get_attr_val(a
, "type", html_context
->doc_cp
);
778 if (*al
== '1') par_format
.flags
= P_NUMBER
;
779 else if (*al
== 'a') par_format
.flags
= P_alpha
;
780 else if (*al
== 'A') par_format
.flags
= P_ALPHA
;
781 else if (*al
== 'r') par_format
.flags
= P_roman
;
782 else if (*al
== 'R') par_format
.flags
= P_ROMAN
;
783 else if (*al
== 'i') par_format
.flags
= P_roman
;
784 else if (*al
== 'I') par_format
.flags
= P_ROMAN
;
789 par_format
.leftmargin
+= (par_format
.list_level
> 1);
790 if (!html_context
->table_level
)
791 int_upper_bound(&par_format
.leftmargin
, par_format
.width
/ 2);
793 par_format
.align
= ALIGN_LEFT
;
794 html_top
->type
= ELEMENT_DONT_KILL
;
824 roman(unsigned char *p
, unsigned n
)
838 while (roman_tbl
[i
].n
<= n
) {
840 strcat(p
, roman_tbl
[i
].s
);
843 assertm(!(n
&& !roman_tbl
[i
].n
),
844 "BUG in roman number convertor");
845 if_assert_failed
break;
850 html_li(struct html_context
*html_context
, unsigned char *a
,
851 unsigned char *xxx3
, unsigned char *xxx4
, unsigned char **xxx5
)
853 /* When handling the code <li><li> @was_li will be 1 and it means we
854 * have to insert a line break since no list item content has done it
856 if (html_context
->was_li
) {
857 html_context
->line_breax
= 0;
858 ln_break(html_context
, 1);
861 /*kill_html_stack_until(html_context, 0
862 "", "UL", "OL", NULL);*/
863 if (!par_format
.list_number
) {
864 unsigned char x
[7] = "* ";
865 int t
= par_format
.flags
& P_LISTMASK
;
867 if (t
== P_O
) x
[0] = 'o';
868 if (t
== P_PLUS
) x
[0] = '+';
869 put_chrs(html_context
, x
, 7);
870 par_format
.leftmargin
+= 2;
871 par_format
.align
= ALIGN_LEFT
;
877 int t
= par_format
.flags
& P_LISTMASK
;
878 int s
= get_num(a
, "value", html_context
->doc_cp
);
880 if (s
!= -1) par_format
.list_number
= s
;
882 if (t
== P_ALPHA
|| t
== P_alpha
) {
883 put_chrs(html_context
, " ", 6);
885 n
[0] = par_format
.list_number
886 ? (par_format
.list_number
- 1) % 26
887 + (t
== P_ALPHA
? 'A' : 'a')
891 } else if (t
== P_ROMAN
|| t
== P_roman
) {
892 roman(n
, par_format
.list_number
);
896 for (x
= n
; *x
; x
++) *x
= toupper(*x
);
900 if (par_format
.list_number
< 10) {
901 put_chrs(html_context
, " ", 6);
905 ulongcat(n
, NULL
, par_format
.list_number
, (sizeof(n
) - 1), 0);
909 put_chrs(html_context
, n
, nlen
);
910 put_chrs(html_context
, ". ", 7);
911 par_format
.leftmargin
+= nlen
+ c
+ 2;
912 par_format
.align
= ALIGN_LEFT
;
915 struct html_element
*element
;
917 element
= search_html_stack(html_context
, "ol");
919 element
->parattr
.list_number
= par_format
.list_number
+ 1;
922 par_format
.list_number
= 0;
925 html_context
->putsp
= HTML_SPACE_SUPPRESS
;
926 html_context
->line_breax
= 2;
927 html_context
->was_li
= 1;
931 html_dl(struct html_context
*html_context
, unsigned char *a
,
932 unsigned char *xxx3
, unsigned char *xxx4
, unsigned char **xxx5
)
934 par_format
.flags
&= ~P_COMPACT
;
935 if (has_attr(a
, "compact", html_context
->doc_cp
))
936 par_format
.flags
|= P_COMPACT
;
937 if (par_format
.list_level
) par_format
.leftmargin
+= 5;
938 par_format
.list_level
++;
939 par_format
.list_number
= 0;
940 par_format
.align
= ALIGN_LEFT
;
941 par_format
.dd_margin
= par_format
.leftmargin
;
942 html_top
->type
= ELEMENT_DONT_KILL
;
943 if (!(par_format
.flags
& P_COMPACT
)) {
944 ln_break(html_context
, 2);
945 html_top
->linebreak
= 2;
950 html_dt(struct html_context
*html_context
, unsigned char *a
,
951 unsigned char *xxx3
, unsigned char *xxx4
, unsigned char **xxx5
)
953 kill_html_stack_until(html_context
, 0, "", "DL", NULL
);
954 par_format
.align
= ALIGN_LEFT
;
955 par_format
.leftmargin
= par_format
.dd_margin
;
956 if (!(par_format
.flags
& P_COMPACT
)
957 && !has_attr(a
, "compact", html_context
->doc_cp
))
958 ln_break(html_context
, 2);
962 html_dd(struct html_context
*html_context
, unsigned char *a
,
963 unsigned char *xxx3
, unsigned char *xxx4
, unsigned char **xxx5
)
965 kill_html_stack_until(html_context
, 0, "", "DL", NULL
);
967 par_format
.leftmargin
= par_format
.dd_margin
+ 3;
969 if (!html_context
->table_level
) {
970 par_format
.leftmargin
+= 5;
971 int_upper_bound(&par_format
.leftmargin
, par_format
.width
/ 2);
973 par_format
.align
= ALIGN_LEFT
;
979 html_noframes(struct html_context
*html_context
, unsigned char *a
,
980 unsigned char *xxx3
, unsigned char *xxx4
, unsigned char **xxx5
)
982 struct html_element
*element
;
984 if (!html_context
->options
->frames
) return;
986 element
= search_html_stack(html_context
, "frameset");
987 if (element
&& !element
->frameset
) return;
989 html_skip(html_context
, a
);
993 html_frame(struct html_context
*html_context
, unsigned char *a
,
994 unsigned char *xxx3
, unsigned char *xxx4
, unsigned char **xxx5
)
996 unsigned char *name
, *src
, *url
;
998 src
= get_url_val(a
, "src", html_context
->doc_cp
);
1000 url
= stracpy("about:blank");
1002 url
= join_urls(html_context
->base_href
, src
);
1007 name
= get_attr_val(a
, "name", html_context
->doc_cp
);
1009 name
= stracpy(url
);
1010 } else if (!name
[0]) {
1011 /* When name doesn't have a value */
1013 name
= stracpy(url
);
1017 if (!html_context
->options
->frames
|| !html_top
->frameset
) {
1018 html_focusable(html_context
, a
);
1019 put_link_line("Frame: ", name
, url
, "", html_context
);
1022 if (html_context
->special_f(html_context
, SP_USED
, NULL
)) {
1023 html_context
->special_f(html_context
, SP_FRAME
,
1024 html_top
->frameset
, name
, url
);
1033 html_frameset(struct html_context
*html_context
, unsigned char *a
,
1034 unsigned char *xxx3
, unsigned char *xxx4
, unsigned char **xxx5
)
1036 struct frameset_param fp
;
1037 unsigned char *cols
, *rows
;
1040 /* XXX: This is still not 100% correct. We should also ignore the
1041 * frameset when we encountered anything 3v1l (read as: non-whitespace
1042 * text/element/anything) in the document outside of <head>. Well, this
1043 * is still better than nothing and it should heal up the security
1044 * concerns at least because sane sites should enclose the documents in
1045 * <body> elements ;-). See also bug 171. --pasky */
1046 if (search_html_stack(html_context
, "BODY")
1047 || !html_context
->options
->frames
1048 || !html_context
->special_f(html_context
, SP_USED
, NULL
))
1051 cols
= get_attr_val(a
, "cols", html_context
->doc_cp
);
1053 cols
= stracpy("100%");
1057 rows
= get_attr_val(a
, "rows", html_context
->doc_cp
);
1059 rows
= stracpy("100%");
1066 if (!html_top
->frameset
) {
1067 width
= html_context
->options
->box
.width
;
1068 height
= html_context
->options
->box
.height
;
1069 html_context
->options
->needs_height
= 1;
1071 struct frameset_desc
*frameset_desc
= html_top
->frameset
;
1074 if (frameset_desc
->box
.y
>= frameset_desc
->box
.height
)
1075 goto free_and_return
;
1076 offset
= frameset_desc
->box
.x
1077 + frameset_desc
->box
.y
* frameset_desc
->box
.width
;
1078 width
= frameset_desc
->frame_desc
[offset
].width
;
1079 height
= frameset_desc
->frame_desc
[offset
].height
;
1082 fp
.width
= fp
.height
= NULL
;
1084 parse_frame_widths(cols
, width
, HTML_FRAME_CHAR_WIDTH
,
1086 parse_frame_widths(rows
, height
, HTML_FRAME_CHAR_HEIGHT
,
1089 fp
.parent
= html_top
->frameset
;
1091 html_top
->frameset
= html_context
->special_f(html_context
, SP_FRAMESET
, &fp
);
1093 mem_free_if(fp
.width
);
1094 mem_free_if(fp
.height
);
1102 html_noscript(struct html_context
*html_context
, unsigned char *a
,
1103 unsigned char *xxx3
, unsigned char *xxx4
, unsigned char **xxx5
)
1105 /* We shouldn't throw <noscript> away until our ECMAScript support is
1106 * halfway decent. */
1107 #ifdef CONFIG_ECMASCRIPT
1108 if (get_opt_bool("ecmascript.enable")
1109 && get_opt_bool("ecmascript.ignore_noscript"))
1110 html_skip(html_context
, a
);