riscos.c
--------

History
-------
26th October 1992  J R C  Started

   This module uses the |callback_| module to provide a callback list and a
useful set of callbacks specific to Wimp_Poll. It also provides various of
the usual functions without which no application is complete and some
non-function external symbols.

   These are used to provide access to the module in the following way:
|riscos_callback| is a callback list, initially empty, which is examined
every time Wimp_Poll returns to get the application to do the work
appropriate for that event. If an application wants only to install an icon
bar icon, and then wait for a QUIT message from the WIMP, it would look like
this (ignoring all error checking):

      static wimp_message_list Messages = ...;

      static bool Quit (void *null, void *block)

      {  riscos_quit = TRUE;
         return TRUE;
      }

      main (void)

      {  riscos_initialise ("Small", &Messages, NULL, &myself);

         callback_register (riscos_callback, &Quit, NULL, 2,
               wimp_MESSAGE, message_QUIT);
         callback_register (riscos_callback, &Quit, NULL, 2,
               wimp_MESSAGE_RECORDED, message_QUIT);

         ... put icon on the icon bar ...

         riscos ();

         riscos_terminate ();
      }

The function |riscos| returns only when the extern |riscos_quit| is set.
|Riscos_initialise| simply creates the empty callback list |riscos_callback|
and remembers the programme name for use by |riscos_complain|.

   By adding and removing callbacks, any combination of events can be
handled by any module. The convention of the |callback_| module is that any
callback (e g, |Quit| above) that return |TRUE| is considered to have
"handled" the event: no other calls back are made.

   In addition to regiatering and deregistering callbacks, an application
may need access to the following variables. (Access to these should probably
be centralised further to allow usage counts to be maintained for mask bits,
etc):

         |riscos_mask| is the mask used by Wimp_Poll or Wimp_PollIdle (type
      |int|);

         |riscos_timeout| is the timeout to be handed to Wimp_PollIdle, if
      used;

         |riscos_quit| is to be set to TRUE to close down the application;

         |riscos_polling_idle|, if set to |TRUE|, causes Wimp_PollIdle to be
      used instead of Wimp_Poll;

         |riscos_pollword| is set to the word to use for event
      PollwordNonZero (if used).

   The module also exports other functions,as alluded to above. These are:

         |riscos_error_lookup| which takes an error token with a variable
      number of arguments and formats it into an error block;

         |riscos__assert|, usually used via the macro |riscos_assert|, which
      provides an assertion facility that uses Wimp_ReportError;

         |riscos_complain| to report an error.

         |riscos_terminate| to delete the callback list creted by
      |riscos_initialise|.

   So, the main function is |riscos|. It works by calling Wimp_Poll (or
Wimp_PollIdle), and then calling |callback| with a certain list of integers
appropriate to the event just returned to find out wht the user wants done
with that event. The integers it uses are as follows:

      wimp_NULL_REASON_CODE, wimp_DRAG_BOX:
         event number only

      wimp_REDRAW_WINDOW_REQUEST:
         event number, window handle

      wimp_OPEN_WINDOW_REQUEST:
         event number, window handle

      wimp_CLOSE_WINDOW_REQUEST:
         event number, window handle, mouse buttons, shifting keys

      wimp_POINTER_LEAVING_WINDOW:
         event number, window handle

      wimp_POINTER_ENTERING_WINDOW:
         event number, window handle

      wimp_MOUSE_CLICK:
         event number, window handle, icon handle, mouse buttons, shifting
               keys

      wimp_KEY_PRESSED:
         event number, window handle, icon handle, character
               (this allows different handlers to be provided for different
               keys - e g, F1, F2 etc, while another handler takes
               everything else.

      wimp_MENU_SELECTION:
         event number, main menu entry number, submenu entry number,
               subsubmenu entry number, ... (as many as provided)

      wimp_SCROLL_REQUEST:
         event number, window handle, mouse buttons, shifting keys

      wimp_LOSE_CARET, wimp_GAIN_CARET:
         event number, window handle, icon handle

      wimp_POLLWORD_NON_ZERO:
         event number, pollword address

      wimp_MESSAGE, wimp_MESSAGE_RECORDED, wimp_MESSAGE_ACKNOWLEDGE:
         depends on the message type

         message_DATA_SAVE, message_DATA_SAVE_ACK, message_DATA_LOAD,
               message_DATA_LOAD_ACK, message_DATA_OPEN:
            event number, action code, window handle, icon handle, file type

         message_DEVICE_CLAIM, message_DEVICE_IN_USE:
            event number, action code, major device, minor device
            
         message_MENU_WARNING:
            event number, action code, main menu entry number, submenu entry
                  number, subsubmenu entry number, ... (as many as provided)

         default:
            event number, action code

      default:
         callback (riscos_callback, &Block, 0);

   The list here seems to work well; it is possible that some of these
sequences are not long enough. For example, the original version did not use
the file type word on the callbacks for wimp_MESSAGE_DATA_LOAD etc; but by
providing it, the user can register separate callbacks for different file
types arriving on windows (without losing the ability to specify a default
callback to be used when there is no more specific one). (ViewDraw does
this, and so ignores non-drawfiles dropped onto its icon bar icon.)

   There are two cases here of using information that the WIMP does not
actually return in the Wimp_Block structure. The mouse button state,
although returned in the structure for a Wimp_MouseClick event, are not
returned for Wimp_CloseWindowRequest or Wimp_ScrollRequest. Neverthless,
they are useful in these cases as they allow the application to take
different action depending on (e g) whether a window was closed with SELECT
or ADJUST.

   In addition, the states of the shifting keys are returned for
Wimp_CloseWindowRequest, Wimp_MouseClick and Wimp_ScrollRequest. These are
read by calling OS_Byte 129 and disjoining the states together into a word
of bits:

         bit 0 <=> SHIFT is down
         bit 1 <=> CTRL  is down
         bit 2 <=> ALT   is down

(constants riscos_SHIFT, riscos_CTRL and riscos_ALT are defined with these
values). This could also encourage more uniformity in the treatment of these
keys.

   There are also two auxiliary functions: |Shifting_Keys| returns the
states of the SHIFT, CTRL and ALT keys, while |Mouse_Buttons| returns the
state of the mouse buttons. These are used when the information is not
returned via Wimp_Poll: this fact is indicated in the list above by the
phrases "shifting keys" and "mouse buttons".
