r4432 mikeL - /branches/mikeL/netsurf/gtk/gtk_window.c
by netsurf@semichrome.net
Author: mikeL
Date: Mon Jun 23 22:00:36 2008
New Revision: 4432
URL: http://source.netsurf-browser.org?rev=4432&view=rev
Log:
Drag events are now emited from where the press originated, instead of from where they became a drag
Modified:
branches/mikeL/netsurf/gtk/gtk_window.c
Modified: branches/mikeL/netsurf/gtk/gtk_window.c
URL: http://source.netsurf-browser.org/branches/mikeL/netsurf/gtk/gtk_window.c...
==============================================================================
--- branches/mikeL/netsurf/gtk/gtk_window.c (original)
+++ branches/mikeL/netsurf/gtk/gtk_window.c Mon Jun 23 22:00:36 2008
@@ -330,8 +330,7 @@
if (g->mouse->state & BROWSER_MOUSE_PRESS_1){
/* Start button 1 drag */
browser_window_mouse_click(g->bw, BROWSER_MOUSE_DRAG_1,
- event->x / g->bw->scale,
- event->y / g->bw->scale);
+ g->mouse->pressed_x, g->mouse->pressed_y);
/* Replace PRESS with HOLDING and declare drag in progress */
g->mouse->state ^= (BROWSER_MOUSE_PRESS_1 |
BROWSER_MOUSE_HOLDING_1);
@@ -340,8 +339,7 @@
else if (g->mouse->state & BROWSER_MOUSE_PRESS_2){
/* Start button 2 drag */
browser_window_mouse_click(g->bw, BROWSER_MOUSE_DRAG_2,
- event->x / g->bw->scale,
- event->y / g->bw->scale);
+ g->mouse->pressed_x, g->mouse->pressed_y);
/* Replace PRESS with HOLDING and declare drag in progress */
g->mouse->state ^= (BROWSER_MOUSE_PRESS_2 |
BROWSER_MOUSE_HOLDING_2);
@@ -381,9 +379,12 @@
g->mouse->state |= BROWSER_MOUSE_MOD_1;
if (event->state & GDK_CONTROL_MASK)
g->mouse->state |= BROWSER_MOUSE_MOD_2;
-
- browser_window_mouse_click(g->bw, g->mouse->state, event->x / g->bw->scale,
- event->y / g->bw->scale);
+
+ g->mouse->pressed_x = event->x / g->bw->scale;
+ g->mouse->pressed_y = event->y / g->bw->scale;
+
+ browser_window_mouse_click(g->bw, g->mouse->state, g->mouse->pressed_x,
+ g->mouse->pressed_y);
}
gboolean nsgtk_window_button_release_event(GtkWidget *widget,
@@ -461,7 +462,6 @@
{
struct gui_window *g = data;
wchar_t nskey = gdkkey_to_nskey(event);
-
if (browser_window_key_press(g->bw, nskey))
return TRUE;
14 years, 9 months
r4431 dynis - /branches/dynis/libnsgif/libnsgif.c
by netsurf@semichrome.net
Author: dynis
Date: Mon Jun 23 21:10:46 2008
New Revision: 4431
URL: http://source.netsurf-browser.org?rev=4431&view=rev
Log:
Added separate functions to handle gif extensions; made to-do list
Modified:
branches/dynis/libnsgif/libnsgif.c
Modified: branches/dynis/libnsgif/libnsgif.c
URL: http://source.netsurf-browser.org/branches/dynis/libnsgif/libnsgif.c?rev=...
==============================================================================
--- branches/dynis/libnsgif/libnsgif.c (original)
+++ branches/dynis/libnsgif/libnsgif.c Mon Jun 23 21:10:46 2008
@@ -63,12 +63,28 @@
[rjw] - Fri 2nd April 2004
*/
+/* TO-DO LIST
+ =================
+
+ + Merge the gif_initialise_frame_extensions and
+ gif_decode_frame_extensions functions, because it seems unnecessary to
+ have both.
+ + Correct the usage of the background_action variable, which is actually
+ an implementation of the "Disposal Method" flag in the Graphic Control
+ Extension.
+/*
+
/* Internal GIF routines
*/
-static gif_result gif_initialise_sprite(struct gif_animation *gif, unsigned int width, unsigned int height, gif_bitmap_callback_vt *bitmap_callbacks);
+static gif_result gif_initialise_sprite(struct gif_animation *gif, unsigned int width, unsigned int height,
+ gif_bitmap_callback_vt *bitmap_callbacks);
static gif_result gif_initialise_frame(struct gif_animation *gif, gif_bitmap_callback_vt *bitmap_callbacks);
+static gif_result gif_initialise_frame_extensions(struct gif_animation *gif, const int frame,
+ unsigned int *background_action_p);
+static gif_result gif_decode_frame_extensions(struct gif_animation *gif, unsigned int *background_action_p,
+ unsigned int *flags_p, int *transparency_index_p);
static unsigned int gif_interlaced_line(int height, int y);
@@ -118,9 +134,9 @@
gif_result gif_initialise(struct gif_animation *gif, gif_bitmap_callback_vt *bitmap_callbacks) {
unsigned char *gif_data;
unsigned int index;
- int return_value;
-
- /* the gif format is thoroughly documented; a full description
+ gif_result return_value;
+
+ /* The GIF format is thoroughly documented; a full description
* can be found at http://www.w3.org/Graphics/GIF/spec-gif89a.txt
*/
@@ -343,7 +359,7 @@
GIF_OK for successful decoding
GIF_WORKING for successful decoding if more frames are expected
*/
-gif_result gif_initialise_frame(struct gif_animation *gif, gif_bitmap_callback_vt *bitmap_callbacks) {
+static gif_result gif_initialise_frame(struct gif_animation *gif, gif_bitmap_callback_vt *bitmap_callbacks) {
int frame;
gif_frame *temp_buf;
@@ -352,10 +368,9 @@
unsigned int flags = 0;
unsigned int background_action;
unsigned int width, height, offset_x, offset_y;
- unsigned int extension_size, colour_table_size;
- unsigned int block_size;
- bool more_images = true;
+ unsigned int block_size, colour_table_size;
bool first_image = true;
+ gif_result return_value;
/* Get the frame to decode and our data position
*/
@@ -411,145 +426,182 @@
the data contained within. This is all basically a cut down version of
gif_decode_frame that doesn't have any of the LZW bits in it.
*/
- while (more_images) {
-
- /* Decode the extensions
- */
- background_action = 0;
- while (gif_data[0] == 0x21) {
- /* Get the extension size
- */
- extension_size = gif_data[2];
-
- /* Graphic control extension - store the frame delay.
- */
- if (gif_data[1] == 0xf9) {
- gif->frames[frame].frame_delay = gif_data[4] | (gif_data[5] << 8);
- background_action = ((gif_data[3] & 0x1c) >> 2);
- more_images = false;
-
- /* Application extension - handle NETSCAPE2.0 looping
- */
- } else if (gif_data[1] == 0xff) {
- if (gif_bytes < 18) return GIF_INSUFFICIENT_FRAME_DATA;
- if ((gif_data[2] == 0x0b) &&
- (strncmp((const char *) gif_data + 3,
- "NETSCAPE2.0", 11) == 0) &&
- (gif_data[14] == 0x03) &&
- (gif_data[15] == 0x01))
- gif->loop_count = gif_data[16] | (gif_data[17] << 8);
- }
-
- /* Move to the first sub-block
- * Skip 3 bytes for extension introducer, label, and extension size fields
- * Skip the extension size itself
- * The special case here is the comment extension (0xfe) because it has no
- * size field and therefore extension size is not skipped either
- */
- if (gif_data[1] == 0xfe)
- gif_data += 2;
- else
- gif_data += (3 + extension_size);
-
- /* Repeatedly skip blocks until we get a zero block or run out of data
- * This library does not process this data
- */
- block_size = 0;
- while (block_size != 1) {
- block_size = gif_data[0] + 1;
- if ((gif_bytes -= block_size) < 0)
- return GIF_INSUFFICIENT_FRAME_DATA;
- gif_data += block_size;
- }
- }
-
- /* Check if we've finished
- */
- if ((gif_bytes = (gif_end - gif_data)) < 1)
+
+ /* Initialise any extensions occurring prior to image data
+ */
+ gif->buffer_position = gif_data - gif->gif_data;
+ if ((return_value = gif_initialise_frame_extensions(gif, frame, &background_action)) != GIF_OK)
+ return return_value;
+ gif_data = (gif->gif_data + gif->buffer_position);
+ gif_bytes = (gif_end - gif_data);
+
+ /* Check if we've finished
+ */
+ if ((gif_bytes = (gif_end - gif_data)) < 1)
+ return GIF_INSUFFICIENT_FRAME_DATA;
+ else if (gif_data[0] == GIF_TRAILER) {
+ gif->buffer_position = (gif_data - gif->gif_data);
+ gif->frame_count = frame + 1;
+ return GIF_OK;
+ }
+
+ /* If we're not done, there should be an image descriptor
+ */
+ if (gif_data[0] != 0x2c) return GIF_FRAME_DATA_ERROR;
+
+ /* Do some simple boundary checking
+ */
+ offset_x = gif_data[1] | (gif_data[2] << 8);
+ offset_y = gif_data[3] | (gif_data[4] << 8);
+ width = gif_data[5] | (gif_data[6] << 8);
+ height = gif_data[7] | (gif_data[8] << 8);
+
+ /* Set up the redraw characteristics. We have to check for extending the area
+ due to multi-image frames.
+ */
+ if (!first_image) {
+ if (gif->frames[frame].redraw_x > offset_x) {
+ gif->frames[frame].redraw_width += (gif->frames[frame].redraw_x - offset_x);
+ gif->frames[frame].redraw_x = offset_x;
+ }
+ if (gif->frames[frame].redraw_y > offset_y) {
+ gif->frames[frame].redraw_height += (gif->frames[frame].redraw_y - offset_y);
+ gif->frames[frame].redraw_y = offset_y;
+ }
+ if ((offset_x + width) > (gif->frames[frame].redraw_x + gif->frames[frame].redraw_width))
+ gif->frames[frame].redraw_width = (offset_x + width) - gif->frames[frame].redraw_x;
+ if ((offset_y + height) > (gif->frames[frame].redraw_y + gif->frames[frame].redraw_height))
+ gif->frames[frame].redraw_height = (offset_y + height) - gif->frames[frame].redraw_y;
+ } else {
+ first_image = false;
+ gif->frames[frame].redraw_x = offset_x;
+ gif->frames[frame].redraw_y = offset_y;
+ gif->frames[frame].redraw_width = width;
+ gif->frames[frame].redraw_height = height;
+ }
+
+ /* if we are clearing the background then we need to redraw enough to cover the previous
+ frame too
+ */
+ gif->frames[frame].redraw_required = ((background_action == 2) || (background_action == 3));
+
+ /* Boundary checking - shouldn't ever happen except with junk data
+ */
+ if (gif_initialise_sprite(gif, (offset_x + width), (offset_y + height), bitmap_callbacks))
+ return GIF_INSUFFICIENT_MEMORY;
+
+ /* Decode the flags
+ */
+ flags = gif_data[9];
+ colour_table_size = 2 << (flags & 0x07);
+
+ /* Move our data onwards and remember we've got a bit of this frame
+ */
+ gif_data += 10;
+ gif_bytes = (gif_end - gif_data);
+ gif->frame_count_partial = frame + 1;
+
+ /* Skip the local colour table
+ */
+ if (flags & 0x80) {
+ gif_data += 3 * colour_table_size;
+ if ((gif_bytes = (gif_end - gif_data)) < 0)
return GIF_INSUFFICIENT_FRAME_DATA;
- else if (gif_data[0] == GIF_TRAILER) {
- gif->buffer_position = gif_data - gif->gif_data;
- gif->frame_count = frame + 1;
- return GIF_OK;
- }
-
- /* If we're not done, there should be an image descriptor
- */
- if (gif_data[0] != 0x2c) return GIF_FRAME_DATA_ERROR;
-
- /* Do some simple boundary checking
- */
- offset_x = gif_data[1] | (gif_data[2] << 8);
- offset_y = gif_data[3] | (gif_data[4] << 8);
- width = gif_data[5] | (gif_data[6] << 8);
- height = gif_data[7] | (gif_data[8] << 8);
-
- /* Set up the redraw characteristics. We have to check for extending the area
- due to multi-image frames.
- */
- if (!first_image) {
- if (gif->frames[frame].redraw_x > offset_x) {
- gif->frames[frame].redraw_width += (gif->frames[frame].redraw_x - offset_x);
- gif->frames[frame].redraw_x = offset_x;
- }
- if (gif->frames[frame].redraw_y > offset_y) {
- gif->frames[frame].redraw_height += (gif->frames[frame].redraw_y - offset_y);
- gif->frames[frame].redraw_y = offset_y;
- }
- if ((offset_x + width) > (gif->frames[frame].redraw_x + gif->frames[frame].redraw_width))
- gif->frames[frame].redraw_width = (offset_x + width) - gif->frames[frame].redraw_x;
- if ((offset_y + height) > (gif->frames[frame].redraw_y + gif->frames[frame].redraw_height))
- gif->frames[frame].redraw_height = (offset_y + height) - gif->frames[frame].redraw_y;
- } else {
- first_image = false;
- gif->frames[frame].redraw_x = offset_x;
- gif->frames[frame].redraw_y = offset_y;
- gif->frames[frame].redraw_width = width;
- gif->frames[frame].redraw_height = height;
- }
-
- /* if we are clearing the background then we need to redraw enough to cover the previous
- frame too
- */
- gif->frames[frame].redraw_required = ((background_action == 2) || (background_action == 3));
-
- /* Boundary checking - shouldn't ever happen except with junk data
- */
- if (gif_initialise_sprite(gif, (offset_x + width), (offset_y + height), bitmap_callbacks))
- return GIF_INSUFFICIENT_MEMORY;
-
- /* Decode the flags
- */
- flags = gif_data[9];
- colour_table_size = 2 << (flags & 0x07);
-
- /* Move our data onwards and remember we've got a bit of this frame
- */
- gif_data += 10;
- gif_bytes = (gif_end - gif_data);
- gif->frame_count_partial = frame + 1;
-
- /* Skip the local colour table
- */
- if (flags & 0x80) {
- gif_data += 3 * colour_table_size;
- if ((gif_bytes = (gif_end - gif_data)) < 0)
- return GIF_INSUFFICIENT_FRAME_DATA;
- }
-
- /* Ensure we have a correct code size
- */
- if (gif_data[0] > GIF_MAX_LZW)
- return GIF_DATA_ERROR;
-
- /* Move our pointer to the actual image data
- */
- gif_data++;
- if (--gif_bytes < 0)
+ }
+
+ /* Ensure we have a correct code size
+ */
+ if (gif_data[0] > GIF_MAX_LZW)
+ return GIF_DATA_ERROR;
+
+ /* Move our pointer to the actual image data
+ */
+ gif_data++;
+ if (--gif_bytes < 0)
+ return GIF_INSUFFICIENT_FRAME_DATA;
+
+ /* Repeatedly skip blocks until we get a zero block or run out of data
+ * These blocks of image data are processed later by gif_decode_frame()
+ */
+ block_size = 0;
+ while (block_size != 1) {
+ block_size = gif_data[0] + 1;
+ if ((gif_bytes -= block_size) < 0)
return GIF_INSUFFICIENT_FRAME_DATA;
+ gif_data += block_size;
+ }
+
+ /* Add the frame and set the display flag
+ */
+ gif->buffer_position = gif_data - gif->gif_data;
+ gif->frame_count = frame + 1;
+ gif->frames[frame].display = true;
+
+ /* Check if we've finished
+ */
+ if (gif_bytes < 1)
+ return GIF_INSUFFICIENT_FRAME_DATA;
+ else
+ if (gif_data[0] == GIF_TRAILER) return GIF_OK;
+ return GIF_WORKING;
+}
+
+/** Attempts to initialise the frame's extensions
+
+ @return GIF_INSUFFICIENT_FRAME_DATA for insufficient data to complete the frame
+ GIF_OK for successful initialisation
+*/
+static gif_result gif_initialise_frame_extensions(struct gif_animation *gif, const int frame, unsigned int *background_action_p) {
+ unsigned char *gif_data, *gif_end;
+ int gif_bytes;
+ unsigned int extension_size, block_size;
+
+ /* Get our buffer position etc.
+ */
+ gif_data = (unsigned char *)(gif->gif_data + gif->buffer_position);
+ gif_end = (unsigned char *)(gif->gif_data + gif->buffer_size);
+ gif_bytes = (gif_end - gif_data);
+
+ /* Initialise the extensions
+ */
+ *background_action_p = 0;
+ while (gif_data[0] == 0x21) {
+ /* Get the extension size
+ */
+ extension_size = gif_data[2];
+
+ /* Graphic control extension - store the frame delay.
+ */
+ if (gif_data[1] == 0xf9) {
+ if (gif_bytes < 6) return GIF_INSUFFICIENT_FRAME_DATA;
+ gif->frames[frame].frame_delay = gif_data[4] | (gif_data[5] << 8);
+ *background_action_p = ((gif_data[3] & 0x1c) >> 2);
+
+ /* Application extension - handle NETSCAPE2.0 looping
+ */
+ } else if (gif_data[1] == 0xff) {
+ if (gif_bytes < 18) return GIF_INSUFFICIENT_FRAME_DATA;
+ if ((gif_data[2] == 0x0b) &&
+ (strncmp((const char *) gif_data + 3,
+ "NETSCAPE2.0", 11) == 0) &&
+ (gif_data[14] == 0x03) &&
+ (gif_data[15] == 0x01))
+ gif->loop_count = gif_data[16] | (gif_data[17] << 8);
+ }
+
+ /* Move to the first sub-block
+ * Skip 3 bytes for extension introducer, label, and extension size fields
+ * Skip the extension size itself
+ * The special case here is the comment extension (0xfe) because it has no
+ * size field and therefore extension size is not skipped either
+ */
+ if (gif_data[1] == 0xfe)
+ gif_data += 2;
+ else
+ gif_data += (3 + extension_size);
/* Repeatedly skip blocks until we get a zero block or run out of data
- * These blocks of image data are processed later by gif_decode_frame()
+ * This library does not process this data
*/
block_size = 0;
while (block_size != 1) {
@@ -558,22 +610,12 @@
return GIF_INSUFFICIENT_FRAME_DATA;
gif_data += block_size;
}
-
- /* Check for end of data
- */
- gif->buffer_position = gif_data - gif->gif_data;
- gif->frame_count = frame + 1;
- gif->frames[frame].display = true;
- more_images &= !((gif_bytes < 1) || (gif_data[0] == GIF_TRAILER));
- }
-
- /* Check if we've finished
- */
- if (gif_bytes < 1)
- return GIF_INSUFFICIENT_FRAME_DATA;
- else
- if (gif_data[0] == GIF_TRAILER) return GIF_OK;
- return GIF_WORKING;
+ }
+
+ /* Set buffer position and return
+ */
+ gif->buffer_position = (gif_data - gif->gif_data);
+ return GIF_OK;
}
@@ -589,15 +631,13 @@
*/
gif_result gif_decode_frame(struct gif_animation *gif, unsigned int frame, gif_bitmap_callback_vt *bitmap_callbacks) {
unsigned int index = 0;
- unsigned char *gif_data;
- unsigned char *gif_end;
+ unsigned char *gif_data, *gif_end;
int gif_bytes;
unsigned int width, height, offset_x, offset_y;
unsigned int flags, colour_table_size, interlace;
unsigned int *colour_table;
unsigned int *frame_data = 0; // Set to 0 for no warnings
unsigned int *frame_scanline;
- unsigned int extension_size;
unsigned int background_action;
int transparency_index = -1;
unsigned int save_buffer_position;
@@ -605,11 +645,9 @@
unsigned int x, y, decode_y, burst_bytes;
unsigned int block_size;
register int colour;
- bool more_images = true;
/* Ensure this frame is supposed to be decoded
*/
- gif->current_error = 0;
if (gif->frames[frame].display == false) {
gif->current_error = GIF_FRAME_NO_DISPLAY;
return GIF_OK;
@@ -664,243 +702,196 @@
*/
save_buffer_position = gif->buffer_position;
gif->buffer_position = gif_data - gif->gif_data;
- gif_data = gif->gif_data + gif->buffer_position;
-
- /* We've got to do this more than one time if we've got multiple images
- */
- while (more_images) {
- background_action = 0;
-
- /* Decode the extensions
- */
- while (gif_data[0] == 0x21) {
-
- /* Get the extension size
+
+ /* Decode any extensions occurring prior to image data
+ */
+ if ((return_value = gif_decode_frame_extensions(gif, &background_action, &flags, &transparency_index)) != GIF_OK)
+ goto gif_decode_frame_exit;
+ gif_data = (gif->gif_data + gif->buffer_position);
+ gif_bytes = (gif_end - gif_data);
+
+ /* Ensure we have enough data for the 10-byte image descriptor + 1-byte gif trailer
+ */
+ if (gif_bytes < 12) {
+ return_value = GIF_INSUFFICIENT_FRAME_DATA;
+ goto gif_decode_frame_exit;
+ }
+
+ /* 10-byte Image Descriptor is:
+ *
+ * +0 CHAR Image Separator (0x2c)
+ * +1 SHORT Image Left Position
+ * +3 SHORT Image Top Position
+ * +5 SHORT Width
+ * +7 SHORT Height
+ * +9 CHAR __Packed Fields__
+ * 1BIT Local Color Table Flag
+ * 1BIT Interlace Flag
+ * 1BIT Sort Flag
+ * 2BITS Reserved
+ * 3BITS Size of Local Color Table
+ */
+ if (gif_data[0] != 0x2c) {
+ return_value = GIF_DATA_ERROR;
+ goto gif_decode_frame_exit;
+ }
+ offset_x = gif_data[1] | (gif_data[2] << 8);
+ offset_y = gif_data[3] | (gif_data[4] << 8);
+ width = gif_data[5] | (gif_data[6] << 8);
+ height = gif_data[7] | (gif_data[8] << 8);
+
+ /* Boundary checking - shouldn't ever happen except unless the data has been
+ modified since initialisation.
+ */
+ if ((offset_x + width > gif->width) || (offset_y + height > gif->height)) {
+ return_value = GIF_DATA_ERROR;
+ goto gif_decode_frame_exit;
+ }
+
+ /* Decode the flags
+ */
+ flags = gif_data[9];
+ colour_table_size = 2 << (flags & 0x07);
+ interlace = flags & 0x40;
+
+ /* Move our pointer to the colour table or image data (if no colour table is given)
+ */
+ gif_data += 10;
+ gif_bytes = (gif_end - gif_data);
+
+ /* Set up the colour table
+ */
+ if (flags & 0x80) {
+ if (gif_bytes < (int)(3 * colour_table_size)) {
+ return_value = GIF_INSUFFICIENT_FRAME_DATA;
+ goto gif_decode_frame_exit;
+ }
+ colour_table = gif->local_colour_table;
+ if (!clear_image) {
+ for (index = 0; index < colour_table_size; index++) {
+ char colour[] = {gif_data[0], gif_data[1],
+ gif_data[2], (char)0xff};
+ colour_table[index] = *((int *) colour);
+ gif_data += 3;
+ }
+ } else {
+ gif_data += 3 * colour_table_size;
+ }
+ gif_bytes = (gif_end - gif_data);
+ } else {
+ colour_table = gif->global_colour_table;
+ }
+
+ /* Check if we've finished
+ */
+ if (gif_bytes < 1) {
+ return_value = GIF_INSUFFICIENT_FRAME_DATA;
+ goto gif_decode_frame_exit;
+ } else if (gif_data[0] == GIF_TRAILER) {
+ return_value = GIF_OK;
+ goto gif_decode_frame_exit;
+ }
+
+ /* If we are clearing the image we just clear, if not decode
+ */
+ if (!clear_image) {
+ /* Ensure we have enough data for the 1-byte LZW code size + 1-byte gif trailer
+ */
+ if (gif_bytes < 2) {
+ return_value = GIF_INSUFFICIENT_FRAME_DATA;
+ goto gif_decode_frame_exit;
+ /* If we only have the 1-byte LZW code size + 1-byte gif trailer, we're finished
+ */
+ } else if ((gif_bytes = 2) && (gif_data[1] == GIF_TRAILER)) {
+ return_value = GIF_OK;
+ goto gif_decode_frame_exit;
+ }
+
+ /* Set our dirty status
+ */
+ if ((background_action == 2) || (background_action == 3))
+ gif->dirty_frame = frame;
+
+ /* Initialise the LZW decoding
+ */
+ set_code_size = gif_data[0];
+ gif->buffer_position = (gif_data - gif->gif_data) + 1;
+
+ /* Set our code variables
+ */
+ code_size = set_code_size + 1;
+ clear_code = (1 << set_code_size);
+ end_code = clear_code + 1;
+ max_code_size = clear_code << 1;
+ max_code = clear_code + 2;
+ curbit = lastbit = 0;
+ last_byte = 2;
+ get_done = false;
+ direct = buf;
+ gif_init_LZW(gif);
+
+ /* Decompress the data
+ */
+ for (y = 0; y < height; y++) {
+ if (interlace)
+ decode_y = gif_interlaced_line(height, y) + offset_y;
+ else
+ decode_y = y + offset_y;
+ frame_scanline = frame_data + offset_x + (decode_y * gif->width);
+
+ /* Rather than decoding pixel by pixel, we try to burst out streams
+ of data to remove the need for end-of data checks every pixel.
*/
- extension_size = gif_data[2];
-
- /* Graphic control extension - store the frame delay.
- */
- if (gif_data[1] == 0xf9) {
- if (gif_bytes < 7) {
- return_value = GIF_INSUFFICIENT_FRAME_DATA;
- break;
- }
- flags = gif_data[3];
- if (flags & 0x01) transparency_index = gif_data[6];
- background_action = ((flags & 0x1c) >> 2);
- more_images = false;
- }
-
- /* Move to the first sub-block
- * Skip 3 bytes for extension introducer, label, and extension size fields
- * Skip the extension size itself
- * The special case here is the comment extension (0xfe) because it has no
- * size field and therefore extension size is not skipped either
- */
- if (gif_data[1] == 0xfe)
- gif_data += 2;
- else
- gif_data += (3 + extension_size);
-
- /* Repeatedly skip blocks until we get a zero block or run out of data
- * This library does not process this data
- */
- block_size = 0;
- while (block_size != 1) {
- block_size = gif_data[0] + 1;
- if ((gif_bytes -= block_size) < 0) {
- return_value = GIF_INSUFFICIENT_FRAME_DATA;
- goto gif_decode_frame_exit;
- }
- gif_data += block_size;
- }
- }
-
- /* Ensure we have enough data for the 10-byte image descriptor + 1-byte gif trailer
- */
- if (gif_bytes < 12) {
- return_value = GIF_INSUFFICIENT_FRAME_DATA;
- break;
- }
-
- /* 10-byte Image Descriptor is:
- *
- * +0 CHAR Image Separator (0x2c)
- * +1 SHORT Image Left Position
- * +3 SHORT Image Top Position
- * +5 SHORT Width
- * +7 SHORT Height
- * +9 CHAR __Packed Fields__
- * 1BIT Local Color Table Flag
- * 1BIT Interlace Flag
- * 1BIT Sort Flag
- * 2BITS Reserved
- * 3BITS Size of Local Color Table
- */
- if (gif_data[0] != 0x2c) {
- return_value = GIF_DATA_ERROR;
- break;
- }
- offset_x = gif_data[1] | (gif_data[2] << 8);
- offset_y = gif_data[3] | (gif_data[4] << 8);
- width = gif_data[5] | (gif_data[6] << 8);
- height = gif_data[7] | (gif_data[8] << 8);
-
- /* Boundary checking - shouldn't ever happen except unless the data has been
- modified since initialisation.
- */
- if ((offset_x + width > gif->width) || (offset_y + height > gif->height)) {
- return_value = GIF_DATA_ERROR;
- break;
- }
-
- /* Decode the flags
- */
- flags = gif_data[9];
- colour_table_size = 2 << (flags & 0x07);
- interlace = flags & 0x40;
-
- /* Move our pointer to the colour table or image data (if no colour table is given)
- */
- gif_data += 10;
- gif_bytes = (gif_end - gif_data);
-
- /* Set up the colour table
- */
- if (flags & 0x80) {
- if (gif_bytes < (int)(3 * colour_table_size)) {
- return_value = GIF_INSUFFICIENT_FRAME_DATA;
- break;
- }
- colour_table = gif->local_colour_table;
- if (!clear_image) {
- for (index = 0; index < colour_table_size; index++) {
- char colour[] = {gif_data[0], gif_data[1],
- gif_data[2], (char)0xff};
- colour_table[index] = *((int *) colour);
- gif_data += 3;
- }
- } else {
- gif_data += 3 * colour_table_size;
- }
- gif_bytes = (gif_end - gif_data);
- } else {
- colour_table = gif->global_colour_table;
- }
-
- /* Check if we've finished
- */
- if (gif_bytes < 1) {
- return_value = GIF_INSUFFICIENT_FRAME_DATA;
- break;
- } else if (gif_data[0] == GIF_TRAILER) {
- return_value = GIF_OK;
- break;
- }
-
- /* If we are clearing the image we just clear, if not decode
- */
- if (!clear_image) {
- /* Ensure we have enough data for the 1-byte LZW code size + 1-byte gif trailer
- */
- if (gif_bytes < 2) {
- return_value = GIF_INSUFFICIENT_FRAME_DATA;
- break;
- /* If we only have the 1-byte LZW code size + 1-byte gif trailer, we're finished
- */
- } else if ((gif_bytes = 2) && (gif_data[1] == GIF_TRAILER)) {
- return_value = GIF_OK;
- break;
- }
-
- /* Set our dirty status
- */
- if ((background_action == 2) || (background_action == 3))
- gif->dirty_frame = frame;
-
- /* Initialise the LZW decoding
- */
- set_code_size = gif_data[0];
- gif->buffer_position = (gif_data - gif->gif_data) + 1;
-
- /* Set our code variables
- */
- code_size = set_code_size + 1;
- clear_code = (1 << set_code_size);
- end_code = clear_code + 1;
- max_code_size = clear_code << 1;
- max_code = clear_code + 2;
- curbit = lastbit = 0;
- last_byte = 2;
- get_done = false;
- direct = buf;
- gif_init_LZW(gif);
-
- /* Decompress the data
- */
- for (y = 0; y < height; y++) {
- if (interlace)
- decode_y = gif_interlaced_line(height, y) + offset_y;
- else
- decode_y = y + offset_y;
- frame_scanline = frame_data + offset_x + (decode_y * gif->width);
-
- /* Rather than decoding pixel by pixel, we try to burst out streams
- of data to remove the need for end-of data checks every pixel.
- */
- x = width;
- while (x > 0) {
- burst_bytes = (stack_pointer - stack);
- if (burst_bytes > 0) {
- if (burst_bytes > x)
- burst_bytes = x;
- x -= burst_bytes;
- while (burst_bytes-- > 0) {
- if ((colour = *--stack_pointer) != transparency_index)
- *frame_scanline = colour_table[colour];
- frame_scanline++;
- }
- } else {
- if (!gif_next_LZW(gif)) {
- return_value = gif->current_error;
- goto gif_decode_frame_exit;
- }
+ x = width;
+ while (x > 0) {
+ burst_bytes = (stack_pointer - stack);
+ if (burst_bytes > 0) {
+ if (burst_bytes > x)
+ burst_bytes = x;
+ x -= burst_bytes;
+ while (burst_bytes-- > 0) {
+ if ((colour = *--stack_pointer) != transparency_index)
+ *frame_scanline = colour_table[colour];
+ frame_scanline++;
+ }
+ } else {
+ if (!gif_next_LZW(gif)) {
+ return_value = gif->current_error;
+ goto gif_decode_frame_exit;
}
}
}
- } else {
- /* Clear our frame
- */
- if ((background_action == 2) || (background_action == 3)) {
- for (y = 0; y < height; y++) {
- frame_scanline = frame_data + offset_x + ((offset_y + y) * gif->width);
- memset(frame_scanline, 0x00, width * 4);
- }
+ }
+ } else {
+ /* Clear our frame
+ */
+ if ((background_action == 2) || (background_action == 3)) {
+ for (y = 0; y < height; y++) {
+ frame_scanline = frame_data + offset_x + ((offset_y + y) * gif->width);
+ memset(frame_scanline, 0x00, width * 4);
}
-
- /* Repeatedly skip blocks until we get a zero block or run out of data
- */
- gif_bytes = gif->buffer_size - gif->buffer_position;
- gif_data = gif->gif_data + gif->buffer_size;
- block_size = 0;
- while (block_size != 1) {
- block_size = gif_data[0] + 1;
- if ((gif_bytes -= block_size) < 0) {
- return_value = GIF_INSUFFICIENT_FRAME_DATA;
- goto gif_decode_frame_exit;
- }
- gif_data += block_size;
+ }
+
+ /* Repeatedly skip blocks until we get a zero block or run out of data
+ */
+ gif_bytes = gif->buffer_size - gif->buffer_position;
+ gif_data = gif->gif_data + gif->buffer_size;
+ block_size = 0;
+ while (block_size != 1) {
+ block_size = gif_data[0] + 1;
+ if ((gif_bytes -= block_size) < 0) {
+ return_value = GIF_INSUFFICIENT_FRAME_DATA;
+ goto gif_decode_frame_exit;
}
- }
+ gif_data += block_size;
+ }
+ }
gif_decode_frame_exit:
- /* Check for end of data
- */
- gif->buffer_position++;
- gif_bytes = gif->buffer_size - gif->buffer_position;
- gif_data = gif->gif_data + gif->buffer_position;
- more_images &= !((gif_bytes < 1) || (gif_data[0] == GIF_TRAILER));
- }
+ /* Check for end of data
+ */
+ gif->buffer_position++;
+ gif_bytes = gif->buffer_size - gif->buffer_position;
+ gif_data = gif->gif_data + gif->buffer_position;
/* Check if we should test for optimisation
*/
@@ -919,6 +910,71 @@
*/
return return_value;
+}
+
+/** Attempts to decode the frame's extensions
+
+ @return GIF_INSUFFICIENT_FRAME_DATA for insufficient data to complete the frame
+ GIF_OK for successful decoding
+*/
+static gif_result gif_decode_frame_extensions(struct gif_animation *gif, unsigned int *background_action_p,
+ unsigned int *flags_p, int *transparency_index_p) {
+ unsigned int extension_size, block_size;
+ unsigned char *gif_data, *gif_end;
+ int gif_bytes;
+
+ /* Get our buffer position etc.
+ */
+ gif_data = (unsigned char *)(gif->gif_data + gif->buffer_position);
+ gif_end = (unsigned char *)(gif->gif_data + gif->buffer_size);
+ gif_bytes = (gif_end - gif_data);
+
+ /* Decode the extensions
+ */
+ *background_action_p = 0;
+ while (gif_data[0] == 0x21) {
+
+ /* Get the extension size
+ */
+ extension_size = gif_data[2];
+
+ /* Graphic control extension - store the frame delay.
+ */
+ if (gif_data[1] == 0xf9) {
+ if (gif_bytes < 7)
+ return GIF_INSUFFICIENT_FRAME_DATA;
+ *flags_p = gif_data[3];
+ if (*flags_p & 0x01) *transparency_index_p = gif_data[6];
+ *background_action_p = ((*flags_p & 0x1c) >> 2);
+ }
+
+ /* Move to the first sub-block
+ * Skip 3 bytes for extension introducer, label, and extension size fields
+ * Skip the extension size itself
+ * The special case here is the comment extension (0xfe) because it has no
+ * size field and therefore extension size is not skipped either
+ */
+ if (gif_data[1] == 0xfe)
+ gif_data += 2;
+ else
+ gif_data += (3 + extension_size);
+
+ /* Repeatedly skip blocks until we get a zero block or run out of data
+ * This library does not process this data
+ */
+ block_size = 0;
+ while (block_size != 1) {
+ block_size = gif_data[0] + 1;
+ if ((gif_bytes -= block_size) < 0)
+ return GIF_INSUFFICIENT_FRAME_DATA;
+ gif_data += block_size;
+ }
+ }
+
+ /* Set buffer position and return
+ */
+ gif->buffer_position = (gif_data - gif->gif_data);
+ return GIF_OK;
}
static unsigned int gif_interlaced_line(int height, int y) {
14 years, 9 months
r4430 takkaria - /trunk/hubbub/src/treebuilder/initial.c
by netsurf@semichrome.net
Author: takkaria
Date: Mon Jun 23 19:00:27 2008
New Revision: 4430
URL: http://source.netsurf-browser.org?rev=4430&view=rev
Log:
Rough and unoptimised quirks-mode detector in the "initial" tree construction phase.
Modified:
trunk/hubbub/src/treebuilder/initial.c
Modified: trunk/hubbub/src/treebuilder/initial.c
URL: http://source.netsurf-browser.org/trunk/hubbub/src/treebuilder/initial.c?...
==============================================================================
--- trunk/hubbub/src/treebuilder/initial.c (original)
+++ trunk/hubbub/src/treebuilder/initial.c Mon Jun 23 19:00:27 2008
@@ -3,6 +3,8 @@
* Licensed under the MIT License,
* http://www.opensource.org/licenses/mit-license.php
* Copyright 2008 John-Mark Bell <jmb(a)netsurf-browser.org>
+ *
+ * Up-to-date with 19 June 2008 spec.
*/
#include <assert.h>
@@ -12,6 +14,225 @@
#include "treebuilder/internal.h"
#include "treebuilder/treebuilder.h"
#include "utils/utils.h"
+
+
+#define S(s) { s, sizeof s }
+
+struct {
+ const char *name;
+ size_t len;
+} public_doctypes[] = {
+ S("+//Silmaril//dtd html Pro v0r11 19970101//"),
+ S("-//AdvaSoft Ltd//DTD HTML 3.0 asWedit + extensions//"),
+ S("-//AS//DTD HTML 3.0 asWedit + extensions//"),
+ S("-//IETF//DTD HTML 2.0 Level 1//"),
+ S("-//IETF//DTD HTML 2.0 Level 2//"),
+ S("-//IETF//DTD HTML 2.0 Strict Level 1//"),
+ S("-//IETF//DTD HTML 2.0 Strict Level 2//"),
+ S("-//IETF//DTD HTML 2.0 Strict//"),
+ S("-//IETF//DTD HTML 2.0//"),
+ S("-//IETF//DTD HTML 2.1E//"),
+ S("-//IETF//DTD HTML 3.0//"),
+ S("-//IETF//DTD HTML 3.2 Final//"),
+ S("-//IETF//DTD HTML 3.2//"),
+ S("-//IETF//DTD HTML 3//"),
+ S("-//IETF//DTD HTML Level 0//"),
+ S("-//IETF//DTD HTML Level 1//"),
+ S("-//IETF//DTD HTML Level 2//"),
+ S("-//IETF//DTD HTML Level 3//"),
+ S("-//IETF//DTD HTML Strict Level 0//"),
+ S("-//IETF//DTD HTML Strict Level 1//"),
+ S("-//IETF//DTD HTML Strict Level 2//"),
+ S("-//IETF//DTD HTML Strict Level 3//"),
+ S("-//IETF//DTD HTML Strict//"),
+ S("-//IETF//DTD HTML//"),
+ S("-//Metrius//DTD Metrius Presentational//"),
+ S("-//Microsoft//DTD Internet Explorer 2.0 HTML Strict//"),
+ S("-//Microsoft//DTD Internet Explorer 2.0 HTML//"),
+ S("-//Microsoft//DTD Internet Explorer 2.0 Tables//"),
+ S("-//Microsoft//DTD Internet Explorer 3.0 HTML Strict//"),
+ S("-//Microsoft//DTD Internet Explorer 3.0 HTML//"),
+ S("-//Microsoft//DTD Internet Explorer 3.0 Tables//"),
+ S("-//Netscape Comm. Corp.//DTD HTML//"),
+ S("-//Netscape Comm. Corp.//DTD Strict HTML//"),
+ S("-//O'Reilly and Associates//DTD HTML 2.0//"),
+ S("-//O'Reilly and Associates//DTD HTML Extended 1.0//"),
+ S("-//O'Reilly and Associates//DTD HTML Extended Relaxed 1.0//"),
+ S("-//SoftQuad Software//DTD HoTMetaL PRO 6.0::19990601::extensions to HTML 4.0//"),
+ S("-//SoftQuad//DTD HoTMetaL PRO 4.0::19971010::extensions to HTML 4.0//"),
+ S("-//Spyglass//DTD HTML 2.0 Extended//"),
+ S("-//SQ//DTD HTML 2.0 HoTMetaL + extensions//"),
+ S("-//Sun Microsystems Corp.//DTD HotJava HTML//"),
+ S("-//Sun Microsystems Corp.//DTD HotJava Strict HTML//"),
+ S("-//W3C//DTD HTML 3 1995-03-24//"),
+ S("-//W3C//DTD HTML 3.2 Draft//"),
+ S("-//W3C//DTD HTML 3.2 Final//"),
+ S("-//W3C//DTD HTML 3.2//"),
+ S("-//W3C//DTD HTML 3.2S Draft//"),
+ S("-//W3C//DTD HTML 4.0 Frameset//"),
+ S("-//W3C//DTD HTML 4.0 Transitional//"),
+ S("-//W3C//DTD HTML Experimental 19960712//"),
+ S("-//W3C//DTD HTML Experimental 970421//"),
+ S("-//W3C//DTD W3 HTML//"),
+ S("-//W3O//DTD W3 HTML 3.0//"),
+};
+
+#undef S
+
+
+/**
+ * Check if one string starts with another.
+ *
+ * \param a String to compare
+ * \param a_len Length of first string
+ * \param b String to compare
+ * \param b_len Length of second string
+ */
+static bool starts_with(const uint8_t *a, size_t a_len, const uint8_t *b,
+ size_t b_len)
+{
+ uint8_t z1, z2;
+
+ if (a_len < b_len)
+ return false;
+
+ for (const uint8_t *s1 = a, *s2 = b; b_len > 0; s1++, s2++, b_len--)
+ {
+ z1 = (*s1 & ~0x20);
+ z2 = (*s2 & ~0x20);
+ if (z1 != z2) return false;
+ if (!z1) return true;
+ }
+
+ return true;
+}
+
+/**
+ * Check that one string is exactly equal to another
+ *
+ * \param a String to compare
+ * \param a_len Length of first string
+ * \param b String to compare
+ * \param b_len Length of second string
+ */
+static bool match(const uint8_t *a, size_t a_len, const uint8_t *b,
+ size_t b_len)
+{
+ uint8_t z1, z2;
+
+ if (a_len != b_len)
+ return false;
+
+ for (const uint8_t *s1 = a, *s2 = b; b_len > 0; s1++, s2++, b_len--)
+ {
+ z1 = (*s1 & ~0x20);
+ z2 = (*s2 & ~0x20);
+ if (z1 != z2) return false;
+ }
+
+ return true;
+}
+
+
+/**
+ * Determine whether this doctype triggers full quirks mode
+ *
+ * \param cdoc The doctype to examine
+ * \return True to trigger quirks, false otherwise
+ */
+static bool lookup_full_quirks(hubbub_treebuilder *treebuilder,
+ const hubbub_doctype *cdoc)
+{
+ size_t i;
+
+ const uint8_t *name = treebuilder->input_buffer + cdoc->name.data.off;
+ size_t name_len = cdoc->name.len;
+
+ const uint8_t *public_id = treebuilder->input_buffer +
+ cdoc->public_id.data.off;
+ size_t public_id_len = cdoc->public_id.len;
+
+ const uint8_t *system_id = treebuilder->input_buffer +
+ cdoc->system_id.data.off;
+ size_t system_id_len = cdoc->system_id.len;
+
+#define S(s) (uint8_t *) s, sizeof s
+
+ /* Check the name is "HTML" (case-insensitively) */
+ if (!match(name, name_len, S("HTML")))
+ return true;
+
+ /* No public id means not-quirks */
+ if (cdoc->public_missing) return false;
+
+ for (i = 0; i < sizeof public_doctypes / sizeof public_doctypes[0]; i++)
+ {
+ if (starts_with(public_id, public_id_len,
+ (uint8_t *) public_doctypes[i].name,
+ public_doctypes[i].len)) {
+ return true;
+ }
+ }
+
+ if (match(public_id, public_id_len,
+ S("-//W3O//DTD W3 HTML Strict 3.0//EN//")) ||
+ match(public_id, public_id_len,
+ S("-/W3C/DTD HTML 4.0 Transitional/EN")) ||
+ match(public_id, public_id_len,
+ S("HTML")) ||
+ match(system_id, system_id_len,
+ S("http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd"))) {
+ return true;
+ }
+
+ if (cdoc->system_missing == true &&
+ (starts_with(public_id, public_id_len,
+ S("-//W3C//DTD HTML 4.01 Frameset//")) ||
+ starts_with(public_id, public_id_len,
+ S("-//W3C//DTD HTML 4.01 Transitional//")))) {
+ return true;
+ }
+
+#undef S
+
+ return false;
+}
+
+
+/**
+ * Determine whether this doctype triggers limited quirks mode
+ *
+ * \param cdoc The doctype to examine
+ * \return True to trigger quirks, false otherwise
+ */
+static bool lookup_limited_quirks(hubbub_treebuilder *treebuilder,
+ const hubbub_doctype *cdoc)
+{
+ const uint8_t *public_id = treebuilder->input_buffer +
+ cdoc->public_id.data.off;
+ size_t public_id_len = cdoc->public_id.len;
+
+#define S(s) (uint8_t *) s, sizeof s
+
+ if (starts_with(public_id, public_id_len,
+ S("-//W3C//DTD XHTML 1.0 Frameset//")) ||
+ starts_with(public_id, public_id_len,
+ S("-//W3C//DTD XHTML 1.0 Transitional//"))) {
+ return true;
+ }
+
+ if (cdoc->system_missing == false &&
+ (starts_with(public_id, public_id_len,
+ S("-//W3C//DTD HTML 4.01 Frameset//")) ||
+ starts_with(public_id, public_id_len,
+ S("-//W3C//DTD HTML 4.01 Transitional//")))) {
+ return true;
+ }
+
+#undef S
+
+ return false;
+}
/**
@@ -71,7 +292,19 @@
doctype);
}
- /* \todo look up the doctype in a catalog */
+ const hubbub_doctype *cdoc = &token->data.doctype;
+
+ /* Work out whether we need quirks mode or not */
+ if (cdoc->force_quirks == true ||
+ lookup_full_quirks(treebuilder, cdoc)) {
+ treebuilder->tree_handler->set_quirks_mode(
+ treebuilder->tree_handler->ctx,
+ HUBBUB_QUIRKS_MODE_FULL);
+ } else if (lookup_limited_quirks(treebuilder, cdoc)) {
+ treebuilder->tree_handler->set_quirks_mode(
+ treebuilder->tree_handler->ctx,
+ HUBBUB_QUIRKS_MODE_LIMITED);
+ }
treebuilder->tree_handler->unref_node(
treebuilder->tree_handler->ctx, appended);
14 years, 9 months
r4429 takkaria - in /trunk/hubbub/src/treebuilder: Makefile after_head.c before_head.c before_html.c generic_rcdata.c in_head.c in_head_noscript.c initial.c internal.h modes.h script_collect.c treebuilder.c
by netsurf@semichrome.net
Author: takkaria
Date: Mon Jun 23 15:22:25 2008
New Revision: 4429
URL: http://source.netsurf-browser.org?rev=4429&view=rev
Log:
Put each insertion mode into its own C file, so that treebuilder.c doesn't get extremely long.
Added:
trunk/hubbub/src/treebuilder/after_head.c (with props)
trunk/hubbub/src/treebuilder/before_head.c (with props)
trunk/hubbub/src/treebuilder/before_html.c (with props)
trunk/hubbub/src/treebuilder/generic_rcdata.c (with props)
trunk/hubbub/src/treebuilder/in_head.c (with props)
trunk/hubbub/src/treebuilder/in_head_noscript.c (with props)
trunk/hubbub/src/treebuilder/initial.c (with props)
trunk/hubbub/src/treebuilder/modes.h (with props)
trunk/hubbub/src/treebuilder/script_collect.c (with props)
Modified:
trunk/hubbub/src/treebuilder/Makefile
trunk/hubbub/src/treebuilder/internal.h
trunk/hubbub/src/treebuilder/treebuilder.c
Modified: trunk/hubbub/src/treebuilder/Makefile
URL: http://source.netsurf-browser.org/trunk/hubbub/src/treebuilder/Makefile?r...
==============================================================================
--- trunk/hubbub/src/treebuilder/Makefile (original)
+++ trunk/hubbub/src/treebuilder/Makefile Mon Jun 23 15:22:25 2008
@@ -32,7 +32,10 @@
d := $(DIR)
# Sources
-SRCS_$(d) := in_body.c treebuilder.c
+SRCS_$(d) := treebuilder.c \
+ initial.c before_html.c before_head.c in_head.c \
+ in_head_noscript.c after_head.c in_body.c \
+ generic_rcdata.c script_collect.c
# Append to sources for component
SOURCES += $(addprefix $(d), $(SRCS_$(d)))
Added: trunk/hubbub/src/treebuilder/after_head.c
URL: http://source.netsurf-browser.org/trunk/hubbub/src/treebuilder/after_head...
==============================================================================
--- trunk/hubbub/src/treebuilder/after_head.c (added)
+++ trunk/hubbub/src/treebuilder/after_head.c Mon Jun 23 15:22:25 2008
@@ -1,0 +1,127 @@
+/*
+ * This file is part of Hubbub.
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2008 John-Mark Bell <jmb(a)netsurf-browser.org>
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include "treebuilder/modes.h"
+#include "treebuilder/internal.h"
+#include "treebuilder/treebuilder.h"
+#include "utils/utils.h"
+
+
+/**
+ * Handle tokens in "after head" insertion mode
+ *
+ * \param treebuilder The treebuilder instance
+ * \param token The token to process
+ * \return True to reprocess the token, false otherwise
+ */
+bool handle_after_head(hubbub_treebuilder *treebuilder,
+ const hubbub_token *token)
+{
+ bool reprocess = false;
+ bool handled = false;
+
+ switch (token->type) {
+ case HUBBUB_TOKEN_CHARACTER:
+ append_text(treebuilder, &token->data.character);
+ break;
+ case HUBBUB_TOKEN_COMMENT:
+ process_comment_append(treebuilder, token,
+ treebuilder->context.element_stack[
+ treebuilder->context.current_node].node);
+ break;
+ case HUBBUB_TOKEN_DOCTYPE:
+ /** \todo parse error */
+ break;
+ case HUBBUB_TOKEN_START_TAG:
+ {
+ element_type type = element_type_from_name(treebuilder,
+ &token->data.tag.name);
+
+ if (type == HTML) {
+ /* Process as if "in body" */
+ process_tag_in_body(treebuilder, token);
+ } else if (type == BODY) {
+ handled = true;
+ } else if (type == FRAMESET) {
+ insert_element(treebuilder, &token->data.tag);
+ treebuilder->context.mode = IN_FRAMESET;
+ } else if (type == BASE || type == LINK || type == META ||
+ type == NOFRAMES || type == SCRIPT ||
+ type == STYLE || type == TITLE) {
+ element_type otype;
+ void *node;
+
+ /** \todo parse error */
+
+ if (!element_stack_push(treebuilder,
+ HEAD,
+ treebuilder->context.head_element)) {
+ /** \todo errors */
+ }
+
+
+ /* This should be identical to handling "in head" */
+ if (type == BASE || type == LINK || type == META) {
+ /** \todo ack sc flag */
+
+ process_base_link_meta_in_head(treebuilder,
+ token, type);
+ } else if (type == SCRIPT) {
+ process_script_in_head(treebuilder, token);
+ } else if (type == STYLE || type == NOFRAMES) {
+ parse_generic_rcdata(treebuilder, token, false);
+ } else if (type == TITLE) {
+ parse_generic_rcdata(treebuilder, token, true);
+ }
+
+ if (!element_stack_pop(treebuilder, &otype, &node)) {
+ /** \todo errors */
+ }
+
+ /* No need to unref node as we never increased
+ * its reference count when pushing it on the stack */
+ } else if (type == HEAD) {
+ /** \todo parse error */
+ } else {
+ reprocess = true;
+ }
+ }
+ break;
+ case HUBBUB_TOKEN_END_TAG:
+ /** \parse error */
+ break;
+ case HUBBUB_TOKEN_EOF:
+ reprocess = true;
+ break;
+ }
+
+ if (handled || reprocess) {
+ hubbub_tag tag;
+
+ if (reprocess) {
+ /* Manufacture body */
+ tag.name.type = HUBBUB_STRING_PTR;
+ tag.name.data.ptr = (const uint8_t *) "body";
+ tag.name.len = SLEN("body");
+
+ tag.n_attributes = 0;
+ tag.attributes = NULL;
+ } else {
+ tag = token->data.tag;
+ }
+
+ insert_element(treebuilder, &tag);
+
+ treebuilder->context.mode = IN_BODY;
+ }
+
+ return reprocess;
+}
+
Propchange: trunk/hubbub/src/treebuilder/after_head.c
------------------------------------------------------------------------------
svn:eol-style = native
Added: trunk/hubbub/src/treebuilder/before_head.c
URL: http://source.netsurf-browser.org/trunk/hubbub/src/treebuilder/before_hea...
==============================================================================
--- trunk/hubbub/src/treebuilder/before_head.c (added)
+++ trunk/hubbub/src/treebuilder/before_head.c Mon Jun 23 15:22:25 2008
@@ -1,0 +1,106 @@
+/*
+ * This file is part of Hubbub.
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2008 John-Mark Bell <jmb(a)netsurf-browser.org>
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include "treebuilder/modes.h"
+#include "treebuilder/internal.h"
+#include "treebuilder/treebuilder.h"
+#include "utils/utils.h"
+
+
+/**
+ * Handle token in "before head" insertion mode
+ *
+ * \param treebuilder The treebuilder instance
+ * \param token The token to handle
+ * \return True to reprocess token, false otherwise
+ */
+bool handle_before_head(hubbub_treebuilder *treebuilder,
+ const hubbub_token *token)
+{
+ bool reprocess = false;
+ bool handled = false;
+
+ switch (token->type) {
+ case HUBBUB_TOKEN_CHARACTER:
+ reprocess = process_characters_expect_whitespace(treebuilder,
+ token, false);
+ break;
+ case HUBBUB_TOKEN_COMMENT:
+ process_comment_append(treebuilder, token,
+ treebuilder->context.element_stack[
+ treebuilder->context.current_node].node);
+ break;
+ case HUBBUB_TOKEN_DOCTYPE:
+ /** \todo parse error */
+ break;
+ case HUBBUB_TOKEN_START_TAG:
+ {
+ element_type type = element_type_from_name(treebuilder,
+ &token->data.tag.name);
+
+ if (type == HTML) {
+ /* Process as if "in body" */
+ process_tag_in_body(treebuilder, token);
+ } else if (type == HEAD) {
+ handled = true;
+ } else {
+ reprocess = true;
+ }
+ }
+ break;
+ case HUBBUB_TOKEN_END_TAG:
+ {
+ element_type type = element_type_from_name(treebuilder,
+ &token->data.tag.name);
+
+ if (type == HEAD || type == BR) {
+ reprocess = true;
+ } else {
+ /** \todo parse error */
+ }
+ }
+ break;
+ case HUBBUB_TOKEN_EOF:
+ reprocess = true;
+ break;
+ }
+
+ if (handled || reprocess) {
+ hubbub_tag tag;
+
+ if (reprocess) {
+ /* Manufacture head tag */
+ tag.name.type = HUBBUB_STRING_PTR;
+ tag.name.data.ptr = (const uint8_t *) "head";
+ tag.name.len = SLEN("head");
+
+ tag.n_attributes = 0;
+ tag.attributes = NULL;
+ } else {
+ tag = token->data.tag;
+ }
+
+ insert_element(treebuilder, &tag);
+
+ treebuilder->tree_handler->ref_node(
+ treebuilder->tree_handler->ctx,
+ treebuilder->context.element_stack[
+ treebuilder->context.current_node].node);
+
+ treebuilder->context.head_element =
+ treebuilder->context.element_stack[
+ treebuilder->context.current_node].node;
+
+ treebuilder->context.mode = IN_HEAD;
+ }
+
+ return reprocess;
+}
+
Propchange: trunk/hubbub/src/treebuilder/before_head.c
------------------------------------------------------------------------------
svn:eol-style = native
Added: trunk/hubbub/src/treebuilder/before_html.c
URL: http://source.netsurf-browser.org/trunk/hubbub/src/treebuilder/before_htm...
==============================================================================
--- trunk/hubbub/src/treebuilder/before_html.c (added)
+++ trunk/hubbub/src/treebuilder/before_html.c Mon Jun 23 15:22:25 2008
@@ -1,0 +1,126 @@
+/*
+ * This file is part of Hubbub.
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2008 John-Mark Bell <jmb(a)netsurf-browser.org>
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include "treebuilder/modes.h"
+#include "treebuilder/internal.h"
+#include "treebuilder/treebuilder.h"
+#include "utils/utils.h"
+
+
+/**
+ * Handle token in "before html" insertion mode
+ *
+ * \param treebuilder The treebuilder instance
+ * \param token The token to handle
+ * \return True to reprocess token, false otherwise
+ */
+bool handle_before_html(hubbub_treebuilder *treebuilder,
+ const hubbub_token *token)
+{
+ bool reprocess = false;
+ bool handled = false;
+
+ switch (token->type) {
+ case HUBBUB_TOKEN_DOCTYPE:
+ /** \todo parse error */
+ break;
+ case HUBBUB_TOKEN_COMMENT:
+ process_comment_append(treebuilder, token,
+ treebuilder->context.document);
+ break;
+ case HUBBUB_TOKEN_CHARACTER:
+ reprocess = process_characters_expect_whitespace(treebuilder,
+ token, false);
+ break;
+ case HUBBUB_TOKEN_START_TAG:
+ {
+ element_type type = element_type_from_name(treebuilder,
+ &token->data.tag.name);
+
+ if (type == HTML) {
+ handled = true;
+ } else {
+ reprocess = true;
+ }
+ }
+ break;
+ case HUBBUB_TOKEN_END_TAG:
+ case HUBBUB_TOKEN_EOF:
+ reprocess = true;
+ break;
+ }
+
+
+ if (handled || reprocess) {
+ int success;
+ void *html, *appended;
+
+ /* We can't use insert_element() here, as it assumes
+ * that we're inserting into current_node. There is
+ * no current_node to insert into at this point so
+ * we get to do it manually. */
+
+ if (reprocess) {
+ /* Need to manufacture html element */
+ hubbub_tag tag;
+
+ /** \todo UTF-16 */
+ tag.name.type = HUBBUB_STRING_PTR;
+ tag.name.data.ptr = (const uint8_t *) "html";
+ tag.name.len = SLEN("html");
+
+ tag.n_attributes = 0;
+ tag.attributes = NULL;
+
+ success = treebuilder->tree_handler->create_element(
+ treebuilder->tree_handler->ctx,
+ &tag, &html);
+ } else {
+ success = treebuilder->tree_handler->create_element(
+ treebuilder->tree_handler->ctx,
+ &token->data.tag, &html);
+ }
+
+ if (success != 0) {
+ /** \todo errors */
+ }
+
+ success = treebuilder->tree_handler->append_child(
+ treebuilder->tree_handler->ctx,
+ treebuilder->context.document,
+ html, &appended);
+ if (success != 0) {
+ /** \todo errors */
+ treebuilder->tree_handler->unref_node(
+ treebuilder->tree_handler->ctx,
+ html);
+ }
+
+ /* We can't use element_stack_push() here, as it
+ * assumes that current_node is pointing at the index
+ * before the one to insert at. For the first entry in
+ * the stack, this does not hold so we must insert
+ * manually. */
+ treebuilder->context.element_stack[0].type = HTML;
+ treebuilder->context.element_stack[0].node = html;
+ treebuilder->context.current_node = 0;
+
+ /** \todo cache selection algorithm */
+
+ treebuilder->tree_handler->unref_node(
+ treebuilder->tree_handler->ctx,
+ appended);
+
+ treebuilder->context.mode = BEFORE_HEAD;
+ }
+
+ return reprocess;
+}
+
Propchange: trunk/hubbub/src/treebuilder/before_html.c
------------------------------------------------------------------------------
svn:eol-style = native
Added: trunk/hubbub/src/treebuilder/generic_rcdata.c
URL: http://source.netsurf-browser.org/trunk/hubbub/src/treebuilder/generic_rc...
==============================================================================
--- trunk/hubbub/src/treebuilder/generic_rcdata.c (added)
+++ trunk/hubbub/src/treebuilder/generic_rcdata.c Mon Jun 23 15:22:25 2008
@@ -1,0 +1,123 @@
+/*
+ * This file is part of Hubbub.
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2008 John-Mark Bell <jmb(a)netsurf-browser.org>
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include "treebuilder/modes.h"
+#include "treebuilder/internal.h"
+#include "treebuilder/treebuilder.h"
+#include "utils/utils.h"
+
+
+/**
+ * Handle tokens in "generic rcdata" insertion mode
+ *
+ * \param treebuilder The treebuilder instance
+ * \param token The token to process
+ * \return True to reprocess the token, false otherwise
+ */
+bool handle_generic_rcdata(hubbub_treebuilder *treebuilder,
+ const hubbub_token *token)
+{
+ bool reprocess = false;
+ bool done = false;
+
+ if (treebuilder->context.strip_leading_lr &&
+ token->type != HUBBUB_TOKEN_CHARACTER) {
+ /* Reset the LR stripping flag */
+ treebuilder->context.strip_leading_lr = false;
+ }
+
+ switch (token->type) {
+ case HUBBUB_TOKEN_CHARACTER:
+ if (treebuilder->context.collect.string.len == 0) {
+ treebuilder->context.collect.string.data.off =
+ token->data.character.data.off;
+ }
+ treebuilder->context.collect.string.len +=
+ token->data.character.len;
+
+ if (treebuilder->context.strip_leading_lr) {
+ const uint8_t *str = treebuilder->input_buffer +
+ treebuilder->context.collect.string.data.off;
+
+ /** \todo UTF-16 */
+ if (*str == '\n') {
+ treebuilder->context.collect.string.data.off++;
+ treebuilder->context.collect.string.len--;
+ }
+
+ treebuilder->context.strip_leading_lr = false;
+ }
+ break;
+ case HUBBUB_TOKEN_END_TAG:
+ {
+ element_type type = element_type_from_name(treebuilder,
+ &token->data.tag.name);
+
+ if (type != treebuilder->context.collect.type) {
+ /** \todo parse error */
+ }
+
+ done = true;
+ }
+ break;
+ case HUBBUB_TOKEN_EOF:
+ /** \todo parse error */
+ done = reprocess = true;
+ break;
+ case HUBBUB_TOKEN_COMMENT:
+ case HUBBUB_TOKEN_DOCTYPE:
+ case HUBBUB_TOKEN_START_TAG:
+ /* Should never happen */
+ assert(0);
+ break;
+ }
+
+ if (done) {
+ int success;
+ void *text, *appended;
+
+ success = treebuilder->tree_handler->create_text(
+ treebuilder->tree_handler->ctx,
+ &treebuilder->context.collect.string,
+ &text);
+ if (success != 0) {
+ /** \todo errors */
+ }
+
+ success = treebuilder->tree_handler->append_child(
+ treebuilder->tree_handler->ctx,
+ treebuilder->context.collect.node,
+ text, &appended);
+ if (success != 0) {
+ /** \todo errors */
+ treebuilder->tree_handler->unref_node(
+ treebuilder->tree_handler->ctx,
+ text);
+ }
+
+ treebuilder->tree_handler->unref_node(
+ treebuilder->tree_handler->ctx, appended);
+ treebuilder->tree_handler->unref_node(
+ treebuilder->tree_handler->ctx, text);
+
+ /* Clean up context */
+ treebuilder->tree_handler->unref_node(
+ treebuilder->tree_handler->ctx,
+ treebuilder->context.collect.node);
+ treebuilder->context.collect.node = NULL;
+
+ /* Return to previous insertion mode */
+ treebuilder->context.mode =
+ treebuilder->context.collect.mode;
+ }
+
+ return reprocess;
+}
+
Propchange: trunk/hubbub/src/treebuilder/generic_rcdata.c
------------------------------------------------------------------------------
svn:eol-style = native
Added: trunk/hubbub/src/treebuilder/in_head.c
URL: http://source.netsurf-browser.org/trunk/hubbub/src/treebuilder/in_head.c?...
==============================================================================
--- trunk/hubbub/src/treebuilder/in_head.c (added)
+++ trunk/hubbub/src/treebuilder/in_head.c Mon Jun 23 15:22:25 2008
@@ -1,0 +1,119 @@
+/*
+ * This file is part of Hubbub.
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2008 John-Mark Bell <jmb(a)netsurf-browser.org>
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include "treebuilder/modes.h"
+#include "treebuilder/internal.h"
+#include "treebuilder/treebuilder.h"
+#include "utils/utils.h"
+
+
+/**
+ * Handle token in "in head" insertion mode
+ *
+ * \param treebuilder The treebuilder instance
+ * \param token The token to handle
+ * \return True to reprocess token, false otherwise
+ */
+bool handle_in_head(hubbub_treebuilder *treebuilder,
+ const hubbub_token *token)
+{
+ bool reprocess = false;
+ bool handled = false;
+
+ switch (token->type) {
+ case HUBBUB_TOKEN_CHARACTER:
+ reprocess = process_characters_expect_whitespace(treebuilder,
+ token, true);
+ break;
+ case HUBBUB_TOKEN_COMMENT:
+ process_comment_append(treebuilder, token,
+ treebuilder->context.element_stack[
+ treebuilder->context.current_node].node);
+ break;
+ case HUBBUB_TOKEN_DOCTYPE:
+ /** \todo parse error */
+ break;
+ case HUBBUB_TOKEN_START_TAG:
+ {
+ element_type type = element_type_from_name(treebuilder,
+ &token->data.tag.name);
+
+ if (type == HTML) {
+ /* Process as if "in body" */
+ process_tag_in_body(treebuilder, token);
+ } else if (type == BASE || type == COMMAND ||
+ type == EVENT_SOURCE || type == LINK) {
+ process_base_link_meta_in_head(treebuilder,
+ token, type);
+
+ /** \todo ack sc flag */
+ } else if (type == META) {
+ process_base_link_meta_in_head(treebuilder,
+ token, type);
+
+ /** \todo ack sc flag */
+
+ /** \todo detect charset */
+ } else if (type == TITLE) {
+ parse_generic_rcdata(treebuilder, token, true);
+ } else if (type == NOFRAMES || type == STYLE) {
+ parse_generic_rcdata(treebuilder, token, false);
+ } else if (type == NOSCRIPT) {
+ /** \todo determine if scripting is enabled */
+ if (false /*scripting_is_enabled*/) {
+ parse_generic_rcdata(treebuilder, token, false);
+ } else {
+ insert_element(treebuilder, &token->data.tag);
+ treebuilder->context.mode = IN_HEAD_NOSCRIPT;
+ }
+ } else if (type == SCRIPT) {
+ process_script_in_head(treebuilder, token);
+ } else if (type == HEAD) {
+ /** \todo parse error */
+ } else {
+ reprocess = true;
+ }
+ }
+ break;
+ case HUBBUB_TOKEN_END_TAG:
+ {
+ element_type type = element_type_from_name(treebuilder,
+ &token->data.tag.name);
+
+ if (type == HEAD) {
+ handled = true;
+ } else if (type == BR) {
+ reprocess = true;
+ } /** \todo parse error */
+ }
+ break;
+ case HUBBUB_TOKEN_EOF:
+ reprocess = true;
+ break;
+ }
+
+ if (handled || reprocess) {
+ element_type otype;
+ void *node;
+
+ if (!element_stack_pop(treebuilder, &otype, &node)) {
+ /** \todo errors */
+ }
+
+ treebuilder->tree_handler->unref_node(
+ treebuilder->tree_handler->ctx,
+ node);
+
+ treebuilder->context.mode = AFTER_HEAD;
+ }
+
+ return reprocess;
+}
+
Propchange: trunk/hubbub/src/treebuilder/in_head.c
------------------------------------------------------------------------------
svn:eol-style = native
Added: trunk/hubbub/src/treebuilder/in_head_noscript.c
URL: http://source.netsurf-browser.org/trunk/hubbub/src/treebuilder/in_head_no...
==============================================================================
--- trunk/hubbub/src/treebuilder/in_head_noscript.c (added)
+++ trunk/hubbub/src/treebuilder/in_head_noscript.c Mon Jun 23 15:22:25 2008
@@ -1,0 +1,121 @@
+/*
+ * This file is part of Hubbub.
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2008 John-Mark Bell <jmb(a)netsurf-browser.org>
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include "treebuilder/modes.h"
+#include "treebuilder/internal.h"
+#include "treebuilder/treebuilder.h"
+#include "utils/utils.h"
+
+
+/**
+ * Handle tokens in "in head noscript" insertion mode
+ *
+ * \param treebuilder The treebuilder instance
+ * \param token The token to process
+ * \return True to reprocess the token, false otherwise
+ */
+bool handle_in_head_noscript(hubbub_treebuilder *treebuilder,
+ const hubbub_token *token)
+{
+ bool reprocess = false;
+ bool handled = false;
+
+ switch (token->type) {
+ case HUBBUB_TOKEN_CHARACTER:
+ /* This should be equivalent to "in head" processing */
+ reprocess = process_characters_expect_whitespace(treebuilder,
+ token, true);
+ break;
+ case HUBBUB_TOKEN_COMMENT:
+ /* This should be equivalent to "in head" processing */
+ process_comment_append(treebuilder, token,
+ treebuilder->context.element_stack[
+ treebuilder->context.current_node].node);
+ break;
+ case HUBBUB_TOKEN_DOCTYPE:
+ /** \todo parse error */
+ break;
+ case HUBBUB_TOKEN_START_TAG:
+ {
+ element_type type = element_type_from_name(treebuilder,
+ &token->data.tag.name);
+
+ if (type == HTML) {
+ /* Process as "in body" */
+ process_tag_in_body(treebuilder, token);
+ } else if (type == NOSCRIPT) {
+ handled = true;
+ } else if (type == LINK) {
+ /* This should be equivalent to "in head" processing */
+ process_base_link_meta_in_head(treebuilder,
+ token, type);
+
+ /** \todo ack sc flag */
+ } else if (type == META) {
+ /* This should be equivalent to "in head" processing */
+ process_base_link_meta_in_head(treebuilder,
+ token, type);
+
+ /** \todo ack sc flag */
+
+ /** \todo detect charset */
+ } else if (type == NOFRAMES) {
+ /* This should be equivalent to "in head" processing */
+ parse_generic_rcdata(treebuilder, token, true);
+ } else if (type == STYLE) {
+ /* This should be equivalent to "in head" processing */
+ parse_generic_rcdata(treebuilder, token, false);
+ } else if (type == HEAD || type == NOSCRIPT) {
+ /** \todo parse error */
+ } else {
+ /** \todo parse error */
+ reprocess = true;
+ }
+ }
+ break;
+ case HUBBUB_TOKEN_END_TAG:
+ {
+ element_type type = element_type_from_name(treebuilder,
+ &token->data.tag.name);
+
+ if (type == NOSCRIPT) {
+ handled = true;
+ } else if (type == BR) {
+ /** \todo parse error */
+ reprocess = true;
+ } else {
+ /** \todo parse error */
+ }
+ }
+ break;
+ case HUBBUB_TOKEN_EOF:
+ /** \todo parse error */
+ reprocess = true;
+ break;
+ }
+
+ if (handled || reprocess) {
+ element_type otype;
+ void *node;
+
+ if (!element_stack_pop(treebuilder, &otype, &node)) {
+ /** \todo errors */
+ }
+
+ treebuilder->tree_handler->unref_node(
+ treebuilder->tree_handler->ctx,
+ node);
+
+ treebuilder->context.mode = IN_HEAD;
+ }
+
+ return reprocess;
+}
+
Propchange: trunk/hubbub/src/treebuilder/in_head_noscript.c
------------------------------------------------------------------------------
svn:eol-style = native
Added: trunk/hubbub/src/treebuilder/initial.c
URL: http://source.netsurf-browser.org/trunk/hubbub/src/treebuilder/initial.c?...
==============================================================================
--- trunk/hubbub/src/treebuilder/initial.c (added)
+++ trunk/hubbub/src/treebuilder/initial.c Mon Jun 23 15:22:25 2008
@@ -1,0 +1,101 @@
+/*
+ * This file is part of Hubbub.
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2008 John-Mark Bell <jmb(a)netsurf-browser.org>
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include "treebuilder/modes.h"
+#include "treebuilder/internal.h"
+#include "treebuilder/treebuilder.h"
+#include "utils/utils.h"
+
+
+/**
+ * Handle token in initial insertion mode
+ *
+ * \param treebuilder The treebuilder instance
+ * \param token The token to handle
+ * \return True to reprocess token, false otherwise
+ */
+bool handle_initial(hubbub_treebuilder *treebuilder, const hubbub_token *token)
+{
+ bool reprocess = false;
+
+ switch (token->type) {
+ case HUBBUB_TOKEN_CHARACTER:
+ if (process_characters_expect_whitespace(treebuilder, token,
+ false)) {
+ /** \todo parse error */
+
+ treebuilder->tree_handler->set_quirks_mode(
+ treebuilder->tree_handler->ctx,
+ HUBBUB_QUIRKS_MODE_FULL);
+ treebuilder->context.mode = BEFORE_HTML;
+ reprocess = true;
+ }
+ break;
+ case HUBBUB_TOKEN_COMMENT:
+ process_comment_append(treebuilder, token,
+ treebuilder->context.document);
+ break;
+ case HUBBUB_TOKEN_DOCTYPE:
+ {
+ int success;
+ void *doctype, *appended;
+
+ /** \todo parse error */
+
+ /** \todo need public and system ids from tokeniser */
+ success = treebuilder->tree_handler->create_doctype(
+ treebuilder->tree_handler->ctx,
+ &token->data.doctype.name,
+ &token->data.doctype.public_id,
+ &token->data.doctype.system_id, &doctype);
+ if (success != 0) {
+ /** \todo errors */
+ }
+
+ /* Append to Document node */
+ success = treebuilder->tree_handler->append_child(
+ treebuilder->tree_handler->ctx,
+ treebuilder->context.document,
+ doctype, &appended);
+ if (success != 0) {
+ /** \todo errors */
+ treebuilder->tree_handler->unref_node(
+ treebuilder->tree_handler->ctx,
+ doctype);
+ }
+
+ /* \todo look up the doctype in a catalog */
+
+ treebuilder->tree_handler->unref_node(
+ treebuilder->tree_handler->ctx, appended);
+ treebuilder->tree_handler->unref_node(
+ treebuilder->tree_handler->ctx, doctype);
+
+ treebuilder->context.mode = BEFORE_HTML;
+ }
+ break;
+ case HUBBUB_TOKEN_START_TAG:
+ case HUBBUB_TOKEN_END_TAG:
+ case HUBBUB_TOKEN_EOF:
+ /** \todo parse error */
+ treebuilder->tree_handler->set_quirks_mode(
+ treebuilder->tree_handler->ctx,
+ HUBBUB_QUIRKS_MODE_FULL);
+ reprocess = true;
+ break;
+ }
+
+ if (reprocess) {
+ treebuilder->context.mode = BEFORE_HTML;
+ }
+
+ return reprocess;
+}
+
Propchange: trunk/hubbub/src/treebuilder/initial.c
------------------------------------------------------------------------------
svn:eol-style = native
Modified: trunk/hubbub/src/treebuilder/internal.h
URL: http://source.netsurf-browser.org/trunk/hubbub/src/treebuilder/internal.h...
==============================================================================
--- trunk/hubbub/src/treebuilder/internal.h (original)
+++ trunk/hubbub/src/treebuilder/internal.h Mon Jun 23 15:22:25 2008
@@ -9,33 +9,6 @@
#define hubbub_treebuilder_internal_h_
#include "treebuilder/treebuilder.h"
-
-typedef enum
-{
- INITIAL,
- BEFORE_HTML,
- BEFORE_HEAD,
- IN_HEAD,
- IN_HEAD_NOSCRIPT,
- AFTER_HEAD,
- IN_BODY,
- IN_TABLE,
- IN_CAPTION,
- IN_COLUMN_GROUP,
- IN_TABLE_BODY,
- IN_ROW,
- IN_CELL,
- IN_SELECT,
- IN_SELECT_IN_TABLE,
- IN_FOREIGN_CONTENT,
- AFTER_BODY,
- IN_FRAMESET,
- AFTER_FRAMESET,
- AFTER_AFTER_BODY,
- AFTER_AFTER_FRAMESET,
- GENERIC_RCDATA,
- SCRIPT_COLLECT_CHARACTERS,
-} insertion_mode;
typedef enum
{
Added: trunk/hubbub/src/treebuilder/modes.h
URL: http://source.netsurf-browser.org/trunk/hubbub/src/treebuilder/modes.h?re...
==============================================================================
--- trunk/hubbub/src/treebuilder/modes.h (added)
+++ trunk/hubbub/src/treebuilder/modes.h Mon Jun 23 15:22:25 2008
@@ -1,0 +1,66 @@
+/*
+ * This file is part of Hubbub.
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2008 John-Mark Bell <jmb(a)netsurf-browser.org>
+ */
+
+#ifndef hubbub_treebuilder_modes_h_
+#define hubbub_treebuilder_modes_h_
+
+#include "treebuilder/treebuilder.h"
+
+/** The various treebuilder insertion modes */
+typedef enum
+{
+ INITIAL,
+ BEFORE_HTML,
+ BEFORE_HEAD,
+ IN_HEAD,
+ IN_HEAD_NOSCRIPT,
+ AFTER_HEAD,
+ IN_BODY,
+ IN_TABLE,
+ IN_CAPTION,
+ IN_COLUMN_GROUP,
+ IN_TABLE_BODY,
+ IN_ROW,
+ IN_CELL,
+ IN_SELECT,
+ IN_SELECT_IN_TABLE,
+ IN_FOREIGN_CONTENT,
+ AFTER_BODY,
+ IN_FRAMESET,
+ AFTER_FRAMESET,
+ AFTER_AFTER_BODY,
+
+ AFTER_AFTER_FRAMESET,
+ GENERIC_RCDATA,
+ SCRIPT_COLLECT_CHARACTERS,
+} insertion_mode;
+
+
+
+bool handle_initial(hubbub_treebuilder *treebuilder,
+ const hubbub_token *token);
+bool handle_before_html(hubbub_treebuilder *treebuilder,
+ const hubbub_token *token);
+bool handle_before_head(hubbub_treebuilder *treebuilder,
+ const hubbub_token *token);
+bool handle_in_head(hubbub_treebuilder *treebuilder,
+ const hubbub_token *token);
+bool handle_in_head_noscript(hubbub_treebuilder *treebuilder,
+ const hubbub_token *token);
+bool handle_after_head(hubbub_treebuilder *treebuilder,
+ const hubbub_token *token);
+bool handle_in_body(hubbub_treebuilder *treebuilder,
+ const hubbub_token *token);
+bool handle_generic_rcdata(hubbub_treebuilder *treebuilder,
+ const hubbub_token *token);
+bool handle_script_collect_characters(hubbub_treebuilder *treebuilder,
+ const hubbub_token *token);
+
+bool process_tag_in_body(hubbub_treebuilder *treebuilder,
+ const hubbub_token *token);
+
+#endif
Propchange: trunk/hubbub/src/treebuilder/modes.h
------------------------------------------------------------------------------
svn:eol-style = native
Added: trunk/hubbub/src/treebuilder/script_collect.c
URL: http://source.netsurf-browser.org/trunk/hubbub/src/treebuilder/script_col...
==============================================================================
--- trunk/hubbub/src/treebuilder/script_collect.c (added)
+++ trunk/hubbub/src/treebuilder/script_collect.c Mon Jun 23 15:22:25 2008
@@ -1,0 +1,123 @@
+/*
+ * This file is part of Hubbub.
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2008 John-Mark Bell <jmb(a)netsurf-browser.org>
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include "treebuilder/modes.h"
+#include "treebuilder/internal.h"
+#include "treebuilder/treebuilder.h"
+#include "utils/utils.h"
+
+
+/**
+ * Handle tokens in "script collect characters" insertion mode
+ *
+ * \param treebuilder The treebuilder instance
+ * \param token The token to process
+ * \return True to reprocess the token, false otherwise
+ */
+bool handle_script_collect_characters(hubbub_treebuilder *treebuilder,
+ const hubbub_token *token)
+{
+ bool reprocess = false;
+ bool done = false;
+
+ switch (token->type) {
+ case HUBBUB_TOKEN_CHARACTER:
+ if (treebuilder->context.collect.string.len == 0) {
+ treebuilder->context.collect.string.data.off =
+ token->data.character.data.off;
+ }
+ treebuilder->context.collect.string.len +=
+ token->data.character.len;
+ break;
+ case HUBBUB_TOKEN_END_TAG:
+ {
+ element_type type = element_type_from_name(treebuilder,
+ &token->data.tag.name);
+
+ if (type != treebuilder->context.collect.type) {
+ /** \todo parse error */
+ /** \todo Mark script as "already executed" */
+ }
+
+ done = true;
+ }
+ break;
+ case HUBBUB_TOKEN_EOF:
+ case HUBBUB_TOKEN_COMMENT:
+ case HUBBUB_TOKEN_DOCTYPE:
+ case HUBBUB_TOKEN_START_TAG:
+ /** \todo parse error */
+ /** \todo Mark script as "already executed" */
+ done = reprocess = true;
+ break;
+ }
+
+ if (done) {
+ int success;
+ void *text, *appended;
+
+ success = treebuilder->tree_handler->create_text(
+ treebuilder->tree_handler->ctx,
+ &treebuilder->context.collect.string,
+ &text);
+ if (success != 0) {
+ /** \todo errors */
+ }
+
+ /** \todo fragment case -- skip this lot entirely */
+
+ success = treebuilder->tree_handler->append_child(
+ treebuilder->tree_handler->ctx,
+ treebuilder->context.collect.node,
+ text, &appended);
+ if (success != 0) {
+ /** \todo errors */
+ treebuilder->tree_handler->unref_node(
+ treebuilder->tree_handler->ctx,
+ text);
+ }
+
+ treebuilder->tree_handler->unref_node(
+ treebuilder->tree_handler->ctx, appended);
+ treebuilder->tree_handler->unref_node(
+ treebuilder->tree_handler->ctx, text);
+
+ /** \todo insertion point manipulation */
+
+ /* Append script node to current node */
+ success = treebuilder->tree_handler->append_child(
+ treebuilder->tree_handler->ctx,
+ treebuilder->context.element_stack[
+ treebuilder->context.current_node].node,
+ treebuilder->context.collect.node, &appended);
+ if (success != 0) {
+ /** \todo errors */
+ }
+
+ /** \todo restore insertion point */
+
+ treebuilder->tree_handler->unref_node(
+ treebuilder->tree_handler->ctx,
+ appended);
+ treebuilder->tree_handler->unref_node(
+ treebuilder->tree_handler->ctx,
+ treebuilder->context.collect.node);
+ treebuilder->context.collect.node = NULL;
+
+ /** \todo process any pending script */
+
+ /* Return to previous insertion mode */
+ treebuilder->context.mode =
+ treebuilder->context.collect.mode;
+ }
+
+ return reprocess;
+}
+
Propchange: trunk/hubbub/src/treebuilder/script_collect.c
------------------------------------------------------------------------------
svn:eol-style = native
Modified: trunk/hubbub/src/treebuilder/treebuilder.c
URL: http://source.netsurf-browser.org/trunk/hubbub/src/treebuilder/treebuilde...
==============================================================================
--- trunk/hubbub/src/treebuilder/treebuilder.c (original)
+++ trunk/hubbub/src/treebuilder/treebuilder.c Mon Jun 23 15:22:25 2008
@@ -8,10 +8,11 @@
#include <assert.h>
#include <string.h>
-#include "treebuilder/in_body.h"
+#include "treebuilder/modes.h"
#include "treebuilder/internal.h"
#include "treebuilder/treebuilder.h"
#include "utils/utils.h"
+
static const struct {
const char *name;
@@ -68,23 +69,6 @@
static void hubbub_treebuilder_token_handler(const hubbub_token *token,
void *pw);
-static bool handle_initial(hubbub_treebuilder *treebuilder,
- const hubbub_token *token);
-static bool handle_before_html(hubbub_treebuilder *treebuilder,
- const hubbub_token *token);
-static bool handle_before_head(hubbub_treebuilder *treebuilder,
- const hubbub_token *token);
-static bool handle_in_head(hubbub_treebuilder *treebuilder,
- const hubbub_token *token);
-static bool handle_in_head_noscript(hubbub_treebuilder *treebuilder,
- const hubbub_token *token);
-static bool handle_after_head(hubbub_treebuilder *treebuilder,
- const hubbub_token *token);
-static bool handle_generic_rcdata(hubbub_treebuilder *treebuilder,
- const hubbub_token *token);
-static bool handle_script_collect_characters(hubbub_treebuilder *treebuilder,
- const hubbub_token *token);
-
/**
* Create a hubbub treebuilder
@@ -371,824 +355,6 @@
}
}
-/**
- * Handle token in initial insertion mode
- *
- * \param treebuilder The treebuilder instance
- * \param token The token to handle
- * \return True to reprocess token, false otherwise
- */
-bool handle_initial(hubbub_treebuilder *treebuilder, const hubbub_token *token)
-{
- bool reprocess = false;
-
- switch (token->type) {
- case HUBBUB_TOKEN_CHARACTER:
- if (process_characters_expect_whitespace(treebuilder, token,
- false)) {
- /** \todo parse error */
-
- treebuilder->tree_handler->set_quirks_mode(
- treebuilder->tree_handler->ctx,
- HUBBUB_QUIRKS_MODE_FULL);
- treebuilder->context.mode = BEFORE_HTML;
- reprocess = true;
- }
- break;
- case HUBBUB_TOKEN_COMMENT:
- process_comment_append(treebuilder, token,
- treebuilder->context.document);
- break;
- case HUBBUB_TOKEN_DOCTYPE:
- {
- int success;
- void *doctype, *appended;
-
- /** \todo parse error */
-
- /** \todo need public and system ids from tokeniser */
- success = treebuilder->tree_handler->create_doctype(
- treebuilder->tree_handler->ctx,
- &token->data.doctype.name,
- &token->data.doctype.public_id,
- &token->data.doctype.system_id, &doctype);
- if (success != 0) {
- /** \todo errors */
- }
-
- /* Append to Document node */
- success = treebuilder->tree_handler->append_child(
- treebuilder->tree_handler->ctx,
- treebuilder->context.document,
- doctype, &appended);
- if (success != 0) {
- /** \todo errors */
- treebuilder->tree_handler->unref_node(
- treebuilder->tree_handler->ctx,
- doctype);
- }
-
- /* \todo look up the doctype in a catalog */
-
- treebuilder->tree_handler->unref_node(
- treebuilder->tree_handler->ctx, appended);
- treebuilder->tree_handler->unref_node(
- treebuilder->tree_handler->ctx, doctype);
-
- treebuilder->context.mode = BEFORE_HTML;
- }
- break;
- case HUBBUB_TOKEN_START_TAG:
- case HUBBUB_TOKEN_END_TAG:
- case HUBBUB_TOKEN_EOF:
- /** \todo parse error */
- treebuilder->tree_handler->set_quirks_mode(
- treebuilder->tree_handler->ctx,
- HUBBUB_QUIRKS_MODE_FULL);
- reprocess = true;
- break;
- }
-
- if (reprocess) {
- treebuilder->context.mode = BEFORE_HTML;
- }
-
- return reprocess;
-}
-
-/**
- * Handle token in "before html" insertion mode
- *
- * \param treebuilder The treebuilder instance
- * \param token The token to handle
- * \return True to reprocess token, false otherwise
- */
-bool handle_before_html(hubbub_treebuilder *treebuilder,
- const hubbub_token *token)
-{
- bool reprocess = false;
- bool handled = false;
-
- switch (token->type) {
- case HUBBUB_TOKEN_DOCTYPE:
- /** \todo parse error */
- break;
- case HUBBUB_TOKEN_COMMENT:
- process_comment_append(treebuilder, token,
- treebuilder->context.document);
- break;
- case HUBBUB_TOKEN_CHARACTER:
- reprocess = process_characters_expect_whitespace(treebuilder,
- token, false);
- break;
- case HUBBUB_TOKEN_START_TAG:
- {
- element_type type = element_type_from_name(treebuilder,
- &token->data.tag.name);
-
- if (type == HTML) {
- handled = true;
- } else {
- reprocess = true;
- }
- }
- break;
- case HUBBUB_TOKEN_END_TAG:
- case HUBBUB_TOKEN_EOF:
- reprocess = true;
- break;
- }
-
-
- if (handled || reprocess) {
- int success;
- void *html, *appended;
-
- /* We can't use insert_element() here, as it assumes
- * that we're inserting into current_node. There is
- * no current_node to insert into at this point so
- * we get to do it manually. */
-
- if (reprocess) {
- /* Need to manufacture html element */
- hubbub_tag tag;
-
- /** \todo UTF-16 */
- tag.name.type = HUBBUB_STRING_PTR;
- tag.name.data.ptr = (const uint8_t *) "html";
- tag.name.len = SLEN("html");
-
- tag.n_attributes = 0;
- tag.attributes = NULL;
-
- success = treebuilder->tree_handler->create_element(
- treebuilder->tree_handler->ctx,
- &tag, &html);
- } else {
- success = treebuilder->tree_handler->create_element(
- treebuilder->tree_handler->ctx,
- &token->data.tag, &html);
- }
-
- if (success != 0) {
- /** \todo errors */
- }
-
- success = treebuilder->tree_handler->append_child(
- treebuilder->tree_handler->ctx,
- treebuilder->context.document,
- html, &appended);
- if (success != 0) {
- /** \todo errors */
- treebuilder->tree_handler->unref_node(
- treebuilder->tree_handler->ctx,
- html);
- }
-
- /* We can't use element_stack_push() here, as it
- * assumes that current_node is pointing at the index
- * before the one to insert at. For the first entry in
- * the stack, this does not hold so we must insert
- * manually. */
- treebuilder->context.element_stack[0].type = HTML;
- treebuilder->context.element_stack[0].node = html;
- treebuilder->context.current_node = 0;
-
- /** \todo cache selection algorithm */
-
- treebuilder->tree_handler->unref_node(
- treebuilder->tree_handler->ctx,
- appended);
-
- treebuilder->context.mode = BEFORE_HEAD;
- }
-
- return reprocess;
-}
-
-/**
- * Handle token in "before head" insertion mode
- *
- * \param treebuilder The treebuilder instance
- * \param token The token to handle
- * \return True to reprocess token, false otherwise
- */
-bool handle_before_head(hubbub_treebuilder *treebuilder,
- const hubbub_token *token)
-{
- bool reprocess = false;
- bool handled = false;
-
- switch (token->type) {
- case HUBBUB_TOKEN_CHARACTER:
- reprocess = process_characters_expect_whitespace(treebuilder,
- token, false);
- break;
- case HUBBUB_TOKEN_COMMENT:
- process_comment_append(treebuilder, token,
- treebuilder->context.element_stack[
- treebuilder->context.current_node].node);
- break;
- case HUBBUB_TOKEN_DOCTYPE:
- /** \todo parse error */
- break;
- case HUBBUB_TOKEN_START_TAG:
- {
- element_type type = element_type_from_name(treebuilder,
- &token->data.tag.name);
-
- if (type == HTML) {
- /* Process as if "in body" */
- process_tag_in_body(treebuilder, token);
- } else if (type == HEAD) {
- handled = true;
- } else {
- reprocess = true;
- }
- }
- break;
- case HUBBUB_TOKEN_END_TAG:
- {
- element_type type = element_type_from_name(treebuilder,
- &token->data.tag.name);
-
- if (type == HEAD || type == BR) {
- reprocess = true;
- } else {
- /** \todo parse error */
- }
- }
- break;
- case HUBBUB_TOKEN_EOF:
- reprocess = true;
- break;
- }
-
- if (handled || reprocess) {
- hubbub_tag tag;
-
- if (reprocess) {
- /* Manufacture head tag */
- tag.name.type = HUBBUB_STRING_PTR;
- tag.name.data.ptr = (const uint8_t *) "head";
- tag.name.len = SLEN("head");
-
- tag.n_attributes = 0;
- tag.attributes = NULL;
- } else {
- tag = token->data.tag;
- }
-
- insert_element(treebuilder, &tag);
-
- treebuilder->tree_handler->ref_node(
- treebuilder->tree_handler->ctx,
- treebuilder->context.element_stack[
- treebuilder->context.current_node].node);
-
- treebuilder->context.head_element =
- treebuilder->context.element_stack[
- treebuilder->context.current_node].node;
-
- treebuilder->context.mode = IN_HEAD;
- }
-
- return reprocess;
-}
-
-/**
- * Handle token in "in head" insertion mode
- *
- * \param treebuilder The treebuilder instance
- * \param token The token to handle
- * \return True to reprocess token, false otherwise
- */
-bool handle_in_head(hubbub_treebuilder *treebuilder,
- const hubbub_token *token)
-{
- bool reprocess = false;
- bool handled = false;
-
- switch (token->type) {
- case HUBBUB_TOKEN_CHARACTER:
- reprocess = process_characters_expect_whitespace(treebuilder,
- token, true);
- break;
- case HUBBUB_TOKEN_COMMENT:
- process_comment_append(treebuilder, token,
- treebuilder->context.element_stack[
- treebuilder->context.current_node].node);
- break;
- case HUBBUB_TOKEN_DOCTYPE:
- /** \todo parse error */
- break;
- case HUBBUB_TOKEN_START_TAG:
- {
- element_type type = element_type_from_name(treebuilder,
- &token->data.tag.name);
-
- if (type == HTML) {
- /* Process as if "in body" */
- process_tag_in_body(treebuilder, token);
- } else if (type == BASE || type == COMMAND ||
- type == EVENT_SOURCE || type == LINK) {
- process_base_link_meta_in_head(treebuilder,
- token, type);
-
- /** \todo ack sc flag */
- } else if (type == META) {
- process_base_link_meta_in_head(treebuilder,
- token, type);
-
- /** \todo ack sc flag */
-
- /** \todo detect charset */
- } else if (type == TITLE) {
- parse_generic_rcdata(treebuilder, token, true);
- } else if (type == NOFRAMES || type == STYLE) {
- parse_generic_rcdata(treebuilder, token, false);
- } else if (type == NOSCRIPT) {
- /** \todo determine if scripting is enabled */
- if (false /*scripting_is_enabled*/) {
- parse_generic_rcdata(treebuilder, token, false);
- } else {
- insert_element(treebuilder, &token->data.tag);
- treebuilder->context.mode = IN_HEAD_NOSCRIPT;
- }
- } else if (type == SCRIPT) {
- process_script_in_head(treebuilder, token);
- } else if (type == HEAD) {
- /** \todo parse error */
- } else {
- reprocess = true;
- }
- }
- break;
- case HUBBUB_TOKEN_END_TAG:
- {
- element_type type = element_type_from_name(treebuilder,
- &token->data.tag.name);
-
- if (type == HEAD) {
- handled = true;
- } else if (type == BR) {
- reprocess = true;
- } /** \todo parse error */
- }
- break;
- case HUBBUB_TOKEN_EOF:
- reprocess = true;
- break;
- }
-
- if (handled || reprocess) {
- element_type otype;
- void *node;
-
- if (!element_stack_pop(treebuilder, &otype, &node)) {
- /** \todo errors */
- }
-
- treebuilder->tree_handler->unref_node(
- treebuilder->tree_handler->ctx,
- node);
-
- treebuilder->context.mode = AFTER_HEAD;
- }
-
- return reprocess;
-}
-
-/**
- * Handle tokens in "in head noscript" insertion mode
- *
- * \param treebuilder The treebuilder instance
- * \param token The token to process
- * \return True to reprocess the token, false otherwise
- */
-bool handle_in_head_noscript(hubbub_treebuilder *treebuilder,
- const hubbub_token *token)
-{
- bool reprocess = false;
- bool handled = false;
-
- switch (token->type) {
- case HUBBUB_TOKEN_CHARACTER:
- /* This should be equivalent to "in head" processing */
- reprocess = process_characters_expect_whitespace(treebuilder,
- token, true);
- break;
- case HUBBUB_TOKEN_COMMENT:
- /* This should be equivalent to "in head" processing */
- process_comment_append(treebuilder, token,
- treebuilder->context.element_stack[
- treebuilder->context.current_node].node);
- break;
- case HUBBUB_TOKEN_DOCTYPE:
- /** \todo parse error */
- break;
- case HUBBUB_TOKEN_START_TAG:
- {
- element_type type = element_type_from_name(treebuilder,
- &token->data.tag.name);
-
- if (type == HTML) {
- /* Process as "in body" */
- process_tag_in_body(treebuilder, token);
- } else if (type == NOSCRIPT) {
- handled = true;
- } else if (type == LINK) {
- /* This should be equivalent to "in head" processing */
- process_base_link_meta_in_head(treebuilder,
- token, type);
-
- /** \todo ack sc flag */
- } else if (type == META) {
- /* This should be equivalent to "in head" processing */
- process_base_link_meta_in_head(treebuilder,
- token, type);
-
- /** \todo ack sc flag */
-
- /** \todo detect charset */
- } else if (type == NOFRAMES) {
- /* This should be equivalent to "in head" processing */
- parse_generic_rcdata(treebuilder, token, true);
- } else if (type == STYLE) {
- /* This should be equivalent to "in head" processing */
- parse_generic_rcdata(treebuilder, token, false);
- } else if (type == HEAD || type == NOSCRIPT) {
- /** \todo parse error */
- } else {
- /** \todo parse error */
- reprocess = true;
- }
- }
- break;
- case HUBBUB_TOKEN_END_TAG:
- {
- element_type type = element_type_from_name(treebuilder,
- &token->data.tag.name);
-
- if (type == NOSCRIPT) {
- handled = true;
- } else if (type == BR) {
- /** \todo parse error */
- reprocess = true;
- } else {
- /** \todo parse error */
- }
- }
- break;
- case HUBBUB_TOKEN_EOF:
- /** \todo parse error */
- reprocess = true;
- break;
- }
-
- if (handled || reprocess) {
- element_type otype;
- void *node;
-
- if (!element_stack_pop(treebuilder, &otype, &node)) {
- /** \todo errors */
- }
-
- treebuilder->tree_handler->unref_node(
- treebuilder->tree_handler->ctx,
- node);
-
- treebuilder->context.mode = IN_HEAD;
- }
-
- return reprocess;
-}
-
-/**
- * Handle tokens in "after head" insertion mode
- *
- * \param treebuilder The treebuilder instance
- * \param token The token to process
- * \return True to reprocess the token, false otherwise
- */
-bool handle_after_head(hubbub_treebuilder *treebuilder,
- const hubbub_token *token)
-{
- bool reprocess = false;
- bool handled = false;
-
- switch (token->type) {
- case HUBBUB_TOKEN_CHARACTER:
- append_text(treebuilder, &token->data.character);
- break;
- case HUBBUB_TOKEN_COMMENT:
- process_comment_append(treebuilder, token,
- treebuilder->context.element_stack[
- treebuilder->context.current_node].node);
- break;
- case HUBBUB_TOKEN_DOCTYPE:
- /** \todo parse error */
- break;
- case HUBBUB_TOKEN_START_TAG:
- {
- element_type type = element_type_from_name(treebuilder,
- &token->data.tag.name);
-
- if (type == HTML) {
- /* Process as if "in body" */
- process_tag_in_body(treebuilder, token);
- } else if (type == BODY) {
- handled = true;
- } else if (type == FRAMESET) {
- insert_element(treebuilder, &token->data.tag);
- treebuilder->context.mode = IN_FRAMESET;
- } else if (type == BASE || type == LINK || type == META ||
- type == NOFRAMES || type == SCRIPT ||
- type == STYLE || type == TITLE) {
- element_type otype;
- void *node;
-
- /** \todo parse error */
-
- if (!element_stack_push(treebuilder,
- HEAD,
- treebuilder->context.head_element)) {
- /** \todo errors */
- }
-
-
- /* This should be identical to handling "in head" */
- if (type == BASE || type == LINK || type == META) {
- /** \todo ack sc flag */
-
- process_base_link_meta_in_head(treebuilder,
- token, type);
- } else if (type == SCRIPT) {
- process_script_in_head(treebuilder, token);
- } else if (type == STYLE || type == NOFRAMES) {
- parse_generic_rcdata(treebuilder, token, false);
- } else if (type == TITLE) {
- parse_generic_rcdata(treebuilder, token, true);
- }
-
- if (!element_stack_pop(treebuilder, &otype, &node)) {
- /** \todo errors */
- }
-
- /* No need to unref node as we never increased
- * its reference count when pushing it on the stack */
- } else if (type == HEAD) {
- /** \todo parse error */
- } else {
- reprocess = true;
- }
- }
- break;
- case HUBBUB_TOKEN_END_TAG:
- /** \parse error */
- break;
- case HUBBUB_TOKEN_EOF:
- reprocess = true;
- break;
- }
-
- if (handled || reprocess) {
- hubbub_tag tag;
-
- if (reprocess) {
- /* Manufacture body */
- tag.name.type = HUBBUB_STRING_PTR;
- tag.name.data.ptr = (const uint8_t *) "body";
- tag.name.len = SLEN("body");
-
- tag.n_attributes = 0;
- tag.attributes = NULL;
- } else {
- tag = token->data.tag;
- }
-
- insert_element(treebuilder, &tag);
-
- treebuilder->context.mode = IN_BODY;
- }
-
- return reprocess;
-}
-
-/**
- * Handle tokens in "generic rcdata" insertion mode
- *
- * \param treebuilder The treebuilder instance
- * \param token The token to process
- * \return True to reprocess the token, false otherwise
- */
-bool handle_generic_rcdata(hubbub_treebuilder *treebuilder,
- const hubbub_token *token)
-{
- bool reprocess = false;
- bool done = false;
-
- if (treebuilder->context.strip_leading_lr &&
- token->type != HUBBUB_TOKEN_CHARACTER) {
- /* Reset the LR stripping flag */
- treebuilder->context.strip_leading_lr = false;
- }
-
- switch (token->type) {
- case HUBBUB_TOKEN_CHARACTER:
- if (treebuilder->context.collect.string.len == 0) {
- treebuilder->context.collect.string.data.off =
- token->data.character.data.off;
- }
- treebuilder->context.collect.string.len +=
- token->data.character.len;
-
- if (treebuilder->context.strip_leading_lr) {
- const uint8_t *str = treebuilder->input_buffer +
- treebuilder->context.collect.string.data.off;
-
- /** \todo UTF-16 */
- if (*str == '\n') {
- treebuilder->context.collect.string.data.off++;
- treebuilder->context.collect.string.len--;
- }
-
- treebuilder->context.strip_leading_lr = false;
- }
- break;
- case HUBBUB_TOKEN_END_TAG:
- {
- element_type type = element_type_from_name(treebuilder,
- &token->data.tag.name);
-
- if (type != treebuilder->context.collect.type) {
- /** \todo parse error */
- }
-
- done = true;
- }
- break;
- case HUBBUB_TOKEN_EOF:
- /** \todo parse error */
- done = reprocess = true;
- break;
- case HUBBUB_TOKEN_COMMENT:
- case HUBBUB_TOKEN_DOCTYPE:
- case HUBBUB_TOKEN_START_TAG:
- /* Should never happen */
- assert(0);
- break;
- }
-
- if (done) {
- int success;
- void *text, *appended;
-
- success = treebuilder->tree_handler->create_text(
- treebuilder->tree_handler->ctx,
- &treebuilder->context.collect.string,
- &text);
- if (success != 0) {
- /** \todo errors */
- }
-
- success = treebuilder->tree_handler->append_child(
- treebuilder->tree_handler->ctx,
- treebuilder->context.collect.node,
- text, &appended);
- if (success != 0) {
- /** \todo errors */
- treebuilder->tree_handler->unref_node(
- treebuilder->tree_handler->ctx,
- text);
- }
-
- treebuilder->tree_handler->unref_node(
- treebuilder->tree_handler->ctx, appended);
- treebuilder->tree_handler->unref_node(
- treebuilder->tree_handler->ctx, text);
-
- /* Clean up context */
- treebuilder->tree_handler->unref_node(
- treebuilder->tree_handler->ctx,
- treebuilder->context.collect.node);
- treebuilder->context.collect.node = NULL;
-
- /* Return to previous insertion mode */
- treebuilder->context.mode =
- treebuilder->context.collect.mode;
- }
-
- return reprocess;
-}
-
-/**
- * Handle tokens in "script collect characters" insertion mode
- *
- * \param treebuilder The treebuilder instance
- * \param token The token to process
- * \return True to reprocess the token, false otherwise
- */
-bool handle_script_collect_characters(hubbub_treebuilder *treebuilder,
- const hubbub_token *token)
-{
- bool reprocess = false;
- bool done = false;
-
- switch (token->type) {
- case HUBBUB_TOKEN_CHARACTER:
- if (treebuilder->context.collect.string.len == 0) {
- treebuilder->context.collect.string.data.off =
- token->data.character.data.off;
- }
- treebuilder->context.collect.string.len +=
- token->data.character.len;
- break;
- case HUBBUB_TOKEN_END_TAG:
- {
- element_type type = element_type_from_name(treebuilder,
- &token->data.tag.name);
-
- if (type != treebuilder->context.collect.type) {
- /** \todo parse error */
- /** \todo Mark script as "already executed" */
- }
-
- done = true;
- }
- break;
- case HUBBUB_TOKEN_EOF:
- case HUBBUB_TOKEN_COMMENT:
- case HUBBUB_TOKEN_DOCTYPE:
- case HUBBUB_TOKEN_START_TAG:
- /** \todo parse error */
- /** \todo Mark script as "already executed" */
- done = reprocess = true;
- break;
- }
-
- if (done) {
- int success;
- void *text, *appended;
-
- success = treebuilder->tree_handler->create_text(
- treebuilder->tree_handler->ctx,
- &treebuilder->context.collect.string,
- &text);
- if (success != 0) {
- /** \todo errors */
- }
-
- /** \todo fragment case -- skip this lot entirely */
-
- success = treebuilder->tree_handler->append_child(
- treebuilder->tree_handler->ctx,
- treebuilder->context.collect.node,
- text, &appended);
- if (success != 0) {
- /** \todo errors */
- treebuilder->tree_handler->unref_node(
- treebuilder->tree_handler->ctx,
- text);
- }
-
- treebuilder->tree_handler->unref_node(
- treebuilder->tree_handler->ctx, appended);
- treebuilder->tree_handler->unref_node(
- treebuilder->tree_handler->ctx, text);
-
- /** \todo insertion point manipulation */
-
- /* Append script node to current node */
- success = treebuilder->tree_handler->append_child(
- treebuilder->tree_handler->ctx,
- treebuilder->context.element_stack[
- treebuilder->context.current_node].node,
- treebuilder->context.collect.node, &appended);
- if (success != 0) {
- /** \todo errors */
- }
-
- /** \todo restore insertion point */
-
- treebuilder->tree_handler->unref_node(
- treebuilder->tree_handler->ctx,
- appended);
- treebuilder->tree_handler->unref_node(
- treebuilder->tree_handler->ctx,
- treebuilder->context.collect.node);
- treebuilder->context.collect.node = NULL;
-
- /** \todo process any pending script */
-
- /* Return to previous insertion mode */
- treebuilder->context.mode =
- treebuilder->context.collect.mode;
- }
-
- return reprocess;
-}
-
/**
* Process a character token in cases where we expect only whitespace
14 years, 9 months
r4428 takkaria - in /trunk/hubbub/test/data/tokeniser2: test2.test test3.test test4.test
by netsurf@semichrome.net
Author: takkaria
Date: Mon Jun 23 12:12:43 2008
New Revision: 4428
URL: http://source.netsurf-browser.org?rev=4428&view=rev
Log:
Update to latest html5lib tests.
Modified:
trunk/hubbub/test/data/tokeniser2/test2.test
trunk/hubbub/test/data/tokeniser2/test3.test
trunk/hubbub/test/data/tokeniser2/test4.test
Modified: trunk/hubbub/test/data/tokeniser2/test2.test
URL: http://source.netsurf-browser.org/trunk/hubbub/test/data/tokeniser2/test2...
==============================================================================
--- trunk/hubbub/test/data/tokeniser2/test2.test (original)
+++ trunk/hubbub/test/data/tokeniser2/test2.test Mon Jun 23 12:12:43 2008
@@ -150,7 +150,7 @@
{"description":"Empty attribute followed by uppercase attribute",
"input":"<h a B=''>",
-"output":[["StartTag", "h", {"a":"", "b":""}]]},
+"output":[["StartTag", "h", {"a":"", "b":""}]]}
]}
Modified: trunk/hubbub/test/data/tokeniser2/test3.test
URL: http://source.netsurf-browser.org/trunk/hubbub/test/data/tokeniser2/test3...
==============================================================================
--- trunk/hubbub/test/data/tokeniser2/test3.test (original)
+++ trunk/hubbub/test/data/tokeniser2/test3.test Mon Jun 23 12:12:43 2008
@@ -134,7 +134,7 @@
{"description":"<!doctype! ??",
"input":"<!doctype! ??",
-"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "!", null, null, false]]},
+"output":["ParseError", "ParseError", ["DOCTYPE", "!", null, null, false]]},
{"description":"<!doctype!?",
"input":"<!doctype!?",
@@ -150,7 +150,7 @@
{"description":"<!doctype! public?",
"input":"<!doctype! public?",
-"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "!", null, null, false]]},
+"output":["ParseError", "ParseError", ["DOCTYPE", "!", null, null, false]]},
{"description":"<!doctype! public''",
"input":"<!doctype! public''",
@@ -170,7 +170,7 @@
{"description":"<!doctype! public\"\"?",
"input":"<!doctype! public\"\"?",
-"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "!", "", null, false]]},
+"output":["ParseError", "ParseError", ["DOCTYPE", "!", "", null, false]]},
{"description":"<!doctype! public\"\"'",
"input":"<!doctype! public\"\"'",
@@ -194,7 +194,7 @@
{"description":"<!doctype! system?",
"input":"<!doctype! system?",
-"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "!", null, null, false]]},
+"output":["ParseError", "ParseError", ["DOCTYPE", "!", null, null, false]]},
{"description":"<!doctype! system''",
"input":"<!doctype! system''",
@@ -214,7 +214,7 @@
{"description":"<!doctype! system\"\"?",
"input":"<!doctype! system\"\"?",
-"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "!", null, "", true]]},
+"output":["ParseError", "ParseError", ["DOCTYPE", "!", null, "", true]]},
{"description":"<!doctype! system\"#",
"input":"<!doctype! system\"#",
Modified: trunk/hubbub/test/data/tokeniser2/test4.test
URL: http://source.netsurf-browser.org/trunk/hubbub/test/data/tokeniser2/test4...
==============================================================================
--- trunk/hubbub/test/data/tokeniser2/test4.test (original)
+++ trunk/hubbub/test/data/tokeniser2/test4.test Mon Jun 23 12:12:43 2008
@@ -44,6 +44,10 @@
"input":"<z z='&\"'>",
"output":["ParseError", ["StartTag", "z", {"z": "&\""}]]},
+{"description":"Text after bogus character reference",
+"input":"<z z='&xlink_xmlns;'>bar<z>",
+"output":["ParseError",["StartTag","z",{"z":"&xlink_xmlns;"}],["Character","bar"],["StartTag","z",{}]]},
+
{"description":"Attribute name starting with \"",
"input":"<foo \"='bar'>",
"output":["ParseError", ["StartTag", "foo", {"\"": "bar"}]]},
@@ -122,7 +126,7 @@
{"description":"Maximum non-BMP numeric entity",
"input":"",
-"output":[["Character", "\uDBFF\uDFFF"]]},
+"output":["ParseError", ["Character", "\uFFFD"]]},
{"description":"Above maximum numeric entity",
"input":"�",
14 years, 9 months
r4427 takkaria - in /trunk/hubbub/src/treebuilder: internal.h treebuilder.c
by netsurf@semichrome.net
Author: takkaria
Date: Sun Jun 22 22:26:18 2008
New Revision: 4427
URL: http://source.netsurf-browser.org?rev=4427&view=rev
Log:
Add a stubbed "in foreign content" state for the treebuilder.
Modified:
trunk/hubbub/src/treebuilder/internal.h
trunk/hubbub/src/treebuilder/treebuilder.c
Modified: trunk/hubbub/src/treebuilder/internal.h
URL: http://source.netsurf-browser.org/trunk/hubbub/src/treebuilder/internal.h...
==============================================================================
--- trunk/hubbub/src/treebuilder/internal.h (original)
+++ trunk/hubbub/src/treebuilder/internal.h Sun Jun 22 22:26:18 2008
@@ -27,6 +27,7 @@
IN_CELL,
IN_SELECT,
IN_SELECT_IN_TABLE,
+ IN_FOREIGN_CONTENT,
AFTER_BODY,
IN_FRAMESET,
AFTER_FRAMESET,
Modified: trunk/hubbub/src/treebuilder/treebuilder.c
URL: http://source.netsurf-browser.org/trunk/hubbub/src/treebuilder/treebuilde...
==============================================================================
--- trunk/hubbub/src/treebuilder/treebuilder.c (original)
+++ trunk/hubbub/src/treebuilder/treebuilder.c Sun Jun 22 22:26:18 2008
@@ -352,6 +352,7 @@
case IN_CELL:
case IN_SELECT:
case IN_SELECT_IN_TABLE:
+ case IN_FOREIGN_CONTENT:
case AFTER_BODY:
case IN_FRAMESET:
case AFTER_FRAMESET:
14 years, 9 months
r4426 takkaria - in /trunk/hubbub/src/treebuilder: in_body.c internal.h treebuilder.c
by netsurf@semichrome.net
Author: takkaria
Date: Sun Jun 22 22:06:24 2008
New Revision: 4426
URL: http://source.netsurf-browser.org?rev=4426&view=rev
Log:
Update the treebuilder so it's closer to current spec (I'm sure I've missed stuff).
Modified:
trunk/hubbub/src/treebuilder/in_body.c
trunk/hubbub/src/treebuilder/internal.h
trunk/hubbub/src/treebuilder/treebuilder.c
Modified: trunk/hubbub/src/treebuilder/in_body.c
URL: http://source.netsurf-browser.org/trunk/hubbub/src/treebuilder/in_body.c?...
==============================================================================
--- trunk/hubbub/src/treebuilder/in_body.c (original)
+++ trunk/hubbub/src/treebuilder/in_body.c Sun Jun 22 22:06:24 2008
@@ -247,24 +247,35 @@
if (type == HTML) {
process_html_in_body(treebuilder, token);
- } else if (type == BASE || type == LINK || type == META) {
- process_base_link_meta_in_head(treebuilder,
- token, type);
+ } else if (type == BASE || type == COMMAND ||
+ type == EVENT_SOURCE || type == LINK) {
+ process_base_link_meta_in_head(treebuilder, token, type);
+
+ /** \todo ack sc flag */
+ } else if (type == META) {
+ process_base_link_meta_in_head(treebuilder, token, type);
+
+ /** \todo ack sc flag */
+ /** \todo detect charset */
} else if (type == SCRIPT) {
process_script_in_head(treebuilder, token);
- } else if (type == STYLE) {
+ } else if (type == NOFRAMES || type == STYLE) {
parse_generic_rcdata(treebuilder, token, false);
} else if (type == TITLE) {
parse_generic_rcdata(treebuilder, token, true);
} else if (type == BODY) {
process_body_in_body(treebuilder, token);
- } else if (type == ADDRESS || type == BLOCKQUOTE ||
- type == CENTER || type == DIR ||
- type == DIV || type == DL ||
- type == FIELDSET || type == H1 || type == H2 ||
- type == H3 || type == H4 || type == H5 ||
- type == H6 || type == MENU || type == OL ||
- type == P || type == UL) {
+ } else if (type == ADDRESS || type == ARTICLE || type == ASIDE ||
+ type == BLOCKQUOTE || type == CENTER ||
+ type == DATAGRID || type == DETAILS ||
+ type == DIALOG || type == DIR ||
+ type == DIV || type == DL || type == FIELDSET ||
+ type == FIGURE || type == FOOTER ||
+ type == H1 || type == H2 || type == H3 ||
+ type == H4 || type == H5 || type == H6 ||
+ type == HEADER || type == MENU || type == NAV ||
+ type == OL || type == P || type == SECTION ||
+ type == UL) {
process_container_in_body(treebuilder, token);
} else if (type == PRE || type == LISTING) {
process_container_in_body(treebuilder, token);
@@ -334,19 +345,25 @@
treebuilder->context.mode == IN_CELL) {
treebuilder->context.mode = IN_SELECT_IN_TABLE;
}
+ } else if (type == RP || type == RT) {
+ /** \todo ruby */
+ } else if (type == MATH) {
+ reconstruct_active_formatting_list(treebuilder);
+ /** \todo adjust foreign attributes */
+ /** \todo insert foreign element */
+ if (token->data.tag.self_closing) {
+ /** \todo pop off the stack of open elements */
+ /** \todo ack sc flag */
+ } else {
+ /** \todo set to "in foreign content" */
+ }
} else if (type == CAPTION || type == COL || type == COLGROUP ||
- type == FRAME || type == FRAMESET ||
- type == HEAD || type == OPTION ||
- type == OPTGROUP || type == TBODY ||
+ type == FRAME || type == FRAMESET ||
+ type == HEAD || type == TBODY ||
type == TD || type == TFOOT || type == TH ||
type == THEAD || type == TR) {
/** \todo parse error */
-/* } else if (type == EVENT_SOURCE || type == SECTION ||
- type == NAV || type == ARTICLE ||
- type == ASIDE || type == HEADER ||
- type == FOOTER || type == DATAGRID ||
- type == COMMAND) {
-*/ } else {
+ } else {
process_phrasing_in_body(treebuilder, token);
}
Modified: trunk/hubbub/src/treebuilder/internal.h
URL: http://source.netsurf-browser.org/trunk/hubbub/src/treebuilder/internal.h...
==============================================================================
--- trunk/hubbub/src/treebuilder/internal.h (original)
+++ trunk/hubbub/src/treebuilder/internal.h Sun Jun 22 22:06:24 2008
@@ -39,19 +39,21 @@
typedef enum
{
/* Special */
- ADDRESS, AREA, BASE, BASEFONT, BGSOUND, BLOCKQUOTE, BODY, BR, CENTER,
- COL, COLGROUP, DD, DIR, DIV, DL, DT, EMBED, FIELDSET, FORM, FRAME,
- FRAMESET, H1, H2, H3, H4, H5, H6, HEAD, HR, IFRAME, IMAGE, IMG, INPUT,
- ISINDEX, LI, LINK, LISTING, MENU, META, NOEMBED, NOFRAMES, NOSCRIPT,
- OL, OPTGROUP, OPTION, P, PARAM, PLAINTEXT, PRE, SCRIPT, SELECT, SPACER,
- STYLE, TBODY, TEXTAREA, TFOOT, THEAD, TITLE, TR, UL, WBR,
+ ADDRESS, AREA, ARTICLE, ASIDE, BASE, BASEFONT, BGSOUND, BLOCKQUOTE,
+ BODY, BR, CENTER, COL, COLGROUP, COMMAND, DATAGRID, DD, DETAILS,
+ DIALOG, DIR, DIV, DL, DT, EMBED, EVENT_SOURCE, FIELDSET, FIGURE,
+ FOOTER, FORM, FRAME, FRAMESET, H1, H2, H3, H4, H5, H6, HEAD, HEADER,
+ HR, IFRAME, IMAGE, IMG, INPUT, ISINDEX, LI, LINK, LISTING, MENU, META,
+ NAV, NOEMBED, NOFRAMES, NOSCRIPT, OL, OPTGROUP, OPTION, P, PARAM,
+ PLAINTEXT, PRE, SCRIPT, SECTION, SELECT, SPACER, STYLE, TBODY,
+ TEXTAREA, TFOOT, THEAD, TITLE, TR, UL, WBR,
/* Scoping */
APPLET, BUTTON, CAPTION, HTML, MARQUEE, OBJECT, TABLE, TD, TH,
/* Formatting */
A, B, BIG, EM, FONT, I, NOBR, S, SMALL, STRIKE, STRONG, TT, U,
/* Phrasing */
/**< \todo Enumerate phrasing elements */
- XMP, LABEL,
+ LABEL, MATH, RP, RT, XMP,
UNKNOWN,
} element_type;
Modified: trunk/hubbub/src/treebuilder/treebuilder.c
URL: http://source.netsurf-browser.org/trunk/hubbub/src/treebuilder/treebuilde...
==============================================================================
--- trunk/hubbub/src/treebuilder/treebuilder.c (original)
+++ trunk/hubbub/src/treebuilder/treebuilder.c Sun Jun 22 22:06:24 2008
@@ -390,12 +390,12 @@
treebuilder->tree_handler->set_quirks_mode(
treebuilder->tree_handler->ctx,
HUBBUB_QUIRKS_MODE_FULL);
-
+ treebuilder->context.mode = BEFORE_HTML;
reprocess = true;
}
break;
case HUBBUB_TOKEN_COMMENT:
- process_comment_append(treebuilder, token,
+ process_comment_append(treebuilder, token,
treebuilder->context.document);
break;
case HUBBUB_TOKEN_DOCTYPE:
@@ -403,11 +403,14 @@
int success;
void *doctype, *appended;
+ /** \todo parse error */
+
/** \todo need public and system ids from tokeniser */
success = treebuilder->tree_handler->create_doctype(
treebuilder->tree_handler->ctx,
&token->data.doctype.name,
- NULL, NULL, &doctype);
+ &token->data.doctype.public_id,
+ &token->data.doctype.system_id, &doctype);
if (success != 0) {
/** \todo errors */
}
@@ -424,7 +427,7 @@
doctype);
}
- /** \todo doctype processing */
+ /* \todo look up the doctype in a catalog */
treebuilder->tree_handler->unref_node(
treebuilder->tree_handler->ctx, appended);
@@ -474,7 +477,7 @@
treebuilder->context.document);
break;
case HUBBUB_TOKEN_CHARACTER:
- reprocess = process_characters_expect_whitespace(treebuilder,
+ reprocess = process_characters_expect_whitespace(treebuilder,
token, false);
break;
case HUBBUB_TOKEN_START_TAG:
@@ -608,8 +611,7 @@
element_type type = element_type_from_name(treebuilder,
&token->data.tag.name);
- if (type == HEAD || type == BODY || type == HTML ||
- type == P || type == BR) {
+ if (type == HEAD || type == BR) {
reprocess = true;
} else {
/** \todo parse error */
@@ -687,11 +689,23 @@
if (type == HTML) {
/* Process as if "in body" */
process_tag_in_body(treebuilder, token);
- } else if (type == BASE || type == LINK || type == META) {
- process_base_link_meta_in_head(treebuilder,
+ } else if (type == BASE || type == COMMAND ||
+ type == EVENT_SOURCE || type == LINK) {
+ process_base_link_meta_in_head(treebuilder,
token, type);
+
+ /** \todo ack sc flag */
+ } else if (type == META) {
+ process_base_link_meta_in_head(treebuilder,
+ token, type);
+
+ /** \todo ack sc flag */
+
+ /** \todo detect charset */
} else if (type == TITLE) {
parse_generic_rcdata(treebuilder, token, true);
+ } else if (type == NOFRAMES || type == STYLE) {
+ parse_generic_rcdata(treebuilder, token, false);
} else if (type == NOSCRIPT) {
/** \todo determine if scripting is enabled */
if (false /*scripting_is_enabled*/) {
@@ -700,8 +714,6 @@
insert_element(treebuilder, &token->data.tag);
treebuilder->context.mode = IN_HEAD_NOSCRIPT;
}
- } else if (type == STYLE) {
- parse_generic_rcdata(treebuilder, token, false);
} else if (type == SCRIPT) {
process_script_in_head(treebuilder, token);
} else if (type == HEAD) {
@@ -718,10 +730,9 @@
if (type == HEAD) {
handled = true;
- } else if (type == BODY || type == HTML ||
- type == P || type == BR) {
+ } else if (type == BR) {
reprocess = true;
- }
+ } /** \todo parse error */
}
break;
case HUBBUB_TOKEN_EOF:
@@ -762,10 +773,12 @@
switch (token->type) {
case HUBBUB_TOKEN_CHARACTER:
+ /* This should be equivalent to "in head" processing */
reprocess = process_characters_expect_whitespace(treebuilder,
token, true);
break;
case HUBBUB_TOKEN_COMMENT:
+ /* This should be equivalent to "in head" processing */
process_comment_append(treebuilder, token,
treebuilder->context.element_stack[
treebuilder->context.current_node].node);
@@ -781,10 +794,27 @@
if (type == HTML) {
/* Process as "in body" */
process_tag_in_body(treebuilder, token);
- } else if (type == LINK || type == META) {
- process_base_link_meta_in_head(treebuilder,
+ } else if (type == NOSCRIPT) {
+ handled = true;
+ } else if (type == LINK) {
+ /* This should be equivalent to "in head" processing */
+ process_base_link_meta_in_head(treebuilder,
token, type);
+
+ /** \todo ack sc flag */
+ } else if (type == META) {
+ /* This should be equivalent to "in head" processing */
+ process_base_link_meta_in_head(treebuilder,
+ token, type);
+
+ /** \todo ack sc flag */
+
+ /** \todo detect charset */
+ } else if (type == NOFRAMES) {
+ /* This should be equivalent to "in head" processing */
+ parse_generic_rcdata(treebuilder, token, true);
} else if (type == STYLE) {
+ /* This should be equivalent to "in head" processing */
parse_generic_rcdata(treebuilder, token, false);
} else if (type == HEAD || type == NOSCRIPT) {
/** \todo parse error */
@@ -801,7 +831,7 @@
if (type == NOSCRIPT) {
handled = true;
- } else if (type == P || type == BR) {
+ } else if (type == BR) {
/** \todo parse error */
reprocess = true;
} else {
@@ -848,8 +878,7 @@
switch (token->type) {
case HUBBUB_TOKEN_CHARACTER:
- reprocess = process_characters_expect_whitespace(treebuilder,
- token, true);
+ append_text(treebuilder, &token->data.character);
break;
case HUBBUB_TOKEN_COMMENT:
process_comment_append(treebuilder, token,
@@ -873,8 +902,8 @@
insert_element(treebuilder, &token->data.tag);
treebuilder->context.mode = IN_FRAMESET;
} else if (type == BASE || type == LINK || type == META ||
- type == SCRIPT || type == STYLE ||
- type == TITLE) {
+ type == NOFRAMES || type == SCRIPT ||
+ type == STYLE || type == TITLE) {
element_type otype;
void *node;
@@ -886,12 +915,16 @@
/** \todo errors */
}
+
+ /* This should be identical to handling "in head" */
if (type == BASE || type == LINK || type == META) {
+ /** \todo ack sc flag */
+
process_base_link_meta_in_head(treebuilder,
token, type);
} else if (type == SCRIPT) {
process_script_in_head(treebuilder, token);
- } else if (type == STYLE) {
+ } else if (type == STYLE || type == NOFRAMES) {
parse_generic_rcdata(treebuilder, token, false);
} else if (type == TITLE) {
parse_generic_rcdata(treebuilder, token, true);
@@ -903,12 +936,16 @@
/* No need to unref node as we never increased
* its reference count when pushing it on the stack */
+ } else if (type == HEAD) {
+ /** \todo parse error */
} else {
reprocess = true;
}
}
break;
case HUBBUB_TOKEN_END_TAG:
+ /** \parse error */
+ break;
case HUBBUB_TOKEN_EOF:
reprocess = true;
break;
@@ -1093,8 +1130,6 @@
int success;
void *text, *appended;
- /** \todo fragment case -- skip this lot entirely */
-
success = treebuilder->tree_handler->create_text(
treebuilder->tree_handler->ctx,
&treebuilder->context.collect.string,
@@ -1102,6 +1137,8 @@
if (success != 0) {
/** \todo errors */
}
+
+ /** \todo fragment case -- skip this lot entirely */
success = treebuilder->tree_handler->append_child(
treebuilder->tree_handler->ctx,
@@ -2093,7 +2130,7 @@
*/
const char *element_type_to_name(element_type type)
{
- for (uint32_t i = 0;
+ for (size_t i = 0;
i < sizeof(name_type_map) / sizeof(name_type_map[0]);
i++) {
if (name_type_map[i].type == type)
14 years, 9 months
r4425 takkaria - /trunk/hubbub/docs/doxygen.conf
by netsurf@semichrome.net
Author: takkaria
Date: Sun Jun 22 22:05:07 2008
New Revision: 4425
URL: http://source.netsurf-browser.org?rev=4425&view=rev
Log:
Make the doxygen file a bit more useful, and also let it output man files for quick reference.
Modified:
trunk/hubbub/docs/doxygen.conf
Modified: trunk/hubbub/docs/doxygen.conf
URL: http://source.netsurf-browser.org/trunk/hubbub/docs/doxygen.conf?rev=4425...
==============================================================================
--- trunk/hubbub/docs/doxygen.conf (original)
+++ trunk/hubbub/docs/doxygen.conf Sun Jun 22 22:05:07 2008
@@ -137,7 +137,7 @@
# comments will behave just like regular Qt-style comments
# (thus requiring an explicit @brief command for a brief description.)
-JAVADOC_AUTOBRIEF = NO
+JAVADOC_AUTOBRIEF = YES
# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
# interpret the first line (until the first dot) of a Qt-style
@@ -965,7 +965,7 @@
# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
# generate man pages
-GENERATE_MAN = NO
+GENERATE_MAN = YES
# The MAN_OUTPUT tag is used to specify where the man pages will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
@@ -984,7 +984,7 @@
# only source the real man page, but without them the man command
# would be unable to find the correct page. The default is NO.
-MAN_LINKS = NO
+MAN_LINKS = YES
#---------------------------------------------------------------------------
# configuration options related to the XML output
14 years, 9 months
r4424 dynis - in /branches/dynis/libnsgif: examples/decode_gif.c libnsgif.c libnsgif.h
by netsurf@semichrome.net
Author: dynis
Date: Sun Jun 22 14:25:33 2008
New Revision: 4424
URL: http://source.netsurf-browser.org?rev=4424&view=rev
Log:
Return values are now in an enum
Modified:
branches/dynis/libnsgif/examples/decode_gif.c
branches/dynis/libnsgif/libnsgif.c
branches/dynis/libnsgif/libnsgif.h
Modified: branches/dynis/libnsgif/examples/decode_gif.c
URL: http://source.netsurf-browser.org/branches/dynis/libnsgif/examples/decode...
==============================================================================
--- branches/dynis/libnsgif/examples/decode_gif.c (original)
+++ branches/dynis/libnsgif/examples/decode_gif.c Sun Jun 22 14:25:33 2008
@@ -69,9 +69,9 @@
/* begin decoding */
do {
code = gif_initialise(&gif, &bitmap_callbacks);
- if (code != 0 && code != 1)
+ if (code != GIF_OK && code != GIF_WORKING)
warning("gif_initialise", code);
- } while (code != 1);
+ } while (code != GIF_OK);
printf("P3\n");
printf("# %s\n", argv[1]);
@@ -89,7 +89,7 @@
char *image;
code = gif_decode_frame(&gif, i, &bitmap_callbacks);
- if (code != 0)
+ if (code != GIF_OK)
warning("gif_decode_frame", code);
printf("# frame %u:\n", i);
Modified: branches/dynis/libnsgif/libnsgif.c
URL: http://source.netsurf-browser.org/branches/dynis/libnsgif/libnsgif.c?rev=...
==============================================================================
--- branches/dynis/libnsgif/libnsgif.c (original)
+++ branches/dynis/libnsgif/libnsgif.c Sun Jun 22 14:25:33 2008
@@ -67,8 +67,8 @@
/* Internal GIF routines
*/
-static int gif_initialise_sprite(struct gif_animation *gif, unsigned int width, unsigned int height, gif_bitmap_callback_vt *bitmap_callbacks);
-static int gif_initialise_frame(struct gif_animation *gif, gif_bitmap_callback_vt *bitmap_callbacks);
+static gif_result gif_initialise_sprite(struct gif_animation *gif, unsigned int width, unsigned int height, gif_bitmap_callback_vt *bitmap_callbacks);
+static gif_result gif_initialise_frame(struct gif_animation *gif, gif_bitmap_callback_vt *bitmap_callbacks);
static unsigned int gif_interlaced_line(int height, int y);
@@ -102,7 +102,7 @@
*/
static bool clear_image = false;
-/* Initialises any workspace held by the animation and attempts to decode
+/** Initialises any workspace held by the animation and attempts to decode
any information that hasn't already been decoded.
If an error occurs, all previously decoded frames are retained.
@@ -112,10 +112,10 @@
GIF_INSUFFICIENT_MEMORY for memory error
GIF_DATA_ERROR for GIF error
GIF_INSUFFICIENT_DATA for insufficient data to do anything
- 0 for successful decoding
- 1 for successful decoding (all frames completely read)
+ GIF_OK for successful decoding
+ GIF_WORKING for successful decoding if more frames are expected
*/
-int gif_initialise(struct gif_animation *gif, gif_bitmap_callback_vt *bitmap_callbacks) {
+gif_result gif_initialise(struct gif_animation *gif, gif_bitmap_callback_vt *bitmap_callbacks) {
unsigned char *gif_data;
unsigned int index;
int return_value;
@@ -225,7 +225,7 @@
*/
if (gif->buffer_size == 14) {
if (gif_data[0] == GIF_TRAILER)
- return 1;
+ return GIF_OK;
else
return GIF_INSUFFICIENT_DATA;
}
@@ -274,9 +274,9 @@
}
}
- /* Repeatedly try to decode frames
- */
- while ((return_value = gif_initialise_frame(gif, bitmap_callbacks)) == 0);
+ /* Repeatedly try to initialise frames
+ */
+ while ((return_value = gif_initialise_frame(gif, bitmap_callbacks)) == GIF_WORKING);
/* If there was a memory error tell the caller
*/
@@ -299,10 +299,10 @@
/** Updates the sprite memory size
- @return -3 for a memory error
- 0 for success
+ @return GIF_INSUFFICIENT_MEMORY for a memory error
+ GIF_OK for success
*/
-static int gif_initialise_sprite(struct gif_animation *gif, unsigned int width, unsigned int height, gif_bitmap_callback_vt *bitmap_callbacks) {
+static gif_result gif_initialise_sprite(struct gif_animation *gif, unsigned int width, unsigned int height, gif_bitmap_callback_vt *bitmap_callbacks) {
unsigned int max_width;
unsigned int max_height;
struct bitmap *buffer;
@@ -310,7 +310,7 @@
/* Check if we've changed
*/
if ((width <= gif->width) && (height <= gif->height))
- return 0;
+ return GIF_OK;
/* Get our maximum values
*/
@@ -329,20 +329,21 @@
/* Invalidate our currently decoded image
*/
gif->decoded_frame = -1;
- return 0;
+ return GIF_OK;
}
-/* Attempts to initialise the next frame
-
- @return -4 for insufficient data to process the entire frame
- -3 for a memory error
- -2 for a data error
- -1 for insufficient data to process anything
- 0 for success
- 1 for success (GIF terminator found)
+/** Attempts to initialise the next frame
+
+ @return GIF_INSUFFICIENT_DATA for insufficient data to do anything
+ GIF_FRAME_DATA_ERROR for GIF frame data error
+ GIF_INSUFFICIENT_MEMORY for insufficient memory to process
+ GIF_INSUFFICIENT_FRAME_DATA for insufficient data to complete the frame
+ GIF_DATA_ERROR for GIF error (invalid frame header)
+ GIF_OK for successful decoding
+ GIF_WORKING for successful decoding if more frames are expected
*/
-int gif_initialise_frame(struct gif_animation *gif, gif_bitmap_callback_vt *bitmap_callbacks) {
+gif_result gif_initialise_frame(struct gif_animation *gif, gif_bitmap_callback_vt *bitmap_callbacks) {
int frame;
gif_frame *temp_buf;
@@ -368,17 +369,17 @@
/* Check if we've finished
*/
- if ((gif_bytes > 0) && (gif_data[0] == GIF_TRAILER)) return 1;
+ if ((gif_bytes > 0) && (gif_data[0] == GIF_TRAILER)) return GIF_OK;
/* Check if we have enough data
* The shortest block of data is a 4-byte comment extension + 1-byte block terminator + 1-byte gif trailer
*/
- if (gif_bytes < 6) return GIF_INSUFFICIENT_FRAME_DATA;
+ if (gif_bytes < 6) return GIF_INSUFFICIENT_DATA;
/* We could theoretically get some junk data that gives us millions of frames, so
we ensure that we don't have a silly number
*/
- if (frame > 4096) return GIF_DATA_ERROR;
+ if (frame > 4096) return GIF_FRAME_DATA_ERROR;
/* Get some memory to store our pointers in etc.
*/
@@ -469,7 +470,7 @@
else if (gif_data[0] == GIF_TRAILER) {
gif->buffer_position = gif_data - gif->gif_data;
gif->frame_count = frame + 1;
- return 1;
+ return GIF_OK;
}
/* If we're not done, there should be an image descriptor
@@ -571,8 +572,8 @@
if (gif_bytes < 1)
return GIF_INSUFFICIENT_FRAME_DATA;
else
- if (gif_data[0] == GIF_TRAILER) return 1;
- return 0;
+ if (gif_data[0] == GIF_TRAILER) return GIF_OK;
+ return GIF_WORKING;
}
@@ -582,11 +583,11 @@
GIF_INSUFFICIENT_FRAME_DATA for insufficient data to complete the frame
GIF_DATA_ERROR for GIF error (invalid frame header)
GIF_INSUFFICIENT_DATA for insufficient data to do anything
- 0 for successful decoding
- If a frame does not contain any image data, 0 is returned and
+ GIF_OK for successful decoding
+ If a frame does not contain any image data, GIF_OK is returned and
gif->current_error is set to GIF_FRAME_NO_DISPLAY
*/
-int gif_decode_frame(struct gif_animation *gif, unsigned int frame, gif_bitmap_callback_vt *bitmap_callbacks) {
+gif_result gif_decode_frame(struct gif_animation *gif, unsigned int frame, gif_bitmap_callback_vt *bitmap_callbacks) {
unsigned int index = 0;
unsigned char *gif_data;
unsigned char *gif_end;
@@ -611,7 +612,7 @@
gif->current_error = 0;
if (gif->frames[frame].display == false) {
gif->current_error = GIF_FRAME_NO_DISPLAY;
- return 0;
+ return GIF_OK;
}
/* Ensure we have a frame to decode
@@ -619,7 +620,7 @@
if (frame > gif->frame_count_partial)
return GIF_INSUFFICIENT_DATA;
if ((!clear_image) && ((int)frame == gif->decoded_frame))
- return 0;
+ return GIF_OK;
/* If the previous frame was dirty, remove it
*/
@@ -794,7 +795,7 @@
return_value = GIF_INSUFFICIENT_FRAME_DATA;
break;
} else if (gif_data[0] == GIF_TRAILER) {
- return_value = 1;
+ return_value = GIF_OK;
break;
}
@@ -809,7 +810,7 @@
/* If we only have the 1-byte LZW code size + 1-byte gif trailer, we're finished
*/
} else if ((gif_bytes = 2) && (gif_data[1] == GIF_TRAILER)) {
- return_value = 1;
+ return_value = GIF_OK;
break;
}
Modified: branches/dynis/libnsgif/libnsgif.h
URL: http://source.netsurf-browser.org/branches/dynis/libnsgif/libnsgif.h?rev=...
==============================================================================
--- branches/dynis/libnsgif/libnsgif.h (original)
+++ branches/dynis/libnsgif/libnsgif.h Sun Jun 22 14:25:33 2008
@@ -28,12 +28,16 @@
/* Error return values
*/
-#define GIF_INSUFFICIENT_FRAME_DATA -1
-#define GIF_FRAME_DATA_ERROR -2
-#define GIF_INSUFFICIENT_DATA -3
-#define GIF_DATA_ERROR -4
-#define GIF_INSUFFICIENT_MEMORY -5
-#define GIF_FRAME_NO_DISPLAY -6
+typedef enum {
+ GIF_WORKING = 1,
+ GIF_OK = 0,
+ GIF_INSUFFICIENT_FRAME_DATA = -1,
+ GIF_FRAME_DATA_ERROR = -2,
+ GIF_INSUFFICIENT_DATA = -3,
+ GIF_DATA_ERROR = -4,
+ GIF_INSUFFICIENT_MEMORY = -5,
+ GIF_FRAME_NO_DISPLAY = -6
+} gif_result;
/* Maximum colour table size
*/
@@ -107,8 +111,8 @@
int current_error; /**< current error type, or 0 for none*/
} gif_animation;
-int gif_initialise(struct gif_animation *gif, gif_bitmap_callback_vt *bitmap_callbacks);
-int gif_decode_frame(struct gif_animation *gif, unsigned int frame, gif_bitmap_callback_vt *bitmap_callbacks);
+gif_result gif_initialise(struct gif_animation *gif, gif_bitmap_callback_vt *bitmap_callbacks);
+gif_result gif_decode_frame(struct gif_animation *gif, unsigned int frame, gif_bitmap_callback_vt *bitmap_callbacks);
void gif_finalise(struct gif_animation *gif, gif_bitmap_callback_vt *bitmap_callbacks);
#endif
14 years, 9 months