Wait() for a message from Intuition/Zune about user activity or other events.

Copy needed data from the message and tell Intuition/Zune you received it by replying. Look at the data and take the appropriate action. e.g. (presses a key on the keyboard, moves the mouse, gadgets hits, menu item selection, time elapsing, disk insertion, disk removal, and window rearrangement.)

Repeat until the user wants to quit. (then closes windows, screen(s) and libraries)

Most of the time, you will not need to setup a screen as you will frequently use an already in use public screen (Wanderer, Scalos or another WB replacement), so you can jump to opening windows on that screen.

AROS (like Amigas before) supports a concept called screens, each screen can be setup with a specific resolution and color depth, limited by the monitor drivers or CRT or LCD display used.

Own public screen where main application can "host" additional modules with same screen specs etc. if needed

Default shared public screen (NULL usually known as Wanderer, Scalos or Workbook) means multiple applications reside on the same screen which saves memory

Last option, is a custom screen creates a new display for each application, i.e. if you want a specific resolution and color depth. Opening any new screen uses memory.

Each line adds and stores a bit of information about the screen in use. Each additional struct inside the Screen struct is an already existing 'blob' of pre-defined data storage inside AROS. A lot of AROS depends on struct's being used inside newer struct's to aid and speed up development.

every screen has a struct ViewPort (screen represent by graphics library) and each screen has a drawinfo (high level) and struct RastPort (low level handle that graphics library uses to draw on that screen). View is the whole display, including all visible screens accessed by ViewAddress()

Tags are a list of parameter names followed comma and then by a value. For example, to specify the DefaultTitle of a screen you use the SA_Title followed a comma and then by the title in quotes and there are many other tags that can be used to define bits of a screen, see later for a list. The last tag item should always be TAG_DONE.

The title bar of the screen, not the title bar of the window, is drawn in front of the window. If moving the window from its default 0,0 position with WA_Top and/or WA_Left (SA_ShowTitle is FALSE of course), just ignore those tags in fullscreen mode instead of setting them to 0.

// Opens a PubScreen. The name can be given as argument. // Default name is "MYPUBSCREEN".#include<proto/intuition.h>#include<proto/dos.h>#include<proto/exec.h>#include<stdlib.h>#include<stdio.h>structScreen*myscreen;structWindow*mywindow;BYTEsignalnum;voidclean_exit(STRPTRtxt){if(mywindow)CloseWindow(mywindow);if(myscreen)CloseScreen(myscreen);FreeSignal(signalnum);if(txt){PutStr(txt);exit(RETURN_FAIL);}exit(RETURN_OK);}intmain(intargc,char**argv){BOOLdone=FALSE;BOOLclosewindow=FALSE;ULONGsignals,winsig,pubsig;structIntuiMessage*message;char*name;if(argc==2){name=argv[1];}else{name="MYPUBSCREEN";}if((signalnum=AllocSignal(-1))==-1){clean_exit("Can't allocate signal\n");}if((myscreen=OpenScreenTags(NULL,SA_PubName,name,SA_PubSig,signalnum,SA_LikeWorkbench,TRUE,SA_Title,name,TAG_DONE))==NULL){clean_exit("Can't open screen\n");}if((mywindow=OpenWindowTags(NULL,WA_Left,30,WA_Top,30,WA_Width,250,WA_Height,100,WA_DragBar,TRUE,WA_DepthGadget,TRUE,WA_CloseGadget,TRUE,WA_Activate,TRUE,WA_Title,"Close me to close the screen",WA_IDCMP,IDCMP_CLOSEWINDOW,WA_PubScreen,myscreen,TAG_DONE))==NULL){clean_exit("Can't open window\n");}if((PubScreenStatus(myscreen,0)&1)==0){clean_exit("Can't make screen public");}winsig=1L<<mywindow->UserPort->mp_SigBit;pubsig=1L<<signalnum;while(!done){signals=Wait(winsig|pubsig);if(mywindow&&(signals&winsig)){while(NULL!=(message=(structIntuiMessage*)GetMsg(mywindow->UserPort))){if(message->Class==IDCMP_CLOSEWINDOW){closewindow=TRUE;}ReplyMsg((structMessage*)message);}}if(signals&pubsig){if(PubScreenStatus(myscreen,PSNF_PRIVATE)&1){done=TRUE;}else{PutStr("Failed to make screen private\n");}}if(closewindow){if(mywindow)CloseWindow(mywindow);winsig=0;mywindow=NULL;closewindow=FALSE;}}clean_exit(NULL);return0;}

#include<proto/intuition.h>#include<proto/dos.h>#include<intuition/screens.h>intmain(){/* makes a copy of the Screen struct(ure) and calls that copy myScreen, changes are made to this copy */structScreen*myScreen;/* you can call the copy 'myScreen' any name you like, as long as you use it throughout the program consistently *//* describe how 'myScreen' looks like by using tags SA_? */myScreen=OpenScreenTags(NULL,SA_Left,0,SA_Top,0,SA_Width,640,SA_Height,480,SA_Depth,8,SA_Title,"My New Screen",SA_Type,PUBLICSCREEN,SA_SysFont,1,TAG_DONE);Delay(500);/* check if screen open, returns TRUE for success and FALSE for failure, if so, use CloseScreen() command to close */if(myScreen)CloseScreen(myScreen);}

#include<proto/intuition.h>#include<proto/dos.h>#include<intuition/screens.h>#include<proto/graphics.h>intmain(void){structScreen*scr;structWindow*win;structRastPort*rp;if(scr=OpenScreenTags(NULL,SA_LikeWorkbench,TRUE,TAG_END))/* open RTG screen */{Delay(50);/* one second */if(win=OpenWindowTags(NULL,WA_CustomScreen,scr,WA_Left,100,WA_Top,100,WA_Width,200,WA_Height,100,TAG_END)){rp=win->RPort;Move(rp,20,40);Text(rp,"Beep !",6);/* you won't see DisplayBeep on a RTG screen */Delay(50);/* one second */CloseWindow(win);}Delay(100);/* two seconds */CloseScreen(scr);}return(0);}

If you do not wish to use a custom screen, then you can use an existing public screen such as Wanderer.
Screens can be closed at any time, so to prevent that, the public screen should be locked while the application is running. You can do this using the LockPubScreen function.

myScreen = LockPubScreen(name)

where name is the name of the Public Screen to lock.If no name (NULL) is given then it will use the Workbench public screen. Once done with the Public screen you can then Unlock it

Having set a screen, you can now have as many windows on that screen as you want.

Opening Windows is very similar to opening screens, OpenWindowTags() with window tags as well...

As Screen tags started with SA_, Window tags start with WA_ and in the case of WA_IDCMP and WA_Flags have further sub-tags. A list follows later...

So when I do window->Width / rport->TxWidth, the number of columns ends up being greater than the visible area, so text goes off screen, same for height. Is there a way to get the window size less the attached gadgets/widgets?
For a non borderless window (aka normal window ), the usable width is w->Width - w->BorderLeft - w->BorderRight, and the height, w->Height - w->BorderTop - w->BorderBottom.

For a GimmeZeroZero window, use w->GZZWidth and w->GZZHeight instead w->Width and w->Height.
GZZWidth and GZZHeight are maintained for non-GZZ windows, too. You don't need to calculate them yourself.

To be able to resize a window you need to set WA_MinWidth, WA_MinHeight, WA_MaxWidth and WA_MaxHeight because they all default to WA_Width resp. WA_Height.

For AROS you should omit all the usual #?Base (GfxBase, IntuitionBase, DOSBase,... ) declarations and "OpenLibrary() & CloseLibrary()" calls for them because AROS GCC compiler opens and closes them automatically for you when it sees a reference. Most of the core libraries are auto opened by the compiler.

This is for background knowledge only. When a library is opened, it will return a pointer to a Library structure or a Base structure specific to that library otherwise it will return a NULL value. Converting old Commodore examples is probably a good way to get understanding of Amiga program to AROS program differences. NOTE those old examples need editing because of OpenLibrary, CloseLibrary and #?base stuff... In the past, to close a library, use the CloseLibrary() function and provide the pointer to the Library or Base structure which was returned in the OpenLibrary(). It is normal practice to test that the library was opened before trying to close it.

#include<proto/exec.h>#include<exec/libraries.h>#include<proto/dos.h>#include<proto/intuition.h>#include<intuition/intuition.h>intmain(intargc,char*argv[]){interror=RETURN_OK;/* makes a copy of the Window struct(ure) and calls that copy win, changes are made to this copy */structWindow*win;/* describe the copy window 'win' looks like by using tags WA_?, this is separate from the struct stuff above */win=OpenWindowTags(NULL,WA_Width,200,WA_Height,100,WA_Title,"Hello World!",TAG_DONE);if(win){/* Now wait for two seconds, so we can look at our nice window. */Delay(100);/* We close our window again. */CloseWindow(win);}returnerror;}

struct TagItem + OpenWindowTagList() Open a window. Not used much see below...
OpenWindowTags() Alternate calling sequence for OpenWindowTagList().
CloseWindow() Close a window.
BeginRefresh() Turn on optimized window refresh mode.
EndRefresh() Turn off optimized window refresh mode.
RefreshWindowFrame() Redraw the borders and border gadgets of an open window.
ActivateWindow() Make an open window active.
SizeWindow() Change the size of an open window.
MoveWindow() Change the position of an open window.
ChangeWindowBox() Change the size and position of an open window.
WindowLimits() Change the minimum and maximum sizes of an open window.
WindowToBack() Move a window behind all other windows.
WindowToFront() Move a window in front of all other windows.
MoveWindowInFrontOf() Move a window in front of another window.
ZipWindow() Change the size of window to its alternate size.
SetWindowTitles() Change the window titles for the window and the screen.
SetPointer() Set up a custom pointer to display whenever the window is active.
ClearPointer() Restore the mouse pointer to its default imagery.

WA_Left - Left edge of the window
WA_Top - Top edge of the window
WA_Width - Width of the window
WA_Height - Height of the window
WA_DetailPen - Pen number for window details (obsolete)
WA_BlockPen - Pen number for filled blocks (obsolete)
WA_IDCMP - Define what events should send messages to your task
IDCMP_CLOSEWINDOW - Check if the Window Close button has been pressed. If so, then close down program
IDCMP_GADGETUP - Check to see if a Gadget has been pressed AND released
IDCMP_GADGETDOWN - Check to see if a Gadget has been pressed (but not released yet) - Not often used
IDCMP_MENUPICK - Check to see if a menu item has been selected
IDCMP_ACTIVEWINDOW - Check to see if Window has been activated (clicked on title bar)
IDCMP_MOUSEMOVE - Check if mouse moves (useful to keep track of x,y position)
IDCMP_NEWSIZE - Check to see if window has been resized
IDCMP_VANILLAKEY - Check to see if a key on keyboard has been pressed
IDCMP_RAWKEY -
IDCMP_NEWPREFS -
IDCMP_DISKINSERTED - Check to see if a floppy disk has been inserted, probably ready for saving
IDCMP_DISKREMOVED - message type is broadcast to all IDCMP that have this flag set, not just active win
IDCMP_INTUITICKS -
IDCMP_IDCMPUPDATE -
IDCMP_CHANGEWINDOW -
IDCMP_LONELYMESSAGE - system use only
WA_Flags -
WFLG_SIZEGADGET, WFLG_DRAGBAR, WFLG_DEPTHGADGET, WFLG_CLOSEGADGET
WFLG_BORDERLESS, WFLG_ACTIVATE, WFLG_NEWLOOKMENUS
WA_Gadgets (struct Gadget *) - Pointer to a linked list of gadgets (WB 2.0 only)
WA_Title (STRPTR) - Window title string
WA_CustomScreen (struct Screen *) - Open window on the given screen
WA_MinWidth
WA_MinHeight
WA_MaxWidth
WA_MaxHeight
WA_SizeGadget (BOOL) - Make window resizeable
WA_DragBar (BOOL) - Make window dragable
WA_DepthGadget (BOOL) - Add a depth gadget
WA_CloseGadget (BOOL) - Add a close gadget
WA_Backdrop (BOOL) - Create a window which is placed behind other windows
WA_ReportMouse (BOOL) - Store mouse position in struct Window
WA_NoCareRefresh (BOOL) - Use this if you don't want to be responsible for calling BeginRefresh()/EndRefresh()
WA_Borderless (BOOL) - Create borderless window
WA_Activate (BOOL) - Make this window the active one, i.e. it receives the input from mouse and keyboard
WA_RMBTrap (BOOL) - Set to TRUE if you want to get button events events for the right mouse button
WA_SimpleRefresh (BOOL) - Enable simplerefresh mode. Only specify if TRUE
WA_SmartRefresh (BOOL) - Enable smartrefresh mode. Only specify if TRUE
WA_SuperBitMap (struct BitMap *) - Create window with superbitmap refreshing, 0 to keep the current size as limit
WA_SizeBRight (BOOL) - Place size gadget in right window border
WA_SizeBBottom (BOOL) - Place size gadget in bottom window border
WA_GimmeZeroZero (BOOL) - Create a GimmeZeroZero window
WA_NewLookMenus (BOOL) - Use DrawInfo colors for rendering the menu bar
WA_ScreenTitle (STRPTR) - Screen title which is shown when window is active
WA_AutoAdjust (BOOL) - usually TRUE make the window to fit on the screen, wrt WA_MinWidth and WA_MinHeight
WA_InnerWidth
WA_InnerHeight - Dimensions of the interior region of the window - this restricts border gadgets
GACT_LEFTBORDER gadgets can't be GFLG_RELWIDTH if WA_InnerWidth is used
GACT_RIGHTBORDER gadgets must be GFLG_RELRIGHT if WA_InnerWidth is used
GACT_TOPBORDER gadgets can't be GFLG_RELHEIGHT if WA_InnerHeight is used
GACT_BOTTOMBORDER gadgets must be GFLG_RELBOTTOM if WA_InnerHeight is used
WA_PubScreen (struct Screen *) - Open the window on the public screen - NULL being WB replacement
WA_PubScreenName (STRPTR) - Open the window on the public screen (name)
WA_PubScreenFallBack (BOOL) - if TRUE fallback to default public screen if other public screen is not available
WA_Zoom (WORD *) - 4 WORDs set Left Top Width Height of the other zoom position - also adds zoom gadget
WA_MouseQueue - Limits the number of possible mousemove messages. Can be changed with SetMouseQueue()
WA_RptQueue - Limits the number of possible repeated IDCMP_RAWKEY, IDCMP_VANILLAKEY and IDCMP_IDCMPUPDATE messages
WA_BackFill (struct Hook *) - Function to be called for backfilling
WA_MenuHelp (BOOL) - Enables menuhelp. Pressing the help key during menu handling sends IDCMP_MENUHELP messages.
WA_NotifyDepth (BOOL) - If TRUE send IDCMP_CHANGEWINDOW events when window is depth arranged. Code field=CWCODE_DEPTH
WA_Checkmark (struct Image *) - Image to use as a checkmark in menus
WA_AmigaKey (struct Image *) - Image to use as the Amiga-key symbol in menus
WA_Pointer (APTR) - The pointer to associate with the window. Use NULL for the Preferences default pointer
WA_BusyPointer (BOOL) - Enable the Preferences busy-pointer. Default is FALSE
WA_PointerDelay (BOOL) - Set this to TRUE to delay change of the pointer image - prevents flickering
WA_HelpGroup (ULONG) - Get IDCMP_GADGETHELP messages from the active window and all other windows
WA_HelpGroupWindow (struct Window *) - Similar for WA_HelpGroup. Use the helpgroup of another window
WA_TabletMessages (BOOL) - Request extended tablet data - Default is FALSE
WA_ToolBox (BOOL) - Make this window a toolbox window
WA_Parent (struct Window *) - Make the window a child of the given window.
WA_Visible (BOOL) - Make window visible Default is TRUE
WA_Shape (struct Region *) -
WA_ShapeHook (struct Hook *) -

A window can receive events destined for it. The usual way is for the application to ask Intuition to send it messages which are based on the input event that Intuition has processed. These messages, called IntuiMessages, are standard Amiga Exec messages, and are sent to a port called an Intuition Direct Communications Message Port, or IDCMP. Every window may have an IDCMP associated with it. Although AmigaOS(TM) started with intuition events, AROS has incorporated these as well for backwards compatibility purposes but recommends using Zune instead, see here Zune

a) Wait for signal from the current Active Window
b) If a signal has been sent, get the Message data structure
c) Reply to the message, so that message is removed from the queue and is being dealt with.
d) Determine the message class (or gadget or event) occurred by comparing class value with IDCMP flags
e) Do some user processing with that event.

An application will have messages sent to it by any intuition event. These messages, IntuiMessages, are standard Exec messages, and are sent to a port called an IDCMP. Every window may/will have an IDCMP associated with it (Window->UserPort). Keys will not work automatically in a window. You must setup it by WA_IDCMP, tags.

IDCMP_RAWKEY - returns all keycodes, both key-up and key-down, including function keys (it's mean keyboards, moving, gadget (close/resize) and many other things)

#include<proto/exec.h>#include<proto/dos.h>#include<proto/graphics.h>#include<proto/intuition.h>intmain(void){/* set up variables to be used in this function */structWindow*win;structIntuiMessage*mess;BOOLcont;BOOLlbutton;BOOLrbutton;longold_x;longold_y;longx;longy;win=OpenWindowTags(NULL,WA_Left,112,WA_Top,84,WA_Width,800,WA_Height,600,WA_Flags,WFLG_CLOSEGADGET|WFLG_DRAGBAR|WFLG_DEPTHGADGET|WFLG_SIZEGADGET|WFLG_RMBTRAP|WFLG_REPORTMOUSE|WFLG_ACTIVATE|WFLG_GIMMEZEROZERO|WFLG_NOCAREREFRESH,WA_IDCMP,IDCMP_CLOSEWINDOW|IDCMP_VANILLAKEY|IDCMP_MOUSEBUTTONS|IDCMP_MOUSEMOVE,WA_MinWidth,80,WA_MinHeight,40,WA_MaxWidth,-1,WA_MaxHeight,-1,TAG_END);/* if (win==NULL) { */if(!win){Printf("cannot open window\n");return(RETURN_FAIL);}rbutton=FALSE;lbutton=FALSE;x=win->MouseX;y=win->MouseY;old_x=x;old_y=y;cont=TRUE;do{if(Wait((1L<<win->UserPort->mp_SigBit)|SIGBREAKF_CTRL_C)&SIGBREAKF_CTRL_C)cont=FALSE;while(mess=(structIntuiMessage*)GetMsg(win->UserPort)){switch(mess->Class){caseIDCMP_MOUSEMOVE:x=mess->MouseX-win->BorderLeft;;y=mess->MouseY-win->BorderTop;break;caseIDCMP_MOUSEBUTTONS:switch(mess->Code){caseSELECTDOWN:lbutton=TRUE;break;caseSELECTUP:lbutton=FALSE;break;caseMENUDOWN:rbutton=TRUE;break;caseMENUUP:rbutton=FALSE;break;}break;caseIDCMP_VANILLAKEY:if(mess->Code==0x1b)/* Esc */cont=FALSE;break;caseIDCMP_CLOSEWINDOW:cont=FALSE;break;}ReplyMsg((structMessage*)mess);}if(x!=old_x||y!=old_y){if(rbutton&&lbutton){SetAPen(win->RPort,3);Move(win->RPort,old_x,old_y);Draw(win->RPort,x,y);}elseif(rbutton){SetAPen(win->RPort,2);Move(win->RPort,old_x,old_y);Draw(win->RPort,x,y);}elseif(lbutton){SetAPen(win->RPort,1);Move(win->RPort,old_x,old_y);Draw(win->RPort,x,y);}old_x=x;old_y=y;}}while(cont);CloseWindow(win);return(RETURN_OK);}

Basically, creating an IDCMP loop to check for user input and/or timer events. Then you probably set up a timer device call that will give you those events. You have to update your window content with the help of IDCMP_INTUITICKS ("ticks" roughly ten times a second). These tick events are to be used as wake up call, and not as timers.

caseIDCMP_INTUITICKS:/* * If the user is NOT holding the LMB down, then we'll * report this event back to the program in order not to confuse * the select box drawing routines. */if(!(imsg->Qualifier&IEQUALIFIER_LEFTBUTTON))method=GID_DW_INTUITICKS;break;

Of course you might want to only update the content every 3rd intuitick for example and only, if the proportional gadget has changed etc.

System support for tablets started on WB 2.x. At that time, tablet drivers were supposed to send informations to the input device as events such as (X,Y) range and coordinates plus the pressure. This method is known today as old style tablet events.

Starting from WB3.0, a new kind of tablet events has been defined to support more tablet's features such as proximity, tilt, etc.
This method is known as new style tablet events.

All IntuiMessages are now slightly extended. The ExtIntuiMessage structure has an additional field for tablet data, which is usually NULL. If a tablet driver which is sending IESUBCLASS_NEWTABLET events is installed in the system, windows with the WA_TabletMessages property set will find that eim_TabletData points to the TabletData structure. Applications must first check that this field is non-NULL; it will be NULL for certain kinds of message, including mouse activity generated from other than the tablet (i.e. the keyboard equivalents or the mouse itself).

WA_TabletMessages - (BOOL) Set to TRUE to request extended IntuiMessages for your window. If a tablet driver is generating IESUBCLASS_NEWTABLET input events, you will be able to receive extended tablet information with most IntuiMessages. See the eim_TabletData field of the ExtIntuiMessage structure. Defaults to FALSE. (V39)

#define WA_TabletMessages TRUE

(WA_Dummy + 0x37) is a boolean. Set to TRUE to request that tablet information be included in IntuiMessages sent to your window. Requires that something (i.e. a tablet driver) feed IESUBCLASS_NEWTABLET InputEvents into the system. For a pointer to the TabletData, examine the ExtIntuiMessage->eim_TabletData field.

Intuition supports the IESUBCLASS_NEWTABLET subclass of the IECLASS_NEWPOINTERPOS event.
The ie_EventAddress of such an event points to a TabletData structure

The TabletData structure contains certain elements including a taglist.
The taglist can be used for special tablet parameters. A tablet driver should include only those tag-items the tablet supports. An application can listen for any tag-items that interest it. Note: an application must set the WA_TabletMessages attribute to TRUE to receive this extended information in its IntuiMessages.

The definitions given here MUST be followed. Pay careful attention to normalization and the interpretation of signs.

TABLETA_TabletZ: the current value of the tablet in the Z direction. This unsigned value should typically be in the natural units of the tablet. You should also provide TABLETA_RangeZ.

TABLETA_RangeZ: the maximum value of the tablet in the Z direction. Normally specified along with TABLETA_TabletZ, this allows the application to scale the actual Z value across its range.

TABLETA_AngleX: the angle of rotation or tilt about the X-axis. This number should be normalized to fill a signed long integer. Positive values imply a clockwise rotation about the X-axis when viewing from +X towards the origin.

TABLETA_AngleY: the angle of rotation or tilt about the Y-axis. This number should be normalized to fill a signed long integer. Positive values imply a clockwise rotation about the Y-axis when viewing from +Y towards the origin.

TABLETA_AngleZ: the angle of rotation or tilt about the Z axis. This number should be normalized to fill a signed long integer. Positive values imply a clockwise rotation about the Z-axis when viewing from +Z towards the origin.

Note: a stylus that supports tilt should use the TABLETA_AngleX and TABLETA_AngleY attributes. Tilting the stylus so the tip points towards increasing or decreasing X is actually a rotation around the Y-axis. Thus, if the stylus tip points towards positive X, then that tilt is represented as a negative TABLETA_AngleY. Likewise, if the stylus tip points towards positive Y, that tilt is represented by positive TABLETA_AngleX.

TABLETA_Pressure: the pressure reading of the stylus. The pressure should be normalized to fill a signed long integer. Typical devices won't generate negative pressure, but the possibility is not precluded. The pressure threshold which is considered to cause a button-click is expected to be set in a Preferences program supplied by the tablet vendor. The tablet driver would send IECODE_LBUTTON-type events as the pressure crossed that threshold.

TABLETA_ButtonBits: ti_Data is a long integer whose bits are to be interpreted at the state of the first 32 buttons of the tablet.

TABLETA_InProximity: ti_Data is a boolean. For tablets that support proximity, they should send the TABLETA_InProximity,FALSE} tag item when the stylus is out of proximity. Can be used as a mouse-blanking commodity which keys off this to blank the mouse. When this tag is absent, the stylus is assumed to be in proximity.

TABLETA_ResolutionX: ti_Data is an unsigned long integer which is the x-axis resolution in dots per inch.

TABLETA_ResolutionY: ti_Data is an unsigned long integer which is the y-axis resolution in dots per inch.

structIntuiText{UBYTEFrontPen,BackPen;/* the pen numbers for the rendering */UBYTEDrawMode;/* the mode for rendering the text */WORDLeftEdge;/* relative start location for the text */WORDTopEdge;/* relative start location for the text */structTextAttr*ITextFont;/* if NULL, you accept the default */UBYTE*IText;/* pointer to null-terminated text */structIntuiText*NextText;/* pointer to another IntuiText to render */};

dri_Pens[TEXTPEN];myBACKGROUNDPEN=drawinfo->dri_Pens[BACKGROUNDPEN];/* create a TextAttr that matches the specified font. */myTextAttr.ta_Name=drawinfo->dri_Font->tf_Message.mn_Node.ln_Name;myTextAttr.ta_YSize=drawinfo->dri_Font->tf_YSize;myTextAttr.ta_Style=drawinfo->dri_Font->tf_Style;myTextAttr.ta_Flags=drawinfo->dri_Font->tf_Flags;/* open a simple window on the workbench screen for displaying a text string. An application would probably never use such a window, but it is useful for demonstrating graphics... */if((win=OpenWindowTags(NULL,WA_PubScreen,(IPTR)screen,WA_RMBTrap,TRUE,WA_IDCMP,IDCMP_RAWKEY,TAG_END))){myIText.FrontPen=myTEXTPEN;myIText.BackPen=myBACKGROUNDPEN;myIText.DrawMode=JAM2;myIText.LeftEdge=MYTEXT_LEFT;myIText.TopEdge=MYTEXT_TOP;myIText.ITextFont=&myTextAttr;myIText.IText="Hello, World. ;-)";myIText.NextText=NULL;/* Draw the text string at 10,10 */PrintIText(win->RPort,&myIText,10,10);/* Wait for keypress */Wait(1L<<win->UserPort->mp_SigBit);CloseWindow(win);}FreeScreenDrawInfo(screen,drawinfo);}UnlockPubScreen(NULL,screen);}return0;}

Although AmigaOS(TM) started out with intuition based Menus, Gadgets, Requesters and Events.

The Amiga has introduced many alternatives like GadTools, BOOPSI, ASL, BGui, ReqTools, ClassAct and MUI. AROS has chosen a MUI rewrite (Zune) to be the default GUI tool set, for example Zune (MUI) Menus.

The rest of this page contains information (intuition based only) and is of backwards compatibility only.

If you want to define your own menus, then I think intuition.library also covers you there, although menus are best left till later as IMHO they are overly complex & error prone.

For each main menu heading (i.e. top option) in the menu bar, you declare one Menu structure for each. For each item or sub-item within a menu, you declare one a MenuItem structure for each. You should use more MenuItem than Menu. Text-based menus require an additional IntuiText structure for each menu and (sub)item. (they appear the most). Image menus require the image struct.

To use Menus you need to use the Menu and MenuItem structures, and then attached them to a Window.
Please note than the IntuiTexts and Image structure should be defined before the MenuItem structures that are calling them.

structMenu{structMenu*NextMenu;/* same level */WORDLeftEdge,TopEdge;/* position of the select box */WORDWidth,Height;/* dimensions of the select box */UWORDFlags;/* flag definitions*/BYTE*MenuName;/* text for this Menu Header */structMenuItem*FirstItem;/* pointer to first in chain */};

structMenuItem{structMenuItem*NextItem;/* pointer to next in chained list */WORDLeftEdge,TopEdge;/* position of the select box */WORDWidth,Height;/* dimensions of the select box */UWORDFlags;/* see the defines below */LONGMutualExclude;/* set bits mean this item excludes that */IPTRItemFill;/* points to Image, IntuiText, or NULL */IPTRSelectFill;/* points to Image, IntuiText, or NULL */BYTECommand;/* only if appliprog sets the COMMSEQ flag */structMenuItem*SubItem;/* if non-zero, points to MenuItem for submenu */UWORDNextSelect;/* Menu no of next selected item when drag-selecting items */};

To add or remove a menu from a window, you need to use the following commands:

BOOL SetMenuStrip( struct Window *window, struct Menu *menu )

void ClearMenuStrip( struct Window *window )

Use the SetMenuStrip command after the Window has been defined and opened and provide the address of the Window and the address of the last Menu structure in the linked list. Before closing a window, you must use ClearMenuStrip command first to remove the menu from the screen before closing a Window. Attaching menus to windows rather than screens can allow your program to have flexibility so if you had multiple windows open you can customise the menu to suit the appropriate window, for example, in a paint package or video program you can have smaller windows with their own menus.

It is possible to enable or disable menu items, when you don`t wish a user to have access to a menu function. This can be done with the OnMenu and OffMenu functions:

void OffMenu( struct Window *window, unsigned long menuNumber)

void OnMenu( struct Window *window, unsigned long menuNumber )

Just provide the menu number of the item to enable or disable. If you change the CHECKED or ITEMENABLED values of menu items then you can refresh the menu using ResetMenuStrip command which is similar and faster than using SetMenuStrip command.

/* Chaos: The Chess HAppening Organisation System V5.3 Copyright (C) 1993 Jochen Wiedmann This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. $RCSfile: ProjectAmi.c,v $ $Revision: 3.4 $ $Date: 1994/11/19 19:32:01 $ This file contains the system dependent functions that support the Project menu. Computer: Amiga 1200 Compiler: Dice 2.07.54 (3.0) Author: Jochen Wiedmann Am Eisteich 9 72555 Metzingen Tel. 07123 / 14881 Internet: jochen.wiedmann@zdv.uni-tuebingen.de*/#ifndef CHAOS_H#include"chaos.h"#endif#ifdef AMIGA#include<libraries/asl.h>#include<libraries/gadtools.h>#include<libraries/dos.h>#include<proto/asl.h>#include<proto/icon.h>#endif /* AMIGA *//* FileRequest() creates a file requester which reads a file name. Inputs: defaultfile a pointer to a string containing the default name title a pointer to a string containing the requester's title. This may be NULL, in which case MSG_CDAT_SELECTION is assumed. ending a pointer to a string containing the default ending. This may be NULL, in which case "#?.cdat" is assumed. Note, that this MUST be something like "#?.xxx" on the Amiga! savemode TRUE, if non-existing files may be selected. Result: Full path name of the file, that was selected or NULL, if the user cancelled.*/char*FileRequest(char*defaultfile,char*title,char*ending,intsavemode)#ifdef AMIGA{structFileRequester*requester;charpattern[20];char*result=NULL;char*filename,*pathname,*endptr;BPTRdir;staticcharFileRequestName[TRNFILENAME_LEN+1];staticcharPathName[TRNFILENAME_LEN+1];structWindow*window;/* Bring up default settings, if needed. */if(title==NULL){title=(char*)MSG_CDAT_SELECTION;}if(ending==NULL){ending="#?.cdat";}/* Get Intuition window pointer from MUI window, allocate Filerequester and parse the ending for wildcards. */get(MainWnd,MUIA_Window_Window,&window);if((requester=(structFileRequester*)MUI_AllocAslRequest(ASL_FileRequest,NULL))==NULL){MemError();return(NULL);}ParsePatternNoCase((UBYTE*)ending,(UBYTE*)pattern,sizeof(pattern));/* Get default file- and drawername. */if(defaultfile&&*defaultfile!='\0'){strcpy(FileRequestName,defaultfile);}else{if(TrnFileName!='\0'){strcpy(FileRequestName,TrnFileName);}else{sprintf(FileRequestName,savemode?"chaos.%d.cdat":"",NumRounds);}}filename=(char*)FilePart((STRPTR)FileRequestName);strcpy(PathName,FileRequestName);*(pathname=(char*)PathPart((STRPTR)PathName))='\0';/* Make the drawername absolute. */dir=Lock((STRPTR)PathName,SHARED_LOCK);NameFromLock(dir,(STRPTR)PathName,sizeof(PathName));UnLock(dir);/* Ensure, that the default filename has the right ending. */if(ending!=NULL&&(endptr=strrchr(filename,'.'))!=NULL){strcpy(endptr,ending+2);}/* Bring up the requester */#ifdef V39_INCLUDESif(MUI_AslRequestTags(requester,ASLFR_Window,window,ASLFR_PrivateIDCMP,TRUE,ASLFR_SleepWindow,TRUE,ASLFR_TitleText,title,ASLFR_InitialFile,filename,ASLFR_InitialDrawer,PathName,ASLFR_InitialPattern,ending,ASLFR_DoSaveMode,savemode,ASLFR_RejectIcons,TRUE,ASLFR_AcceptPattern,pattern,TAG_DONE)!=FALSE&&requester->fr_File!=NULL&&requester->fr_File!='\0'){strcpy(FileRequestName,(char*)requester->fr_Drawer);AddPart((STRPTR)FileRequestName,requester->fr_File,sizeof(FileRequestName));result=FileRequestName;}#elseif(MUI_AslRequestTags(requester,ASL_Window,window,ASL_Hail,titleASL_File,filename,ASL_Dir,PathName,TAG_DONE)==FALSE&&requester->rf_File!=NULL&&requester->rf_File!='\0'){strcpy(FileRequestName,(char*)requester->rf_Dir);AddPart((STRPTR)FileRequestName,(STRPTR)requester->rf_File,sizeof(FileRequestName));result=FileRequestName;}#endifMUI_FreeAslRequest((APTR)requester);return(result);}#endif /* AMIGA *//* CreateIcon() puts an icon to a recently saved file. Inputs: name of the file just created; must not be NULL*/voidCreateIcon(char*name)#ifdef AMIGA{externintMakeIcons;/* Does the user want to have an icon? */if(MakeIcons){/* Yes, get a diskobject */structDiskObject*dobj;char*olddeftool;intlen=strlen(IconName);/* Icon.library doesn't like a trailing ".info" when calling GetDiskObject(). */if(len>=5&&Stricmp((STRPTR)IconName+len-5,(STRPTR)".info")==0){IconName[len-5]='\0';}if((dobj=GetDiskObject((STRPTR)IconName))!=NULL||(dobj=GetDiskObject((STRPTR)"s:Chaos_Project"))!=NULL||(dobj=GetDefDiskObject(WBPROJECT))!=NULL){/* Put the right settings into the diskobject and save it. */dobj->do_Type=WBPROJECT;olddeftool=dobj->do_DefaultTool;dobj->do_DefaultTool=ProgName;dobj->do_CurrentX=dobj->do_CurrentY=NO_ICON_POSITION;if(dobj->do_StackSize<20000){dobj->do_StackSize=20000;}PutDiskObject((STRPTR)name,dobj);dobj->do_DefaultTool=olddeftool;FreeDiskObject(dobj);}}}#else /* !AMIGA */{/* There is nothing to be done on other systems. */}#endif /* !AMIGA *//* AskSave brings up a requester asking the user, if he wants to save first.*/intAskSave(void)#ifdef AMIGA{switch(MUI_RequestA(App,MainWnd,0,(char*)MSG_ATTENTION,(char*)MSG_YES_NO_CANCEL,(char*)MSG_CHANGES_MADE,NULL)){case2:return(TRUE);case1:return(SaveTournament(NULL));}return(FALSE);}#endif /* AMIGA *//* The TerminateTrnWnd() function closes the tournament input window.*/#ifdef AMIGAstaticAPTRTrnWnd=NULL;/* Tournament window */staticAPTRTrnOkGad;/* Ok gadget (tournament window) */staticAPTRTrnCancelGad;/* Cancel gadget (tournament window) */staticAPTRTrnNameGad;/* Tournament name gadget */staticAPTRWinnerPointsGad;/* Winner points gadget */staticAPTRDrawPointsGad;/* Draw points gadget */voidTerminateTrnWnd(void){if(TrnWnd){set(TrnWnd,MUIA_Window_Open,FALSE);DoMethod(App,OM_REMMEMBER,TrnWnd);MUI_DisposeObject(TrnWnd);TrnWnd=NULL;}}#endif /* AMIGA *//* The InitTrnWnd() function brings up a window, that allows to input tournament data. Inputs: name pointer to a buffer, that can hold the tournament name winnerpoints current number of points for winning a game drawpoints current number of points for a draw Results: TRUE, if successfull, FALSE otherwise*/#ifdef AMIGA#define ID_TrnWnd_Cancel 201#define ID_TrnWnd_Ok 202intInitTrnWnd(char*buffer,intwinnerpoints,intdrawpoints){ULONGopen;intOK_SC=*MSG_OK_SC;intCancel_SC=*MSG_CANCEL_SC;/* Open the window and check for success. */TrnWnd=WindowObject,MUIA_Window_ID,MAKE_ID('T','R','N','I'),MUIA_Window_Title,MSG_TOURNAMENT_INPUT_TITLE,MUIA_Window_Width,MUIV_Window_Width_MinMax(40),WindowContents,VGroup,Child,HGroup,Child,Label2(MSG_TOURNAMENT_NAME_OUTPUT),Child,TrnNameGad=StringObject,StringFrame,MUIA_String_MaxLen,TRNNAME_LEN+1,MUIA_String_Contents,buffer,End,End,Child,VSpace(0),Child,HGroup,Child,VGroup,Child,Label2(MSG_WINNERPOINTS),Child,Label2(MSG_DRAWPOINTS),End,Child,VGroup,Child,WinnerPointsGad=StringObject,StringFrame,MUIA_String_MaxLen,3,MUIA_String_Accept,"0123456789 ",MUIA_String_Integer,winnerpoints,End,Child,DrawPointsGad=StringObject,StringFrame,MUIA_String_MaxLen,3,MUIA_String_Accept,"0123456789 ",MUIA_String_Integer,drawpoints,End,End,Child,HSpace(0),End,Child,VSpace(0),Child,HGroup,MUIA_Group_SameSize,TRUE,Child,TrnOkGad=KeyButton(MSG_OK,OK_SC),Child,HSpace(0),Child,TrnCancelGad=KeyButton(MSG_CANCEL_INPUT,Cancel_SC),End,End,End;if(!TrnWnd){return(FALSE);}DoMethod(App,OM_ADDMEMBER,TrnWnd);DoMethod(TrnWnd,MUIM_Window_SetCycleChain,TrnNameGad,TrnOkGad,TrnCancelGad,NULL);set(TrnWnd,MUIA_Window_ActiveObject,TrnNameGad);/* Setting up the notification events for the tournament input window: CloseWindow, Ok- and Cancel Gadget */DoMethod(TrnWnd,MUIM_Notify,MUIA_Window_CloseRequest,TRUE,App,2,MUIM_Application_ReturnID,ID_TrnWnd_Cancel);DoMethod(TrnWnd,MUIM_Notify,MUIA_Window_InputEvent,"ctrl return",App,2,MUIM_Application_ReturnID,ID_TrnWnd_Ok);DoMethod(TrnOkGad,MUIM_Notify,MUIA_Pressed,FALSE,App,2,MUIM_Application_ReturnID,ID_TrnWnd_Ok);DoMethod(TrnCancelGad,MUIM_Notify,MUIA_Pressed,FALSE,App,2,MUIM_Application_ReturnID,ID_TrnWnd_Cancel);DoMethod(TrnWnd,MUIM_Window_SetCycleChain,TrnNameGad,WinnerPointsGad,DrawPointsGad,TrnOkGad,TrnCancelGad,NULL);DoMethod(TrnNameGad,MUIM_Notify,MUIA_String_Acknowledge,MUIV_EveryTime,TrnWnd,3,MUIM_Set,MUIA_Window_ActiveObject,WinnerPointsGad);DoMethod(WinnerPointsGad,MUIM_Notify,MUIA_String_Acknowledge,MUIV_EveryTime,TrnWnd,3,MUIM_Set,MUIA_Window_ActiveObject,DrawPointsGad);DoMethod(DrawPointsGad,MUIM_Notify,MUIA_String_Acknowledge,MUIV_EveryTime,TrnWnd,3,MUIM_Set,MUIA_Window_ActiveObject,TrnNameGad);set(TrnWnd,MUIA_Window_Open,TRUE);get(TrnWnd,MUIA_Window_Open,&open);if(!open){MUIError((char*)ERRMSG_CANNOT_OPEN_WINDOW);TerminateTrnWnd();return(FALSE);}set(TrnWnd,MUIA_Window_ActiveObject,TrnNameGad);set(MainWnd,MUIA_Window_Open,FALSE);return(TRUE);}#endif /* AMIGA *//* The ProcessTrnWnd() function waits for user actions concerning the tournament input window. Inputs: buffer pointer to a string, that holds the users input. (Not needed on the Amiga.) winnerpoints pointer to an int where to store the number of points for winning a game game drawpoints pointer to an int where to store the number of points for a draw Results: 0 Indicates, that the user has cancelled. 1 Indicates, that this has to be called again. -1 Terminating via Ok-Gadget, okay*/intProcessTrnWnd(char*buffer,int*winnerpoints,int*drawpoints)#ifdef AMIGA{ULONGSignal;char*name;/* Check for user actions */switch(DoMethod(App,MUIM_Application_Input,&Signal)){caseMUIV_Application_ReturnID_Quit:if(TestSaved()){exit(0);}break;caseID_TrnWnd_Cancel:return(0);caseID_TrnWnd_Ok:/* Get the final state of the tournament name gadget. */if(buffer){get(TrnNameGad,MUIA_String_Contents,&name);strcpy(buffer,name);get(WinnerPointsGad,MUIA_String_Integer,winnerpoints);get(DrawPointsGad,MUIA_String_Integer,drawpoints);}return(-1);}if(Signal){Wait(Signal);}return(1);}#endif

String gadgets require their own special structure called the StringInfo structure.
For a string gadget, set the GadgetType field in the Gadget structure to GTYP_STRGADGET. Set the SpecialInfo field to point to an instance of a StringInfo structure, which must be initialized by the application.

EditOp Action Taken by Global Hook
------ ---------------------------
EO_NOOP Did nothing.
EO_DELBACKWARD Deleted some chars (possibly 0).
EO_DELFORWARD Deleted some characters under and in front of the cursor.
EO_MOVECURSOR Moved the cursor.
EO_ENTER Enter or Return key, terminate.
EO_RESET Current Intuition-style undo.
EO_REPLACECHAR Replaced one character and (maybe) advanced cursor.
EO_INSERTCHAR Inserted one character into string or added one at end.
EO_BADFORMAT Didn't like the text data, e.g., alpha characters in a GACT_LONGINT type.
EO_BIGCHANGE Complete or major change to the text, e.g. new string.
EO_UNDO Some other style of undo.
EO_CLEAR Clear the string.
EO_SPECIAL An operation that doesn't fit into the categories here.
These are the actions to be taken by Intuition after the hook returns.
Actions Flag Purpose
------------ -------
SGA_USE If set, use contents of SGWork.
SGA_END Terminate gadget, Code field is sent to application in IDCMP_GADGETUP event code field.
SGA_BEEP Beep (i.e., flash) the screen.
SGA_REUSE Reuse the input event. Only valid with SGA_END.
SGA_REDISPLAY Gadget visuals have changed, update on screen.
SGA_NEXTACTIVE Make next possible gadget active
SGA_PREVACTIVE Make previous possible gadget active

BOOPSI is great for GUI stuff and runtime class loading/method dispatching. It's written in C and the designers made a *very* good job when you realise the limitations of the language for this kind of system. But consider if we had decent C++ support since the start of Amigas, sure BOOPSI would have been written in it.

The thing is, BOOPSI lends itself well to event-driven code (such as a GUI) where the users interaction is rate determining. However, the method dispatch mechanisms and data access methods are vastly slower (by virtue of how they work) than a C++ virtual function call, let alone a non-virtual or static member func.

You wouldn't want to rely on BOOPSI for all your OOP needs. Imagine the speed penalty of the method calls used in a time critical loop. Ouch :-)

If you use BOOPSI scrollers, you can set Total, Visible and Top attributes. And you can let it send you messages when the user moves the bar. Intuition comes with its own BOOPSI scroller class - the propgclass. It is better integrated inside the window border.

There also seems to be a problem with sending the SA_PubSig signal to the SA_PubTask. The SA_PubTask gets the signal, if UnlockPubScreen is called and this was the last lock. This is independent of the number of windows on the screen.

As you can see in, it seems to be not necessary to lock a pubscreen to open a window on it, at least, if you own it.

LockPubScreen() Find Workbench or any other public screen; prevent it from closing while a window is opened or its attributes copied.
UnlockPubScreen() Release the lock allowing the screen to later be closed.
struct Screen *LockPubScreen( UBYTE * )
VOID UnlockPubScreen( UBYTE * , struct Screen *)
SetDefaultPubScreen() Establishes a given public screen as the default.
GetDefaultPubScreen() Copies the name of the default screen to a user supplied buffer for use by the screen manager utility
(the name is not needed by normal applications, use LockPubScreen(NULL) instead).
PubScreenStatus() Converts a screen to private or public status.
SetPubScreenModes() Controls the public screen global mode bits.
WBenchToBack() Move the Workbench screen behind all other screens.
WBenchToFront() Move the Workbench screen in front of all other screens.
OpenWorkBench() Open the Workbench screen. If the screen is already open, this call has no effect.
This call will re-awaken the Workbench application if it was active when CloseWorkBench() was called.
CloseWorkBench() Attempt to reclaim memory used for the Workbench screen.
If successful, this call closes the screen and puts the Workbench application to sleep.
This call fails if any application has windows open or locks on the Workbench screen.
LockPubScreenList() Lock the public screen list maintained by intuition so that it may be quickly copied.
UnlockPubScreenList() Release the lock on the public screen list.
NextPubScreen() Find the next screen in the public screen list.

On AROS, you have your normal entry point as main(int argc, char **argv).

If argc == 0, then argv actually points to a struct WBStartup.

If argc > 0, then the program was started from CLI.

However, programs run from CLI *MUST* call Permit() for each Forbid() since the final 'rts' drops back to shell, and does not terminate the process.

Semaphores should be used when possible. Forbid()/Permit() should only be used when there is no alternative. Semaphores can be very useful for things like access to memory pools, lists that could be modified by other threads, etc. etc.

Some programs use the technique of starting a new process and clearing cli_Module in order to detach from the shell they are run from. At least for FileX (see contrib/aminet/disk/moni/filex/main.c), this doesn't seem to work anymore. FileX only works if the SYNC argument is used to disable this behaviour.

Does the standard startup code or shell support detaching like this? Perhaps the seglist is being unloaded regardless of the value placed in cli_Module.

Would it be feasible to keep libraries open at exit if cli_Module has been cleared by the program? And could they then be closed when the detached process exits?
Not really because it wouldn't fix more common "split segment list" way of detaching.

How does that differ from what FileX does? :-| I presume the similarity of the SegmentSplit() function name is misleading. Yeah, FileX does not do any segment split tricks (perhaps it originally did?), it only clears cli_Module. "Standard" segment list split is to have 2 (or more) segments, code in first segment unlinks following segment(s) from single linked segment list -> only first segment is freed by dos.

It is aroscbase that is set to NULL (guess it is also freed) when original process exists. Which is of course still in use by detached process.. Ouch. I guess FileX doesn't use detach.o? It should to avoid such problems.

It implies to include aros/detach.h and to not link against the standard startup module but against detach.o as Fabio just said. It is done in the mmakefile.src by detach=yes assertion. One can even choose where the detachment has to occur by using the Detach() function.

AmigaOS libnix opens own console only for libc I/O. It does not reassign default dos.library streams to it. In other words: when the program is started from CLI, libc I/O (printf(), write(), stdin, stdout, etc.) is directed into dos.library default streams. When program is started from Workbench, libc opens own window for own I/O, but does not touch dos.library streams. As a consequence, when started from WB, printf() will send a string to __stdiowin, but Printf() will send it to NIL:.

That final Forbid() guarantees the Workbench don't have a change to UnLoadSeg() the seglist of the program while the program is still executes.

If there is no Forbid(), the ReplyMsg() results in task scheduling, and Workbench get change to run. Workbench UnLoadSeg() the seglist, and the last few instructions are executed on unallocated memory. This will lead into crashes.

There is no need for final Permit(), since the process will RemTask(NULL) itself eventually (default Task EndPC), and this completely removes the process anyway.

use intuition.library/StartScreenNotifyTagList() in order to allow screen preferences changes without having to close/reopen it

There are some additional functions you can use to manipulate screens.

void DisplayBeep(struct Screen *)
This function will flash the specified screen, for example, to indicate an error.
e.g. DisplayBeep(myScreen);
void MoveScreen(struct Screen *, WORD dx, WORD dy)
This function will move the current screen to the specified pixel co-ordinates.
This is similar to dragging the screen bar to a new location.
e.g. MoveScreen(myScreen, 0, 100); /* Move screen down to y co-ord 100 */
void ScreenToBack(struct Screen *)
void ScreenToFront(struct Screen *)
If you have multiple screens open, then you can switch between screens
using these functions. ScreenToFront will make a screen the visible screen.
e.g. ScreenToFront(myScreen);
void MakeScreen(struct Screen *)
e.g. MakeScreen(myScreen);
void ShowTitle(struct Screen *, BOOL)
Specifies whether to show the screen's title bar or not.
e.g. ShowTitle(myScreen, FALSE);

as I will only get the default pointer and not the current one that might be set by an application using SetWindowPointer() or SetPointer() functions.

Is there a way to get the current pointer bitmap? You could always patch the necessary function at runtime so that your own routine would be called with the necessary information, and then do what you need (as well as call the original function to actually set the visible pointer).

intercept the call,

copy the bitmap so that I can use it for my own purpose

forward the call to the original function

Digging into it is seems that it's not SetWindowPointerA that I shall patch but rather ChangeExtSpriteA.
SetWindowPointer is used when a new pointer is set for a window, this pointer will therefore be used when the window is active. But ChangeExtSprite is called each time the pointer changes, i.e. also when active window is changing.

Is there a way to get notification of the current pointer change? An application can change the pointer image at any time by calling SetWindowPointer(), for example to show the busy pointer. These changes are not reflected by a file change and will not cause a DOS notification.