From e36770dc7c929f48f18d727260461d1efa985351 Mon Sep 17 00:00:00 2001
From: Kevin Bracey <kbracey@gitlab.riscosopen.org>
Date: Fri, 1 Aug 1997 09:00:59 +0000
Subject: [PATCH] Made INPUT type=image work

---
 c/Browser    |  16 +++--
 c/Fetch      |  25 +++----
 c/FontManage |  40 +++++------
 c/Forms      | 189 ++++++++++++++++++++++++++++-----------------------
 c/Handlers   |  67 ++++++++++++------
 c/Images     |   4 +-
 c/Redraw     |  66 ++++++++++--------
 c/Reformat   |  92 ++++++++++++++++---------
 h/Browser    |  14 ++--
 h/FontManage |   4 +-
 h/Forms      |   4 +-
 h/Reformat   |   2 +-
 12 files changed, 302 insertions(+), 221 deletions(-)

diff --git a/c/Browser b/c/Browser
index 4e3b9d1..0c55ac3 100644
--- a/c/Browser
+++ b/c/Browser
@@ -1249,7 +1249,8 @@ int browser_move_selection(browser_data * b, int key)
          )
          form_click_field(owner,
                           new,
-                          key == akbd_RightK ? 1 : 2);
+                          key == akbd_RightK ? 1 : 2,
+                          0, 0);
 
       /* Turn the pointer off, and reset the check to see if */
       /* the user has moved it manually.                     */
@@ -1303,7 +1304,9 @@ static int browser_navigate_map(browser_data * b, int key)
   {
     tp = browser_get_pointer_token(b, &p, NULL, NULL);
 
-    if (tp && redraw_selected(b, tp) && (tp->style & IMG) && (tp->type & TYPE_ISMAP))
+    if (tp && redraw_selected(b, tp) &&
+        (((tp->style & IMG) && (tp->type & TYPE_ISMAP)) ||
+         ((tp->style & INPUT) && HtmlINPUTtype(tp) == inputtype_IMAGE)))
     {
       int       last_move = 4;
       int       last_key, start_key;
@@ -1676,7 +1679,9 @@ int browser_pointer_check(int eventcode, WimpPollBlock * b, IdBlock * idb, brows
         if ((tp->style & IMG) && (tp->type & TYPE_ISMAP)) mouse_set_pointer_shape(Mouse_Shape_Map);
         else                                              mouse_set_pointer_shape(Mouse_Shape_Link);
       }
-      else mouse_set_pointer_shape(Mouse_Shape_Normal);
+      else if ((tp->style & INPUT) &&
+               HtmlINPUTtype(tp) == inputtype_IMAGE)      mouse_set_pointer_shape(Mouse_Shape_Link);
+      else                                                mouse_set_pointer_shape(Mouse_Shape_Normal);
     }
 
     /* If the mouse pointer is on, then update the status bar */
@@ -2010,13 +2015,14 @@ static HStream * browser_get_pointer_token_r(browser_data * b, reformat_cell * c
 
       /* If the token represents an image... */
 
-      else if (tp->style & IMG)
+      else if ((tp->style & IMG) ||
+               ((tp->style & INPUT) && HtmlINPUTtype(tp) == inputtype_IMAGE))
       {
         reformat_get_image_size(b, tp, &box);
 
         /* Correct for the border size, if the image is a link */
 
-        if (ISLINK(tp))
+        if (ISLINK(tp) && (tp->style & IMG))
         {
           int b;
 
diff --git a/c/Fetch b/c/Fetch
index e272940..3c841f7 100644
--- a/c/Fetch
+++ b/c/Fetch
@@ -219,8 +219,9 @@ void * fetch_token_data_address(browser_data * b, HStream * token)
 {
   /* No data for horizontal rules or images */
 
-  if (token->style & HR)  return NULL;
-  if (token->style & IMG) return NULL;
+  if (token->style & HR)                                                 return NULL;
+  if (token->style & IMG)                                                return NULL;
+  if ((token->style & INPUT) && HtmlINPUTtype(token) == inputtype_IMAGE) return NULL;
 
   /* Otherwise, return a pointer to the text */
 
@@ -431,16 +432,16 @@ void fetch_preprocess_token(browser_data * b, HStream * tptr)
 
       if (tptr->style & INPUT)
       {
-        switch(tptr->type&TYPE_RESET)
+        switch(HtmlINPUTtype(tptr))
         {
-          case TYPE_TEXT:    if (fetch_chkerror(b, form_new_field(b, tptr, form_text,     tptr->text                           ))) return; break;
-          case TYPE_PASSWORD:if (fetch_chkerror(b, form_new_field(b, tptr, form_password, tptr->text                           ))) return; break;
-          case TYPE_CHECKBOX:if (fetch_chkerror(b, form_new_field(b, tptr, form_checkbox, (char *) (tptr->type & TYPE_CHECKED) ))) return; break;
-          case TYPE_RADIO:   if (fetch_chkerror(b, form_new_field(b, tptr, form_radio,    (char *) (tptr->type & TYPE_CHECKED) ))) return; break;
-          case TYPE_IMAGE:   if (fetch_chkerror(b, form_new_field(b, tptr, form_image,    NULL                                 ))) return; break;
-          case TYPE_HIDDEN:  if (fetch_chkerror(b, form_new_field(b, tptr, form_hidden,   NULL                                 ))) return; break;
-          case TYPE_SUBMIT:  if (fetch_chkerror(b, form_new_field(b, tptr, form_submit,   NULL                                 ))) return; break;
-          case TYPE_RESET:   if (fetch_chkerror(b, form_new_field(b, tptr, form_reset,    NULL                                 ))) return; break;
+          case inputtype_TEXT:    if (fetch_chkerror(b, form_new_field(b, tptr, form_text,     tptr->text                      ))) return; break;
+          case inputtype_PASSWORD:if (fetch_chkerror(b, form_new_field(b, tptr, form_password, tptr->text                      ))) return; break;
+          case inputtype_CHECKBOX:if (fetch_chkerror(b, form_new_field(b, tptr, form_checkbox, (char *) HtmlINPUTchecked(tptr) ))) return; break;
+          case inputtype_RADIO:   if (fetch_chkerror(b, form_new_field(b, tptr, form_radio,    (char *) HtmlINPUTchecked(tptr) ))) return; break;
+          case inputtype_IMAGE:   if (fetch_chkerror(b, form_new_field(b, tptr, form_image,    NULL                            ))) return; break;
+          case inputtype_HIDDEN:  if (fetch_chkerror(b, form_new_field(b, tptr, form_hidden,   NULL                            ))) return; break;
+          case inputtype_SUBMIT:  if (fetch_chkerror(b, form_new_field(b, tptr, form_submit,   NULL                            ))) return; break;
+          case inputtype_RESET:   if (fetch_chkerror(b, form_new_field(b, tptr, form_reset,    NULL                            ))) return; break;
         }
       }
 
@@ -455,7 +456,7 @@ void fetch_preprocess_token(browser_data * b, HStream * tptr)
 
       if ((tptr->style) & SELECT)
       {
-        if (fetch_chkerror(b, form_new_field(b, tptr, form_select, tptr->value))) return;
+        if (fetch_chkerror(b, form_new_field(b, tptr, form_select, (char *)HtmlSELECToptions(tptr)))) return;
       }
 
       b->formflag = 1;
diff --git a/c/FontManage b/c/FontManage
index 50b9ec0..0ea79e1 100644
--- a/c/FontManage
+++ b/c/FontManage
@@ -981,7 +981,7 @@ _kernel_oserror * fm_set_font_colour(fm_face h, int fore, int back)
 /*             Font Manager earlier than v3.37.  */
 /*************************************************/
 
-_kernel_oserror * fm_puts(fm_face h, int x, int y,char * s, int os, int blend)
+_kernel_oserror * fm_puts(fm_face h, int x, int y, const char * s, int os, int blend)
 {
   #ifdef TRACE
     if (tl & (1u<<10)) Printf("\nfm_puts: Called with handle %p\n         String '%s'\n",(void *) h, s);
@@ -1450,7 +1450,7 @@ void fm_shutdown(void)
 /* Returns:    See parameters list.              */
 /*************************************************/
 
-_kernel_oserror * fm_get_string_width(fm_face h, char * s, int maxwid, int maxbytes,
+_kernel_oserror * fm_get_string_width(fm_face h, const char * s, int maxwid, int maxbytes,
                                       int split, int * bytes, int * width)
 {
   if (h >= 0)
@@ -1464,13 +1464,13 @@ _kernel_oserror * fm_get_string_width(fm_face h, char * s, int maxwid, int maxby
 
     e = _swix(Font_SetFont,_IN(0),h);
 
-    /* Force a terminator in the string */
-
-    if (maxbytes < strlen(s))
-    {
-      c1 = s[maxbytes];
-      s[maxbytes] = 0;
-    }
+//    /* Force a terminator in the string */
+//
+//    if (maxbytes < strlen(s))
+//    {
+//      c1 = s[maxbytes];
+//      s[maxbytes] = 0;
+//    }
 
     /* Get the width */
 
@@ -1520,7 +1520,7 @@ _kernel_oserror * fm_get_string_width(fm_face h, char * s, int maxwid, int maxby
 
     if (!e && !*width && split > 0)
     {
-      char * p = s;
+      const char * p = s;
 
       /* Adjust the string length to the first split character. */
       /* (Thanks to Tony Cheal for spotting this when doing     */
@@ -1532,13 +1532,13 @@ _kernel_oserror * fm_get_string_width(fm_face h, char * s, int maxwid, int maxby
 
       while (*p && *(p++) != split);
 
-      /* Force a terminator at the split character, if found */
-
-      if (*p)
-      {
-        c2 = *p;
-        *p = 0;
-      }
+//      /* Force a terminator at the split character, if found */
+//
+//      if (*p)
+//      {
+//        c2 = *p;
+//        *p = 0;
+//      }
 
       /* Now call the Font Manager without asking for a split, knowing that */
       /* the string length only runs up to the split character.             */
@@ -1550,19 +1550,19 @@ _kernel_oserror * fm_get_string_width(fm_face h, char * s, int maxwid, int maxby
             0x1000000,    /* Maximum width if splitting is allowed     */
             0x1000000,    /* Maximum height if splitting is allowed    */
             -1,           /* Character to split on, or -1 for no split */
-            maxbytes,     /* Maximum string length                     */
+            p - s /*maxbytes*/,     /* Maximum string length                     */
 
             width,        /* Width of scanned string                   */
             bytes);       /* Length of scanned string                  */
 
       /* Restore the overwritten character, if any */
 
-      if (c2) *p = c2;
+//      if (c2) *p = c2;
     }
 
     /* Put the character that was overwritten by a terminator (if any) back */
 
-    if (c1) s[maxbytes] = c1;
+//    if (c1) s[maxbytes] = c1;
 
     /* Exit if there was some error */
 
diff --git a/c/Forms b/c/Forms
index 8448112..72512d0 100644
--- a/c/Forms
+++ b/c/Forms
@@ -42,6 +42,7 @@
 #include "Browser.h"
 #include "FetchPage.h"
 #include "FontManage.h"
+#include "Images.h"
 #include "Redraw.h"
 #include "TokenUtils.h"
 #include "Toolbars.h"
@@ -482,7 +483,7 @@ static _kernel_oserror * form_validate_select(browser_data * b, HStream * tp, in
   /* If the SELECT item can take multiple selections, there's */
   /* no work to do, so exit.                                  */
 
-  if (tp->type & TYPE_MULTIPLE) return NULL;
+  if (HtmlSELECTmultiple(tp)) return NULL;
 
   /* Otherwise, find the form field record */
 
@@ -584,7 +585,7 @@ static _kernel_oserror * form_validate_radio(browser_data * b, HStream * token)
   form_field  * fp;
   form_header * hp;
   HStream     * tp;
-  char        * name;
+  const char  * name;
   int           selectthis;
   int           foundone;
   int           i;
@@ -601,7 +602,7 @@ static _kernel_oserror * form_validate_radio(browser_data * b, HStream * token)
   /* 'name' to the radio's name.                        */
 
   selectthis = fp->value.checked;
-  name       = token->name;
+  name       = HtmlINPUTname(token);
 
   /* Find the form header and first record of the form that */
   /* the given token lies in.                               */
@@ -626,7 +627,7 @@ static _kernel_oserror * form_validate_radio(browser_data * b, HStream * token)
       /* See if the name of the token representing this radio */
       /* matches the name of the token given to the function  */
 
-      if (name && tp->name && !strcmp(name, tp->name))
+      if (name && HtmlINPUTname(tp) && !strcmp(name, HtmlINPUTname(tp)))
       {
         /* If so, it's in the same group of radio buttons. */
 
@@ -925,16 +926,15 @@ _kernel_oserror * form_put_field(browser_data * b, HStream * token, char * value
 /*             hold selections plus terminator). */
 /*************************************************/
 
-static void form_build_selection(char * value, char * selection)
+static void form_build_selection(const int * value, char * selection)
 {
   int    i, n;
   char * p;
 
   /* Find the number of entries and point to the first in 'p' */
 
-  p  = value;
-  n  = *(int *) p;
-  p += 8;
+  p  = (char *) (value + 2);
+  n  = value[0];
 
   /* Can't go past the internal limit (see top of this file) */
 
@@ -1020,7 +1020,7 @@ _kernel_oserror * form_new_field(browser_data * b, HStream * token, form_fieldty
 
     case form_select:
     {
-      form_build_selection(value, select);
+      form_build_selection((int *) value, select);
 
       value  = select;
       space += strlen(value) + 1 + sizeof(fv_select) - 4;
@@ -1105,6 +1105,12 @@ _kernel_oserror * form_new_field(browser_data * b, HStream * token, form_fieldty
   if (type == form_radio)  form_validate_radio (b, token);
   if (type == form_select) form_validate_select(b, token, 0);
 
+  /* Start an image fetch for these beauties... */
+  if (type == form_image && HtmlINPUTsrc(token))
+  {
+      e = image_new_image(b, HtmlINPUTsrc(token), token, 0);
+  }
+
   /* Finished */
 
   return NULL;
@@ -1166,19 +1172,20 @@ form_field_value * form_get_field(browser_data * b, HStream * token)
 
 static char * form_select_text(browser_data * b, HStream * tp, char * selection)
 {
-  int       i, n, s;
-  char    * p;
-  char    * f;
+  int          i, n, s;
+  const int  * pi;
+  const char * p;
+  char       * f;
 
   s  = 0;
 
   /* Find the number of entries in the list and skip to the first */
   /* one in 'p' and 'f'.                                          */
 
-  p  = tp->value;
-  n  = *(int *) p;
-  p += 8;
-  f  = p;
+  pi = HtmlSELECToptions(tp);
+  n  = pi[0];
+  p  = (const char *) (pi + 2);
+  f  = (char *) p;
 
   if (n > MAXSELECTIONS) n = MAXSELECTIONS;
 
@@ -1193,7 +1200,7 @@ static char * form_select_text(browser_data * b, HStream * tp, char * selection)
     {
       s++;
 
-      f = p;
+      f = (char *) p;
     }
 
     /* Move past the selected/unselected inidicator char */
@@ -1357,7 +1364,7 @@ static _kernel_oserror * form_reset_form(browser_data * b, HStream * token)
         {
           /* Value is NULL for unselected, non-NULL for selected */
 
-          value = (char *) (tp->type & TYPE_CHECKED);
+          value = (char *) HtmlINPUTchecked(tp);
         }
         break;
 
@@ -1365,7 +1372,7 @@ static _kernel_oserror * form_reset_form(browser_data * b, HStream * token)
         {
           /* Value is the array of FORM_SELCHAR and FORM_UNSELCHAR characters */
 
-          form_build_selection(tp->value, select);
+          form_build_selection(HtmlSELECToptions(tp), select);
           value = select;
         }
         break;
@@ -1444,7 +1451,7 @@ void form_get_linesize(BBox * fontbox, int * lh, int * lb)
 /* Assumes:    That the int pointer is not NULL. */
 /*************************************************/
 
-static void form_textarea_find_caret(char * p, int fh, int * index, int x, int y)
+static void form_textarea_find_caret(const char * p, int fh, int * index, int x, int y)
 {
   int    i, l, w;
   char   c;
@@ -1522,11 +1529,11 @@ static void form_textarea_find_caret(char * p, int fh, int * index, int x, int y
 /* Returns:    See parameters list.              */
 /*************************************************/
 
-static void form_textarea_caretpos(char * p, int fh, int index, int * x, int * y)
+static void form_textarea_caretpos(const char * p, int fh, int index, int * x, int * y)
 {
-  int    ox, oy, i, li;
-  char * t;
-  char * l;
+  int          ox, oy, i, li;
+  const char * t;
+  const char * l;
 
   i = li = oy = ox = 0;
 
@@ -1795,6 +1802,7 @@ static _kernel_oserror * form_create_menu(browser_data * b, HStream * tp)
 {
   form_field              * fp;
   char                    * p, * o;
+  const int               * pi;
   int                       w, i, n, size;
   WimpGetPointerInfoBlock   m;
   wimp_menuhdr            * mhp;
@@ -1817,8 +1825,8 @@ static _kernel_oserror * form_create_menu(browser_data * b, HStream * tp)
   /* and thus get the number of items in 'n'.            */
 
   size = sizeof(wimp_menuhdr);
-  p    = tp->value;
-  n    = *(int *) p;
+  pi   = HtmlSELECToptions(tp);
+  n    = pi[0];
 
   /* Can't create a field if there are no items! */
 
@@ -1834,7 +1842,7 @@ static _kernel_oserror * form_create_menu(browser_data * b, HStream * tp)
 
   /* Skip 'p' to the first item's selected/deselected char */
 
-  p += 8;
+  p = (char *)&pi[2];
 
   /* Keep a running count of the width used so far in 'w'      */
   /* (for earlier OS versions which need this to be specified) */
@@ -1893,7 +1901,7 @@ static _kernel_oserror * form_create_menu(browser_data * b, HStream * tp)
 
   /* Use the item name for a menu title */
 
-  strncpy(mhp->title, tp->name, 12);
+  strncpy(mhp->title, HtmlSELECTname(tp), 12);
 
   /* If the title is now a NULL string or is a full */
   /* 12 chars long excluding terminator, replace it */
@@ -1913,7 +1921,7 @@ static _kernel_oserror * form_create_menu(browser_data * b, HStream * tp)
 
   /* Point to the first item's selected/deselected char */
 
-  p = tp->value + 8;
+  p = (char *)(HtmlSELECToptions(tp) + 2);
 
   /* Point past the nth menu item structure (note the pointer */
   /* arithmetic...) - i.e. the limit of the menu item         */
@@ -2249,7 +2257,7 @@ static _kernel_oserror * form_start_textarea_edit(browser_data * b, HStream * tp
   if (e) return e;
 
   fe_single   = !(tp->style & TEXTAREA);
-  fe_password = (tp->type & TYPE_RESET) == TYPE_PASSWORD;
+  fe_password = (tp->style & INPUT) && HtmlINPUTtype(tp) == inputtype_PASSWORD;
   fe_browser  = b;
   fe_token    = tp;
 
@@ -2613,7 +2621,7 @@ static int form_extend_flex(void **data, int size)
 /*             escaped character sequences).     */
 /*************************************************/
 
-static int form_encode_flex_data(void ** data, char * enctype, int start_at)
+static int form_encode_flex_data(void ** data, const char * enctype, int start_at)
 {
   int    i, o;
   char * p;
@@ -2702,15 +2710,15 @@ static int form_encode_flex_data(void ** data, char * enctype, int start_at)
 /*             to hold the item.                 */
 /*************************************************/
 
-static int form_field_data_size(browser_data * b, form_field * fp, HStream * tp)
+static int form_field_data_size(browser_data * b, form_field * fp, HStream * tp, unsigned int x, unsigned int y)
 {
   int size;
 
   size = 0;
 
-  if (tp->name)
+  if (HtmlELEMENTname(tp))
   {
-    size = strlen(tp->name) + 1; /* add one for the ' = ' sign */
+    size = strlen(HtmlELEMENTname(tp)) + 1; /* add one for the ' = ' sign */
     switch(fp->header.type)
     {
       case form_textarea: /* form_textarea same as form_password: no break */
@@ -2731,8 +2739,8 @@ static int form_field_data_size(browser_data * b, form_field * fp, HStream * tp)
 
         if (fp->value.checked)
         {
-          if (tp->value) size += strlen(tp->value);
-          else           size += 2;
+          if (HtmlINPUTvalue(tp)) size += strlen(HtmlINPUTvalue(tp));
+          else                    size += 2;
         }
         else size = 0;
       }
@@ -2749,8 +2757,8 @@ static int form_field_data_size(browser_data * b, form_field * fp, HStream * tp)
         /* name is present (use p).                               */
 
         s = 0;
-        n = *(int *) tp->value;
-        p = tp->value + 8;
+        n = HtmlSELECToptions(tp)[0];
+        p = (char *)(HtmlSELECToptions(tp) + 2);
 
         for (i = 0; i < n; i++)
         {
@@ -2772,11 +2780,18 @@ static int form_field_data_size(browser_data * b, form_field * fp, HStream * tp)
       }
       break;
 
-      // Image button types not supported yet...
+      /* Image buttons send "name.x=123&name.y=123" */
 
       case form_image:
       {
-        size = 0;
+        char tempbuf[32];
+
+         /* We've already added up length of "name=", this gives us */
+         /* length of "name.x=&name.y="                             */
+        size = (size+2) * 2 + 1;
+
+        /* Add in length of the two coordinates */
+        size += sprintf(tempbuf, "%u%u", x, y);
         break;
       }
 
@@ -2792,8 +2807,8 @@ static int form_field_data_size(browser_data * b, form_field * fp, HStream * tp)
 
       case form_hidden:
       {
-        if (tp->value) size += strlen(tp->value);
-        else           size  = 0;
+        if (HtmlINPUTvalue(tp)) size += strlen(HtmlINPUTvalue(tp));
+        else                    size  = 0;
       }
       break;
     }
@@ -2817,7 +2832,7 @@ static int form_field_data_size(browser_data * b, form_field * fp, HStream * tp)
 /* included as part of this data.                */
 /*                                               */
 /* x and y are coords for forms submitted by     */
-/* INPUT TYPE = IMAGE [not implemented].         */
+/* INPUT TYPE = IMAGE.                           */
 /*                                               */
 /* Parameters: Pointer to a browser_data struct  */
 /*             relevant to the form;             */
@@ -2826,10 +2841,10 @@ static int form_field_data_size(browser_data * b, form_field * fp, HStream * tp)
 /*             representing the form;            */
 /*                                               */
 /*             X coord for INPUT TYPE = IMAGE    */
-/*             submissions [not implemented];    */
+/*             submissions;                      */
 /*                                               */
 /*             Y coord for INPUT TYPE = IMAGE    */
-/*             submissions [not implemented];    */
+/*             submissions;                      */
 /*                                               */
 /*             Pointer to the flex anchor for    */
 /*             the flex block in which the data  */
@@ -2912,7 +2927,7 @@ static _kernel_oserror * form_build_data(browser_data * b, HStream * token, int
     /* which case the item will be included in the encoded data.     */
 
     if (
-         tp->name                                                      &&
+         HtmlELEMENTname(tp)                                           &&
          fp->header.type != form_reset                                 &&
          (fp->header.type != form_submit || fp->header.token == token) &&
          (fp->header.type != form_image  || fp->header.token == token)
@@ -2922,7 +2937,7 @@ static _kernel_oserror * form_build_data(browser_data * b, HStream * token, int
 
       /* Find out how much space the encoded item will need */
 
-      size = form_field_data_size(b, fp, tp);
+      size = form_field_data_size(b, fp, tp, x, y);
 
       if (size)
       {
@@ -2955,7 +2970,7 @@ static _kernel_oserror * form_build_data(browser_data * b, HStream * token, int
 
         *p = 0;
 
-        strcpy(p, tp->name);
+        strcpy(p, HtmlELEMENTname(tp));
 
         /* Put in a name/value separator */
 
@@ -2981,8 +2996,8 @@ static _kernel_oserror * form_build_data(browser_data * b, HStream * token, int
             /* If the item has a value, use this. Otherwise use the default */
             /* string of 'on'.                                              */
 
-            if (tp->value) strcpy(p, tp->value);
-            else           strcpy(p, "on");
+            if (HtmlINPUTvalue(tp)) strcpy(p, HtmlINPUTvalue(tp));
+            else                    strcpy(p, "on");
           }
           break;
 
@@ -2993,8 +3008,8 @@ static _kernel_oserror * form_build_data(browser_data * b, HStream * token, int
             char * q;
 
             first = 1;
-            n     = *(int *) tp->value;
-            f     = tp->value + 8;
+            n     = HtmlSELECToptions(tp)[0];
+            f     = (char *)(HtmlSELECToptions(tp) + 2);
 
             for (i = 0; i < n; i++)
             {
@@ -3010,7 +3025,7 @@ static _kernel_oserror * form_build_data(browser_data * b, HStream * token, int
                 {
                   *p++ = ENCODE_FIELDSEP;
 
-                  strcpy(p, tp->name);
+                  strcpy(p, HtmlSELECTname(tp));
 
                    p   = strchr(p, 0);
                   *p++ = ENCODE_VALUESEP;
@@ -3035,7 +3050,8 @@ static _kernel_oserror * form_build_data(browser_data * b, HStream * token, int
 
           case form_image:
           {
-            // Not implemented yet
+            /* Need to back up a bit */
+            p += sprintf(p-1, ".x%c%u%c%s.y%c%u", ENCODE_VALUESEP, x, ENCODE_FIELDSEP, HtmlINPUTname(tp), ENCODE_VALUESEP, y) - 1;
           }
           break;
 
@@ -3051,7 +3067,7 @@ static _kernel_oserror * form_build_data(browser_data * b, HStream * token, int
           {
             /* Use the item value */
 
-            if (tp->value) strcat(p, tp->value);
+            if (HtmlINPUTvalue(tp)) strcat(p, HtmlINPUTvalue(tp));
           }
           break;
         }
@@ -3074,7 +3090,7 @@ static _kernel_oserror * form_build_data(browser_data * b, HStream * token, int
 
   /* Now encode the block according to the specified encoding type */
 
-  if (!form_encode_flex_data(data, tp->enctype, additions_start))
+  if (!form_encode_flex_data(data, HtmlFORMenctype(tp), additions_start))
   {
     make_no_cont_memory_error(7);
     return &erb;
@@ -3101,7 +3117,7 @@ static _kernel_oserror * form_build_data(browser_data * b, HStream * token, int
 /*             to submit the form to.            */
 /*************************************************/
 
-static _kernel_oserror * form_submit_form(browser_data * b, HStream * token)
+static _kernel_oserror * form_submit_form(browser_data * b, HStream * token, int x, int y)
 {
   void            * data;
   _kernel_oserror * e;
@@ -3122,7 +3138,7 @@ static _kernel_oserror * form_submit_form(browser_data * b, HStream * token)
 
   if (HtmlFORMmethod(tp) == formmethod_GET && HtmlFORMaction(tp))
   {
-    e = form_build_data(b, token, 0, 0, &data); // 0, 0 need filling in for INPUT TYPE = IMAGE
+    e = form_build_data(b, token, x, y, &data);
     if (!e) e = fetchpage_new(b, data, 1);
 
     if (data)
@@ -3142,7 +3158,7 @@ static _kernel_oserror * form_submit_form(browser_data * b, HStream * token)
 
   else if (HtmlFORMmethod(tp) == formmethod_POST && HtmlFORMaction(tp))
   {
-    e = form_build_data(b, token, 0, 0, &b->extradata); // 0, 0 need filling in for INPUT TYPE = IMAGE
+    e = form_build_data(b, token, x, y, &b->extradata);
     tp = hp->token;
 
     if (e)
@@ -3185,9 +3201,13 @@ static _kernel_oserror * form_submit_form(browser_data * b, HStream * token)
 /*             1 = start of line for text area,  */
 /*                 end of line for writable,     */
 /*             2 = end of line.                  */
+/*                                               */
+/*             x-coordinate (if input image)     */
+/*                                               */
+/*             y-coordinate (if input image)     */
 /*************************************************/
 
-_kernel_oserror * form_click_field(browser_data * b, HStream * token, int mode)
+_kernel_oserror * form_click_field(browser_data * b, HStream * token, int mode, int x, int y)
 {
   form_field      * fp;
   _kernel_oserror * e = NULL;
@@ -3226,16 +3246,13 @@ _kernel_oserror * form_click_field(browser_data * b, HStream * token, int mode)
       case form_select:   e = form_start_select_edit(b, token);
       break;
 
-      // Images not implemented yet
-
-      case form_image:    break;
-
       /* For 'submit' buttons, slab the button in and out and submit the form */
 
+      case form_image:
       case form_submit:
       {
         browser_flash_token(b, token);
-        e = form_submit_form(b, token);
+        e = form_submit_form(b, token, x, y);
       }
       break;
 
@@ -3306,14 +3323,14 @@ _kernel_oserror * form_finish_edit(browser_data * b)
 /*             unknown button type.              */
 /*************************************************/
 
-char * form_button_text(HStream * tp)
+const char * form_button_text(HStream * tp)
 {
-  char * p;
+  const char * p;
 
-  p = tp->value;
+  p = HtmlINPUTvalue(tp);
 
-  if (!p && ((tp->type & TYPE_RESET) == TYPE_SUBMIT)) p = lookup_token("Submit:Submit",0,0);
-  if (!p && ((tp->type & TYPE_RESET) == TYPE_RESET))  p = lookup_token("Reset:Reset",  0,0);
+       if (!p && HtmlINPUTtype(tp) == inputtype_SUBMIT) p = lookup_token("Submit:Submit",0,0);
+  else if (!p && HtmlINPUTtype(tp) == inputtype_RESET)  p = lookup_token("Reset:Reset",  0,0);
 
   if (!p) p = "Unknown:Action";
 
@@ -3465,7 +3482,7 @@ static _kernel_oserror * form_next_field(int auto_submit, int * used)
     /* Either submit the form, or jump back up to the first editable */
     /* element.                                                      */
 
-    if (auto_submit) return (form_submit_form(fe_browser, fe_token));
+    if (auto_submit) return (form_submit_form(fe_browser, fe_token, 0, 0));
     else next = first;
   }
 
@@ -3528,7 +3545,7 @@ static _kernel_oserror * form_next_field(int auto_submit, int * used)
       {
         browser_select_token(owner, t, 0);
 
-        return form_click_field(owner, t, 2);
+        return form_click_field(owner, t, 2, 0, 0);
       }
       else
       {
@@ -3550,7 +3567,7 @@ static _kernel_oserror * form_next_field(int auto_submit, int * used)
     if (next && next != fe_token)
     {
       if (choices.keyboardctl) browser_select_token(fe_browser, next, 0); /* If moving by Tab, make sure the selection keeps up */
-      return form_click_field(fe_browser, next, 2);
+      return form_click_field(fe_browser, next, 2, 0, 0);
     }
   }
 
@@ -3675,7 +3692,7 @@ static _kernel_oserror * form_previous_field(int * used)
       {
         browser_select_token(owner, t, 0);
 
-        return form_click_field(owner, t, 2);
+        return form_click_field(owner, t, 2, 0, 0);
       }
       else
       {
@@ -3697,7 +3714,7 @@ static _kernel_oserror * form_previous_field(int * used)
     if (previous && previous != fe_token)
     {
       if (choices.keyboardctl) browser_select_token(fe_browser, previous, 0); /* If moving by Tab, make sure the selection keeps up */
-      return form_click_field(fe_browser, previous, 2);
+      return form_click_field(fe_browser, previous, 2, 0, 0);
     }
   }
 
@@ -3724,7 +3741,7 @@ static _kernel_oserror * form_cursor_right(int * used)
 
   if (fe_token && fe_browser)
   {
-    char * p;
+    const char * p;
 
     p = form_get_field_text(fe_browser, fe_token);
 
@@ -3769,7 +3786,7 @@ static _kernel_oserror * form_cursor_bottom(void)
 
   if (fe_token && fe_browser)
   {
-    char *p;
+    const char *p;
 
     p = form_get_field_text(fe_browser, fe_token);
 
@@ -3797,8 +3814,8 @@ static _kernel_oserror * form_cursor_eol(void)
 {
   if(fe_token && fe_browser)
   {
-    char *p;
-    int  o;
+    const char *p;
+    int         o;
 
     p = form_get_field_text(fe_browser, fe_token);
     o = fe_index;
@@ -3831,8 +3848,8 @@ static _kernel_oserror * form_cursor_bol(void)
 {
   if (fe_token && fe_browser && fe_index)
   {
-    char * p;
-    int    o;
+    const char * p;
+    int          o;
 
     p = form_get_field_text(fe_browser, fe_token);
     o = fe_index;
@@ -3962,9 +3979,9 @@ static _kernel_oserror * form_cursor_y(int dir, int * used)
 
   if (fe_token && fe_browser && dir)
   {
-    char    * p;
-    int       o, x, y, fh;
-    HStream * tp;
+    const char * p;
+    int          o, x, y, fh;
+    HStream    * tp;
 
     /* For single line items, just look at the relevant direction to move */
 
@@ -4563,7 +4580,7 @@ void form_select_menu_event(WimpPollBlock * e)
     /* of items that the menu should have                        */
 
     tp = fe_mtoken;
-    n  = *(int *) tp->value;
+    n  = HtmlSELECToptions(tp)[0];
     o  = e->menu_selection[0];
 
     if (o >= n) return;
@@ -4578,7 +4595,7 @@ void form_select_menu_event(WimpPollBlock * e)
     /* the selection type. Otherwise, need to make sure that any     */
     /* other selected item is cleared.                               */
 
-    if (tp->type & TYPE_MULTIPLE)
+    if (HtmlSELECTmultiple(tp))
     {
       select[o] = (select[o] == FORM_SELCHAR) ? FORM_UNSELCHAR : FORM_SELCHAR;
     }
diff --git a/c/Handlers b/c/Handlers
index c3c759d..52cc22b 100644
--- a/c/Handlers
+++ b/c/Handlers
@@ -1521,6 +1521,42 @@ int handle_clicks(int eventcode, WimpPollBlock * b, IdBlock * idb, browser_data
   return 0;
 }
 
+/*************************************************/
+/* handle_calc_image_click_coords()              */
+/*                                               */
+/* Calculate the coordinates of a click on an    */
+/* image  in pixels from the top left corner, as */
+/* required by image maps and image input        */
+/* fields.                                       */
+/*************************************************/
+int handle_calc_image_click_coords(HStream * p, WimpGetPointerInfoBlock * i, int * x, int * y, browser_data * handle)
+{
+    WimpGetWindowStateBlock   s;
+    BBox                      box;
+
+    /* Get the image's size and position on screen */
+
+    s.window_handle = handle->window_handle;
+    if (wimp_get_window_state(&s)) return 0;
+
+    if (image_get_token_image_size(handle, p, &box)) return 0;
+    if (image_get_token_image_position(handle, p, x, y)) return 0;
+
+    *x = coords_x_toscreen(*x, (WimpRedrawWindowBlock *) &s);
+    *y = coords_y_toscreen(*y, (WimpRedrawWindowBlock *) &s);
+
+    /* Get the offset of the pointer position from the top left */
+    /* of the image in ox and oy                                */
+
+    *x = i->x - *x;
+    *y = *y + (box.ymax - box.ymin) - i->y;
+
+    image_convert_to_pixels(handle, p, x, y);
+
+    return 1;
+}
+
+
 /*************************************************/
 /* handle_link_clicks()                          */
 /*                                               */
@@ -1595,7 +1631,12 @@ int handle_link_clicks(int eventcode, WimpPollBlock * b, IdBlock * idb, browser_
          )
        )
     {
-      ChkError(form_click_field(handle, p, 0));
+      int x = 0, y = 0;
+
+      if ((p->style & INPUT) && HtmlINPUTtype(p) == inputtype_IMAGE && eventcode >= 0)
+          handle_calc_image_click_coords(p, &i, &x, &y, handle);
+
+      ChkError(form_click_field(handle, p, 0, x, y));
       used = 1;
     }
     else
@@ -1643,11 +1684,8 @@ int handle_link_clicks(int eventcode, WimpPollBlock * b, IdBlock * idb, browser_
 
             if ((p->style & IMG) && (p->type & TYPE_ISMAP))
             {
-              WimpGetWindowStateBlock   s;
               char                      coords[64];
               browser_data            * targetted;
-              BBox                      box;
-              int                       x, y;
 
               if (eventcode < 0)
               {
@@ -1656,27 +1694,12 @@ int handle_link_clicks(int eventcode, WimpPollBlock * b, IdBlock * idb, browser_
                 if (!p) return 0;
               }
 
-              /* Get the image's size and position on screen */
-
-              s.window_handle = handle->window_handle;
-              if (wimp_get_window_state(&s)) return 0;
-
-              if (image_get_token_image_size(handle, p, &box)) return 0;
-              if (image_get_token_image_position(handle, p, &x, &y)) return 0;
-
-              x = coords_x_toscreen(x, (WimpRedrawWindowBlock *) &s);
-              y = coords_y_toscreen(y, (WimpRedrawWindowBlock *) &s);
-
-              /* Get the offset of the pointer position from the top left */
-              /* of the image in ox and oy                                */
-
-              ox = i.x - x;
-              oy = y + (box.ymax - box.ymin) - i.y;
+              /* Find out which pixel we clicked on */
+              handle_calc_image_click_coords(p, &i, &ox, &oy, handle);
 
               if (ox >= 0 && oy >= 0)
               {
-                /* Convert the coordinate to pixels and build an appropriate */
-                /* CGI string including this information.                    */
+                /* Build an appropriate CGI string including this information. */
 
                 image_convert_to_pixels(handle, p, &ox, &oy);
                 sprintf(coords, "?%d,%d", ox, oy);
diff --git a/c/Images b/c/Images
index 784d672..e3a4f54 100644
--- a/c/Images
+++ b/c/Images
@@ -886,7 +886,7 @@ _kernel_oserror * image_new_image(browser_data * b, const char * url, HStream *
   /* width and height fields according to any details in the  */
   /* HTML source.                                             */
 
-  if (!background)
+  if (!background && !(tp->style & INPUT))
   {
     if (tp->cols > 0) idata[nimages].currw = tp->cols * 2;
     if (tp->rows > 0) idata[nimages].currh = tp->rows * 2;
@@ -2294,7 +2294,7 @@ static _kernel_oserror * image_update_image(browser_data * b, int image, BBox *
           /* correct its X and Y coordinates appropriately */
 
           o = 0;
-          if (ISLINK(tp)) o = tp->maxlen * 2;
+          if (ISLINK(tp) && (tp->style & IMG)) o = tp->maxlen * 2;
           x += o;
           y += ibox.ymin + o;
 
diff --git a/c/Redraw b/c/Redraw
index 1defe06..2cb952b 100644
--- a/c/Redraw
+++ b/c/Redraw
@@ -1627,9 +1627,9 @@ _kernel_oserror * redraw_draw_r(int toplevel, int xorg, int yorg, browser_data *
                   /* A text-based element */
 
                   if (
-                       (tp->type & TYPE_RESET) == TYPE_TEXT     ||
-                       (tp->type & TYPE_RESET) == TYPE_PASSWORD ||
-                       (tp->style & (TEXTAREA | SELECT))
+                       (tp->style & (TEXTAREA | SELECT))       ||
+                       HtmlINPUTtype(tp) == inputtype_TEXT     ||
+                       HtmlINPUTtype(tp) == inputtype_PASSWORD
                      )
                   {
                     BBox    box;
@@ -1676,7 +1676,7 @@ _kernel_oserror * redraw_draw_r(int toplevel, int xorg, int yorg, browser_data *
                                            &r->redraw_area,
                                            fh,
                                            !!(tp->style & TEXTAREA),
-                                           (tp->type & TYPE_RESET) == TYPE_PASSWORD);
+                                           (tp->style & INPUT) && HtmlINPUTtype(tp) == inputtype_PASSWORD);
                     }
 
                     /* If the element is a SELECT field, it needs a menu icon too */
@@ -1740,37 +1740,41 @@ _kernel_oserror * redraw_draw_r(int toplevel, int xorg, int yorg, browser_data *
 //                      }
                     }
                   }
-                  else switch(tp->type & TYPE_RESET)
+                  else switch(HtmlINPUTtype(tp))
                   {
                     /* Graphics-based forms elements */
 
-                    case TYPE_CHECKBOX: if (nocontent != tp) redraw_switch(b,
-                                                                           tp,
-                                                                           x,
-                                                                           y + base,
-                                                                           form_get_field(b,
-                                                                                          d->cdata[cn].t) -> checked ? "fopton" : "foptoff",
-                                                                           r);
+                    case inputtype_CHECKBOX:
+                      if (nocontent != tp)
+                        redraw_switch(b,
+                                      tp,
+                                      x,
+                                      y + base,
+                                      form_get_field(b, d->cdata[cn].t) -> checked ? "fopton" : "foptoff",
+                                      r);
                     break;
 
-                    case TYPE_RADIO:    if (nocontent != tp) redraw_switch(b,
-                                                                           tp,
-                                                                           x,
-                                                                           y + base,
-                                                                           form_get_field(b,
-                                                                                          d->cdata[cn].t) -> checked ? "fradioon" : "fradiooff",
-                                                                           r);
+                    case inputtype_RADIO:
+                      if (nocontent != tp)
+                        redraw_switch(b,
+                                      tp,
+                                      x,
+                                      y + base,
+                                      form_get_field(b, d->cdata[cn].t) -> checked ? "fradioon" : "fradiooff",
+                                      r);
                     break;
 
-                    case TYPE_IMAGE:
-                    case TYPE_HIDDEN: break;
+                    case inputtype_IMAGE:
+                         goto do_image;
+
+                    case inputtype_HIDDEN: break;
 
-                    case TYPE_SUBMIT: /* SUBMIT same as RESET: no break */
-                    case TYPE_RESET:
+                    case inputtype_SUBMIT: /* SUBMIT same as RESET: no break */
+                    case inputtype_RESET:
                     {
-                      BBox   box;
-                      int    fh, ox, oy, colour;
-                      char * p;
+                      BBox         box;
+                      int          fh, ox, oy, colour;
+                      const char * p;
 
                       p = form_button_text(tp);
 
@@ -1845,7 +1849,11 @@ _kernel_oserror * redraw_draw_r(int toplevel, int xorg, int yorg, browser_data *
                 else if (tp->style & IMG)
                 {
                   BBox box;
-                  int  ox, oy, o = 0;
+                  int  ox, oy, o;
+
+              do_image:
+
+                  o = 0;
 
                   convert_pair_to_os(x, y + base, &ox, &oy);
 
@@ -1874,7 +1882,7 @@ _kernel_oserror * redraw_draw_r(int toplevel, int xorg, int yorg, browser_data *
 
                     if (ISLINK(tp))
                     {
-                      o = tp->maxlen * 2;
+                      o = (tp->style & IMG) ? tp->maxlen * 2 : 4;
 
                       if (o)
                       {
@@ -1887,6 +1895,8 @@ _kernel_oserror * redraw_draw_r(int toplevel, int xorg, int yorg, browser_data *
                       }
                       else if (redraw_selected(b, tp)) redraw_border_around_box(&box, b->selecol);
                     }
+                    else if ((tp->style & INPUT) && redraw_selected(b, tp))
+                      redraw_border_around_box(&box, b->selecol);
 
                     /* Redraw the image itself */
 
diff --git a/c/Reformat b/c/Reformat
index 54cb472..4ad16d8 100644
--- a/c/Reformat
+++ b/c/Reformat
@@ -162,7 +162,8 @@ _kernel_oserror * reformat_stop(browser_data * b)
 
 static int reformat_istext(HStream * tp)
 {
-  return (((tp->style) & (IMG | HR)) == 0);
+  return (((tp->style) & (IMG | HR)) == 0 &&
+          !((tp->style & INPUT) && HtmlINPUTtype(tp) == inputtype_IMAGE));
 }
 
 /*************************************************/
@@ -194,6 +195,7 @@ static int reformat_istext(HStream * tp)
 static _kernel_oserror * reformat_token_width(reformat_width_data * w, unsigned int flags)
 {
   _kernel_oserror * e = NULL;
+  BBox box;
 
   /* Deal with tables */
 
@@ -281,13 +283,12 @@ static _kernel_oserror * reformat_token_width(reformat_width_data * w, unsigned
 
   else if (w->tp->style & (INPUT | TEXTAREA | SELECT))
   {
-    if (
-         (w->tp->type  & TYPE_RESET) == TYPE_TEXT ||
-         (w->tp->type  & TYPE_RESET) == TYPE_PASSWORD ||
-         (w->tp->style & (TEXTAREA | SELECT))
+    if ( (w->tp->style & (TEXTAREA | SELECT) ||
+         HtmlINPUTtype(w->tp) == inputtype_TEXT ||
+         HtmlINPUTtype(w->tp) == inputtype_PASSWORD
+         )
        )
     {
-      BBox box;
       int  h, length, extra = 0;
 
       if (w->tp->style & TEXTAREA)
@@ -314,7 +315,7 @@ static _kernel_oserror * reformat_token_width(reformat_width_data * w, unsigned
         width += 32; /* Account for border and gap */
         convert_to_points(width, &extra);
 
-        p = w->tp->value + 8;
+        p = (char *) HtmlSELECToptions(w->tp) + 8;
         l = 8;
 
         while(*p != 0xff)
@@ -330,7 +331,7 @@ static _kernel_oserror * reformat_token_width(reformat_width_data * w, unsigned
       {
         /* One line writable */
 
-        length = w->tp->size;
+        length = HtmlINPUTsize(w->tp);
 
         if (length == 1) length = 2;
         else if (length < 2)
@@ -361,12 +362,12 @@ static _kernel_oserror * reformat_token_width(reformat_width_data * w, unsigned
 
       return e;
     }
-    else switch(w->tp->type & TYPE_RESET)
+    else switch(HtmlINPUTtype(w->tp))
     {
-      case TYPE_SUBMIT: /*; no break - same as RESET */
-      case TYPE_RESET:
+      case inputtype_SUBMIT: /*; no break - same as RESET */
+      case inputtype_RESET:
       {
-        char * p;
+        const char * p;
         int    h, length, end;
 
         p = form_button_text(w->tp);
@@ -395,7 +396,7 @@ static _kernel_oserror * reformat_token_width(reformat_width_data * w, unsigned
       }
       break;
 
-      case TYPE_CHECKBOX:
+      case inputtype_CHECKBOX:
       {
         w->bytes = 0;
 
@@ -405,7 +406,7 @@ static _kernel_oserror * reformat_token_width(reformat_width_data * w, unsigned
       }
       break;
 
-      case TYPE_RADIO:
+      case inputtype_RADIO:
       {
         w->bytes = 0;
 
@@ -415,17 +416,23 @@ static _kernel_oserror * reformat_token_width(reformat_width_data * w, unsigned
       }
       break;
 
-      case TYPE_IMAGE:
-      case TYPE_HIDDEN:
+      case inputtype_HIDDEN:
       {
         w->width = w->bytes = 0;
       }
       break;
+
+      case inputtype_IMAGE:
+      {
+          goto do_image;
+      }
+      break;
     }
   }
   else if (w->tp->style & IMG)
   {
-    BBox box;
+
+  do_image:
 
     w->bytes = 0;
     w->width = 0;
@@ -1201,27 +1208,41 @@ void reformat_free_queue(browser_data * b)
 _kernel_oserror * reformat_get_image_size(browser_data * b, HStream * tp, BBox * box)
 {
   _kernel_oserror * e;
+  imgalign          al;
 
   e = image_get_token_image_size(b, tp, box);
   if (e) return e;
 
-  if ((tp->type & TYPE_ALIGN_MASK) == TYPE_MIDDLE)
+  if (tp->style & IMG)
   {
-    box->ymin -= box->ymax / 2;
-    box->ymax /= 2;
+    if ((tp->type & TYPE_ALIGN_MASK) == TYPE_MIDDLE)
+      al = imgalign_MIDDLE;
+    else if ((tp->type & TYPE_ALIGN_MASK) == TYPE_TOP)
+      al = imgalign_TOP;
+    else
+      al = imgalign_NONE;
   }
+  else
+    al = HtmlINPUTalign(tp);
 
-  if ((tp->type & TYPE_ALIGN_MASK) == TYPE_TOP)
+  switch (al)
   {
-    box->ymin =- box->ymax;
-    box->ymax = 0;
+    case imgalign_MIDDLE:
+      box->ymin -= box->ymax / 2;
+      box->ymax /= 2;
+      break;
+
+    case imgalign_TOP:
+      box->ymin =- box->ymax;
+      box->ymax = 0;
+      break;
   }
 
   /* Deal with links - need to account for a border */
   /* of maxlen * 2 pixels width. ISLINK is defined  */
   /* in Fetch.h.                                    */
 
-  if (ISLINK(tp))
+  if (ISLINK(tp) && (tp->style & IMG))
   {
     int b;
 
@@ -1350,7 +1371,8 @@ static _kernel_oserror * reformat_check_height(int toplevel, browser_data * b, r
 
   /* Find out the height of an image */
 
-  if (tp->style & IMG)
+  if ((tp->style & IMG) ||
+      (tp->style & INPUT) && HtmlINPUTtype(tp) == inputtype_IMAGE)
   {
     BBox box;
 
@@ -1394,14 +1416,14 @@ static _kernel_oserror * reformat_check_height(int toplevel, browser_data * b, r
 
   /* A few easy to work out forms elements */
 
-  else if ((tp->style & INPUT) && (tp->type & TYPE_RESET) == TYPE_CHECKBOX)
+  else if ((tp->style & INPUT) && HtmlINPUTtype(tp) == inputtype_CHECKBOX)
   {
     read_sprite_size("fopton", NULL, &top);
     top -= 8;
     bot = 8;
   }
 
-  else if ((tp->style & INPUT) && (tp->type & TYPE_RESET) == TYPE_RADIO)
+  else if ((tp->style & INPUT) && HtmlINPUTtype(tp) == inputtype_RADIO)
   {
     read_sprite_size("fradioon", NULL, &top);
     top -= 8;
@@ -1585,15 +1607,15 @@ static _kernel_oserror * reformat_check_height(int toplevel, browser_data * b, r
   {
     /* General input types */
 
-    switch(tp->type & TYPE_RESET)
+    switch(HtmlINPUTtype(tp))
     {
-      case TYPE_TEXT: /* No break - same as PASSWORD */
-      case TYPE_PASSWORD:
+      case inputtype_TEXT: /* No break - same as PASSWORD */
+      case inputtype_PASSWORD:
         bot += 8;
         top += 8;
       break;
-      case TYPE_SUBMIT: /* No break - same as RESET */
-      case TYPE_RESET:
+      case inputtype_SUBMIT: /* No break - same as RESET */
+      case inputtype_RESET:
         bot += 8;
         top += 12;
       break;
@@ -2430,7 +2452,9 @@ if (!tpCurr) done = 1;
             /* moved. The new position will be set when the reformatted         */
             /* region is next redrawn.                                          */
 
-            if (tpCurr->style & IMG) image_set_token_image_position(b, tpCurr, -1, -1);
+            if (tpCurr->style & IMG ||
+                ((tpCurr->style & INPUT) && HtmlINPUTtype(tpCurr)==inputtype_IMAGE))
+              image_set_token_image_position(b, tpCurr, -1, -1);
 
             /* If the image has a known width and height, the reformatter has */
             /* dealt with it - so the image library can mark it as redrawable */
@@ -2882,7 +2906,7 @@ void reformat_change_text(browser_data * b, HStream * tp)
   /* If we have ALT text for an image, strip off any preceeding */
   /* spaces or [s, and any trailing spaces or ]s.               */
 
-  else if (tp && tp->text && (tp->style & IMG))
+  else if (tp && tp->text && ((tp->style & IMG) || ((tp->style & INPUT) && HtmlINPUTtype(tp) == inputtype_IMAGE)))
   {
     char * start, * end;
     char   last;
diff --git a/h/Browser b/h/Browser
index fc1a6c7..a8f84c4 100644
--- a/h/Browser
+++ b/h/Browser
@@ -25,13 +25,13 @@
 /* (e.g. by drawing a box around it, changing its colour, etc.) and has    */
 /* some defined action if clicked on.                                      */
 
-#define CanBeSelected(t) (                                                 \
-                           ISLINK(t) ||                                    \
-                           (                                               \
-                             ((t)->style & (INPUT | TEXTAREA | SELECT)) && \
-                             ((t)->type & TYPE_RESET) != TYPE_HIDDEN    && \
-                             ((t)->type & TYPE_RESET) != TYPE_IMAGE        \
-                           )                                               \
+#define CanBeSelected(t) (                                            \
+                           ISLINK(t) ||                               \
+                           ((t)->style & (TEXTAREA | SELECT)) ||      \
+                           (                                          \
+                             ((t)->style & INPUT) &&                  \
+                             (HtmlINPUTtype(t) != inputtype_HIDDEN)   \
+                           )                                          \
                          )
 
 /* Function prototypes */
diff --git a/h/FontManage b/h/FontManage
index 21bc2ad..68b719a 100644
--- a/h/FontManage
+++ b/h/FontManage
@@ -70,7 +70,7 @@ _kernel_oserror * fm_rescale_fonts            (browser_data * b);
 
 _kernel_oserror * fm_font_box                 (fm_face h,BBox * box);
 _kernel_oserror * fm_set_font_colour          (fm_face h,int fore,int back);
-_kernel_oserror * fm_puts                     (fm_face h,int x,int y,char * s,int os,int blend);
+_kernel_oserror * fm_puts                     (fm_face h,int x,int y,const char * s,int os,int blend);
 _kernel_oserror * fm_putsl                    (fm_face handle,int x,int y,char * s,int chars,int os,int blend);
 
 _kernel_oserror * fm_write_descriptor         (char * name,char * buffer);
@@ -84,7 +84,7 @@ int               fm_system_font              (void);
 void              fm_init                     (int systemfont, int base_size);
 void              fm_shutdown                 (void);
 
-_kernel_oserror * fm_get_string_width         (fm_face h, char * s, int maxwid, int maxbytes, int split, int * bytes, int * width);
+_kernel_oserror * fm_get_string_width         (fm_face h, const char * s, int maxwid, int maxbytes, int split, int * bytes, int * width);
 
 void              fm_token_font_info          (HStream * t, int * facenum, int * size, int * italic, int * bold);
 fm_face           fm_find_token_font          (browser_data * b, HStream * t);
diff --git a/h/Forms b/h/Forms
index d65226a..c8fb9d6 100644
--- a/h/Forms
+++ b/h/Forms
@@ -66,10 +66,10 @@ void               form_abandon_menu          (void);
 
 int                form_give_focus            (browser_data * b);
 
-_kernel_oserror  * form_click_field           (browser_data * b, HStream * token, int mode);
+_kernel_oserror  * form_click_field           (browser_data * b, HStream * token, int mode, int x, int y);
 _kernel_oserror  * form_cancel_edit           (browser_data * b);
 _kernel_oserror  * form_finish_edit           (browser_data * b);
-char             * form_button_text           (HStream * tp);
+const char       * form_button_text           (HStream * tp);
 int                form_token_cursor_editable (browser_data * b, HStream * token);
 _kernel_oserror  * form_process_key           (browser_data * b, int * key);
 void               form_select_menu_event     (WimpPollBlock * e);
diff --git a/h/Reformat b/h/Reformat
index e193d57..a6d711a 100644
--- a/h/Reformat
+++ b/h/Reformat
@@ -38,7 +38,7 @@
 
 /* Other tag classification masks */
 
-#define VISUALDATA   (HR | IMG)         /* Does the tag contain displayable data, despite */
+#define VISUALDATA   (HR | IMG | INPUT) /* Does the tag contain displayable data, despite */
                                         /* having no text inside it? If the tag's style   */
                                         /* word contains the bit(s) defined here, it is   */
                                         /* deemed to contain such data.                   */
-- 
GitLab