Commit 2eacb2ce authored by Andrew Hodgkinson's avatar Andrew Hodgkinson
Browse files

Further printing tweaks. Font colours inside anchors now work (must be built...

Further printing tweaks. Font colours inside anchors now work (must be built with the 02-Mar-2000 HTMLLib or later). Event log won't show guts of internal URLs for just-born browser windows if displaying the list by URL. Empty Location headers don't redirect down zero page and give a nasty internal error; raise "no fetcher service found" instead.
parent c3204ab0
......@@ -54,3 +54,4 @@ ahodgkin_208_i2 Intermediate 2.08 build. Printing headers and
features (25-Feb-2000).
ahodgkin_208_i3 Intermediate 2.08 build. Printing headers and
footers now work... (01-Mar-2000).
ahodgkin_208_i4 Intermediate 2.08 build. Various fixes over i3.
......@@ -1043,6 +1043,10 @@ _kernel_oserror * eventlogs_url_changed(browser_data * b, unsigned int ok_to_cle
if (!text) text = browser_current_url(b);
if (!text) text = "...";
/* Clean up internal URLs */
if (!strncmp(text, Internal_URL, Int_URL_Len)) text += urlutils_internal_extra(text);
return scrolllist_set_item_text(0,
window_id,
EventLogsScrollList,
......
......@@ -2005,10 +2005,10 @@ _kernel_oserror * html_get_next_token(browser_data * b, unsigned int handle, int
strcat(tokens, url);
}
if (strlen(redirect) + strlen(tokens) + 5 < sizeof(tokens))
if (strlen(redirect ? redirect : "<NULL>") + strlen(tokens) + 5 < sizeof(tokens))
{
strcat(tokens, " -> ");
strcat(tokens, redirect);
strcat(tokens, redirect ? redirect : "<NULL>");
}
/* Let this fail silently */
......@@ -2016,6 +2016,8 @@ _kernel_oserror * html_get_next_token(browser_data * b, unsigned int handle, int
eventlogs_log_message(b, eventlogs_http_message, tokens);
}
if (redirect == NULL) redirect = "";
/* Stop the current fetch and free the source store, */
/* remembering to invalidate the anchor pointing to it */
......
......@@ -2491,6 +2491,8 @@ static void print_header_and_footer_sizes(browser_data * b, unsigned int pages,
/* print_header() */
/* */
/* Given a page number and y coordinate, print a page header. */
/* The LeftMargin and RightMargin Choices file entries are */
/* dealt with internally. */
/* */
/* Parameters: Pointer to a browser_data struct relevant to */
/* the page being printed; */
......@@ -2511,10 +2513,14 @@ static void print_header(browser_data * b, unsigned int pages, unsigned int page
{
char buffer[Limits_Message];
int top, bot, h;
int lm, rm;
if (choices.print_headers_from == 0 || page < choices.print_headers_from) return;
if (reformat_text_line_height(b, NULL, &top, &bot)) return;
convert_to_os(b->left_margin, &lm);
convert_to_os(b->right_margin, &rm);
top = (top * choices.print_hf_scale) / 100;
bot = (bot * choices.print_hf_scale) / 100;
......@@ -2526,7 +2532,11 @@ static void print_header(browser_data * b, unsigned int pages, unsigned int page
choices.print_hf_italic,
choices.print_hf_bold);
convert_to_points(width - (PrintHeaderAndFooterWidthAdjust * 2), &width);
convert_to_points(width, &width);
fm_set_font_colour(h,
Redraw_Colour_Black,
Redraw_Colour_White);
/* Left hand side's string */
......@@ -2550,7 +2560,7 @@ static void print_header(browser_data * b, unsigned int pages, unsigned int page
if (*buffer != '\0')
{
fm_puts(h,
PrintHeaderAndFooterWidthAdjust,
lm,
header_y,
buffer,
1,
......@@ -2639,7 +2649,7 @@ static void print_header(browser_data * b, unsigned int pages, unsigned int page
convert_to_os(width - w, &w);
fm_puts(h,
w,
w - rm,
header_y,
buffer,
1,
......@@ -2653,6 +2663,8 @@ static void print_header(browser_data * b, unsigned int pages, unsigned int page
/* print_footer() */
/* */
/* Given a page number and y coordinate, print a page footer. */
/* The LeftMargin and RightMargin Choices file entries are */
/* dealt with internally. */
/* */
/* Parameters: Pointer to a browser_data struct relevant to */
/* the page being printed; */
......@@ -2673,10 +2685,14 @@ static void print_footer(browser_data * b, unsigned int pages, unsigned int page
{
char buffer[Limits_Message];
int top, bot, h;
int lm, rm;
if (choices.print_footers_from == 0 || page < choices.print_footers_from) return;
if (reformat_text_line_height(b, NULL, &top, &bot)) return;
convert_to_os(b->left_margin, &lm);
convert_to_os(b->right_margin, &rm);
top = (top * choices.print_hf_scale) / 100;
bot = (bot * choices.print_hf_scale) / 100;
......@@ -2687,7 +2703,11 @@ static void print_footer(browser_data * b, unsigned int pages, unsigned int page
choices.print_hf_italic,
choices.print_hf_bold);
convert_to_points(width - (PrintHeaderAndFooterWidthAdjust * 2), &width);
convert_to_points(width, &width);
fm_set_font_colour(h,
Redraw_Colour_Black,
Redraw_Colour_White);
/* Left hand side's string */
......@@ -2711,7 +2731,7 @@ static void print_footer(browser_data * b, unsigned int pages, unsigned int page
if (*buffer != '\0')
{
fm_puts(h,
PrintHeaderAndFooterWidthAdjust,
lm,
bot,
buffer,
1,
......@@ -2800,7 +2820,7 @@ static void print_footer(browser_data * b, unsigned int pages, unsigned int page
convert_to_os(width - w, &w);
fm_puts(h,
w,
w - rm,
bot,
buffer,
1,
......@@ -3026,111 +3046,24 @@ static void print_fake_redraw(browser_data * b, WimpRedrawWindowBlock * r)
if (printing == 1) /* 1 = may force page break, 2 = don't */
{
/* Printing page split rules: First, simple "line drops off page" rule */
if (d->ldata[l].y < page_bottom)
{
if (d->ldata[l].h <= ((page_height * 100) / PrintSplitFraction)) /* (See Print.h) */
{
r->xscroll = d->ldata[l].y + d->ldata[l].h;
return;
}
}
int split_y, store;
/* ...with "line fits on *exactly*" adjustment. */
else if (
d->ldata[l].y == page_bottom &&
l + 1 < d->nlines
)
{
r->xscroll = d->ldata[l + 1].y + d->ldata[l + 1].h;
return;
}
/* Second, look ahead to keep heading lines and DT / DD lines together */
/* If we find a split point it's returned in r->xscroll (rather hacky, but */
/* it's always zero during printing otherwise so why not...?). */
if (
(l + 1 < d->nlines) &&
d->ldata[l + 1].y < page_bottom &&
(d->ldata[l + 1].h <= ((page_height * 100) / PrintSplitFraction))
print_find_splitting_point(d,
0,
l,
page_bottom,
page_height,
&split_y,
&store)
!= NULL
)
{
HStream * t1 = d->cdata[d->ldata[l].chunks].t;
HStream * t2 = d->cdata[d->ldata[l + 1].chunks].t;
if (
reformat_istext(t1) &&
(
(
((t1->style & H_MASK) != 0) &&
(
(t2->style & H_MASK) == 0 ||
!reformat_istext(t2)
)
)
||
(
reformat_istext(t2) &&
((t1->style & DT) != 0) &&
((t2->style & DD) != 0)
)
)
)
{
r->xscroll = d->ldata[l].y + d->ldata[l].h;
return;
}
}
/* Last, look behind for page break at headings */
if (l > 0 && choices.print_page_break_hx != 0)
{
int scan = l - 1;
HStream * t1 = d->cdata[d->ldata[scan].chunks].t;
HStream * t2 = d->cdata[d->ldata[l].chunks].t;
int h1;
int h2;
if (reformat_istext(t2))
{
/* The previous line might not be useful (e.g. two H2s in a row */
/* would have a dummy tag in between occuping a zero height */
/* line of its own). So we need to scan backwards to get a */
/* useful token. */
while (
t1 != NULL &&
(
reformat_istext(t1) &&
t1->text == NULL
)
&& --scan >= 0
)
t1 = d->cdata[d->ldata[scan].chunks].t;
h1 = reformat_istext(t1) ? redraw_header(t1->style) : 0;
h2 = redraw_header(t2->style);
if (
d->ldata[scan].y < wbox.ymax &&
d->ldata[scan].y + d->ldata[scan].h <= wbox.ymax
&&
(
h1 > choices.print_page_break_hx ||
h1 == 0
)
&& h2 <= choices.print_page_break_hx
&& h2 > 0
)
{
r->xscroll = d->ldata[l].y + d->ldata[l].h;
return;
}
}
r->xscroll = split_y;
return;
}
}
......@@ -3200,3 +3133,200 @@ static void print_fake_redraw(browser_data * b, WimpRedrawWindowBlock * r)
return;
}
/**************************************************************/
/* print_find_splitting_point() */
/* */
/* Service routine for print_fake_redraw and redraw_draw_r. */
/* Given a reformat cell, line number within it and page */
/* dimensions, works out if a new page should be started. */
/* */
/* Parameters: Pointer to the reformat_cell being printed */
/* (really this should always be top level); */
/* */
/* Notional y coord origin of cell in OS units; */
/* */
/* Current line number within the cell; */
/* */
/* Page bottom y coordinate in OS units; */
/* */
/* Page height in OS units; */
/* */
/* Pointer to an int updated with the y coord */
/* split point (OS units, negative down from 0). */
/* */
/* Pointer to an int updated with 1 if the */
/* inferred section should be stored through the */
/* returned token, else 0. */
/* */
/* Returns: Pointer to the token that will be used on the */
/* first line of the new page if a split point is */
/* found, with the given int updated with the y */
/* coordinate; else NULL. */
/* */
/* Assumes: All pointers are non-NULL and valid. */
/**************************************************************/
HStream * print_find_splitting_point(reformat_cell * d, int osyorg, int l, int page_bottom, int page_height,
int * split_y, int * store)
{
int page_top = page_bottom + page_height;
*store = 0;
/* Printing page split rules: First, simple "line drops off page" rule. */
/* For large lines - e.g. very big images, tables, or lines taller than */
/* the whole page - we either should, or in the latter case must, split */
/* that line. So, if the line is taller than 1/PrintSplitFraction of */
/* the page height, it will be split over the page boundary. */
if (osyorg + d->ldata[l].y < page_bottom)
{
if (d->ldata[l].h <= ((page_height * 100) / PrintSplitFraction)) /* (See Print.h) */
{
HStream * t1 = d->cdata[d->ldata[l].chunks].t;
*split_y = osyorg + d->ldata[l].y + d->ldata[l].h;
if (
choices.print_page_break_hx > 0 &&
reformat_istext(t1) &&
redraw_header(t1->style) > 0 &&
redraw_header(t1->style) <= choices.print_page_break_hx
)
*store = 1;
return t1;
}
}
/* ...with "line fits on *exactly*" adjustment. */
else if (
osyorg + d->ldata[l].y == page_bottom &&
l + 1 < d->nlines
)
{
HStream * t1 = d->cdata[d->ldata[l + 1].chunks].t;
*split_y = osyorg + d->ldata[l + 1].y + d->ldata[l + 1].h;
if (
choices.print_page_break_hx > 0 &&
reformat_istext(t1) &&
redraw_header(t1->style) > 0 &&
redraw_header(t1->style) <= choices.print_page_break_hx
)
*store = 1;
return t1;
}
/* Trying to get clever now. Here we look one line ahead, and see if */
/* this line would fall off the page. If so, then should we allow it */
/* to get seperated from the current line, or should we put *both* */
/* onto the next side? (Above caveat on fraction of page height of */
/* the line we're looking ahead to applies). */
if (
(l + 1 < d->nlines) &&
osyorg + d->ldata[l + 1].y < page_bottom &&
(d->ldata[l + 1].h <= ((page_height * 100) / PrintSplitFraction))
)
{
HStream * t1 = d->cdata[d->ldata[l].chunks].t;
HStream * t2 = d->cdata[d->ldata[l + 1].chunks].t;
/* If current line is a heading and next line isn't, or current line */
/* is a definition list term (heading) and the next line is data, */
/* then don't split up the two lines. */
if (
reformat_istext(t1) &&
(
(
((t1->style & H_MASK) != 0) &&
(
(t2->style & H_MASK) == 0 ||
!reformat_istext(t2)
)
)
||
(
((t1->style & DT) != 0) &&
((t2->style & DD) != 0)
)
)
)
{
*split_y = osyorg + d->ldata[l].y + d->ldata[l].h;
if (
choices.print_page_break_hx > 0 &&
reformat_istext(t1) &&
redraw_header(t1->style) > 0 &&
redraw_header(t1->style) <= choices.print_page_break_hx
)
*store = 1;
return t1;
}
}
/* There's also a case for look-behind. If this line is heading 1 or 2 */
/* and the previous wasn't, start a new page here. */
if (l > 0 && choices.print_page_break_hx != 0)
{
int scan = l - 1;
HStream * t1 = d->cdata[d->ldata[scan].chunks].t;
HStream * t2 = d->cdata[d->ldata[l].chunks].t;
int h1;
int h2;
if (reformat_istext(t2))
{
/* The previous line might not be useful (e.g. two H2s in a row */
/* would have a dummy tag in between occuping a zero height */
/* line of its own). So we need to scan backwards to get a */
/* useful token. */
while (
t1 != NULL &&
(
reformat_istext(t1) &&
t1->text == NULL
)
&& --scan >= 0
)
t1 = d->cdata[d->ldata[scan].chunks].t;
h1 = reformat_istext(t1) ? redraw_header(t1->style) : 0;
h2 = redraw_header(t2->style);
if (
osyorg + d->ldata[scan].y < page_top &&
osyorg + d->ldata[scan].y + d->ldata[scan].h <= page_top
&&
(
h1 > choices.print_page_break_hx ||
h1 == 0
)
&& h2 <= choices.print_page_break_hx
&& h2 > 0
)
{
*split_y = osyorg + d->ldata[l].y + d->ldata[l].h;
*store = 1;
return t2;
}
}
}
/* No split point found */
return NULL;
}
......@@ -78,7 +78,9 @@ static void redraw_button (browser_data * b, HStream * t, BBox * box, int
static void redraw_switch (browser_data * b, HStream * t, int x, int y, char * spr, WimpRedrawWindowBlock * r);
static void redraw_bullet (int x, int y, int bullet, WimpRedrawWindowBlock * r);
/* Used for printing */
/* Used for printing. Needed because redraw_token_colour takes no "noback" flag. */
/* Could add it, but it'd hit efficiency to add a parameter to such a commonly */
/* called function - a static is hacky but faster and means far fewer changes. */
static int use_noback = 0;
......@@ -272,14 +274,18 @@ int redraw_token_colour(browser_data * b, HStream * t)
if (ISLINK(t))
{
/* If tokens are highlighted, return the appropriate colour */
if (b->highlight) return (b->use_source_cols ? b->followed_colour : choices.followed_colour);
/* If tokens are selected, return the appropriate colour */
if (redraw_selected(b, t)) return (b->use_source_cols ? b->selected_colour : choices.selected_colour);
/* If the token has attached specific colour information, return that */
if ((t->type & TYPE_COLOURED) && b->use_source_cols) return (t->colour << 8);
/* If tokens are highlighted, return the appropriate colour */
if (b->highlight) return (b->use_source_cols ? b->followed_colour : choices.followed_colour);
/* If the token has been followed in the past, give the used colour */
/* - otherwise give the unfollowed link colour. */
......@@ -1618,176 +1624,30 @@ _kernel_oserror * redraw_draw_r(int toplevel, int xorg, int yorg, browser_data *
/* to the function. The printing routines use this to work */
/* out where to start the next redraw from. */
/* */
/* However, for large lines - e.g. very big images, tables, */
/* or lines taller than the whole page - we either should, */
/* or in the latter case must, split that line. So, if the */
/* line is taller than 1/PrintSplitFraction of the page */
/* height, will indeed be split over the page boundary. */
/* */
/* If you add code here, remember that xscroll must be */
/* filled in eventually or the printing loop will exit, */
/* assuming there's no more page to draw. */
if (osyorg + d->ldata[l].y < page_bottom)
{
if (d->ldata[l].h <= ((page_height * 100) / PrintSplitFraction)) /* (See Print.h) */
{
HStream * t1 = d->cdata[d->ldata[l].chunks].t;
r->xscroll = osyorg + d->ldata[l].y + d->ldata[l].h;
HStream * split_token;
int split_y;
int store;
/* Possibly store inferred section */
split_token = print_find_splitting_point(d,
osyorg,
l,
page_bottom,
page_height,
&split_y,
&store);
if (
choices.print_page_break_hx > 0 &&
reformat_istext(t1) &&
redraw_header(t1->style) > 0 &&
redraw_header(t1->style) <= choices.print_page_break_hx
)
redraw_read_section(b, t1);
return NULL;
}
/* The effective 'else' case here has to be handled at the end */
/* of printing, or you've just scrolled the page a long way to */
/* right... */
}
/* The unusual one-off case where the line exactly fits on the page */
else if (
osyorg + d->ldata[l].y == page_bottom &&
l + 1 < d->nlines
)
if (split_token != NULL)
{
HStream * t1 = d->cdata[d->ldata[l + 1].chunks].t;
r->xscroll = osyorg + d->ldata[l + 1].y + d->ldata[l + 1].h;
/* Possibly store inferred section */
r->xscroll = split_y;
if (
choices.print_page_break_hx > 0 &&
reformat_istext(t1) &&
redraw_header(t1->style) > 0 &&
redraw_header(t1->style) <= choices.print_page_break_hx
)
redraw_read_section(b, t1);
if (store == 1) redraw_read_section(b, split_token);
return NULL;
}
/* Trying to get clever now. Here we look one line ahead, and see if */
/* this line would fall off the page. If so, then should we allow it */
/* to get seperated from the current line, or should we put *both* */
/* onto the next side? (Above caveat on fraction of page height of */
/* the line we're looking ahead to applies). */
if (
(l + 1 < d->nlines) &&
osyorg + d->ldata[l + 1].y < page_bottom &&
(d->ldata[l + 1].h <= ((page_height * 100) / PrintSplitFraction))
)
{
HStream * t1 = d->cdata[d->ldata[l].chunks].t;
HStream * t2 = d->cdata[d->ldata[l + 1].chunks].t;
/* If current line is a heading and next line isn't, or current line */
/* is a definition list term (heading) and the next line is data, */
/* then don't split up the two lines. */
if (
reformat_istext(t1) &&
(
(
((t1->style & H_MASK) != 0) &&
(
(t2->style & H_MASK) == 0 ||
!reformat_istext(t2)
)
)
||
(
reformat_istext(t2) &&
((t1->style & DT) != 0) &&
((t2->style & DD) != 0)
)
)
)
{
r->xscroll = osyorg + d->ldata[l].y + d->ldata[l].h;
/* Possibly store inferred section */
/* Possibly store inferred section */
if (
choices.print_page_break_hx > 0 &&
reformat_istext(t1) &&
redraw_header(t1->style) > 0 &&
redraw_header(t1->style) <= choices.print_page_break_hx
)
redraw_read_section(b, t1);
return NULL;
}
}
/* There's also a case for look-behind. If this line is heading 1 or 2 */
/* and the previous wasn't, start a new page here. */
if (l > 0 && choices.print_page_break_hx != 0)
{
int scan = l - 1;
HStream * t1 = d->cdata[d->ldata[scan].chunks].t;
HStream * t2 = d->cdata[d->ldata[l].chunks].t;
int h1;
int h2;
if (reformat_istext(t2))
{
/* The previous line might not be useful (e.g. two H2s in a row */
/* would have a dummy tag in between occuping a zero height */
/* line of its own). So we need to scan backwards to get a */
/* useful token. */
while (
t1 != NULL &&
(
reformat_istext(t1) &&
t1->text == NULL
)
&& --scan >= 0
)
t1 = d->cdata[d->ldata[scan].chunks].t;
h1 = reformat_istext(t1) ? redraw_header(t1->style) : 0;
h2 = redraw_header(t2->style);
if (
osyorg + d->ldata[scan].y < wbox.ymax &&
osyorg + d->ldata[scan].y + d->ldata[scan].h <= wbox.ymax
&&
(
h1 > choices.print_page_break_hx ||
h1 == 0
)
&& h2 <= choices.print_page_break_hx
&& h2 > 0
)
{
r->xscroll = osyorg + d->ldata[l].y + d->ldata[l].h;
/* Store inferred section */
redraw_read_section(b, t2);
return NULL;
}
}
}
}
/* Put the base address of the line's chunks into cp, */
......@@ -2087,6 +1947,13 @@ _kernel_oserror * redraw_draw_r(int toplevel, int xorg, int yorg, browser_data *
t_noback,
nocontent);
/* Restore print loop noback flag. Since noback is a parameter it stacks and */
/* unstacks as we call the redraw function recursively, but the static */
/* use_noback doesn't. So we have to ensure it is kept in step with noback */
/* after any recursive redraw calls. */
use_noback = noback;
/* Restore the WimpRedrawWindowBlock redraw rectangle */
r->redraw_area = oldrect;
......
......@@ -97,11 +97,6 @@
#define PrintHeaderAndFooterHeightMultiplier (15)
/* Width adjust to avoid oblique fonts falling outside left/right */
/* margins and so-on. OS unit inset from left. */
#define PrintHeaderAndFooterWidthAdjust (4)
/* Function prototypes */
_kernel_oserror * print_open_for (browser_data * b, ObjectId parent);
......@@ -115,3 +110,5 @@ void print_print (const char * path);
void print_abort_print (void);
void print_return_dialogue_info (ObjectId * self, ObjectId * window, ObjectId * ancestor, browser_data ** ancestor_b);
HStream * print_find_splitting_point (reformat_cell * d, int osyorg, int l, int page_bottom, int page_height, int * split_y, int * store);
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment