WaitREIMsg
Synopsis
rmsg = WaitREIMsg(rei, underscore)
D0 A0 D0:8C Prototype
struct REIMessage *WaitREIMsg(struct REI *, LONG);Description
Use WaitREIMsg() instead of the usual exec.library/GetMsg() and gadtools.library/GT_GetIMsg() to process REI events. WaitREIMsg() puts the task to sleep until a valid event arrives at the port of the Window belonging to the REI. At that point, WaitREIMsg() performs internal operations to manage the entire REI system (gadgets, window, menus, etc.). When control is returned to the task, it means an event has occurred, and WaitREIMsg() reports it through the REIMessage structure:
struct REIMessage {
ULONG rim_Class;
UWORD rim_Code;
UWORD rim_Qualifier;
APTR rim_IAddress;
ULONG rim_REICode;
};The REIMessage structure is essentially a copy of the relevant fields from the IntuiMessage structure. Since the Window’s IntuiMessage is processed by gadtools.library, the REIMessage fields also contain all the additional information for GadTools gadget management.
NEW (V41.2) — The rim_REICode field now contains additional event handling information. Double-click detection has been introduced for both left and right mouse buttons. This event must always be checked in conjunction with IDCMP_MOUSEBUTTONS. The rim_Code field via SELECTDOWN and MENUDOWN indicates which button was pressed (left or right respectively). rim_REICode with RIM_LEFTDOUBLECLICK and RIM_RIGHTDOUBLECLICK indicates if a double-click occurred.
WaitREIMsg() introduces a new way of handling Window messages with significant advantages over the standard procedure. The first simplification is that you no longer need to reply to messages — this is done automatically.
Automatic Gadget Handling
WaitREIMsg() supports both standard event handling and fully automated event management. Automated management means the automatic execution of a routine linked to a gadget or menu via SetAsmGadgetAttrsA().
If an AsmGadget has been initialized via SetAsmGadgetAttrsA() and contains a pointer to an initialized Hook structure, WaitREIMsg() invokes this Hook. The Hook is invoked following standard Amiga Hook conventions:
object == (struct AsmGadget *)
message == (struct REIMessage *)For Assembly programmers:
; A0 = Address of the Hook structure
; A1 = message -> (struct REIMessage *)
; A2 = object -> (struct AsmGadget *)
; A6 = pointer to AssemblyBaseRegisters A0, A1, A2, A6 must be saved, and the Hook must always return NULL as its return code.
Keyboard/Underscore Control
Allows simulating gadget activation via keyboard. Automatically recognizes if a pressed key corresponds to a gadget. Since OS 2.04, it has been possible to underline a character in a gadget’s text. WaitREIMsg() adds actual keyboard handling for this feature. Allowed key combinations for a gadget with label "_Mode":
m- SHIFT +
m - CAPS_LOCK +
m
Other modifier combinations (ALT, LEFT_AMIGA, etc.) are reserved for future extensions.
Gadget Type-Specific Behavior
- BUTTON_KIND — Invokes the Hook (if present) both on key press and mouse click. Keyboard selection is visually highlighted.
- STRING_KIND / INTEGER_KIND — If the gadget contains the underscore character, it is automatically activated and the cursor appears. On ENTER/release, the associated Hook is invoked if present.
- CYCLE_KIND — If the gadget has an underscored label, it is cycled automatically by
WaitREIMsg(), and the associated Hook is invoked if present. - DISABLE CONTROL — If a key is pressed matching a disabled gadget,
WaitREIMsg()returns control without doing anything.
In all cases, the REIMessage structure is always returned and properly initialized. If a gadget is selected via keyboard, the rim_IAddress field will contain the address of the activated gadget.
Inputs
- rei — Pointer to a REI structure that displays at least one Window.
- underscore — 8-bit value identifying the underscore character used for gadget label underlining. This parameter must NEVER be NULL, and defaults to 0x5F (the
_character).
Result
- rmsg — Address of a REIMessage structure.
See Also
Implementation
The original 68020 assembly implementation:
; (15-11-1994) --- WaitREIMsg(rei, underscore) (a0/d0)
_LVOWaitREIMsg
movem.l d2-d7/a2-a6,-(sp)
move.b d0,d6 * D6 = Default Underscore
move.l a6,a5 * Save AsmBase
move.l a0,a4 * Save REI
GetMesD move.l ([rei_Window.w,a4],wd_UserPort.w),a0 * Port in A0
bsr _LVOAS_GetIMsg
move.l d0,d7
bne.s WRElabo
InWait moveq #0,d1 * otherwise put the Task in wait state::!!
moveq #0,d0
move.l ([rei_Window.w,a4],wd_UserPort.w),a0
move.b MP_SIGBIT(a0),d1
bset d1,d0
move.l ab_ExecBase(a5),a6
jsr _LVOWait(a6)
GetMes move.l a5,a6
move.l ([rei_Window.w,a4],wd_UserPort.w),a0 * Port in A0
bsr _LVOAS_GetIMsg * It must have arrived!
move.l d0,d7 * Check for NULL and switch in D7
beq.s WExit * Go back to waiting...
WRElabo move.l d7,a2 * IntuiMessage in A2
;--------------------------------------------------------------------------------------
move.l im_Class(a2),rei_REIMessage+rim_Class(a4)
move.l im_Code(a2),rei_REIMessage+rim_Code(a4)
move.l im_IAddress(a2),rei_REIMessage+rim_IAddress(a4)
;--------------------------------------------------------------------------------------
move.l im_Class(a2),d0
subq.l #IDCMP_NEWSIZE,d0
beq.s Drawing
subq.l #(IDCMP_REFRESHWINDOW-IDCMP_NEWSIZE),d0
beq.s Refresh
subq.l #(IDCMP_MOUSEBUTTONS-IDCMP_REFRESHWINDOW),d0
beq CheckDouble
sub.l #(IDCMP_GADGETUP-IDCMP_MOUSEBUTTONS),d0
beq AutoGadget
sub.l #(IDCMP_MENUPICK-IDCMP_GADGETUP),d0
beq AutoMenu
sub.l #(IDCMP_VANILLAKEY-IDCMP_MENUPICK),d0
beq AutoKey
move.l a2,a1
bsr _LVOAS_ReplyIMsg
WExit lea rei_REIMessage(a4),a0
move.l a0,d0
movem.l (sp)+,d2-d7/a2-a6
rts
;--------------------------------------------------------------------------------------
Refresh move.l rei_Window(a4),a0 * Get the Window
move.l ab_GadToolsBase(a5),a6
jsr _LVOGT_BeginRefresh(a6)
move.l rei_Window(a4),a0
moveq #1,d0
jsr _LVOGT_EndRefresh(a6)
;--------------------------------------------------------------------------------------
Reply move.l d7,a1
pea GetMes(pc)
move.l a5,a6
bra _LVOAS_ReplyIMsg
;--------------------------------------------------------------------------------------
Drawing move.l rei_glist(a4),a0
move.l gg_NextGadget(a0),d0 * Are there Gadgets??
beq.s AskHook
moveq #0,d1
move.l d1,gg_NextGadget(a0)
move.l d0,a0
move.l ab_GadToolsBase(a5),a6
jsr _LVOFreeGadgets(a6) * Free Gadgets
move.l rei_glist(a4),a2
move.l rei_HEADAsmGadget(a4),a3 * surely they exist!!...
move.l a5,a6
jsr LayoutAsmGList * A4=REI, A3=AsmGList, A2=PrevGadget
move.l ab_LayersBase(a5),a6
move.l ([rei_Window.w,a4],wd_RPort.w),a1
move.l ([rp_Layer.w,a1],lr_BackFill.w),a0
suba.l a2,a2
jsr _LVODoHookClipRects(a6)
;--------------------------------------------------------------------------------------
AskHook move.l rei_CustomHook(a4),d0 * Check if a Custom Hook exists
beq.s NoCHook * Custom Hook...
DoHook move.l a5,a6 * Since a CustomHook exists, we don't
move.l d7,a1 * perform any window refresh
bsr _LVOAS_ReplyIMsg * but invoke the Hook
move.l rei_CustomHook(a4),a0 * The message here is already replied...
suba.l a1,a1
move.l rei_Window(a4),a2
move.l a5,a6
move.l h_Entry(a0),a3
pea GetMes(pc) * More messages... returns here
jmp (a3)
;--------------------------------------------------------------------------------------
NoCHook move.l rei_Window(a4),a0 * If no CustomHook exists, everything
move.l ab_IntuiBase(a5),a6 * proceeds as usual... and the Window
jsr _LVORefreshWindowFrame(a6) * gets refreshed...
move.l ab_GadToolsBase(a5),a6
move.l rei_Window(a4),a0
suba.l a1,a1
jsr _LVOGT_RefreshWindow(a6)
move.l d7,a1
pea GetMes(pc)
move.l a5,a6
bra _LVOAS_ReplyIMsg
;--------------------------------------------------------------------------------------
; AUTOGADGET()
;--------------------------------------------------------------------------------------
AutoGadget
move.l a2,-(sp) * Reply to the message, since I know what it is
move.l rei_REIMessage+rim_IAddress(a4),a2 * A2 (struct Gadget *)
move.l gg_UserData(a2),a2 * A2 (struct AsmGadget *)
move.l agg_Kind(a2),d0 * What type should I handle?
beq.s JmpAddr * security... generic kind
lea AAG_Table2(pc),a0
move.l ab_GadToolsBase(a5),a6
jmp ([a0,d0.w*4])
;--------------------------------------------------------------------------------------
JmpAddr move.l agg_NewGadget+gng_UserData(a2),d0 * D0 = (struct Hook *)
beq.s AGSimGd * If there was none, then exit
lea rei_REIMessage(a4),a1 * A1 = message (struct REIMessage *)
move.l d0,a0 * A0 = itself (struct Hook *)
move.l a5,a6 * Force A6 = asmbase...
jsr ([h_Entry.w,a0]) * Call the Hook
move.l (sp)+,a1
move.l a5,a6
pea GetMes(pc)
bra _LVOAS_ReplyIMsg
AGSimGd move.l (sp)+,a1
move.l #GADGETUP,rei_REIMessage+rim_Class(a4)
move.l agg_Gadget(a2),rei_REIMessage+rim_IAddress(a4)
move.l a5,a6
pea WExit(pc)
bra _LVOAS_ReplyIMsg
;--------------------------------------------------------------------------------------
; AUTOKEY
;--------------------------------------------------------------------------------------
AutoKey move.l a2,-(sp) * Reply to the msg, since I know what it is
move.w rei_REIMessage+rim_Qualifier(a4),d1 * from REIMessage
andi.w #~$8007,d1 * Check if it's a message I can handle
bne.s AG_ER1 * Otherwise exit
move.w rei_REIMessage+rim_Code(a4),d5 * D5 = Key (pressed) to search for
move.l ([rei_HEADAsmGadget.w,a4]),d0 * Are there Gadgets??
beq.s AG_ER1 * No, then find exit...
move.l rei_HEADAsmGadget(a4),a2 * A2 (struct AsmGadget *)
CerRout move.l agg_NewGadget+gng_GadgetText(a2),d0 * Does it have associated text??
bne.s FinRout * Yes, then check
ChekNex move.l ([a2]),d0 * Get next, does it exist...
move.l LN_SUCC(a2),a2
bne.s CerRout * yes, continue
AAG_EXT move.l (sp)+,a1
move.l a5,a6
bsr _LVOAS_ReplyIMsg
lea rei_REIMessage(a4),a0 * Exit from WaitREIMsg()
move.l a0,d0 * (struct REIMessage *)
movem.l (sp)+,d2-d7/a2-a6
rts
;--------------------------------------------------------------------------------------
FinRout move.l d0,a0 * A0 ^ GadgetText
Undersc move.b (a0)+,d0 * character
beq.s ChekNex
cmp.b d6,d0 * Search for the Underscore
bne.s Undersc * nothing, continue
cmp.b (a0),d5 * Found it, check the character now
beq.s CharFin * FOUND... it was this one
bchg #5,d5 * Retry, for CASE
cmp.b (a0),d5 * try now...
bne.s ChekNex * Nothing, it wasn't this one obviously...
CharFin move.w ([agg_Gadget.w,a2],gg_Flags.w),d0 * Flags
btst #8,d0 * It's ghosted??
bne.s AAG_EXT * it's ghosted, so exit...
move.l agg_Kind(a2),d0 * What type should I handle?
lea AAG_Table(pc),a0 * Table
jmp ([d0.w*4,a0]) * Process
;--------------------------------------------------------------------------------------
; AUTOMENU
;--------------------------------------------------------------------------------------
AutoMenu
move.l a2,a3 * Save IntuiMessage in A3
move.w im_Code(a3),d0 * Check that a valid code arrived
cmpi.w #MENUNULL,d0 * and not MENUNULL... in that case
beq.s AMU_NOM * Exit, clearing everything...
move.l rei_Menu(a4),a0
move.l ab_IntuiBase(a5),a6
jsr _LVOItemAddress(a6)
move.l d0,a2 * A2 (struct Sub/MenuItem *)
move.l a2,rei_REIMessage+rim_IAddress(a4) * Save Address in rim_IAddress
move.l mi_SIZEOF(a2),d1 * ID in MenuItem structure...
move.w d1,rei_REIMessage+rim_Code(a4) * Menu ID in rim_Code
move.l a3,a1 * reply to the message
move.l a5,a6
pea WExit(pc) * and shamelessly exit
bra _LVOAS_ReplyIMsg
;--------------------------------------------------------------------------------------
AMU_NOM move.w d0,rei_REIMessage+rim_Code(a4) * Put MENUNULL in rim_Code
addq.w #1,d0 * D0 == NULL!
move.l d0,rei_REIMessage+rim_IAddress(a4) * Clear rim_IAddress
move.l a3,a1 * Reply to the message
move.l a5,a6
pea GetMes(pc)
bra _LVOAS_ReplyIMsg