mirror of
https://github.com/netsurf-browser/netsurf
synced 2024-12-22 20:16:54 +03:00
[project @ 2003-04-04 15:19:31 by bursa]
New CSS parser. svn path=/import/netsurf/; revision=112
This commit is contained in:
parent
eb256015ad
commit
4421b2e633
@ -1,11 +1,12 @@
|
||||
/**
|
||||
* $Id: content.c,v 1.3 2003/02/28 11:49:13 bursa Exp $
|
||||
* $Id: content.c,v 1.4 2003/04/04 15:19:31 bursa Exp $
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "netsurf/content/content.h"
|
||||
#include "netsurf/css/css.h"
|
||||
#include "netsurf/render/html.h"
|
||||
#include "netsurf/render/textplain.h"
|
||||
#include "netsurf/riscos/jpeg.h"
|
||||
@ -19,8 +20,8 @@ struct mime_entry {
|
||||
};
|
||||
static const struct mime_entry mime_map[] = {
|
||||
{"image/jpeg", CONTENT_JPEG},
|
||||
/* {"image/png", CONTENT_PNG},
|
||||
{"text/css", CONTENT_CSS},*/
|
||||
/* {"image/png", CONTENT_PNG},*/
|
||||
{"text/css", CONTENT_CSS},
|
||||
{"text/html", CONTENT_HTML},
|
||||
{"text/plain", CONTENT_TEXTPLAIN},
|
||||
};
|
||||
@ -40,8 +41,8 @@ static const struct handler_entry handler_map[] = {
|
||||
{textplain_create, textplain_process_data, textplain_convert,
|
||||
textplain_revive, textplain_reformat, textplain_destroy},
|
||||
{jpeg_create, jpeg_process_data, jpeg_convert, jpeg_revive, jpeg_reformat, jpeg_destroy},
|
||||
/* {css_create, css_process_data, css_convert, css_revive, css_destroy},
|
||||
{png_create, png_process_data, png_convert, png_revive, png_destroy},*/
|
||||
{css_create, css_process_data, css_convert, css_revive, css_destroy},
|
||||
/* {png_create, png_process_data, png_convert, png_revive, png_destroy},*/
|
||||
};
|
||||
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/**
|
||||
* $Id: content.h,v 1.2 2003/02/25 21:00:27 bursa Exp $
|
||||
* $Id: content.h,v 1.3 2003/04/04 15:19:31 bursa Exp $
|
||||
*/
|
||||
|
||||
#ifndef _NETSURF_DESKTOP_CONTENT_H_
|
||||
@ -7,7 +7,7 @@
|
||||
|
||||
#include "libxml/HTMLparser.h"
|
||||
#include "netsurf/content/cache.h"
|
||||
#include "netsurf/render/css.h"
|
||||
#include "netsurf/css/css.h"
|
||||
#include "netsurf/render/box.h"
|
||||
#include "netsurf/riscos/font.h"
|
||||
|
||||
@ -66,22 +66,21 @@ struct content
|
||||
struct page_elements elements;
|
||||
} html;
|
||||
|
||||
struct
|
||||
{
|
||||
struct css_stylesheet * stylesheet;
|
||||
} css;
|
||||
struct css_stylesheet *css;
|
||||
|
||||
struct
|
||||
{
|
||||
char * data;
|
||||
unsigned long length;
|
||||
} jpeg;
|
||||
|
||||
|
||||
} data;
|
||||
|
||||
struct cache_entry *cache;
|
||||
unsigned long size;
|
||||
char *title;
|
||||
unsigned int active;
|
||||
int error;
|
||||
};
|
||||
|
||||
|
||||
|
410
css/css.c
Normal file
410
css/css.c
Normal file
@ -0,0 +1,410 @@
|
||||
/**
|
||||
* $Id: css.c,v 1.1 2003/04/04 15:19:31 bursa Exp $
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#define CSS_INTERNALS
|
||||
#include "netsurf/content/content.h"
|
||||
#include "netsurf/css/css.h"
|
||||
#include "netsurf/utils/log.h"
|
||||
#include "netsurf/utils/utils.h"
|
||||
|
||||
/**
|
||||
* internal structures
|
||||
*/
|
||||
|
||||
struct decl {
|
||||
unsigned long score;
|
||||
struct rule * rule;
|
||||
};
|
||||
|
||||
void css_dump_style(const struct css_style * const style);
|
||||
|
||||
|
||||
|
||||
const struct css_style css_base_style = {
|
||||
0xffffff,
|
||||
CSS_CLEAR_NONE,
|
||||
0x000000,
|
||||
CSS_DISPLAY_BLOCK,
|
||||
CSS_FLOAT_NONE,
|
||||
{ CSS_FONT_SIZE_LENGTH, { { 12, CSS_UNIT_PT } } },
|
||||
CSS_FONT_WEIGHT_NORMAL,
|
||||
CSS_FONT_STYLE_NORMAL,
|
||||
{ CSS_HEIGHT_AUTO, { 1, CSS_UNIT_EM } },
|
||||
{ CSS_LINE_HEIGHT_ABSOLUTE, { 1.2 } },
|
||||
CSS_TEXT_ALIGN_LEFT,
|
||||
{ CSS_WIDTH_AUTO, { { 1, CSS_UNIT_EM } } }
|
||||
};
|
||||
|
||||
const struct css_style css_empty_style = {
|
||||
CSS_COLOR_INHERIT,
|
||||
CSS_CLEAR_INHERIT,
|
||||
CSS_COLOR_INHERIT,
|
||||
CSS_DISPLAY_INHERIT,
|
||||
CSS_FLOAT_INHERIT,
|
||||
{ CSS_FONT_SIZE_INHERIT, { { 1, CSS_UNIT_EM } } },
|
||||
CSS_FONT_WEIGHT_INHERIT,
|
||||
CSS_FONT_STYLE_INHERIT,
|
||||
{ CSS_HEIGHT_AUTO, { 1, CSS_UNIT_EM } },
|
||||
{ CSS_LINE_HEIGHT_INHERIT, { 1.2 } },
|
||||
CSS_TEXT_ALIGN_INHERIT,
|
||||
{ CSS_WIDTH_INHERIT, { { 1, CSS_UNIT_EM } } }
|
||||
};
|
||||
|
||||
const struct css_style css_blank_style = {
|
||||
TRANSPARENT,
|
||||
CSS_CLEAR_NONE,
|
||||
CSS_COLOR_INHERIT,
|
||||
CSS_DISPLAY_INLINE,
|
||||
CSS_FLOAT_NONE,
|
||||
{ CSS_FONT_SIZE_INHERIT, { { 1, CSS_UNIT_EM } } },
|
||||
CSS_FONT_WEIGHT_INHERIT,
|
||||
CSS_FONT_STYLE_INHERIT,
|
||||
{ CSS_HEIGHT_AUTO, { 1, CSS_UNIT_EM } },
|
||||
{ CSS_LINE_HEIGHT_INHERIT, { 1.2 } },
|
||||
CSS_TEXT_ALIGN_INHERIT,
|
||||
{ CSS_WIDTH_AUTO, { { 1, CSS_UNIT_EM } } }
|
||||
};
|
||||
|
||||
|
||||
|
||||
void css_create(struct content *c)
|
||||
{
|
||||
LOG(("content %p", c));
|
||||
c->data.css = xcalloc(1, sizeof(*c->data.css));
|
||||
css_lex_init(&c->data.css->lexer);
|
||||
c->data.css->parser = css_parser_Alloc(malloc);
|
||||
c->data.css->rule = 0;
|
||||
c->data.css->last_rule = 0;
|
||||
}
|
||||
|
||||
|
||||
void css_process_data(struct content *c, char *data, unsigned long size)
|
||||
{
|
||||
int token;
|
||||
YY_BUFFER_STATE buffer;
|
||||
|
||||
LOG(("content %p, size %lu", c, size));
|
||||
|
||||
buffer = css__scan_bytes(data, size, c->data.css->lexer);
|
||||
while ((token = css_lex(c->data.css->lexer))) {
|
||||
css_parser_(c->data.css->parser, token,
|
||||
strdup(css_get_text(c->data.css->lexer)),
|
||||
c->data.css);
|
||||
}
|
||||
css__delete_buffer(buffer, c->data.css->lexer);
|
||||
}
|
||||
|
||||
|
||||
int css_convert(struct content *c, unsigned int width, unsigned int height)
|
||||
{
|
||||
LOG(("content %p", c));
|
||||
|
||||
css_parser_(c->data.css->parser, 0, 0, c->data.css);
|
||||
|
||||
css_parser_Free(c->data.css->parser, free);
|
||||
css_lex_destroy(c->data.css->lexer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void css_revive(struct content *c, unsigned int width, unsigned int height)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void css_reformat(struct content *c, unsigned int width, unsigned int height)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void css_destroy(struct content *c)
|
||||
{
|
||||
xfree(c->data.css);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* parser support functions
|
||||
*/
|
||||
|
||||
struct node * css_new_node(node_type type, char *data,
|
||||
struct node *left, struct node *right)
|
||||
{
|
||||
struct node *node = xcalloc(1, sizeof(*node));
|
||||
node->type = type;
|
||||
node->data = data;
|
||||
node->left = left;
|
||||
node->right = right;
|
||||
node->next = 0;
|
||||
node->comb = COMB_NONE;
|
||||
node->style = 0;
|
||||
return node;
|
||||
}
|
||||
|
||||
void css_free_node(struct node *node)
|
||||
{
|
||||
if (node == 0)
|
||||
return;
|
||||
if (node->left != 0)
|
||||
css_free_node(node->left);
|
||||
if (node->right != 0)
|
||||
css_free_node(node->right);
|
||||
if (node->next != 0)
|
||||
css_free_node(node->next);
|
||||
if (node->data != 0)
|
||||
free(node->data);
|
||||
free(node);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void css_get_style(struct css_stylesheet * stylesheet, struct css_selector * selector,
|
||||
unsigned int selectors, struct css_style * style)
|
||||
{
|
||||
struct node *r, *n, *m;
|
||||
unsigned int i;
|
||||
|
||||
LOG(("stylesheet %p, selectors %u", stylesheet, selectors));
|
||||
|
||||
for (r = stylesheet->rule; r != 0; r = r->next) {
|
||||
i = selectors - 1;
|
||||
n = r;
|
||||
/* compare element */
|
||||
if (strcasecmp(selector[i].element, n->data) != 0)
|
||||
goto not_matched;
|
||||
LOG(("top element '%s' matched", selector[i].element));
|
||||
while (1) {
|
||||
/* class and id */
|
||||
for (m = n->left; m != 0; m = m->next) {
|
||||
if (m->type == NODE_ID) {
|
||||
/* TODO: check if case sensitive */
|
||||
if (strcmp(selector[i].id, m->data) != 0)
|
||||
goto not_matched;
|
||||
} else if (m->type == NODE_CLASS) {
|
||||
/* TODO: check if case sensitive */
|
||||
if (strcmp(selector[i].class, m->data) != 0)
|
||||
goto not_matched;
|
||||
} else {
|
||||
goto not_matched;
|
||||
}
|
||||
}
|
||||
LOG(("class and id matched"));
|
||||
/* ancestors etc. */
|
||||
if (n->comb == COMB_NONE)
|
||||
goto matched; /* match successful */
|
||||
else if (n->comb == COMB_ANCESTOR) {
|
||||
/* search for ancestor */
|
||||
assert(n->right != 0);
|
||||
n = n->right;
|
||||
LOG(("searching for ancestor '%s'", n->data));
|
||||
while (i != 0 && strcasecmp(selector[i - 1].element, n->data) != 0)
|
||||
i--;
|
||||
if (i == 0)
|
||||
goto not_matched;
|
||||
i--;
|
||||
LOG(("found"));
|
||||
} else {
|
||||
/* TODO: COMB_PRECEDED, COMB_PARENT */
|
||||
goto not_matched;
|
||||
}
|
||||
}
|
||||
|
||||
matched:
|
||||
/* TODO: sort by specificity */
|
||||
LOG(("matched rule %p", r));
|
||||
css_dump_style(r->style);
|
||||
css_cascade(style, r->style);
|
||||
|
||||
not_matched:
|
||||
|
||||
}
|
||||
|
||||
css_dump_style(style);
|
||||
}
|
||||
|
||||
|
||||
void css_parse_property_list(struct css_style * style, char * str)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* dump a style
|
||||
*/
|
||||
|
||||
static void dump_length(const struct css_length * const length)
|
||||
{
|
||||
LOG(("%g%s", length->value,
|
||||
css_unit_name[length->unit]));
|
||||
}
|
||||
|
||||
#define DUMP_LENGTH(pre, len, post) LOG((pre "%g%s" post, (len)->value, css_unit_name[(len)->unit]));
|
||||
|
||||
void css_dump_style(const struct css_style * const style)
|
||||
{
|
||||
LOG(("{ "));
|
||||
LOG(("background-color: #%lx;", style->background_color));
|
||||
LOG(("clear: %s;", css_clear_name[style->clear]));
|
||||
LOG(("color: #%lx;", style->color));
|
||||
LOG(("display: %s;", css_display_name[style->display]));
|
||||
LOG(("float: %s;", css_float_name[style->float_]));
|
||||
switch (style->font_size.size) {
|
||||
case CSS_FONT_SIZE_ABSOLUTE:
|
||||
LOG(("font-size: [%g];", style->font_size.value.absolute)); break;
|
||||
case CSS_FONT_SIZE_LENGTH:
|
||||
DUMP_LENGTH("font-size: ", &style->font_size.value.length, ";"); break;
|
||||
case CSS_FONT_SIZE_PERCENT:
|
||||
LOG(("font-size: %g%%;", style->font_size.value.percent)); break;
|
||||
case CSS_FONT_SIZE_INHERIT: LOG(("font-size: inherit;")); break;
|
||||
default: LOG(("font-size: UNKNOWN;")); break;
|
||||
}
|
||||
switch (style->height.height) {
|
||||
case CSS_HEIGHT_AUTO: LOG(("height: auto;")); break;
|
||||
case CSS_HEIGHT_LENGTH: DUMP_LENGTH("height: ", &style->height.length, ";"); break;
|
||||
default: LOG(("height: UNKNOWN;")); break;
|
||||
}
|
||||
switch (style->line_height.size) {
|
||||
case CSS_LINE_HEIGHT_ABSOLUTE:
|
||||
LOG(("line-height: [%g];", style->line_height.value.absolute)); break;
|
||||
case CSS_LINE_HEIGHT_LENGTH:
|
||||
DUMP_LENGTH("line-height: ", &style->line_height.value.length, ";"); break;
|
||||
case CSS_LINE_HEIGHT_PERCENT:
|
||||
LOG(("line-height: %g%%;", style->line_height.value.percent)); break;
|
||||
case CSS_LINE_HEIGHT_INHERIT: LOG(("line-height: inherit;")); break;
|
||||
default: LOG(("line-height: UNKNOWN;")); break;
|
||||
}
|
||||
LOG(("text-align: %s;", css_text_align_name[style->text_align]));
|
||||
switch (style->width.width) {
|
||||
case CSS_WIDTH_AUTO: LOG(("width: auto;")); break;
|
||||
case CSS_WIDTH_LENGTH:
|
||||
DUMP_LENGTH("width: ", &style->width.value.length, ";"); break;
|
||||
case CSS_WIDTH_PERCENT: LOG(("width: %g%%;", style->width.value.percent)); break;
|
||||
default: LOG(("width: UNKNOWN;")); break;
|
||||
}
|
||||
LOG(("}"));
|
||||
}
|
||||
#if 0
|
||||
static void dump_selector(const struct css_selector * const sel)
|
||||
{
|
||||
if (sel->class != 0)
|
||||
LOG(("'%s'.'%s' ", sel->element, sel->class);
|
||||
else if (sel->id != 0)
|
||||
LOG(("'%s'#'%s' ", sel->element, sel->id);
|
||||
else
|
||||
LOG(("'%s' ", sel->element);
|
||||
}
|
||||
|
||||
static void dump_rule(const struct rule * rule)
|
||||
{
|
||||
unsigned int i;
|
||||
for (i = 0; i < rule->selectors; i++)
|
||||
dump_selector(&rule->selector[i]);
|
||||
css_dump_style(rule->style);
|
||||
}
|
||||
|
||||
void css_dump_stylesheet(const struct css_stylesheet * stylesheet)
|
||||
{
|
||||
unsigned int i;
|
||||
for (i = 0; i < HASH_SIZE; i++) {
|
||||
struct rule * rule;
|
||||
LOG(("hash %i:\n", i);
|
||||
for (rule = stylesheet->hash[i]; rule != 0; rule = rule->next)
|
||||
dump_rule(rule);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/**
|
||||
* cascade styles
|
||||
*/
|
||||
|
||||
void css_cascade(struct css_style * const style, const struct css_style * const apply)
|
||||
{
|
||||
float f;
|
||||
|
||||
if (apply->background_color != CSS_COLOR_INHERIT)
|
||||
style->background_color = apply->background_color;
|
||||
if (apply->clear != CSS_CLEAR_INHERIT)
|
||||
style->clear = apply->clear;
|
||||
if (apply->color != CSS_COLOR_INHERIT)
|
||||
style->color = apply->color;
|
||||
if (apply->display != CSS_DISPLAY_INHERIT)
|
||||
style->display = apply->display;
|
||||
if (apply->float_ != CSS_FLOAT_INHERIT)
|
||||
style->float_ = apply->float_;
|
||||
if (apply->height.height != CSS_HEIGHT_INHERIT)
|
||||
style->height = apply->height;
|
||||
if (apply->text_align != CSS_TEXT_ALIGN_INHERIT)
|
||||
style->text_align = apply->text_align;
|
||||
if (apply->width.width != CSS_WIDTH_INHERIT)
|
||||
style->width = apply->width;
|
||||
if (apply->font_weight != CSS_FONT_WEIGHT_INHERIT)
|
||||
style->font_weight = apply->font_weight;
|
||||
if (apply->font_style != CSS_FONT_STYLE_INHERIT)
|
||||
style->font_style = apply->font_style;
|
||||
|
||||
/* font-size */
|
||||
f = apply->font_size.value.percent / 100;
|
||||
switch (apply->font_size.size) {
|
||||
case CSS_FONT_SIZE_ABSOLUTE:
|
||||
style->font_size = apply->font_size;
|
||||
break;
|
||||
case CSS_FONT_SIZE_LENGTH:
|
||||
switch (apply->font_size.value.length.unit) {
|
||||
case CSS_UNIT_EM:
|
||||
f = apply->font_size.value.length.value;
|
||||
break;
|
||||
case CSS_UNIT_EX:
|
||||
f = apply->font_size.value.length.value * 0.6 /*?*/;
|
||||
break;
|
||||
default:
|
||||
style->font_size = apply->font_size;
|
||||
}
|
||||
if ((apply->font_size.value.length.unit != CSS_UNIT_EM) &&
|
||||
(apply->font_size.value.length.unit != CSS_UNIT_EX))
|
||||
break;
|
||||
/* drop through if EM or EX */
|
||||
case CSS_FONT_SIZE_PERCENT:
|
||||
switch (style->font_size.size) {
|
||||
case CSS_FONT_SIZE_ABSOLUTE:
|
||||
style->font_size.value.absolute *= f;
|
||||
break;
|
||||
case CSS_FONT_SIZE_LENGTH:
|
||||
style->font_size.value.length.value *= f;
|
||||
break;
|
||||
default:
|
||||
die("attempting percentage of unknown font-size");
|
||||
}
|
||||
break;
|
||||
case CSS_FONT_SIZE_INHERIT:
|
||||
default: /* leave unchanged */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
int main()
|
||||
{
|
||||
const char data[] = "h1 { blah: foo; display: block; }"
|
||||
"h1.c1 h2#id1 + h3, h4 h5.c2#id2 { size: 100mm; color: red }"
|
||||
"p { background-color: #123; clear: left; color: #ff0000; display: block;"
|
||||
"float: left; font-size: 150%; height: blah; line-height: 100;"
|
||||
"text-align: left right; width: 90%;}";
|
||||
struct content c;
|
||||
css_create(&c);
|
||||
css_process_data(&c, data, 24);
|
||||
css_process_data(&c, data + 24, sizeof(data) - 25);
|
||||
css_convert(&c, 100, 100);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
182
css/css.h
Normal file
182
css/css.h
Normal file
@ -0,0 +1,182 @@
|
||||
/**
|
||||
* $Id: css.h,v 1.1 2003/04/04 15:19:31 bursa Exp $
|
||||
*/
|
||||
|
||||
#ifndef _NETSURF_CSS_CSS_H_
|
||||
#define _NETSURF_CSS_CSS_H_
|
||||
|
||||
#include "css_enum.h"
|
||||
|
||||
/**
|
||||
* structures and typedefs
|
||||
*/
|
||||
|
||||
typedef unsigned long colour; /* 0xbbggrr */
|
||||
#define TRANSPARENT 0x1000000
|
||||
#define CSS_COLOR_INHERIT 0x2000000
|
||||
|
||||
struct css_length {
|
||||
float value;
|
||||
css_unit unit;
|
||||
};
|
||||
|
||||
struct css_style {
|
||||
colour background_color;
|
||||
css_clear clear;
|
||||
colour color;
|
||||
css_display display;
|
||||
css_float float_;
|
||||
|
||||
struct {
|
||||
enum { CSS_FONT_SIZE_INHERIT,
|
||||
CSS_FONT_SIZE_ABSOLUTE,
|
||||
CSS_FONT_SIZE_LENGTH,
|
||||
CSS_FONT_SIZE_PERCENT } size;
|
||||
union {
|
||||
struct css_length length;
|
||||
float absolute;
|
||||
float percent;
|
||||
} value;
|
||||
} font_size;
|
||||
|
||||
css_font_weight font_weight;
|
||||
css_font_style font_style;
|
||||
|
||||
struct {
|
||||
enum { CSS_HEIGHT_INHERIT,
|
||||
CSS_HEIGHT_AUTO,
|
||||
CSS_HEIGHT_LENGTH } height;
|
||||
struct css_length length;
|
||||
} height;
|
||||
|
||||
struct {
|
||||
enum { CSS_LINE_HEIGHT_INHERIT,
|
||||
CSS_LINE_HEIGHT_ABSOLUTE,
|
||||
CSS_LINE_HEIGHT_LENGTH,
|
||||
CSS_LINE_HEIGHT_PERCENT } size;
|
||||
union {
|
||||
float absolute;
|
||||
struct css_length length;
|
||||
float percent;
|
||||
} value;
|
||||
} line_height;
|
||||
|
||||
css_text_align text_align;
|
||||
|
||||
struct {
|
||||
enum { CSS_WIDTH_INHERIT,
|
||||
CSS_WIDTH_AUTO,
|
||||
CSS_WIDTH_LENGTH,
|
||||
CSS_WIDTH_PERCENT } width;
|
||||
union {
|
||||
struct css_length length;
|
||||
float percent;
|
||||
} value;
|
||||
} width;
|
||||
};
|
||||
|
||||
struct css_stylesheet;
|
||||
|
||||
struct css_selector {
|
||||
const char *element;
|
||||
char *class;
|
||||
char *id;
|
||||
};
|
||||
|
||||
|
||||
extern const struct css_style css_base_style;
|
||||
extern const struct css_style css_empty_style;
|
||||
extern const struct css_style css_blank_style;
|
||||
|
||||
|
||||
#ifdef CSS_INTERNALS
|
||||
|
||||
typedef enum {
|
||||
NODE_BLOCK,
|
||||
NODE_DECLARATION,
|
||||
NODE_IDENT,
|
||||
NODE_NUMBER,
|
||||
NODE_PERCENTAGE,
|
||||
NODE_DIMENSION,
|
||||
NODE_STRING,
|
||||
NODE_DELIM,
|
||||
NODE_URI,
|
||||
NODE_HASH,
|
||||
NODE_UNICODE_RANGE,
|
||||
NODE_INCLUDES,
|
||||
NODE_FUNCTION,
|
||||
NODE_DASHMATCH,
|
||||
NODE_COLON,
|
||||
NODE_COMMA,
|
||||
NODE_PLUS,
|
||||
NODE_GT,
|
||||
NODE_PAREN,
|
||||
NODE_BRAC,
|
||||
NODE_SELECTOR,
|
||||
NODE_ID,
|
||||
NODE_CLASS,
|
||||
} node_type;
|
||||
|
||||
typedef enum {
|
||||
COMB_NONE,
|
||||
COMB_ANCESTOR,
|
||||
COMB_PARENT,
|
||||
COMB_PRECEDED,
|
||||
} combinator;
|
||||
|
||||
struct node {
|
||||
node_type type;
|
||||
char *data;
|
||||
struct node *left;
|
||||
struct node *right;
|
||||
struct node *next;
|
||||
combinator comb;
|
||||
struct css_style *style;
|
||||
};
|
||||
|
||||
#include "netsurf/css/scanner.h"
|
||||
|
||||
struct css_stylesheet {
|
||||
yyscan_t lexer;
|
||||
void *parser;
|
||||
struct node *rule;
|
||||
struct node *last_rule;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* interface
|
||||
*/
|
||||
|
||||
#include "netsurf/content/content.h"
|
||||
|
||||
void css_create(struct content *c);
|
||||
void css_process_data(struct content *c, char *data, unsigned long size);
|
||||
int css_convert(struct content *c, unsigned int width, unsigned int height);
|
||||
void css_revive(struct content *c, unsigned int width, unsigned int height);
|
||||
void css_reformat(struct content *c, unsigned int width, unsigned int height);
|
||||
void css_destroy(struct content *c);
|
||||
|
||||
#ifdef CSS_INTERNALS
|
||||
|
||||
struct node * css_new_node(node_type type, char *data,
|
||||
struct node *left, struct node *right);
|
||||
void css_free_node(struct node *node);
|
||||
void css_add_ruleset(struct css_stylesheet *stylesheet,
|
||||
struct node *selector,
|
||||
struct node *declaration);
|
||||
|
||||
void css_parser_Trace(FILE *TraceFILE, char *zTracePrompt);
|
||||
void *css_parser_Alloc(void *(*mallocProc)(int));
|
||||
void css_parser_Free(void *p, void (*freeProc)(void*));
|
||||
void css_parser_(void *yyp, int yymajor, char* yyminor, struct css_stylesheet *stylesheet);
|
||||
|
||||
#endif
|
||||
|
||||
void css_get_style(struct css_stylesheet * stylesheet, struct css_selector * selector,
|
||||
unsigned int selectors, struct css_style * style);
|
||||
void css_cascade(struct css_style * const style, const struct css_style * const apply);
|
||||
void css_parse_property_list(struct css_style * style, char * str);
|
||||
|
||||
#endif
|
16
render/makeenum → css/makeenum
Normal file → Executable file
16
render/makeenum → css/makeenum
Normal file → Executable file
@ -1,5 +1,5 @@
|
||||
#!/usr/bin/perl -W
|
||||
# $Id: makeenum,v 1.2 2002/04/24 17:37:37 bursa Exp $
|
||||
# $Id: makeenum,v 1.1 2003/04/04 15:19:31 bursa Exp $
|
||||
|
||||
$out = shift or die "usage: makeenum leafname";
|
||||
|
||||
@ -18,21 +18,21 @@ while (<>) {
|
||||
$uc_name = uc $name;
|
||||
|
||||
print H "extern const char * const ${name}_name[];\n";
|
||||
print H "typedef enum {\n ${uc_name}_";
|
||||
print H join ",\n ${uc_name}_", @uc_enum;
|
||||
print H ",\n ${uc_name}_UNKNOWN\n";
|
||||
print H "typedef enum {\n ${uc_name}_";
|
||||
print H join ",\n ${uc_name}_", @uc_enum;
|
||||
print H ",\n ${uc_name}_UNKNOWN\n";
|
||||
print H "} $name;\n";
|
||||
print H "$name ${name}_parse(const char * const s);\n\n";
|
||||
|
||||
print C "/**\n * $name\n */\n\n";
|
||||
print C "const char * const ${name}_name[] = {\n \"";
|
||||
print C join "\",\n \"", @enum;
|
||||
print C "const char * const ${name}_name[] = {\n \"";
|
||||
print C join "\",\n \"", @enum;
|
||||
print C "\"\n};\n\n";
|
||||
print C "$name ${name}_parse(const char * const s)\n{\n";
|
||||
foreach $x (@enum) {
|
||||
$ux = uc $x;
|
||||
$ux =~ s/-/_/g;
|
||||
print C " if (strcmp(s, \"$x\") == 0) return ${uc_name}_$ux;\n";
|
||||
print C " if (strcasecmp(s, \"$x\") == 0) return ${uc_name}_$ux;\n";
|
||||
}
|
||||
print C " return ${uc_name}_UNKNOWN;\n}\n\n";
|
||||
print C " return ${uc_name}_UNKNOWN;\n}\n\n";
|
||||
}
|
21
css/parser.y
21
css/parser.y
@ -1,5 +1,5 @@
|
||||
/**
|
||||
* $Id: parser.y,v 1.3 2003/04/01 21:33:08 bursa Exp $
|
||||
* $Id: parser.y,v 1.4 2003/04/04 15:19:31 bursa Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -47,7 +47,7 @@ block_body ::= block_body SEMI.
|
||||
|
||||
ruleset ::= selector_list(A) LBRACE declaration_list(B) RBRACE.
|
||||
{ css_add_ruleset(stylesheet, A, B);
|
||||
css_free_node(A); css_free_node(B); }
|
||||
css_free_node(B); }
|
||||
ruleset ::= any_list_1(A) LBRACE declaration_list(B) RBRACE.
|
||||
{ css_free_node(A); css_free_node(B); } /* not CSS2 */
|
||||
ruleset ::= LBRACE declaration_list RBRACE.
|
||||
@ -61,14 +61,14 @@ selector_list(A) ::= selector_list(B) COMMA selector(C).
|
||||
selector(A) ::= simple_selector(B).
|
||||
{ A = B; }
|
||||
selector(A) ::= selector(B) combinator(C) simple_selector(D).
|
||||
{ B->right = D; A->data = C; A = B; }
|
||||
{ D->right = B; D->comb = C; A = D; }
|
||||
|
||||
combinator(A) ::= .
|
||||
{ A = 0; }
|
||||
combinator(A) ::= PLUS(B).
|
||||
{ A = B; }
|
||||
combinator(A) ::= GT(B).
|
||||
{ A = B; }
|
||||
{ A = COMB_ANCESTOR; }
|
||||
combinator(A) ::= PLUS.
|
||||
{ A = COMB_PRECEDED; }
|
||||
combinator(A) ::= GT.
|
||||
{ A = COMB_PARENT; }
|
||||
|
||||
simple_selector(A) ::= element_name(B) detail_list(C).
|
||||
{ A = css_new_node(NODE_SELECTOR, B, C, 0); }
|
||||
@ -159,6 +159,7 @@ any(A) ::= LBRAC any_list(B) RBRAC.
|
||||
%extra_argument { struct css_stylesheet *stylesheet }
|
||||
%include {
|
||||
#define CSS_INTERNALS
|
||||
#include "netsurf/css/scanner.h"
|
||||
#include "netsurf/css/css.h"
|
||||
#include "netsurf/utils/utils.h" }
|
||||
%name css_parser_
|
||||
@ -168,7 +169,7 @@ any(A) ::= LBRAC any_list(B) RBRAC.
|
||||
|
||||
%type selector_list { struct node * }
|
||||
%type selector { struct node * }
|
||||
%type combinator { struct node * }
|
||||
%type combinator { combinator }
|
||||
%type simple_selector { struct node * }
|
||||
%type detail_list { struct node * }
|
||||
%type declaration_list { struct node * }
|
||||
@ -178,7 +179,9 @@ any(A) ::= LBRAC any_list(B) RBRAC.
|
||||
%type any_list_1 { struct node * }
|
||||
%type any { struct node * }
|
||||
|
||||
%destructor selector_list { css_free_node($$); }
|
||||
%destructor selector { css_free_node($$); }
|
||||
%destructor simple_selector { css_free_node($$); }
|
||||
%destructor declaration_list { css_free_node($$); }
|
||||
%destructor declaration { css_free_node($$); }
|
||||
%destructor value { css_free_node($$); }
|
||||
|
336
css/ruleset.c
Normal file
336
css/ruleset.c
Normal file
@ -0,0 +1,336 @@
|
||||
/**
|
||||
* $Id: ruleset.c,v 1.1 2003/04/04 15:19:31 bursa Exp $
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#define CSS_INTERNALS
|
||||
#include "netsurf/css/css.h"
|
||||
#include "netsurf/utils/log.h"
|
||||
#include "netsurf/utils/utils.h"
|
||||
|
||||
|
||||
struct property_entry {
|
||||
const char name[20];
|
||||
void (*parse) (struct css_style * const s, const struct node * const v);
|
||||
};
|
||||
|
||||
struct colour_entry {
|
||||
const char name[12];
|
||||
colour col;
|
||||
};
|
||||
|
||||
struct font_size_entry {
|
||||
const char name[10];
|
||||
float size;
|
||||
};
|
||||
|
||||
|
||||
static int parse_length(struct css_length * const length, const struct node * const v);
|
||||
static colour parse_colour(const struct node * const v);
|
||||
static void parse_background_color(struct css_style * const s, const struct node * const v);
|
||||
static void parse_clear(struct css_style * const s, const struct node * const v);
|
||||
static void parse_color(struct css_style * const s, const struct node * const v);
|
||||
static void parse_display(struct css_style * const s, const struct node * const v);
|
||||
static void parse_float(struct css_style * const s, const struct node * const v);
|
||||
static void parse_font_size(struct css_style * const s, const struct node * const v);
|
||||
static void parse_font_style(struct css_style * const s, const struct node * const v);
|
||||
static void parse_font_weight(struct css_style * const s, const struct node * const v);
|
||||
static void parse_height(struct css_style * const s, const struct node * const v);
|
||||
static void parse_line_height(struct css_style * const s, const struct node * const v);
|
||||
static void parse_text_align(struct css_style * const s, const struct node * const v);
|
||||
static void parse_width(struct css_style * const s, const struct node * const v);
|
||||
|
||||
|
||||
/* table of property parsers: MUST be sorted by property name */
|
||||
static const struct property_entry property_table[] = {
|
||||
{ "background-color", parse_background_color },
|
||||
{ "clear", parse_clear },
|
||||
{ "color", parse_color },
|
||||
{ "display", parse_display },
|
||||
{ "float", parse_float },
|
||||
{ "font-size", parse_font_size },
|
||||
{ "font-style", parse_font_style },
|
||||
{ "font-weight", parse_font_weight },
|
||||
{ "height", parse_height },
|
||||
{ "line-height", parse_line_height },
|
||||
{ "text-align", parse_text_align },
|
||||
{ "width", parse_width },
|
||||
};
|
||||
|
||||
/* table of standard colour names: MUST be sorted by colour name */
|
||||
static const struct colour_entry colour_table[] = {
|
||||
{ "aqua", 0x00ffff },
|
||||
{ "black", 0x000000 },
|
||||
{ "blue", 0x0000ff },
|
||||
{ "fuchsia", 0xff00ff },
|
||||
{ "gray", 0x808080 },
|
||||
{ "green", 0x008000 },
|
||||
{ "lime", 0x00ff00 },
|
||||
{ "maroon", 0x800000 },
|
||||
{ "navy", 0x000080 },
|
||||
{ "olive", 0x808000 },
|
||||
{ "purple", 0x800080 },
|
||||
{ "red", 0xff0000 },
|
||||
{ "silver", 0xc0c0c0 },
|
||||
{ "teal", 0x008080 },
|
||||
{ "transparent", TRANSPARENT },
|
||||
{ "white", 0xffffff },
|
||||
{ "yellow", 0xffff00 },
|
||||
};
|
||||
|
||||
/* table of font sizes: MUST be sorted by name */
|
||||
#define SIZE_FACTOR 1.2
|
||||
static const struct font_size_entry font_size_table[] = {
|
||||
{ "large", 1.0 * SIZE_FACTOR },
|
||||
{ "medium", 1.0 },
|
||||
{ "small", 1.0 / SIZE_FACTOR },
|
||||
{ "x-large", 1.0 * SIZE_FACTOR * SIZE_FACTOR },
|
||||
{ "x-small", 1.0 / (SIZE_FACTOR * SIZE_FACTOR) },
|
||||
{ "xx-large", 1.0 * SIZE_FACTOR * SIZE_FACTOR * SIZE_FACTOR },
|
||||
{ "xx-small", 1.0 / (SIZE_FACTOR * SIZE_FACTOR * SIZE_FACTOR) },
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* css_add_ruleset -- add a ruleset to a stylesheet
|
||||
*/
|
||||
|
||||
void css_add_ruleset(struct css_stylesheet *stylesheet,
|
||||
struct node *selector,
|
||||
struct node *declaration)
|
||||
{
|
||||
struct node *n, *last;
|
||||
struct css_style *style;
|
||||
|
||||
/* construct the struct css_style */
|
||||
style = xcalloc(1, sizeof(*style));
|
||||
memcpy(style, &css_blank_style, sizeof(*style));
|
||||
|
||||
for (n = declaration; n != 0; n = n->next) {
|
||||
struct property_entry *p;
|
||||
assert(n->type == NODE_DECLARATION && n->data != 0 && n->left != 0);
|
||||
p = bsearch(n->data, property_table,
|
||||
sizeof(property_table) / sizeof(property_table[0]),
|
||||
sizeof(property_table[0]), strcasecmp);
|
||||
if (p == 0)
|
||||
continue;
|
||||
p->parse(style, n->left);
|
||||
}
|
||||
|
||||
/*css_dump_style(style);*/
|
||||
|
||||
/* add selectors to the stylesheet */
|
||||
/* TODO: merge with identical selector */
|
||||
for (n = selector; n != 0; n = n->next) {
|
||||
n->style = style;
|
||||
last = n;
|
||||
}
|
||||
|
||||
if (stylesheet->rule == 0)
|
||||
stylesheet->rule = selector;
|
||||
else
|
||||
stylesheet->last_rule->next = selector;
|
||||
stylesheet->last_rule = last;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* property parsers
|
||||
*/
|
||||
|
||||
int parse_length(struct css_length * const length, const struct node * const v)
|
||||
{
|
||||
css_unit u;
|
||||
if (v->type != NODE_DIMENSION)
|
||||
return 1;
|
||||
u = css_unit_parse(v->data + strspn(v->data, "0123456789+-."));
|
||||
if (u == CSS_UNIT_UNKNOWN)
|
||||
return 1;
|
||||
length->unit = u;
|
||||
length->value = atof(v->data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
colour parse_colour(const struct node * const v)
|
||||
{
|
||||
colour c = TRANSPARENT;
|
||||
int len;
|
||||
unsigned int r, g, b;
|
||||
struct colour_entry *col;
|
||||
|
||||
switch (v->type) {
|
||||
case NODE_HASH:
|
||||
len = strlen(v->data);
|
||||
if (len == 4) {
|
||||
if (sscanf(v->data + 1, "%1x%1x%1x", &r, &g, &b) == 3)
|
||||
c = (b << 20) | (b << 16) | (g << 12) | (g << 8) | (r << 4) | r;
|
||||
} else if (len == 7) {
|
||||
if (sscanf(v->data + 1, "%2x%2x%2x", &r, &g, &b) == 3)
|
||||
c = (b << 16) | (g << 8) | r;
|
||||
}
|
||||
break;
|
||||
|
||||
case NODE_FUNCTION:
|
||||
/* TODO: rgb(r, g, b) */
|
||||
break;
|
||||
|
||||
case NODE_IDENT:
|
||||
col = bsearch(v->data, colour_table,
|
||||
sizeof(colour_table) / sizeof(colour_table[0]),
|
||||
sizeof(colour_table[0]), strcasecmp);
|
||||
if (col != 0)
|
||||
c = col->col;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
void parse_background_color(struct css_style * const s, const struct node * const v)
|
||||
{
|
||||
s->background_color = parse_colour(v);
|
||||
}
|
||||
|
||||
void parse_clear(struct css_style * const s, const struct node * const v)
|
||||
{
|
||||
css_clear z;
|
||||
if (v->type != NODE_IDENT || v->next != 0)
|
||||
return;
|
||||
z = css_clear_parse(v->data);
|
||||
if (z != CSS_CLEAR_UNKNOWN)
|
||||
s->clear = z;
|
||||
}
|
||||
|
||||
void parse_color(struct css_style * const s, const struct node * const v)
|
||||
{
|
||||
s->color = parse_colour(v);
|
||||
}
|
||||
|
||||
void parse_display(struct css_style * const s, const struct node * const v)
|
||||
{
|
||||
css_display z;
|
||||
if (v->type != NODE_IDENT || v->next != 0)
|
||||
return;
|
||||
z = css_display_parse(v->data);
|
||||
if (z != CSS_DISPLAY_UNKNOWN)
|
||||
s->display = z;
|
||||
}
|
||||
|
||||
void parse_float(struct css_style * const s, const struct node * const v)
|
||||
{
|
||||
css_float z;
|
||||
if (v->type != NODE_IDENT || v->next != 0)
|
||||
return;
|
||||
z = css_float_parse(v->data);
|
||||
if (z != CSS_FLOAT_UNKNOWN)
|
||||
s->float_ = z;
|
||||
}
|
||||
|
||||
void parse_font_size(struct css_style * const s, const struct node * const v)
|
||||
{
|
||||
struct font_size_entry *fs;
|
||||
switch (v->type) {
|
||||
case NODE_IDENT:
|
||||
fs = bsearch(v->data, font_size_table,
|
||||
sizeof(font_size_table) / sizeof(font_size_table[0]),
|
||||
sizeof(font_size_table[0]), strcasecmp);
|
||||
if (fs != 0) {
|
||||
s->font_size.size = CSS_FONT_SIZE_LENGTH;
|
||||
s->font_size.value.length.unit = CSS_UNIT_PT;
|
||||
s->font_size.value.length.value = fs->size * 12;
|
||||
} else if (strcasecmp(v->data, "larger") == 0) {
|
||||
s->font_size.size = CSS_FONT_SIZE_PERCENT;
|
||||
s->font_size.value.percent = SIZE_FACTOR * 100;
|
||||
} else if (strcmp(v->data, "smaller") == 0) {
|
||||
s->font_size.size = CSS_FONT_SIZE_PERCENT;
|
||||
s->font_size.value.percent = 1 / SIZE_FACTOR * 100;
|
||||
}
|
||||
break;
|
||||
|
||||
case NODE_PERCENTAGE:
|
||||
s->font_size.size = CSS_FONT_SIZE_PERCENT;
|
||||
s->font_size.value.percent = atof(v->data);
|
||||
break;
|
||||
|
||||
case NODE_DIMENSION:
|
||||
if (parse_length(&s->font_size.value.length, v) == 0)
|
||||
s->font_size.size = CSS_FONT_SIZE_LENGTH;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void parse_font_style(struct css_style * const s, const struct node * const v)
|
||||
{
|
||||
css_font_style z;
|
||||
if (v->type != NODE_IDENT || v->next != 0)
|
||||
return;
|
||||
z = css_font_style_parse(v->data);
|
||||
if (z != CSS_FONT_STYLE_UNKNOWN)
|
||||
s->font_style = z;
|
||||
}
|
||||
|
||||
void parse_font_weight(struct css_style * const s, const struct node * const v)
|
||||
{
|
||||
css_font_weight z;
|
||||
if (v->type != NODE_IDENT || v->next != 0)
|
||||
return;
|
||||
z = css_font_weight_parse(v->data);
|
||||
if (z != CSS_FONT_WEIGHT_UNKNOWN)
|
||||
s->font_weight = z;
|
||||
}
|
||||
void parse_height(struct css_style * const s, const struct node * const v)
|
||||
{
|
||||
if (v->type == NODE_IDENT && strcasecmp(v->data, "auto") == 0)
|
||||
s->height.height = CSS_HEIGHT_AUTO;
|
||||
else if (v->type == NODE_DIMENSION && parse_length(&s->height.length, v) == 0)
|
||||
s->height.height = CSS_HEIGHT_LENGTH;
|
||||
}
|
||||
|
||||
void parse_line_height(struct css_style * const s, const struct node * const v)
|
||||
{
|
||||
if (v->type == NODE_IDENT && strcasecmp(v->data, "normal") == 0) {
|
||||
s->line_height.size = CSS_LINE_HEIGHT_ABSOLUTE;
|
||||
s->line_height.value.absolute = 1.0;
|
||||
} else if (v->type == NODE_PERCENTAGE) {
|
||||
s->line_height.size = CSS_LINE_HEIGHT_PERCENT;
|
||||
s->line_height.value.percent = atof(v->data);
|
||||
} else if (v->type == NODE_DIMENSION &&
|
||||
parse_length(&s->line_height.value.length, v) == 0) {
|
||||
s->line_height.size = CSS_LINE_HEIGHT_LENGTH;
|
||||
}
|
||||
}
|
||||
|
||||
void parse_text_align(struct css_style * const s, const struct node * const v)
|
||||
{
|
||||
css_text_align z;
|
||||
if (v->type != NODE_IDENT || v->next != 0)
|
||||
return;
|
||||
z = css_text_align_parse(v->data);
|
||||
if (z != CSS_TEXT_ALIGN_UNKNOWN)
|
||||
s->text_align = z;
|
||||
}
|
||||
|
||||
void parse_width(struct css_style * const s, const struct node * const v)
|
||||
{
|
||||
if (v->type == NODE_IDENT && strcasecmp(v->data, "auto") == 0)
|
||||
s->width.width = CSS_WIDTH_AUTO;
|
||||
else if (v->type == NODE_PERCENTAGE) {
|
||||
s->width.width = CSS_WIDTH_PERCENT;
|
||||
s->width.value.percent = atof(v->data);
|
||||
} else if (v->type == NODE_DIMENSION &&
|
||||
parse_length(&s->width.value.length, v) == 0)
|
||||
s->width.width = CSS_WIDTH_LENGTH;
|
||||
}
|
38
makefile
38
makefile
@ -1,13 +1,13 @@
|
||||
# $Id: makefile,v 1.15 2003/03/15 15:53:20 bursa Exp $
|
||||
# $Id: makefile,v 1.16 2003/04/04 15:19:31 bursa Exp $
|
||||
|
||||
all: !NetSurf/!RunImage,ff8
|
||||
clean:
|
||||
rm */arm-riscos-aof/*
|
||||
-rm */arm-riscos-aof/* css/parser.c css/parser.h css/scanner.c css/scanner.h
|
||||
|
||||
setup: render/arm-riscos-aof riscos/arm-riscos-aof desktop/arm-riscos-aof \
|
||||
content/arm-riscos-aof utils/arm-riscos-aof
|
||||
content/arm-riscos-aof utils/arm-riscos-aof css/arm-riscos-aof
|
||||
%/arm-riscos-aof:
|
||||
mkdir $@
|
||||
-mkdir $@
|
||||
|
||||
FLAGS = -Wall -W -Wundef -Wpointer-arith -Wbad-function-cast -Wcast-qual \
|
||||
-Wcast-align -Wwrite-strings -Wconversion -Wstrict-prototypes -Wmissing-prototypes \
|
||||
@ -19,31 +19,31 @@ OBJECTS = \
|
||||
content/arm-riscos-aof/cache.o content/arm-riscos-aof/content.o \
|
||||
content/arm-riscos-aof/fetch.o content/arm-riscos-aof/fetchcache.o \
|
||||
desktop/arm-riscos-aof/browser.o desktop/arm-riscos-aof/netsurf.o \
|
||||
render/arm-riscos-aof/box.o render/arm-riscos-aof/css.o \
|
||||
render/arm-riscos-aof/css_enum.o render/arm-riscos-aof/html.o \
|
||||
render/arm-riscos-aof/box.o \
|
||||
render/arm-riscos-aof/html.o \
|
||||
render/arm-riscos-aof/layout.o render/arm-riscos-aof/textplain.o \
|
||||
riscos/arm-riscos-aof/font.o riscos/arm-riscos-aof/gui.o \
|
||||
riscos/arm-riscos-aof/theme.o riscos/arm-riscos-aof/jpeg.o \
|
||||
riscos/arm-riscos-aof/filetype.o utils/arm-riscos-aof/utils.o
|
||||
riscos/arm-riscos-aof/filetype.o utils/arm-riscos-aof/utils.o \
|
||||
css/arm-riscos-aof/css.o css/arm-riscos-aof/css_enum.o \
|
||||
css/arm-riscos-aof/parser.o css/arm-riscos-aof/scanner.o \
|
||||
css/arm-riscos-aof/ruleset.o
|
||||
HEADERS = \
|
||||
content/cache.h content/content.h content/fetch.h content/fetchcache.h \
|
||||
desktop/browser.h desktop/gui.h desktop/netsurf.h render/box.h \
|
||||
render/css.h render/css_enum.h render/html.h render/layout.h \
|
||||
render/html.h render/layout.h \
|
||||
riscos/font.h riscos/gui.h riscos/theme.h utils/log.h \
|
||||
utils/utils.h render/textplain.h
|
||||
utils/utils.h render/textplain.h \
|
||||
css/css.h css/css_enum.h css/parser.h css/scanner.h
|
||||
LIBS = \
|
||||
/usr/local/riscoslibs/libxml2/libxml2.ro \
|
||||
/usr/local/riscoslibs/OSLib/OSLib.ro \
|
||||
/usr/local/riscoslibs/curl/libcurl.ro \
|
||||
/usr/local/riscoslibs/libutf-8/libutf-8.ro
|
||||
# /usr/local/riscoslibs/ubiqx/ubiqx.ro
|
||||
|
||||
!NetSurf/!RunImage,ff8: $(OBJECTS)
|
||||
$(CC) $(FLAGS) -o !NetSurf/!RunImage,ff8 $(OBJECTS) $(LIBS)
|
||||
|
||||
render/css_enum.c render/css_enum.h: render/css_enums render/makeenum
|
||||
cd ..; /usr/bin/perl netsurf/render/makeenum netsurf/render/css_enum < netsurf/render/css_enums
|
||||
|
||||
render/arm-riscos-aof/%.o: render/%.c $(HEADERS)
|
||||
$(CC) $(FLAGS) -o $@ -c $<
|
||||
|
||||
@ -59,6 +59,18 @@ content/arm-riscos-aof/%.o: content/%.c $(HEADERS)
|
||||
utils/arm-riscos-aof/%.o: utils/%.c $(HEADERS)
|
||||
$(CC) $(FLAGS) -o $@ -c $<
|
||||
|
||||
css/css_enum.c css/css_enum.h: css/css_enums css/makeenum
|
||||
cd ..; /usr/bin/perl netsurf/css/makeenum netsurf/css/css_enum < netsurf/css/css_enums
|
||||
|
||||
css/parser.c css/parser.h: css/parser.y
|
||||
-cd css; lemon parser.y
|
||||
|
||||
css/scanner.c css/scanner.h: css/scanner.l
|
||||
cd css; flex scanner.l
|
||||
|
||||
css/arm-riscos-aof/%.o: css/%.c $(HEADERS)
|
||||
$(CC) $(FLAGS) -o $@ -c $<
|
||||
|
||||
netsurf.zip: !NetSurf/!RunImage,ff8
|
||||
rm netsurf.zip; riscos-zip -9vr, netsurf.zip !NetSurf
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/**
|
||||
* $Id: box.c,v 1.35 2003/03/25 21:51:29 bursa Exp $
|
||||
* $Id: box.c,v 1.36 2003/04/04 15:19:31 bursa Exp $
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
@ -9,7 +9,7 @@
|
||||
#include <string.h>
|
||||
#include "libxml/HTMLparser.h"
|
||||
#include "libutf-8/utf-8.h"
|
||||
#include "netsurf/render/css.h"
|
||||
#include "netsurf/css/css.h"
|
||||
#include "netsurf/riscos/font.h"
|
||||
#include "netsurf/render/box.h"
|
||||
#include "netsurf/utils/utils.h"
|
||||
|
@ -1,5 +1,5 @@
|
||||
/**
|
||||
* $Id: box.h,v 1.20 2003/03/04 11:59:35 bursa Exp $
|
||||
* $Id: box.h,v 1.21 2003/04/04 15:19:31 bursa Exp $
|
||||
*/
|
||||
|
||||
#ifndef _NETSURF_RENDER_BOX_H_
|
||||
@ -7,7 +7,7 @@
|
||||
|
||||
#include <limits.h>
|
||||
#include "libxml/HTMLparser.h"
|
||||
#include "netsurf/render/css.h"
|
||||
#include "netsurf/css/css.h"
|
||||
#include "netsurf/riscos/font.h"
|
||||
|
||||
/**
|
||||
|
743
render/css.c
743
render/css.c
@ -1,743 +0,0 @@
|
||||
/**
|
||||
* $Id: css.c,v 1.13 2003/02/09 12:58:15 bursa Exp $
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "netsurf/render/css.h"
|
||||
#include "netsurf/utils/utils.h"
|
||||
|
||||
/**
|
||||
* internal structures
|
||||
*/
|
||||
|
||||
struct rule {
|
||||
struct css_selector * selector;
|
||||
unsigned int selectors;
|
||||
struct css_style * style;
|
||||
struct rule * next;
|
||||
};
|
||||
|
||||
struct decl {
|
||||
unsigned long score;
|
||||
struct rule * rule;
|
||||
};
|
||||
|
||||
#define HASH_SIZE 1
|
||||
|
||||
struct css_stylesheet {
|
||||
struct rule * hash[HASH_SIZE];
|
||||
};
|
||||
|
||||
static int parse_length(struct css_length * const length, const char *s);
|
||||
static colour parse_colour(const char *s);
|
||||
static void parse_background_color(struct css_style * const style, const char * const value);
|
||||
static void parse_clear(struct css_style * const style, const char * const value);
|
||||
static void parse_color(struct css_style * const style, const char * const value);
|
||||
static void parse_display(struct css_style * const style, const char * const value);
|
||||
static void parse_float(struct css_style * const style, const char * const value);
|
||||
static void parse_font_size(struct css_style * const style, const char * const value);
|
||||
static void parse_height(struct css_style * const style, const char * const value);
|
||||
static void parse_text_align(struct css_style * const style, const char * const value);
|
||||
static void parse_width(struct css_style * const style, const char * const value);
|
||||
static void parse_selector(struct css_selector * sel, char * const str);
|
||||
static unsigned int hash_str(const char * str);
|
||||
static int seleq(const struct css_selector * const s1, const struct css_selector * const s2);
|
||||
static unsigned long selmatch(const struct css_selector * const s, const struct css_selector * const sr);
|
||||
static struct rule * find_rule(struct css_stylesheet * stylesheet,
|
||||
struct css_selector * selector, unsigned int selectors);
|
||||
static int cmpdecl(const struct decl * d0, const struct decl * d1);
|
||||
static void update_style(struct css_stylesheet * stylesheet, struct css_selector * selector,
|
||||
unsigned int selectors, char * str);
|
||||
static void dump_length(const struct css_length * const length);
|
||||
static void dump_selector(const struct css_selector * const sel);
|
||||
static void dump_rule(const struct rule * rule);
|
||||
|
||||
const struct css_style css_base_style = {
|
||||
0xffffff,
|
||||
CSS_CLEAR_NONE,
|
||||
0x000000,
|
||||
CSS_DISPLAY_BLOCK,
|
||||
CSS_FLOAT_NONE,
|
||||
{ CSS_FONT_SIZE_LENGTH, { { 12, CSS_UNIT_PT } } },
|
||||
CSS_FONT_WEIGHT_NORMAL,
|
||||
CSS_FONT_STYLE_NORMAL,
|
||||
{ CSS_HEIGHT_AUTO, { 1, CSS_UNIT_EM } },
|
||||
{ CSS_LINE_HEIGHT_ABSOLUTE, { 1.2 } },
|
||||
CSS_TEXT_ALIGN_LEFT,
|
||||
{ CSS_WIDTH_AUTO, { { 1, CSS_UNIT_EM } } }
|
||||
};
|
||||
|
||||
const struct css_style css_empty_style = {
|
||||
CSS_COLOR_INHERIT,
|
||||
CSS_CLEAR_INHERIT,
|
||||
CSS_COLOR_INHERIT,
|
||||
CSS_DISPLAY_INHERIT,
|
||||
CSS_FLOAT_INHERIT,
|
||||
{ CSS_FONT_SIZE_INHERIT, { { 1, CSS_UNIT_EM } } },
|
||||
CSS_FONT_WEIGHT_INHERIT,
|
||||
CSS_FONT_STYLE_INHERIT,
|
||||
{ CSS_HEIGHT_AUTO, { 1, CSS_UNIT_EM } },
|
||||
{ CSS_LINE_HEIGHT_INHERIT, { 1.2 } },
|
||||
CSS_TEXT_ALIGN_INHERIT,
|
||||
{ CSS_WIDTH_INHERIT, { { 1, CSS_UNIT_EM } } }
|
||||
};
|
||||
|
||||
const struct css_style css_blank_style = {
|
||||
TRANSPARENT,
|
||||
CSS_CLEAR_NONE,
|
||||
CSS_COLOR_INHERIT,
|
||||
CSS_DISPLAY_INLINE,
|
||||
CSS_FLOAT_NONE,
|
||||
{ CSS_FONT_SIZE_INHERIT, { { 1, CSS_UNIT_EM } } },
|
||||
CSS_FONT_WEIGHT_INHERIT,
|
||||
CSS_FONT_STYLE_INHERIT,
|
||||
{ CSS_HEIGHT_AUTO, { 1, CSS_UNIT_EM } },
|
||||
{ CSS_LINE_HEIGHT_INHERIT, { 1.2 } },
|
||||
CSS_TEXT_ALIGN_INHERIT,
|
||||
{ CSS_WIDTH_AUTO, { { 1, CSS_UNIT_EM } } }
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* property parsers
|
||||
*/
|
||||
|
||||
static int parse_length(struct css_length * const length, const char *s)
|
||||
{
|
||||
length->unit = css_unit_parse(s + strspn(s, "0123456789+-."));
|
||||
if (length->unit == CSS_UNIT_UNKNOWN) return 1;
|
||||
length->value = atof(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static colour parse_colour(const char *s)
|
||||
{
|
||||
int len = strlen(s);
|
||||
colour c = TRANSPARENT;
|
||||
unsigned int r, g, b;
|
||||
|
||||
if (s[0] == '#' && len == 4) {
|
||||
if (sscanf(s + 1, "%1x%1x%1x", &r, &g, &b) == 3)
|
||||
c = (b << 20) | (b << 16) | (g << 12) | (g << 8) | (r << 4) | r;
|
||||
|
||||
} else if (s[0] == '#' && len == 7) {
|
||||
if (sscanf(s + 1, "%2x%2x%2x", &r, &g, &b) == 3)
|
||||
c = (b << 16) | (g << 8) | r;
|
||||
|
||||
} else if (sscanf(s, "rgb(%u, %u, %u)", &r, &g, &b) == 3) {
|
||||
c = (b << 16) | (g << 8) | r;
|
||||
|
||||
} else if (sscanf(s, "rgb(%u%%, %u%%, %u%%)", &r, &g, &b) == 3) {
|
||||
c = ((int) (b * 2.55) << 16) | ((int) (g * 2.55) << 8) | (int) (r * 2.55);
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static void parse_background_color(struct css_style * const style, const char * const value)
|
||||
{
|
||||
if (strcmp(value, "transparent") == 0) {
|
||||
style->background_color = TRANSPARENT;
|
||||
} else {
|
||||
style->background_color = parse_colour(value);
|
||||
}
|
||||
}
|
||||
|
||||
static void parse_clear(struct css_style * const style, const char * const value)
|
||||
{
|
||||
style->clear = css_clear_parse(value);
|
||||
}
|
||||
|
||||
static void parse_color(struct css_style * const style, const char * const value)
|
||||
{
|
||||
style->color = parse_colour(value);
|
||||
}
|
||||
|
||||
static void parse_display(struct css_style * const style, const char * const value)
|
||||
{
|
||||
style->display = css_display_parse(value);
|
||||
}
|
||||
|
||||
static void parse_float(struct css_style * const style, const char * const value)
|
||||
{
|
||||
style->float_ = css_float_parse(value);
|
||||
}
|
||||
|
||||
static void parse_font_weight(struct css_style * const style, const char * const value)
|
||||
{
|
||||
style->font_weight = css_font_weight_parse(value);
|
||||
}
|
||||
|
||||
static void parse_font_style(struct css_style * const style, const char * const value)
|
||||
{
|
||||
style->font_style = css_font_style_parse(value);
|
||||
}
|
||||
|
||||
#define SIZE_FACTOR 1.2
|
||||
|
||||
static struct font_size {
|
||||
const char * keyword;
|
||||
float size;
|
||||
} const font_size[] = {
|
||||
{ "xx-small", 1.0 / (SIZE_FACTOR * SIZE_FACTOR * SIZE_FACTOR) },
|
||||
{ "x-small", 1.0 / (SIZE_FACTOR * SIZE_FACTOR) },
|
||||
{ "small", 1.0 / SIZE_FACTOR },
|
||||
{ "medium", 1.0 },
|
||||
{ "large", 1.0 * SIZE_FACTOR },
|
||||
{ "x-large", 1.0 * SIZE_FACTOR * SIZE_FACTOR },
|
||||
{ "xx-large", 1.0 * SIZE_FACTOR * SIZE_FACTOR * SIZE_FACTOR }
|
||||
};
|
||||
|
||||
static void parse_font_size(struct css_style * const style, const char * const value)
|
||||
{
|
||||
unsigned int i;
|
||||
for (i = 0; i < sizeof(font_size) / sizeof(struct font_size); i++) {
|
||||
if (strcmp(value, font_size[i].keyword) == 0) {
|
||||
style->font_size.size = CSS_FONT_SIZE_LENGTH;
|
||||
style->font_size.value.length.unit = CSS_UNIT_PT;
|
||||
style->font_size.value.length.value = font_size[i].size * 12;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (strcmp(value, "larger") == 0) {
|
||||
style->font_size.size = CSS_FONT_SIZE_PERCENT;
|
||||
style->font_size.value.percent = SIZE_FACTOR * 100;
|
||||
} else if (strcmp(value, "smaller") == 0) {
|
||||
style->font_size.size = CSS_FONT_SIZE_PERCENT;
|
||||
style->font_size.value.percent = 1 / SIZE_FACTOR * 100;
|
||||
} else if (strrchr(value, '%')) {
|
||||
style->font_size.size = CSS_FONT_SIZE_PERCENT;
|
||||
style->font_size.value.percent = atof(value);
|
||||
} else if (parse_length(&style->font_size.value.length, value) == 0) {
|
||||
style->font_size.size = CSS_FONT_SIZE_LENGTH;
|
||||
}
|
||||
}
|
||||
|
||||
static void parse_height(struct css_style * const style, const char * const value)
|
||||
{
|
||||
if (strcmp(value, "auto") == 0)
|
||||
style->height.height = CSS_HEIGHT_AUTO;
|
||||
else if (parse_length(&style->height.length, value) == 0)
|
||||
style->height.height = CSS_HEIGHT_LENGTH;
|
||||
}
|
||||
|
||||
static void parse_line_height(struct css_style * const style, const char * const value)
|
||||
{
|
||||
if (strcmp(value, "normal") == 0) {
|
||||
style->line_height.size = CSS_LINE_HEIGHT_ABSOLUTE;
|
||||
style->line_height.value.absolute = 1.0;
|
||||
} else if (strrchr(value, '%')) {
|
||||
style->line_height.size = CSS_LINE_HEIGHT_PERCENT;
|
||||
style->line_height.value.percent = atof(value);
|
||||
} else if (parse_length(&style->line_height.value.length, value) == 0) {
|
||||
style->line_height.size = CSS_LINE_HEIGHT_LENGTH;
|
||||
}
|
||||
}
|
||||
|
||||
static void parse_text_align(struct css_style * const style, const char * const value)
|
||||
{
|
||||
style->text_align = css_text_align_parse(value);
|
||||
}
|
||||
|
||||
static void parse_width(struct css_style * const style, const char * const value)
|
||||
{
|
||||
if (strcmp(value, "auto") == 0)
|
||||
style->width.width = CSS_WIDTH_AUTO;
|
||||
else if (strrchr(value, '%')) {
|
||||
style->width.width = CSS_WIDTH_PERCENT;
|
||||
style->width.value.percent = atof(value);
|
||||
} else if (parse_length(&style->width.value.length, value) == 0)
|
||||
style->width.width = CSS_WIDTH_LENGTH;
|
||||
}
|
||||
|
||||
static struct property {
|
||||
const char * const name;
|
||||
void (*parse) (struct css_style * const s, const char * const value);
|
||||
} const property[] = {
|
||||
{ "background-color", parse_background_color },
|
||||
{ "clear", parse_clear },
|
||||
{ "color", parse_color },
|
||||
{ "display", parse_display },
|
||||
{ "float", parse_float },
|
||||
{ "font-weight", parse_font_weight },
|
||||
{ "font-size", parse_font_size },
|
||||
{ "font-style", parse_font_style },
|
||||
{ "height", parse_height },
|
||||
{ "line-height", parse_line_height },
|
||||
{ "text-align", parse_text_align },
|
||||
{ "width", parse_width },
|
||||
};
|
||||
|
||||
/**
|
||||
* parse a property list
|
||||
*/
|
||||
|
||||
void css_parse_property_list(struct css_style * style, char * str)
|
||||
{
|
||||
char * end;
|
||||
for (; str != 0; str = end) {
|
||||
char * prop;
|
||||
char * value;
|
||||
unsigned int i;
|
||||
|
||||
if ((end = strchr(str, ';')) != 0) {
|
||||
*end = 0;
|
||||
end++;
|
||||
}
|
||||
if ((value = strchr(str, ':')) == 0)
|
||||
continue;
|
||||
*value = 0;
|
||||
value++;
|
||||
prop = strip(str);
|
||||
value = strip(value);
|
||||
/*fprintf(stderr, "css_parse: '%s' => '%s'\n", prop, value);*/
|
||||
|
||||
for (i = 0; i < sizeof(property) / sizeof(struct property); i++) {
|
||||
if (strcmp(prop, property[i].name) == 0) {
|
||||
property[i].parse(style, value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* selectors
|
||||
*/
|
||||
|
||||
static void parse_selector(struct css_selector * sel, char * const str)
|
||||
{
|
||||
char * dot = strchr(str, '.');
|
||||
char * hash = strchr(str, '#');
|
||||
|
||||
if ((dot == 0) && (hash == 0)) {
|
||||
sel->element = xstrdup(str);
|
||||
sel->class = sel->id = 0;
|
||||
} else if (dot != 0) {
|
||||
*dot = 0;
|
||||
sel->element = xstrdup(str);
|
||||
sel->class = xstrdup(dot + 1);
|
||||
sel->id = 0;
|
||||
} else if (hash != 0) {
|
||||
*hash = 0;
|
||||
sel->element = xstrdup(str);
|
||||
sel->class = 0;
|
||||
sel->id = xstrdup(hash + 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* stylesheet structure
|
||||
*/
|
||||
|
||||
static unsigned int hash_str(const char * str)
|
||||
{
|
||||
unsigned int s = 0;
|
||||
for (; *str != 0; str++)
|
||||
s += *str;
|
||||
return s % HASH_SIZE;
|
||||
}
|
||||
|
||||
static int seleq(const struct css_selector * const s1, const struct css_selector * const s2)
|
||||
{
|
||||
return strcmp(s1->element, s2->element) == 0 &&
|
||||
((s1->class == 0 && s2->class == 0) ||
|
||||
(s1->class != 0 && s2->class != 0 && strcmp(s1->class, s2->class) == 0)) &&
|
||||
((s1->id == 0 && s2->id == 0) ||
|
||||
(s1->id != 0 && s2->id != 0 && strcmp(s1->id, s2->id) == 0));
|
||||
}
|
||||
|
||||
static unsigned long selmatch(const struct css_selector * const s, const struct css_selector * const sr)
|
||||
{
|
||||
unsigned int c;
|
||||
if (sr->element[0] != 0 && strcmp(s->element, sr->element) != 0) return 0;
|
||||
c = s->element[0] == 0 ? 0 : 1;
|
||||
if (sr->class != 0) {
|
||||
if (s->class != 0 && strcmp(s->class, sr->class) == 0) return 0x100 + c;
|
||||
return 0;
|
||||
}
|
||||
if (sr->id != 0) {
|
||||
if (s->id != 0 && strcmp(s->id, sr->id) == 0) return 0x10000 + c;
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct css_stylesheet * css_new_stylesheet(void)
|
||||
{
|
||||
struct css_stylesheet * stylesheet = xcalloc(1, sizeof(struct css_stylesheet));
|
||||
return stylesheet;
|
||||
}
|
||||
|
||||
static struct rule * find_rule(struct css_stylesheet * stylesheet,
|
||||
struct css_selector * selector, unsigned int selectors)
|
||||
{
|
||||
struct rule * rule;
|
||||
for (rule = stylesheet->hash[hash_str(selector[selectors - 1].element)];
|
||||
rule != 0; rule = rule->next) {
|
||||
unsigned int i;
|
||||
if (selectors != rule->selectors)
|
||||
continue;
|
||||
/* inv: selector[0..i) == rule->selector[0..i) */
|
||||
for (i = 0; i != selectors && seleq(&selector[i], &rule->selector[i]); i++)
|
||||
;
|
||||
if (i == selectors)
|
||||
return rule;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmpdecl(const struct decl * d0, const struct decl * d1)
|
||||
{
|
||||
if (d0->score < d1->score) return -1;
|
||||
else if (d0->score == d1->score) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void css_get_style(struct css_stylesheet * stylesheet, struct css_selector * selector,
|
||||
unsigned int selectors, struct css_style * style)
|
||||
{
|
||||
struct rule * rule;
|
||||
struct decl * decl = xcalloc(0, sizeof(struct decl));
|
||||
unsigned int d, decls = 0;
|
||||
|
||||
/* fprintf(stderr, "css_get_style: "); */
|
||||
/* for (d = 0; d < selectors; d++) dump_selector(&selector[d]); */
|
||||
/* fprintf(stderr, "\n"); */
|
||||
|
||||
for (rule = stylesheet->hash[hash_str(selector[selectors - 1].element)];
|
||||
rule != 0; rule = rule->next) {
|
||||
unsigned int i = selectors - 1;
|
||||
unsigned int j;
|
||||
unsigned int score, s;
|
||||
|
||||
/* for (d = 0; d < rule->selectors; d++) dump_selector(&rule->selector[d]); */
|
||||
|
||||
if ((score = selmatch(&selector[i], &rule->selector[rule->selectors - 1])) == 0) {
|
||||
/* fprintf(stderr, " last selector match fails\n"); */
|
||||
continue;
|
||||
}
|
||||
if (selectors < rule->selectors) {
|
||||
/* fprintf(stderr, " less selectors than in rule\n"); */
|
||||
continue;
|
||||
}
|
||||
|
||||
for (j = rule->selectors - 1; j != 0; j--) {
|
||||
for (; i != 0 && (s = selmatch(&selector[i - 1], &rule->selector[j - 1])) == 0; i--)
|
||||
;
|
||||
if (i == 0)
|
||||
break;
|
||||
score += s;
|
||||
}
|
||||
if (j == 0) {
|
||||
/* fprintf(stderr, " match\n"); */
|
||||
decl = xrealloc(decl, (decls + 1) * sizeof(struct decl));
|
||||
decl[decls].score = score;
|
||||
decl[decls].rule = rule;
|
||||
decls++;
|
||||
} else {
|
||||
/* fprintf(stderr, " some selector match fails\n"); */
|
||||
}
|
||||
}
|
||||
|
||||
if (decls == 0) {
|
||||
css_cascade(style, &css_blank_style);
|
||||
|
||||
} else {
|
||||
qsort(decl, decls, sizeof(struct decl), (int (*) (const void *, const void *)) cmpdecl);
|
||||
|
||||
for (d = 0; d < decls; d++) {
|
||||
/* fprintf(stderr, "%i: 0x%lx\n", d, decl[d].score); */
|
||||
/* dump_rule(decl[d].rule);*/
|
||||
css_cascade(style, decl[d].rule->style);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void update_style(struct css_stylesheet * stylesheet, struct css_selector * selector,
|
||||
unsigned int selectors, char * str)
|
||||
{
|
||||
struct rule * rule = find_rule(stylesheet, selector, selectors);
|
||||
if (rule == 0) {
|
||||
unsigned int h = hash_str(selector[selectors - 1].element);
|
||||
/*fprintf(stderr, "update_style: not present - adding\n");*/
|
||||
rule = xcalloc(1, sizeof(struct rule));
|
||||
rule->selector = selector;
|
||||
rule->selectors = selectors;
|
||||
rule->style = xcalloc(1, sizeof(struct css_style));
|
||||
memcpy(rule->style, &css_blank_style, sizeof(struct css_style));
|
||||
css_parse_property_list(rule->style, str);
|
||||
rule->next = stylesheet->hash[h];
|
||||
stylesheet->hash[h] = rule;
|
||||
} else {
|
||||
/*fprintf(stderr, "update_style: already present - updating\n");*/
|
||||
css_parse_property_list(rule->style, str);
|
||||
free(selector);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* parse an entire css file or block
|
||||
*/
|
||||
|
||||
void css_parse_stylesheet(struct css_stylesheet * stylesheet, char * str)
|
||||
{
|
||||
/* overwrite comments with spaces */
|
||||
char * copen = strstr(str, "/*");
|
||||
while (copen != 0) {
|
||||
char * cclose = strstr(copen + 2, "*/");
|
||||
if (cclose == 0) { *copen = 0; break; }
|
||||
memset(copen, ' ', (size_t) (cclose - copen + 2));
|
||||
copen = strstr(cclose + 2, "/*");
|
||||
}
|
||||
|
||||
while (*str != 0) {
|
||||
char * open = strchr(str, '{');
|
||||
char * close = strchr(str, '}');
|
||||
char * sels_str;
|
||||
char * comma;
|
||||
|
||||
if ((open == 0) || (close == 0)) break;
|
||||
*open = 0; *close = 0;
|
||||
|
||||
sels_str = strip(str);
|
||||
do {
|
||||
char * sel_str;
|
||||
char * space;
|
||||
char * style_str;
|
||||
unsigned int selectors = 0;
|
||||
struct css_selector * selector = xcalloc(0, sizeof(struct css_selector));
|
||||
|
||||
comma = strchr(sels_str, ',');
|
||||
if (comma != 0) *comma = 0;
|
||||
|
||||
sel_str = strip(sels_str);
|
||||
/*fprintf(stderr, "css_parse_stylesheet: %s\n", sel_str);*/
|
||||
do {
|
||||
space = strchr(sel_str, ' ');
|
||||
if (space != 0) *space = 0;
|
||||
selector = xrealloc(selector, sizeof(struct css_selector) * (selectors + 1));
|
||||
parse_selector(&selector[selectors++], sel_str);
|
||||
if (space != 0) sel_str = strip(space + 1);
|
||||
} while (space != 0);
|
||||
|
||||
style_str = xstrdup(open + 1);
|
||||
update_style(stylesheet, selector, selectors, style_str);
|
||||
free(style_str);
|
||||
|
||||
if (comma != 0) sels_str = strip(comma + 1);
|
||||
} while (comma != 0);
|
||||
|
||||
str = close + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* dump a style
|
||||
*/
|
||||
|
||||
static void dump_length(const struct css_length * const length)
|
||||
{
|
||||
fprintf(stderr, "%g%s", length->value,
|
||||
css_unit_name[length->unit]);
|
||||
}
|
||||
|
||||
void css_dump_style(const struct css_style * const style)
|
||||
{
|
||||
fprintf(stderr, "{ ");
|
||||
fprintf(stderr, "background-color: #%lx; ", style->background_color);
|
||||
fprintf(stderr, "clear: %s; ", css_clear_name[style->clear]);
|
||||
fprintf(stderr, "color: #%lx; ", style->color);
|
||||
fprintf(stderr, "display: %s; ", css_display_name[style->display]);
|
||||
fprintf(stderr, "float: %s; ", css_float_name[style->float_]);
|
||||
fprintf(stderr, "font-size: ");
|
||||
switch (style->font_size.size) {
|
||||
case CSS_FONT_SIZE_ABSOLUTE: fprintf(stderr, "[%g]", style->font_size.value.absolute); break;
|
||||
case CSS_FONT_SIZE_LENGTH: dump_length(&style->font_size.value.length); break;
|
||||
case CSS_FONT_SIZE_PERCENT: fprintf(stderr, "%g%%", style->font_size.value.percent); break;
|
||||
case CSS_FONT_SIZE_INHERIT: fprintf(stderr, "inherit"); break;
|
||||
default: fprintf(stderr, "UNKNOWN"); break;
|
||||
}
|
||||
fprintf(stderr, "; ");
|
||||
fprintf(stderr, "height: ");
|
||||
switch (style->height.height) {
|
||||
case CSS_HEIGHT_AUTO: fprintf(stderr, "auto"); break;
|
||||
case CSS_HEIGHT_LENGTH: dump_length(&style->height.length); break;
|
||||
default: fprintf(stderr, "UNKNOWN"); break;
|
||||
}
|
||||
fprintf(stderr, "; ");
|
||||
fprintf(stderr, "line-height: ");
|
||||
switch (style->line_height.size) {
|
||||
case CSS_LINE_HEIGHT_ABSOLUTE: fprintf(stderr, "[%g]", style->line_height.value.absolute); break;
|
||||
case CSS_LINE_HEIGHT_LENGTH: dump_length(&style->line_height.value.length); break;
|
||||
case CSS_LINE_HEIGHT_PERCENT: fprintf(stderr, "%g%%", style->line_height.value.percent); break;
|
||||
case CSS_LINE_HEIGHT_INHERIT: fprintf(stderr, "inherit"); break;
|
||||
default: fprintf(stderr, "UNKNOWN"); break;
|
||||
}
|
||||
fprintf(stderr, "; ");
|
||||
fprintf(stderr, "text-align: %s; ", css_text_align_name[style->text_align]);
|
||||
fprintf(stderr, "width: ");
|
||||
switch (style->width.width) {
|
||||
case CSS_WIDTH_AUTO: fprintf(stderr, "auto"); break;
|
||||
case CSS_WIDTH_LENGTH: dump_length(&style->width.value.length); break;
|
||||
case CSS_WIDTH_PERCENT: fprintf(stderr, "%g%%", style->width.value.percent); break;
|
||||
default: fprintf(stderr, "UNKNOWN"); break;
|
||||
}
|
||||
fprintf(stderr, "; ");
|
||||
fprintf(stderr, "}");
|
||||
}
|
||||
|
||||
static void dump_selector(const struct css_selector * const sel)
|
||||
{
|
||||
if (sel->class != 0)
|
||||
fprintf(stderr, "'%s'.'%s' ", sel->element, sel->class);
|
||||
else if (sel->id != 0)
|
||||
fprintf(stderr, "'%s'#'%s' ", sel->element, sel->id);
|
||||
else
|
||||
fprintf(stderr, "'%s' ", sel->element);
|
||||
}
|
||||
|
||||
static void dump_rule(const struct rule * rule)
|
||||
{
|
||||
unsigned int i;
|
||||
for (i = 0; i < rule->selectors; i++)
|
||||
dump_selector(&rule->selector[i]);
|
||||
css_dump_style(rule->style);
|
||||
}
|
||||
|
||||
void css_dump_stylesheet(const struct css_stylesheet * stylesheet)
|
||||
{
|
||||
unsigned int i;
|
||||
for (i = 0; i < HASH_SIZE; i++) {
|
||||
struct rule * rule;
|
||||
fprintf(stderr, "hash %i:\n", i);
|
||||
for (rule = stylesheet->hash[i]; rule != 0; rule = rule->next)
|
||||
dump_rule(rule);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* cascade styles
|
||||
*/
|
||||
|
||||
void css_cascade(struct css_style * const style, const struct css_style * const apply)
|
||||
{
|
||||
float f;
|
||||
|
||||
if (apply->background_color != CSS_COLOR_INHERIT)
|
||||
style->background_color = apply->background_color;
|
||||
if (apply->clear != CSS_CLEAR_INHERIT)
|
||||
style->clear = apply->clear;
|
||||
if (apply->color != CSS_COLOR_INHERIT)
|
||||
style->color = apply->color;
|
||||
if (apply->display != CSS_DISPLAY_INHERIT)
|
||||
style->display = apply->display;
|
||||
if (apply->float_ != CSS_FLOAT_INHERIT)
|
||||
style->float_ = apply->float_;
|
||||
if (apply->height.height != CSS_HEIGHT_INHERIT)
|
||||
style->height = apply->height;
|
||||
if (apply->text_align != CSS_TEXT_ALIGN_INHERIT)
|
||||
style->text_align = apply->text_align;
|
||||
if (apply->width.width != CSS_WIDTH_INHERIT)
|
||||
style->width = apply->width;
|
||||
if (apply->font_weight != CSS_FONT_WEIGHT_INHERIT)
|
||||
style->font_weight = apply->font_weight;
|
||||
if (apply->font_style != CSS_FONT_STYLE_INHERIT)
|
||||
style->font_style = apply->font_style;
|
||||
|
||||
/* font-size */
|
||||
f = apply->font_size.value.percent / 100;
|
||||
switch (apply->font_size.size) {
|
||||
case CSS_FONT_SIZE_ABSOLUTE:
|
||||
style->font_size = apply->font_size;
|
||||
break;
|
||||
case CSS_FONT_SIZE_LENGTH:
|
||||
switch (apply->font_size.value.length.unit) {
|
||||
case CSS_UNIT_EM:
|
||||
f = apply->font_size.value.length.value;
|
||||
break;
|
||||
case CSS_UNIT_EX:
|
||||
f = apply->font_size.value.length.value * 0.6 /*?*/;
|
||||
break;
|
||||
default:
|
||||
style->font_size = apply->font_size;
|
||||
}
|
||||
if ((apply->font_size.value.length.unit != CSS_UNIT_EM) &&
|
||||
(apply->font_size.value.length.unit != CSS_UNIT_EX))
|
||||
break;
|
||||
/* drop through if EM or EX */
|
||||
case CSS_FONT_SIZE_PERCENT:
|
||||
switch (style->font_size.size) {
|
||||
case CSS_FONT_SIZE_ABSOLUTE:
|
||||
style->font_size.value.absolute *= f;
|
||||
break;
|
||||
case CSS_FONT_SIZE_LENGTH:
|
||||
style->font_size.value.length.value *= f;
|
||||
break;
|
||||
default:
|
||||
die("attempting percentage of unknown font-size");
|
||||
}
|
||||
break;
|
||||
case CSS_FONT_SIZE_INHERIT:
|
||||
default: /* leave unchanged */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* testing
|
||||
*/
|
||||
/*
|
||||
int main(int argv, char *argc[])
|
||||
{
|
||||
int i;
|
||||
struct rule * r;
|
||||
struct css_stylesheet * s;
|
||||
struct css_selector sel = { "h1", 0, 0 };
|
||||
struct css_selector con[] = {{ "html", 0, 0 }, {"body", 0, 0}, {"h1", "foo", 0}, {"b", 0, "bar"}};
|
||||
struct css_style * style = xcalloc(1, sizeof(struct css_style));
|
||||
|
||||
s = css_new_stylesheet();
|
||||
css_parse_stylesheet(s, argc[1]);
|
||||
css_dump_stylesheet(s);
|
||||
|
||||
r->selectors = 1;
|
||||
css_stylesheet_add_rule(s, r);
|
||||
puts("********** finding h1:");
|
||||
r = find_rule(s, &sel, 1);
|
||||
if (r)
|
||||
dump_rule(r);
|
||||
else
|
||||
puts("not found");
|
||||
|
||||
puts("********** finding html body h1.foo b#bar:");
|
||||
for (i = 1; i <= sizeof(con) / sizeof(con[0]); i++) {
|
||||
css_get_style(s, con, i, style);
|
||||
css_dump_style(style);
|
||||
}
|
||||
|
||||
fprintf(stderr, "%x %x\n", r, r2);
|
||||
|
||||
struct css_style *s;
|
||||
struct css_selector *sel;
|
||||
|
||||
s = parse_property_list(argc[1]);
|
||||
css_dump_style(s);
|
||||
|
||||
for (i = 2; i < argv; i++) {
|
||||
css_cascade(s, parse_property_list(argc[i]));
|
||||
css_dump_style(s);
|
||||
}*/
|
||||
|
||||
/* for (i = 1; i < argv; i++) {
|
||||
sel = parse_selector(argc[i]);
|
||||
css_dump_selector(sel);
|
||||
puts("");
|
||||
}*/
|
||||
/*
|
||||
return 0;
|
||||
}
|
||||
*/
|
103
render/css.h
103
render/css.h
@ -1,103 +0,0 @@
|
||||
/**
|
||||
* $Id: css.h,v 1.9 2002/12/27 20:13:18 bursa Exp $
|
||||
*/
|
||||
|
||||
#ifndef _NETSURF_RENDER_CSS_H_
|
||||
#define _NETSURF_RENDER_CSS_H_
|
||||
|
||||
#include "css_enum.h"
|
||||
|
||||
/**
|
||||
* structures and typedefs
|
||||
*/
|
||||
|
||||
typedef unsigned long colour; /* 0xbbggrr */
|
||||
#define TRANSPARENT 0x1000000
|
||||
#define CSS_COLOR_INHERIT 0x2000000
|
||||
|
||||
struct css_length {
|
||||
float value;
|
||||
css_unit unit;
|
||||
};
|
||||
|
||||
struct css_style {
|
||||
colour background_color;
|
||||
css_clear clear;
|
||||
colour color;
|
||||
css_display display;
|
||||
css_float float_;
|
||||
|
||||
struct {
|
||||
enum { CSS_FONT_SIZE_INHERIT,
|
||||
CSS_FONT_SIZE_ABSOLUTE,
|
||||
CSS_FONT_SIZE_LENGTH,
|
||||
CSS_FONT_SIZE_PERCENT } size;
|
||||
union {
|
||||
struct css_length length;
|
||||
float absolute;
|
||||
float percent;
|
||||
} value;
|
||||
} font_size;
|
||||
|
||||
css_font_weight font_weight;
|
||||
css_font_style font_style;
|
||||
|
||||
struct {
|
||||
enum { CSS_HEIGHT_INHERIT,
|
||||
CSS_HEIGHT_AUTO,
|
||||
CSS_HEIGHT_LENGTH } height;
|
||||
struct css_length length;
|
||||
} height;
|
||||
|
||||
struct {
|
||||
enum { CSS_LINE_HEIGHT_INHERIT,
|
||||
CSS_LINE_HEIGHT_ABSOLUTE,
|
||||
CSS_LINE_HEIGHT_LENGTH,
|
||||
CSS_LINE_HEIGHT_PERCENT } size;
|
||||
union {
|
||||
float absolute;
|
||||
struct css_length length;
|
||||
float percent;
|
||||
} value;
|
||||
} line_height;
|
||||
|
||||
css_text_align text_align;
|
||||
|
||||
struct {
|
||||
enum { CSS_WIDTH_INHERIT,
|
||||
CSS_WIDTH_AUTO,
|
||||
CSS_WIDTH_LENGTH,
|
||||
CSS_WIDTH_PERCENT } width;
|
||||
union {
|
||||
struct css_length length;
|
||||
float percent;
|
||||
} value;
|
||||
} width;
|
||||
};
|
||||
|
||||
struct css_stylesheet;
|
||||
|
||||
struct css_selector {
|
||||
const char * element;
|
||||
char * class;
|
||||
char * id;
|
||||
};
|
||||
|
||||
extern const struct css_style css_base_style;
|
||||
extern const struct css_style css_empty_style;
|
||||
extern const struct css_style css_blank_style;
|
||||
|
||||
/**
|
||||
* interface
|
||||
*/
|
||||
|
||||
struct css_stylesheet * css_new_stylesheet(void);
|
||||
void css_get_style(struct css_stylesheet * stylesheet, struct css_selector * selector,
|
||||
unsigned int selectors, struct css_style * style);
|
||||
void css_parse_stylesheet(struct css_stylesheet * stylesheet, char * str);
|
||||
void css_dump_style(const struct css_style * const style);
|
||||
void css_dump_stylesheet(const struct css_stylesheet * stylesheet);
|
||||
void css_cascade(struct css_style * const style, const struct css_style * const apply);
|
||||
void css_parse_property_list(struct css_style * style, char * str);
|
||||
|
||||
#endif
|
@ -1,10 +1,12 @@
|
||||
/**
|
||||
* $Id: html.c,v 1.6 2003/03/25 21:51:29 bursa Exp $
|
||||
* $Id: html.c,v 1.7 2003/04/04 15:19:31 bursa Exp $
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "netsurf/content/fetch.h"
|
||||
#include "netsurf/content/fetchcache.h"
|
||||
#include "netsurf/desktop/gui.h"
|
||||
#include "netsurf/render/html.h"
|
||||
#include "netsurf/render/layout.h"
|
||||
@ -12,6 +14,8 @@
|
||||
#include "netsurf/utils/log.h"
|
||||
|
||||
|
||||
static void html_convert_callback(fetchcache_msg msg, struct content *css,
|
||||
void *p, const char *error);
|
||||
static void html_title(struct content *c);
|
||||
|
||||
|
||||
@ -42,8 +46,7 @@ void html_process_data(struct content *c, char *data, unsigned long size)
|
||||
|
||||
int html_convert(struct content *c, unsigned int width, unsigned int height)
|
||||
{
|
||||
char* file;
|
||||
struct css_selector* selector = xcalloc(1, sizeof(struct css_selector));
|
||||
struct css_selector* selector = xcalloc(1, sizeof(struct css_selector));
|
||||
|
||||
htmlParseChunk(c->data.html.parser, "", 0, 1);
|
||||
c->data.html.document = c->data.html.parser->myDoc;
|
||||
@ -70,16 +73,26 @@ int html_convert(struct content *c, unsigned int width, unsigned int height)
|
||||
|
||||
html_title(c);
|
||||
|
||||
/* TODO: rewrite stylesheet handling */
|
||||
LOG(("Loading CSS"));
|
||||
file = load("<NetSurf$Dir>.Resources.CSS"); /*!!! not portable! !!!*/
|
||||
c->data.html.stylesheet = css_new_stylesheet();
|
||||
LOG(("Parsing stylesheet"));
|
||||
css_parse_stylesheet(c->data.html.stylesheet, file);
|
||||
c->error = 0;
|
||||
c->active = 0;
|
||||
|
||||
LOG(("Copying base style"));
|
||||
c->data.html.style = xcalloc(1, sizeof(struct css_style));
|
||||
memcpy(c->data.html.style, &css_base_style, sizeof(struct css_style));
|
||||
fetchcache("file:///%3CNetSurf$Dir%3E/Resources/CSS", 0,
|
||||
html_convert_callback, c, width, height);
|
||||
c->active++;
|
||||
|
||||
while (c->active != 0) {
|
||||
fetch_poll();
|
||||
gui_multitask();
|
||||
}
|
||||
|
||||
if (c->error) {
|
||||
/* TODO: clean up */
|
||||
return 1;
|
||||
}
|
||||
|
||||
LOG(("Copying base style"));
|
||||
c->data.html.style = xcalloc(1, sizeof(struct css_style));
|
||||
memcpy(c->data.html.style, &css_base_style, sizeof(struct css_style));
|
||||
|
||||
LOG(("Creating box"));
|
||||
c->data.html.layout = xcalloc(1, sizeof(struct box));
|
||||
@ -105,6 +118,31 @@ int html_convert(struct content *c, unsigned int width, unsigned int height)
|
||||
}
|
||||
|
||||
|
||||
void html_convert_callback(fetchcache_msg msg, struct content *css,
|
||||
void *p, const char *error)
|
||||
{
|
||||
struct content *c = p;
|
||||
switch (msg) {
|
||||
case FETCHCACHE_OK:
|
||||
/* TODO: store struct content *css somewhere in c */
|
||||
c->data.html.stylesheet = css->data.css;
|
||||
c->active--;
|
||||
break;
|
||||
case FETCHCACHE_BADTYPE:
|
||||
case FETCHCACHE_ERROR:
|
||||
c->active--;
|
||||
c->error = 1;
|
||||
break;
|
||||
case FETCHCACHE_STATUS:
|
||||
/* TODO: need to add a way of sending status to the
|
||||
* owning window */
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void html_title(struct content *c)
|
||||
{
|
||||
xmlNode *node = c->data.html.markup;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/**
|
||||
* $Id: layout.c,v 1.36 2003/03/25 21:51:29 bursa Exp $
|
||||
* $Id: layout.c,v 1.37 2003/04/04 15:19:31 bursa Exp $
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
@ -10,7 +10,7 @@
|
||||
#include "libxml/HTMLparser.h"
|
||||
#include "netsurf/desktop/gui.h"
|
||||
#include "netsurf/render/box.h"
|
||||
#include "netsurf/render/css.h"
|
||||
#include "netsurf/css/css.h"
|
||||
#include "netsurf/render/layout.h"
|
||||
#include "netsurf/riscos/font.h"
|
||||
#include "netsurf/utils/utils.h"
|
||||
|
@ -1,5 +1,5 @@
|
||||
/**
|
||||
* $Id: filetype.c,v 1.1 2003/03/15 15:53:20 bursa Exp $
|
||||
* $Id: filetype.c,v 1.2 2003/04/04 15:19:31 bursa Exp $
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
@ -15,6 +15,7 @@ struct type_entry {
|
||||
char mime_type[16];
|
||||
};
|
||||
static const struct type_entry type_map[] = {
|
||||
{0x0cc, "text/css"},
|
||||
{0xc85, "image/jpeg"},
|
||||
{0xfaf, "text/html"},
|
||||
{0xfff, "text/plain"},
|
||||
|
@ -1,11 +1,11 @@
|
||||
/**
|
||||
* $Id: font.c,v 1.12 2003/03/04 11:59:35 bursa Exp $
|
||||
* $Id: font.c,v 1.13 2003/04/04 15:19:31 bursa Exp $
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include "libutf-8/utf-8.h"
|
||||
#include "netsurf/render/css.h"
|
||||
#include "netsurf/css/css.h"
|
||||
#include "netsurf/riscos/font.h"
|
||||
#include "netsurf/utils/utils.h"
|
||||
#include "netsurf/desktop/gui.h"
|
||||
|
@ -1,5 +1,5 @@
|
||||
/**
|
||||
* $Id: font.h,v 1.6 2003/03/03 22:40:39 bursa Exp $
|
||||
* $Id: font.h,v 1.7 2003/04/04 15:19:32 bursa Exp $
|
||||
*/
|
||||
|
||||
#ifndef _NETSURF_RISCOS_FONT_H_
|
||||
@ -9,7 +9,7 @@
|
||||
* structures and typedefs
|
||||
*/
|
||||
|
||||
#include "netsurf/render/css.h"
|
||||
#include "netsurf/css/css.h"
|
||||
#include "oslib/font.h"
|
||||
|
||||
typedef unsigned int font_id;
|
||||
|
Loading…
Reference in New Issue
Block a user