Commit 8c9a9091 authored by Andrew Hodgkinson's avatar Andrew Hodgkinson
Browse files

Added support for HTMLLib HttpEndParse call.

Text items with no VALUE specified in the HTML were not cleared on
hitting a Reset button as the text field of the token is NULL; fixed.
SELECT lists with no default selection item were not being changed
on hitting a Reset button; fixed. In radio groups with no default
selection specified, no item will be selected. This goes against
the HTML 2 spec but allows broken Navigator-esque forms behaviour.
In consequence, radios can be deselected by clicking on the same
one twice. I'd fixed the flickering experienced when doing this
recently, but that, now, is irrelevant, since the state of a radio
must always change.

Reformatter's new 'find width of a SELECT field' didn't account for
the width of <none> and <many> items, and now does (particularly
important for broken items with no OPTION contents).

Under certain circumstances, illegally named targets would open in the
ancestor rather than a new window - a deliberate decision in the code,
but now reversed due to a test suite failure; they'll open in a new
window instead.

Altered the left hand indent handling for lists so that headings and
body text follow the Navigator 48 pixel indent and the bullet point
items drop to the left of the left hand margin, rather than sitting
on the margin with the text indented to the right.

Tightened up the hotlist_load_directory checking of URLs, so that
only those with '://' in - i.e. look fully specified - are accepted.
HTML files are loaded into a new directory now.

Items without a descriptive title in hotlist_new_url will have the URL
substituted in instead. White space before and after descriptions and
after URLs is stripped. Directories with zero length names or null
strings (after white space is stripped) will still be created, with a
generic name (see Messages, token 'HotlistUntitled').
parent 26e079aa
......@@ -120,7 +120,7 @@ LeftMargin:0
RightMargin:0
QuoteMargin:0
Leading:4
LeftIndent:12800
LeftIndent:38400
#LeftMargin:1600
#RightMargin:6400
#QuoteMargin:19200
......
No preview for this file type
......@@ -119,7 +119,7 @@ LeftMargin:1600
RightMargin:6400
QuoteMargin:19200
Leading:4
LeftIndent:12800
LeftIndent:38400
# Fetch controls
# ==============
......
......@@ -119,7 +119,7 @@ LeftMargin:1600
RightMargin:6400
QuoteMargin:19200
Leading:4
LeftIndent:12800
LeftIndent:38400
# Fetch controls
# ==============
......
......@@ -146,7 +146,7 @@ static int encoding_tick_entry(ObjectId o, int enc, int state)
/* object. */
/*************************************************/
static void encoding_prepare_menu(ObjectId o, browser_data *b)
static void encoding_prepare_menu(ObjectId o, browser_data * b)
{
menu_set_tick(0, o, 0x11FFF, b->encoding_priority != priority_user);
......
......@@ -1275,7 +1275,7 @@ void fetch_fetcher(browser_data * b)
/* We're not waiting, but if there's also no data left to fetch, */
/* then we're just chugging through the list of tokens that the */
/* library is generating, telling various bits of the code about */
/* library has generated, telling various bits of the code about */
/* their contents (e.g. a new image, a new form). In this case, */
/* change the fetch status so the status bar can reflect the new */
/* situation. */
......
......@@ -517,7 +517,7 @@ _kernel_oserror * html_close(int handle)
if (tl & (1u<<12)) Printf("html_close: free block %p for 'context' field of 'urlstat' structure\n",up->context);
#endif
free(up->context);
HtmlEndParse(up->context);
up->context = NULL;
}
......@@ -694,6 +694,7 @@ _kernel_oserror * html_get_next_token(browser_data * b, unsigned int handle, int
&status, /* Protocol status */
&r, /* Number of bytes read */
remaining); /* Number of bytes left to get */
/* Deal with cookies */
if (!e && (status & (1u<<16))) e = cookies_process_cookie(b);
......@@ -1674,18 +1675,13 @@ _kernel_oserror * html_get_next_token(browser_data * b, unsigned int handle, int
/* was not flagged as being in progress. */
}
/* If no data has been fetched from the url_read_data call */
/* from earlier on, and there hasn't been an error flagged */
/* so far, and both the general 'authorisation taking place' */
/* and urlstat-based 'authorisation in progress' flags are */
/* clear, ask the URL module for its current status. If it */
/* says it has finished (which would explain this set of */
/* circumstances - basically, having no data from the */
/* url_read_data call but nothing else is wrong), set the */
/* urlstat structure flag to say fetching is no longer in */
/* progress. */
if (!r && !e && up->authorised != 1 && !authorising)
/* If we're not in the middle of authorisation, there hasn't */
/* been an error, and the urlstat structure for the fetch */
/* flags that fetching is still in progress, ask the URL */
/* module if things are finished yet. If so, do the relevant */
/* tidying up and unset the 'fetch in progress' flag. */
if (!e && up->authorised != 1 && !authorising && up->fetching)
{
int s;
......@@ -1696,7 +1692,16 @@ _kernel_oserror * html_get_next_token(browser_data * b, unsigned int handle, int
}
else s = URL_Status_Done; /* Internal URLs 'fetch' immediately */
if (s & URL_Status_Done) up->fetching = 0;
if (s & URL_Status_Done)
{
up->fetching = 0;
if (up->context)
{
HtmlEndParse(up->context);
up->context = NULL;
}
}
}
/* If we've been passed somewhere to put the size of the store, */
......
......@@ -1155,10 +1155,10 @@ _kernel_oserror * fm_putsl(fm_face handle, int x, int y, char * s, int chars, in
/* the terminator wrote over whther or not */
/* there is an error. */
if (chars < strlen(s))
if (s[chars] != '\0')
{
c = s[chars];
s[chars] = 0;
s[chars] = '\0';
e = fm_puts(handle,x,y,s,os,blend);
......
......@@ -567,8 +567,8 @@ static _kernel_oserror * form_validate_select(browser_data * b, HStream * tp, in
/* */
/* If more than one is selected, all but the */
/* last are deselected (unless the passed token */
/* is selected). If none are selected, the */
/* passed token is selected. */
/* is selected). If none are selected, that's */
/* allowed (Netscape Navigator - hmph). */
/* */
/* This behaviour is important when loading */
/* forms as it ensures that the correct default */
......@@ -580,10 +580,6 @@ static _kernel_oserror * form_validate_select(browser_data * b, HStream * tp, in
/* also ensures sensible behaviour when the user */
/* clicks on the selected button. */
/* */
/* If the token passed in is selected, it will */
/* stay selected. This ensures that clicking on */
/* an already selected radio works. */
/* */
/* This function initiates appropriate redraws. */
/* */
/* Parameters: Pointer to a browser_data struct */
......@@ -672,19 +668,6 @@ static _kernel_oserror * form_validate_radio(browser_data * b, HStream * token)
fp = (form_field *) (((int) fp) + fp->header.size * 4);
}
/* If no items were found selected, find the record for the token */
/* given tothe function and selected it. */
if (!foundone)
{
fp = form_find_record(b, token, 0);
if (!fp) return NULL;
fp->value.checked = 1;
browser_update_token(b, fp->header.token, 0, 0);
}
/* Finished */
return NULL;
......@@ -845,7 +828,7 @@ _kernel_oserror * form_put_field(browser_data * b, HStream * token, char * value
/* If the 'value' parameter passed to the function is NULL, the */
/* item will be deselected, else it will be selected. */
changed = ((!!value) != (fp->value.checked));
changed = ((!value) != (!fp->value.checked));
fp->value.checked = !!value;
}
break;
......@@ -856,7 +839,7 @@ _kernel_oserror * form_put_field(browser_data * b, HStream * token, char * value
{
/* Set the item's selected state as for option boxes above */
changed = ((!!value) != (fp->value.checked));
changed = ((!value) != (!fp->value.checked));
fp->value.checked = !!value;
/* For radios, need to make sure only one is selected */
......@@ -874,13 +857,13 @@ _kernel_oserror * form_put_field(browser_data * b, HStream * token, char * value
/* If value is NULL, change it to be an empty string instead - */
/* avoids having to keep checking for (value == NULL) later. */
value = value ? value : "";
value = value ? value : fp->value.select.selection;
/* Try to find the first selected item in the field; */
/* if not found, point to the first item. */
o = strchr(fp->value.select.selection, FORM_SELCHAR);
if (!o) o = fp->value.select.selection;
o = strchr(value, FORM_SELCHAR);
if (!o) o = value;
/* If the value passed to the function differs from that */
/* already set for the field, change to the new value */
......@@ -898,7 +881,7 @@ _kernel_oserror * form_put_field(browser_data * b, HStream * token, char * value
/* (some SELECT field types only allow one item to be */
/* selected at any one time). */
form_validate_select(b, token, o - fp->value.select.selection);
form_validate_select(b, token, o - value);
}
break;
}
......@@ -984,14 +967,15 @@ static void form_build_selection(const int * value, char * selection)
/* */
/* Add a new field to the last form in the list */
/* (always the right one due to the sequential */
/* nature of HTML). The value is initialised as */
/* passed in; for radio and checkbox this is */
/* taken to be NULL = not selected, otherwise */
/* selected. For SELECT fields, this is taken as */
/* a pointer to the value part of the token; */
/* this will be converted to a zero terminated */
/* list of bytes where FORM_UNSELCHAR = not */
/* selected, FORM_SELCHAR = selected. */
/* nature of HTML forms). The value is */
/* initialised as passed in; for radios and */
/* checkboxes this is taken to be NULL = not */
/* selected, otherwise selected. For SELECT */
/* fields, this is taken as a pointer to the */
/* value part of the token; this will be */
/* converted to a zero terminated list of bytes */
/* where FORM_UNSELCHAR = not selected, */
/* FORM_SELCHAR = selected. */
/* */
/* Parameters: Pointer to a browser_data struct */
/* relevant to the form; */
......@@ -1216,7 +1200,7 @@ static char * form_select_text(browser_data * b, HStream * tp, char * selection)
f = (char *) p;
}
/* Move past the selected/unselected inidicator char */
/* Move past the selected/unselected indicator char */
p++;
......@@ -1368,7 +1352,7 @@ static _kernel_oserror * form_reset_form(browser_data * b, HStream * token)
{
/* Value is a simple text string for these types */
value = tp->text;
value = tp->text ? tp->text : "";
}
break;
......@@ -2662,6 +2646,7 @@ static int form_encode_flex_data(void ** data, const char * enctype, int start_a
!isalnum((int) *p)
&& *p != ' '
&& *p != '_'
&& *p != ENCODE_DATASEP
&& *p != ENCODE_FIELDSEP
&& *p != ENCODE_VALUESEP
......@@ -3251,9 +3236,9 @@ _kernel_oserror * form_click_field(browser_data * b, HStream * token, int mode,
case form_password: e = form_start_textarea_edit(b, token, mode);
break;
/* For check (option) boxes and radios, toggle values as appropriate */
/* For check (option) boxes and radios, toggle or values as appropriate */
case form_checkbox: /* same as form_radio: no break */
case form_checkbox: /* As for radios, so no 'break' */
case form_radio: e = form_put_field(b, token, (char *) !fp->value.checked, 1);
break;
......
......@@ -2492,15 +2492,11 @@ browser_data * frames_find_target(browser_data * b, HStream * t)
)
return b;
/* If all else fails, want to try getting to the highest possible */
/* level - after all, accidentally opening what was meant to be a */
/* full size page inside some tiny frame would be pretty bad...! */
/* If all else fails, we don't recognise the name or it is */
/* illegal. Safest to open in a new window, leaving the */
/* original document intact. */
ancestor = b->ancestor;
if (!ancestor) ancestor = b->real_parent;
if (!ancestor) ancestor = b;
return ancestor;
return NULL;
}
/*************************************************/
......
......@@ -576,7 +576,24 @@ static _kernel_oserror * hotlist_new_directory(hotlist_item * parent, char * dir
hotlist_item * item;
_kernel_oserror * e;
if (!directory_name) return NULL;
lookup_token("HotlistUntitled:(Untitled)",0,0);
if (!directory_name) directory_name = tokens;
else
{
while (*directory_name && *directory_name <= ' ') directory_name ++;
if (!*directory_name) directory_name = tokens;
else
{
int len = strlen(directory_name) - 1;
while (len && directory_name[len] <= ' ') len--;
if (!len) directory_name = tokens;
else directory_name[len + 1] = '\0';
}
}
/* Allocate space for the item and its name */
......@@ -670,6 +687,33 @@ static _kernel_oserror * hotlist_new_url(hotlist_item * parent, unsigned int pos
hotlist_item * item;
_kernel_oserror * e;
/* Do we have a URL string? */
if (!url) return NULL;
while (*url && *url <= ' ') url++;
if (!*url) return NULL;
/* Do we have a useful title string? */
if (!url_description) url_description = url;
else
{
while (*url_description && *url_description <= ' ') url_description ++;
if (!*url_description) url_description = url;
else
{
int len = strlen(url_description) - 1;
while (len && url_description[len] <= ' ') len--;
if (!len) url_description = url;
else url_description[len + 1] = '\0';
}
}
/* Allocate a new hotlist_item structure */
if ((item = malloc(sizeof(hotlist_item))) == NULL)
......@@ -1920,8 +1964,6 @@ _kernel_oserror * hotlist_add(char * description, char * url, int at_bottom)
position = at_bottom ? HOTLIST_POSITION_END : HOTLIST_POSITION_BEGINNING;
if (!description || !*description) description = lookup_token("HotlistUntitled:(Untitled)",0,0);
/* Add the item and ensure the window extent etc. is correct */
e = hotlist_new_url(hotlist_root,
......@@ -3268,19 +3310,24 @@ static _kernel_oserror * hotlist_load_directory(FILE * fileptr, hotlist_item * t
str_ptr = strtok(NULL, "><");
/* Add this item */
/* Get ready to add this item, provided that the URL string has */
/* '://' in - i.e. looks fully specified */
if (target_type == 0)
if (strstr(url, "://"))
{
e = hotlist_new_url(target, HOTLIST_POSITION_END, str_ptr, url);
target_type = 1;
}
else
{
e = hotlist_new_url(target, HOTLIST_POSITION_AFTER, str_ptr, url);
if (target_type == 0)
{
e = hotlist_new_url(target, HOTLIST_POSITION_END, str_ptr, url);
target_type = 1;
}
else
{
e = hotlist_new_url(target, HOTLIST_POSITION_AFTER, str_ptr, url);
}
if (e) goto hotlist_load_directory_exit; /* (See near end of function) */
target = hotlist_newitem;
}
if (e) goto hotlist_load_directory_exit; /* (See near end of function) */
target = hotlist_newitem;
}
/* Treat any '<ul>' tags as the start of a new directory. The name comes */
......@@ -6253,8 +6300,6 @@ _kernel_oserror * hotlist_add_position(int x, int y, char * description, char *
int winx, winy;
int top, position;
if (!description || !*description) description = lookup_token("HotlistUntitled:(Untitled)",0,0);
/* Calculate window relative coordinates */
RetError(window_get_wimp_handle(0,
......@@ -6359,6 +6404,7 @@ _kernel_oserror * hotlist_add_html_file(int x, int y, char * path)
unsigned int item_height, item_dir_width, item_url_width;
int winx, winy;
int top, position;
char * dirname;
/* Calculate window relative coordinates */
......@@ -6404,6 +6450,12 @@ _kernel_oserror * hotlist_add_html_file(int x, int y, char * path)
targetitem = hotlist_root;
}
dirname = strrchr(path, '.');
if (dirname) dirname ++;
if (!dirname || !*dirname) dirname = lookup_token("HotlistUntitled:(Untitled)",0,0);
RetError(hotlist_new_directory(targetitem, dirname, position, &newitem));
/* Open the file */
fileptr = fopen(path, "r");
......@@ -6420,52 +6472,21 @@ _kernel_oserror * hotlist_add_html_file(int x, int y, char * path)
return &erb;
}
/* Load it, adding to the bottom of the root directory */
/* Load it, adding to the new directory */
e = hotlist_load_directory(fileptr, hotlist_root);
e = hotlist_load_directory(fileptr, newitem);
fclose(fileptr);
/* Clear all of the various flags for redraw, */
/* selection etc. now that we have a new */
/* hotlist. */
hotlist_clear_flags(hotlist_root, hl_ALL, HOTLIST_G_REDRAW_NOW);
if (e) return e;
/* Move to the intended load position; first, find */
/* the item we just added, then move it to the */
/* relevant position relative to the target item, */
/* as worked out above. */
newitem = hotlist_root->data.directory_content;
while (newitem && newitem->next) newitem = newitem->next;
if (newitem)
{
/* Need to set the selected flags on the directory, or hotlist_move_item */
/* will think we're moving only part of it, and will end up just copying */
/* the directory item. */
hotlist_set_flags(newitem, hl_ALL, HOTLIST_G_IS_SELECTED);
RetError(hotlist_move_item(newitem, targetitem, position));
/* Now deselect it... */
hotlist_clear_flags(newitem, hl_ALL, HOTLIST_G_IS_SELECTED);
}
/* Handle redraw */
hotlist_preopen();
/* Optimise the redraw to do as little as possible depending */
/* upon where in the list the item was added. */
hotlist_set_flags(hotlist_root, hl_ALL, HOTLIST_G_REDRAW_NOW);
RetError(hotlist_redraw_items(top,
hotlist_count_displayed_items(hotlist_root->data.directory_content)));
RetError(hotlist_redraw_now());
/* Exit through the 'has modified' routine */
......
......@@ -75,7 +75,7 @@ static void image_remove_all_data (browser_data * b, int ima
static void image_delay (browser_data * b, int image);
static void image_abandon (browser_data * b, int image);
static void image_delete_image_entry (int image);
static void image_refetch (browser_data * b, int image, int priority);
static void image_refetch (browser_data * b, int image, int priority, int redraw);
static _kernel_oserror * image_update_area (browser_data * b, int x, int y, BBox * ubox, int image, int redraw);
static _kernel_oserror * image_update_image (browser_data * b, int image, BBox * box);
......@@ -1820,10 +1820,15 @@ _kernel_oserror * image_discard(browser_data * b)
/* Value to set Priority flag to (so */
/* that if 'show foreground images' */
/* is turned off, the image will */
/* override it). */
/* override it); */
/* */
/* 1 to redraw the image, 0 to not */
/* bother (e.g. for many images, */
/* may want to redraw the whole */
/* window instead). */
/*************************************************/
static void image_refetch(browser_data * b, int image, int priority)
static void image_refetch(browser_data * b, int image, int priority, int redraw)
{
int i;
......@@ -1880,7 +1885,8 @@ static void image_refetch(browser_data * b, int image, int priority)
idata[image].priority = priority;
idata[image].hadfirst = 0;
image_update_image(b, image, NULL);
if (redraw) image_update_image(b, image, NULL);
}
/* Deal with all cross referencers of the base image */
......@@ -1891,7 +1897,8 @@ static void image_refetch(browser_data * b, int image, int priority)
{
idata[i].priority = priority;
idata[i].hadfirst = 0;
image_update_image(b, i, NULL);
if (redraw) image_update_image(b, i, NULL);
}
}
}
......@@ -1918,7 +1925,7 @@ void image_reload(browser_data * b, HStream * token)
if (image < 0) return;
image_refetch(b, image, 1);
image_refetch(b, image, 1, 1);
}
/*************************************************/
......@@ -1926,7 +1933,10 @@ void image_reload(browser_data * b, HStream * token)
/* */
/* If image loading has been suspended for any */
/* reason, it can be resumed by calling this */
/* function. */
/* function. Any images already loaded will be */
/* reshown. The priority flag for images is not */
/* set, so the browser must be set to display */
/* foreground images for anything to show up. */
/* */
/* Parameters: Pointer to a browser_data struct */
/* relevant to the images; */
......@@ -1963,7 +1973,7 @@ void image_restart_fetches(browser_data * b, int foreground, int background)
(idata[image].background && background) ||
(!idata[image].background && foreground)
)
image_refetch(idata[image].owner, image, 0);
image_refetch(idata[image].owner, image, 0, 0);
}
}
}
......
......@@ -483,7 +483,7 @@ static void initialise_app(void)
/* Find out window tool sizes */
ChkError(windows_initialise_tool_sizes());
show_error(windows_initialise_tool_sizes());
}
/*************************************************/
......@@ -1113,6 +1113,22 @@ int main(int argc, char * argv[])
}
}
#else
/* Non-debug builds have a WimpSlot close to the actual startup */
/* requirements. Debug builds have a huge slotsize because of */
/* all of the debug information, despite this being copied away */
/* by the debugger on startup. This leaves a very large free */
/* chunk within the WimpSlot size in which malloc may operate, */
/* and thus creates a distinctly different environment for the */
/* memory system in a debug build. */
/* */
/* To try and get closer to the non-debug memory usage, TRACE */
/* builds will malloc the following large block in an attempt */
/* to soak up that initial free space. */
malloc(2*1024*1024);
#endif
signal(SIGOSERROR, catch_errors); /* OS error */
......
......@@ -365,11 +365,11 @@ int redraw_margin(browser_data * b, reformat_cell * d, HStream * t)
if (t->tag == TABLE && ISBODY(t)) return redraw_left_margin(b, d);
/* Indent more depending on the header type, if the */
/* HStream represents a header. */
if (redraw_header(s)) return i + redraw_left_margin(b, d);
// if (redraw_header(s)) return i + redraw_left_margin(b, d);
//
// /* Indent more depending on the header type, if the */
// /* HStream represents a header. */
//
// if (redraw_header(s) == 1 || redraw_header(s) == 2) return (i + 4);
// if (redraw_header(s) == 3) return (i + 16 + 4);
// if (redraw_header(s) == 4 || redraw_header(s) == 5) return (i + 32 + 4);
......
......@@ -356,6 +356,37 @@ static _kernel_oserror * reformat_token_width(reformat_width_data * w, unsigned
width = 0;
length = 0; /* Not used, but stops compiler giving warnings */
/* Some fields can hold the selNONE or selMANY text, as well */
/* as the menu item texts. */
if (HtmlSELECTmultiple(w->tp) || *p == 0xff)
{
e = fm_get_string_width(h,
lookup_token("selNONE:<None>",0,0),
Reformat_AsWideAsPossible_MP,
strlen(tokens),
-1,
&temp,
&width);
if (!e && width > l) l = width;
}
if (HtmlSELECTmultiple(w->tp))
{
e = fm_get_string_width(h,
lookup_token("selMANY:<Many>",0,0),
Reformat_AsWideAsPossible_MP,
strlen(tokens),
-1,
&temp,
&width);
if (!e && width > l) l = width;
}
/* Look for the width of the widest OPTION field */
while (*p != 0xff)
{
p++;
......@@ -375,12 +406,17 @@ static _kernel_oserror * reformat_token_width(reformat_width_data * w, unsigned
break;
}
/* Record if this is the widest and skip to the next field */
if (width > l) l = width;
p += strlen(p) + 1;
p += strlen(p) + 1;
}
/* Set the width and flag that we've done the calculation */
/* already so code lower down doesn't try. */
w->width = l + extra;
done = 1;
......
......@@ -24,10 +24,10 @@
/* Function prototypes */
int encoding_select (int eventcode,ToolboxEvent * event,IdBlock * idb,void * handle);
int encoding_from_document_select (int eventcode,ToolboxEvent * event,IdBlock * idb,void * handle);
int encoding_show_menu (int eventcode,ToolboxEvent * event,IdBlock * idb,void * handle);
int encoding_select (int eventcode, ToolboxEvent * event, IdBlock * idb, void * handle);
int encoding_from_document_select (int eventcode, ToolboxEvent * event, IdBlock * idb, void * handle);
int encoding_show_menu (int eventcode, ToolboxEvent * event, IdBlock * idb, void * handle);
void encoding_changed_by_meta (int encoding, void * handle);
void encoding_update_menus (browser_data *d);
void encoding_update_menus (browser_data * b);
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