aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/css.cc141
-rw-r--r--src/css.hh51
-rw-r--r--src/cssparser.cc14
-rw-r--r--src/dillo.cc3
-rw-r--r--src/form.cc2
-rw-r--r--src/html.cc280
-rw-r--r--src/html_common.hh9
-rw-r--r--src/misc.c1
-rw-r--r--src/styleengine.cc10
-rw-r--r--src/styleengine.hh3
-rw-r--r--src/url.c10
11 files changed, 356 insertions, 168 deletions
diff --git a/src/css.cc b/src/css.cc
index d4dc72ad..4938a1cf 100644
--- a/src/css.cc
+++ b/src/css.cc
@@ -1,7 +1,7 @@
/*
* File: css.cc
*
- * Copyright 2008-2009 Johannes Hofmann <Johannes.Hofmann@gmx.de>
+ * Copyright 2008-2014 Johannes Hofmann <Johannes.Hofmann@gmx.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -108,33 +108,31 @@ CssSelector::CssSelector () {
struct CombinatorAndSelector *cs;
refCount = 0;
- selectorList = new lout::misc::SimpleVector
- <struct CombinatorAndSelector> (1);
- selectorList->increase ();
- cs = selectorList->getRef (selectorList->size () - 1);
+ matchCacheOffset = -1;
+ selectorList.increase ();
+ cs = selectorList.getRef (selectorList.size () - 1);
- cs->notMatchingBefore = -1;
cs->combinator = COMB_NONE;
cs->selector = new CssSimpleSelector ();
}
CssSelector::~CssSelector () {
- for (int i = selectorList->size () - 1; i >= 0; i--)
- delete selectorList->getRef (i)->selector;
- delete selectorList;
+ for (int i = selectorList.size () - 1; i >= 0; i--)
+ delete selectorList.getRef (i)->selector;
}
/**
* \brief Return whether selector matches at a given node in the document tree.
*/
bool CssSelector::match (Doctree *docTree, const DoctreeNode *node,
- int i, Combinator comb) {
+ int i, Combinator comb, MatchCache *matchCache) {
+ int *matchCacheEntry;
assert (node);
if (i < 0)
return true;
- struct CombinatorAndSelector *cs = selectorList->getRef (i);
+ struct CombinatorAndSelector *cs = selectorList.getRef (i);
CssSimpleSelector *sel = cs->selector;
switch (comb) {
@@ -148,14 +146,16 @@ bool CssSelector::match (Doctree *docTree, const DoctreeNode *node,
break;
case COMB_DESCENDANT:
node = docTree->parent (node);
+ matchCacheEntry = matchCache->getRef(matchCacheOffset + i);
for (const DoctreeNode *n = node;
- n && n->num > cs->notMatchingBefore; n = docTree->parent (n))
- if (sel->match (n) && match (docTree, n, i - 1, cs->combinator))
+ n && n->num > *matchCacheEntry; n = docTree->parent (n))
+ if (sel->match (n) &&
+ match (docTree, n, i - 1, cs->combinator, matchCache))
return true;
if (node) // remember that it didn't match to avoid future tests
- cs->notMatchingBefore = node->num;
+ *matchCacheEntry = node->num;
return false;
break;
@@ -167,23 +167,23 @@ bool CssSelector::match (Doctree *docTree, const DoctreeNode *node,
return false;
// tail recursion should be optimized by the compiler
- return match (docTree, node, i - 1, cs->combinator);
+ return match (docTree, node, i - 1, cs->combinator, matchCache);
}
void CssSelector::addSimpleSelector (Combinator c) {
struct CombinatorAndSelector *cs;
- selectorList->increase ();
- cs = selectorList->getRef (selectorList->size () - 1);
+ assert (matchCacheOffset == -1);
+ selectorList.increase ();
+ cs = selectorList.getRef (selectorList.size () - 1);
cs->combinator = c;
- cs->notMatchingBefore = -1;
cs->selector = new CssSimpleSelector ();
}
bool CssSelector::checksPseudoClass () {
- for (int i = 0; i < selectorList->size (); i++)
- if (selectorList->getRef (i)->selector->getPseudoClass ())
+ for (int i = 0; i < selectorList.size (); i++)
+ if (selectorList.getRef (i)->selector->getPseudoClass ())
return true;
return false;
}
@@ -197,18 +197,18 @@ bool CssSelector::checksPseudoClass () {
int CssSelector::specificity () {
int spec = 0;
- for (int i = 0; i < selectorList->size (); i++)
- spec += selectorList->getRef (i)->selector->specificity ();
+ for (int i = 0; i < selectorList.size (); i++)
+ spec += selectorList.getRef (i)->selector->specificity ();
return spec;
}
void CssSelector::print () {
- for (int i = 0; i < selectorList->size (); i++) {
- selectorList->getRef (i)->selector->print ();
+ for (int i = 0; i < selectorList.size (); i++) {
+ selectorList.getRef (i)->selector->print ();
- if (i < selectorList->size () - 1) {
- switch (selectorList->getRef (i + 1)->combinator) {
+ if (i < selectorList.size () - 1) {
+ switch (selectorList.getRef (i + 1)->combinator) {
case COMB_CHILD:
fprintf (stderr, "> ");
break;
@@ -230,17 +230,13 @@ void CssSelector::print () {
CssSimpleSelector::CssSimpleSelector () {
element = ELEMENT_ANY;
- klass = NULL;
id = NULL;
pseudo = NULL;
}
CssSimpleSelector::~CssSimpleSelector () {
- if (klass) {
- for (int i = 0; i < klass->size (); i++)
- dFree (klass->get (i));
- delete klass;
- }
+ for (int i = 0; i < klass.size (); i++)
+ dFree (klass.get (i));
dFree (id);
dFree (pseudo);
}
@@ -248,10 +244,8 @@ CssSimpleSelector::~CssSimpleSelector () {
void CssSimpleSelector::setSelect (SelectType t, const char *v) {
switch (t) {
case SELECT_CLASS:
- if (klass == NULL)
- klass = new lout::misc::SimpleVector <char *> (1);
- klass->increase ();
- klass->set (klass->size () - 1, dStrdup (v));
+ klass.increase ();
+ klass.set (klass.size () - 1, dStrdup (v));
break;
case SELECT_PSEUDO_CLASS:
if (pseudo == NULL)
@@ -279,20 +273,18 @@ bool CssSimpleSelector::match (const DoctreeNode *n) {
return false;
if (id != NULL && (n->id == NULL || dStrAsciiCasecmp (id, n->id) != 0))
return false;
- if (klass != NULL) {
- for (int i = 0; i < klass->size (); i++) {
- bool found = false;
- if (n->klass != NULL) {
- for (int j = 0; j < n->klass->size (); j++) {
- if (dStrAsciiCasecmp (klass->get(i), n->klass->get(j)) == 0) {
- found = true;
- break;
- }
+ for (int i = 0; i < klass.size (); i++) {
+ bool found = false;
+ if (n->klass != NULL) {
+ for (int j = 0; j < n->klass->size (); j++) {
+ if (dStrAsciiCasecmp (klass.get(i), n->klass->get(j)) == 0) {
+ found = true;
+ break;
}
}
- if (! found)
- return false;
}
+ if (! found)
+ return false;
}
return true;
@@ -308,8 +300,7 @@ int CssSimpleSelector::specificity () {
if (id)
spec += 1 << 20;
- if (klass)
- spec += klass->size() << 10;
+ spec += klass.size() << 10;
if (pseudo)
spec += 1 << 10;
if (element != ELEMENT_ANY)
@@ -321,11 +312,9 @@ int CssSimpleSelector::specificity () {
void CssSimpleSelector::print () {
fprintf (stderr, "Element %d, pseudo %s, id %s ",
element, pseudo, id);
- if (klass != NULL) {
- fprintf (stderr, "class ");
- for (int i = 0; i < klass->size (); i++)
- fprintf (stderr, ".%s", klass->get (i));
- }
+ fprintf (stderr, "class ");
+ for (int i = 0; i < klass.size (); i++)
+ fprintf (stderr, ".%s", klass.get (i));
}
CssRule::CssRule (CssSelector *selector, CssPropertyList *props, int pos) {
@@ -344,9 +333,9 @@ CssRule::~CssRule () {
props->unref ();
}
-void CssRule::apply (CssPropertyList *props,
- Doctree *docTree, const DoctreeNode *node) {
- if (selector->match (docTree, node))
+void CssRule::apply (CssPropertyList *props, Doctree *docTree,
+ const DoctreeNode *node, MatchCache *matchCache) const {
+ if (selector->match (docTree, node, matchCache))
this->props->apply (props);
}
@@ -410,6 +399,8 @@ void CssStyleSheet::addRule (CssRule *rule) {
}
if (ruleList) {
+ rule->selector->setMatchCacheOffset (matchCacheOffset);
+ matchCacheOffset += rule->selector->size ();
ruleList->insert (rule);
} else {
assert (top->getElement () == CssSimpleSelector::ELEMENT_NONE);
@@ -423,10 +414,10 @@ void CssStyleSheet::addRule (CssRule *rule) {
* The properties are set as defined by the rules in the stylesheet that
* match at the given node in the document tree.
*/
-void CssStyleSheet::apply (CssPropertyList *props,
- Doctree *docTree, const DoctreeNode *node) {
+void CssStyleSheet::apply (CssPropertyList *props, Doctree *docTree,
+ const DoctreeNode *node, MatchCache *matchCache) const {
static const int maxLists = 32;
- RuleList *ruleList[maxLists];
+ const RuleList *ruleList[maxLists];
int numLists = 0, index[maxLists] = {0};
if (node->id) {
@@ -470,7 +461,7 @@ void CssStyleSheet::apply (CssPropertyList *props,
int minSpecIndex = -1;
for (int i = 0; i < numLists; i++) {
- RuleList *rl = ruleList[i];
+ const RuleList *rl = ruleList[i];
if (rl && rl->size () > index[i] &&
(rl->get(index[i])->specificity () < minSpec ||
@@ -484,8 +475,8 @@ void CssStyleSheet::apply (CssPropertyList *props,
}
if (minSpecIndex >= 0) {
- ruleList[minSpecIndex]->get (index[minSpecIndex])->apply
- (props, docTree, node);
+ CssRule *rule = ruleList[minSpecIndex]->get (index[minSpecIndex]);
+ rule->apply(props, docTree, node, matchCache);
index[minSpecIndex]++;
} else {
break;
@@ -493,8 +484,11 @@ void CssStyleSheet::apply (CssPropertyList *props,
}
}
+CssStyleSheet CssContext::userAgentSheet;
+
CssContext::CssContext () {
pos = 0;
+ matchCache[CSS_PRIMARY_USER_AGENT].setSize (userAgentSheet.matchCacheOffset, -1);
}
/**
@@ -511,23 +505,28 @@ void CssContext::apply (CssPropertyList *props, Doctree *docTree,
CssPropertyList *tagStyle, CssPropertyList *tagStyleImportant,
CssPropertyList *nonCssHints) {
- sheet[CSS_PRIMARY_USER_AGENT].apply (props, docTree, node);
- sheet[CSS_PRIMARY_USER].apply (props, docTree, node);
+ userAgentSheet.apply (props, docTree, node,
+ &matchCache[CSS_PRIMARY_USER_AGENT]);
+ sheet[CSS_PRIMARY_USER].apply (props, docTree, node,
+ &matchCache[CSS_PRIMARY_USER]);
if (nonCssHints)
nonCssHints->apply (props);
- sheet[CSS_PRIMARY_AUTHOR].apply (props, docTree, node);
+ sheet[CSS_PRIMARY_AUTHOR].apply (props, docTree, node,
+ &matchCache[CSS_PRIMARY_AUTHOR]);
if (tagStyle)
tagStyle->apply (props);
- sheet[CSS_PRIMARY_AUTHOR_IMPORTANT].apply (props, docTree, node);
+ sheet[CSS_PRIMARY_AUTHOR_IMPORTANT].apply (props, docTree, node,
+ &matchCache[CSS_PRIMARY_AUTHOR_IMPORTANT]);
if (tagStyleImportant)
tagStyleImportant->apply (props);
- sheet[CSS_PRIMARY_USER_IMPORTANT].apply (props, docTree, node);
+ sheet[CSS_PRIMARY_USER_IMPORTANT].apply (props, docTree, node,
+ &matchCache[CSS_PRIMARY_USER_IMPORTANT]);
}
void CssContext::addRule (CssSelector *sel, CssPropertyList *props,
@@ -541,8 +540,12 @@ void CssContext::addRule (CssSelector *sel, CssPropertyList *props,
!rule->isSafe ()) {
MSG_WARN ("Ignoring unsafe author style that might reveal browsing history\n");
delete rule;
- } else {
+ } else if (order == CSS_PRIMARY_USER_AGENT) {
+ userAgentSheet.addRule (rule);
+ matchCache[CSS_PRIMARY_USER_AGENT].setSize (userAgentSheet.matchCacheOffset, -1);
+ } else {
sheet[order].addRule (rule);
+ matchCache[order].setSize (sheet[order].matchCacheOffset, -1);
}
}
}
diff --git a/src/css.hh b/src/css.hh
index a7143c27..4dd94ffe 100644
--- a/src/css.hh
+++ b/src/css.hh
@@ -293,6 +293,7 @@ class CssProperty {
switch (type) {
case CSS_TYPE_STRING:
case CSS_TYPE_SYMBOL:
+ case CSS_TYPE_URI:
dFree (value.strVal);
break;
case CSS_TYPE_BACKGROUND_POSITION:
@@ -335,7 +336,7 @@ class CssSimpleSelector {
private:
int element;
char *pseudo, *id;
- lout::misc::SimpleVector <char *> *klass;
+ lout::misc::SimpleVector <char *> klass;
public:
enum {
@@ -354,7 +355,7 @@ class CssSimpleSelector {
~CssSimpleSelector ();
inline void setElement (int e) { element = e; };
void setSelect (SelectType t, const char *v);
- inline lout::misc::SimpleVector <char *> *getClass () { return klass; };
+ inline lout::misc::SimpleVector <char *> *getClass () { return &klass; };
inline const char *getPseudoClass () { return pseudo; };
inline const char *getId () { return id; };
inline int getElement () { return element; };
@@ -363,6 +364,11 @@ class CssSimpleSelector {
void print ();
};
+class MatchCache : public lout::misc::SimpleVector <int> {
+ public:
+ MatchCache() : lout::misc::SimpleVector <int> (0) {};
+};
+
/**
* \brief CSS selector class.
*
@@ -379,26 +385,31 @@ class CssSelector {
private:
struct CombinatorAndSelector {
- int notMatchingBefore; // used for optimizing CSS selector matching
Combinator combinator;
CssSimpleSelector *selector;
};
- int refCount;
- lout::misc::SimpleVector <struct CombinatorAndSelector> *selectorList;
+ int refCount, matchCacheOffset;
+ lout::misc::SimpleVector <struct CombinatorAndSelector> selectorList;
- bool match (Doctree *dt, const DoctreeNode *node, int i, Combinator comb);
+ bool match (Doctree *dt, const DoctreeNode *node, int i, Combinator comb,
+ MatchCache *matchCache);
public:
CssSelector ();
~CssSelector ();
void addSimpleSelector (Combinator c);
inline CssSimpleSelector *top () {
- return selectorList->getRef (selectorList->size () - 1)->selector;
+ return selectorList.getRef (selectorList.size () - 1)->selector;
+ };
+ inline int size () { return selectorList.size (); };
+ inline bool match (Doctree *dt, const DoctreeNode *node,
+ MatchCache *matchCache) {
+ return match (dt, node, selectorList.size () - 1, COMB_NONE,
+ matchCache);
};
- inline int size () { return selectorList->size (); };
- inline bool match (Doctree *dt, const DoctreeNode *node) {
- return match (dt, node, selectorList->size () - 1, COMB_NONE);
+ inline void setMatchCacheOffset (int mo) {
+ matchCacheOffset = mo;
};
int specificity ();
bool checksPseudoClass ();
@@ -423,8 +434,8 @@ class CssRule {
CssRule (CssSelector *selector, CssPropertyList *props, int pos);
~CssRule ();
- void apply (CssPropertyList *props,
- Doctree *docTree, const DoctreeNode *node);
+ void apply (CssPropertyList *props, Doctree *docTree,
+ const DoctreeNode *node, MatchCache *matchCache) const;
inline bool isSafe () {
return !selector->checksPseudoClass () || props->isSafe ();
};
@@ -463,19 +474,23 @@ class CssStyleSheet {
<lout::object::ConstString, RuleList > (true, true, 256) {};
};
- static const int ntags = 90 + 10; // \todo don't hardcode
+ static const int ntags = 90 + 14; // \todo don't hardcode
/* 90 is the full number of html4 elements, including those which we have
- * implemented. From html 5, let's add: article, header, footer, mark,
- * nav, section, aside, figure, figcaption, wbr.
+ * implemented. From html5, let's add: article, header, footer, mark,
+ * nav, section, aside, figure, figcaption, wbr, audio, video, source,
+ * embed.
*/
RuleList elementTable[ntags], anyTable;
RuleMap idTable, classTable;
public:
+ int matchCacheOffset;
+
+ CssStyleSheet () { matchCacheOffset = 0; }
void addRule (CssRule *rule);
- void apply (CssPropertyList *props,
- Doctree *docTree, const DoctreeNode *node);
+ void apply (CssPropertyList *props, Doctree *docTree,
+ const DoctreeNode *node, MatchCache *matchCache) const;
};
/**
@@ -483,7 +498,9 @@ class CssStyleSheet {
*/
class CssContext {
private:
+ static CssStyleSheet userAgentSheet;
CssStyleSheet sheet[CSS_PRIMARY_USER_IMPORTANT + 1];
+ MatchCache matchCache[CSS_PRIMARY_USER_IMPORTANT + 1];
int pos;
public:
diff --git a/src/cssparser.cc b/src/cssparser.cc
index 4ff8f4f7..07412a8d 100644
--- a/src/cssparser.cc
+++ b/src/cssparser.cc
@@ -19,6 +19,7 @@
#include <stdlib.h>
#include <stdio.h>
+#include "lout/debug.hh"
#include "msg.h"
#include "colors.h"
#include "html_common.hh"
@@ -27,7 +28,6 @@
using namespace dw::core::style;
-#define DEBUG_MSG(A, B, ...) _MSG(B, __VA_ARGS__)
#define MSG_CSS(A, ...) MSG(A, __VA_ARGS__)
#define DEBUG_TOKEN_LEVEL 0
#define DEBUG_PARSE_LEVEL 0
@@ -287,7 +287,7 @@ typedef struct {
CSS_SHORTHAND_BORDER, /* special, used for 'border' */
CSS_SHORTHAND_FONT, /* special, used for 'font' */
} type;
- const CssPropertyName * properties;/* CSS_SHORTHAND_MULTIPLE:
+ const CssPropertyName *properties; /* CSS_SHORTHAND_MULTIPLE:
* must be terminated by -1
* CSS_SHORTHAND_DIRECTIONS:
* must have length 4
@@ -728,7 +728,7 @@ bool CssParser::tokenMatchesProperty(CssPropertyName prop, CssValueType *type)
dStrAsciiCasecmp(tval, "right") == 0 ||
dStrAsciiCasecmp(tval, "top") == 0 ||
dStrAsciiCasecmp(tval, "bottom") == 0))
- return true;
+ return true;
// Fall Through (lenght and percentage)
case CSS_TYPE_LENGTH_PERCENTAGE:
case CSS_TYPE_LENGTH_PERCENTAGE_NUMBER:
@@ -871,7 +871,7 @@ bool CssParser::parseRgbColor(int32_t *c) {
bool CssParser::parseValue(CssPropertyName prop,
CssValueType type,
- CssPropertyValue * val)
+ CssPropertyValue *val)
{
CssLengthType lentype;
bool found, ret = false;
@@ -1199,8 +1199,8 @@ static int Css_shorthand_info_cmp(const void *a, const void *b)
((CssShorthandInfo *) b)->symbol);
}
-void CssParser::parseDeclaration(CssPropertyList * props,
- CssPropertyList * importantProps)
+void CssParser::parseDeclaration(CssPropertyList *props,
+ CssPropertyList *importantProps)
{
CssPropertyInfo pi = {NULL, {CSS_TYPE_UNUSED}, NULL}, *pip;
CssShorthandInfo *sip;
@@ -1715,7 +1715,7 @@ void CssParser::ignoreStatement()
}
}
-void CssParser::parse(DilloHtml *html, DilloUrl *url, CssContext * context,
+void CssParser::parse(DilloHtml *html, DilloUrl *url, CssContext *context,
const char *buf,
int buflen, CssOrigin origin)
{
diff --git a/src/dillo.cc b/src/dillo.cc
index 9930ae74..4d96988f 100644
--- a/src/dillo.cc
+++ b/src/dillo.cc
@@ -52,6 +52,7 @@
#include "cookies.h"
#include "domain.h"
#include "auth.h"
+#include "styleengine.hh"
#include "lout/debug.hh"
#include "dw/fltkcore.hh"
@@ -379,6 +380,7 @@ int main(int argc, char **argv)
DBG_OBJ_COLOR("#c0ff80", "dw::*");
DBG_OBJ_COLOR("#c0c0ff", "dw::fltk::*");
DBG_OBJ_COLOR("#ffa0a0", "dw::core::*");
+ DBG_OBJ_COLOR("#ffe0a0", "dw::core::style::*");
DBG_OBJ_COLOR ("#80ffa0", "dw::Image");
DBG_OBJ_COLOR ("#f0ff80", "dw::Textblock");
@@ -479,6 +481,7 @@ int main(int argc, char **argv)
a_Cookies_init();
a_Auth_init();
a_UIcmd_init();
+ StyleEngine::init();
dw::Textblock::setPenaltyHyphen (prefs.penalty_hyphen);
dw::Textblock::setPenaltyHyphen2 (prefs.penalty_hyphen_2);
diff --git a/src/form.cc b/src/form.cc
index c5bb10af..07c12815 100644
--- a/src/form.cc
+++ b/src/form.cc
@@ -2003,7 +2003,7 @@ static Embed *Html_input_image(DilloHtml *html, const char *tag, int tagsize)
html->styleEngine->setPseudoLink ();
/* create new image and add it to the button */
- a_Html_image_attrs(html, tag, tagsize);
+ a_Html_common_image_attrs(html, tag, tagsize);
if ((Image = a_Html_image_new(html, tag, tagsize))) {
// At this point, we know that Image->ir represents an image
// widget. Notice that the order of the casts matters, because
diff --git a/src/html.cc b/src/html.cc
index 74b90577..3319b35e 100644
--- a/src/html.cc
+++ b/src/html.cc
@@ -1383,7 +1383,7 @@ static void Html_tag_cleanup_at_close(DilloHtml *html, int new_idx)
* by closing them before opening another.
* This is not an HTML SPEC restriction , but it avoids lots of trouble
* inside dillo (concurrent inputs), and makes almost no sense to have.
- */
+ */
static void Html_tag_cleanup_nested_inputs(DilloHtml *html, int new_idx)
{
static int i_BUTTON = a_Html_tag_index("button"),
@@ -1696,9 +1696,9 @@ static void Html_tag_close_head(DilloHtml *html)
/* match for the well formed start of HEAD section */
if (html->Num_TITLE == 0)
BUG_MSG("HEAD section lacks the TITLE element\n");
-
+
html->InFlags &= ~IN_HEAD;
-
+
/* charset is already set, load remote stylesheets now */
for (int i = 0; i < html->cssUrls->size(); i++) {
a_Html_load_stylesheet(html, html->cssUrls->get(i));
@@ -2084,13 +2084,13 @@ static void Html_tag_open_abbr(DilloHtml *html, const char *tag, int tagsize)
/*
* Read image-associated tag attributes and create new image.
*/
-void a_Html_image_attrs(DilloHtml *html, const char *tag, int tagsize)
+void a_Html_common_image_attrs(DilloHtml *html, const char *tag, int tagsize)
{
char *width_ptr, *height_ptr;
const char *attrbuf;
CssLength l_w = CSS_CREATE_LENGTH(0.0, CSS_LENGTH_TYPE_AUTO);
CssLength l_h = CSS_CREATE_LENGTH(0.0, CSS_LENGTH_TYPE_AUTO);
- int space, border, w = 0, h = 0;
+ int w = 0, h = 0;
if (prefs.show_tooltip &&
(attrbuf = a_Html_get_attr(html, tag, tagsize, "title"))) {
@@ -2126,7 +2126,8 @@ void a_Html_image_attrs(DilloHtml *html, const char *tag, int tagsize)
dFree(width_ptr);
dFree(height_ptr);
width_ptr = height_ptr = NULL;
- MSG("a_Html_image_attrs: suspicious image size request %d x %d\n", w, h);
+ MSG("a_Html_common_image_attrs: suspicious image size request %d x %d\n",
+ w, h);
} else {
if (CSS_LENGTH_TYPE(l_w) != CSS_LENGTH_TYPE_AUTO)
html->styleEngine->setNonCssHint (CSS_PROPERTY_WIDTH,
@@ -2143,55 +2144,6 @@ void a_Html_image_attrs(DilloHtml *html, const char *tag, int tagsize)
[...]
*/
- /* Spacing to the left and right */
- if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "hspace"))) {
- space = strtol(attrbuf, NULL, 10);
- if (space > 0) {
- space = CSS_CREATE_LENGTH(space, CSS_LENGTH_TYPE_PX);
- html->styleEngine->setNonCssHint (CSS_PROPERTY_MARGIN_LEFT,
- CSS_TYPE_LENGTH_PERCENTAGE, space);
- html->styleEngine->setNonCssHint (CSS_PROPERTY_MARGIN_RIGHT,
- CSS_TYPE_LENGTH_PERCENTAGE, space);
- }
- }
-
- /* Spacing at the top and bottom */
- if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "vspace"))) {
- space = strtol(attrbuf, NULL, 10);
- if (space > 0) {
- space = CSS_CREATE_LENGTH(space, CSS_LENGTH_TYPE_PX);
- html->styleEngine->setNonCssHint (CSS_PROPERTY_MARGIN_TOP,
- CSS_TYPE_LENGTH_PERCENTAGE, space);
- html->styleEngine->setNonCssHint (CSS_PROPERTY_MARGIN_BOTTOM,
- CSS_TYPE_LENGTH_PERCENTAGE, space);
- }
- }
-
- /* Border */
- if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "border"))) {
- border = strtol(attrbuf, NULL, 10);
- if (border >= 0) {
- border = CSS_CREATE_LENGTH(border, CSS_LENGTH_TYPE_PX);
- html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_TOP_WIDTH,
- CSS_TYPE_LENGTH_PERCENTAGE, border);
- html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_BOTTOM_WIDTH,
- CSS_TYPE_LENGTH_PERCENTAGE, border);
- html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_LEFT_WIDTH,
- CSS_TYPE_LENGTH_PERCENTAGE, border);
- html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_RIGHT_WIDTH,
- CSS_TYPE_LENGTH_PERCENTAGE, border);
-
- html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_TOP_STYLE,
- CSS_TYPE_ENUM, BORDER_SOLID);
- html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_BOTTOM_STYLE,
- CSS_TYPE_ENUM, BORDER_SOLID);
- html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_LEFT_STYLE,
- CSS_TYPE_ENUM, BORDER_SOLID);
- html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_RIGHT_STYLE,
- CSS_TYPE_ENUM, BORDER_SOLID);
- }
- }
-
/* x_img is an index to a list of {url,image} pairs.
* We know a_Html_image_new() will use size() as its next index */
html->styleEngine->setNonCssHint (PROPERTY_X_IMG, CSS_TYPE_INTEGER,
@@ -2272,7 +2224,60 @@ static bool Html_load_image(BrowserWindow *bw, DilloUrl *url,
static void Html_tag_open_img(DilloHtml *html, const char *tag, int tagsize)
{
- a_Html_image_attrs(html, tag, tagsize);
+ int space, border;
+ const char *attrbuf;
+
+ a_Html_common_image_attrs(html, tag, tagsize);
+
+ /* Spacing to the left and right */
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "hspace"))) {
+ space = strtol(attrbuf, NULL, 10);
+ if (space > 0) {
+ space = CSS_CREATE_LENGTH(space, CSS_LENGTH_TYPE_PX);
+ html->styleEngine->setNonCssHint (CSS_PROPERTY_MARGIN_LEFT,
+ CSS_TYPE_LENGTH_PERCENTAGE, space);
+ html->styleEngine->setNonCssHint (CSS_PROPERTY_MARGIN_RIGHT,
+ CSS_TYPE_LENGTH_PERCENTAGE, space);
+ }
+ }
+
+ /* Spacing at the top and bottom */
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "vspace"))) {
+ space = strtol(attrbuf, NULL, 10);
+ if (space > 0) {
+ space = CSS_CREATE_LENGTH(space, CSS_LENGTH_TYPE_PX);
+ html->styleEngine->setNonCssHint (CSS_PROPERTY_MARGIN_TOP,
+ CSS_TYPE_LENGTH_PERCENTAGE, space);
+ html->styleEngine->setNonCssHint (CSS_PROPERTY_MARGIN_BOTTOM,
+ CSS_TYPE_LENGTH_PERCENTAGE, space);
+ }
+ }
+
+ /* Border */
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "border"))) {
+ border = strtol(attrbuf, NULL, 10);
+ if (border >= 0) {
+ border = CSS_CREATE_LENGTH(border, CSS_LENGTH_TYPE_PX);
+ html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_TOP_WIDTH,
+ CSS_TYPE_LENGTH_PERCENTAGE, border);
+ html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_BOTTOM_WIDTH,
+ CSS_TYPE_LENGTH_PERCENTAGE, border);
+ html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_LEFT_WIDTH,
+ CSS_TYPE_LENGTH_PERCENTAGE, border);
+ html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_RIGHT_WIDTH,
+ CSS_TYPE_LENGTH_PERCENTAGE, border);
+
+ html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_TOP_STYLE,
+ CSS_TYPE_ENUM, BORDER_SOLID);
+ html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_BOTTOM_STYLE,
+ CSS_TYPE_ENUM, BORDER_SOLID);
+ html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_LEFT_STYLE,
+ CSS_TYPE_ENUM, BORDER_SOLID);
+ html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_RIGHT_STYLE,
+ CSS_TYPE_ENUM, BORDER_SOLID);
+ }
+ }
+
}
/*
@@ -2509,10 +2514,156 @@ static void Html_tag_open_object(DilloHtml *html, const char *tag, int tagsize)
html->styleEngine->setNonCssHint(PROPERTY_X_LINK, CSS_TYPE_INTEGER,
Html_set_new_link(html, &url));
+ }
+ a_Url_free(base_url);
+}
+static void Html_tag_content_object(DilloHtml *html, const char *tag,
+ int tagsize)
+{
+ if (a_Html_get_attr(html, tag, tagsize, "data"))
HT2TB(html)->addText("[OBJECT]", html->wordStyle ());
+}
+
+/*
+ * <VIDEO>
+ * Provide a link to the video.
+ */
+static void Html_tag_open_video(DilloHtml *html, const char *tag, int tagsize)
+{
+ DilloUrl *url;
+ const char *attrbuf;
+
+ if (html->InFlags & IN_MEDIA) {
+ MSG("<video> not handled when already inside a media element.\n");
+ return;
}
- a_Url_free(base_url);
+ /* TODO: poster attr */
+
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "src"))) {
+ url = a_Html_url_new(html, attrbuf, NULL, 0);
+ dReturn_if_fail ( url != NULL );
+
+ if (a_Capi_get_flags_with_redirection(url) & CAPI_IsCached) {
+ html->styleEngine->setPseudoVisited ();
+ } else {
+ html->styleEngine->setPseudoLink ();
+ }
+
+ html->styleEngine->setNonCssHint(PROPERTY_X_LINK, CSS_TYPE_INTEGER,
+ Html_set_new_link(html, &url));
+
+ HT2TB(html)->addText("[VIDEO]", html->wordStyle ());
+ }
+ html->InFlags |= IN_MEDIA;
+}
+
+/*
+ * <AUDIO>
+ * Provide a link to the audio.
+ */
+static void Html_tag_open_audio(DilloHtml *html, const char *tag, int tagsize)
+{
+ DilloUrl *url;
+ const char *attrbuf;
+
+ if (html->InFlags & IN_MEDIA) {
+ MSG("<audio> not handled when already inside a media element.\n");
+ return;
+ }
+
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "src"))) {
+ url = a_Html_url_new(html, attrbuf, NULL, 0);
+ dReturn_if_fail ( url != NULL );
+
+ if (a_Capi_get_flags_with_redirection(url) & CAPI_IsCached) {
+ html->styleEngine->setPseudoVisited ();
+ } else {
+ html->styleEngine->setPseudoLink ();
+ }
+
+ html->styleEngine->setNonCssHint(PROPERTY_X_LINK, CSS_TYPE_INTEGER,
+ Html_set_new_link(html, &url));
+
+ HT2TB(html)->addText("[AUDIO]", html->wordStyle ());
+ }
+ html->InFlags |= IN_MEDIA;
+}
+
+/*
+ * <SOURCE>
+ * Media resource; provide a link to its address.
+ */
+static void Html_tag_open_source(DilloHtml *html, const char *tag,
+ int tagsize)
+{
+ const char *attrbuf;
+
+ if (!(html->InFlags & IN_MEDIA)) {
+ BUG_MSG("<source> element not inside a media element.\n");
+ return;
+ }
+ if (!(attrbuf = a_Html_get_attr(html, tag, tagsize, "src"))) {
+ BUG_MSG("src attribute is required in <source> element.\n");
+ return;
+ } else {
+ DilloUrl *url = a_Html_url_new(html, attrbuf, NULL, 0);
+
+ dReturn_if_fail ( url != NULL );
+
+ if (a_Capi_get_flags_with_redirection(url) & CAPI_IsCached) {
+ html->styleEngine->setPseudoVisited ();
+ } else {
+ html->styleEngine->setPseudoLink ();
+ }
+ html->styleEngine->setNonCssHint(PROPERTY_X_LINK, CSS_TYPE_INTEGER,
+ Html_set_new_link(html, &url));
+ }
+}
+
+static void Html_tag_content_source(DilloHtml *html, const char *tag,
+ int tagsize)
+{
+ if ((html->InFlags & IN_MEDIA) && a_Html_get_attr(html, tag, tagsize,"src"))
+ HT2TB(html)->addText("[MEDIA SOURCE]", html->wordStyle ());
+}
+
+/*
+ * Media (AUDIO/VIDEO) close function
+ */
+static void Html_tag_close_media(DilloHtml *html)
+{
+ html->InFlags &= ~IN_MEDIA;
+}
+
+/*
+ * <EMBED>
+ * Provide a link to embedded content.
+ */
+static void Html_tag_open_embed(DilloHtml *html, const char *tag, int tagsize)
+{
+ const char *attrbuf;
+
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "src"))) {
+ DilloUrl *url = a_Html_url_new(html, attrbuf, NULL, 0);
+
+ dReturn_if_fail ( url != NULL );
+
+ if (a_Capi_get_flags_with_redirection(url) & CAPI_IsCached) {
+ html->styleEngine->setPseudoVisited ();
+ } else {
+ html->styleEngine->setPseudoLink ();
+ }
+
+ html->styleEngine->setNonCssHint(PROPERTY_X_LINK, CSS_TYPE_INTEGER,
+ Html_set_new_link(html, &url));
+ }
+}
+
+static void Html_tag_content_embed(DilloHtml *html,const char *tag,int tagsize)
+{
+ if (a_Html_get_attr(html, tag, tagsize, "src"))
+ HT2TB(html)->addText("[EMBED]", html->wordStyle ());
}
/*
@@ -2997,8 +3148,11 @@ static void Html_tag_open_meta(DilloHtml *html, const char *tag, int tagsize)
} else {
sprintf(delay_str, ".");
}
- /* Skip to anything after "URL=" */
- while (*content && *(content++) != '=') ;
+ /* Skip to anything after "URL=" or ";" if "URL=" is not found */
+ if ((p = dStriAsciiStr(content, "url=")))
+ content = p + strlen("url=");
+ else if ((p = strstr(content, ";")))
+ content = p + strlen(";");
/* Handle the case of a quoted URL */
if (*content == '"' || *content == '\'') {
if ((p = strchr(content + 1, *content)))
@@ -3280,6 +3434,7 @@ const TagInfo Tags[] = {
NULL},
{"article", B8(011110),'R',2, Html_tag_open_default, NULL, NULL},
{"aside", B8(011110),'R',2, Html_tag_open_default, NULL, NULL},
+ {"audio", B8(011101),'R',2, Html_tag_open_audio, NULL, Html_tag_close_media},
{"b", B8(010101),'R',2, Html_tag_open_default, NULL, NULL},
{"base", B8(100001),'F',0, Html_tag_open_base, NULL, NULL},
/* basefont 010001 -- obsolete in HTML5 */
@@ -3306,6 +3461,7 @@ const TagInfo Tags[] = {
{"dl", B8(011010),'R',2, Html_tag_open_dl, NULL, Html_tag_close_par},
{"dt", B8(010110),'O',1, Html_tag_open_dt, NULL, Html_tag_close_par},
{"em", B8(010101),'R',2, Html_tag_open_default, NULL, NULL},
+ {"embed", B8(010001),'F',0, Html_tag_open_embed, Html_tag_content_embed,NULL},
/* fieldset */
{"figcaption", B8(011110),'R',2, Html_tag_open_default, NULL, NULL},
{"figure", B8(011110),'R',2, Html_tag_open_default, NULL, NULL},
@@ -3349,7 +3505,8 @@ const TagInfo Tags[] = {
{"nav", B8(011110),'R',2, Html_tag_open_default, NULL, NULL},
/* noframes 1011 -- obsolete in HTML5 */
/* noscript 1011 */
- {"object", B8(111101),'R',2, Html_tag_open_object, NULL, NULL},
+ {"object", B8(111101),'R',2, Html_tag_open_object, Html_tag_content_object,
+ NULL},
{"ol", B8(011010),'R',2, Html_tag_open_ol, NULL, NULL},
{"optgroup", B8(010101),'O',1, Html_tag_open_optgroup, NULL,
Html_tag_close_optgroup},
@@ -3364,6 +3521,8 @@ const TagInfo Tags[] = {
{"section", B8(011110),'R',2, Html_tag_open_default, NULL, NULL},
{"select", B8(010101),'R',2, Html_tag_open_select,NULL,Html_tag_close_select},
{"small", B8(010101),'R',2, Html_tag_open_default, NULL, NULL},
+ {"source", B8(010001),'F',0, Html_tag_open_source, Html_tag_content_source,
+ NULL},
{"span", B8(010101),'R',2, Html_tag_open_span, NULL, NULL},
{"strike", B8(010101),'R',2, Html_tag_open_default, NULL, NULL},
{"strong", B8(010101),'R',2, Html_tag_open_default, NULL, NULL},
@@ -3388,6 +3547,7 @@ const TagInfo Tags[] = {
{"u", B8(010101),'R',2, Html_tag_open_default, NULL, NULL},
{"ul", B8(011010),'R',2, Html_tag_open_ul, NULL, NULL},
{"var", B8(010101),'R',2, Html_tag_open_default, NULL, NULL},
+ {"video", B8(011101),'R',2, Html_tag_open_video, NULL, Html_tag_close_media},
{"wbr", B8(010101),'F',0, Html_tag_open_default, Html_tag_content_wbr, NULL}
};
#define NTAGS (sizeof(Tags)/sizeof(Tags[0]))
diff --git a/src/html_common.hh b/src/html_common.hh
index a43d91b7..de3069cb 100644
--- a/src/html_common.hh
+++ b/src/html_common.hh
@@ -87,8 +87,9 @@ typedef enum {
IN_MAP = 1 << 9,
IN_PRE = 1 << 10,
IN_LI = 1 << 11,
- IN_META_HACK = 1 << 12,
- IN_EOF = 1 << 13,
+ IN_MEDIA = 1 << 12,
+ IN_META_HACK = 1 << 13,
+ IN_EOF = 1 << 14,
} DilloHtmlProcessingState;
/*
@@ -233,7 +234,7 @@ public:
{ return styleEngine->wordStyle (bw, base_url); }
inline void restyle () { styleEngine->restyle (bw, base_url); }
-
+
};
/*
@@ -257,7 +258,7 @@ DilloUrl *a_Html_url_new(DilloHtml *html,
const char *url_str, const char *base_url,
int use_base_url);
-void a_Html_image_attrs(DilloHtml *html, const char *tag, int tagsize);
+void a_Html_common_image_attrs(DilloHtml *html, const char *tag, int tagsize);
DilloImage *a_Html_image_new(DilloHtml *html, const char *tag, int tagsize);
char *a_Html_parse_entities(DilloHtml *html, const char *token, int toksize);
diff --git a/src/misc.c b/src/misc.c
index 3e8496e5..00589999 100644
--- a/src/misc.c
+++ b/src/misc.c
@@ -115,6 +115,7 @@ static const ContentType_t MimeTypes[] = {
typedef enum {
DT_OCTET_STREAM = 0,
+ DT_PLACEHOLDER,
DT_TEXT_HTML,
DT_TEXT_PLAIN,
DT_IMAGE_GIF,
diff --git a/src/styleengine.cc b/src/styleengine.cc
index 2da9d8f7..ffc0b0f6 100644
--- a/src/styleengine.cc
+++ b/src/styleengine.cc
@@ -65,7 +65,6 @@ StyleEngine::StyleEngine (dw::core::Layout *layout) {
doctree = new Doctree ();
stack = new lout::misc::SimpleVector <Node> (1);
cssContext = new CssContext ();
- buildUserAgentStyle ();
buildUserStyle ();
this->layout = layout;
importDepth = 0;
@@ -548,8 +547,10 @@ void StyleEngine::apply (int i, StyleAttrs *attrs, CssPropertyList *props,
attrs->backgroundImage->connectDeletion
(new StyleImageDeletionReceiver (clientKey));
}
+
+ a_Url_free (imgUrl);
}
- break;
+ break;
case CSS_PROPERTY_BACKGROUND_POSITION:
computeLength (&attrs->backgroundPositionX, p->value.posVal->posX,
attrs->font);
@@ -958,7 +959,7 @@ void StyleEngine::parse (DilloHtml *html, DilloUrl *url, const char *buf,
* The user agent style defines how dillo renders HTML in the absence of
* author or user styles.
*/
-void StyleEngine::buildUserAgentStyle () {
+void StyleEngine::init () {
const char *cssBuf =
"body {margin: 5px}"
"big {font-size: 1.17em}"
@@ -1015,7 +1016,8 @@ void StyleEngine::buildUserAgentStyle () {
*/
"table, caption {font-size: medium; font-weight: normal}";
- CssParser::parse (NULL, NULL, cssContext, cssBuf, strlen (cssBuf),
+ CssContext context;
+ CssParser::parse (NULL, NULL, &context, cssBuf, strlen (cssBuf),
CSS_ORIGIN_USER_AGENT);
}
diff --git a/src/styleengine.hh b/src/styleengine.hh
index 714553ff..bec4875b 100644
--- a/src/styleengine.hh
+++ b/src/styleengine.hh
@@ -38,7 +38,6 @@ class StyleEngine {
void stackPush ();
void stackPop ();
- void buildUserAgentStyle ();
void buildUserStyle ();
dw::core::style::Style *style0 (int i, BrowserWindow *bw, DilloUrl *url);
dw::core::style::Style *wordStyle0 (BrowserWindow *bw, DilloUrl *url);
@@ -64,6 +63,8 @@ class StyleEngine {
dw::core::style::Font *font);
public:
+ static void init ();
+
StyleEngine (dw::core::Layout *layout);
~StyleEngine ();
diff --git a/src/url.c b/src/url.c
index 6780ca8e..9d3e14b2 100644
--- a/src/url.c
+++ b/src/url.c
@@ -688,14 +688,14 @@ static uint_t Url_host_public_internal_dots(const char *host)
if (tld_len > 0) {
/* These TLDs were chosen by examining the current publicsuffix list
- * in September 2013 and picking out those where it was simplest for
+ * in February 2014 and picking out those where it was simplest for
* them to describe the situation by beginning with a "*.[tld]" rule
* or every rule was "[something].[tld]".
*/
- const char *const tlds[] = {"au","bd","bn","ck","cy","er","et","fj",
- "fk","gn","gu","il","jm","ke","kh","kp",
- "kw","lb","lr","mm","mt","mz","ni","np",
- "nz","pg","tr","uk","ye","za","zm","zw"};
+ const char *const tlds[] = {"bd","bn","ck","cy","er","et","fj","fk",
+ "gu","il","jm","ke","kh","kw","mm","mz",
+ "ni","np","nz","pg","tr","uk","ye","za",
+ "zm","zw"};
uint_t i, tld_num = sizeof(tlds) / sizeof(tlds[0]);
for (i = 0; i < tld_num; i++) {