Programming AmigaOS in C

Reaction Window

a) Creating a reaction window

To create a reaction window, you need to use the window.class, you need to create a WindowObject and then specify its parameters with a list of tags. WindowObject is actually a macro for 'NewObject( WINDOW_GetClass(), NULL' which creates a new object and provides the window class. The parameter tags are defined in intuiton/intuition.h (WA_) and classes/window.h (WINDOW_).

Here is an example of an instance of a Reaction 200x150 window

 windowObj = WindowObject,
   WA_ScreenTitle, "ReAction",
   WA_Title, "ReAction Window Example",
   WA_Activate, TRUE,
   WA_DepthGadget, TRUE,
   WA_DragBar, TRUE,
   WA_CloseGadget, TRUE,
   WA_SizeGadget, TRUE,
   WA_Width, 200,
   WA_Height, 150,
   WINDOW_IconifyGadget, TRUE,
   WINDOW_IconTitle, "Example",
   WINDOW_AppPort, AppPort,
   WINDOW_Position, WPOS_CENTERMOUSE,
   WINDOW_ParentGroup, VLayoutObject,
       LAYOUT_SpaceOuter, TRUE,
       LAYOUT_DeferLayout, TRUE,
   EndGroup, 
 EndWindow;

The variable win_object is of the type Object. The Message Port or AppPort value is set using 'AppPort = CreateMsgPort()' or for AmigaOS 4 use, 'AppPort = IExec->AllocSysObjectTags(ASOT_PORT, TAG_DONE);' (the CreateMsgPort()' command is now deprecated).
Notice that the is a Endobject tag, so for WindowObject there is a EndWindow tab, for VLayoutObject there is an EndGroup tag. It is a macro that basically closes the parameter list with a 'TAG_END)'. VLayoutObject means that the window will use a vertical orientated layout. SpaceOuter defines whether that there is space around objects such as gadgets and DeferLayout defines that it will defer GM_LAYOUT and GM_RENDER from the input.device and let the application take care of those events.

For Storm C or VBCC, the above code gives a 'unterminated macro call' error, so you will have to expand the WindowObject and VLayoutObject to the full NewObject function call and replace the EndVLayout and EndWindow to TAG_END) equivalents.

b) Window functions

To actually open the window, use the RA_OpenWindow() function. For example,

myWindow = (struct Window *)RA_OpenWindow(windowObj);

The RA_OpenWindow function is a macro for DoMethod(win, WM_OPEN, NULL) which will called the WM_OPEN method for the window object (windowObj).

To free the Message Port (AppPort), use ether:
if (AppPort) DeleteMsgPort(AppPort);
if (AppPort) IExec->FreeSysObject(ASOT_PORT, AppPort); /* AmigaOS 4 */

To close the window and delete the object use the RA_CloseWindow or/and the DisposeObject() function. For example,

RA_CloseWindow(myWindow);
or
DisposeObject(myWindow);

Other methods for windows include:

RA_HandleInput(win, code) - Handle a code word from a gadget.

This function is needed to determine what gadgets a users has clicked on and we need to perform some actions:

app = (1L << AppPort->mp_SigBit);
/* Obtain the window wait signal mask */
GetAttr(WINDOW_SigMask, windowObj, &signal);
wait = Wait(signal | SIGBREAKF_CTRL_C | app);
/* Handle message from window and process it */
while (( result = RA_HandleInput(windowObj, &code)) != WHMI_LASTMSG)
{
    switch (result & WHMI_CLASSMASK)
    {
        case WMHI_CLOSEWINDOW:
            done = TRUE;
            break;
       case WMHI_GADGETUP:
             /* deal with gadets here */
       case WMHI_ICONIFY:
             RA_Iconify(windowObj);
             myWindow = NULL;
             break;
        case WMHI_UNICONIFY:
              myWindow = (struct Window *)RA_OpenWindow(windowObj);
              if (myWindow)
             {
                    GetAttr(WINDOW_SigMask, windowObj, &signal);
             } else
             {
                       done = TRUE; /* error opening window */
             }
             break;
       }
}

Here, the program will wait for some event from the system or the user. If a signal is received then it will return a WHMI result by using the RA_HandleInput function.
The result is masked with WHMI_CLASSMASK to get the correct value for the switch statement. The switch statement can then either close the window if the close
button is pressed, handle any gadgets, iconify the window if the iconify gadget is selected or the window re-opened if the window icon is selected to expand it out again.

RA_OpenWindow(win) - Open a Reaction Window. Returns a point to struct Window.
RA_CloseWindow(win) - Close a Reaction Window.
RA_HandleInput(win, code) - Handle any input from a window.
RA_Iconify(win) - Turn window into an icon on desktop.
RA_Uniconify(win) - Turn icon back into a full window.

In AmigaOS 4, the Reaction windows functions have been replace with enhanced Intuition functions which will work with Boopsi/Reaction interfaces, although you can still use RA functions to make it easier to migrate AmigaOS 3 programs across:

OpenWindowTags() - Open a window with Tags to set parameters.
CloseWindow() - Close a Window.

c) List of events that can be handled.

The following values are defined in the header classes\window.h for events that can be handled from a Reaction Window

WMHI_CLOSEWINDOW = The close gadget was clicked or a hook function trigged close
WMHI_GADGETUP = A gadget was released
WMHI_INACTIVE = The window was de-activated
WMHI_ACTIVE = The window was activated
WMHI_NEWSIZE = The window was resized
WMHI_MENUPICK = A menu item was picked
WMHI_MENUHELP = Help was hit in a menu
WMHI_GADGETHELP = A gadget returns a help code
WMHI_ICONIFY = Window requests to be iconified
WMHI_UNICONIFY = Window was uniconified
WMHI_RAWKEY = Raw key codes
WMHI_VANILLAKEY =Vanilla key codes
WMHI_CHANGEWINDOW = Window moved (or depth arranged)
WMHI_INTUITICK= IDCMP intuitick (maximum 10 per second)
WMHI_MOUSEMOVE = IDCMP mouse move
WMHI_MOUSEBUTTONS= IDCMP mouse buttons
WMHI_DISPOSEDWINDOW = hook function triggered disposal

Example reaction window code

Reaction gadgets