2003-06-30 16:44:03 +04:00
/*
* This file is part of NetSurf , http : //netsurf.sourceforge.net/
* Licensed under the GNU General Public License ,
* http : //www.opensource.org/licenses/gpl-license
* Copyright 2003 James Bursa < bursa @ users . sourceforge . net >
* Copyright 2003 Phil Mellor < monkeyson @ users . sourceforge . net >
* Copyright 2003 John M Bell < jmb202 @ ecs . soton . ac . uk >
2002-05-04 23:57:18 +04:00
*/
# include <assert.h>
# include <ctype.h>
# include <stdio.h>
2003-07-15 02:57:45 +04:00
# include <stdbool.h>
2002-05-04 23:57:18 +04:00
# include <stdlib.h>
# include <string.h>
# include "libxml/HTMLparser.h"
2004-01-05 05:10:59 +03:00
# include "netsurf/utils/config.h"
2003-10-25 18:13:49 +04:00
# include "netsurf/content/content.h"
2003-04-04 19:19:32 +04:00
# include "netsurf/css/css.h"
2004-02-14 02:07:42 +03:00
# include "netsurf/desktop/options.h"
2002-08-18 20:46:45 +04:00
# include "netsurf/render/box.h"
2003-07-18 03:01:02 +04:00
# include "netsurf/render/font.h"
2003-10-25 04:35:49 +04:00
# include "netsurf/render/form.h"
2003-07-05 01:17:53 +04:00
# include "netsurf/render/html.h"
2003-06-17 23:24:21 +04:00
# ifdef riscos
# include "netsurf/desktop/gui.h"
2004-01-05 05:10:59 +03:00
# ifdef WITH_PLUGIN
2003-05-31 22:47:00 +04:00
# include "netsurf/riscos/plugin.h"
2003-07-15 02:57:45 +04:00
# endif
2004-01-05 05:10:59 +03:00
# endif
2003-06-17 23:24:21 +04:00
# define NDEBUG
2003-05-31 22:47:00 +04:00
# include "netsurf/utils/log.h"
2003-09-27 03:22:00 +04:00
# include "netsurf/utils/messages.h"
2004-01-02 15:04:04 +03:00
# include "netsurf/utils/pool.h"
2003-02-09 15:58:15 +03:00
# include "netsurf/utils/utils.h"
2002-05-04 23:57:18 +04:00
2003-07-05 01:17:53 +04:00
/* status for box tree construction */
struct status {
struct content * content ;
char * href ;
char * title ;
struct form * current_form ;
struct page_elements * elements ;
} ;
/* result of converting a special case element */
struct result {
struct box * box ; /* box for element, if any, 0 otherwise */
int convert_children ; /* children should be converted */
2003-04-15 21:53:00 +04:00
} ;
2003-07-05 01:17:53 +04:00
static struct box * convert_xml_to_box ( xmlNode * n , struct content * content ,
2003-04-15 21:53:00 +04:00
struct css_style * parent_style ,
2003-07-05 01:17:53 +04:00
struct box * parent , struct box * inline_container ,
struct status status ) ;
2003-04-06 01:38:06 +04:00
static struct css_style * box_get_style ( struct content * * stylesheet ,
unsigned int stylesheet_count , struct css_style * parent_style ,
2003-12-11 02:12:39 +03:00
xmlNode * n ) ;
2003-07-05 01:17:53 +04:00
static struct result box_a ( xmlNode * n , struct status * status ,
struct css_style * style ) ;
2003-08-31 01:45:03 +04:00
static struct result box_body ( xmlNode * n , struct status * status ,
struct css_style * style ) ;
2003-07-05 01:17:53 +04:00
static struct result box_image ( xmlNode * n , struct status * status ,
struct css_style * style ) ;
static struct result box_form ( xmlNode * n , struct status * status ,
struct css_style * style ) ;
static struct result box_textarea ( xmlNode * n , struct status * status ,
struct css_style * style ) ;
static struct result box_select ( xmlNode * n , struct status * status ,
struct css_style * style ) ;
2003-09-27 03:22:00 +04:00
static struct result box_input ( xmlNode * n , struct status * status ,
struct css_style * style ) ;
2003-09-29 03:41:07 +04:00
static struct box * box_input_text ( xmlNode * n , struct status * status ,
struct css_style * style , bool password ) ;
2003-09-27 03:22:00 +04:00
static struct result box_button ( xmlNode * n , struct status * status ,
2003-07-05 01:17:53 +04:00
struct css_style * style ) ;
2003-10-25 04:35:49 +04:00
static void add_option ( xmlNode * n , struct form_control * current_select , char * text ) ;
2004-01-02 15:04:04 +03:00
static void box_normalise_block ( struct box * block , pool box_pool ) ;
static void box_normalise_table ( struct box * table , pool box_pool ) ;
2003-07-07 01:10:12 +04:00
void box_normalise_table_row_group ( struct box * row_group ,
2004-01-02 15:04:04 +03:00
unsigned int * * row_span , unsigned int * table_columns ,
pool box_pool ) ;
2003-07-07 01:10:12 +04:00
void box_normalise_table_row ( struct box * row ,
2004-01-02 15:04:04 +03:00
unsigned int * * row_span , unsigned int * table_columns ,
pool box_pool ) ;
static void box_normalise_inline_container ( struct box * cont , pool box_pool ) ;
2003-10-25 04:35:49 +04:00
static void gadget_free ( struct form_control * g ) ;
2003-03-04 14:59:36 +03:00
static void box_free_box ( struct box * box ) ;
2004-01-05 05:10:59 +03:00
# ifdef WITH_PLUGIN
2003-07-08 02:10:51 +04:00
static struct result box_object ( xmlNode * n , struct status * status ,
struct css_style * style ) ;
static struct result box_embed ( xmlNode * n , struct status * status ,
struct css_style * style ) ;
static struct result box_applet ( xmlNode * n , struct status * status ,
struct css_style * style ) ;
2004-01-05 05:10:59 +03:00
# endif
# if defined(WITH_PLUGIN)
2003-08-25 02:39:55 +04:00
static struct result box_iframe ( xmlNode * n , struct status * status ,
struct css_style * style ) ;
2004-01-05 05:10:59 +03:00
# endif
2003-03-04 14:59:36 +03:00
static void add_form_element ( struct page_elements * pe , struct form * f ) ;
2003-10-25 04:35:49 +04:00
static void add_gadget_element ( struct page_elements * pe , struct form_control * g ) ;
2004-01-05 05:10:59 +03:00
# ifdef WITH_PLUGIN
2003-07-10 01:33:01 +04:00
static bool plugin_decode ( struct content * content , char * url , struct box * box ,
struct object_params * po ) ;
2004-01-05 05:10:59 +03:00
# endif
2003-07-05 01:17:53 +04:00
/* element_table must be sorted by name */
struct element_entry {
char name [ 10 ] ; /* element type */
struct result ( * convert ) ( xmlNode * n , struct status * status ,
struct css_style * style ) ;
} ;
static const struct element_entry element_table [ ] = {
{ " a " , box_a } ,
2004-01-05 05:10:59 +03:00
# ifdef WITH_PLUGIN
2003-07-17 18:26:15 +04:00
{ " applet " , box_applet } ,
2004-01-05 05:10:59 +03:00
# endif
2003-08-31 01:45:03 +04:00
{ " body " , box_body } ,
2003-09-27 03:22:00 +04:00
{ " button " , box_button } ,
2004-01-05 05:10:59 +03:00
# ifdef WITH_PLUGIN
2003-09-27 03:22:00 +04:00
{ " embed " , box_embed } ,
2004-01-05 05:10:59 +03:00
# endif
2003-07-05 01:17:53 +04:00
{ " form " , box_form } ,
2004-01-05 05:10:59 +03:00
# if defined(WITH_PLUGIN)
2003-08-25 02:39:55 +04:00
{ " iframe " , box_iframe } ,
2004-01-05 05:10:59 +03:00
# endif
2003-07-05 01:17:53 +04:00
{ " img " , box_image } ,
{ " input " , box_input } ,
2004-01-05 05:10:59 +03:00
# ifdef WITH_PLUGIN
2003-07-08 02:10:51 +04:00
{ " object " , box_object } ,
2004-01-05 05:10:59 +03:00
# endif
2003-07-05 01:17:53 +04:00
{ " select " , box_select } ,
{ " textarea " , box_textarea }
} ;
# define ELEMENT_TABLE_COUNT (sizeof(element_table) / sizeof(element_table[0]))
2002-05-04 23:57:18 +04:00
/**
2003-10-09 19:22:48 +04:00
* Add a child to a box tree node .
2002-05-04 23:57:18 +04:00
*/
void box_add_child ( struct box * parent , struct box * child )
{
2003-01-02 16:26:43 +03:00
if ( parent - > children ! = 0 ) { /* has children already */
2002-05-04 23:57:18 +04:00
parent - > last - > next = child ;
2003-01-02 16:26:43 +03:00
child - > prev = parent - > last ;
} else { /* this is the first child */
2002-05-04 23:57:18 +04:00
parent - > children = child ;
2003-01-02 16:26:43 +03:00
child - > prev = 0 ;
}
2002-05-04 23:57:18 +04:00
parent - > last = child ;
child - > parent = parent ;
}
2003-10-09 19:22:48 +04:00
2002-06-27 03:27:30 +04:00
/**
2003-10-09 19:22:48 +04:00
* Create a box tree node .
2002-06-27 03:27:30 +04:00
*/
2003-07-05 20:16:15 +04:00
struct box * box_create ( struct css_style * style ,
2004-01-02 15:04:04 +03:00
char * href , char * title , pool box_pool )
2002-06-27 03:27:30 +04:00
{
2004-02-02 03:22:59 +03:00
unsigned int i ;
2004-01-02 15:04:04 +03:00
struct box * box = pool_alloc ( box_pool , sizeof ( struct box ) ) ;
assert ( box ) ;
2003-07-05 20:16:15 +04:00
box - > type = BOX_INLINE ;
2002-06-27 03:27:30 +04:00
box - > style = style ;
2002-09-19 23:54:43 +04:00
box - > width = UNKNOWN_WIDTH ;
2002-09-18 23:36:28 +04:00
box - > max_width = UNKNOWN_MAX_WIDTH ;
2003-09-20 01:23:19 +04:00
box - > href = href ? xstrdup ( href ) : 0 ;
box - > title = title ? xstrdup ( title ) : 0 ;
2002-09-18 23:36:28 +04:00
box - > columns = 1 ;
2003-07-05 23:51:10 +04:00
box - > rows = 1 ;
2003-07-05 01:17:53 +04:00
box - > text = 0 ;
box - > space = 0 ;
2003-09-10 01:43:44 +04:00
box - > clone = 0 ;
2003-09-20 01:23:19 +04:00
box - > style_clone = 0 ;
2003-07-05 01:17:53 +04:00
box - > length = 0 ;
2003-07-07 01:10:12 +04:00
box - > start_column = 0 ;
2002-08-18 20:46:45 +04:00
box - > next = 0 ;
2003-01-02 16:26:43 +03:00
box - > prev = 0 ;
2002-08-18 20:46:45 +04:00
box - > children = 0 ;
box - > last = 0 ;
box - > parent = 0 ;
box - > float_children = 0 ;
box - > next_float = 0 ;
2002-09-18 23:36:28 +04:00
box - > col = 0 ;
2002-09-27 01:38:33 +04:00
box - > font = 0 ;
2002-12-30 01:27:35 +03:00
box - > gadget = 0 ;
2003-04-15 21:53:00 +04:00
box - > object = 0 ;
2004-01-05 05:10:59 +03:00
# ifdef WITH_PLUGIN
2003-07-10 01:33:01 +04:00
box - > object_params = 0 ;
2003-07-15 02:57:45 +04:00
box - > object_state = 0 ;
2004-01-05 05:10:59 +03:00
# endif
2004-01-02 15:04:04 +03:00
box - > x = box - > y = 0 ;
2004-01-26 18:07:20 +03:00
box - > height = 0 ;
2004-02-02 03:22:59 +03:00
for ( i = 0 ; i ! = 4 ; i + + )
box - > margin [ i ] = box - > padding [ i ] = box - > border [ i ] = 0 ;
2002-06-27 03:27:30 +04:00
return box ;
}
2002-05-04 23:57:18 +04:00
2002-09-12 01:19:24 +04:00
2003-10-09 19:22:48 +04:00
/**
* Insert a new box as a sibling to a box in a tree .
*/
void box_insert_sibling ( struct box * box , struct box * new_box )
{
new_box - > parent = box - > parent ;
new_box - > prev = box ;
new_box - > next = box - > next ;
box - > next = new_box ;
if ( new_box - > next )
new_box - > next - > prev = new_box ;
else if ( new_box - > parent )
new_box - > parent - > last = new_box ;
}
2003-04-15 21:53:00 +04:00
/**
* make a box tree with style data from an xml tree
*/
void xml_to_box ( xmlNode * n , struct content * c )
{
2003-07-05 01:17:53 +04:00
struct status status = { c , 0 , 0 , 0 , & c - > data . html . elements } ;
2003-04-15 21:53:00 +04:00
LOG ( ( " node %p " , n ) ) ;
assert ( c - > type = = CONTENT_HTML ) ;
2004-01-02 15:04:04 +03:00
c - > data . html . layout = box_create ( 0 , 0 , 0 , c - > data . html . box_pool ) ;
2003-04-15 21:53:00 +04:00
c - > data . html . layout - > type = BOX_BLOCK ;
c - > data . html . style = xcalloc ( 1 , sizeof ( struct css_style ) ) ;
memcpy ( c - > data . html . style , & css_base_style , sizeof ( struct css_style ) ) ;
2004-02-14 02:07:42 +03:00
c - > data . html . style - > font_size . value . length . value = option_font_size * 0.1 ;
2003-04-15 21:53:00 +04:00
c - > data . html . fonts = font_new_set ( ) ;
c - > data . html . object_count = 0 ;
c - > data . html . object = xcalloc ( 0 , sizeof ( * c - > data . html . object ) ) ;
convert_xml_to_box ( n , c , c - > data . html . style ,
2003-12-11 02:12:39 +03:00
c - > data . html . layout , 0 , status ) ;
2003-04-15 21:53:00 +04:00
LOG ( ( " normalising " ) ) ;
2004-01-02 15:04:04 +03:00
box_normalise_block ( c - > data . html . layout - > children ,
c - > data . html . box_pool ) ;
2003-04-15 21:53:00 +04:00
}
2002-05-04 23:57:18 +04:00
/**
* make a box tree with style data from an xml tree
*
* arguments :
* n xml tree
2003-04-15 21:53:00 +04:00
* content content structure
2002-05-04 23:57:18 +04:00
* parent_style style at this point in xml tree
* parent parent in box tree
* inline_container current inline container box , or 0
2003-07-05 01:17:53 +04:00
* status status for forms etc .
2002-05-04 23:57:18 +04:00
*
* returns :
* updated current inline container
*/
2003-07-05 20:16:15 +04:00
/* mapping from CSS display to box type
* this table must be in sync with css / css_enums */
static box_type box_map [ ] = {
0 , /*CSS_DISPLAY_INHERIT,*/
BOX_INLINE , /*CSS_DISPLAY_INLINE,*/
BOX_BLOCK , /*CSS_DISPLAY_BLOCK,*/
BOX_BLOCK , /*CSS_DISPLAY_LIST_ITEM,*/
BOX_INLINE , /*CSS_DISPLAY_RUN_IN,*/
2003-09-22 02:47:08 +04:00
BOX_INLINE_BLOCK , /*CSS_DISPLAY_INLINE_BLOCK,*/
2003-07-05 20:16:15 +04:00
BOX_TABLE , /*CSS_DISPLAY_TABLE,*/
BOX_TABLE , /*CSS_DISPLAY_INLINE_TABLE,*/
BOX_TABLE_ROW_GROUP , /*CSS_DISPLAY_TABLE_ROW_GROUP,*/
BOX_TABLE_ROW_GROUP , /*CSS_DISPLAY_TABLE_HEADER_GROUP,*/
BOX_TABLE_ROW_GROUP , /*CSS_DISPLAY_TABLE_FOOTER_GROUP,*/
BOX_TABLE_ROW , /*CSS_DISPLAY_TABLE_ROW,*/
BOX_INLINE , /*CSS_DISPLAY_TABLE_COLUMN_GROUP,*/
BOX_INLINE , /*CSS_DISPLAY_TABLE_COLUMN,*/
BOX_TABLE_CELL , /*CSS_DISPLAY_TABLE_CELL,*/
BOX_INLINE /*CSS_DISPLAY_TABLE_CAPTION,*/
} ;
2003-04-15 21:53:00 +04:00
struct box * convert_xml_to_box ( xmlNode * n , struct content * content ,
struct css_style * parent_style ,
2003-07-05 01:17:53 +04:00
struct box * parent , struct box * inline_container ,
struct status status )
2002-05-04 23:57:18 +04:00
{
2003-01-07 02:53:40 +03:00
struct box * box = 0 ;
2002-05-04 23:57:18 +04:00
struct box * inline_container_c ;
2003-04-13 16:50:10 +04:00
struct css_style * style = 0 ;
2002-05-04 23:57:18 +04:00
xmlNode * c ;
2002-06-27 03:27:30 +04:00
char * s ;
2003-07-01 02:21:51 +04:00
xmlChar * title0 ;
char * title = 0 ;
2003-07-05 01:17:53 +04:00
int convert_children = 1 ;
2003-09-20 01:23:19 +04:00
char * href_in = status . href ;
2002-05-04 23:57:18 +04:00
2003-12-11 02:12:39 +03:00
assert ( n ! = 0 & & parent_style ! = 0 & & parent ! = 0 ) ;
LOG ( ( " node %p, node type %i " , n , n - > type ) ) ;
2002-09-11 18:24:02 +04:00
gui_multitask ( ) ;
2002-05-04 23:57:18 +04:00
if ( n - > type = = XML_ELEMENT_NODE ) {
2003-07-05 01:17:53 +04:00
struct element_entry * element ;
2003-04-15 21:53:00 +04:00
style = box_get_style ( content - > data . html . stylesheet_content ,
2003-12-11 02:12:39 +03:00
content - > data . html . stylesheet_count , parent_style , n ) ;
2002-10-08 13:38:29 +04:00
LOG ( ( " display: %s " , css_display_name [ style - > display ] ) ) ;
2003-04-13 16:50:10 +04:00
if ( style - > display = = CSS_DISPLAY_NONE ) {
free ( style ) ;
2003-12-11 02:12:39 +03:00
LOG ( ( " node %p, node type %i END " , n , n - > type ) ) ;
2003-09-20 01:23:19 +04:00
goto end ;
2003-04-13 16:50:10 +04:00
}
2003-04-15 21:53:00 +04:00
/* floats are treated as blocks */
if ( style - > float_ = = CSS_FLOAT_LEFT | | style - > float_ = = CSS_FLOAT_RIGHT )
if ( style - > display = = CSS_DISPLAY_INLINE )
style - > display = CSS_DISPLAY_BLOCK ;
2002-08-12 03:01:02 +04:00
2003-07-01 02:21:51 +04:00
/* extract title attribute, if present */
if ( ( title0 = xmlGetProp ( n , ( const xmlChar * ) " title " ) ) ) {
2003-09-20 01:23:19 +04:00
status . title = title = squash_tolat1 ( title0 ) ;
2003-07-01 02:21:51 +04:00
xfree ( title0 ) ;
}
2003-01-07 02:53:40 +03:00
/* special elements */
2003-07-05 01:17:53 +04:00
element = bsearch ( ( const char * ) n - > name , element_table ,
ELEMENT_TABLE_COUNT , sizeof ( element_table [ 0 ] ) ,
( int ( * ) ( const void * , const void * ) ) strcmp ) ;
if ( element ! = 0 ) {
2003-07-05 20:16:15 +04:00
/* a special convert function exists for this element */
2003-07-05 01:17:53 +04:00
struct result res = element - > convert ( n , & status , style ) ;
box = res . box ;
convert_children = res . convert_children ;
2003-07-05 20:16:15 +04:00
if ( box = = 0 ) {
/* no box for this element */
assert ( convert_children = = 0 ) ;
2003-09-20 01:23:19 +04:00
free ( style ) ;
2003-12-11 02:12:39 +03:00
LOG ( ( " node %p, node type %i END " , n , n - > type ) ) ;
2003-09-20 01:23:19 +04:00
goto end ;
2003-07-05 20:16:15 +04:00
}
} else {
/* general element */
2004-01-02 15:04:04 +03:00
box = box_create ( style , status . href , title ,
content - > data . html . box_pool ) ;
2003-01-07 02:53:40 +03:00
}
2003-07-05 23:51:10 +04:00
box - > type = box_map [ style - > display ] ;
2003-01-07 02:53:40 +03:00
} else if ( n - > type = = XML_TEXT_NODE ) {
2003-10-08 01:34:39 +04:00
/* text node: added to inline container below */
} else {
/* not an element or text node: ignore it (eg. comment) */
2003-12-11 02:12:39 +03:00
LOG ( ( " node %p, node type %i END " , n , n - > type ) ) ;
2003-10-08 01:34:39 +04:00
goto end ;
}
content - > size + = sizeof ( struct box ) + sizeof ( struct css_style ) ;
if ( n - > type = = XML_TEXT_NODE & &
( parent_style - > white_space = = CSS_WHITE_SPACE_NORMAL | |
parent_style - > white_space = = CSS_WHITE_SPACE_NOWRAP ) ) {
char * text = squash_tolat1 ( n - > content ) ;
2003-03-26 00:51:29 +03:00
2003-07-05 01:17:53 +04:00
/* if the text is just a space, combine it with the preceding
* text node , if any */
2003-01-07 02:53:40 +03:00
if ( text [ 0 ] = = ' ' & & text [ 1 ] = = 0 ) {
if ( inline_container ! = 0 ) {
assert ( inline_container - > last ! = 0 ) ;
inline_container - > last - > space = 1 ;
}
xfree ( text ) ;
2003-09-20 01:23:19 +04:00
goto end ;
2002-12-31 01:56:30 +03:00
}
2003-07-05 01:17:53 +04:00
2003-10-08 01:34:39 +04:00
if ( inline_container = = 0 ) {
/* this is the first inline node: make a container */
2004-01-02 15:04:04 +03:00
inline_container = box_create ( 0 , 0 , 0 ,
content - > data . html . box_pool ) ;
2003-10-08 01:34:39 +04:00
inline_container - > type = BOX_INLINE_CONTAINER ;
box_add_child ( parent , inline_container ) ;
}
2004-01-02 15:04:04 +03:00
box = box_create ( parent_style , status . href , title ,
content - > data . html . box_pool ) ;
2003-10-25 04:35:49 +04:00
box - > text = text ;
2003-09-20 01:23:19 +04:00
box - > style_clone = 1 ;
2003-07-05 01:17:53 +04:00
box - > length = strlen ( text ) ;
if ( text [ box - > length - 1 ] = = ' ' ) {
box - > space = 1 ;
box - > length - - ;
}
2004-02-01 00:18:44 +03:00
switch ( parent_style - > text_transform ) {
/* perform text-transform */
unsigned int ch ;
case CSS_TEXT_TRANSFORM_UPPERCASE :
for ( ch = 0 ; ch ! = box - > length ; ch + + ) {
box - > text [ ch ] = toupper ( box - > text [ ch ] ) ;
}
break ;
case CSS_TEXT_TRANSFORM_LOWERCASE :
for ( ch = 0 ; ch ! = box - > length ; ch + + ) {
box - > text [ ch ] = tolower ( box - > text [ ch ] ) ;
}
break ;
case CSS_TEXT_TRANSFORM_CAPITALIZE :
for ( ch = 0 ; ch ! = box - > length ; ch + + ) {
2004-02-01 07:45:55 +03:00
if ( ch = = 0 ) { /* first char in box */
if ( inline_container & & ( inline_container - > last - > text & & inline_container - > last - > space ) ) { /* end of previous box */
box - > text [ ch ] = toupper ( box - > text [ ch ] ) ;
}
else if ( inline_container & & ( inline_container - > last - > prev & & inline_container - > last - > prev - > text & & inline_container - > last - > prev - > space ) ) { /* end of box before previous box */
box - > text [ ch ] = toupper ( box - > text [ ch ] ) ;
}
2004-02-01 00:18:44 +03:00
}
else if ( ! ( ( box - > text [ ch - 1 ] > 64 & & box - > text [ ch - 1 ] < 91 ) | |
( box - > text [ ch - 1 ] > 96 & & box - > text [ ch - 1 ] < 123 ) ) ) {
box - > text [ ch ] = toupper ( box - > text [ ch ] ) ;
}
}
break ;
default :
break ;
}
2003-10-08 01:34:39 +04:00
if ( parent_style - > white_space = = CSS_WHITE_SPACE_NOWRAP ) {
2003-12-27 05:03:48 +03:00
unsigned int i ;
2003-10-08 01:34:39 +04:00
for ( i = 0 ; i ! = box - > length ; i + + )
if ( text [ i ] = = ' ' )
text [ i ] = 160 ;
}
2003-07-05 01:17:53 +04:00
box - > font = font_open ( content - > data . html . fonts , box - > style ) ;
2003-10-08 01:34:39 +04:00
box_add_child ( inline_container , box ) ;
if ( text [ 0 ] = = ' ' ) {
box - > length - - ;
memmove ( text , text + 1 , box - > length ) ;
if ( box - > prev ! = 0 )
box - > prev - > space = 1 ;
}
2003-09-20 01:23:19 +04:00
goto end ;
2003-01-07 02:53:40 +03:00
2003-10-08 01:34:39 +04:00
} else if ( n - > type = = XML_TEXT_NODE ) {
/* white-space: pre */
char * text = tolat1_pre ( n - > content ) ;
char * current ;
assert ( parent_style - > white_space = = CSS_WHITE_SPACE_PRE ) ;
for ( current = text ; * current ; current + + )
if ( * current = = ' ' | | * current = = ' \t ' )
* current = 160 ;
current = text ;
do {
size_t len = strcspn ( current , " \r \n " ) ;
char old = current [ len ] ;
current [ len ] = 0 ;
2003-10-08 03:47:57 +04:00
if ( ! inline_container ) {
2004-01-02 15:04:04 +03:00
inline_container = box_create ( 0 , 0 , 0 ,
content - > data . html . box_pool ) ;
2003-10-08 01:34:39 +04:00
inline_container - > type = BOX_INLINE_CONTAINER ;
2003-10-08 03:47:57 +04:00
box_add_child ( parent , inline_container ) ;
2003-10-08 01:34:39 +04:00
}
2004-01-02 15:04:04 +03:00
box = box_create ( parent_style , status . href , title ,
content - > data . html . box_pool ) ;
2003-10-08 01:34:39 +04:00
box - > type = BOX_INLINE ;
box - > style_clone = 1 ;
box - > text = xstrdup ( current ) ;
box - > length = strlen ( box - > text ) ;
2004-02-01 00:18:44 +03:00
switch ( parent_style - > text_transform ) {
/* perform text-transform */
unsigned int ch ;
case CSS_TEXT_TRANSFORM_UPPERCASE :
for ( ch = 0 ; ch ! = box - > length ; ch + + ) {
box - > text [ ch ] =
toupper ( box - > text [ ch ] ) ;
}
break ;
case CSS_TEXT_TRANSFORM_LOWERCASE :
for ( ch = 0 ; ch ! = box - > length ; ch + + ) {
box - > text [ ch ] =
tolower ( box - > text [ ch ] ) ;
}
break ;
case CSS_TEXT_TRANSFORM_CAPITALIZE :
for ( ch = 0 ; ch ! = box - > length ; ch + + ) {
2004-02-01 07:45:55 +03:00
if ( ch = = 0 ) { /* first char in box */
if ( inline_container & & ( inline_container - > last - > text & & inline_container - > last - > space ) ) { /* end of previous box */
box - > text [ ch ] = toupper ( box - > text [ ch ] ) ;
}
else if ( inline_container & & ( inline_container - > last - > prev & & inline_container - > last - > prev - > text & & inline_container - > last - > prev - > space ) ) { /* end of box before previous box */
box - > text [ ch ] = toupper ( box - > text [ ch ] ) ;
}
2004-02-01 00:18:44 +03:00
}
else if ( ! ( ( box - > text [ ch - 1 ] > 64 & & box - > text [ ch - 1 ] < 91 ) | |
( box - > text [ ch - 1 ] > 96 & & box - > text [ ch - 1 ] < 123 ) ) ) {
box - > text [ ch ] =
toupper ( box - > text [ ch ] ) ;
}
}
break ;
default :
break ;
}
2003-10-08 01:34:39 +04:00
box - > font = font_open ( content - > data . html . fonts , box - > style ) ;
box_add_child ( inline_container , box ) ;
current [ len ] = old ;
current + = len ;
2003-10-08 03:47:57 +04:00
if ( current [ 0 ] = = ' \r ' & & current [ 1 ] = = ' \n ' ) {
2003-10-08 01:34:39 +04:00
current + = 2 ;
2003-10-08 03:47:57 +04:00
inline_container = 0 ;
} else if ( current [ 0 ] ! = 0 ) {
2003-10-08 01:34:39 +04:00
current + + ;
2003-10-08 03:47:57 +04:00
inline_container = 0 ;
}
2003-10-08 01:34:39 +04:00
} while ( * current ) ;
xfree ( text ) ;
goto end ;
2003-07-05 01:17:53 +04:00
2003-10-08 01:34:39 +04:00
} else if ( box - > type = = BOX_INLINE | |
2003-09-22 02:47:08 +04:00
box - > type = = BOX_INLINE_BLOCK | |
2003-07-05 01:17:53 +04:00
style - > float_ = = CSS_FLOAT_LEFT | |
style - > float_ = = CSS_FLOAT_RIGHT ) {
/* this is an inline box */
2003-01-07 02:53:40 +03:00
if ( inline_container = = 0 ) {
2003-01-02 16:26:43 +03:00
/* this is the first inline node: make a container */
2004-01-02 15:04:04 +03:00
inline_container = box_create ( 0 , 0 , 0 ,
content - > data . html . box_pool ) ;
2002-05-22 01:32:35 +04:00
inline_container - > type = BOX_INLINE_CONTAINER ;
box_add_child ( parent , inline_container ) ;
}
2003-01-07 02:53:40 +03:00
2003-10-08 01:34:39 +04:00
if ( box - > type = = BOX_INLINE ) {
2003-07-05 20:16:15 +04:00
/* inline box: add to tree and recurse */
box_add_child ( inline_container , box ) ;
if ( convert_children ) {
for ( c = n - > children ; c ! = 0 ; c = c - > next )
inline_container = convert_xml_to_box ( c , content , style ,
2003-12-11 02:12:39 +03:00
parent , inline_container ,
2003-07-05 20:16:15 +04:00
status ) ;
}
2003-12-11 02:12:39 +03:00
LOG ( ( " node %p, node type %i END " , n , n - > type ) ) ;
2003-09-20 01:23:19 +04:00
goto end ;
2003-09-22 02:47:08 +04:00
} else if ( box - > type = = BOX_INLINE_BLOCK ) {
/* inline block box: add to tree and recurse */
box_add_child ( inline_container , box ) ;
if ( convert_children ) {
inline_container_c = 0 ;
for ( c = n - > children ; c ! = 0 ; c = c - > next )
inline_container_c = convert_xml_to_box ( c , content , style ,
2003-12-11 02:12:39 +03:00
box , inline_container_c ,
2003-09-22 02:47:08 +04:00
status ) ;
}
2003-12-11 02:12:39 +03:00
LOG ( ( " node %p, node type %i END " , n , n - > type ) ) ;
2003-09-22 02:47:08 +04:00
goto end ;
2003-07-05 01:17:53 +04:00
} else {
/* float: insert a float box between the parent and current node */
assert ( style - > float_ = = CSS_FLOAT_LEFT | | style - > float_ = = CSS_FLOAT_RIGHT ) ;
2003-01-07 02:53:40 +03:00
LOG ( ( " float " ) ) ;
2004-01-02 15:04:04 +03:00
parent = box_create ( 0 , status . href , title ,
content - > data . html . box_pool ) ;
2003-07-05 20:16:15 +04:00
if ( style - > float_ = = CSS_FLOAT_LEFT )
parent - > type = BOX_FLOAT_LEFT ;
else
parent - > type = BOX_FLOAT_RIGHT ;
2003-01-07 02:53:40 +03:00
box_add_child ( inline_container , parent ) ;
2003-09-22 02:47:08 +04:00
if ( box - > type = = BOX_INLINE | | box - > type = = BOX_INLINE_BLOCK )
2003-07-05 23:51:10 +04:00
box - > type = BOX_BLOCK ;
2002-05-05 01:17:06 +04:00
}
2002-06-29 00:14:04 +04:00
}
2002-05-05 01:17:06 +04:00
2003-07-05 01:17:53 +04:00
assert ( n - > type = = XML_ELEMENT_NODE ) ;
2003-07-05 20:16:15 +04:00
assert ( CSS_DISPLAY_INLINE < style - > display & &
style - > display < CSS_DISPLAY_NONE ) ;
/* non-inline box: add to tree and recurse */
box_add_child ( parent , box ) ;
if ( convert_children ) {
inline_container_c = 0 ;
for ( c = n - > children ; c ! = 0 ; c = c - > next )
inline_container_c = convert_xml_to_box ( c , content , style ,
2003-12-11 02:12:39 +03:00
box , inline_container_c ,
2003-07-05 20:16:15 +04:00
status ) ;
}
if ( style - > float_ = = CSS_FLOAT_NONE )
/* new inline container unless this is a float */
inline_container = 0 ;
2003-07-05 01:17:53 +04:00
2003-07-05 20:16:15 +04:00
if ( ( s = ( char * ) xmlGetProp ( n , ( const xmlChar * ) " colspan " ) ) ) {
if ( ( box - > columns = strtol ( s , 0 , 10 ) ) = = 0 )
box - > columns = 1 ;
xmlFree ( s ) ;
}
2003-07-05 23:51:10 +04:00
if ( ( s = ( char * ) xmlGetProp ( n , ( const xmlChar * ) " rowspan " ) ) ) {
if ( ( box - > rows = strtol ( s , 0 , 10 ) ) = = 0 )
box - > rows = 1 ;
xmlFree ( s ) ;
}
2002-05-04 23:57:18 +04:00
2003-09-20 01:23:19 +04:00
end :
free ( title ) ;
if ( ! href_in )
xmlFree ( status . href ) ;
2003-12-11 02:12:39 +03:00
LOG ( ( " node %p, node type %i END " , n , n - > type ) ) ;
2002-05-04 23:57:18 +04:00
return inline_container ;
}
2002-09-08 22:11:56 +04:00
/**
2003-07-05 01:17:53 +04:00
* Get the style for an element
*
* The style is collected from three sources :
* 1. any styles for this element in the document stylesheet ( s )
* 2. non - CSS HTML attributes
* 3. the ' style ' attribute
2002-05-22 01:32:35 +04:00
*/
2003-04-06 01:38:06 +04:00
struct css_style * box_get_style ( struct content * * stylesheet ,
unsigned int stylesheet_count , struct css_style * parent_style ,
2003-12-11 02:12:39 +03:00
xmlNode * n )
2002-05-22 01:32:35 +04:00
{
struct css_style * style = xcalloc ( 1 , sizeof ( struct css_style ) ) ;
2004-01-02 15:04:04 +03:00
struct css_style style_new ;
2002-06-26 16:19:24 +04:00
char * s ;
2003-04-06 01:38:06 +04:00
unsigned int i ;
2002-05-22 01:32:35 +04:00
memcpy ( style , parent_style , sizeof ( struct css_style ) ) ;
2004-01-02 15:04:04 +03:00
memcpy ( & style_new , & css_blank_style , sizeof ( struct css_style ) ) ;
2003-04-06 01:38:06 +04:00
for ( i = 0 ; i ! = stylesheet_count ; i + + ) {
if ( stylesheet [ i ] ! = 0 ) {
assert ( stylesheet [ i ] - > type = = CONTENT_CSS ) ;
2004-01-02 15:04:04 +03:00
css_get_style ( stylesheet [ i ] , n , & style_new ) ;
2003-04-06 01:38:06 +04:00
}
}
2004-01-02 15:04:04 +03:00
css_cascade ( style , & style_new ) ;
2002-05-22 01:32:35 +04:00
2003-01-08 02:15:23 +03:00
if ( ( s = ( char * ) xmlGetProp ( n , ( const xmlChar * ) " bgcolor " ) ) ) {
2002-12-27 23:35:32 +03:00
unsigned int r , g , b ;
if ( s [ 0 ] = = ' # ' & & sscanf ( s + 1 , " %2x%2x%2x " , & r , & g , & b ) = = 3 )
style - > background_color = ( b < < 16 ) | ( g < < 8 ) | r ;
2003-04-13 16:50:10 +04:00
else if ( s [ 0 ] ! = ' # ' )
style - > background_color = named_colour ( s ) ;
2003-04-25 12:03:15 +04:00
xmlFree ( s ) ;
2002-12-27 23:35:32 +03:00
}
2003-01-08 02:15:23 +03:00
if ( ( s = ( char * ) xmlGetProp ( n , ( const xmlChar * ) " color " ) ) ) {
2002-12-27 23:35:32 +03:00
unsigned int r , g , b ;
if ( s [ 0 ] = = ' # ' & & sscanf ( s + 1 , " %2x%2x%2x " , & r , & g , & b ) = = 3 )
style - > color = ( b < < 16 ) | ( g < < 8 ) | r ;
2003-04-13 16:50:10 +04:00
else if ( s [ 0 ] ! = ' # ' )
style - > color = named_colour ( s ) ;
2003-04-25 12:03:15 +04:00
xmlFree ( s ) ;
2002-12-27 23:35:32 +03:00
}
2003-01-08 02:15:23 +03:00
if ( ( s = ( char * ) xmlGetProp ( n , ( const xmlChar * ) " height " ) ) ) {
2003-08-28 00:09:57 +04:00
float value = atof ( s ) ;
if ( value < 0 ) {
/* ignore negative values */
} else if ( strrchr ( s , ' % ' ) ) {
2003-07-17 18:26:15 +04:00
/*the specification doesn't make clear what
* percentage heights mean , so ignore them */
} else {
2003-08-28 00:09:57 +04:00
style - > height . height = CSS_HEIGHT_LENGTH ;
style - > height . length . unit = CSS_UNIT_PX ;
style - > height . length . value = value ;
2003-07-15 22:06:31 +04:00
}
2003-04-25 12:03:15 +04:00
xmlFree ( s ) ;
2003-01-07 02:53:40 +03:00
}
2003-09-20 03:36:17 +04:00
if ( strcmp ( ( const char * ) n - > name , " input " ) = = 0 ) {
if ( ( s = ( char * ) xmlGetProp ( n , ( const xmlChar * ) " size " ) ) ) {
int size = atoi ( s ) ;
if ( 0 < size ) {
char * type = ( char * ) xmlGetProp ( n , ( const xmlChar * ) " type " ) ;
style - > width . width = CSS_WIDTH_LENGTH ;
if ( ! type | | stricmp ( type , " text " ) = = 0 | |
stricmp ( type , " password " ) = = 0 )
/* in characters for text or password */
style - > width . value . length . unit = CSS_UNIT_EX ;
else
/* in pixels otherwise */
style - > width . value . length . unit = CSS_UNIT_PX ;
style - > width . value . length . value = size ;
if ( type )
xmlFree ( type ) ;
}
xmlFree ( s ) ;
}
}
2003-01-08 02:24:43 +03:00
if ( strcmp ( ( const char * ) n - > name , " body " ) = = 0 ) {
if ( ( s = ( char * ) xmlGetProp ( n , ( const xmlChar * ) " text " ) ) ) {
unsigned int r , g , b ;
if ( s [ 0 ] = = ' # ' & & sscanf ( s + 1 , " %2x%2x%2x " , & r , & g , & b ) = = 3 )
style - > color = ( b < < 16 ) | ( g < < 8 ) | r ;
2003-04-13 16:50:10 +04:00
else if ( s [ 0 ] ! = ' # ' )
style - > color = named_colour ( s ) ;
2003-04-25 12:03:15 +04:00
xmlFree ( s ) ;
2003-01-08 02:24:43 +03:00
}
}
2003-01-08 02:15:23 +03:00
if ( ( s = ( char * ) xmlGetProp ( n , ( const xmlChar * ) " width " ) ) ) {
2003-08-28 00:09:57 +04:00
float value = atof ( s ) ;
if ( value < 0 ) {
/* ignore negative values */
} else if ( strrchr ( s , ' % ' ) ) {
2002-08-12 03:01:02 +04:00
style - > width . width = CSS_WIDTH_PERCENT ;
2003-08-28 00:09:57 +04:00
style - > width . value . percent = value ;
2002-08-12 03:01:02 +04:00
} else {
style - > width . width = CSS_WIDTH_LENGTH ;
style - > width . value . length . unit = CSS_UNIT_PX ;
2003-08-28 00:09:57 +04:00
style - > width . value . length . value = value ;
2002-08-12 03:01:02 +04:00
}
2003-04-25 12:03:15 +04:00
xmlFree ( s ) ;
2002-05-22 01:32:35 +04:00
}
2003-09-22 02:47:08 +04:00
if ( strcmp ( ( const char * ) n - > name , " textarea " ) = = 0 ) {
if ( ( s = ( char * ) xmlGetProp ( n , ( const xmlChar * ) " rows " ) ) ) {
int value = atoi ( s ) ;
if ( 0 < value ) {
style - > height . height = CSS_HEIGHT_LENGTH ;
style - > height . length . unit = CSS_UNIT_EM ;
style - > height . length . value = value ;
}
xmlFree ( s ) ;
}
if ( ( s = ( char * ) xmlGetProp ( n , ( const xmlChar * ) " cols " ) ) ) {
int value = atoi ( s ) ;
if ( 0 < value ) {
style - > width . width = CSS_WIDTH_LENGTH ;
style - > width . value . length . unit = CSS_UNIT_EX ;
style - > width . value . length . value = value ;
}
xmlFree ( s ) ;
}
}
2003-10-25 04:35:49 +04:00
2003-01-08 02:15:23 +03:00
if ( ( s = ( char * ) xmlGetProp ( n , ( const xmlChar * ) " style " ) ) ) {
2004-01-02 15:04:04 +03:00
struct css_style astyle ;
memcpy ( & astyle , & css_empty_style , sizeof ( struct css_style ) ) ;
css_parse_property_list ( & astyle , s ) ;
css_cascade ( style , & astyle ) ;
2003-04-25 12:03:15 +04:00
xmlFree ( s ) ;
2002-05-22 01:32:35 +04:00
}
return style ;
}
2004-01-24 20:08:16 +03:00
/*
2003-07-05 01:17:53 +04:00
* Special case elements
*
* These functions are called by convert_xml_to_box when an element is being
* converted , according to the entries in element_table ( top of file ) .
*
* The parameters are the xmlNode , a status structure for the conversion , and
* the style found for the element .
*
* If a box is created , it is returned in the result structure . The
* convert_children field should be 1 if convert_xml_to_box should convert the
* node ' s children recursively , 0 if it should ignore them ( presumably they
2003-07-05 20:16:15 +04:00
* have been processed in some way by the function ) . If box is 0 , no box will
* be created for that element , and convert_children must be 0.
2003-07-05 01:17:53 +04:00
*/
struct result box_a ( xmlNode * n , struct status * status ,
struct css_style * style )
{
2003-07-05 20:16:15 +04:00
struct box * box ;
2003-07-05 01:17:53 +04:00
char * s ;
if ( ( s = ( char * ) xmlGetProp ( n , ( const xmlChar * ) " href " ) ) )
status - > href = s ;
2004-01-02 15:04:04 +03:00
box = box_create ( style , status - > href , status - > title ,
status - > content - > data . html . box_pool ) ;
2003-07-05 20:16:15 +04:00
return ( struct result ) { box , 1 } ;
2003-07-05 01:17:53 +04:00
}
2003-08-31 01:45:03 +04:00
struct result box_body ( xmlNode * n , struct status * status ,
struct css_style * style )
{
struct box * box ;
status - > content - > data . html . background_colour = style - > background_color ;
2004-01-02 15:04:04 +03:00
box = box_create ( style , status - > href , status - > title ,
status - > content - > data . html . box_pool ) ;
2003-08-31 01:45:03 +04:00
return ( struct result ) { box , 1 } ;
}
2004-01-24 20:08:16 +03:00
static const content_type image_types [ ] = {
# ifdef riscos
CONTENT_JPEG , CONTENT_PNG , CONTENT_GIF , CONTENT_SPRITE , CONTENT_DRAW ,
# endif
CONTENT_UNKNOWN } ;
2003-07-05 01:17:53 +04:00
struct result box_image ( xmlNode * n , struct status * status ,
struct css_style * style )
{
struct box * box ;
2004-01-24 20:12:32 +03:00
char * s , * url , * s1 ;
2003-09-10 01:43:44 +04:00
xmlChar * s2 ;
2003-07-05 01:17:53 +04:00
2004-01-02 15:04:04 +03:00
box = box_create ( style , status - > href , status - > title ,
status - > content - > data . html . box_pool ) ;
2003-07-05 01:17:53 +04:00
/* handle alt text */
2003-09-10 01:43:44 +04:00
if ( ( s2 = xmlGetProp ( n , ( const xmlChar * ) " alt " ) ) ) {
2003-07-05 01:17:53 +04:00
box - > text = squash_tolat1 ( s2 ) ;
box - > length = strlen ( box - > text ) ;
2003-09-10 01:43:44 +04:00
box - > font = font_open ( status - > content - > data . html . fonts , style ) ;
2004-01-02 15:04:04 +03:00
xmlFree ( s2 ) ;
2003-09-10 01:43:44 +04:00
}
2003-07-05 01:17:53 +04:00
/* img without src is an error */
if ( ! ( s = ( char * ) xmlGetProp ( n , ( const xmlChar * ) " src " ) ) )
return ( struct result ) { box , 0 } ;
2004-01-24 20:12:32 +03:00
/* remove leading and trailing whitespace */
s1 = strip ( s ) ;
2004-01-24 19:41:52 +03:00
2004-01-24 20:12:32 +03:00
url = url_join ( s1 , status - > content - > data . html . base_url ) ;
2003-12-26 03:17:55 +03:00
if ( ! url )
return ( struct result ) { box , 0 } ;
2003-07-05 01:17:53 +04:00
LOG ( ( " image '%s' " , url ) ) ;
xmlFree ( s ) ;
/* start fetch */
2004-01-24 20:08:16 +03:00
html_fetch_object ( status - > content , url , box , image_types ) ;
2003-07-05 01:17:53 +04:00
return ( struct result ) { box , 0 } ;
}
struct result box_form ( xmlNode * n , struct status * status ,
struct css_style * style )
{
2003-10-25 18:13:49 +04:00
char * s , * s2 ;
2003-07-05 20:16:15 +04:00
struct box * box ;
2003-10-25 04:35:49 +04:00
struct form * form ;
2004-01-02 15:04:04 +03:00
box = box_create ( style , status - > href , status - > title ,
status - > content - > data . html . box_pool ) ;
2003-10-25 04:35:49 +04:00
2003-10-25 18:13:49 +04:00
s = ( char * ) xmlGetProp ( n , ( const xmlChar * ) " action " ) ;
if ( ! s ) {
/* the action attribute is required */
return ( struct result ) { box , 1 } ;
2003-10-25 04:35:49 +04:00
}
2003-10-25 18:13:49 +04:00
status - > current_form = form = xcalloc ( 1 , sizeof ( * form ) ) ;
form - > action = s ;
2003-10-25 04:35:49 +04:00
form - > method = method_GET ;
if ( ( s = ( char * ) xmlGetProp ( n , ( const xmlChar * ) " method " ) ) ) {
2003-10-25 18:13:49 +04:00
if ( strcasecmp ( s , " post " ) = = 0 ) {
form - > method = method_POST_URLENC ;
if ( ( s2 = ( char * ) xmlGetProp ( n , ( const xmlChar * ) " enctype " ) ) ) {
if ( strcasecmp ( s2 , " multipart/form-data " ) = = 0 )
form - > method = method_POST_MULTIPART ;
xmlFree ( s2 ) ;
}
}
2003-10-25 04:35:49 +04:00
xmlFree ( s ) ;
}
form - > controls = form - > last_control = 0 ;
2003-07-05 01:17:53 +04:00
add_form_element ( status - > elements , status - > current_form ) ;
2003-07-05 20:16:15 +04:00
return ( struct result ) { box , 1 } ;
2003-07-05 01:17:53 +04:00
}
struct result box_textarea ( xmlNode * n , struct status * status ,
struct css_style * style )
{
2003-09-22 02:47:08 +04:00
xmlChar * content , * current ;
struct box * box , * inline_container , * inline_box ;
2003-07-05 01:17:53 +04:00
char * s ;
2004-01-02 15:04:04 +03:00
box = box_create ( style , NULL , 0 ,
status - > content - > data . html . box_pool ) ;
2003-10-25 04:35:49 +04:00
box - > gadget = xcalloc ( 1 , sizeof ( struct form_control ) ) ;
2003-10-02 02:48:39 +04:00
box - > gadget - > box = box ;
2003-07-05 01:17:53 +04:00
box - > gadget - > type = GADGET_TEXTAREA ;
2003-10-27 03:34:09 +03:00
if ( status - > current_form )
form_add_control ( status - > current_form , box - > gadget ) ;
2003-12-11 22:06:39 +03:00
else
box - > gadget - > form = 0 ;
2003-09-27 03:22:00 +04:00
style - > display = CSS_DISPLAY_INLINE_BLOCK ;
2003-07-05 01:17:53 +04:00
2003-09-22 02:47:08 +04:00
/* split the content at newlines and make an inline container with an
* inline box for each line */
current = content = xmlNodeGetContent ( n ) ;
2003-09-23 01:55:08 +04:00
do {
2003-09-22 02:47:08 +04:00
size_t len = strcspn ( current , " \r \n " ) ;
char old = current [ len ] ;
current [ len ] = 0 ;
2004-01-02 15:04:04 +03:00
inline_container = box_create ( 0 , 0 , 0 ,
status - > content - > data . html . box_pool ) ;
2003-09-22 02:47:08 +04:00
inline_container - > type = BOX_INLINE_CONTAINER ;
2004-01-02 15:04:04 +03:00
inline_box = box_create ( style , 0 , 0 ,
status - > content - > data . html . box_pool ) ;
2003-09-22 02:47:08 +04:00
inline_box - > type = BOX_INLINE ;
inline_box - > style_clone = 1 ;
inline_box - > text = tolat1 ( current ) ;
inline_box - > length = strlen ( inline_box - > text ) ;
inline_box - > font = font_open ( status - > content - > data . html . fonts , style ) ;
box_add_child ( inline_container , inline_box ) ;
box_add_child ( box , inline_container ) ;
current [ len ] = old ;
current + = len ;
2003-10-08 01:34:39 +04:00
if ( current [ 0 ] = = ' \r ' & & current [ 1 ] = = ' \n ' )
current + = 2 ;
2003-10-26 01:50:49 +04:00
else if ( current [ 0 ] ! = 0 )
2003-10-08 01:34:39 +04:00
current + + ;
2003-09-23 01:55:08 +04:00
} while ( * current ) ;
2003-09-22 02:47:08 +04:00
xmlFree ( content ) ;
2003-07-05 01:17:53 +04:00
if ( ( s = ( char * ) xmlGetProp ( n , ( const xmlChar * ) " name " ) ) )
{
box - > gadget - > name = s ;
}
add_gadget_element ( status - > elements , box - > gadget ) ;
return ( struct result ) { box , 0 } ;
}
struct result box_select ( xmlNode * n , struct status * status ,
struct css_style * style )
{
2003-10-02 02:48:39 +04:00
struct box * box ;
struct box * inline_container ;
struct box * inline_box ;
2003-10-25 04:35:49 +04:00
struct form_control * gadget = xcalloc ( 1 , sizeof ( struct form_control ) ) ;
2003-07-05 01:17:53 +04:00
char * s ;
2003-10-02 02:48:39 +04:00
xmlNode * c , * c2 ;
2003-07-05 01:17:53 +04:00
2003-10-02 02:48:39 +04:00
gadget - > type = GADGET_SELECT ;
2003-10-27 03:34:09 +03:00
if ( status - > current_form )
form_add_control ( status - > current_form , gadget ) ;
2003-12-11 22:06:39 +03:00
else
gadget - > form = 0 ;
2003-07-05 01:17:53 +04:00
2003-10-02 02:48:39 +04:00
gadget - > data . select . multiple = false ;
2003-07-05 01:17:53 +04:00
if ( ( s = ( char * ) xmlGetProp ( n , ( const xmlChar * ) " multiple " ) ) ) {
2003-10-02 02:48:39 +04:00
gadget - > data . select . multiple = true ;
xmlFree ( s ) ;
2003-07-05 01:17:53 +04:00
}
2003-10-02 02:48:39 +04:00
gadget - > data . select . items = NULL ;
gadget - > data . select . last_item = NULL ;
gadget - > data . select . num_items = 0 ;
gadget - > data . select . num_selected = 0 ;
2003-07-05 01:17:53 +04:00
for ( c = n - > children ; c ! = 0 ; c = c - > next ) {
if ( strcmp ( ( const char * ) c - > name , " option " ) = = 0 ) {
xmlChar * content = xmlNodeGetContent ( c ) ;
2003-10-02 02:48:39 +04:00
add_option ( c , gadget , squash_tolat1 ( content ) ) ;
2003-07-05 01:17:53 +04:00
xmlFree ( content ) ;
2003-10-02 02:48:39 +04:00
gadget - > data . select . num_items + + ;
} else if ( strcmp ( ( const char * ) c - > name , " optgroup " ) = = 0 ) {
for ( c2 = c - > children ; c2 ; c2 = c2 - > next ) {
if ( strcmp ( ( const char * ) c2 - > name , " option " ) = = 0 ) {
xmlChar * content = xmlNodeGetContent ( c2 ) ;
add_option ( c2 , gadget , squash_tolat1 ( content ) ) ;
xmlFree ( content ) ;
gadget - > data . select . num_items + + ;
}
}
2003-07-05 01:17:53 +04:00
}
}
2003-10-02 02:48:39 +04:00
if ( gadget - > data . select . num_items = = 0 ) {
/* no options: ignore entire select */
xfree ( gadget ) ;
return ( struct result ) { 0 , 0 } ;
}
if ( ( s = ( char * ) xmlGetProp ( n , ( const xmlChar * ) " name " ) ) ) {
gadget - > name = s ;
}
2004-01-02 15:04:04 +03:00
box = box_create ( style , NULL , 0 , status - > content - > data . html . box_pool ) ;
2003-10-02 02:48:39 +04:00
box - > gadget = gadget ;
gadget - > box = box ;
style - > display = CSS_DISPLAY_INLINE_BLOCK ;
2004-01-02 15:04:04 +03:00
inline_container = box_create ( 0 , 0 , 0 ,
status - > content - > data . html . box_pool ) ;
2003-10-02 02:48:39 +04:00
inline_container - > type = BOX_INLINE_CONTAINER ;
2004-01-02 15:04:04 +03:00
inline_box = box_create ( style , 0 , 0 ,
status - > content - > data . html . box_pool ) ;
2003-10-02 02:48:39 +04:00
inline_box - > type = BOX_INLINE ;
inline_box - > style_clone = 1 ;
box_add_child ( inline_container , inline_box ) ;
box_add_child ( box , inline_container ) ;
if ( ! gadget - > data . select . multiple & &
gadget - > data . select . num_selected = = 0 ) {
gadget - > data . select . current = gadget - > data . select . items ;
2003-10-02 15:13:21 +04:00
gadget - > data . select . current - > initial_selected =
gadget - > data . select . current - > selected = true ;
2003-10-02 02:48:39 +04:00
gadget - > data . select . num_selected = 1 ;
}
if ( gadget - > data . select . num_selected = = 0 )
inline_box - > text = xstrdup ( messages_get ( " Form_None " ) ) ;
else if ( gadget - > data . select . num_selected = = 1 )
inline_box - > text = xstrdup ( gadget - > data . select . current - > text ) ;
else
inline_box - > text = xstrdup ( messages_get ( " Form_Many " ) ) ;
inline_box - > length = strlen ( inline_box - > text ) ;
inline_box - > font = font_open ( status - > content - > data . html . fonts , style ) ;
add_gadget_element ( status - > elements , gadget ) ;
2003-07-05 01:17:53 +04:00
return ( struct result ) { box , 0 } ;
}
2003-10-25 04:35:49 +04:00
void add_option ( xmlNode * n , struct form_control * current_select , char * text )
2003-07-05 01:17:53 +04:00
{
2003-10-25 04:35:49 +04:00
struct form_option * option = xcalloc ( 1 , sizeof ( struct form_option ) ) ;
2003-10-02 02:48:39 +04:00
char * s , * c ;
2003-07-05 01:17:53 +04:00
assert ( current_select ! = 0 ) ;
if ( current_select - > data . select . items = = 0 )
current_select - > data . select . items = option ;
else
2003-10-02 02:48:39 +04:00
current_select - > data . select . last_item - > next = option ;
current_select - > data . select . last_item = option ;
2003-10-25 18:13:49 +04:00
if ( ( s = ( char * ) xmlGetProp ( n , ( const xmlChar * ) " value " ) ) ) {
option - > value = s ;
} else {
option - > value = xstrdup ( text ) ;
}
2003-10-02 02:48:39 +04:00
for ( c = text ; * c ; c + + )
if ( * c = = ' ' )
* c = 160 ;
2003-07-05 01:17:53 +04:00
2003-10-02 02:48:39 +04:00
option - > selected = option - > initial_selected = false ;
2003-07-05 01:17:53 +04:00
option - > text = text ;
if ( ( s = ( char * ) xmlGetProp ( n , ( const xmlChar * ) " selected " ) ) ) {
xmlFree ( s ) ;
2003-10-02 02:48:39 +04:00
if ( current_select - > data . select . num_selected = = 0 | |
current_select - > data . select . multiple ) {
option - > selected = option - > initial_selected = true ;
current_select - > data . select . num_selected + + ;
current_select - > data . select . current = option ;
}
2003-07-05 01:17:53 +04:00
}
}
struct result box_input ( xmlNode * n , struct status * status ,
struct css_style * style )
{
struct box * box = 0 ;
2003-10-25 04:35:49 +04:00
struct form_control * gadget = 0 ;
2003-09-09 23:25:28 +04:00
char * s , * type , * url ;
2003-07-05 01:17:53 +04:00
type = ( char * ) xmlGetProp ( n , ( const xmlChar * ) " type " ) ;
/* the default type is "text" */
2003-09-09 23:25:28 +04:00
if ( type = = 0 | | stricmp ( type , " text " ) = = 0 )
2003-07-05 01:17:53 +04:00
{
2003-09-29 03:41:07 +04:00
box = box_input_text ( n , status , style , false ) ;
gadget = box - > gadget ;
2003-10-02 02:48:39 +04:00
gadget - > box = box ;
2003-09-09 23:25:28 +04:00
}
2003-09-11 02:40:32 +04:00
else if ( stricmp ( type , " password " ) = = 0 )
2003-09-09 23:25:28 +04:00
{
2003-09-29 03:41:07 +04:00
box = box_input_text ( n , status , style , true ) ;
gadget = box - > gadget ;
2003-10-02 02:48:39 +04:00
gadget - > box = box ;
2003-07-05 01:17:53 +04:00
}
else if ( stricmp ( type , " hidden " ) = = 0 )
{
2003-07-05 20:16:15 +04:00
/* no box for hidden inputs */
2003-10-25 04:35:49 +04:00
gadget = xcalloc ( 1 , sizeof ( struct form_control ) ) ;
2003-07-05 01:17:53 +04:00
gadget - > type = GADGET_HIDDEN ;
if ( ( s = ( char * ) xmlGetProp ( n , ( const xmlChar * ) " value " ) ) )
2003-10-25 04:35:49 +04:00
gadget - > value = s ;
2003-07-05 01:17:53 +04:00
}
else if ( stricmp ( type , " checkbox " ) = = 0 | | stricmp ( type , " radio " ) = = 0 )
{
2004-01-02 15:04:04 +03:00
box = box_create ( style , NULL , 0 ,
status - > content - > data . html . box_pool ) ;
2003-10-25 04:35:49 +04:00
box - > gadget = gadget = xcalloc ( 1 , sizeof ( struct form_control ) ) ;
2003-10-02 02:48:39 +04:00
gadget - > box = box ;
2003-07-05 01:17:53 +04:00
if ( type [ 0 ] = = ' c ' | | type [ 0 ] = = ' C ' )
gadget - > type = GADGET_CHECKBOX ;
else
gadget - > type = GADGET_RADIO ;
if ( ( s = ( char * ) xmlGetProp ( n , ( const xmlChar * ) " checked " ) ) ) {
if ( gadget - > type = = GADGET_CHECKBOX )
gadget - > data . checkbox . selected = - 1 ;
else
gadget - > data . radio . selected = - 1 ;
xmlFree ( s ) ;
}
2003-10-25 04:35:49 +04:00
if ( ( s = ( char * ) xmlGetProp ( n , ( const xmlChar * ) " value " ) ) )
gadget - > value = s ;
2003-07-05 01:17:53 +04:00
}
else if ( stricmp ( type , " submit " ) = = 0 | | stricmp ( type , " reset " ) = = 0 )
{
2003-09-27 03:22:00 +04:00
struct result result = box_button ( n , status , style ) ;
struct box * inline_container , * inline_box ;
box = result . box ;
2004-01-02 15:04:04 +03:00
inline_container = box_create ( 0 , 0 , 0 ,
status - > content - > data . html . box_pool ) ;
2003-09-27 03:22:00 +04:00
inline_container - > type = BOX_INLINE_CONTAINER ;
2004-01-02 15:04:04 +03:00
inline_box = box_create ( style , 0 , 0 ,
status - > content - > data . html . box_pool ) ;
2003-09-27 03:22:00 +04:00
inline_box - > type = BOX_INLINE ;
inline_box - > style_clone = 1 ;
if ( box - > gadget - > value )
inline_box - > text = tolat1 ( box - > gadget - > value ) ;
else if ( box - > gadget - > type = = GADGET_SUBMIT )
inline_box - > text = xstrdup ( messages_get ( " Form_Submit " ) ) ;
2003-07-05 01:17:53 +04:00
else
2003-09-27 03:22:00 +04:00
inline_box - > text = xstrdup ( messages_get ( " Form_Reset " ) ) ;
inline_box - > length = strlen ( inline_box - > text ) ;
inline_box - > font = font_open ( status - > content - > data . html . fonts , style ) ;
box_add_child ( inline_container , inline_box ) ;
box_add_child ( box , inline_container ) ;
2003-07-05 01:17:53 +04:00
}
2003-09-09 23:25:28 +04:00
else if ( stricmp ( type , " image " ) = = 0 )
{
2004-01-02 15:04:04 +03:00
box = box_create ( style , NULL , 0 ,
status - > content - > data . html . box_pool ) ;
2003-10-25 04:35:49 +04:00
box - > gadget = gadget = xcalloc ( 1 , sizeof ( struct form_control ) ) ;
2003-10-02 02:48:39 +04:00
gadget - > box = box ;
2003-09-09 23:25:28 +04:00
gadget - > type = GADGET_IMAGE ;
if ( ( s = ( char * ) xmlGetProp ( n , ( const xmlChar * ) " src " ) ) ) {
2003-12-26 03:17:55 +03:00
url = url_join ( s , status - > content - > data . html . base_url ) ;
if ( url )
2004-01-24 20:08:16 +03:00
html_fetch_object ( status - > content , url , box ,
image_types ) ;
2003-10-25 04:35:49 +04:00
xmlFree ( s ) ;
2003-09-09 23:25:28 +04:00
}
}
2003-07-05 01:17:53 +04:00
if ( type ! = 0 )
xmlFree ( type ) ;
if ( gadget ! = 0 ) {
2003-10-27 03:34:09 +03:00
if ( status - > current_form )
form_add_control ( status - > current_form , gadget ) ;
2003-12-11 22:06:39 +03:00
else
gadget - > form = 0 ;
2003-09-27 03:22:00 +04:00
gadget - > name = ( char * ) xmlGetProp ( n , ( const xmlChar * ) " name " ) ;
2003-07-05 01:17:53 +04:00
add_gadget_element ( status - > elements , gadget ) ;
}
return ( struct result ) { box , 0 } ;
}
2003-09-29 03:41:07 +04:00
struct box * box_input_text ( xmlNode * n , struct status * status ,
struct css_style * style , bool password )
{
char * s ;
unsigned int i ;
2004-01-02 15:04:04 +03:00
struct box * box = box_create ( style , 0 , 0 ,
status - > content - > data . html . box_pool ) ;
2003-09-29 03:41:07 +04:00
struct box * inline_container , * inline_box ;
style - > display = CSS_DISPLAY_INLINE_BLOCK ;
2003-10-25 04:35:49 +04:00
box - > gadget = xcalloc ( 1 , sizeof ( struct form_control ) ) ;
2003-10-02 02:48:39 +04:00
box - > gadget - > box = box ;
2003-09-29 03:41:07 +04:00
box - > gadget - > maxlength = 100 ;
if ( ( s = ( char * ) xmlGetProp ( n , ( const xmlChar * ) " maxlength " ) ) ) {
box - > gadget - > maxlength = atoi ( s ) ;
xmlFree ( s ) ;
}
s = ( char * ) xmlGetProp ( n , ( const xmlChar * ) " value " ) ;
box - > gadget - > value = s ? tolat1 ( s ) : xstrdup ( " " ) ;
box - > gadget - > initial_value = xstrdup ( box - > gadget - > value ) ;
if ( s )
xmlFree ( s ) ;
2004-01-02 15:04:04 +03:00
inline_container = box_create ( 0 , 0 , 0 ,
status - > content - > data . html . box_pool ) ;
2003-09-29 03:41:07 +04:00
inline_container - > type = BOX_INLINE_CONTAINER ;
2004-01-02 15:04:04 +03:00
inline_box = box_create ( style , 0 , 0 ,
status - > content - > data . html . box_pool ) ;
2003-09-29 03:41:07 +04:00
inline_box - > type = BOX_INLINE ;
inline_box - > style_clone = 1 ;
inline_box - > length = strlen ( box - > gadget - > value ) ;
if ( password ) {
box - > gadget - > type = GADGET_PASSWORD ;
inline_box - > text = xcalloc ( inline_box - > length + 1 , 1 ) ;
for ( i = 0 ; i ! = inline_box - > length ; i + + )
inline_box - > text [ i ] = ' * ' ;
} else {
box - > gadget - > type = GADGET_TEXTBOX ;
inline_box - > text = xstrdup ( box - > gadget - > value ) ;
/* replace spaces with hard spaces to prevent line wrapping */
for ( i = 0 ; i ! = inline_box - > length ; i + + )
if ( inline_box - > text [ i ] = = ' ' )
inline_box - > text [ i ] = 160 ;
}
inline_box - > font = font_open ( status - > content - > data . html . fonts , style ) ;
box_add_child ( inline_container , inline_box ) ;
box_add_child ( box , inline_container ) ;
return box ;
}
2003-09-27 03:22:00 +04:00
struct result box_button ( xmlNode * n , struct status * status ,
struct css_style * style )
{
char * type = ( char * ) xmlGetProp ( n , ( const xmlChar * ) " type " ) ;
2004-01-02 15:04:04 +03:00
struct box * box = box_create ( style , 0 , 0 ,
status - > content - > data . html . box_pool ) ;
2003-09-27 03:22:00 +04:00
style - > display = CSS_DISPLAY_INLINE_BLOCK ;
if ( ! type | | strcasecmp ( type , " submit " ) = = 0 ) {
2003-10-25 04:35:49 +04:00
box - > gadget = xcalloc ( 1 , sizeof ( struct form_control ) ) ;
2003-09-27 03:22:00 +04:00
box - > gadget - > type = GADGET_SUBMIT ;
} else if ( strcasecmp ( type , " reset " ) = = 0 ) {
2003-10-25 04:35:49 +04:00
box - > gadget = xcalloc ( 1 , sizeof ( struct form_control ) ) ;
2003-09-27 03:22:00 +04:00
box - > gadget - > type = GADGET_RESET ;
} else {
/* type="button" or unknown: just render the contents */
xmlFree ( type ) ;
return ( struct result ) { box , 1 } ;
}
if ( type )
xmlFree ( type ) ;
2003-10-27 03:34:09 +03:00
if ( status - > current_form )
form_add_control ( status - > current_form , box - > gadget ) ;
2003-12-11 22:06:39 +03:00
else
box - > gadget - > form = 0 ;
2003-10-02 02:48:39 +04:00
box - > gadget - > box = box ;
2003-09-27 03:22:00 +04:00
box - > gadget - > name = ( char * ) xmlGetProp ( n , ( const xmlChar * ) " name " ) ;
box - > gadget - > value = ( char * ) xmlGetProp ( n , ( const xmlChar * ) " value " ) ;
return ( struct result ) { box , 1 } ;
}
2003-07-05 01:17:53 +04:00
2002-09-08 22:11:56 +04:00
/**
2002-05-04 23:57:18 +04:00
* print a box tree to standard output
*/
void box_dump ( struct box * box , unsigned int depth )
{
unsigned int i ;
struct box * c ;
2002-06-19 01:24:21 +04:00
2002-05-04 23:57:18 +04:00
for ( i = 0 ; i < depth ; i + + )
2002-06-19 01:24:21 +04:00
fprintf ( stderr , " " ) ;
2002-05-04 23:57:18 +04:00
2002-06-19 01:24:21 +04:00
fprintf ( stderr , " x%li y%li w%li h%li " , box - > x , box - > y , box - > width , box - > height ) ;
2003-12-27 05:03:48 +03:00
if ( ( unsigned long ) box - > max_width ! = UNKNOWN_MAX_WIDTH )
2002-09-18 23:36:28 +04:00
fprintf ( stderr , " min%lu max%lu " , box - > min_width , box - > max_width ) ;
2002-05-04 23:57:18 +04:00
switch ( box - > type ) {
2002-06-27 03:27:30 +04:00
case BOX_BLOCK : fprintf ( stderr , " BOX_BLOCK " ) ; break ;
2002-06-19 01:24:21 +04:00
case BOX_INLINE_CONTAINER : fprintf ( stderr , " BOX_INLINE_CONTAINER " ) ; break ;
2003-09-10 01:43:44 +04:00
case BOX_INLINE : fprintf ( stderr , " BOX_INLINE " ) ; break ;
2003-09-22 02:47:08 +04:00
case BOX_INLINE_BLOCK : fprintf ( stderr , " BOX_INLINE_BLOCK " ) ; break ;
2002-06-27 03:27:30 +04:00
case BOX_TABLE : fprintf ( stderr , " BOX_TABLE " ) ; break ;
case BOX_TABLE_ROW : fprintf ( stderr , " BOX_TABLE_ROW " ) ; break ;
2002-09-18 23:36:28 +04:00
case BOX_TABLE_CELL : fprintf ( stderr , " BOX_TABLE_CELL [columns %i] " ,
box - > columns ) ; break ;
2002-08-18 20:46:45 +04:00
case BOX_TABLE_ROW_GROUP : fprintf ( stderr , " BOX_TABLE_ROW_GROUP " ) ; break ;
2002-06-29 00:14:04 +04:00
case BOX_FLOAT_LEFT : fprintf ( stderr , " BOX_FLOAT_LEFT " ) ; break ;
case BOX_FLOAT_RIGHT : fprintf ( stderr , " BOX_FLOAT_RIGHT " ) ; break ;
2002-06-19 01:24:21 +04:00
default : fprintf ( stderr , " Unknown box type " ) ;
2002-05-04 23:57:18 +04:00
}
2003-09-10 01:43:44 +04:00
if ( box - > text )
fprintf ( stderr , " '%.*s' " , ( int ) box - > length , box - > text ) ;
2004-02-01 07:45:55 +03:00
if ( box - > space )
fprintf ( stderr , " space " ) ;
2003-09-10 01:43:44 +04:00
if ( box - > object )
fprintf ( stderr , " (object '%s') " , box - > object - > url ) ;
2002-06-19 01:24:21 +04:00
if ( box - > style )
css_dump_style ( box - > style ) ;
2002-08-12 03:01:02 +04:00
if ( box - > href ! = 0 )
2003-09-10 01:43:44 +04:00
fprintf ( stderr , " -> '%s' " , box - > href ) ;
2003-07-01 02:21:51 +04:00
if ( box - > title ! = 0 )
2003-09-10 01:43:44 +04:00
fprintf ( stderr , " [%s] " , box - > title ) ;
2002-06-19 01:24:21 +04:00
fprintf ( stderr , " \n " ) ;
2002-05-04 23:57:18 +04:00
for ( c = box - > children ; c ! = 0 ; c = c - > next )
box_dump ( c , depth + 1 ) ;
}
2002-08-18 20:46:45 +04:00
2002-09-08 22:11:56 +04:00
/**
* ensure the box tree is correctly nested
2003-01-02 16:26:43 +03:00
*
* parent permitted child nodes
2003-09-22 02:47:08 +04:00
* BLOCK , INLINE_BLOCK BLOCK , INLINE_CONTAINER , TABLE
* INLINE_CONTAINER INLINE , INLINE_BLOCK , FLOAT_LEFT , FLOAT_RIGHT
2003-01-02 16:26:43 +03:00
* INLINE none
* TABLE at least 1 TABLE_ROW_GROUP
* TABLE_ROW_GROUP at least 1 TABLE_ROW
* TABLE_ROW at least 1 TABLE_CELL
* TABLE_CELL BLOCK , INLINE_CONTAINER , TABLE ( same as BLOCK )
* FLOAT_ ( LEFT | RIGHT ) exactly 1 BLOCK or TABLE
2002-08-18 20:46:45 +04:00
*/
2004-01-02 15:04:04 +03:00
void box_normalise_block ( struct box * block , pool box_pool )
2002-08-18 20:46:45 +04:00
{
struct box * child ;
2003-01-02 16:26:43 +03:00
struct box * next_child ;
2002-08-18 20:46:45 +04:00
struct box * table ;
struct css_style * style ;
2003-01-02 16:26:43 +03:00
assert ( block ! = 0 ) ;
2003-09-22 02:47:08 +04:00
assert ( block - > type = = BOX_BLOCK | | block - > type = = BOX_INLINE_BLOCK | |
block - > type = = BOX_TABLE_CELL ) ;
2003-01-08 02:15:23 +03:00
LOG ( ( " block %p, block->type %u " , block , block - > type ) ) ;
2003-07-05 01:17:53 +04:00
gui_multitask ( ) ;
2002-08-18 20:46:45 +04:00
2003-01-02 16:26:43 +03:00
for ( child = block - > children ; child ! = 0 ; child = next_child ) {
LOG ( ( " child %p, child->type = %d " , child , child - > type ) ) ;
next_child = child - > next ; /* child may be destroyed */
2002-08-18 20:46:45 +04:00
switch ( child - > type ) {
case BOX_BLOCK :
/* ok */
2004-01-02 15:04:04 +03:00
box_normalise_block ( child , box_pool ) ;
2002-08-18 20:46:45 +04:00
break ;
case BOX_INLINE_CONTAINER :
2004-01-02 15:04:04 +03:00
box_normalise_inline_container ( child , box_pool ) ;
2002-08-18 20:46:45 +04:00
break ;
case BOX_TABLE :
2004-01-02 15:04:04 +03:00
box_normalise_table ( child , box_pool ) ;
2002-08-18 20:46:45 +04:00
break ;
case BOX_INLINE :
2003-09-22 02:47:08 +04:00
case BOX_INLINE_BLOCK :
2002-08-18 20:46:45 +04:00
case BOX_FLOAT_LEFT :
case BOX_FLOAT_RIGHT :
/* should have been wrapped in inline
container by convert_xml_to_box ( ) */
assert ( 0 ) ;
break ;
case BOX_TABLE_ROW_GROUP :
case BOX_TABLE_ROW :
case BOX_TABLE_CELL :
/* insert implied table */
style = xcalloc ( 1 , sizeof ( struct css_style ) ) ;
memcpy ( style , block - > style , sizeof ( struct css_style ) ) ;
css_cascade ( style , & css_blank_style ) ;
2004-01-02 15:04:04 +03:00
table = box_create ( style , block - > href , 0 , box_pool ) ;
2003-07-05 20:16:15 +04:00
table - > type = BOX_TABLE ;
2003-01-02 16:26:43 +03:00
if ( child - > prev = = 0 )
2002-08-18 20:46:45 +04:00
block - > children = table ;
else
2003-01-02 16:26:43 +03:00
child - > prev - > next = table ;
table - > prev = child - > prev ;
2002-08-18 20:46:45 +04:00
while ( child ! = 0 & & (
child - > type = = BOX_TABLE_ROW_GROUP | |
child - > type = = BOX_TABLE_ROW | |
child - > type = = BOX_TABLE_CELL ) ) {
box_add_child ( table , child ) ;
child = child - > next ;
}
2003-01-02 16:26:43 +03:00
table - > last - > next = 0 ;
table - > next = next_child = child ;
2002-09-18 23:36:28 +04:00
table - > parent = block ;
2004-01-02 15:04:04 +03:00
box_normalise_table ( table , box_pool ) ;
2002-08-18 20:46:45 +04:00
break ;
default :
assert ( 0 ) ;
}
}
2003-01-02 16:26:43 +03:00
LOG ( ( " block %p done " , block ) ) ;
2002-08-18 20:46:45 +04:00
}
2004-01-02 15:04:04 +03:00
void box_normalise_table ( struct box * table , pool box_pool )
2002-08-18 20:46:45 +04:00
{
struct box * child ;
2003-01-02 16:26:43 +03:00
struct box * next_child ;
2002-08-18 20:46:45 +04:00
struct box * row_group ;
struct css_style * style ;
2003-07-07 01:10:12 +04:00
unsigned int * row_span = xcalloc ( 2 , sizeof ( row_span [ 0 ] ) ) ;
2003-07-20 17:12:38 +04:00
unsigned int table_columns = 1 ;
2002-08-18 20:46:45 +04:00
2003-01-02 16:26:43 +03:00
assert ( table ! = 0 ) ;
2002-08-18 20:46:45 +04:00
assert ( table - > type = = BOX_TABLE ) ;
2003-01-02 16:26:43 +03:00
LOG ( ( " table %p " , table ) ) ;
2003-07-07 01:10:12 +04:00
row_span [ 0 ] = row_span [ 1 ] = 0 ;
2002-08-18 20:46:45 +04:00
2003-01-02 16:26:43 +03:00
for ( child = table - > children ; child ! = 0 ; child = next_child ) {
next_child = child - > next ;
2002-08-18 20:46:45 +04:00
switch ( child - > type ) {
case BOX_TABLE_ROW_GROUP :
/* ok */
2003-07-07 01:10:12 +04:00
box_normalise_table_row_group ( child , & row_span ,
2004-01-02 15:04:04 +03:00
& table_columns , box_pool ) ;
2002-08-18 20:46:45 +04:00
break ;
case BOX_BLOCK :
case BOX_INLINE_CONTAINER :
case BOX_TABLE :
case BOX_TABLE_ROW :
case BOX_TABLE_CELL :
/* insert implied table row group */
style = xcalloc ( 1 , sizeof ( struct css_style ) ) ;
memcpy ( style , table - > style , sizeof ( struct css_style ) ) ;
css_cascade ( style , & css_blank_style ) ;
2004-01-02 15:04:04 +03:00
row_group = box_create ( style , table - > href , 0 ,
box_pool ) ;
2003-07-05 20:16:15 +04:00
row_group - > type = BOX_TABLE_ROW_GROUP ;
2003-01-02 16:26:43 +03:00
if ( child - > prev = = 0 )
2002-08-18 20:46:45 +04:00
table - > children = row_group ;
else
2003-01-02 16:26:43 +03:00
child - > prev - > next = row_group ;
row_group - > prev = child - > prev ;
2002-08-18 20:46:45 +04:00
while ( child ! = 0 & & (
child - > type = = BOX_BLOCK | |
child - > type = = BOX_INLINE_CONTAINER | |
child - > type = = BOX_TABLE | |
child - > type = = BOX_TABLE_ROW | |
child - > type = = BOX_TABLE_CELL ) ) {
box_add_child ( row_group , child ) ;
child = child - > next ;
}
2003-01-02 16:26:43 +03:00
row_group - > last - > next = 0 ;
row_group - > next = next_child = child ;
2002-09-18 23:36:28 +04:00
row_group - > parent = table ;
2003-07-07 01:10:12 +04:00
box_normalise_table_row_group ( row_group , & row_span ,
2004-01-02 15:04:04 +03:00
& table_columns , box_pool ) ;
2002-08-18 20:46:45 +04:00
break ;
case BOX_INLINE :
2003-09-22 02:47:08 +04:00
case BOX_INLINE_BLOCK :
2002-08-18 20:46:45 +04:00
case BOX_FLOAT_LEFT :
case BOX_FLOAT_RIGHT :
/* should have been wrapped in inline
container by convert_xml_to_box ( ) */
assert ( 0 ) ;
break ;
default :
fprintf ( stderr , " %i \n " , child - > type ) ;
assert ( 0 ) ;
}
}
2003-01-02 16:26:43 +03:00
2003-07-07 01:10:12 +04:00
table - > columns = table_columns ;
xfree ( row_span ) ;
2003-01-02 16:26:43 +03:00
if ( table - > children = = 0 ) {
LOG ( ( " table->children == 0, removing " ) ) ;
if ( table - > prev = = 0 )
table - > parent - > children = table - > next ;
else
table - > prev - > next = table - > next ;
if ( table - > next ! = 0 )
table - > next - > prev = table - > prev ;
2003-09-20 01:23:19 +04:00
box_free ( table ) ;
2003-01-02 16:26:43 +03:00
}
LOG ( ( " table %p done " , table ) ) ;
2002-08-18 20:46:45 +04:00
}
2003-07-07 01:10:12 +04:00
void box_normalise_table_row_group ( struct box * row_group ,
2004-01-02 15:04:04 +03:00
unsigned int * * row_span , unsigned int * table_columns ,
pool box_pool )
2002-08-18 20:46:45 +04:00
{
struct box * child ;
2003-01-02 16:26:43 +03:00
struct box * next_child ;
2002-08-18 20:46:45 +04:00
struct box * row ;
struct css_style * style ;
2003-01-02 16:26:43 +03:00
assert ( row_group ! = 0 ) ;
2002-08-18 20:46:45 +04:00
assert ( row_group - > type = = BOX_TABLE_ROW_GROUP ) ;
2003-01-02 16:26:43 +03:00
LOG ( ( " row_group %p " , row_group ) ) ;
2002-08-18 20:46:45 +04:00
2003-01-02 16:26:43 +03:00
for ( child = row_group - > children ; child ! = 0 ; child = next_child ) {
next_child = child - > next ;
2002-08-18 20:46:45 +04:00
switch ( child - > type ) {
case BOX_TABLE_ROW :
/* ok */
2004-01-02 15:04:04 +03:00
box_normalise_table_row ( child , row_span ,
table_columns , box_pool ) ;
2002-08-18 20:46:45 +04:00
break ;
case BOX_BLOCK :
case BOX_INLINE_CONTAINER :
case BOX_TABLE :
case BOX_TABLE_ROW_GROUP :
case BOX_TABLE_CELL :
/* insert implied table row */
style = xcalloc ( 1 , sizeof ( struct css_style ) ) ;
memcpy ( style , row_group - > style , sizeof ( struct css_style ) ) ;
css_cascade ( style , & css_blank_style ) ;
2004-01-02 15:04:04 +03:00
row = box_create ( style , row_group - > href , 0 ,
box_pool ) ;
2003-07-05 20:16:15 +04:00
row - > type = BOX_TABLE_ROW ;
2003-01-02 16:26:43 +03:00
if ( child - > prev = = 0 )
2002-08-18 20:46:45 +04:00
row_group - > children = row ;
else
2003-01-02 16:26:43 +03:00
child - > prev - > next = row ;
row - > prev = child - > prev ;
2002-08-18 20:46:45 +04:00
while ( child ! = 0 & & (
child - > type = = BOX_BLOCK | |
child - > type = = BOX_INLINE_CONTAINER | |
child - > type = = BOX_TABLE | |
child - > type = = BOX_TABLE_ROW_GROUP | |
child - > type = = BOX_TABLE_CELL ) ) {
box_add_child ( row , child ) ;
child = child - > next ;
}
2003-01-02 16:26:43 +03:00
row - > last - > next = 0 ;
row - > next = next_child = child ;
2002-09-18 23:36:28 +04:00
row - > parent = row_group ;
2004-01-02 15:04:04 +03:00
box_normalise_table_row ( row , row_span ,
table_columns , box_pool ) ;
2002-08-18 20:46:45 +04:00
break ;
case BOX_INLINE :
2003-09-22 02:47:08 +04:00
case BOX_INLINE_BLOCK :
2002-08-18 20:46:45 +04:00
case BOX_FLOAT_LEFT :
case BOX_FLOAT_RIGHT :
/* should have been wrapped in inline
container by convert_xml_to_box ( ) */
assert ( 0 ) ;
break ;
default :
assert ( 0 ) ;
}
}
2003-01-02 16:26:43 +03:00
if ( row_group - > children = = 0 ) {
LOG ( ( " row_group->children == 0, removing " ) ) ;
if ( row_group - > prev = = 0 )
row_group - > parent - > children = row_group - > next ;
else
row_group - > prev - > next = row_group - > next ;
if ( row_group - > next ! = 0 )
row_group - > next - > prev = row_group - > prev ;
2003-09-20 01:23:19 +04:00
box_free ( row_group ) ;
2003-01-02 16:26:43 +03:00
}
LOG ( ( " row_group %p done " , row_group ) ) ;
2002-08-18 20:46:45 +04:00
}
2003-07-07 01:10:12 +04:00
void box_normalise_table_row ( struct box * row ,
2004-01-02 15:04:04 +03:00
unsigned int * * row_span , unsigned int * table_columns ,
pool box_pool )
2002-08-18 20:46:45 +04:00
{
struct box * child ;
2003-01-02 16:26:43 +03:00
struct box * next_child ;
2002-08-18 20:46:45 +04:00
struct box * cell ;
struct css_style * style ;
2003-12-27 05:03:48 +03:00
unsigned int columns = 0 , i ;
2002-08-18 20:46:45 +04:00
2003-01-02 16:26:43 +03:00
assert ( row ! = 0 ) ;
2002-08-18 20:46:45 +04:00
assert ( row - > type = = BOX_TABLE_ROW ) ;
2003-01-02 16:26:43 +03:00
LOG ( ( " row %p " , row ) ) ;
2002-08-18 20:46:45 +04:00
2003-01-02 16:26:43 +03:00
for ( child = row - > children ; child ! = 0 ; child = next_child ) {
next_child = child - > next ;
2002-08-18 20:46:45 +04:00
switch ( child - > type ) {
case BOX_TABLE_CELL :
/* ok */
2004-01-02 15:04:04 +03:00
box_normalise_block ( child , box_pool ) ;
2003-07-07 01:10:12 +04:00
cell = child ;
2002-08-18 20:46:45 +04:00
break ;
case BOX_BLOCK :
case BOX_INLINE_CONTAINER :
case BOX_TABLE :
case BOX_TABLE_ROW_GROUP :
case BOX_TABLE_ROW :
/* insert implied table cell */
style = xcalloc ( 1 , sizeof ( struct css_style ) ) ;
memcpy ( style , row - > style , sizeof ( struct css_style ) ) ;
css_cascade ( style , & css_blank_style ) ;
2004-01-02 15:04:04 +03:00
cell = box_create ( style , row - > href , 0 , box_pool ) ;
2003-07-05 20:16:15 +04:00
cell - > type = BOX_TABLE_CELL ;
2003-01-02 16:26:43 +03:00
if ( child - > prev = = 0 )
2002-08-18 20:46:45 +04:00
row - > children = cell ;
else
2003-01-02 16:26:43 +03:00
child - > prev - > next = cell ;
cell - > prev = child - > prev ;
2002-08-18 20:46:45 +04:00
while ( child ! = 0 & & (
child - > type = = BOX_BLOCK | |
child - > type = = BOX_INLINE_CONTAINER | |
child - > type = = BOX_TABLE | |
child - > type = = BOX_TABLE_ROW_GROUP | |
child - > type = = BOX_TABLE_ROW ) ) {
box_add_child ( cell , child ) ;
child = child - > next ;
}
2003-01-02 16:26:43 +03:00
cell - > last - > next = 0 ;
cell - > next = next_child = child ;
2002-09-18 23:36:28 +04:00
cell - > parent = row ;
2004-01-02 15:04:04 +03:00
box_normalise_block ( cell , box_pool ) ;
2002-08-18 20:46:45 +04:00
break ;
case BOX_INLINE :
2003-09-22 02:47:08 +04:00
case BOX_INLINE_BLOCK :
2002-08-18 20:46:45 +04:00
case BOX_FLOAT_LEFT :
case BOX_FLOAT_RIGHT :
/* should have been wrapped in inline
container by convert_xml_to_box ( ) */
assert ( 0 ) ;
break ;
default :
assert ( 0 ) ;
}
2003-07-07 01:10:12 +04:00
/* skip columns with cells spanning from above */
2003-07-08 22:49:14 +04:00
while ( ( * row_span ) [ columns ] ! = 0 )
2003-07-07 01:10:12 +04:00
columns + + ;
cell - > start_column = columns ;
if ( * table_columns < columns + cell - > columns ) {
* table_columns = columns + cell - > columns ;
* row_span = xrealloc ( * row_span ,
sizeof ( ( * row_span ) [ 0 ] ) *
( * table_columns + 1 ) ) ;
( * row_span ) [ * table_columns ] = 0 ; /* sentinel */
}
for ( i = 0 ; i ! = cell - > columns ; i + + )
2003-07-08 22:49:14 +04:00
( * row_span ) [ columns + i ] = cell - > rows ;
2003-07-07 01:10:12 +04:00
columns + = cell - > columns ;
2002-08-18 20:46:45 +04:00
}
2003-07-07 01:10:12 +04:00
2003-07-08 22:49:14 +04:00
for ( i = 0 ; i ! = * table_columns ; i + + )
if ( ( * row_span ) [ i ] ! = 0 )
( * row_span ) [ i ] - - ;
2003-01-02 16:26:43 +03:00
if ( row - > children = = 0 ) {
LOG ( ( " row->children == 0, removing " ) ) ;
if ( row - > prev = = 0 )
row - > parent - > children = row - > next ;
else
row - > prev - > next = row - > next ;
if ( row - > next ! = 0 )
row - > next - > prev = row - > prev ;
2003-09-20 01:23:19 +04:00
box_free ( row ) ;
2003-01-02 16:26:43 +03:00
}
LOG ( ( " row %p done " , row ) ) ;
2002-08-18 20:46:45 +04:00
}
2004-01-02 15:04:04 +03:00
void box_normalise_inline_container ( struct box * cont , pool box_pool )
2002-08-18 20:46:45 +04:00
{
struct box * child ;
2003-01-02 16:26:43 +03:00
struct box * next_child ;
2002-08-18 20:46:45 +04:00
2003-01-02 16:26:43 +03:00
assert ( cont ! = 0 ) ;
2002-08-18 20:46:45 +04:00
assert ( cont - > type = = BOX_INLINE_CONTAINER ) ;
2003-01-02 16:26:43 +03:00
LOG ( ( " cont %p " , cont ) ) ;
2002-08-18 20:46:45 +04:00
2003-01-02 16:26:43 +03:00
for ( child = cont - > children ; child ! = 0 ; child = next_child ) {
next_child = child - > next ;
2002-08-18 20:46:45 +04:00
switch ( child - > type ) {
case BOX_INLINE :
/* ok */
break ;
2003-09-22 02:47:08 +04:00
case BOX_INLINE_BLOCK :
/* ok */
2004-01-02 15:04:04 +03:00
box_normalise_block ( child , box_pool ) ;
2003-09-22 02:47:08 +04:00
break ;
2002-08-18 20:46:45 +04:00
case BOX_FLOAT_LEFT :
case BOX_FLOAT_RIGHT :
/* ok */
assert ( child - > children ! = 0 ) ;
switch ( child - > children - > type ) {
case BOX_BLOCK :
2004-01-02 15:04:04 +03:00
box_normalise_block ( child - > children ,
box_pool ) ;
2002-08-18 20:46:45 +04:00
break ;
case BOX_TABLE :
2004-01-02 15:04:04 +03:00
box_normalise_table ( child - > children ,
box_pool ) ;
2002-08-18 20:46:45 +04:00
break ;
default :
assert ( 0 ) ;
}
2003-09-05 23:19:05 +04:00
if ( child - > children = = 0 ) {
/* the child has destroyed itself: remove float */
if ( child - > prev = = 0 )
child - > parent - > children = child - > next ;
else
child - > prev - > next = child - > next ;
if ( child - > next ! = 0 )
child - > next - > prev = child - > prev ;
2003-09-20 01:23:19 +04:00
box_free ( child ) ;
2003-09-05 23:19:05 +04:00
}
2002-08-18 20:46:45 +04:00
break ;
case BOX_BLOCK :
case BOX_INLINE_CONTAINER :
case BOX_TABLE :
case BOX_TABLE_ROW_GROUP :
case BOX_TABLE_ROW :
case BOX_TABLE_CELL :
default :
assert ( 0 ) ;
}
}
2003-01-02 16:26:43 +03:00
LOG ( ( " cont %p done " , cont ) ) ;
2002-08-18 20:46:45 +04:00
}
2002-09-08 22:11:56 +04:00
2003-10-25 04:35:49 +04:00
void gadget_free ( struct form_control * g )
2002-12-31 01:56:30 +03:00
{
2003-10-25 04:35:49 +04:00
struct form_option * o , * o1 ;
2002-12-31 01:56:30 +03:00
if ( g - > name ! = 0 )
2003-04-25 12:03:15 +04:00
xmlFree ( g - > name ) ;
2003-09-27 03:22:00 +04:00
free ( g - > value ) ;
free ( g - > initial_value ) ;
2003-01-02 16:26:43 +03:00
2003-10-25 04:35:49 +04:00
if ( g - > type = = GADGET_SELECT ) {
o = g - > data . select . items ;
while ( o ! = NULL )
{
if ( o - > text ! = 0 )
xmlFree ( o - > text ) ;
if ( o - > value ! = 0 )
xmlFree ( o - > value ) ;
o1 = o - > next ;
xfree ( o ) ;
o = o1 ;
}
2002-12-31 01:56:30 +03:00
}
}
2002-09-08 22:11:56 +04:00
/**
* free a box tree recursively
*/
void box_free ( struct box * box )
{
2003-09-20 01:23:19 +04:00
struct box * child , * next ;
2002-09-08 22:11:56 +04:00
2003-09-20 01:23:19 +04:00
/* free children first */
for ( child = box - > children ; child ; child = next ) {
next = child - > next ;
box_free ( child ) ;
}
2002-09-08 22:11:56 +04:00
/* last this box */
2003-01-02 16:26:43 +03:00
box_free_box ( box ) ;
}
void box_free_box ( struct box * box )
{
2003-09-20 01:23:19 +04:00
if ( ! box - > clone ) {
if ( box - > gadget ) {
gadget_free ( box - > gadget ) ;
free ( box - > gadget ) ;
}
free ( box - > href ) ;
free ( box - > title ) ;
free ( box - > col ) ;
if ( ! box - > style_clone )
free ( box - > style ) ;
2002-12-30 01:27:35 +03:00
}
2002-12-30 05:06:03 +03:00
2003-07-01 02:21:51 +04:00
free ( box - > text ) ;
2003-07-15 02:57:45 +04:00
/* TODO: free object_params */
2002-09-08 22:11:56 +04:00
}
2002-12-30 01:27:35 +03:00
2003-04-15 21:53:00 +04:00
/**
2003-07-05 01:17:53 +04:00
* form helper functions
2003-04-15 21:53:00 +04:00
*/
2002-12-31 01:56:30 +03:00
void add_form_element ( struct page_elements * pe , struct form * f )
{
pe - > forms = xrealloc ( pe - > forms , ( pe - > numForms + 1 ) * sizeof ( struct form * ) ) ;
pe - > forms [ pe - > numForms ] = f ;
pe - > numForms + + ;
}
2003-10-25 04:35:49 +04:00
void add_gadget_element ( struct page_elements * pe , struct form_control * g )
2002-12-31 01:56:30 +03:00
{
2003-10-25 04:35:49 +04:00
pe - > gadgets = xrealloc ( pe - > gadgets , ( pe - > numGadgets + 1 ) * sizeof ( struct form_control * ) ) ;
2002-12-31 01:56:30 +03:00
pe - > gadgets [ pe - > numGadgets ] = g ;
pe - > numGadgets + + ;
}
2004-01-05 05:10:59 +03:00
# ifdef WITH_PLUGIN
2003-05-31 22:47:00 +04:00
/**
* add an object to the box tree
*/
2003-07-08 02:10:51 +04:00
struct result box_object ( xmlNode * n , struct status * status ,
struct css_style * style )
2003-05-31 22:47:00 +04:00
{
struct box * box ;
2003-07-10 01:33:01 +04:00
struct object_params * po ;
2003-07-17 18:26:15 +04:00
struct plugin_params * pp ;
2003-12-27 05:03:48 +03:00
char * s , * url = NULL ;
2003-07-17 18:26:15 +04:00
xmlNode * c ;
2002-12-31 01:56:30 +03:00
2004-01-02 15:04:04 +03:00
box = box_create ( style , status - > href , 0 ,
status - > content - > data . html . box_pool ) ;
2003-07-08 02:10:51 +04:00
po = xcalloc ( 1 , sizeof ( * po ) ) ;
2003-05-31 22:47:00 +04:00
2003-07-08 02:10:51 +04:00
/* initialise po struct */
po - > data = 0 ;
po - > type = 0 ;
po - > codetype = 0 ;
po - > codebase = 0 ;
po - > classid = 0 ;
2003-07-17 18:26:15 +04:00
po - > params = 0 ;
2003-05-31 22:47:00 +04:00
2003-07-08 02:10:51 +04:00
/* object data */
2003-05-31 22:47:00 +04:00
if ( ( s = ( char * ) xmlGetProp ( n , ( const xmlChar * ) " data " ) ) ) {
2003-12-26 03:17:55 +03:00
url = url_join ( s , status - > content - > data . html . base_url ) ;
if ( ! url ) {
free ( po ) ;
xmlFree ( s ) ;
return ( struct result ) { box , 1 } ;
}
2003-06-06 06:08:56 +04:00
po - > data = strdup ( s ) ;
2003-07-08 02:10:51 +04:00
LOG ( ( " object '%s' " , po - > data ) ) ;
2003-05-31 22:47:00 +04:00
xmlFree ( s ) ;
}
/* object type */
if ( ( s = ( char * ) xmlGetProp ( n , ( const xmlChar * ) " type " ) ) ) {
2003-06-06 06:08:56 +04:00
po - > type = strdup ( s ) ;
2003-07-08 02:10:51 +04:00
LOG ( ( " type: %s " , s ) ) ;
2003-05-31 22:47:00 +04:00
xmlFree ( s ) ;
}
/* object codetype */
if ( ( s = ( char * ) xmlGetProp ( n , ( const xmlChar * ) " codetype " ) ) ) {
2003-06-06 06:08:56 +04:00
po - > codetype = strdup ( s ) ;
2003-07-08 02:10:51 +04:00
LOG ( ( " codetype: %s " , s ) ) ;
2003-05-31 22:47:00 +04:00
xmlFree ( s ) ;
}
/* object codebase */
if ( ( s = ( char * ) xmlGetProp ( n , ( const xmlChar * ) " codebase " ) ) ) {
2003-06-06 06:08:56 +04:00
po - > codebase = strdup ( s ) ;
2003-07-08 02:10:51 +04:00
LOG ( ( " codebase: %s " , s ) ) ;
2003-05-31 22:47:00 +04:00
xmlFree ( s ) ;
}
/* object classid */
if ( ( s = ( char * ) xmlGetProp ( n , ( const xmlChar * ) " classid " ) ) ) {
2003-06-06 06:08:56 +04:00
po - > classid = strdup ( s ) ;
2003-07-08 02:10:51 +04:00
LOG ( ( " classid: %s " , s ) ) ;
2003-05-31 22:47:00 +04:00
xmlFree ( s ) ;
}
2003-07-17 18:26:15 +04:00
/* parameters
* parameter data is stored in a singly linked list .
* po - > params points to the head of the list .
* new parameters are added to the head of the list .
*/
for ( c = n - > children ; c ! = 0 ; c = c - > next ) {
if ( strcmp ( ( const char * ) c - > name , " param " ) = = 0 ) {
pp = xcalloc ( 1 , sizeof ( * pp ) ) ;
/* initialise pp struct */
pp - > name = 0 ;
pp - > value = 0 ;
2003-08-25 02:39:55 +04:00
pp - > valuetype = 0 ;
2003-07-17 18:26:15 +04:00
pp - > type = 0 ;
pp - > next = 0 ;
if ( ( s = ( char * ) xmlGetProp ( c , ( const xmlChar * ) " name " ) ) ) {
pp - > name = strdup ( s ) ;
xmlFree ( s ) ;
}
if ( ( s = ( char * ) xmlGetProp ( c , ( const xmlChar * ) " value " ) ) ) {
pp - > value = strdup ( s ) ;
xmlFree ( s ) ;
}
if ( ( s = ( char * ) xmlGetProp ( c , ( const xmlChar * ) " type " ) ) ) {
pp - > type = strdup ( s ) ;
xmlFree ( s ) ;
}
if ( ( s = ( char * ) xmlGetProp ( c , ( const xmlChar * ) " valuetype " ) ) ) {
pp - > valuetype = strdup ( s ) ;
xmlFree ( s ) ;
}
else {
pp - > valuetype = strdup ( " data " ) ;
}
pp - > next = po - > params ;
po - > params = pp ;
}
else {
/* The first non-param child is the start of the
* alt html . Therefore , we should break out of this loop .
*/
continue ;
}
}
2003-07-10 01:33:01 +04:00
box - > object_params = po ;
2003-05-31 22:47:00 +04:00
/* start fetch */
2003-07-10 01:33:01 +04:00
if ( plugin_decode ( status - > content , url , box , po ) )
return ( struct result ) { box , 0 } ;
2003-05-31 22:47:00 +04:00
2003-07-10 01:33:01 +04:00
return ( struct result ) { box , 1 } ;
2003-05-31 22:47:00 +04:00
}
/**
* add an embed to the box tree
*/
2003-07-08 02:10:51 +04:00
struct result box_embed ( xmlNode * n , struct status * status ,
struct css_style * style )
2003-05-31 22:47:00 +04:00
{
struct box * box ;
2003-07-10 01:33:01 +04:00
struct object_params * po ;
2003-08-25 02:39:55 +04:00
struct plugin_params * pp ;
2003-12-27 05:03:48 +03:00
char * s , * url = NULL ;
2003-08-25 02:39:55 +04:00
xmlAttr * a ;
2003-05-31 22:47:00 +04:00
2004-01-02 15:04:04 +03:00
box = box_create ( style , status - > href , 0 ,
status - > content - > data . html . box_pool ) ;
2003-05-31 22:47:00 +04:00
po = xcalloc ( 1 , sizeof ( * po ) ) ;
2003-07-08 02:10:51 +04:00
/* initialise po struct */
po - > data = 0 ;
po - > type = 0 ;
po - > codetype = 0 ;
po - > codebase = 0 ;
po - > classid = 0 ;
2003-07-17 18:26:15 +04:00
po - > params = 0 ;
2003-07-08 02:10:51 +04:00
2003-05-31 22:47:00 +04:00
/* embed src */
if ( ( s = ( char * ) xmlGetProp ( n , ( const xmlChar * ) " src " ) ) ) {
2003-12-26 03:17:55 +03:00
url = url_join ( s , status - > content - > data . html . base_url ) ;
if ( ! url ) {
free ( po ) ;
xmlFree ( s ) ;
return ( struct result ) { box , 0 } ;
}
2003-05-31 22:47:00 +04:00
LOG ( ( " embed '%s' " , url ) ) ;
2003-12-26 03:17:55 +03:00
po - > data = strdup ( s ) ;
2003-05-31 22:47:00 +04:00
xmlFree ( s ) ;
}
2003-08-25 02:39:55 +04:00
/**
* we munge all other attributes into a plugin_parameter structure
*/
for ( a = n - > properties ; a ! = 0 ; a = a - > next ) {
pp = xcalloc ( 1 , sizeof ( * pp ) ) ;
/* initialise pp struct */
pp - > name = 0 ;
pp - > value = 0 ;
pp - > valuetype = 0 ;
pp - > type = 0 ;
pp - > next = 0 ;
if ( strcasecmp ( ( char * ) a - > name , " src " ) ! = 0 ) {
pp - > name = strdup ( ( char * ) a - > name ) ;
pp - > value = strdup ( ( char * ) a - > children - > content ) ;
pp - > valuetype = strdup ( " data " ) ;
pp - > next = po - > params ;
po - > params = pp ;
}
}
2003-07-10 01:33:01 +04:00
box - > object_params = po ;
2003-06-08 02:24:22 +04:00
/* start fetch */
2003-07-08 02:10:51 +04:00
plugin_decode ( status - > content , url , box , po ) ;
2003-05-31 22:47:00 +04:00
2003-07-08 02:10:51 +04:00
return ( struct result ) { box , 0 } ;
2003-05-31 22:47:00 +04:00
}
/**
* add an applet to the box tree
*/
2003-07-08 02:10:51 +04:00
struct result box_applet ( xmlNode * n , struct status * status ,
struct css_style * style )
2003-05-31 22:47:00 +04:00
{
struct box * box ;
2003-07-17 18:26:15 +04:00
struct object_params * po ;
struct plugin_params * pp ;
2003-12-27 05:03:48 +03:00
char * s , * url = NULL ;
2003-07-17 18:26:15 +04:00
xmlNode * c ;
2003-05-31 22:47:00 +04:00
2004-01-02 15:04:04 +03:00
box = box_create ( style , status - > href , 0 ,
status - > content - > data . html . box_pool ) ;
2003-05-31 22:47:00 +04:00
2003-07-17 18:26:15 +04:00
po = xcalloc ( 1 , sizeof ( * po ) ) ;
2003-05-31 22:47:00 +04:00
2003-07-17 18:26:15 +04:00
/* initialise po struct */
po - > data = 0 ;
po - > type = 0 ;
po - > codetype = 0 ;
po - > codebase = 0 ;
po - > classid = 0 ;
po - > params = 0 ;
2003-12-26 03:17:55 +03:00
/* code */
2003-07-17 18:26:15 +04:00
if ( ( s = ( char * ) xmlGetProp ( n , ( const xmlChar * ) " code " ) ) ) {
2003-12-26 03:17:55 +03:00
url = url_join ( s , status - > content - > data . html . base_url ) ;
if ( ! url ) {
free ( po ) ;
xmlFree ( s ) ;
return ( struct result ) { box , 1 } ;
}
LOG ( ( " applet '%s' " , url ) ) ;
po - > classid = strdup ( s ) ;
xmlFree ( s ) ;
}
2003-07-17 18:26:15 +04:00
/* object codebase */
if ( ( s = ( char * ) xmlGetProp ( n , ( const xmlChar * ) " codebase " ) ) ) {
po - > codebase = strdup ( s ) ;
LOG ( ( " codebase: %s " , s ) ) ;
xmlFree ( s ) ;
}
/* parameters
* parameter data is stored in a singly linked list .
* po - > params points to the head of the list .
* new parameters are added to the head of the list .
*/
for ( c = n - > children ; c ! = 0 ; c = c - > next ) {
if ( strcmp ( ( const char * ) c - > name , " param " ) = = 0 ) {
pp = xcalloc ( 1 , sizeof ( * pp ) ) ;
/* initialise pp struct */
pp - > name = 0 ;
pp - > value = 0 ;
2003-08-25 02:39:55 +04:00
pp - > valuetype = 0 ;
2003-07-17 18:26:15 +04:00
pp - > type = 0 ;
pp - > next = 0 ;
if ( ( s = ( char * ) xmlGetProp ( c , ( const xmlChar * ) " name " ) ) ) {
pp - > name = strdup ( s ) ;
xmlFree ( s ) ;
}
if ( ( s = ( char * ) xmlGetProp ( c , ( const xmlChar * ) " value " ) ) ) {
pp - > value = strdup ( s ) ;
xmlFree ( s ) ;
}
if ( ( s = ( char * ) xmlGetProp ( c , ( const xmlChar * ) " type " ) ) ) {
pp - > type = strdup ( s ) ;
xmlFree ( s ) ;
}
if ( ( s = ( char * ) xmlGetProp ( c , ( const xmlChar * ) " valuetype " ) ) ) {
pp - > valuetype = strdup ( s ) ;
xmlFree ( s ) ;
}
else {
pp - > valuetype = strdup ( " data " ) ;
}
pp - > next = po - > params ;
po - > params = pp ;
}
else {
/* The first non-param child is the start of the
* alt html . Therefore , we should break out of this loop .
*/
continue ;
}
}
2003-05-31 22:47:00 +04:00
2003-09-18 01:47:21 +04:00
box - > object_params = po ;
2003-05-31 22:47:00 +04:00
/* start fetch */
2003-07-17 18:26:15 +04:00
if ( plugin_decode ( status - > content , url , box , po ) )
return ( struct result ) { box , 0 } ;
2003-05-31 22:47:00 +04:00
2003-07-17 18:26:15 +04:00
return ( struct result ) { box , 1 } ;
2003-05-31 22:47:00 +04:00
}
2003-07-10 01:33:01 +04:00
2003-08-25 02:39:55 +04:00
/**
* box_iframe
* add an iframe to the box tree
* TODO - implement GUI nested wimp stuff ' cos this looks naff atm . ( 16 _5 )
*/
struct result box_iframe ( xmlNode * n , struct status * status ,
struct css_style * style )
{
struct box * box ;
struct object_params * po ;
2003-12-27 05:03:48 +03:00
char * s , * url = NULL ;
2003-08-25 02:39:55 +04:00
2004-01-02 15:04:04 +03:00
box = box_create ( style , status - > href , 0 ,
status - > content - > data . html . box_pool ) ;
2003-08-25 02:39:55 +04:00
po = xcalloc ( 1 , sizeof ( * po ) ) ;
/* initialise po struct */
po - > data = 0 ;
po - > type = 0 ;
po - > codetype = 0 ;
po - > codebase = 0 ;
po - > classid = 0 ;
po - > params = 0 ;
/* iframe src */
if ( ( s = ( char * ) xmlGetProp ( n , ( const xmlChar * ) " src " ) ) ) {
2003-12-26 03:17:55 +03:00
url = url_join ( s , status - > content - > data . html . base_url ) ;
if ( ! url ) {
free ( po ) ;
xmlFree ( s ) ;
return ( struct result ) { box , 0 } ;
}
LOG ( ( " embed '%s' " , url ) ) ;
po - > data = strdup ( s ) ;
xmlFree ( s ) ;
}
2003-08-25 02:39:55 +04:00
box - > object_params = po ;
/* start fetch */
plugin_decode ( status - > content , url , box , po ) ;
return ( struct result ) { box , 0 } ;
}
2003-07-10 01:33:01 +04:00
/**
* plugin_decode
* This function checks that the contents of the plugin_object struct
* are valid . If they are , it initiates the fetch process . If they are
* not , it exits , leaving the box structure as it was on entry . This is
* necessary as there are multiple ways of declaring an object ' s attributes .
*
* Returns false if the object could not be handled .
2003-12-26 03:17:55 +03:00
*
* TODO : reformat , plug failure leaks
2003-07-10 01:33:01 +04:00
*/
bool plugin_decode ( struct content * content , char * url , struct box * box ,
struct object_params * po )
{
2003-08-29 02:04:11 +04:00
struct plugin_params * pp ;
2003-07-10 01:33:01 +04:00
/* Check if the codebase attribute is defined.
* If it is not , set it to the codebase of the current document .
*/
if ( po - > codebase = = 0 )
2003-12-26 03:17:55 +03:00
po - > codebase = url_join ( " ./ " , content - > data . html . base_url ) ;
2003-07-10 01:33:01 +04:00
else
2003-12-26 03:17:55 +03:00
po - > codebase = url_join ( po - > codebase , content - > data . html . base_url ) ;
if ( ! po - > codebase )
return false ;
/* Set basehref */
po - > basehref = strdup ( content - > data . html . base_url ) ;
2003-07-10 01:33:01 +04:00
/* Check that we have some data specified.
* First , check the data attribute .
* Second , check the classid attribute .
* The data attribute takes precedence .
* If neither are specified or if classid begins " clsid: " ,
* we can ' t handle this object .
*/
if ( po - > data = = 0 & & po - > classid = = 0 ) {
2003-07-18 03:01:02 +04:00
return false ;
2003-07-10 01:33:01 +04:00
}
if ( po - > data = = 0 & & po - > classid ! = 0 ) {
2003-07-15 02:57:45 +04:00
if ( strncasecmp ( po - > classid , " clsid: " , 6 ) = = 0 ) {
2003-08-29 02:04:11 +04:00
/* Flash */
if ( strcasecmp ( po - > classid , " clsid:D27CDB6E-AE6D-11cf-96B8-444553540000 " ) = = 0 ) {
for ( pp = po - > params ; pp ! = 0 & &
( strcasecmp ( pp - > name , " movie " ) ! = 0 ) ;
pp = pp - > next ) ;
2003-12-26 03:17:55 +03:00
if ( pp = = 0 )
return false ;
url = url_join ( pp - > value , po - > basehref ) ;
if ( ! url )
return false ;
2003-09-16 23:53:59 +04:00
/* munge the codebase */
2003-12-26 03:17:55 +03:00
po - > codebase = url_join ( " ./ " ,
content - > data . html . base_url ) ;
if ( ! po - > codebase )
return false ;
2003-08-29 02:04:11 +04:00
}
else {
LOG ( ( " ActiveX object - n0 " ) ) ;
return false ;
}
2003-07-10 01:33:01 +04:00
}
else {
url = url_join ( po - > classid , po - > codebase ) ;
2003-12-26 03:17:55 +03:00
if ( ! url )
return false ;
2003-07-17 18:26:15 +04:00
/* The java plugin doesn't need the .class extension
* so we strip it .
*/
if ( stricmp ( ( & po - > classid [ strlen ( po - > classid ) - 6 ] ) ,
" .class " ) = = 0 )
po - > classid [ strlen ( po - > classid ) - 6 ] = 0 ;
2003-07-10 01:33:01 +04:00
}
}
else {
url = url_join ( po - > data , po - > codebase ) ;
2003-12-26 03:17:55 +03:00
if ( ! url )
return false ;
2003-07-10 01:33:01 +04:00
}
/* Check if the declared mime type is understandable.
* Checks type and codetype attributes .
*/
if ( po - > type ! = 0 ) {
if ( content_lookup ( po - > type ) = = CONTENT_OTHER )
2003-07-18 03:01:02 +04:00
return false ;
2003-07-10 01:33:01 +04:00
}
if ( po - > codetype ! = 0 ) {
if ( content_lookup ( po - > codetype ) = = CONTENT_OTHER )
2003-07-18 03:01:02 +04:00
return false ;
2003-07-10 01:33:01 +04:00
}
/* If we've got to here, the object declaration has provided us with
* enough data to enable us to have a go at downloading and displaying it .
*
* We may still find that the object has a MIME type that we can ' t handle
* when we fetch it ( if the type was not specified or is different to that
* given in the attributes ) .
*/
2004-01-24 20:08:16 +03:00
html_fetch_object ( content , url , box , 0 ) ;
2003-07-10 01:33:01 +04:00
2003-07-18 03:01:02 +04:00
return true ;
2003-07-10 01:33:01 +04:00
}
2004-01-05 05:10:59 +03:00
# endif
2003-09-03 21:52:45 +04:00
/**
* Find the absolute coordinates of a box .
*/
void box_coords ( struct box * box , unsigned long * x , unsigned long * y )
{
* x = box - > x ;
* y = box - > y ;
while ( box - > parent ! = 0 ) {
box = box - > parent ;
* x + = box - > x ;
* y + = box - > y ;
}
}