From 74600d0d27dea38f304ec4af18782c9d4cd44185 Mon Sep 17 00:00:00 2001
From: Jeffrey Lee <me@phlamethrower.co.uk>
Date: Thu, 19 Mar 2020 20:24:03 +0000
Subject: [PATCH] Implement scroll mouse configuration

Support configuring the WindowScroll module, via a settings Obey file at
Choices:Boot.Tasks.WimpScroll

Version 0.17. Tagged as 'MousSetup-0_17'
---
 Makefile              |   2 +-
 Resources/UK/Messages |   5 ++
 Resources/UK/Res,fae  | Bin 4520 -> 5852 bytes
 VersionNum            |  22 ++++---
 c/Main                |  78 +++++++++++++++++++++++++
 c/ScrollTypes         | 106 ++++++++++++++++++++++++++++++++++
 c/Settings            | 130 ++++++++++++++++++++++++++++++++++++++++++
 c/ToolboxE            |  25 +++-----
 h/Main                |   2 +
 h/ScrollTypes         |  25 ++++++++
 h/Settings            |  14 +++++
 11 files changed, 378 insertions(+), 31 deletions(-)
 create mode 100644 c/ScrollTypes
 create mode 100644 h/ScrollTypes

diff --git a/Makefile b/Makefile
index 46b5c4c..aed31a5 100644
--- a/Makefile
+++ b/Makefile
@@ -18,7 +18,7 @@
 COMPONENT  = MousSetup
 TARGET     = !RunImage
 INSTTYPE   = app
-APP_OBJS   = Main MouseType Settings ToolboxE WimpE WimpM
+APP_OBJS   = Main MouseType Settings ToolboxE WimpE WimpM ScrollTypes
 LIBS       = ${CONLIB} ${EVENTLIB} ${TBOXLIB} ${WIMPLIB}
 CINCLUDES  = -Itbox:,C:,<Lib$Dir>.ConfigLib.
 INSTAPP_FILES = !Boot !Run !RunImage Res \
diff --git a/Resources/UK/Messages b/Resources/UK/Messages
index 0adc03b..903302e 100644
--- a/Resources/UK/Messages
+++ b/Resources/UK/Messages
@@ -10,3 +10,8 @@ NoneAvail:No mouse drivers are available
 NewType:You are about to change the mouse type to '%s'. If you do not have this sort of mouse connected the pointer will stop working. Do you want to continue with the reconfiguration?
 Err_NoDefCMOS:Cannot find default CMOS file
 Err_Alloc:Not enough free memory
+Err_BadClass:Resource file is corrupt
+Type_Pointer:Window under the pointer
+Type_Focus:Window with input focus
+Type_FocusOrPointer:Input focus or under pointer
+Type_FavourHigher:Highest of input focus or pointer
diff --git a/Resources/UK/Res,fae b/Resources/UK/Res,fae
index cee54d9029220ad509a7391c2ef8165e5d2c0887..69fb0d3da7683f729544af0d17f3d0779733c2a9 100644
GIT binary patch
delta 2213
zcmb7^UuYav6vof&X0zM4X`{4SZEY{H53y`Ep@cq!h-*!)LR%$`SfT!z&feXbW_E76
zGuv%2xKTv<P%L4Bz6788P_z#%X=}hdR1xu^&<YlU)INv^Ld8Cm(n56o&g`9biwL^O
z@|%0V@7{Cnxo7s&Q`h>3$9C>}K@w3G-zGk}G||XfqM5!78JH{KyGPZ0coZIK5ZV@S
zrE_+8Yql3pC-KE1nmzp3K=XJf(G3iKSVeTE0}uMcTR%c{KAlJ#Nh8bAXk=yf!tK;^
zc)A>(H8ywuh<NiDvG+*$ld)kZ1_d(u2r=pOpUvh_l1M;BkjMqldkLboJ77$X(lT~f
z`m5QT!`w}f)A}TQCNUuAF~iEDRx(ho<2eU*VORW90g>jw8ThVXr*j~VL0O1zffHbR
zB=&J6_H{vTgx@Cy8XSq09Nert1m!ZG8{l441dmZ9F54({j&u~{lDr1}1o$i19*KP%
ziGAJB??N93`SUTp*dk`wNUn=c%WL?wyk<4@7gIz-;4~QLATZ8A=Nv}BH5k7O{V@0k
z*q#IXI0yFiK+lGElLI9_Eh~IlRvv~TaXrVt-@!Q2cNky74RR!c?@8b`^q;|HTvK}_
z_HiWkZ32EvhaYw1D;$a?J`_uvf$g}*e$WErP+Jg!ubM+~6Ksbrp^t%IfH)V;pcK>C
z=arRKQ_X=~#jl}%3H_zeNNw1=AG0o8$3X+?9(2PZ)T<!37B?zDxQ%E>Zc|>f1oD~$
z)?9=4WsINb3J;~WHF~*G+PeBAY~0oJI2a*Ryk$Rp@qr4w0D1=71)u@nF!Wb3f1=H|
z9y<Gq+LwTD9=Zh|H)u}*O;|__(IgC`FkXVe1(RS0`jnfT&r;Of2ErP(>oPpNxj<H&
zL<hze*1QS*EADZ8F47?Wu!r^yf+_gEg+7J(XR~NP?nV9-@SVXs+k*%fQ3XEkEwB>{
z_TXj6L+5I|lMSyMy_@!9$Tltl+tRST58H>B&vY+*n)=M>2y8P5ccrhcd){@d3CAl7
z(<_Q%)hw4W2;W}y_`+=FLMq&td1GPM>IuW%XH}K!in=YOOXIfV3tt8SFSL{wK=XyI
z>Y`-&fv7uPQPtsSt#Le2mHwpid?^AI&qh0miaH`I(hK}NwIYODJ9``P26YD^mFG^y
zi%j8HOw5@TRr3(YmYxV~8OyCbksEJY%#-h`I=!xH!ZJO9ALf?Vb&9genV7{xHKhBG
zymS8}@q9Sgx$(h-^=ebNX0<H;Ypz^5+A$@hXC8F9u0dOob7Hcp%2l)C3)h*zIponm
z$f6Uds*iFvP?GyOw~FIq12Yh26&Z+1%?+GMR|-{%Y7nhQ6e(=!l<go-yLk}X?$yk)
zl|tE2_SRJfe4;><s;Uz0gR86MX}l3l|4UocZO5{8PYB$NSt>~@kVSFu-nBm13!;y&
zwABNm=0%r<30%1^b3)<j?#p#2u!ZxeH(5hg%BuNKBb`<@G`4Vl&F4nr7rdu<1L%h4
zEs$T;_4sw;d7;?{^89W+9@jje=V$cznC2<XGn!X4mo@LS=n&z@I|`&Zu6aOnTJr<V
T)0*cr7d4kOztOy@c}Mea+lp=X

delta 929
zcmYk4Pe_wt9LIm}=G!)#O=D3yN+A!c)Tu}eLy^cRC<E)@Me>kd5@b}+A(+SLP_8F}
zz`%pz=noi!2#ZMQ5D`IOhrl4pphJgFQIW0Bx8A{C_V9gwzt8u1zt5kowHJ5y4iBC@
zJZ@%jMw#b^Z&pm0O{b&g(VJi#pSo}k&lImV3u{Hs_=VoR@kZX}84*Syw>?uHt1%l1
z@d-LFc&|MA^j5QlNGRfky|~hBW~1=%yWh{-OZUKQu6s+~ES0=D_ufmn`be~|lkV3)
z<?<TZ0@;M)5(&fTYczS#Y#@Bd)&t)hJ^8excdjp#886b&7oG<s3TX+OwV}sQem3Bx
zZ4O-ulGf1}^$_qhdLOM$l21wU)xuZYn@}dNB#|s`k<E|>P9cxZpp~R0>ho~zsfg-0
zZo#jiX)d5TNj@dXR|h`;KZWYK$>0+eb@}kNf4kKj?N)QPz^^c;2YrfG*06&*3)dPZ
zQSQ~A!E<OAhg`h|`LqW4>fuA~XE-yV-HK?pA`Os5W?n`!9DgNgmHPL_|D;ZQJE^nq
zk7yH@QJo~8lH}V3-xqaPYdQuMC8SLWHG?iPwH;kRS+`BIMg1}6@%51X1=Z;+!XLvs
z+#WyGc#rNRt`DdO?dFyrL6_aApK20)LM0l4u0T&vmt*d_-yMq7mi9;Pc<ys_)!j~v
zx~_P#^eMLNmwqMAdPMe@jwbJVM_zH2Otx<*QT8KHEmQqgRQ<L<dxHK*P>%)r7Yzsc
AO#lD@

diff --git a/VersionNum b/VersionNum
index 3848a32..7473779 100644
--- a/VersionNum
+++ b/VersionNum
@@ -1,23 +1,21 @@
-/* (0.16)
+/* (0.17)
  *
  * This file is automatically maintained by srccommit, do not edit manually.
- * Last processed by srccommit version: 1.1.
  *
  */
-#define Module_MajorVersion_CMHG        0.16
+#define Module_MajorVersion_CMHG        0.17
 #define Module_MinorVersion_CMHG        
-#define Module_Date_CMHG                03 Aug 2013
+#define Module_Date_CMHG                28 Mar 2020
 
-#define Module_MajorVersion             "0.16"
-#define Module_Version                  16
+#define Module_MajorVersion             "0.17"
+#define Module_Version                  17
 #define Module_MinorVersion             ""
-#define Module_Date                     "03 Aug 2013"
+#define Module_Date                     "28 Mar 2020"
 
-#define Module_ApplicationDate          "03-Aug-13"
+#define Module_ApplicationDate          "28-Mar-20"
 
 #define Module_ComponentName            "MousSetup"
-#define Module_ComponentPath            "castle/RiscOS/Sources/SystemRes/Configure2/PlugIns/MousSetup"
 
-#define Module_FullVersion              "0.16"
-#define Module_HelpVersion              "0.16 (03 Aug 2013)"
-#define Module_LibraryVersionInfo       "0:16"
+#define Module_FullVersion              "0.17"
+#define Module_HelpVersion              "0.17 (28 Mar 2020)"
+#define Module_LibraryVersionInfo       "0:17"
diff --git a/c/Main b/c/Main
index 53faac3..f8bf076 100644
--- a/c/Main
+++ b/c/Main
@@ -31,14 +31,18 @@ Date		Who	Change
 /* Toolbox */
 #include "event.h"
 #include "toolbox.h"
+#include "window.h"
 /* Common */
 #include "error.h"
 #include "misc.h"
+#include "message.h"
 /* Local headers */
 #include "Main.h"  /* includes prototypes for this file */
 #include "ToolboxE.h"
 #include "WimpE.h"
 #include "WimpM.h"
+#include "Settings.h"
+#include "ScrollTypes.h"
 
 #define	WimpVersion	((int) 310)
 
@@ -47,12 +51,64 @@ Date		Who	Change
 	BOOL		quit = FALSE;
 	ObjectId	mainwindow_id;
 	MessagesFD	messages;
+	const _kernel_oserror err_alloc = { 0, "Err_Alloc" };
+	BOOL		wheel_supported;
 
 /* Static global variables */
 
 static	WimpPollBlock	poll_block;
 static	IdBlock		id_block;
 
+static ObjectId auto_scrollbar(const char *windowname)
+{
+  int  screeny;
+  ObjectTemplateHeader *objtemplate;
+  WindowTemplate       *wintemplate;
+  WimpWindow           *windef;
+  ObjectId              window_id;
+
+  /* Read the window object in by hand */
+  throw (toolbox_template_lookup (0, windowname, &objtemplate));
+  if (objtemplate->object_class != Window_ObjectClass) {
+    static const _kernel_oserror e = { 0, "Err_BadClass" };
+    message_error(messages, e);
+  }
+  wintemplate = objtemplate->body;
+  windef = &wintemplate->window;
+  screeny = _swi (OS_ReadModeVariable, _INR(0,1) | _RETURN(2), -1, 12) <<
+            _swi (OS_ReadModeVariable, _INR(0,1) | _RETURN(2), -1, 5);
+
+  /* Calculate the window height compared with the screen and
+   * turn the vertical scrollbar on if it doesn't fit
+   */
+  if ((windef->visible_area.ymax - windef->visible_area.ymin) >= screeny) {
+    windef->flags |= WimpWindow_VScroll;
+  }
+  else {
+    windef->flags &= ~WimpWindow_VScroll;
+  }
+  throw (toolbox_create_object (Toolbox_CreateObject_InCore, objtemplate, &window_id));
+  return window_id;
+}
+
+/*---------------------------------------------------------------------------*
+ * grey_gadget                                                               *
+ *                                                                           *
+ * Grey a a gadget.                                                          *
+ *                                                                           *
+ * In: objectid = ID of the object containing the gadget.                    *
+ *     gadgetid = ID of the gadget.                                          *
+ *---------------------------------------------------------------------------*/
+
+static void grey_gadget(int objectid, int gadgetid)
+{
+  unsigned int flags;
+
+  throw(gadget_get_flags(0, objectid, gadgetid, &flags));
+  flags=flags | Gadget_Faded;
+  throw(gadget_set_flags(0, objectid, gadgetid, flags));
+}
+
 /******	main() ************************************************************\
 
 In:		Command line option:
@@ -70,11 +126,33 @@ int main (int argc, char *argv[])
   throw (event_initialise (&id_block));
   throw (event_set_mask (wimpe_mask));
 
+  /* Disable the scroll wheel settings if the OS/Wimp doesn't support scrolling
+     (no WindowScroll module loaded). No need to read/write a config file which
+     will have no effect. */
+  wheel_supported = (_swix(OS_CLI,_IN(0),"RMEnsure WindowScroll 0") == NULL);
+
   /* Register for messages and events */
   wimpm_register ();
   wimpe_register ();
   toolboxe_register ();
 
+  /* Create & initialise window */
+  mainwindow_id = auto_scrollbar("Mouse");
+  scrolltypes_init ();
+  if (!wheel_supported)
+  {
+    grey_gadget(mainwindow_id, mainwindow_wheelspeedlabel);
+    grey_gadget(mainwindow_id, mainwindow_wheelspeedslow);
+    grey_gadget(mainwindow_id, mainwindow_wheelspeed);
+    grey_gadget(mainwindow_id, mainwindow_wheelspeedfast);
+    grey_gadget(mainwindow_id, mainwindow_linescroll);
+    grey_gadget(mainwindow_id, mainwindow_wheeltarget);
+    grey_gadget(mainwindow_id, mainwindow_wheeltargetlabel);
+  }
+  misc_openwindow (mainwindow_id, TRUE);
+  settings_read (cmos_read);
+  choices_read ();
+
   /* Go */
   error_recover_point();
   while (!quit) {
diff --git a/c/ScrollTypes b/c/ScrollTypes
new file mode 100644
index 0000000..7ae9cf9
--- /dev/null
+++ b/c/ScrollTypes
@@ -0,0 +1,106 @@
+/* Copyright 2020 Acorn Computers Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* Clib */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "swis.h"
+#include "Global/ModHand.h"
+#include "Global/RISCOS.h"
+/* Toolbox */
+#include "wimplib.h"
+#include "gadgets.h"
+/* Common */
+#include "cmos.h"
+#include "message.h"
+#include "str.h"
+#include "misc.h"
+/* Local headers */
+#include "Main.h"
+#include "ScrollTypes.h"  /* includes prototypes for this file */
+#include "Settings.h"
+
+#define NUM_TYPES 4
+
+static const char *scroll_types[NUM_TYPES] =
+{
+  /* n.b. tail end of each identifier must match the *WimpScroll setting */
+  "Type_Pointer",
+  "Type_Focus",
+  "Type_FocusOrPointer",
+  "Type_FavourHigher",
+};
+
+static char *scroll_descs[NUM_TYPES];
+
+void scrolltypes_init (void)
+{
+  /* Construct list of choices */
+  int len = 0;
+  for (int i=0;i<NUM_TYPES;i++)
+  {
+    const char *text = message_lookup_direct(messages,scroll_types[i]);
+    len += str_len(text)+1;
+  }
+  char *buf = malloc(len);
+  if (!buf)
+  {
+    message_error(messages, err_alloc);
+    exit(1);
+  }
+  for (int i=0;i<NUM_TYPES;i++)
+  {
+    scroll_descs[i] = buf;
+    const char *text = message_lookup_direct(messages,scroll_types[i]);
+    len = str_len(text);
+    memcpy(buf, text, len);
+    buf[len] = (i==NUM_TYPES-1 ? 0 : ',');
+    buf += len+1;
+  }
+  /* Initialise the string set */
+  throw(stringset_set_available(0, mainwindow_id, mainwindow_wheeltarget, scroll_descs[0]));
+  /* Now go back and null-terminate the options, ready for getselection */
+  for (int i=1;i<NUM_TYPES;i++)
+  {
+    scroll_descs[i][-1] = 0;
+  }
+}
+
+void scrolltypes_setselection (const char *value)
+{
+  for(int i=0;i<NUM_TYPES;i++)
+  {
+    if (!strcmp(value,scroll_types[i] + 5))
+    {
+      throw (stringset_set_selected (0, mainwindow_id, mainwindow_wheeltarget, scroll_descs[i]));
+      return;
+    }
+  }
+}
+
+const char *scrolltypes_getselection (void)
+{
+  char choice[256];
+  stringset_get_selected(0, mainwindow_id, mainwindow_wheeltarget, choice, 256, NULL);
+  for(int i=0;i<NUM_TYPES;i++)
+  {
+    if (!strcmp(choice,scroll_descs[i]))
+    {
+      return scroll_types[i] + 5;
+    }
+  }
+  return NULL;
+}
diff --git a/c/Settings b/c/Settings
index baa7375..f25597c 100644
--- a/c/Settings
+++ b/c/Settings
@@ -34,6 +34,8 @@ Date		Who	Change
 #include <string.h>
 #include "swis.h"
 #include "Global/OsWords.h"
+#include "Global/FileTypes.h"
+#include "Interface/HighFSI.h"
 /* Toolbox */
 #include "toolbox.h"
 #include "window.h"
@@ -41,10 +43,12 @@ Date		Who	Change
 /* Common */
 #include "cmos.h"
 #include "misc.h"
+#include "message.h"
 /* local headers */
 #include "Main.h"
 #include "MouseType.h"
 #include "Settings.h"  /* includes prototypes for this file */
+#include "ScrollTypes.h"
 
 #define mousespeed_slider_upperbound	((int) 9)
 
@@ -150,3 +154,129 @@ BOOL settings_write (void)
 //
   return TRUE;
 }
+
+/******	choices_default() *************************************************\
+
+Purpose:	Update GUI to default settings for Choices
+
+\**************************************************************************/
+
+void choices_default(void)
+{
+  if (!wheel_supported)
+  {
+    return;
+  }
+  throw (optionbutton_set_state (0, mainwindow_id, mainwindow_linescroll, 0));
+  scrolltypes_setselection("Pointer");
+  slider_set_value(0, mainwindow_id, mainwindow_wheelspeed, 40);
+}
+
+/******	parse_wimpscroll_command() ****************************************\
+
+Purpose:	Parse the given *WimpScroll command argument list and update
+		the GUI.
+In:		Settings string to parse
+
+\**************************************************************************/
+
+static void parse_wimpscroll_command(const char *arg_string)
+{
+  /* Parse the settings */
+  void *buf[64];
+  _kernel_oserror *e = _swix(OS_ReadArgs,_INR(0,3),"Type,LineScroll/S,Speed/E",arg_string,buf,sizeof(buf));
+  if (e)
+  {
+    throw(e);
+    return;
+  }
+
+  if (buf[0])
+  {
+    scrolltypes_setselection((char *) buf[0]);
+  }
+
+  throw (optionbutton_set_state (0, mainwindow_id, mainwindow_linescroll, (buf[1] != NULL) ? 1 : 0));
+
+  if (buf[2])
+  {
+    const char *speed = (const char *) buf[2];
+    if (*speed == 0)
+    {
+      int speed_value = speed[1] + (speed[2]<<8) + (speed[3]<<16) + (speed[4]<<24);
+      throw (slider_set_value (0, mainwindow_id, mainwindow_wheelspeed, speed_value));
+    }
+  }
+}
+
+/******	choices_read() ****************************************************\
+
+Purpose:	Reads current settings from Choices, reflect them in GUI
+
+\**************************************************************************/
+
+void choices_read(void)
+{
+  if (!wheel_supported)
+  {
+    return;
+  }
+
+  /* Set GUI to default settings */
+  choices_default();
+
+  /* Read WindowScroll settings */
+  FILE *fp;
+  char  string[1024];
+
+  fp = fopen(ChoicesFileRO, "r");
+  if (fp != NULL)
+  {
+      while (fgets(string, 1024, fp))
+      {
+          if (strncmp(string, "X WimpScroll ", 13)==0) parse_wimpscroll_command(string+13);
+      }
+      fclose(fp);
+  }
+}
+
+/******	choices_write() ***************************************************\
+
+Purpose:	Reads current settings from GUI, save them to Choices,
+		and apply them.
+
+\**************************************************************************/
+
+void choices_write(void)
+{
+  if (!wheel_supported)
+  {
+    return;
+  }
+
+  FILE *fp;
+  int linescroll,speed;
+  const char *scrolltype = scrolltypes_getselection();
+
+  throw (slider_get_value (0, mainwindow_id, mainwindow_wheelspeed, &speed));
+  throw (optionbutton_get_state (0, mainwindow_id, mainwindow_linescroll, &linescroll));
+
+  fp = fopen(ChoicesFile, "w");
+  if (fp != NULL)
+  {
+    fprintf(fp,
+            "X WimpScroll -Type %s %s-Speed %d\n",
+            scrolltype,
+            (linescroll ? "-LineScroll ":""),
+            speed);
+    fclose(fp);
+  }
+  _swix(OS_File, _INR(0,2),
+        OSFile_SetType,
+        ChoicesFile,
+        FileType_Obey);
+
+  char string[256];
+  sprintf(string, "Filer_Run %s", ChoicesFile);
+  _swix(OS_CLI, _IN(0), string);
+}
diff --git a/c/ToolboxE b/c/ToolboxE
index 491db84..6731d8f 100644
--- a/c/ToolboxE
+++ b/c/ToolboxE
@@ -44,7 +44,6 @@ Date		Who	Change
 
 static int toolboxe_actionbuttonselected (int event_code, ToolboxEvent *event, IdBlock *id_block, void *handle);
 static int toolboxe_stringsetabouttobeshown (int event_code, ToolboxEvent *event, IdBlock *id_block, void *handle);
-static int toolboxe_objectautocreated (int event_code, ToolboxEvent *event, IdBlock *id_block, void *handle);
 
 int toolboxe_events [5] =     { ActionButton_Selected,
 				StringSet_AboutToBeShown,
@@ -55,7 +54,6 @@ void toolboxe_register (void)
 {
   throw (event_register_toolbox_handler (-1, ActionButton_Selected, toolboxe_actionbuttonselected, NULL));
   throw (event_register_toolbox_handler (-1, StringSet_AboutToBeShown, toolboxe_stringsetabouttobeshown, NULL));
-  throw (event_register_toolbox_handler (-1, Toolbox_ObjectAutoCreated, toolboxe_objectautocreated, NULL));
 }
 
 /******	toolboxe_actionbuttonselected() ***********************************\
@@ -69,13 +67,19 @@ static int toolboxe_actionbuttonselected (int event_code, ToolboxEvent *event, I
   switch (id_block->self_component) {
     case mainwindow_default:
       settings_read (cmos_default);
+      choices_default ();
       break;
     case mainwindow_cancel:
       if (!(event->hdr.flags & 1)) quit = TRUE;
-      else settings_read (cmos_read);
+      else
+      {
+        settings_read (cmos_read);
+        choices_read ();
+      }
       break;
     case mainwindow_set:
       if (settings_write ()) if (!(event->hdr.flags & 1)) quit = TRUE;
+      choices_write ();
       break;
   }
   return 1;
@@ -95,7 +99,6 @@ static int toolboxe_stringsetabouttobeshown (int event_code, ToolboxEvent *event
   newcrc = mousetype_getavailable (&buffer);
   if (buffer == NULL)
   {
-    static const _kernel_oserror err_alloc = { 0, "Err_Alloc" };
     message_error(messages, err_alloc);
     return 1;
   }
@@ -109,17 +112,3 @@ static int toolboxe_stringsetabouttobeshown (int event_code, ToolboxEvent *event
 
   return 1;
 }
-
-/******	toolboxe_objectautocreated() **************************************\
-
-Purpose:	Handles Toolbox_ObjectAutoCreated event
-
-\**************************************************************************/
-
-static int toolboxe_objectautocreated (int event_code, ToolboxEvent *event, IdBlock *id_block, void *handle)
-{
-  mainwindow_id = id_block->self_id;
-  misc_openwindow (mainwindow_id, TRUE);
-  settings_read (cmos_read);
-  return 1;
-}
diff --git a/h/Main b/h/Main
index efb1a54..690a123 100644
--- a/h/Main
+++ b/h/Main
@@ -37,6 +37,8 @@ Date		Who	Change
 extern BOOL quit;
 extern ObjectId mainwindow_id;
 extern MessagesFD messages;
+extern const _kernel_oserror err_alloc;
+extern BOOL wheel_supported;
 
 /* Prototypes */
 
diff --git a/h/ScrollTypes b/h/ScrollTypes
new file mode 100644
index 0000000..986a0c5
--- /dev/null
+++ b/h/ScrollTypes
@@ -0,0 +1,25 @@
+/* Copyright 2020 Acorn Computers Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __scrolltypes_h
+#define __scrolltypes_h
+
+/* Prototypes */
+
+extern void scrolltypes_init (void);
+extern void scrolltypes_setselection (const char *value);
+extern const char *scrolltypes_getselection (void);
+
+#endif
diff --git a/h/Settings b/h/Settings
index 17b21b1..34f5bee 100644
--- a/h/Settings
+++ b/h/Settings
@@ -59,6 +59,16 @@ Date		Who	Change
 #define mainwindow_set			((ComponentId) 0x100)
 #define mainwindow_cancel		((ComponentId) 0x101)
 #define mainwindow_default		((ComponentId) 0x102)
+#define mainwindow_wheelspeedlabel	((ComponentId) 0x201)
+#define mainwindow_wheelspeedslow	((ComponentId) 0x202)
+#define mainwindow_wheelspeed		((ComponentId) 0x203)
+#define mainwindow_wheelspeedfast	((ComponentId) 0x204)
+#define mainwindow_linescroll		((ComponentId) 0x205)
+#define mainwindow_wheeltarget		((ComponentId) 0x206)
+#define mainwindow_wheeltargetlabel	((ComponentId) 0x207)
+
+#define ChoicesFile           "<Choices$Write>.Boot.Tasks.WimpScroll"
+#define ChoicesFileRO         "Choices:Boot.Tasks.WimpScroll"
 
 /* Global variables */
 
@@ -69,4 +79,8 @@ extern const cmos cmos_details [];
 extern void settings_read (int(*get)(cmos item, void *messages));
 extern BOOL settings_write (void);
 
+extern void choices_default(void);
+extern void choices_read(void);
+extern void choices_write(void);
+
 #endif
-- 
GitLab