home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Elysian Archive
/
AmigaElysianArchive.iso
/
commod
/
altmenu.lha
/
AltMenuCom.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-05-23
|
16KB
|
764 lines
/*======================================================*/
/* */
/* Small and efficient commodity to simulate the */
/* MS-Windows(TM) way of walking through the menus */
/* with the arrow keys. */
/* (Tab size 2) */
/* */
/* © Copyright 1992, Jorrit Tyberghein */
/* */
/*======================================================*/
#include <exec/types.h>
#include <exec/memory.h>
#include <exec/interrupts.h>
#include <devices/input.h>
#include <devices/inputevent.h>
#include <dos/dos.h>
#include <pragmas/exec.h>
#include <pragmas/dos.h>
#include <pragmas/intuition.h>
#include <pragmas/keymap.h>
#include <pragmas/input.h>
#include <pragmas/commodities.h>
#include <pragmas/icon.h>
#include <intuition/intuitionbase.h>
#include <string.h>
#include <ctype.h>
#include <libraries/commodities.h>
#include <workbench/workbench.h>
/* Input handler and commodity stuff */
struct MsgPort *InputMP;
struct MsgPort *CxPort;
struct Library *CxBase;
struct Library *InputBase;
struct Interrupt Handler;
struct IOStdReq *InputIO;
struct RDArgs *RDArgs;
CxObj *Broker;
/* Some library bases */
extern APTR DOSBase;
APTR KeymapBase;
struct IntuitionBase *IntuitionBase;
struct Library *IconBase;
/* Commandline arguments */
ULONG *ArgsArray[6];
/* Success code for OpenDevice */
LONG Device = -1;
/* Raw key codes */
#define CODE_LEFT 0x4f
#define CODE_RIGHT 0x4e
#define CODE_UP 0x4c
#define CODE_DOWN 0x4d
#define CODE_ENTER 0x43
#define CODE_RETURN 0x44
#define CODE_SPACE 0x40
#define CODE_HELP 0x5f
/* External handler routine */
struct InputEvent *handler ();
/* Our broker */
struct NewBroker NewBroker =
{
NB_VERSION,"AltMenu",
"AltMenu 1.0, © 1992 Jorrit Tyberghein",
"Use arrows to navigate in menus",
NBU_UNIQUE,0,0,0,0
};
/* Message used to pass some information from input handler to main program */
struct SpecMsg
{
struct Message msg;
WORD Code;
WORD Qualifier;
WORD Class;
};
/* Global data used to pass information from main program to input handler */
struct GlobData
{
ULONG peek,qual;
int EveryKey;
WORD Enable;
int IsAlt;
struct MsgPort *Port;
};
struct GlobData volatile glob = { 0,0,0,TRUE,0,NULL };
/*
* Clean everything and release all memory
*/
void __regargs CloseStuff (UWORD code)
{
if (Broker) DeleteCxObj (Broker);
if (CxPort) DeleteMsgPort (CxPort);
if (RDArgs) FreeArgs (RDArgs);
if (!Device) CloseDevice (InputIO);
if (InputIO) DeleteExtIO (InputIO);
if (InputMP) DeleteMsgPort (InputMP);
if (glob.Port) DeleteMsgPort (glob.Port);
if (IconBase) CloseLibrary (IconBase);
if (CxBase) CloseLibrary (CxBase);
if (IntuitionBase) CloseLibrary (IntuitionBase);
if (KeymapBase) CloseLibrary ((struct Library *)KeymapBase);
XCEXIT (code);
}
/*
* Open everything
*/
void OpenStuff (void)
{
if (!(IconBase = (struct IconBase *)OpenLibrary ("icon.library",37)))
CloseStuff (10);
if (!(IntuitionBase = (struct IntuitionBase *)OpenLibrary ("intuition.library",37)))
CloseStuff (10);
if (!(CxBase = (struct CxBase *)OpenLibrary ("commodities.library",37)))
CloseStuff (10);
if (!(KeymapBase = (APTR)OpenLibrary ("keymap.library",37)))
CloseStuff (10);
if (!(InputMP = (struct MsgPort *)CreateMsgPort ()))
CloseStuff (10);
if (!(glob.Port = (struct MsgPort *)CreateMsgPort ()))
CloseStuff (10);
if (!(InputIO = (struct StdIOReq *)CreateExtIO (InputMP,sizeof (struct IOStdReq))))
CloseStuff (10);
if (Device = OpenDevice ("input.device",NULL,InputIO,NULL))
CloseStuff (10);
InputBase = (struct Library *)InputIO->io_Device;
glob.EveryKey = FALSE;
if (!(CxPort = (struct MsgPort *)CreateMsgPort ()))
CloseStuff (10);
NewBroker.nb_Port = CxPort;
if (!(Broker = (CxObj *)CxBroker (&NewBroker,NULL)))
CloseStuff (10);
ActivateCxObj (Broker,TRUE);
}
/*
* Add an input event to the input event chain
*/
void AddEvent (int class, int subclass, int code, int qual, int x, int y, APTR eventad)
{
struct InputEvent ie;
ie.ie_Code = code;
ie.ie_Qualifier = qual;
ie.ie_Class = class;
ie.ie_SubClass = subclass;
if (eventad) ie.ie_EventAddress = eventad;
else
{
ie.ie_X = x;
ie.ie_Y = y;
}
InputIO->io_Data = (APTR)&ie;
InputIO->io_Command = IND_WRITEEVENT;
InputIO->io_Length = sizeof (struct InputEvent);
DoIO (InputIO);
}
/*
* This routine is only for the input handler. It is used to send a
* message to the main program
*/
void __regargs Send (struct GlobData *gd, struct InputEvent *ev)
{
struct SpecMsg *Msg;
if (Msg = (struct SpecMsg *)AllocMem (sizeof (struct SpecMsg),MEMF_PUBLIC))
{
Msg->msg.mn_ReplyPort = NULL;
Msg->msg.mn_Length = sizeof (struct SpecMsg);
Msg->Class = ev->ie_Class;
Msg->Code = ev->ie_Code;
Msg->Qualifier = ev->ie_Qualifier;
PutMsg (gd->Port,(struct Message *)Msg);
}
}
/*
* The input handler
*/
void __asm HandlerCode (register __a0 struct InputEvent *Ev,
register __a1 struct GlobData *gd)
{
struct InputEvent *ev;
if (!gd->Enable) return;
for (ev = Ev; ev; ev = ev->ie_NextEvent)
if (ev->ie_Class == IECLASS_RAWMOUSE)
{
gd->IsAlt = 0;
if (ev->ie_Qualifier == 0x1234) continue;
else if (ev->ie_Code == IECODE_RBUTTON+0x80)
{
/* Right mouse button */
Send (gd,ev);
ev->ie_Class = IECLASS_NULL;
}
}
else if (ev->ie_Class == IECLASS_RAWKEY)
if (gd->EveryKey)
{
/* Menu mode */
Send (gd,ev);
ev->ie_Class = IECLASS_NULL;
}
else
{
if (!(ev->ie_Qualifier & gd->qual))
if (ev->ie_Code == gd->peek) /* Left-alt */
{
/* Left-alt is pressed */
gd->IsAlt = 1;
}
else if (ev->ie_Code == gd->peek+0x80)
{
/* Left-alt is released */
if (!gd->IsAlt) continue;
gd->IsAlt = 0;
Send (gd,ev);
}
else gd->IsAlt = 0;
else gd->IsAlt = 0;
}
}
/*
* Handle some special commodity messages
*/
UWORD TraiterCx (void)
{
CxMsg *CxMsg;
UWORD Quit = FALSE;
ULONG msgid,msgtype;
while (CxMsg = (LONG *)GetMsg (CxPort))
{
msgid = CxMsgID (CxMsg);
msgtype = CxMsgType (CxMsg);
ReplyMsg ((struct Message *)CxMsg);
if (msgtype == CXM_COMMAND)
switch (msgid)
{
case CXCMD_DISABLE:
glob.Enable = FALSE;
ActivateCxObj (Broker, FALSE);
break;
case CXCMD_ENABLE:
glob.Enable = TRUE;
ActivateCxObj (Broker, TRUE);
break;
case CXCMD_KILL:
Quit = TRUE;
break;
}
}
return (Quit);
}
/* Data to remember the selected item */
struct Menu *menu;
struct MenuItem *menuit,*menusub;
struct Screen *scr;
struct Window *win;
/*
* Move the mouse pointer to a fixed position
*/
void __regargs MovePointer (int x, int y)
{
struct IEPointerPixel iepp;
iepp.iepp_Screen = scr;
iepp.iepp_Position.X = x;
iepp.iepp_Position.Y = y;
AddEvent (IECLASS_NEWPOINTERPOS,IESUBCLASS_PIXEL,0,0,0,0,(APTR)&iepp);
}
/*
* Move the mouse pointer to the position represented by the selected
* item
*/
void MoveMenu ()
{
int x,y;
x = menu->LeftEdge+3;
y = menu->TopEdge+3;
if (menuit)
{
x += 7+menuit->LeftEdge;
y += menuit->TopEdge+scr->BarHeight;
}
if (menusub)
{
x += menusub->LeftEdge;
y += menusub->TopEdge;
}
MovePointer (x,y);
}
/*
* Search for the menu on a given position
*/
struct Menu * __regargs SearchMenu (int x, int y)
{
struct Menu *m;
m = win->MenuStrip;
while (m)
{
if (x >= m->LeftEdge && x <= (m->LeftEdge+m->Width) && y >= m->TopEdge
&& y <= (m->TopEdge+scr->BarHeight))
return (m);
m = m->NextMenu;
}
return (NULL);
}
/*
* Search for the menuitem on a given position
*/
struct MenuItem * __regargs SearchItem (struct Menu **m)
{
struct MenuItem *mi,*ms;
*m = win->MenuStrip;
while (*m)
{
mi = (*m)->FirstItem;
while (mi)
{
if (mi->Flags & HIGHITEM)
{
ms = mi->SubItem;
while (ms)
{
if (ms->Flags & HIGHITEM) return (NULL);
ms = ms->NextItem;
}
return (mi);
}
mi = mi->NextItem;
}
*m = (*m)->NextMenu;
}
*m = NULL;
return (NULL);
}
/*
* Move to the left
*/
void __regargs MoveLeft (int qual)
{
struct Menu *m;
if (qual & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT))
{
menusub = menuit = NULL;
menu = win->MenuStrip;
return;
}
if (menusub) menusub = NULL;
else
{
m = win->MenuStrip;
while (m)
{
if (m->NextMenu == menu || m->NextMenu == NULL)
{
menu = m;
menuit = NULL;
break;
}
m = m->NextMenu;
}
}
}
/*
* Move to the right
*/
void __regargs MoveRight (int qual)
{
if (qual & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT))
{
menusub = menuit = NULL;
while (menu->NextMenu) menu = menu->NextMenu;
return;
}
if ((!menusub) && menuit && menuit->SubItem)
menusub = menuit->SubItem;
else
{
if (menu->NextMenu)
menu = menu->NextMenu;
else menu = win->MenuStrip;
menuit = NULL;
menusub = NULL;
}
}
/*
* Move down
*/
void __regargs MoveDown (int qual)
{
int shift;
shift = qual & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT);
if (menusub)
{
if (menusub->NextItem) menusub = menusub->NextItem;
if (shift)
while (menusub->NextItem) menusub = menusub->NextItem;
}
else
{
if (menuit)
{
if (menuit->NextItem) menuit = menuit->NextItem;
if (shift)
while (menuit->NextItem) menuit = menuit->NextItem;
}
else
{
menuit = menu->FirstItem;
if (shift)
while (menuit->NextItem) menuit = menuit->NextItem;
}
}
}
/*
* Move up
*/
void __regargs MoveUp (int qual)
{
int shift;
struct MenuItem *mi;
shift = qual & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT);
if (menusub)
{
if (shift) menusub = menuit->SubItem;
else
{
mi = menuit->SubItem;
while (mi)
{
if (mi->NextItem == menusub)
{
menusub = mi;
break;
}
mi = mi->NextItem;
}
}
}
else
{
if (menuit)
{
if (shift) menuit = menu->FirstItem;
else
{
mi = menu->FirstItem;
while (mi)
{
if (mi->NextItem == menuit)
{
menuit = mi;
break;
}
mi = mi->NextItem;
}
if (!mi) menuit = NULL;
}
}
}
}
/*
* Search the next char and move to that item
*/
void __regargs MoveChar (int code, int qual)
{
struct MenuItem *mi;
struct Menu *m;
struct IntuiText *it;
char buf[3];
int rc;
struct InputEvent ie;
ie.ie_Class = IECLASS_RAWKEY;
ie.ie_SubClass = 0;
ie.ie_X = 0;
ie.ie_Y = 0;
ie.ie_Code = code;
ie.ie_Qualifier = qual;
rc = MapRawKey (&ie,buf,1,NULL);
if (!rc) return;
buf[0] = tolower(buf[0]);
if (menusub)
{
mi = menusub;
do
{
if (mi->Flags & ITEMTEXT)
{
it = (struct IntuiText *)(mi->ItemFill);
if (it && tolower(it->IText[0]) == buf[0])
{
menusub = mi;
break;
}
}
mi = mi->NextItem;
if (!mi) mi = menuit->SubItem;
}
while (mi != menusub);
}
else
{
if (menuit)
{
mi = menuit;
do
{
if (mi->Flags & ITEMTEXT)
{
it = (struct IntuiText *)(mi->ItemFill);
if (it && tolower(it->IText[0]) == buf[0])
{
menuit = mi;
if (menuit->SubItem)
{
MoveMenu ();
MoveRight (0);
}
break;
}
}
mi = mi->NextItem;
if (!mi) mi = menu->FirstItem;
}
while (mi != menuit);
}
else
{
m = menu;
do
{
if (m->MenuName && tolower(m->MenuName[0]) == buf[0])
{
menu = m;
MoveMenu ();
MoveDown (0);
break;
}
m = m->NextMenu;
if (!m) m = win->MenuStrip;
}
while (m != menu);
}
}
}
/*
* Main program
*/
void argmain (void)
{
long sig,sigport,sigcx;
struct SpecMsg *msg;
struct Task *Task;
struct DiskObject *diskobj;
int MouseX = 0,MouseY = 0;
int end;
OpenStuff ();
glob.peek = 0x64;
if (Cli ())
{
PutStr ("\33[33mAltMenu 1.0 by Jorrit Tyberghein\33[31m\n© Copyright 1992\33[31m\n");
if (RDArgs = (struct RDArgs *)ReadArgs ("LALT/s,RALT/s,CTRL/s,LCMD/s,RCMD/s",ArgsArray,NULL))
{
if (ArgsArray[0]) glob.peek = 0x64;
if (ArgsArray[1]) glob.peek = 0x65;
if (ArgsArray[2]) glob.peek = 0x63;
if (ArgsArray[3]) glob.peek = 0x66;
if (ArgsArray[4]) glob.peek = 0x67;
}
else
{
PutStr ("Invalid parameters!\n");
CloseStuff (10);
}
}
else
{
Task = (struct Task *)FindTask (NULL);
if (diskobj = (struct DiskObject *)GetDiskObjectNew (Task->tc_Node.ln_Name))
{
if (FindToolType (diskobj->do_ToolTypes,"LALT")) glob.peek = 0x64;
if (FindToolType (diskobj->do_ToolTypes,"RALT")) glob.peek = 0x65;
if (FindToolType (diskobj->do_ToolTypes,"CTRL")) glob.peek = 0x63;
if (FindToolType (diskobj->do_ToolTypes,"LCMD")) glob.peek = 0x66;
if (FindToolType (diskobj->do_ToolTypes,"RCMD")) glob.peek = 0x67;
FreeDiskObject (diskobj);
}
}
switch (glob.peek)
{
case 0x64 : glob.qual = 0xfb & ~IEQUALIFIER_LALT; break;
case 0x65 : glob.qual = 0xfb & ~IEQUALIFIER_RALT; break;
case 0x63 : glob.qual = 0xfb & ~IEQUALIFIER_CONTROL; break;
case 0x66 : glob.qual = 0xfb & ~IEQUALIFIER_LCOMMAND; break;
case 0x67 : glob.qual = 0xfb & ~IEQUALIFIER_RCOMMAND; break;
}
Handler.is_Code = (APTR)handler;
Handler.is_Data = (APTR)&glob;
Handler.is_Node.ln_Pri = 100;
Handler.is_Node.ln_Name = "AltMenu";
InputIO->io_Data = &Handler;
InputIO->io_Command = IND_ADDHANDLER;
DoIO (InputIO);
sigport = 1<<glob.Port->mp_SigBit;
sigcx = 1<<CxPort->mp_SigBit;
while (TRUE)
{
sig = Wait (sigcx|sigport|SIGBREAKF_CTRL_C);
if (sig & sigport)
while (msg = (struct SpecMsg *)GetMsg (glob.Port))
{
if (glob.EveryKey && (msg->Class != IECLASS_RAWMOUSE || msg->Code != IECODE_RBUTTON+0x80))
{
end = FALSE;
if (msg->Code == glob.peek) msg->Code = -1;
switch (msg->Code)
{
case CODE_SPACE :
AddEvent (IECLASS_RAWMOUSE,0,IECODE_LBUTTON,0x1234,0,0,NULL);
AddEvent (IECLASS_RAWMOUSE,0,IECODE_LBUTTON+0x80,0x1234,0,0,NULL);
break;
case -1 :
AddEvent (IECLASS_POINTERPOS,0,0,0,0,0,NULL);
case CODE_ENTER :
case CODE_RETURN :
end = TRUE;
glob.EveryKey = FALSE;
AddEvent (IECLASS_RAWMOUSE,0,IECODE_RBUTTON+0x80,0x1234,0,0,NULL);
MovePointer (MouseX,MouseY);
break;
case CODE_LEFT :
MoveLeft (msg->Qualifier);
break;
case CODE_RIGHT :
MoveRight (msg->Qualifier);
break;
case CODE_DOWN :
MoveDown (msg->Qualifier);
break;
case CODE_UP :
MoveUp (msg->Qualifier);
break;
default :
MoveChar (msg->Code,msg->Qualifier);
}
if (!end) MoveMenu ();
}
else
{
glob.EveryKey = FALSE;
win = IntuitionBase->ActiveWindow;
scr = win->WScreen;
MouseX = scr->MouseX;
MouseY = scr->MouseY;
menuit = menusub = NULL;
if (msg->Class == IECLASS_RAWMOUSE && msg->Code == IECODE_RBUTTON+0x80)
{
if (menu = SearchMenu (MouseX,MouseY))
{
MoveMenu ();
glob.EveryKey = TRUE;
}
else if ((menuit = SearchItem (&menu)) && menuit->SubItem)
{
MoveMenu ();
glob.EveryKey = TRUE;
}
else AddEvent (IECLASS_RAWMOUSE,0,IECODE_RBUTTON+0x80,0x1234,0,0,NULL);
}
else if (menu = win->MenuStrip)
{
MovePointer (0,0);
AddEvent (IECLASS_RAWMOUSE,0,IECODE_RBUTTON,0x1234,0,0,NULL);
MoveMenu ();
glob.EveryKey = TRUE;
}
}
FreeMem (msg,msg->msg.mn_Length);
}
if (sig & sigcx)
if (TraiterCx ()) break;
if (sig & SIGBREAKF_CTRL_C) break;
}
InputIO->io_Data = &Handler;
InputIO->io_Command = IND_REMHANDLER;
DoIO (InputIO);
CloseStuff (0);
}