void gui_window_update_extent(struct gui_window *g) { if (!g->bw->current_content) return; gtk_layout_set_size(g->layout, content_get_width(g->bw->current_content) * g->bw->scale, content_get_height(g->bw->current_content) * g->bw->scale); }
bool save_as_draw(hlcache_handle *h, const char *path) { pencil_code code; char *drawfile_buffer; size_t drawfile_size; os_error *error; ro_save_draw_diagram = pencil_create(); if (!ro_save_draw_diagram) { warn_user("NoMemory", 0); return false; } ro_save_draw_width = content_get_width(h); ro_save_draw_height = content_get_height(h); plot = ro_save_draw_plotters; if (!content_redraw(h, 0, -ro_save_draw_height, ro_save_draw_width, ro_save_draw_height, INT_MIN, INT_MIN, INT_MAX, INT_MAX, 1, 0xFFFFFF)) { pencil_free(ro_save_draw_diagram); return false; } /*pencil_dump(ro_save_draw_diagram);*/ code = pencil_save_drawfile(ro_save_draw_diagram, "NetSurf", &drawfile_buffer, &drawfile_size); if (code != pencil_OK) { warn_user("SaveError", 0); pencil_free(ro_save_draw_diagram); return false; } assert(drawfile_buffer); error = xosfile_save_stamped(path, osfile_TYPE_DRAW, (byte *) drawfile_buffer, (byte *) drawfile_buffer + drawfile_size); if (error) { LOG(("xosfile_save_stamped failed: 0x%x: %s", error->errnum, error->errmess)); warn_user("SaveError", error->errmess); pencil_free(ro_save_draw_diagram); return false; } pencil_free(ro_save_draw_diagram); return true; }
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; }
void gui_window_update_extent(struct gui_window *gw) { float scale = gw->bw->scale; fbtk_set_scroll_parameters(gw->hscroll, 0, content_get_width(gw->bw->current_content) * scale, fbtk_get_width(gw->browser), 100); fbtk_set_scroll_parameters(gw->vscroll, 0, content_get_height(gw->bw->current_content) * scale, fbtk_get_height(gw->browser), 100); }
void gui_window_update_extent(struct gui_window *g) { CALLED(); if (!g->bw->current_content) return; if (g->view == NULL) return; if (!g->view->LockLooper()) return; float x_max = content_get_width(g->bw->current_content) * g->bw->scale /* - 1*/; float y_max = content_get_height(g->bw->current_content) * g->bw->scale /* - 1*/; float x_prop = g->view->Bounds().Width() / x_max; float y_prop = g->view->Bounds().Height() / y_max; x_max -= g->view->Bounds().Width() + 1; y_max -= g->view->Bounds().Height() + 1; printf("x_max = %f y_max = %f x_prop = %f y_prop = %f\n", x_max, y_max, x_prop, y_prop); if (g->view->ScrollBar(B_HORIZONTAL)) { g->view->ScrollBar(B_HORIZONTAL)->SetRange(0, x_max); g->view->ScrollBar(B_HORIZONTAL)->SetProportion(x_prop); g->view->ScrollBar(B_HORIZONTAL)->SetSteps(10, 50); } if (g->view->ScrollBar(B_VERTICAL)) { g->view->ScrollBar(B_VERTICAL)->SetRange(0, y_max); g->view->ScrollBar(B_VERTICAL)->SetProportion(y_prop); g->view->ScrollBar(B_VERTICAL)->SetSteps(10, 50); } #if 0 g->view->ResizeTo( g->bw->current_content->width * g->bw->scale /* - 1*/, g->bw->current_content->height * g->bw->scale /* - 1*/); #endif g->view->UnlockLooper(); #warning WRITEME #if 0 /* GTK */ gtk_widget_set_size_request(GTK_WIDGET(g->drawing_area), g->bw->current_content->width * g->bw->scale, g->bw->current_content->height * g->bw->scale); gtk_widget_set_size_request(GTK_WIDGET(g->viewport), 0, 0); #endif }
/* It seems this method is called when content size got adjusted, so that we can adjust scroll info. We also have to call it when tab change occurs. */ void gui_window_update_extent(struct gui_window *gw) { if( gw->browser->bw->current_content != NULL ) { // TODO: store content size! if(window_get_active_gui_window(gw->root) == gw) { window_set_content_size( gw->root, content_get_width(gw->browser->bw->current_content), content_get_height(gw->browser->bw->current_content) ); window_update_back_forward(gw->root); GRECT area; window_get_grect(gw->root, BROWSER_AREA_CONTENT, &area); window_schedule_redraw_grect(gw->root, &area); } } }
/** * This function calls print setup, prints page after page until the whole * content is printed calls cleaning up afterwise. * * \param content The content to be printed * \param printer The printer interface for the printer to be used * \param settings The settings for printing to use * \return true if successful, false otherwise */ bool print_basic_run(hlcache_handle *content, const struct printer *printer, struct print_settings *settings) { bool ret = true; assert(content != NULL && printer != NULL && settings != NULL); if (print_set_up(content, printer, settings, NULL)) return false; while (ret && (done_height < content_get_height(printed_content)) ) { ret = print_draw_next_page(printer, settings); } print_cleanup(content, printer, settings); return ret; }
/** * This function prepares the content to be printed. The current browser content * is duplicated and resized, printer initialization is called. * * \param content The content to be printed * \param printer The printer interface for the printer to be used * \param settings The settings for printing to use * \param height updated to the height of the printed content * \return true if successful, false otherwise */ bool print_set_up(hlcache_handle *content, const struct printer *printer, struct print_settings *settings, double *height) { printed_content = print_init(content, settings); if (printed_content == NULL) return false; print_apply_settings(printed_content, settings); if (height) *height = content_get_height(printed_content); printer->print_begin(settings); done_height = 0; return true; }
/** * The content is resized to fit page width. * * \param content The content to be printed * \param settings The settings for printing to use * \return true if successful, false otherwise */ bool print_apply_settings(hlcache_handle *content, struct print_settings *settings) { if (settings == NULL) return false; /* Apply settings - adjust page size etc */ page_content_width = (settings->page_width - FIXTOFLT(FSUB(settings->margins[MARGINLEFT], settings->margins[MARGINRIGHT]))) / settings->scale; page_content_height = (settings->page_height - FIXTOFLT(FSUB(settings->margins[MARGINTOP], settings->margins[MARGINBOTTOM]))) / settings->scale; content_reformat(content, false, page_content_width, 0); LOG("New layout applied.New height = %d ; New width = %d ", content_get_height(content), content_get_width(content)); return true; }
/* queue a window scroll */ static void widget_scroll_y(struct gui_window *gw, int y, bool abs) { struct browser_widget_s *bwidget = fbtk_get_userpw(gw->browser); int content_height; int height; float scale = gw->bw->scale; LOG(("window scroll")); if (abs) { bwidget->pany = y - bwidget->scrolly; } else { bwidget->pany += y; } content_height = content_get_height(gw->bw->current_content) * scale; height = fbtk_get_height(gw->browser); /* dont pan off the top */ if ((bwidget->scrolly + bwidget->pany) < 0) bwidget->pany = -bwidget->scrolly; /* do not pan off the bottom of the content */ if ((bwidget->scrolly + bwidget->pany) > (content_height - height)) bwidget->pany = (content_height - height) - bwidget->scrolly; if (bwidget->pany == 0) return; bwidget->pan_required = true; fbtk_request_redraw(gw->browser); fbtk_set_scroll_position(gw->vscroll, bwidget->scrolly + bwidget->pany); }
/** * 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) { 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 == SCROLLING_YES) { scroll_x = true; scroll_y = true; } else if (bw->scrolling == 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))) 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))) 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); }
/* Report scroll event to the browser component. */ void browser_scroll( struct gui_window * gw, short mode, int value, bool abs ) { LGRECT work; int max_y_scroll; int max_x_scroll; int oldx = gw->browser->scroll.current.x; int oldy = gw->browser->scroll.current.y; struct s_browser * b = gw->browser; LOG(("")); if( b->bw->current_content != NULL ) { browser_get_rect( gw, BR_CONTENT, &work); max_y_scroll = (content_get_height( b->bw->current_content ) - work.g_h ); max_x_scroll = (content_get_width( b->bw->current_content ) - work.g_w); } else { return; } switch( mode ) { case WA_UPPAGE: case WA_UPLINE: if( max_y_scroll < 1 ) return; if( abs == false ) b->scroll.requested.y -= value; else b->scroll.requested.y = value - b->scroll.current.y; break; case WA_DNPAGE: case WA_DNLINE: if( max_y_scroll < 1 ) return; if( abs == false ) b->scroll.requested.y += value; else b->scroll.requested.y = value - b->scroll.current.y; break; case WA_LFPAGE: case WA_LFLINE: if( max_x_scroll < 1 ) return; if( abs == false ) b->scroll.requested.x -= value; else b->scroll.requested.x = value - b->scroll.current.x; break; case WA_RTPAGE: case WA_RTLINE: if( max_x_scroll < 1 ) return; if( abs == false ) b->scroll.requested.x += value; else b->scroll.requested.x = value - b->scroll.current.x; break; default: break; } if( b->scroll.current.y + b->scroll.requested.y < 0 ) { b->scroll.requested.y = -b->scroll.current.y; } if( b->scroll.current.y + b->scroll.requested.y > max_y_scroll ) { b->scroll.requested.y = max_y_scroll - b->scroll.current.y; } if( b->scroll.current.x + b->scroll.requested.x < 0 ) { b->scroll.requested.x = -b->scroll.current.x; } if( b->scroll.current.x + b->scroll.requested.x > max_x_scroll ) { b->scroll.requested.x = max_x_scroll - b->scroll.current.x; } if( oldy != b->scroll.current.y + b->scroll.requested.y || oldx != b->scroll.current.x + b->scroll.requested.x ) { b->scroll.required = true; } }
/** * 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; }
bool save_as_draw(hlcache_handle *h, const char *path) { pencil_code code; char *drawfile_buffer; struct rect clip; struct content_redraw_data data; size_t drawfile_size; os_error *error; struct redraw_context ctx = { .interactive = false, .background_images = true, .plot = &ro_save_draw_plotters }; ro_save_draw_diagram = pencil_create(); if (!ro_save_draw_diagram) { warn_user("NoMemory", 0); return false; } ro_save_draw_width = content_get_width(h); ro_save_draw_height = content_get_height(h); clip.x0 = clip.y0 = INT_MIN; clip.x1 = clip.y1 = INT_MAX; data.x = 0; data.y = -ro_save_draw_height; data.width = ro_save_draw_width; data.height = ro_save_draw_height; data.background_colour = 0xFFFFFF; data.scale = 1; data.repeat_x = false; data.repeat_y = false; if (!content_redraw(h, &data, &clip, &ctx)) { pencil_free(ro_save_draw_diagram); return false; } /*pencil_dump(ro_save_draw_diagram);*/ code = pencil_save_drawfile(ro_save_draw_diagram, "NetSurf", &drawfile_buffer, &drawfile_size); if (code != pencil_OK) { warn_user("SaveError", 0); pencil_free(ro_save_draw_diagram); return false; } assert(drawfile_buffer); error = xosfile_save_stamped(path, osfile_TYPE_DRAW, (byte *) drawfile_buffer, (byte *) drawfile_buffer + drawfile_size); if (error) { LOG("xosfile_save_stamped failed: 0x%x: %s", error->errnum, error->errmess); warn_user("SaveError", error->errmess); pencil_free(ro_save_draw_diagram); return false; } pencil_free(ro_save_draw_diagram); return true; } bool ro_save_draw_rectangle(int x0, int y0, int x1, int y1, const plot_style_t *style) { pencil_code code; const int path[] = { draw_MOVE_TO, x0 * 2, -y0 * 2 - 1, draw_LINE_TO, x1 * 2, -y0 * 2 - 1, draw_LINE_TO, x1 * 2, -y1 * 2 - 1, draw_LINE_TO, x0 * 2, -y1 * 2 - 1, draw_CLOSE_LINE, draw_END_PATH }; if (style->fill_type != PLOT_OP_TYPE_NONE) { code = pencil_path(ro_save_draw_diagram, path, sizeof path / sizeof path[0], style->fill_colour << 8, pencil_TRANSPARENT, 0, pencil_JOIN_MITRED, pencil_CAP_BUTT, pencil_CAP_BUTT, 0, 0, false, pencil_SOLID); if (code != pencil_OK) return ro_save_draw_error(code); } if (style->stroke_type != PLOT_OP_TYPE_NONE) { code = pencil_path(ro_save_draw_diagram, path, sizeof path / sizeof path[0], pencil_TRANSPARENT, style->stroke_colour << 8, style->stroke_width, pencil_JOIN_MITRED, pencil_CAP_BUTT, pencil_CAP_BUTT, 0, 0, false, pencil_SOLID); if (code != pencil_OK) return ro_save_draw_error(code); } return true; }
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; }