예제 #1
0
파일: theme.c 프로젝트: pcwalton/NetSurf
/**
 * when CONTENT_THEME needs handling call this function
 */
void theme_install_start(hlcache_handle *c)
{
	assert(c);
	assert(content_get_type(c) == CONTENT_THEME);

	/* stop theme sitting in memory cache */
	content_invalidate_reuse_data(c);

	hlcache_handle_replace_callback(c, theme_install_callback, NULL);
}
예제 #2
0
static bool save_complete_save_html_object(save_complete_ctx *ctx,
		hlcache_handle *obj)
{
	const char *obj_data;
	unsigned long obj_size;
	lwc_string *type;
	bool result;
	char filename[32];

	if (content_get_type(obj) == CONTENT_NONE)
		return true;

	obj_data = content_get_source_data(obj, &obj_size);
	if (obj_data == NULL)
		return true;

	if (save_complete_ctx_has_content(ctx, obj))
		return true;

	if (save_complete_ctx_add_content(ctx, obj) == false) {
		warn_user("NoMemory", 0);
		return false;
	}

	if (content_get_type(obj) == CONTENT_HTML) {
		return save_complete_save_html(ctx, obj, false);
	}

	snprintf(filename, sizeof filename, "%p", obj);

	type = content_get_mime_type(obj);
	if (type == NULL)
		return false;

	result = save_complete_save_buffer(ctx, filename, 
			obj_data, obj_size, type);

	lwc_string_unref(type);

	return result;
}
예제 #3
0
nserror html_object_close_objects(html_content *html)
{
	struct content_html_object *object, *next;

	for (object = html->object_list; object != NULL; object = next) {
		next = object->next;

		if (object->content == NULL || object->box == NULL)
			continue;

		if (content_get_type(object->content) == CONTENT_NONE)
			continue;

		if (content_get_type(object->content) == CONTENT_HTML) {
			guit->misc->schedule(-1, html_object_refresh, object);
		}

		content_close(object->content);
	}
	return NSERROR_OK;
}
예제 #4
0
bool ro_gui_url_bar_set_site_favicon(struct url_bar *url_bar,
		struct hlcache_handle *h)
{
	content_type		type = CONTENT_NONE;

	if (url_bar == NULL)
		return false;

	if (h != NULL)
		type = content_get_type(h);

	// \TODO -- Maybe test for CONTENT_ICO ???

	if (type == CONTENT_IMAGE) {
		url_bar->favicon_content = h;
		url_bar->favicon_width = content_get_width(h);
		url_bar->favicon_height = content_get_height(h);

		if (url_bar->favicon_width > URLBAR_FAVICON_SIZE)
			url_bar->favicon_width = URLBAR_FAVICON_SIZE;

		if (url_bar->favicon_height > URLBAR_FAVICON_SIZE)
			url_bar->favicon_height = URLBAR_FAVICON_SIZE;

		url_bar->favicon_offset.x = ((url_bar->favicon_extent.x1 -
				url_bar->favicon_extent.x0) -
				(url_bar->favicon_width * 2)) / 2;
		url_bar->favicon_offset.y = ((url_bar->favicon_extent.y1 -
				url_bar->favicon_extent.y0) -
				(url_bar->favicon_height * 2)) / 2;
	} else {
		url_bar->favicon_content = NULL;

		if (url_bar->favicon_type != 0)
			snprintf(url_bar->favicon_sprite,
					URLBAR_FAVICON_NAME_LENGTH,
					"Ssmall_%.3x", url_bar->favicon_type);
		else
			snprintf(url_bar->favicon_sprite,
					URLBAR_FAVICON_NAME_LENGTH,
					"Ssmall_xxx");
	}

		if (!url_bar->hidden)
			xwimp_force_redraw(url_bar->window,
				url_bar->favicon_extent.x0,
				url_bar->favicon_extent.y0,
				url_bar->favicon_extent.x1,
				url_bar->favicon_extent.y1);

	return true;
}
예제 #5
0
nserror nsgtk_viewsource(GtkWindow *parent, struct browser_window *bw)
{
	nserror ret;
	struct hlcache_handle *hlcontent;
	const char *source_data;
	unsigned long source_size;
	char *ndata = NULL;
	size_t ndata_len;
	char *filename;
	char *title;

	hlcontent = browser_window_get_content(bw);
	if (hlcontent == NULL) {
		return NSERROR_BAD_PARAMETER;
	}

	if (content_get_type(hlcontent) != CONTENT_HTML) {
		return NSERROR_BAD_CONTENT;
	}

	source_data = content_get_source_data(hlcontent, &source_size);

	ret = nsurl_nice(browser_window_get_url(bw), &filename, false);
	if (ret != NSERROR_OK) {
		filename = strdup(messages_get("SaveSource"));
		if (filename == NULL) {
			return NSERROR_NOMEM;
		}
	}

	title = malloc(strlen(nsurl_access(browser_window_get_url(bw))) + SLEN("Source of  - NetSurf") + 1);
	if (title == NULL) {
		free(filename);
		return NSERROR_NOMEM;
	}
	sprintf(title, "Source of %s - NetSurf", nsurl_access(browser_window_get_url(bw)));

	ret = utf8_from_enc(source_data,
			    content_get_encoding(hlcontent, CONTENT_ENCODING_NORMAL),
			    source_size,
			    &ndata,
			    &ndata_len);
	if (ret == NSERROR_OK) {
		ret = nsgtk_viewdata(title, filename, ndata, ndata_len);
	}

	free(filename);
	free(title);

	return ret;
}
예제 #6
0
/* attempt defer and async script execution
 *
 * execute scripts using algorithm found in:
 * http://www.whatwg.org/specs/web-apps/current-work/multipage/scripting-1.html#the-script-element
 *
 */
bool html_scripts_exec(html_content *c)
{
	unsigned int i;
	struct html_script *s;
	script_handler_t *script_handler;

	if (c->jscontext == NULL)
		return false;

	for (i = 0, s = c->scripts; i != c->scripts_count; i++, s++) {
		if (s->already_started) {
			continue;
		}

		if ((s->type == HTML_SCRIPT_ASYNC) ||
		    (s->type == HTML_SCRIPT_DEFER)) {
			/* ensure script content is present */
			if (s->data.handle == NULL)
				continue;

			/* ensure script content fetch status is not an error */
			if (content_get_status(s->data.handle) ==
					CONTENT_STATUS_ERROR)
				continue;

			/* ensure script handler for content type */
			script_handler = select_script_handler(
					content_get_type(s->data.handle));
			if (script_handler == NULL)
				continue; /* unsupported type */

			if (content_get_status(s->data.handle) ==
					CONTENT_STATUS_DONE) {
				/* external script is now available */
				const char *data;
				unsigned long size;
				data = content_get_source_data(
						s->data.handle, &size );
				script_handler(c->jscontext, data, size);

				s->already_started = true;

			} 
		}
	}

	return true;
}
예제 #7
0
/**
 * Save an HTML page with all dependencies, recursing through imported pages.
 *
 * \param  ctx    Save complete context
 * \param  c      Content to save
 * \param  index  true to save as "index"
 * \return  true on success, false on error and error reported
 */
static bool save_complete_save_html(save_complete_ctx *ctx, hlcache_handle *c,
		bool index)
{
	if (content_get_type(c) != CONTENT_HTML)
		return false;

	if (save_complete_ctx_has_content(ctx, c))
		return true;

	if (save_complete_save_html_stylesheets(ctx, c) == false)
		return false;

	if (save_complete_save_html_objects(ctx, c) == false)
		return false;

	return save_complete_save_html_document(ctx, c, index);
}
예제 #8
0
void save_as_text(hlcache_handle *c, char *path)
{
	FILE *out;
	struct save_text_state save = { NULL, 0, 0 };
	save_text_whitespace before = WHITESPACE_NONE;
	bool first = true;
	nserror ret;
	char *result;

	if (!c || content_get_type(c) != CONTENT_HTML) {
		return;
	}

	extract_text(html_get_box_tree(c), &first, &before, &save);
	if (!save.block)
		return;

	ret = guit->utf8->utf8_to_local(save.block, save.length, &result);
	free(save.block);

	if (ret != NSERROR_OK) {
		LOG(("failed to convert to local encoding, return %d", ret));
		return;
	}

	out = fopen(path, "w");
	if (out) {
		int res = fputs(result, out);

		if (res < 0) {
			LOG(("Warning: write failed"));
		}

		res = fputs("\n", out);
		if (res < 0) {
			LOG(("Warning: failed writing trailing newline"));
		}

		fclose(out);
	}

	free(result);
}
예제 #9
0
nserror html_object_free_objects(html_content *html)
{
	while (html->object_list != NULL) {
		struct content_html_object *victim = html->object_list;

		if (victim->content != NULL) {
			LOG("object %p", victim->content);

			if (content_get_type(victim->content) == CONTENT_HTML) {
				guit->misc->schedule(-1, html_object_refresh, victim);
			}
			hlcache_handle_release(victim->content);
		}

		html->object_list = victim->next;
		free(victim);
	}
	return NSERROR_OK;
}
예제 #10
0
nserror html_object_open_objects(html_content *html, struct browser_window *bw)
{
	struct content_html_object *object, *next;

	for (object = html->object_list; object != NULL; object = next) {
		next = object->next;

		if (object->content == NULL || object->box == NULL)
			continue;

		if (content_get_type(object->content) == CONTENT_NONE)
			continue;

		content_open(object->content,
			     bw,
			     &html->base,
			     object->box->object_params);
	}
	return NSERROR_OK;
}
예제 #11
0
static void html_object_refresh(void *p)
{
	struct content_html_object *object = p;
	nsurl *refresh_url;

	assert(content_get_type(object->content) == CONTENT_HTML);

	refresh_url = content_get_refresh_url(object->content);

	/* Ignore if refresh URL has gone
	 * (may happen if fetch errored) */
	if (refresh_url == NULL)
		return;

	content_invalidate_reuse_data(object->content);

	if (!html_replace_object(object, refresh_url)) {
		/** \todo handle memory exhaustion */
	}
}
예제 #12
0
void theme_install_start(hlcache_handle *c)
{
	assert(c != NULL);
	assert(content_get_type(c) == CONTENT_THEME);

	if (ro_gui_dialog_open_top(dialog_theme_install, NULL, 0, 0)) {
		warn_user("ThemeInstActive", 0);
		return;
	}

	/* stop theme sitting in memory cache */
	content_invalidate_reuse_data(c);

	hlcache_handle_replace_callback(c, theme_install_callback, NULL);

	ro_gui_set_icon_string(dialog_theme_install, ICON_THEME_INSTALL_MESSAGE,
			messages_get("ThemeInstDown"), true);
	ro_gui_set_icon_shaded_state(dialog_theme_install,
			ICON_THEME_INSTALL_INSTALL, true);
	ro_gui_wimp_event_register_close_window(dialog_theme_install,
			theme_install_close);
}
예제 #13
0
파일: menu.c 프로젝트: ysei/NetSurf
static void ami_menu_item_edit_copy(struct Hook *hook, APTR window, struct IntuiMessage *msg)
{
	struct bitmap *bm;
	struct gui_window_2 *gwin;
	GetAttr(WINDOW_UserData, (Object *)window, (ULONG *)&gwin);

	if(content_get_type(gwin->bw->current_content) <= CONTENT_CSS)
	{
		browser_window_key_press(gwin->bw, KEY_COPY_SELECTION);
		browser_window_key_press(gwin->bw, KEY_CLEAR_SELECTION);
	}
	else if(bm = content_get_bitmap(gwin->bw->current_content))
	{
		bm->url = (char *)nsurl_access(hlcache_handle_get_url(gwin->bw->current_content));
		bm->title = (char *)content_get_title(gwin->bw->current_content);
		ami_easy_clipboard_bitmap(bm);
	}
#ifdef WITH_NS_SVG
	else if(ami_mime_compare(gwin->bw->current_content, "svg") == true)
	{
		ami_easy_clipboard_svg(gwin->bw->current_content);
	}
#endif
}
예제 #14
0
파일: menu.c 프로젝트: ysei/NetSurf
void ami_menu_update_disabled(struct gui_window *g, hlcache_handle *c)
{
	struct Window *win = g->shared->win;

	if(nsoption_bool(kiosk_mode) == true) return;

	if(content_get_type(c) <= CONTENT_CSS)
	{
		OnMenu(win,AMI_MENU_SAVEAS_TEXT);
		OnMenu(win,AMI_MENU_SAVEAS_COMPLETE);
#ifdef WITH_PDF_EXPORT
		OnMenu(win,AMI_MENU_SAVEAS_PDF);
#endif
		if(browser_window_get_editor_flags(g->shared->bw) & BW_EDITOR_CAN_COPY)
		{
			OnMenu(win,AMI_MENU_COPY);
			OnMenu(win,AMI_MENU_CLEAR);
		} else {
			OffMenu(win,AMI_MENU_COPY);
			OffMenu(win,AMI_MENU_CLEAR);	
		}

		if(browser_window_get_editor_flags(g->shared->bw) & BW_EDITOR_CAN_CUT)
			OnMenu(win,AMI_MENU_CUT);
		else
			OffMenu(win,AMI_MENU_CUT);		
		
		if(browser_window_get_editor_flags(g->shared->bw) & BW_EDITOR_CAN_PASTE)
			OnMenu(win,AMI_MENU_PASTE);
		else
			OffMenu(win,AMI_MENU_PASTE);

		OnMenu(win,AMI_MENU_SELECTALL);
		OnMenu(win,AMI_MENU_FIND);
		OffMenu(win,AMI_MENU_SAVEAS_IFF);
	}
	else
	{
		OffMenu(win,AMI_MENU_CUT);
		OffMenu(win,AMI_MENU_PASTE);
		OffMenu(win,AMI_MENU_CLEAR);

		OffMenu(win,AMI_MENU_SAVEAS_TEXT);
		OffMenu(win,AMI_MENU_SAVEAS_COMPLETE);
#ifdef WITH_PDF_EXPORT
		OffMenu(win,AMI_MENU_SAVEAS_PDF);
#endif
		OffMenu(win,AMI_MENU_SELECTALL);
		OffMenu(win,AMI_MENU_FIND);

#ifdef WITH_NS_SVG
		if(content_get_bitmap(c) || (ami_mime_compare(c, "svg") == true))
#else
		if(content_get_bitmap(c))
#endif
		{
			OnMenu(win,AMI_MENU_COPY);
			OnMenu(win,AMI_MENU_SAVEAS_IFF);
		}
		else
		{
			OffMenu(win,AMI_MENU_COPY);
			OffMenu(win,AMI_MENU_SAVEAS_IFF);
		}
	}
}
예제 #15
0
static nserror
html_object_callback(hlcache_handle *object,
		     const hlcache_event *event,
		     void *pw)
{
	struct content_html_object *o = pw;
	html_content *c = (html_content *) o->parent;
	int x, y;
	struct box *box;

	assert(c->base.status != CONTENT_STATUS_ERROR);

	box = o->box;
	if (box == NULL && event->type != CONTENT_MSG_ERROR) {
		return NSERROR_OK;
	}

	switch (event->type) {
	case CONTENT_MSG_LOADING:
		if (c->base.status != CONTENT_STATUS_LOADING && c->bw != NULL)
			content_open(object,
					c->bw, &c->base,
					box->object_params);
		break;

	case CONTENT_MSG_READY:
		if (content_can_reformat(object)) {
			/* TODO: avoid knowledge of box internals here */
			content_reformat(object, false,
					box->max_width != UNKNOWN_MAX_WIDTH ?
							box->width : 0,
					box->max_width != UNKNOWN_MAX_WIDTH ?
							box->height : 0);

			/* Adjust parent content for new object size */
			html_object_done(box, object, o->background);
			if (c->base.status == CONTENT_STATUS_READY ||
					c->base.status == CONTENT_STATUS_DONE)
				content__reformat(&c->base, false,
						c->base.available_width,
						c->base.height);
		}
		break;

	case CONTENT_MSG_DONE:
		c->base.active--;
		LOG("%d fetches active", c->base.active);

		html_object_done(box, object, o->background);

		if (c->base.status != CONTENT_STATUS_LOADING &&
				box->flags & REPLACE_DIM) {
			union content_msg_data data;

			if (!box_visible(box))
				break;

			box_coords(box, &x, &y);

			data.redraw.x = x + box->padding[LEFT];
			data.redraw.y = y + box->padding[TOP];
			data.redraw.width = box->width;
			data.redraw.height = box->height;
			data.redraw.full_redraw = true;

			content_broadcast(&c->base, CONTENT_MSG_REDRAW, data);
		}
		break;

	case CONTENT_MSG_ERROR:
		hlcache_handle_release(object);

		o->content = NULL;

		if (box != NULL) {
			c->base.active--;
			LOG("%d fetches active", c->base.active);

			content_add_error(&c->base, "?", 0);
			html_object_failed(box, c, o->background);
		}
		break;

	case CONTENT_MSG_REDRAW:
		if (c->base.status != CONTENT_STATUS_LOADING) {
			union content_msg_data data = event->data;

			if (!box_visible(box))
				break;

			box_coords(box, &x, &y);

			if (object == box->background) {
				/* Redraw request is for background */
				css_fixed hpos = 0, vpos = 0;
				css_unit hunit = CSS_UNIT_PX;
				css_unit vunit = CSS_UNIT_PX;
				int width = box->padding[LEFT] + box->width +
						box->padding[RIGHT];
				int height = box->padding[TOP] + box->height +
						box->padding[BOTTOM];
				int t, h, l, w;

				/* Need to know background-position */
				css_computed_background_position(box->style,
						&hpos, &hunit, &vpos, &vunit);

				w = content_get_width(box->background);
				if (hunit == CSS_UNIT_PCT) {
					l = (width - w) * hpos / INTTOFIX(100);
				} else {
					l = FIXTOINT(nscss_len2px(hpos, hunit,
							box->style));
				}

				h = content_get_height(box->background);
				if (vunit == CSS_UNIT_PCT) {
					t = (height - h) * vpos / INTTOFIX(100);
				} else {
					t = FIXTOINT(nscss_len2px(vpos, vunit,
							box->style));
				}

				/* Redraw area depends on background-repeat */
				switch (css_computed_background_repeat(
						box->style)) {
				case CSS_BACKGROUND_REPEAT_REPEAT:
					data.redraw.x = 0;
					data.redraw.y = 0;
					data.redraw.width = box->width;
					data.redraw.height = box->height;
					break;

				case CSS_BACKGROUND_REPEAT_REPEAT_X:
					data.redraw.x = 0;
					data.redraw.y += t;
					data.redraw.width = box->width;
					break;

				case CSS_BACKGROUND_REPEAT_REPEAT_Y:
					data.redraw.x += l;
					data.redraw.y = 0;
					data.redraw.height = box->height;
					break;

				case CSS_BACKGROUND_REPEAT_NO_REPEAT:
					data.redraw.x += l;
					data.redraw.y += t;
					break;

				default:
					break;
				}

				data.redraw.object_width = box->width;
				data.redraw.object_height = box->height;

				/* Add offset to box */
				data.redraw.x += x;
				data.redraw.y += y;
				data.redraw.object_x += x;
				data.redraw.object_y += y;

				content_broadcast(&c->base,
						CONTENT_MSG_REDRAW, data);
				break;

			} else {
				/* Non-background case */
				if (hlcache_handle_get_content(object) ==
						event->data.redraw.object) {

					int w = content_get_width(object);
					int h = content_get_height(object);

					if (w != 0) {
						data.redraw.x =
							data.redraw.x *
							box->width / w;
						data.redraw.width =
							data.redraw.width *
							box->width / w;
					}

					if (h != 0) {
						data.redraw.y =
							data.redraw.y *
							box->height / h;
						data.redraw.height =
							data.redraw.height *
							box->height / h;
					}

					data.redraw.object_width = box->width;
					data.redraw.object_height = box->height;
				}

				data.redraw.x += x + box->padding[LEFT];
				data.redraw.y += y + box->padding[TOP];
				data.redraw.object_x += x + box->padding[LEFT];
				data.redraw.object_y += y + box->padding[TOP];
			}

			content_broadcast(&c->base, CONTENT_MSG_REDRAW, data);
		}
		break;

	case CONTENT_MSG_REFRESH:
		if (content_get_type(object) == CONTENT_HTML) {
			/* only for HTML objects */
			guit->misc->schedule(event->data.delay * 1000,
					html_object_refresh, o);
		}

		break;

	case CONTENT_MSG_LINK:
		/* Don't care about favicons that aren't on top level content */
		break;

	case CONTENT_MSG_GETCTX:
		*(event->data.jscontext) = NULL;
		break;

	case CONTENT_MSG_SCROLL:
		if (box->scroll_x != NULL)
			scrollbar_set(box->scroll_x, event->data.scroll.x0,
					false);
		if (box->scroll_y != NULL)
			scrollbar_set(box->scroll_y, event->data.scroll.y0,
					false);
		break;

	case CONTENT_MSG_DRAGSAVE:
	{
		union content_msg_data msg_data;
		if (event->data.dragsave.content == NULL)
			msg_data.dragsave.content = object;
		else
			msg_data.dragsave.content =
					event->data.dragsave.content;

		content_broadcast(&c->base, CONTENT_MSG_DRAGSAVE, msg_data);
	}
		break;

	case CONTENT_MSG_SAVELINK:
	case CONTENT_MSG_POINTER:
	case CONTENT_MSG_SELECTMENU:
	case CONTENT_MSG_GADGETCLICK:
		/* These messages are for browser window layer.
		 * we're not interested, so pass them on. */
		content_broadcast(&c->base, event->type, event->data);
		break;

	case CONTENT_MSG_CARET:
	{
		union html_focus_owner focus_owner;
		focus_owner.content = box;

		switch (event->data.caret.type) {
		case CONTENT_CARET_REMOVE:
		case CONTENT_CARET_HIDE:
			html_set_focus(c, HTML_FOCUS_CONTENT, focus_owner,
					true, 0, 0, 0, NULL);
			break;
		case CONTENT_CARET_SET_POS:
			html_set_focus(c, HTML_FOCUS_CONTENT, focus_owner,
					false, event->data.caret.pos.x,
					event->data.caret.pos.y,
					event->data.caret.pos.height,
					event->data.caret.pos.clip);
			break;
		}
	}
		break;

	case CONTENT_MSG_DRAG:
	{
		html_drag_type drag_type = HTML_DRAG_NONE;
		union html_drag_owner drag_owner;
		drag_owner.content = box;

		switch (event->data.drag.type) {
		case CONTENT_DRAG_NONE:
			drag_type = HTML_DRAG_NONE;
			drag_owner.no_owner = true;
			break;
		case CONTENT_DRAG_SCROLL:
			drag_type = HTML_DRAG_CONTENT_SCROLL;
			break;
		case CONTENT_DRAG_SELECTION:
			drag_type = HTML_DRAG_CONTENT_SELECTION;
			break;
		}
		html_set_drag_type(c, drag_type, drag_owner,
				event->data.drag.rect);
	}
		break;

	case CONTENT_MSG_SELECTION:
	{
		html_selection_type sel_type;
		union html_selection_owner sel_owner;

		if (event->data.selection.selection) {
			sel_type = HTML_SELECTION_CONTENT;
			sel_owner.content = box;
		} else {
			sel_type = HTML_SELECTION_NONE;
			sel_owner.none = true;
		}
		html_set_selection(c, sel_type, sel_owner,
				event->data.selection.read_only);
	}
		break;

	default:
		break;
	}

	if (c->base.status == CONTENT_STATUS_READY && c->base.active == 0 &&
			(event->type == CONTENT_MSG_LOADING ||
			event->type == CONTENT_MSG_DONE ||
			event->type == CONTENT_MSG_ERROR)) {
		/* all objects have arrived */
		content__reformat(&c->base, false, c->base.available_width,
				c->base.height);
		content_set_done(&c->base);
	}

	/* If  1) the configuration option to reflow pages while objects are
	 *        fetched is set
	 *     2) an object is newly fetched & converted,
	 *     3) the box's dimensions need to change due to being replaced
	 *     4) the object's parent HTML is ready for reformat,
	 *     5) the time since the previous reformat is more than the
	 *        configured minimum time between reformats
	 * then reformat the page to display newly fetched objects */
	else if (nsoption_bool(incremental_reflow) &&
			event->type == CONTENT_MSG_DONE &&
			box != NULL && !(box->flags & REPLACE_DIM) &&
			(c->base.status == CONTENT_STATUS_READY ||
			 c->base.status == CONTENT_STATUS_DONE) &&
			(wallclock() > c->base.reformat_time)) {
		content__reformat(&c->base, false, c->base.available_width,
				c->base.height);
	}

	return NSERROR_OK;
}
예제 #16
0
파일: save_pdf.c 프로젝트: kyllikki/netsurf
HPDF_Image pdf_extract_image(struct bitmap *bitmap)
{
	HPDF_Image image = NULL;
	hlcache_handle *content = NULL;

	/* TODO - get content from bitmap pointer */

	if (content) {
		const char *source_data;
		unsigned long source_size;

		/*Not sure if I don't have to check if downloading has been
		finished.
		Other way - lock pdf plotting while fetching a website
		*/
		source_data = content_get_source_data(content, &source_size);

		switch(content_get_type(content)){
		/*Handle "embeddable" types of images*/
		case CONTENT_JPEG:
 			image = HPDF_LoadJpegImageFromMem(pdf_doc,
 					(const HPDF_BYTE *) source_data,
 					source_size);
 			break;

		/*Disabled until HARU PNG support will be more stable.

		case CONTENT_PNG:
			image = HPDF_LoadPngImageFromMem(pdf_doc,
					(const HPDF_BYTE *)content->source_data,
					content->total_size);
			break;*/
		default:
			break;
		}
	}

	if (!image) {
		HPDF_Image smask;
		unsigned char *img_buffer, *rgb_buffer, *alpha_buffer;
		int img_width, img_height, img_rowstride;
		int i, j;

		/*Handle pixmaps*/
		img_buffer = bitmap_get_buffer(bitmap);
		img_width = bitmap_get_width(bitmap);
		img_height = bitmap_get_height(bitmap);
		img_rowstride = bitmap_get_rowstride(bitmap);

		rgb_buffer = (unsigned char *)malloc(3 * img_width * img_height);
		alpha_buffer = (unsigned char *)malloc(img_width * img_height);
		if (rgb_buffer == NULL || alpha_buffer == NULL) {
			NSLOG(netsurf, INFO,
			      "Not enough memory to create RGB buffer");
			free(rgb_buffer);
			free(alpha_buffer);
			return NULL;
		}

		for (i = 0; i < img_height; i++)
			for (j = 0; j < img_width; j++) {
				rgb_buffer[((i * img_width) + j) * 3] =
				  img_buffer[(i * img_rowstride) + (j * 4)];

				rgb_buffer[(((i * img_width) + j) * 3) + 1] =
				  img_buffer[(i * img_rowstride) + (j * 4) + 1];

				rgb_buffer[(((i * img_width) + j) * 3) + 2] =
				  img_buffer[(i * img_rowstride) + (j * 4) + 2];

				alpha_buffer[(i * img_width)+j] =
				  img_buffer[(i * img_rowstride) + (j * 4) + 3];
			}

		smask = HPDF_LoadRawImageFromMem(pdf_doc, alpha_buffer,
				img_width, img_height,
     				HPDF_CS_DEVICE_GRAY, 8);

		image = HPDF_LoadRawImageFromMem(pdf_doc, rgb_buffer,
				img_width, img_height,
     				HPDF_CS_DEVICE_RGB, 8);

		if (HPDF_Image_AddSMask(image, smask) != HPDF_OK)
			image = NULL;

		free(rgb_buffer);
		free(alpha_buffer);
	}

	return image;
}
예제 #17
0
bool save_complete_html(hlcache_handle *c, const char *path, bool index,
		struct save_complete_entry **list)
{
	struct html_stylesheet *sheets;
	struct content_html_object *objects;
	const char *base_url;
	char filename[256];
	unsigned int i, count;
	xmlDocPtr doc;
	bool res;

	if (content_get_type(c) != CONTENT_HTML)
		return false;

	if (save_complete_list_check(c, *list))
		return true;

	base_url = html_get_base_url(c);

	/* save stylesheets, ignoring the base and adblocking sheets */
	sheets = html_get_stylesheets(c, &count);

	for (i = STYLESHEET_START; i != count; i++) {
		hlcache_handle *css;
		const char *css_data;
		unsigned long css_size;
		char *source;
		int source_len;
		struct nscss_import *imports;
		uint32_t import_count;

		if (sheets[i].type == HTML_STYLESHEET_INTERNAL) {
			if (save_imported_sheets(
					sheets[i].data.internal->imports, 
					sheets[i].data.internal->import_count, 
					path, list) == false)
				return false;

			continue;
		}

		css = sheets[i].data.external;

		if (!css)
			continue;
		if (save_complete_list_check(css, *list))
			continue;

		if (!save_complete_list_add(css, list)) {
			warn_user("NoMemory", 0);
			return false;
		}

		imports = nscss_get_imports(css, &import_count);
		if (!save_imported_sheets(imports, import_count, path, list))
			return false;

		snprintf(filename, sizeof filename, "%p", css);

		css_data = content_get_source_data(css, &css_size);

		source = rewrite_stylesheet_urls(css_data, css_size, 
				&source_len, content_get_url(css),
				*list);
		if (!source) {
			warn_user("NoMemory", 0);
			return false;
		}
		res = save_complete_gui_save(path, filename, source_len,
				source, CONTENT_CSS);
		free(source);
		if (res == false)
			return false;
	}
	
	/* save objects */
	objects = html_get_objects(c, &count);

	for (i = 0; i != count; i++) {
		hlcache_handle *obj = objects[i].content;
		const char *obj_data;
		unsigned long obj_size;

		if (obj == NULL || content_get_type(obj) >= CONTENT_OTHER)
			continue;

		obj_data = content_get_source_data(obj, &obj_size);

		if (obj_data == NULL)
			continue;

		if (save_complete_list_check(obj, *list))
			continue;

		if (!save_complete_list_add(obj, list)) {
			warn_user("NoMemory", 0);
			return false;
		}

		if (content_get_type(obj) == CONTENT_HTML) {
			if (!save_complete_html(obj, path, false, list))
				return false;
			continue;
		}

		snprintf(filename, sizeof filename, "%p", obj);
		res = save_complete_gui_save(path, filename, 
				obj_size, obj_data, content_get_type(obj));
		if(res == false)
			return false;
	}

	/*save_complete_list_dump();*/

	/* copy document */
	doc = xmlCopyDoc(html_get_document(c), 1);
	if (doc == NULL) {
		warn_user("NoMemory", 0);
		return false;
	}

	/* rewrite all urls we know about */
	if (!rewrite_document_urls(doc, html_get_base_url(c), *list)) {
		xmlFreeDoc(doc);
		warn_user("NoMemory", 0);
		return false;
	}

	/* save the html file out last of all */
	if (index)
		snprintf(filename, sizeof filename, "index");
	else 
		snprintf(filename, sizeof filename, "%p", c);

	errno = 0;
	if (save_complete_htmlSaveFileFormat(path, filename, doc, 0, 0) == -1) {
		if (errno)
			warn_user("SaveError", strerror(errno));
		else
			warn_user("SaveError", "htmlSaveFileFormat failed");

		xmlFreeDoc(doc);
		return false;
	}	

	xmlFreeDoc(doc);

	return true;
}
예제 #18
0
void html_mouse_action(struct content *c, struct browser_window *bw,
                       browser_mouse_state mouse, int x, int y)
{
    html_content *html = (html_content *) c;
    enum { ACTION_NONE, ACTION_SUBMIT, ACTION_GO } action = ACTION_NONE;
    const char *title = 0;
    nsurl *url = 0;
    const char *target = 0;
    char status_buffer[200];
    const char *status = 0;
    browser_pointer_shape pointer = BROWSER_POINTER_DEFAULT;
    bool imagemap = false;
    int box_x = 0, box_y = 0;
    int gadget_box_x = 0, gadget_box_y = 0;
    int html_object_pos_x = 0, html_object_pos_y = 0;
    int text_box_x = 0;
    struct box *url_box = 0;
    struct box *gadget_box = 0;
    struct box *text_box = 0;
    struct box *box;
    struct form_control *gadget = 0;
    hlcache_handle *object = NULL;
    struct box *html_object_box = NULL;
    struct browser_window *iframe = NULL;
    struct box *next_box;
    struct box *drag_candidate = NULL;
    struct scrollbar *scrollbar = NULL;
    plot_font_style_t fstyle;
    int scroll_mouse_x = 0, scroll_mouse_y = 0;
    int padding_left, padding_right, padding_top, padding_bottom;
    browser_drag_type drag_type = browser_window_get_drag_type(bw);
    union content_msg_data msg_data;
    struct dom_node *node = NULL;
    union html_drag_owner drag_owner;
    union html_selection_owner sel_owner;
    bool click = mouse & (BROWSER_MOUSE_PRESS_1 | BROWSER_MOUSE_PRESS_2 |
                          BROWSER_MOUSE_CLICK_1 | BROWSER_MOUSE_CLICK_2 |
                          BROWSER_MOUSE_DRAG_1 | BROWSER_MOUSE_DRAG_2);

    if (drag_type != DRAGGING_NONE && !mouse &&
            html->visible_select_menu != NULL) {
        /* drag end: select menu */
        form_select_mouse_drag_end(html->visible_select_menu,
                                   mouse, x, y);
    }

    if (html->visible_select_menu != NULL) {
        box = html->visible_select_menu->box;
        box_coords(box, &box_x, &box_y);

        box_x -= box->border[LEFT].width;
        box_y += box->height + box->border[BOTTOM].width +
                 box->padding[BOTTOM] + box->padding[TOP];
        status = form_select_mouse_action(html->visible_select_menu,
                                          mouse, x - box_x, y - box_y);
        if (status != NULL) {
            msg_data.explicit_status_text = status;
            content_broadcast(c, CONTENT_MSG_STATUS, msg_data);
        } else {
            int width, height;
            form_select_get_dimensions(html->visible_select_menu,
                                       &width, &height);
            html->visible_select_menu = NULL;
            browser_window_redraw_rect(bw, box_x, box_y,
                                       width, height);
        }
        return;
    }

    if (html->drag_type == HTML_DRAG_SELECTION) {
        /* Selection drag */
        struct box *box;
        int dir = -1;
        int dx, dy;

        if (!mouse) {
            /* End of selection drag */
            int dir = -1;
            size_t idx;

            if (selection_dragging_start(&html->sel))
                dir = 1;

            idx = html_selection_drag_end(html, mouse, x, y, dir);

            if (idx != 0)
                selection_track(&html->sel, mouse, idx);

            drag_owner.no_owner = true;
            html_set_drag_type(html, HTML_DRAG_NONE,
                               drag_owner, NULL);
            return;
        }

        if (selection_dragging_start(&html->sel))
            dir = 1;

        box = box_pick_text_box(html, x, y, dir, &dx, &dy);

        if (box != NULL) {
            int pixel_offset;
            size_t idx;
            plot_font_style_t fstyle;

            font_plot_style_from_css(box->style, &fstyle);

            nsfont.font_position_in_string(&fstyle,
                                           box->text, box->length,
                                           dx, &idx, &pixel_offset);

            selection_track(&html->sel, mouse,
                            box->byte_offset + idx);
        }
        return;
    }

    if (html->drag_type == HTML_DRAG_SCROLLBAR) {
        struct scrollbar *scr = html->drag_owner.scrollbar;
        struct html_scrollbar_data *data = scrollbar_get_data(scr);

        if (!mouse) {
            /* drag end: scrollbar */
            html_overflow_scroll_drag_end(scr, mouse, x, y);
        }

        box = data->box;
        box_coords(box, &box_x, &box_y);
        if (scrollbar_is_horizontal(scr)) {
            scroll_mouse_x = x - box_x ;
            scroll_mouse_y = y - (box_y + box->padding[TOP] +
                                  box->height + box->padding[BOTTOM] -
                                  SCROLLBAR_WIDTH);
            status = scrollbar_mouse_status_to_message(
                         scrollbar_mouse_action(scr, mouse,
                                                scroll_mouse_x,
                                                scroll_mouse_y));
        } else {
            scroll_mouse_x = x - (box_x + box->padding[LEFT] +
                                  box->width + box->padding[RIGHT] -
                                  SCROLLBAR_WIDTH);
            scroll_mouse_y = y - box_y;
            status = scrollbar_mouse_status_to_message(
                         scrollbar_mouse_action(scr, mouse,
                                                scroll_mouse_x,
                                                scroll_mouse_y));
        }

        msg_data.explicit_status_text = status;
        content_broadcast(c, CONTENT_MSG_STATUS, msg_data);
        return;
    }

    if (html->drag_type == HTML_DRAG_TEXTAREA_SELECTION ||
            html->drag_type == HTML_DRAG_TEXTAREA_SCROLLBAR) {
        box = html->drag_owner.textarea;
        assert(box->gadget != NULL);
        assert(box->gadget->type == GADGET_TEXTAREA ||
               box->gadget->type == GADGET_PASSWORD ||
               box->gadget->type == GADGET_TEXTBOX);

        box_coords(box, &box_x, &box_y);
        textarea_mouse_action(box->gadget->data.text.ta, mouse,
                              x - box_x, y - box_y);

        /* TODO: Set appropriate statusbar message */
        return;
    }

    if (html->drag_type == HTML_DRAG_CONTENT_SELECTION ||
            html->drag_type == HTML_DRAG_CONTENT_SCROLL) {
        box = html->drag_owner.content;
        assert(box->object != NULL);

        box_coords(box, &box_x, &box_y);
        content_mouse_track(box->object, bw, mouse,
                            x - box_x, y - box_y);
        return;
    }

    if (html->drag_type == HTML_DRAG_CONTENT_SELECTION) {
        box = html->drag_owner.content;
        assert(box->object != NULL);

        box_coords(box, &box_x, &box_y);
        content_mouse_track(box->object, bw, mouse,
                            x - box_x, y - box_y);
        return;
    }

    /* Content related drags handled by now */
    assert(html->drag_type == HTML_DRAG_NONE);

    /* search the box tree for a link, imagemap, form control, or
     * box with scrollbars
     */

    box = html->layout;

    /* Consider the margins of the html page now */
    box_x = box->margin[LEFT];
    box_y = box->margin[TOP];

    /* descend through visible boxes setting more specific values for:
     * box - deepest box at point
     * html_object_box - html object
     * html_object_pos_x - html object
     * html_object_pos_y - html object
     * object - non html object
     * iframe - iframe
     * url - href or imagemap
     * target - href or imagemap or gadget
     * url_box - href or imagemap
     * imagemap - imagemap
     * gadget - gadget
     * gadget_box - gadget
     * gadget_box_x - gadget
     * gadget_box_y - gadget
     * title - title
     * pointer
     *
     * drag_candidate - first box with scroll
     * padding_left - box with scroll
     * padding_right
     * padding_top
     * padding_bottom
     * scrollbar - inside padding box stops decent
     * scroll_mouse_x - inside padding box stops decent
     * scroll_mouse_y - inside padding box stops decent
     *
     * text_box - text box
     * text_box_x - text_box
     */
    while ((next_box = box_at_point(box, x, y, &box_x, &box_y)) != NULL) {
        box = next_box;

        if ((box->style != NULL) &&
                (css_computed_visibility(box->style) ==
                 CSS_VISIBILITY_HIDDEN)) {
            continue;
        }

        if (box->node != NULL) {
            node = box->node;
        }

        if (box->object) {
            if (content_get_type(box->object) == CONTENT_HTML) {
                html_object_box = box;
                html_object_pos_x = box_x;
                html_object_pos_y = box_y;
            } else {
                object = box->object;
            }
        }

        if (box->iframe) {
            iframe = box->iframe;
        }

        if (box->href) {
            url = box->href;
            target = box->target;
            url_box = box;
        }

        if (box->usemap) {
            url = imagemap_get(html, box->usemap,
                               box_x, box_y, x, y, &target);
            if (url) {
                imagemap = true;
                url_box = box;
            }
        }

        if (box->gadget) {
            gadget = box->gadget;
            gadget_box = box;
            gadget_box_x = box_x;
            gadget_box_y = box_y;
            if (gadget->form)
                target = gadget->form->target;
        }

        if (box->title) {
            title = box->title;
        }

        pointer = get_pointer_shape(box, false);

        if ((box->scroll_x != NULL) ||
                (box->scroll_y != NULL)) {

            if (drag_candidate == NULL) {
                drag_candidate = box;
            }

            padding_left = box_x +
                           scrollbar_get_offset(box->scroll_x);
            padding_right = padding_left + box->padding[LEFT] +
                            box->width + box->padding[RIGHT];
            padding_top = box_y +
                          scrollbar_get_offset(box->scroll_y);
            padding_bottom = padding_top + box->padding[TOP] +
                             box->height + box->padding[BOTTOM];

            if ((x > padding_left) &&
                    (x < padding_right) &&
                    (y > padding_top) &&
                    (y < padding_bottom)) {
                /* mouse inside padding box */

                if ((box->scroll_y != NULL) &&
                        (x > (padding_right -
                              SCROLLBAR_WIDTH))) {
                    /* mouse above vertical box scroll */

                    scrollbar = box->scroll_y;
                    scroll_mouse_x = x - (padding_right -
                                          SCROLLBAR_WIDTH);
                    scroll_mouse_y = y - padding_top;
                    break;

                } else if ((box->scroll_x != NULL) &&
                           (y > (padding_bottom -
                                 SCROLLBAR_WIDTH))) {
                    /* mouse above horizontal box scroll */

                    scrollbar = box->scroll_x;
                    scroll_mouse_x = x - padding_left;
                    scroll_mouse_y = y - (padding_bottom -
                                          SCROLLBAR_WIDTH);
                    break;
                }
            }
        }

        if (box->text && !box->object) {
            text_box = box;
            text_box_x = box_x;
        }
    }

    /* use of box_x, box_y, or content below this point is probably a
     * mistake; they will refer to the last box returned by box_at_point */

    if (scrollbar) {
        status = scrollbar_mouse_status_to_message(
                     scrollbar_mouse_action(scrollbar, mouse,
                                            scroll_mouse_x,
                                            scroll_mouse_y));
        pointer = BROWSER_POINTER_DEFAULT;
    } else if (gadget) {
        textarea_mouse_status ta_status;

        switch (gadget->type) {
        case GADGET_SELECT:
            status = messages_get("FormSelect");
            pointer = BROWSER_POINTER_MENU;
            if (mouse & BROWSER_MOUSE_CLICK_1 &&
                    nsoption_bool(core_select_menu)) {
                html->visible_select_menu = gadget;
                form_open_select_menu(c, gadget,
                                      form_select_menu_callback,
                                      c);
                pointer = BROWSER_POINTER_DEFAULT;
            } else if (mouse & BROWSER_MOUSE_CLICK_1)
                gui_create_form_select_menu(bw, gadget);
            break;
        case GADGET_CHECKBOX:
            status = messages_get("FormCheckbox");
            if (mouse & BROWSER_MOUSE_CLICK_1) {
                gadget->selected = !gadget->selected;
                html__redraw_a_box(html, gadget_box);
            }
            break;
        case GADGET_RADIO:
            status = messages_get("FormRadio");
            if (mouse & BROWSER_MOUSE_CLICK_1)
                form_radio_set(html, gadget);
            break;
        case GADGET_IMAGE:
            if (mouse & BROWSER_MOUSE_CLICK_1) {
                gadget->data.image.mx = x - gadget_box_x;
                gadget->data.image.my = y - gadget_box_y;
            }
        /* drop through */
        case GADGET_SUBMIT:
            if (gadget->form) {
                snprintf(status_buffer, sizeof status_buffer,
                         messages_get("FormSubmit"),
                         gadget->form->action);
                status = status_buffer;
                pointer = get_pointer_shape(gadget_box, false);
                if (mouse & (BROWSER_MOUSE_CLICK_1 |
                             BROWSER_MOUSE_CLICK_2))
                    action = ACTION_SUBMIT;
            } else {
                status = messages_get("FormBadSubmit");
            }
            break;
        case GADGET_TEXTBOX:
        case GADGET_PASSWORD:
        case GADGET_TEXTAREA:
            if (gadget->type == GADGET_TEXTAREA)
                status = messages_get("FormTextarea");
            else
                status = messages_get("FormTextbox");

            if (click && (html->selection_type !=
                          HTML_SELECTION_TEXTAREA ||
                          html->selection_owner.textarea !=
                          gadget_box)) {
                sel_owner.none = true;
                html_set_selection(html, HTML_SELECTION_NONE,
                                   sel_owner, true);
            }

            ta_status = textarea_mouse_action(gadget->data.text.ta,
                                              mouse, x - gadget_box_x,
                                              y - gadget_box_y);

            if (ta_status & TEXTAREA_MOUSE_EDITOR) {
                pointer = get_pointer_shape(gadget_box, false);
            } else {
                pointer = BROWSER_POINTER_DEFAULT;
                status = scrollbar_mouse_status_to_message(
                             ta_status >> 3);
            }
            break;
        case GADGET_HIDDEN:
            /* not possible: no box generated */
            break;
        case GADGET_RESET:
            status = messages_get("FormReset");
            break;
        case GADGET_FILE:
            status = messages_get("FormFile");
            break;
        case GADGET_BUTTON:
            /* This gadget cannot be activated */
            status = messages_get("FormButton");
            break;
        }

    } else if (object && (mouse & BROWSER_MOUSE_MOD_2)) {
예제 #19
0
void html_mouse_action(struct content *c, struct browser_window *bw,
		browser_mouse_state mouse, int x, int y)
{
	html_content *html = (html_content *) c;
	enum { ACTION_NONE, ACTION_SUBMIT, ACTION_GO } action = ACTION_NONE;
	const char *title = 0;
	nsurl *url = 0;
	const char *target = 0;
	char status_buffer[200];
	const char *status = 0;
	browser_pointer_shape pointer = BROWSER_POINTER_DEFAULT;
	bool imagemap = false;
	int box_x = 0, box_y = 0;
	int gadget_box_x = 0, gadget_box_y = 0;
	int html_object_pos_x = 0, html_object_pos_y = 0;
	int text_box_x = 0;
	struct box *url_box = 0;
	struct box *gadget_box = 0;
	struct box *text_box = 0;
	struct box *box;
	struct form_control *gadget = 0;
	hlcache_handle *object = NULL;
	struct box *html_object_box = NULL;
	struct browser_window *iframe = NULL;
	struct box *next_box;
	struct box *drag_candidate = NULL;
	struct scrollbar *scrollbar = NULL;
	plot_font_style_t fstyle;
	int scroll_mouse_x = 0, scroll_mouse_y = 0;
	int padding_left, padding_right, padding_top, padding_bottom;
	browser_drag_type drag_type = browser_window_get_drag_type(bw);
	union content_msg_data msg_data;
	struct dom_node *node = NULL;

	if (drag_type != DRAGGING_NONE && !mouse &&
			html->visible_select_menu != NULL) {
		/* drag end: select menu */
		form_select_mouse_drag_end(html->visible_select_menu,
				mouse, x, y);
	}

	if (html->visible_select_menu != NULL) {
		box = html->visible_select_menu->box;
		box_coords(box, &box_x, &box_y);

		box_x -= box->border[LEFT].width;
		box_y += box->height + box->border[BOTTOM].width +
				box->padding[BOTTOM] + box->padding[TOP];
		status = form_select_mouse_action(html->visible_select_menu,
				mouse, x - box_x, y - box_y);
		if (status != NULL) {
			msg_data.explicit_status_text = status;
			content_broadcast(c, CONTENT_MSG_STATUS, msg_data);
		} else {
			int width, height;
			form_select_get_dimensions(html->visible_select_menu,
					&width, &height);
			html->visible_select_menu = NULL;
			browser_window_redraw_rect(bw, box_x, box_y,
					width, height);					
		}
		return;
	}

	if (!mouse && html->scrollbar != NULL) {
		/* drag end: scrollbar */
		html_overflow_scroll_drag_end(html->scrollbar, mouse, x, y);
	}

	if (html->scrollbar != NULL) {
		struct html_scrollbar_data *data =
				scrollbar_get_data(html->scrollbar);
		box = data->box;
		box_coords(box, &box_x, &box_y);
		if (scrollbar_is_horizontal(html->scrollbar)) {
			scroll_mouse_x = x - box_x ;
			scroll_mouse_y = y - (box_y + box->padding[TOP] +
					box->height + box->padding[BOTTOM] -
					SCROLLBAR_WIDTH);
			status = scrollbar_mouse_action(html->scrollbar, mouse,
					scroll_mouse_x, scroll_mouse_y);
		} else {
			scroll_mouse_x = x - (box_x + box->padding[LEFT] +
					box->width + box->padding[RIGHT] -
					SCROLLBAR_WIDTH);
			scroll_mouse_y = y - box_y;
			status = scrollbar_mouse_action(html->scrollbar, mouse, 
					scroll_mouse_x, scroll_mouse_y);
		}

		msg_data.explicit_status_text = status;
		content_broadcast(c, CONTENT_MSG_STATUS, msg_data);
		return;
	}

	/* Content related drags handled by now */
	browser_window_set_drag_type(bw, DRAGGING_NONE, NULL);

	/* search the box tree for a link, imagemap, form control, or
	 * box with scrollbars 
	 */

	box = html->layout;

	/* Consider the margins of the html page now */
	box_x = box->margin[LEFT];
	box_y = box->margin[TOP];

	/* descend through visible boxes setting more specific values for:
	 * box - deepest box at point 
	 * html_object_box - html object
	 * html_object_pos_x - html object
	 * html_object_pos_y - html object
	 * object - non html object
	 * iframe - iframe
	 * url - href or imagemap
	 * target - href or imagemap or gadget
	 * url_box - href or imagemap
	 * imagemap - imagemap
	 * gadget - gadget
	 * gadget_box - gadget
	 * gadget_box_x - gadget
	 * gadget_box_y - gadget
	 * title - title
	 * pointer
	 *
	 * drag_candidate - first box with scroll
	 * padding_left - box with scroll
	 * padding_right
	 * padding_top
	 * padding_bottom
	 * scrollbar - inside padding box stops decent
	 * scroll_mouse_x - inside padding box stops decent
	 * scroll_mouse_y - inside padding box stops decent
	 * 
	 * text_box - text box
	 * text_box_x - text_box
	 */
	while ((next_box = box_at_point(box, x, y, &box_x, &box_y)) != NULL) {
		box = next_box;

		if ((box->style != NULL) && 
		    (css_computed_visibility(box->style) == 
		     CSS_VISIBILITY_HIDDEN)) {
			continue;
		}

		if (box->node != NULL) {
			node = box->node;
		}

		if (box->object) {
			if (content_get_type(box->object) == CONTENT_HTML) {
				html_object_box = box;
				html_object_pos_x = box_x;
				html_object_pos_y = box_y;
			} else {
				object = box->object;
			}
		}

		if (box->iframe) {
			iframe = box->iframe;
		}

		if (box->href) {
			url = box->href;
			target = box->target;
			url_box = box;
		}

		if (box->usemap) {
			url = imagemap_get(html, box->usemap,
					box_x, box_y, x, y, &target);
			if (url) {
				imagemap = true;
				url_box = box;
			}
		}

		if (box->gadget) {
			gadget = box->gadget;
			gadget_box = box;
			gadget_box_x = box_x;
			gadget_box_y = box_y;
			if (gadget->form)
				target = gadget->form->target;
		}

		if (box->title) {
			title = box->title;
		}

		pointer = get_pointer_shape(box, false);
		
		if ((box->scroll_x != NULL) || 
		    (box->scroll_y != NULL)) {

			if (drag_candidate == NULL) {
				drag_candidate = box;
			}

			padding_left = box_x +
					scrollbar_get_offset(box->scroll_x);
			padding_right = padding_left + box->padding[LEFT] +
					box->width + box->padding[RIGHT];
			padding_top = box_y +
					scrollbar_get_offset(box->scroll_y);
			padding_bottom = padding_top + box->padding[TOP] +
					box->height + box->padding[BOTTOM];
			
			if ((x > padding_left) && 
			    (x < padding_right) &&
			    (y > padding_top) && 
			    (y < padding_bottom)) {
				/* mouse inside padding box */
				
				if ((box->scroll_y != NULL) && 
				    (x > (padding_right - SCROLLBAR_WIDTH))) {
					/* mouse above vertical box scroll */
					
					scrollbar = box->scroll_y;
					scroll_mouse_x = x - (padding_right -
							     SCROLLBAR_WIDTH);
					scroll_mouse_y = y - padding_top;
					break;
				
				} else if ((box->scroll_x != NULL) &&
					   (y > (padding_bottom - SCROLLBAR_WIDTH))) {
					/* mouse above horizontal box scroll */
							
					scrollbar = box->scroll_x;
					scroll_mouse_x = x - padding_left;
					scroll_mouse_y = y - (padding_bottom -
							SCROLLBAR_WIDTH);
					break;
				}
			}
		}

		if (box->text && !box->object) {
			text_box = box;
			text_box_x = box_x;
		}
	}

	/* use of box_x, box_y, or content below this point is probably a
	 * mistake; they will refer to the last box returned by box_at_point */

	if (scrollbar) {
		status = scrollbar_mouse_action(scrollbar, mouse,
				scroll_mouse_x, scroll_mouse_y);
		pointer = BROWSER_POINTER_DEFAULT;
	} else if (gadget) {
		switch (gadget->type) {
		case GADGET_SELECT:
			status = messages_get("FormSelect");
			pointer = BROWSER_POINTER_MENU;
			if (mouse & BROWSER_MOUSE_CLICK_1 &&
			    nsoption_bool(core_select_menu)) {
				html->visible_select_menu = gadget;
				form_open_select_menu(c, gadget,
						form_select_menu_callback,
						c);
				pointer =  BROWSER_POINTER_DEFAULT;
			} else if (mouse & BROWSER_MOUSE_CLICK_1)
				gui_create_form_select_menu(bw, gadget);
			break;
		case GADGET_CHECKBOX:
			status = messages_get("FormCheckbox");
			if (mouse & BROWSER_MOUSE_CLICK_1) {
				gadget->selected = !gadget->selected;
				html__redraw_a_box(html, gadget_box);
			}
			break;
		case GADGET_RADIO:
			status = messages_get("FormRadio");
			if (mouse & BROWSER_MOUSE_CLICK_1)
				form_radio_set(html, gadget);
			break;
		case GADGET_IMAGE:
			if (mouse & BROWSER_MOUSE_CLICK_1) {
				gadget->data.image.mx = x - gadget_box_x;
				gadget->data.image.my = y - gadget_box_y;
			}
			/* drop through */
		case GADGET_SUBMIT:
			if (gadget->form) {
				snprintf(status_buffer, sizeof status_buffer,
						messages_get("FormSubmit"),
						gadget->form->action);
				status = status_buffer;
				pointer = get_pointer_shape(gadget_box, false);
				if (mouse & (BROWSER_MOUSE_CLICK_1 |
						BROWSER_MOUSE_CLICK_2))
					action = ACTION_SUBMIT;
			} else {
				status = messages_get("FormBadSubmit");
			}
			break;
		case GADGET_TEXTAREA:
			status = messages_get("FormTextarea");
			pointer = get_pointer_shape(gadget_box, false);

			if (mouse & (BROWSER_MOUSE_PRESS_1 |
					BROWSER_MOUSE_PRESS_2)) {
				if (text_box && selection_root(&html->sel) !=
						gadget_box)
					selection_init(&html->sel, gadget_box);

				textinput_textarea_click(c, mouse,
						gadget_box,
						gadget_box_x,
						gadget_box_y,
						x - gadget_box_x,
						y - gadget_box_y);
			}

			if (text_box) {
				int pixel_offset;
				size_t idx;

				font_plot_style_from_css(text_box->style, 
						&fstyle);

				nsfont.font_position_in_string(&fstyle,
					text_box->text,
					text_box->length,
					x - gadget_box_x - text_box->x,
					&idx,
					&pixel_offset);

				selection_click(&html->sel, mouse,
						text_box->byte_offset + idx);

				if (selection_dragging(&html->sel)) {
					browser_window_set_drag_type(bw,
							DRAGGING_SELECTION,
							NULL);
					status = messages_get("Selecting");
				}
			}
			else if (mouse & BROWSER_MOUSE_PRESS_1)
				selection_clear(&html->sel, true);
			break;
		case GADGET_TEXTBOX:
		case GADGET_PASSWORD:
			status = messages_get("FormTextbox");
			pointer = get_pointer_shape(gadget_box, false);

			if ((mouse & BROWSER_MOUSE_PRESS_1) &&
					!(mouse & (BROWSER_MOUSE_MOD_1 |
					BROWSER_MOUSE_MOD_2))) {
				textinput_input_click(c,
						gadget_box,
						gadget_box_x,
						gadget_box_y,
						x - gadget_box_x,
						y - gadget_box_y);
			}
			if (text_box) {
				int pixel_offset;
				size_t idx;

				if (mouse & (BROWSER_MOUSE_DRAG_1 |
						BROWSER_MOUSE_DRAG_2))
					selection_init(&html->sel, gadget_box);

				font_plot_style_from_css(text_box->style,
						&fstyle);

				nsfont.font_position_in_string(&fstyle,
					text_box->text,
					text_box->length,
					x - gadget_box_x - text_box->x,
					&idx,
					&pixel_offset);

				selection_click(&html->sel, mouse,
						text_box->byte_offset + idx);

				if (selection_dragging(&html->sel))
					browser_window_set_drag_type(bw,
							DRAGGING_SELECTION,
							NULL);
			}
			else if (mouse & BROWSER_MOUSE_PRESS_1)
				selection_clear(&html->sel, true);
			break;
		case GADGET_HIDDEN:
			/* not possible: no box generated */
			break;
		case GADGET_RESET:
			status = messages_get("FormReset");
			break;
		case GADGET_FILE:
			status = messages_get("FormFile");
			break;
		case GADGET_BUTTON:
			/* This gadget cannot be activated */
			status = messages_get("FormButton");
			break;
		}

	} else if (object && (mouse & BROWSER_MOUSE_MOD_2)) {

		if (mouse & BROWSER_MOUSE_DRAG_2) {
			msg_data.dragsave.type = CONTENT_SAVE_NATIVE;
			msg_data.dragsave.content = object;
			content_broadcast(c, CONTENT_MSG_DRAGSAVE, msg_data);

		} else if (mouse & BROWSER_MOUSE_DRAG_1) {
			msg_data.dragsave.type = CONTENT_SAVE_ORIG;
			msg_data.dragsave.content = object;
			content_broadcast(c, CONTENT_MSG_DRAGSAVE, msg_data);
		}

		/* \todo should have a drag-saving object msg */

	} else if (iframe) {
		int pos_x, pos_y;
		float scale = browser_window_get_scale(bw);

		browser_window_get_position(iframe, false, &pos_x, &pos_y);

		pos_x /= scale;
		pos_y /= scale;

		if (mouse & BROWSER_MOUSE_CLICK_1 ||
				mouse & BROWSER_MOUSE_CLICK_2) {
			browser_window_mouse_click(iframe, mouse,
					x - pos_x, y - pos_y);
		} else {
			browser_window_mouse_track(iframe, mouse,
					x - pos_x, y - pos_y);
		}
	} else if (html_object_box) {
		if (mouse & BROWSER_MOUSE_CLICK_1 ||
				mouse & BROWSER_MOUSE_CLICK_2) {
			content_mouse_action(html_object_box->object,
					bw, mouse,
					x - html_object_pos_x,
					y - html_object_pos_y);
		} else {
			content_mouse_track(html_object_box->object,
					bw, mouse,
					x - html_object_pos_x,
					y - html_object_pos_y);
		}
	} else if (url) {
		if (title) {
			snprintf(status_buffer, sizeof status_buffer, "%s: %s",
					nsurl_access(url), title);
			status = status_buffer;
		} else
			status = nsurl_access(url);

		pointer = get_pointer_shape(url_box, imagemap);

		if (mouse & BROWSER_MOUSE_CLICK_1 &&
				mouse & BROWSER_MOUSE_MOD_1) {
			/* force download of link */
			browser_window_go_post(bw, nsurl_access(url), 0, 0,
					false,
					nsurl_access(content_get_url(c)),
					true, true, 0);

		} else if (mouse & BROWSER_MOUSE_CLICK_2 &&
				mouse & BROWSER_MOUSE_MOD_1) {
			msg_data.savelink.url = nsurl_access(url);
			msg_data.savelink.title = title;
			content_broadcast(c, CONTENT_MSG_SAVELINK, msg_data);

		} else if (mouse & (BROWSER_MOUSE_CLICK_1 |
				BROWSER_MOUSE_CLICK_2))
			action = ACTION_GO;
	} else {
		bool done = false;

		/* frame resizing */
		if (browser_window_frame_resize_start(bw, mouse, x, y,
				&pointer)) {
			if (mouse & (BROWSER_MOUSE_DRAG_1 |
					BROWSER_MOUSE_DRAG_2)) {
				status = messages_get("FrameDrag");
			}
			done = true;
		}

		/* if clicking in the main page, remove the selection from any
		 * text areas */
		if (!done) {
			struct box *layout = html->layout;

			if (mouse && (mouse < BROWSER_MOUSE_MOD_1) &&
					selection_root(&html->sel) != layout) {
				selection_init(&html->sel, layout);
			}

			if (text_box) {
				int pixel_offset;
				size_t idx;

				font_plot_style_from_css(text_box->style,
						&fstyle);

				nsfont.font_position_in_string(&fstyle,
					text_box->text,
					text_box->length,
					x - text_box_x,
					&idx,
					&pixel_offset);

				if (selection_click(&html->sel, mouse,
						text_box->byte_offset + idx)) {
					/* key presses must be directed at the
					 * main browser window, paste text
					 * operations ignored */

					if (selection_dragging(&html->sel)) {
						browser_window_set_drag_type(bw,
							DRAGGING_SELECTION,
							NULL);
						status = messages_get(
								"Selecting");
					}

					done = true;
				}

			} else if (mouse & BROWSER_MOUSE_PRESS_1)
				selection_clear(&html->sel, true);
		}

		if (!done) {
			if (title)
				status = title;

			if (mouse & BROWSER_MOUSE_DRAG_1) {
				if (mouse & BROWSER_MOUSE_MOD_2) {
					msg_data.dragsave.type =
							CONTENT_SAVE_COMPLETE;
					msg_data.dragsave.content = NULL;
					content_broadcast(c,
							CONTENT_MSG_DRAGSAVE,
							msg_data);
				} else {
					if (drag_candidate == NULL) {
						browser_window_page_drag_start(
								bw, x, y);
					} else {
						html_box_drag_start(
								drag_candidate,
								x, y);
					}
					pointer = BROWSER_POINTER_MOVE;
				}
			}
			else if (mouse & BROWSER_MOUSE_DRAG_2) {
				if (mouse & BROWSER_MOUSE_MOD_2) {
					msg_data.dragsave.type =
							CONTENT_SAVE_SOURCE;
					msg_data.dragsave.content = NULL;
					content_broadcast(c,
							CONTENT_MSG_DRAGSAVE,
							msg_data);
				} else {
					if (drag_candidate == NULL) {
						browser_window_page_drag_start(
								bw, x, y);
					} else {
						html_box_drag_start(
								drag_candidate,
								x, y);
					}
					pointer = BROWSER_POINTER_MOVE;
				}
			}
		}
		if (mouse && mouse < BROWSER_MOUSE_MOD_1) {
			/* ensure key presses still act on the browser window */
			browser_window_remove_caret(bw);
		}
	}

	if (!iframe && !html_object_box) {
		msg_data.explicit_status_text = status;
		content_broadcast(c, CONTENT_MSG_STATUS, msg_data);

		msg_data.pointer = pointer;
		content_broadcast(c, CONTENT_MSG_POINTER, msg_data);
	}

	/* fire dom click event */
	if ((mouse & BROWSER_MOUSE_CLICK_1) ||
	    (mouse & BROWSER_MOUSE_CLICK_2)) {
		js_fire_event(html->jscontext, "click", html->document, node);
	}

	/* deferred actions that can cause this browser_window to be destroyed
	 * and must therefore be done after set_status/pointer
	 */
	switch (action) {
	case ACTION_SUBMIT:
		form_submit(content_get_url(c),
				browser_window_find_target(bw, target, mouse),
				gadget->form, gadget);
		break;
	case ACTION_GO:
		browser_window_go(browser_window_find_target(bw, target, mouse),
				nsurl_access(url),
				nsurl_access(content_get_url(c)), true);
		break;
	case ACTION_NONE:
		break;
	}
}
예제 #20
0
void ro_gui_save_drag_end(wimp_dragged *drag)
{
	const char *name;
	wimp_pointer pointer;
	wimp_message message;
	os_error *error;
	char *dp, *ep;
	char *local_name = NULL;
	utf8_convert_ret err;

	if (dragbox_active)
		ro_gui_drag_box_cancel();

	error = xwimp_get_pointer_info(&pointer);
	if (error) {
		LOG(("xwimp_get_pointer_info: 0x%x: %s",
				error->errnum, error->errmess));
		warn_user("WimpError", error->errmess);
		return;
	}

	/* perform hit-test if the destination is the same as the source window;
		we want to allow drag-saving from a page into the input fields within
		the page, but avoid accidental replacements of the current page */
	if (gui_save_sourcew != (wimp_w)-1 && pointer.w == gui_save_sourcew) {
		int dx = (drag->final.x1 + drag->final.x0)/2;
		int dy = (drag->final.y1 + drag->final.y0)/2;
		struct gui_window *g;
		bool dest_ok = false;
		os_coord pos;

		g = ro_gui_window_lookup(gui_save_sourcew);

		if (g && ro_gui_window_to_window_pos(g, dx, dy, &pos)) {
			hlcache_handle *h = g->bw->current_content;

			if (h && content_get_type(h) == CONTENT_HTML) {
				struct box *box = html_get_box_tree(h);
				int box_x, box_y;

				/* Consider the margins of the html page now */
				box_x = box->margin[LEFT];
				box_y = box->margin[TOP];

				while (!dest_ok && (box = box_at_point(box,
						pos.x, pos.y, &box_x, &box_y,
						&h))) {
					if (box->style && 
							css_computed_visibility(
								box->style) == 
							CSS_VISIBILITY_HIDDEN)
						continue;

					if (box->gadget) {
						switch (box->gadget->type) {
							case GADGET_FILE:
							case GADGET_TEXTBOX:
							case GADGET_TEXTAREA:
							case GADGET_PASSWORD:
								dest_ok = true;
								break;

							default:	/* appease compiler */
								break;
						}
					}
				}
			}
		}
		if (!dest_ok) {
			/* cancel the drag operation */
			gui_current_drag_type = GUI_DRAG_NONE;
			return;
		}
	}
예제 #21
0
파일: frames.c 프로젝트: ysei/NetSurf
void browser_window_create_frameset(struct browser_window *bw,
		struct content_html_frames *frameset)
{
	int row, col, index;
	struct content_html_frames *frame;
	struct browser_window *window;
	hlcache_handle *parent;

	assert(bw && frameset);

	/* 1. Create children */
	assert(bw->children == NULL);
	assert(frameset->cols + frameset->rows != 0);

	bw->children = calloc((frameset->cols * frameset->rows), sizeof(*bw));
	if (!bw->children)
		return;
	bw->cols = frameset->cols;
	bw->rows = frameset->rows;
	for (row = 0; row < bw->rows; row++) {
		for (col = 0; col < bw->cols; col++) {
			index = (row * bw->cols) + col;
			frame = &frameset->children[index];
			window = &bw->children[index];

			/* Initialise common parts */
			browser_window_initialise_common(BW_CREATE_NONE,
					window, NULL);

			/* window characteristics */
			if (frame->children)
				window->browser_window_type =
						BROWSER_WINDOW_FRAMESET;
			else
				window->browser_window_type =
						BROWSER_WINDOW_FRAME;
			window->scrolling = frame->scrolling;
			window->border = frame->border;
			window->border_colour = frame->border_colour;
			window->no_resize = frame->no_resize;
			window->frame_width = frame->width;
			window->frame_height = frame->height;
			window->margin_width = frame->margin_width;
			window->margin_height = frame->margin_height;
			if (frame->name) {
				window->name = strdup(frame->name);
				if (!window->name)
					warn_user("NoMemory", 0);
			}

			window->scale = bw->scale;

			/* linking */
			window->parent = bw;

			if (window->name)
				LOG(("Created frame '%s'", window->name));
			else
				LOG(("Created frame (unnamed)"));
		}
	}

	/* 2. Calculate dimensions */
	browser_window_update_extent(bw);
	browser_window_recalculate_frameset(bw);

	/* 3. Recurse for grandchildren */
	for (row = 0; row < bw->rows; row++) {
		for (col = 0; col < bw->cols; col++) {
			index = (row * bw->cols) + col;
			frame = &frameset->children[index];
			window = &bw->children[index];

			if (frame->children)
				browser_window_create_frameset(window, frame);
		}
	}

	/* Use the URL of the first ancestor window containing html content
	 * as the referer */
	for (window = bw; window->parent; window = window->parent) {
		if (window->current_content && 
				content_get_type(window->current_content) == 
				CONTENT_HTML)
			break;
	}

	parent = window->current_content;

	/* 4. Launch content */
	for (row = 0; row < bw->rows; row++) {
		for (col = 0; col < bw->cols; col++) {
			index = (row * bw->cols) + col;
			frame = &frameset->children[index];
			window = &bw->children[index];

			if (frame->url) {
				browser_window_navigate(window,
					frame->url,
					hlcache_handle_get_url(parent),
					BW_NAVIGATE_HISTORY |
					BW_NAVIGATE_UNVERIFIABLE,
					NULL,
					NULL,
					parent);
			}
		}
	}
}
예제 #22
0
/**
 * Callback for (i)frame scrollbars.
 */
void browser_window_scroll_callback(void *client_data,
		struct scrollbar_msg_data *scrollbar_data)
{
	struct browser_window *bw = client_data;

	switch(scrollbar_data->msg) {
	case SCROLLBAR_MSG_MOVED:
		if (bw->browser_window_type == BROWSER_WINDOW_IFRAME) {
			html_redraw_a_box(bw->parent->current_content, bw->box);
		} else {
			struct rect rect;

			rect.x0 = scrollbar_get_offset(bw->scroll_x);
			rect.y0 = scrollbar_get_offset(bw->scroll_y);
			rect.x1 = rect.x0 + bw->width;
			rect.y1 = rect.y0 + bw->height;

			browser_window_update_box(bw, &rect);
		}
		break;
	case SCROLLBAR_MSG_SCROLL_START:
	{
		struct rect rect = {
			.x0 = scrollbar_data->x0,
			.y0 = scrollbar_data->y0,
			.x1 = scrollbar_data->x1,
			.y1 = scrollbar_data->y1
		};

		if (scrollbar_is_horizontal(scrollbar_data->scrollbar))
			browser_window_set_drag_type(bw, DRAGGING_SCR_X, &rect);
		else
			browser_window_set_drag_type(bw, DRAGGING_SCR_Y, &rect);
	}
		break;
	case SCROLLBAR_MSG_SCROLL_FINISHED:
		browser_window_set_drag_type(bw, DRAGGING_NONE, NULL);

		browser_window_set_pointer(bw, BROWSER_POINTER_DEFAULT);
		break;
	}
}

/* exported interface, documented in browser.h */
void browser_window_handle_scrollbars(struct browser_window *bw)
{
	struct hlcache_handle *h = bw->current_content;
	bool scroll_x;
	bool scroll_y;
	int c_width = 0;
	int c_height = 0;

	assert(!bw->window); /* Core-handled windows only */

	if (h != NULL) {
		c_width  = content_get_width(h);
		c_height = content_get_height(h);
	}

	if (bw->scrolling == BW_SCROLLING_YES) {
		scroll_x = true;
		scroll_y = true;
	} else if (bw->scrolling == BW_SCROLLING_AUTO &&
			bw->current_content) {
		int bw_width = bw->width;
		int bw_height = bw->height;

		/* subtract existing scrollbar width */
		bw_width -= bw->scroll_y ? SCROLLBAR_WIDTH : 0;
		bw_height -= bw->scroll_x ? SCROLLBAR_WIDTH : 0;

		scroll_y = (c_height > bw_height) ? true : false;
		scroll_x = (c_width > bw_width) ? true : false;
	} else {
		/* No scrollbars */
		scroll_x = false;
		scroll_y = false;
	}

	if (!scroll_x && bw->scroll_x != NULL) {
		scrollbar_destroy(bw->scroll_x);
		bw->scroll_x = NULL;
	}

	if (!scroll_y && bw->scroll_y != NULL) {
		scrollbar_destroy(bw->scroll_y);
		bw->scroll_y = NULL;
	}

	if (scroll_y) {
		int length = bw->height;
		int visible = bw->height - (scroll_x ? SCROLLBAR_WIDTH : 0);

		if (bw->scroll_y == NULL) {
			/* create vertical scrollbar */
			if (scrollbar_create(false, length, c_height, visible,
					     bw, browser_window_scroll_callback,
					     &(bw->scroll_y)) != NSERROR_OK) {
				return;
			}
		} else {
			/* update vertical scrollbar */
			scrollbar_set_extents(bw->scroll_y, length,
					visible, c_height);
		}
	}

	if (scroll_x) {
		int length = bw->width - (scroll_y ? SCROLLBAR_WIDTH : 0);
		int visible = length;

		if (bw->scroll_x == NULL) {
			/* create horizontal scrollbar */
			if (scrollbar_create(true, length, c_width, visible,
					     bw, browser_window_scroll_callback,
					     &(bw->scroll_x)) != NSERROR_OK) {
				return;
			}
		} else {
			/* update horizontal scrollbar */
			scrollbar_set_extents(bw->scroll_x, length,
					visible, c_width);
		}
	}

	if (scroll_x && scroll_y)
		scrollbar_make_pair(bw->scroll_x, bw->scroll_y);
}


/* exported function documented in desktop/frames.h */
nserror browser_window_create_iframes(struct browser_window *bw,
		struct content_html_iframe *iframe)
{
	struct browser_window *window;
	struct content_html_iframe *cur;
	struct rect rect;
	int iframes = 0;
	int index;
	nserror ret = NSERROR_OK;

	if (iframe == NULL) {
		return NSERROR_BAD_PARAMETER;
	}

	/* Count iframe list and allocate enough space within the
	 * browser window.
	 */
	for (cur = iframe; cur; cur = cur->next) {
		iframes++;
	}
	bw->iframes = calloc(iframes, sizeof(*bw));
	if (!bw->iframes) {
		return NSERROR_NOMEM;
	}
	bw->iframe_count = iframes;

	index = 0;
	for (cur = iframe; cur; cur = cur->next) {
		window = &(bw->iframes[index++]);

		/* Initialise common parts */
		browser_window_initialise_common(BW_CREATE_NONE,
				window, NULL);

		/* window characteristics */
		window->browser_window_type = BROWSER_WINDOW_IFRAME;
		window->scrolling = cur->scrolling;
		window->border = cur->border;
		window->border_colour = cur->border_colour;
		window->no_resize = true;
		window->margin_width = cur->margin_width;
		window->margin_height = cur->margin_height;
		window->scale = bw->scale;
		if (cur->name != NULL) {
			window->name = strdup(cur->name);
			if (window->name == NULL) {
				free(bw->iframes) ;
				bw->iframes = 0;
				bw->iframe_count = 0;
				return NSERROR_NOMEM;
			}
		}

		/* linking */
		window->box = cur->box;
		window->parent = bw;
		window->box->iframe = window;

		/* iframe dimensions */
		box_bounds(window->box, &rect);

		browser_window_set_position(window, rect.x0, rect.y0);
		browser_window_set_dimensions(window, rect.x1 - rect.x0,
				rect.y1 - rect.y0);
	}

	/* calculate dimensions */
	browser_window_update_extent(bw);
	browser_window_recalculate_iframes(bw);

	index = 0;
	for (cur = iframe; cur; cur = cur->next) {
		window = &(bw->iframes[index++]);
		if (cur->url) {
			/* fetch iframe's content */
			ret = browser_window_navigate(window,
				cur->url,
				hlcache_handle_get_url(bw->current_content),
				BW_NAVIGATE_UNVERIFIABLE,
				NULL,
				NULL,
				bw->current_content);
		}
	}

	return ret;
}


/**
 * Recalculate iframe positions following a resize.
 *
 * \param  bw	    The browser window to reposition iframes for
 */

void browser_window_recalculate_iframes(struct browser_window *bw)
{
	struct browser_window *window;
	int index;

	for (index = 0; index < bw->iframe_count; index++) {
		window = &(bw->iframes[index]);

		if (window != NULL) {
			browser_window_handle_scrollbars(window);
		}
	}
}


/* exported interface documented in desktop/frames.h */
nserror browser_window_create_frameset(struct browser_window *bw,
		struct content_html_frames *frameset)
{
	int row, col, index;
	struct content_html_frames *frame;
	struct browser_window *window;
	hlcache_handle *parent;

	assert(bw && frameset);

	/* 1. Create children */
	assert(bw->children == NULL);
	assert(frameset->cols + frameset->rows != 0);

	bw->children = calloc((frameset->cols * frameset->rows), sizeof(*bw));
	if (!bw->children) {
		return NSERROR_NOMEM;
	}

	bw->cols = frameset->cols;
	bw->rows = frameset->rows;
	for (row = 0; row < bw->rows; row++) {
		for (col = 0; col < bw->cols; col++) {
			index = (row * bw->cols) + col;
			frame = &frameset->children[index];
			window = &bw->children[index];

			/* Initialise common parts */
			browser_window_initialise_common(BW_CREATE_NONE,
					window, NULL);

			/* window characteristics */
			if (frame->children)
				window->browser_window_type =
						BROWSER_WINDOW_FRAMESET;
			else
				window->browser_window_type =
						BROWSER_WINDOW_FRAME;
			window->scrolling = frame->scrolling;
			window->border = frame->border;
			window->border_colour = frame->border_colour;
			window->no_resize = frame->no_resize;
			window->frame_width = frame->width;
			window->frame_height = frame->height;
			window->margin_width = frame->margin_width;
			window->margin_height = frame->margin_height;
			if (frame->name) {
				window->name = strdup(frame->name);
				if (!window->name) {
					free(bw->children);
					bw->children = NULL;
					return NSERROR_NOMEM;
				}
			}

			window->scale = bw->scale;

			/* linking */
			window->parent = bw;

			if (window->name)
				LOG("Created frame '%s'", window->name);
			else
				LOG("Created frame (unnamed)");
		}
	}

	/* 2. Calculate dimensions */
	browser_window_update_extent(bw);
	browser_window_recalculate_frameset(bw);

	/* 3. Recurse for grandchildren */
	for (row = 0; row < bw->rows; row++) {
		for (col = 0; col < bw->cols; col++) {
			index = (row * bw->cols) + col;
			frame = &frameset->children[index];
			window = &bw->children[index];

			if (frame->children)
				browser_window_create_frameset(window, frame);
		}
	}

	/* Use the URL of the first ancestor window containing html content
	 * as the referer */
	for (window = bw; window->parent; window = window->parent) {
		if (window->current_content &&
				content_get_type(window->current_content) ==
				CONTENT_HTML)
			break;
	}

	parent = window->current_content;

	/* 4. Launch content */
	for (row = 0; row < bw->rows; row++) {
		for (col = 0; col < bw->cols; col++) {
			index = (row * bw->cols) + col;
			frame = &frameset->children[index];
			window = &bw->children[index];

			if (frame->url) {
				browser_window_navigate(window,
					frame->url,
					hlcache_handle_get_url(parent),
					BW_NAVIGATE_HISTORY |
					BW_NAVIGATE_UNVERIFIABLE,
					NULL,
					NULL,
					parent);
			}
		}
	}

	return NSERROR_OK;
}
예제 #23
0
/**
 * Callback for syncronous scripts
 */
static nserror
convert_script_sync_cb(hlcache_handle *script,
			  const hlcache_event *event,
			  void *pw)
{
	html_content *parent = pw;
	unsigned int i;
	struct html_script *s;
	script_handler_t *script_handler;
	dom_hubbub_error err;

	/* Find script */
	for (i = 0, s = parent->scripts; i != parent->scripts_count; i++, s++) {
		if (s->type == HTML_SCRIPT_SYNC && s->data.handle == script)
			break;
	}

	assert(i != parent->scripts_count);

	switch (event->type) {
	case CONTENT_MSG_LOADING:
		break;

	case CONTENT_MSG_READY:
		break;

	case CONTENT_MSG_DONE:
		LOG(("script %d done '%s'", i,
				nsurl_access(hlcache_handle_get_url(script))));
		parent->base.active--;
		LOG(("%d fetches active", parent->base.active));

		s->already_started = true;

		/* attempt to execute script */
		script_handler = select_script_handler(content_get_type(s->data.handle));
		if (script_handler != NULL) {
			/* script has a handler */
			const char *data;
			unsigned long size;
			data = content_get_source_data(s->data.handle, &size );
			script_handler(parent->jscontext, data, size);
		}

		/* continue parse */
		err = dom_hubbub_parser_pause(parent->parser, false);
		if (err != DOM_HUBBUB_OK) {
			LOG(("unpause returned 0x%x", err));
		} 

		break;

	case CONTENT_MSG_ERROR:
		LOG(("script %s failed: %s",
				nsurl_access(hlcache_handle_get_url(script)),
				event->data.error));

		hlcache_handle_release(script);
		s->data.handle = NULL;
		parent->base.active--;

		LOG(("%d fetches active", parent->base.active));
		content_add_error(&parent->base, "?", 0);

		s->already_started = true;

		/* continue parse */
		err = dom_hubbub_parser_pause(parent->parser, false);
		if (err != DOM_HUBBUB_OK) {
			LOG(("unpause returned 0x%x", err));
		} 

		break;

	case CONTENT_MSG_STATUS:
		break;

	default:
		assert(0);
	}

	/* if there are no active fetches remaining begin post parse
	 * conversion
	 */
	if (html_can_begin_conversion(parent)) {
		html_begin_conversion(parent);
	}

	return NSERROR_OK;
}
예제 #24
0
nserror favicon_callback(hlcache_handle *icon,
		const hlcache_event *event, void *pw)
{
	struct content *c = pw;

	switch (event->type) {
	case CONTENT_MSG_LOADING:
		/* check that the favicon is really a correct image type */
		if (content_get_type(icon) == CONTENT_UNKNOWN) {
			union content_msg_data msg_data;

			LOG(("%s is not a favicon", content_get_url(icon)));

			hlcache_handle_abort(icon);
			hlcache_handle_release(icon);
			c->data.html.favicon = NULL;
			c->active -= 1;

			content_add_error(c, "NotFavIco", 0);

			msg_data.error = messages_get("NotFavIco");
			content_broadcast(c, CONTENT_MSG_STATUS, msg_data);
		}
		break;

	case CONTENT_MSG_READY:
		break;
	case CONTENT_MSG_DONE:
		c->active -= 1;
		break;

	case CONTENT_MSG_ERROR:
		LOG(("favicon %s failed: %s", 
				content_get_url(icon), event->data.error));
		hlcache_handle_release(c->data.html.favicon);
		c->data.html.favicon = NULL;

		content_add_error(c, "?", 0);
		
		c->active -= 1;
		break;

	case CONTENT_MSG_STATUS:
		content_broadcast(c, CONTENT_MSG_STATUS, event->data);
		break;

	case CONTENT_MSG_REDRAW:
		/* Fall through */
	case CONTENT_MSG_REFRESH:
		/* Fall through */
	case CONTENT_MSG_REFORMAT:
		break;

	default:
		assert(0);
	}

	if (c->active == 0) {
		/* all objects have arrived */
		content__reformat(c, c->available_width, c->height);
		html_set_status(c, "");
		content_set_done(c);
	}
	
	return NSERROR_OK;
}