mirror of
https://github.com/netsurf-browser/netsurf
synced 2024-12-26 05:57:00 +03:00
6ff76b4c3f
Temporarily disable declaring fonts. Printing may now work on RO3-4 non-PS only. svn path=/import/netsurf/; revision=1529
807 lines
20 KiB
C
807 lines
20 KiB
C
/*
|
|
* This file is part of NetSurf, http://netsurf.sourceforge.net/
|
|
* Licensed under the GNU General Public License,
|
|
* http://www.opensource.org/licenses/gpl-license
|
|
* Copyright 2004 John M Bell <jmb202@ecs.soton.ac.uk>
|
|
*/
|
|
|
|
#include <assert.h>
|
|
#include <string.h>
|
|
#include "oslib/font.h"
|
|
#include "oslib/hourglass.h"
|
|
#include "oslib/osfile.h"
|
|
#include "oslib/osfind.h"
|
|
#include "oslib/pdriver.h"
|
|
#include "oslib/wimp.h"
|
|
#include "rufl.h"
|
|
#include "netsurf/utils/config.h"
|
|
#include "netsurf/content/content.h"
|
|
#include "netsurf/desktop/plotters.h"
|
|
#include "netsurf/render/box.h"
|
|
#include "netsurf/render/font.h"
|
|
#include "netsurf/render/html.h"
|
|
#include "netsurf/render/layout.h"
|
|
#include "netsurf/riscos/gui.h"
|
|
#include "netsurf/riscos/print.h"
|
|
#include "netsurf/riscos/wimp.h"
|
|
#include "netsurf/utils/log.h"
|
|
#include "netsurf/utils/messages.h"
|
|
#include "netsurf/utils/utils.h"
|
|
|
|
/** \todo landscape format pages
|
|
* \todo be somewhat more intelligent and try not to crop pages
|
|
* half way up a line of text
|
|
* \todo make use of print stylesheets
|
|
*/
|
|
|
|
/* extern globals */
|
|
struct gui_window *print_current_window = 0;
|
|
bool print_text_black = false;
|
|
bool print_active = false;
|
|
|
|
#ifdef WITH_PRINT
|
|
|
|
/* 1 millipoint == 1/400 OS unit == 1/800 browser units */
|
|
|
|
/* static globals */
|
|
static int print_prev_message = 0;
|
|
static bool print_in_background = false;
|
|
static float print_scale = 1.0;
|
|
static int print_num_copies = 1;
|
|
static bool print_bg_images = false;
|
|
static int print_max_sheets = -1;
|
|
|
|
/* a font in a document */
|
|
struct print_font {
|
|
font_f handle;
|
|
void *font_name;
|
|
};
|
|
|
|
static void print_update_sheets_shaded_state(bool on);
|
|
static void print_send_printsave(struct content *c);
|
|
static bool print_send_printtypeknown(wimp_message *m);
|
|
static bool print_document(struct gui_window *g, const char *filename);
|
|
static const char *print_declare_fonts(struct box *box);
|
|
static bool print_find_fonts(struct box *box, struct print_font **print_fonts,
|
|
int *font_count);
|
|
|
|
/**
|
|
* Open the print dialog
|
|
*
|
|
* \param g parent window
|
|
* \param x leftmost edge of dialog (only if sub_menu == true)
|
|
* \param y topmost edge of dialog (as above)
|
|
* \param sub_menu open window as a submenu or as a persistent dialog
|
|
* \param keypress whether we were opened by a keypress
|
|
*/
|
|
void ro_gui_print_open(struct gui_window *g, int x, int y, bool sub_menu, bool keypress)
|
|
{
|
|
char *pdName;
|
|
bool printers_exists = true;
|
|
os_error *e;
|
|
|
|
assert(g != NULL);
|
|
|
|
print_current_window = g;
|
|
print_prev_message = 0;
|
|
|
|
/* Read Printer Driver name */
|
|
e = xpdriver_info(0, 0, 0, 0, &pdName, 0, 0, 0);
|
|
if (e) {
|
|
LOG(("%s", e->errmess));
|
|
printers_exists = false;
|
|
}
|
|
|
|
print_bg_images = g->option.background_images;
|
|
|
|
ro_gui_set_icon_selected_state(dialog_print, ICON_PRINT_TO_BOTTOM, true);
|
|
|
|
ro_gui_set_icon_selected_state(dialog_print, ICON_PRINT_SHEETS, false);
|
|
ro_gui_set_icon_integer(dialog_print, ICON_PRINT_SHEETS_VALUE, 1);
|
|
ro_gui_set_icon_string(dialog_print, ICON_PRINT_SHEETS_TEXT,
|
|
messages_get("PrintSheetFilled"));
|
|
print_update_sheets_shaded_state(true);
|
|
|
|
ro_gui_set_icon_selected_state(dialog_print, ICON_PRINT_FG_IMAGES, true);
|
|
ro_gui_set_icon_shaded_state(dialog_print, ICON_PRINT_FG_IMAGES, true);
|
|
|
|
ro_gui_set_icon_selected_state(dialog_print, ICON_PRINT_BG_IMAGES, print_bg_images);
|
|
|
|
ro_gui_set_icon_selected_state(dialog_print, ICON_PRINT_IN_BACKGROUND, false);
|
|
|
|
ro_gui_set_icon_selected_state(dialog_print, ICON_PRINT_UPRIGHT, true);
|
|
ro_gui_set_icon_selected_state(dialog_print, ICON_PRINT_SIDEWAYS, false);
|
|
|
|
ro_gui_set_icon_selected_state(dialog_print, ICON_PRINT_TEXT_BLACK, false);
|
|
|
|
ro_gui_set_icon_integer(dialog_print, ICON_PRINT_COPIES, 1);
|
|
|
|
if (!printers_exists) {
|
|
ro_gui_set_icon_shaded_state(dialog_print, ICON_PRINT_PRINT, true);
|
|
}
|
|
else {
|
|
ro_gui_set_icon_shaded_state(dialog_print, ICON_PRINT_PRINT, false);
|
|
ro_gui_set_window_title(dialog_print, pdName);
|
|
}
|
|
|
|
if (sub_menu) {
|
|
e = xwimp_create_sub_menu((wimp_menu *) dialog_print, x, y);
|
|
if (e) {
|
|
LOG(("xwimp_create_sub_menu: 0x%x: %s",
|
|
e->errnum, e->errmess));
|
|
warn_user("MenuError", e->errmess);
|
|
}
|
|
}
|
|
else {
|
|
ro_gui_dialog_open_persistant(g->window, dialog_print, !keypress);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle mouse clicks in print dialog
|
|
*
|
|
* \param pointer wimp_pointer block
|
|
*/
|
|
void ro_gui_print_click(wimp_pointer *pointer)
|
|
{
|
|
int copies = atoi(ro_gui_get_icon_string(dialog_print,
|
|
ICON_PRINT_COPIES));
|
|
int sheets = atoi(ro_gui_get_icon_string(dialog_print,
|
|
ICON_PRINT_SHEETS_VALUE));
|
|
|
|
if (pointer->buttons == wimp_CLICK_MENU)
|
|
return;
|
|
|
|
switch (pointer->i) {
|
|
case ICON_PRINT_SHEETS:
|
|
/* retain selection state */
|
|
ro_gui_set_icon_selected_state(dialog_print,
|
|
pointer->i, true);
|
|
print_update_sheets_shaded_state(false);
|
|
break;
|
|
case ICON_PRINT_TO_BOTTOM:
|
|
print_update_sheets_shaded_state(true);
|
|
case ICON_PRINT_UPRIGHT:
|
|
case ICON_PRINT_SIDEWAYS:
|
|
/* retain selection state */
|
|
ro_gui_set_icon_selected_state(dialog_print,
|
|
pointer->i, true);
|
|
break;
|
|
case ICON_PRINT_COPIES_UP: copies += 1; break;
|
|
case ICON_PRINT_COPIES_DOWN: copies -= 1; break;
|
|
case ICON_PRINT_SHEETS_UP: sheets += 1; break;
|
|
case ICON_PRINT_SHEETS_DOWN: sheets -= 1; break;
|
|
case ICON_PRINT_CANCEL:
|
|
print_cleanup();
|
|
break;
|
|
case ICON_PRINT_PRINT:
|
|
print_in_background = ro_gui_get_icon_selected_state(dialog_print, ICON_PRINT_IN_BACKGROUND);
|
|
print_text_black = ro_gui_get_icon_selected_state(dialog_print, ICON_PRINT_TEXT_BLACK);
|
|
print_num_copies = copies;
|
|
if (ro_gui_get_icon_selected_state(dialog_print, ICON_PRINT_SHEETS))
|
|
print_max_sheets = sheets;
|
|
else
|
|
print_max_sheets = -1;
|
|
print_current_window->option.background_images = ro_gui_get_icon_selected_state(dialog_print, ICON_PRINT_BG_IMAGES);
|
|
print_send_printsave(print_current_window->bw->current_content);
|
|
break;
|
|
}
|
|
|
|
if (copies < 1)
|
|
copies = 1;
|
|
else if (copies > 99)
|
|
copies = 99;
|
|
ro_gui_set_icon_integer(dialog_print, ICON_PRINT_COPIES, copies);
|
|
|
|
if (sheets < 1)
|
|
sheets = 1;
|
|
else if (sheets > 99)
|
|
sheets = 99;
|
|
ro_gui_set_icon_integer(dialog_print, ICON_PRINT_SHEETS_VALUE, sheets);
|
|
if (sheets > 1)
|
|
ro_gui_set_icon_string(dialog_print, ICON_PRINT_SHEETS_TEXT,
|
|
messages_get("PrintSheetsFilled"));
|
|
else
|
|
ro_gui_set_icon_string(dialog_print, ICON_PRINT_SHEETS_TEXT,
|
|
messages_get("PrintSheetFilled"));
|
|
}
|
|
|
|
/**
|
|
* Handle keypresses in print dialog
|
|
*
|
|
* \param key wimp_key block
|
|
* \return true if keypress dealt with, false otherwise.
|
|
*/
|
|
bool ro_gui_print_keypress(wimp_key *key)
|
|
{
|
|
switch (key->c) {
|
|
case wimp_KEY_ESCAPE:
|
|
print_cleanup();
|
|
return true;
|
|
case wimp_KEY_RETURN:
|
|
if (ro_gui_get_icon_shaded_state(dialog_print, ICON_PRINT_PRINT))
|
|
return true;
|
|
|
|
print_in_background = ro_gui_get_icon_selected_state(dialog_print, ICON_PRINT_IN_BACKGROUND);
|
|
print_text_black = ro_gui_get_icon_selected_state(dialog_print, ICON_PRINT_TEXT_BLACK);
|
|
print_num_copies = atoi(ro_gui_get_icon_string(dialog_print, ICON_PRINT_COPIES));
|
|
if (ro_gui_get_icon_selected_state(dialog_print, ICON_PRINT_SHEETS))
|
|
print_max_sheets = atoi(ro_gui_get_icon_string(dialog_print, ICON_PRINT_SHEETS_VALUE));
|
|
else
|
|
print_max_sheets = -1;
|
|
print_current_window->option.background_images = ro_gui_get_icon_selected_state(dialog_print, ICON_PRINT_BG_IMAGES);
|
|
print_send_printsave(print_current_window->bw->current_content);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Set shaded state of sheets
|
|
*
|
|
* \param on whether to turn shading on or off
|
|
*/
|
|
void print_update_sheets_shaded_state(bool on)
|
|
{
|
|
ro_gui_set_icon_shaded_state(dialog_print, ICON_PRINT_SHEETS_VALUE, on);
|
|
ro_gui_set_icon_shaded_state(dialog_print, ICON_PRINT_SHEETS_DOWN, on);
|
|
ro_gui_set_icon_shaded_state(dialog_print, ICON_PRINT_SHEETS_UP, on);
|
|
ro_gui_set_icon_shaded_state(dialog_print, ICON_PRINT_SHEETS_TEXT, on);
|
|
ro_gui_set_caret_first(dialog_print);
|
|
}
|
|
|
|
/**
|
|
* Send a message_PRINT_SAVE
|
|
*
|
|
* \param c content to print
|
|
*/
|
|
void print_send_printsave(struct content *c)
|
|
{
|
|
wimp_full_message_data_xfer m;
|
|
os_error *e;
|
|
int len;
|
|
|
|
len = strlen(c->title) + 1;
|
|
if (212 < len)
|
|
len = 212;
|
|
|
|
m.size = ((44+len+3) & ~3);
|
|
m.your_ref = 0;
|
|
m.action = message_PRINT_SAVE;
|
|
m.w = (wimp_w)0;
|
|
m.i = m.pos.x = m.pos.y = 0;
|
|
m.est_size = 1024; /* arbitrary value - it really doesn't matter */
|
|
m.file_type = ro_content_filetype(c);
|
|
strncpy(m.file_name, c->title, 211);
|
|
m.file_name[211] = 0;
|
|
e = xwimp_send_message(wimp_USER_MESSAGE_RECORDED,
|
|
(wimp_message *)&m, 0);
|
|
if (e) {
|
|
LOG(("xwimp_send_message: 0x%x: %s",
|
|
e->errnum, e->errmess));
|
|
warn_user("WimpError", e->errmess);
|
|
print_cleanup();
|
|
}
|
|
print_prev_message = m.my_ref;
|
|
}
|
|
|
|
/**
|
|
* Send a message_PRINT_TYPE_KNOWN
|
|
*
|
|
* \param m message to reply to
|
|
* \return true on success, false otherwise
|
|
*/
|
|
bool print_send_printtypeknown(wimp_message *m)
|
|
{
|
|
os_error *e;
|
|
|
|
m->size = 20;
|
|
m->your_ref = m->my_ref;
|
|
m->action = message_PRINT_TYPE_KNOWN;
|
|
e = xwimp_send_message(wimp_USER_MESSAGE, m, m->sender);
|
|
if (e) {
|
|
LOG(("xwimp_send_message: 0x%x: %s",
|
|
e->errnum, e->errmess));
|
|
warn_user("WimpError", e->errmess);
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Handle a bounced message_PRINT_SAVE
|
|
*
|
|
* \param m the bounced message
|
|
*/
|
|
void print_save_bounce(wimp_message *m)
|
|
{
|
|
if (m->my_ref == 0 || m->my_ref != print_prev_message)
|
|
return;
|
|
|
|
/* try to print anyway (we're graphics printing) */
|
|
if (print_current_window) {
|
|
print_document(print_current_window, "printer:");
|
|
}
|
|
print_cleanup();
|
|
}
|
|
|
|
/**
|
|
* Handle message_PRINT_ERROR
|
|
*
|
|
* \param m the message containing the error
|
|
*/
|
|
void print_error(wimp_message *m)
|
|
{
|
|
pdriver_message_print_error *p = (pdriver_message_print_error*)&m->data;
|
|
if (m->your_ref == 0 || m->your_ref != print_prev_message)
|
|
return;
|
|
|
|
if (m->size == 20)
|
|
warn_user("PrintErrorRO2", 0);
|
|
else
|
|
warn_user("PrintError", p->errmess);
|
|
|
|
print_cleanup();
|
|
}
|
|
|
|
/**
|
|
* Handle message_PRINT_TYPE_ODD
|
|
*
|
|
* \param m the message to handle
|
|
*/
|
|
void print_type_odd(wimp_message *m)
|
|
{
|
|
if ((m->your_ref == 0 || m->your_ref == print_prev_message) &&
|
|
!print_in_background) {
|
|
/* reply to a previous message (ie printsave) */
|
|
if (print_current_window && print_send_printtypeknown(m)) {
|
|
print_document(print_current_window, "printer:");
|
|
}
|
|
print_cleanup();
|
|
}
|
|
else {
|
|
/* broadcast message */
|
|
/* no need to do anything */
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
* Handle message_DATASAVE_ACK for the printing protocol.
|
|
*
|
|
* \param m the message to handle
|
|
* \return true if message successfully handled, false otherwise
|
|
*
|
|
* We cheat here and, instead of giving Printers what it asked for (a copy of
|
|
* the file so it can poke us later via a broadcast of PrintTypeOdd), we give
|
|
* it a file that it can print itself without having to bother us further. For
|
|
* PostScript printers (type 0) we give it a PostScript file. Otherwise, we give
|
|
* it a PrintOut file.
|
|
*
|
|
* This method has a couple of advantages:
|
|
* - we can reuse this code for background printing (we simply ignore the
|
|
* PrintTypeOdd reply)
|
|
* - there's no need to ensure all components of a page queued to be printed
|
|
* still exist when it reaches the top of the queue. (which reduces complexity
|
|
* a fair bit)
|
|
*/
|
|
|
|
bool print_ack(wimp_message *m)
|
|
{
|
|
pdriver_info_type info_type;
|
|
pdriver_type type;
|
|
os_error *error;
|
|
|
|
if (m->your_ref == 0 || m->your_ref != print_prev_message ||
|
|
!print_current_window)
|
|
return false;
|
|
|
|
/* read printer driver type */
|
|
error = xpdriver_info(&info_type, 0, 0, 0, 0, 0, 0, 0);
|
|
if (error) {
|
|
LOG(("xpdriver_info: 0x%x: %s",
|
|
error->errnum, error->errmess));
|
|
warn_user("PrintError", error->errmess);
|
|
print_cleanup();
|
|
return true;
|
|
}
|
|
type = info_type >> 16;
|
|
|
|
/* print to file */
|
|
if (!print_document(print_current_window,
|
|
m->data.data_xfer.file_name)) {
|
|
print_cleanup();
|
|
return true;
|
|
}
|
|
|
|
/* send dataload */
|
|
m->your_ref = m->my_ref;
|
|
m->action = message_DATA_LOAD;
|
|
|
|
if (type == pdriver_TYPE_PS)
|
|
m->data.data_xfer.file_type = osfile_TYPE_POSTSCRIPT;
|
|
else
|
|
m->data.data_xfer.file_type = osfile_TYPE_PRINTOUT;
|
|
|
|
error = xwimp_send_message(wimp_USER_MESSAGE_RECORDED, m, m->sender);
|
|
if (error) {
|
|
LOG(("xwimp_send_message: 0x%x: %s",
|
|
error->errnum, error->errmess));
|
|
warn_user("WimpError", error->errmess);
|
|
/* and delete temporary file */
|
|
xosfile_delete(m->data.data_xfer.file_name,
|
|
0, 0, 0, 0, 0);
|
|
}
|
|
print_prev_message = m->my_ref;
|
|
|
|
print_cleanup();
|
|
return true;
|
|
}
|
|
|
|
|
|
/**
|
|
* Handle a bounced dataload message
|
|
*
|
|
* \param m the message to handle
|
|
*/
|
|
void print_dataload_bounce(wimp_message *m)
|
|
{
|
|
if (m->your_ref == 0 || m->your_ref != print_prev_message)
|
|
return;
|
|
|
|
xosfile_delete(m->data.data_xfer.file_name, 0, 0, 0, 0, 0);
|
|
print_cleanup();
|
|
}
|
|
|
|
/**
|
|
* Cleanup after printing
|
|
*/
|
|
void print_cleanup(void)
|
|
{
|
|
if (print_current_window)
|
|
print_current_window->option.background_images =
|
|
print_bg_images;
|
|
print_current_window = 0;
|
|
print_text_black = false;
|
|
print_prev_message = 0;
|
|
print_max_sheets = -1;
|
|
xwimp_create_menu((wimp_menu *)-1, 0, 0);
|
|
ro_gui_dialog_close(dialog_print);
|
|
}
|
|
|
|
|
|
/**
|
|
* Print a document.
|
|
*
|
|
* \param g gui_window containing the document to print
|
|
* \param filename name of file to print to
|
|
* \return true on success, false on error and error reported
|
|
*/
|
|
|
|
bool print_document(struct gui_window *g, const char *filename)
|
|
{
|
|
int left, right, top, bottom, width, height;
|
|
int saved_width;
|
|
int yscroll = 0, sheets = print_max_sheets;
|
|
struct box *box = 0;
|
|
struct content *c = g->bw->current_content;
|
|
const char *error_message;
|
|
pdriver_features features;
|
|
os_fw fhandle, old_job = 0;
|
|
os_error *error;
|
|
|
|
/* no point printing a blank page */
|
|
if (!c) {
|
|
warn_user("PrintError", "nothing to print");
|
|
return false;
|
|
}
|
|
|
|
if (c->type == CONTENT_HTML)
|
|
box = c->data.html.layout;
|
|
|
|
/* read printer driver features */
|
|
error = xpdriver_info(0, 0, 0, &features, 0, 0, 0, 0);
|
|
if (error) {
|
|
LOG(("xpdriver_info: 0x%x: %s",
|
|
error->errnum, error->errmess));
|
|
warn_user("PrintError", error->errmess);
|
|
return false;
|
|
}
|
|
|
|
/* read page size */
|
|
error = xpdriver_page_size(0, 0, &left, &bottom, &right, &top);
|
|
if (error) {
|
|
LOG(("xpdriver_page_size: 0x%x: %s",
|
|
error->errnum, error->errmess));
|
|
warn_user("PrintError", error->errmess);
|
|
return false;
|
|
}
|
|
|
|
width = (right - left) / 800;
|
|
height = (top - bottom) / 800;
|
|
|
|
/* layout the document to the correct width */
|
|
saved_width = c->width;
|
|
if (c->type == CONTENT_HTML)
|
|
layout_document(box, width, c->data.html.box_pool);
|
|
|
|
/* open printer file */
|
|
error = xosfind_openoutw(osfind_NO_PATH | osfind_ERROR_IF_DIR |
|
|
osfind_ERROR_IF_ABSENT, filename, 0, &fhandle);
|
|
if (error) {
|
|
LOG(("xosfind_openoutw: 0x%x: %s",
|
|
error->errnum, error->errmess));
|
|
warn_user("PrintError", error->errmess);
|
|
return false;
|
|
}
|
|
|
|
/* select print job */
|
|
error = xpdriver_select_jobw(fhandle, "NetSurf", &old_job);
|
|
if (error) {
|
|
LOG(("xpdriver_select_jobw: 0x%x: %s",
|
|
error->errnum, error->errmess));
|
|
warn_user("PrintError", error->errmess);
|
|
xosfind_closew(fhandle);
|
|
return false;
|
|
}
|
|
|
|
rufl_invalidate_cache();
|
|
|
|
/* declare fonts, if necessary */
|
|
/*if (features & pdriver_FEATURE_DECLARE_FONT &&
|
|
c->type == CONTENT_HTML) {
|
|
if ((error_message = print_declare_fonts(box)))
|
|
goto error;
|
|
}*/
|
|
|
|
plot = ro_plotters;
|
|
ro_plot_set_scale(print_scale);
|
|
ro_gui_current_redraw_gui = g;
|
|
|
|
/* print is now active */
|
|
print_active = true;
|
|
|
|
do {
|
|
int clip_x0, clip_y0, clip_x1, clip_y1;
|
|
os_box b = {left / 400 - 2, bottom / 400 - 2,
|
|
right / 400 + 2, top / 400 + 2};
|
|
os_hom_trfm t = { { {65536, 0}, {0, 65536} } };
|
|
os_coord p = {left, bottom};
|
|
osbool more;
|
|
|
|
xhourglass_percentage((int) (yscroll * 100 / c->height));
|
|
|
|
/* give page rectangle */
|
|
error = xpdriver_give_rectangle(0, &b, &t, &p, os_COLOUR_WHITE);
|
|
if (error) {
|
|
LOG(("xpdriver_give_rectangle: 0x%x: %s",
|
|
error->errnum, error->errmess));
|
|
error_message = error->errmess;
|
|
goto error;
|
|
}
|
|
|
|
LOG(("given rectangle: [(%d, %d), (%d, %d)]",
|
|
b.x0, b.y0, b.x1, b.y1));
|
|
|
|
/* and redraw the document */
|
|
error = xpdriver_draw_page(print_num_copies, &b, 0, 0,
|
|
&more, 0);
|
|
if (error) {
|
|
LOG(("xpdriver_draw_page: 0x%x: %s",
|
|
error->errnum, error->errmess));
|
|
error_message = error->errmess;
|
|
goto error;
|
|
}
|
|
|
|
ro_plot_origin_x = left / 400;
|
|
ro_plot_origin_y = top / 400 + yscroll * 2;
|
|
|
|
while (more) {
|
|
LOG(("redrawing area: [(%d, %d), (%d, %d)]",
|
|
b.x0, b.y0, b.x1, b.y1));
|
|
clip_x0 = (b.x0 - ro_plot_origin_x) / 2;
|
|
clip_y0 = (ro_plot_origin_y - b.y1) / 2;
|
|
clip_x1 = (b.x1 - ro_plot_origin_x) / 2;
|
|
clip_y1 = (ro_plot_origin_y - b.y0) / 2;
|
|
if (!content_redraw(c, 0, 0,
|
|
c->width, c->height,
|
|
clip_x0, clip_y0, clip_x1, clip_y1,
|
|
print_scale,
|
|
0xFFFFFF)) {
|
|
error_message = "redraw error";
|
|
goto error;
|
|
}
|
|
|
|
error = xpdriver_get_rectangle(&b, &more, 0);
|
|
if (error) {
|
|
LOG(("xpdriver_get_rectangle: 0x%x: %s",
|
|
error->errnum, error->errmess));
|
|
error_message = error->errmess;
|
|
goto error;
|
|
}
|
|
}
|
|
|
|
yscroll += height;
|
|
} while (yscroll <= c->height && --sheets != 0);
|
|
|
|
/* make print inactive */
|
|
print_active = false;
|
|
ro_gui_current_redraw_gui = 0;
|
|
|
|
/* clean up */
|
|
error = xpdriver_end_jobw(fhandle);
|
|
if (error) {
|
|
LOG(("xpdriver_end_jobw: 0x%x: %s",
|
|
error->errnum, error->errmess));
|
|
error_message = error->errmess;
|
|
goto error;
|
|
}
|
|
|
|
error = xosfind_closew(fhandle);
|
|
if (error) {
|
|
LOG(("xosfind_closew: 0x%x: %s",
|
|
error->errnum, error->errmess));
|
|
warn_user("PrintError", error->errmess);
|
|
return false;
|
|
}
|
|
|
|
if (old_job) {
|
|
error = xpdriver_select_jobw(old_job, 0, 0);
|
|
if (error) {
|
|
LOG(("xpdriver_select_jobw: 0x%x: %s",
|
|
error->errnum, error->errmess));
|
|
warn_user("PrintError", error->errmess);
|
|
/* the printing succeeded anyway */
|
|
return true;
|
|
}
|
|
}
|
|
|
|
rufl_invalidate_cache();
|
|
|
|
/* restore document layout */
|
|
if (c->type == CONTENT_HTML)
|
|
layout_document(box, saved_width, c->data.html.box_pool);
|
|
|
|
return true;
|
|
|
|
error:
|
|
xpdriver_abort_job(fhandle);
|
|
xosfind_closew(fhandle);
|
|
if (old_job)
|
|
xpdriver_select_jobw(old_job, 0, 0);
|
|
print_active = false;
|
|
ro_gui_current_redraw_gui = 0;
|
|
|
|
warn_user("PrintError", error_message);
|
|
|
|
rufl_invalidate_cache();
|
|
|
|
/* restore document layout */
|
|
if (c->type == CONTENT_HTML)
|
|
layout_document(box, saved_width, c->data.html.box_pool);
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
/**
|
|
* Declare fonts to the printer driver.
|
|
*
|
|
* \param box box tree being printed
|
|
* \return 0 on success, error message on error
|
|
*/
|
|
|
|
const char *print_declare_fonts(struct box *box)
|
|
{
|
|
struct print_font *print_fonts = calloc(255, sizeof (*print_fonts));
|
|
unsigned int font_count = 0, i;
|
|
const char *error_message = 0;
|
|
os_error *error;
|
|
|
|
if (!print_fonts)
|
|
return messages_get("NoMemory");
|
|
|
|
if (!print_find_fonts(box, &print_fonts, &font_count)) {
|
|
LOG(("print_find_fonts() failed"));
|
|
error_message = "print_find_fonts() failed";
|
|
goto end;
|
|
}
|
|
|
|
for (i = 0; i != font_count; ++i) {
|
|
error = xpdriver_declare_font(print_fonts[i].handle,
|
|
print_fonts[i].font_name, 0);
|
|
if (error) {
|
|
LOG(("xpdriver_declare_font: 0x%x: %s",
|
|
error->errnum, error->errmess));
|
|
error_message = error->errmess;
|
|
goto end;
|
|
}
|
|
}
|
|
error = xpdriver_declare_font(0, 0, 0);
|
|
if (error) {
|
|
LOG(("xpdriver_declare_font: 0x%x: %s",
|
|
error->errnum, error->errmess));
|
|
error_message = error->errmess;
|
|
goto end;
|
|
}
|
|
|
|
end:
|
|
for (i = 0; i != font_count; i++)
|
|
free(print_fonts[i].font_name);
|
|
free(print_fonts);
|
|
|
|
return error_message;
|
|
}
|
|
|
|
|
|
/**
|
|
* Find all fonts in a document
|
|
*
|
|
* \param box Root of box tree
|
|
* \param print_fonts pointer to array of fonts in document
|
|
* \paran font_count number of fonts declared
|
|
* \return true on success, false otherwise
|
|
*/
|
|
bool print_find_fonts(struct box *box, struct print_font **print_fonts, int *font_count)
|
|
{
|
|
struct box *a;
|
|
const char *txt;
|
|
size_t txt_len;
|
|
size_t width, rolength, consumed;
|
|
const char *rofontname, *rotext;
|
|
int i;
|
|
|
|
assert(box);
|
|
#if 0
|
|
if (box->text && box->font && box->length > 0) {
|
|
txt = box->text;
|
|
txt_len = box->length;
|
|
|
|
if (box->font->ftype == FONTTYPE_UFONT) {
|
|
/** \todo handle ufont */
|
|
LOG(("ufont"));
|
|
return false;
|
|
}
|
|
|
|
nsfont_txtenum(box->font, txt, txt_len,
|
|
&width, &rofontname,
|
|
&rotext, &rolength,
|
|
&consumed);
|
|
|
|
if (rotext == NULL) {
|
|
LOG(("rotext = null (%d)", txt_len));
|
|
return false;
|
|
}
|
|
|
|
for (i = 0; i != *font_count; ++i) {
|
|
if (!strcmp(((*print_fonts)[i]).font_name, rofontname))
|
|
break;
|
|
}
|
|
|
|
if (i == *font_count) {
|
|
/* max 255 fonts (as per draw) */
|
|
if (*font_count == 255)
|
|
return false;
|
|
if ((((*print_fonts)[*font_count]).font_name = strdup(rofontname)) == NULL) {
|
|
LOG(("failed to strdup (%s)", rofontname));
|
|
return false;
|
|
}
|
|
((*print_fonts)[(*font_count)++]).handle = (font_f)box->font->handle;
|
|
}
|
|
|
|
free((void*)rotext);
|
|
}
|
|
|
|
for (a = box->children; a; a = a->next) {
|
|
if (!print_find_fonts(a, print_fonts, font_count))
|
|
return false;
|
|
}
|
|
#endif
|
|
return true;
|
|
}
|
|
|
|
#endif
|