499 lines
11 KiB
C
499 lines
11 KiB
C
/*
|
|
File: KATS.C
|
|
*/
|
|
|
|
#include <ats.h>
|
|
#include <p_gen.h>
|
|
#include <p_file.h>
|
|
#include <wlib.h>
|
|
#include <olib.g>
|
|
#include <appman.g>
|
|
#include <gate.g>
|
|
#include <kats.rsg>
|
|
|
|
#define KATS_MODS (W_CTRL_MODIFIER|W_PSION_MODIFIER)
|
|
#define KATS_RECORD 0x20
|
|
#define KATS_PLAYBACK W_KEY_RETURN
|
|
#define KATS_PLAYBACK2 W_KEY_TAB
|
|
#define KATS_SAVE W_KEY_DIAMOND
|
|
|
|
#define MAX_NUM_KEYS 128 /* maximum number of keys per macro */
|
|
#define MACRO_NAME_LEN 24 /* includes zero terminator */
|
|
|
|
typedef struct
|
|
{
|
|
TEXT name[MACRO_NAME_LEN];
|
|
WORD num_keys;
|
|
ATS_KEY_DEF keys[MAX_NUM_KEYS];
|
|
} KATS_MACRO;
|
|
|
|
GLREF_D VOID *DatCommandPtr;
|
|
GLREF_D VOID *DatGate;
|
|
|
|
LOCAL_D HANDLE olib;
|
|
|
|
LOCAL_D VOID *vaxvar;
|
|
LOCAL_D UWORD nmacros;
|
|
|
|
LOCAL_D KATS_MACRO mac_rec; /* macro being recorded */
|
|
LOCAL_D ATS_KEY full_key; /* key being recorded */
|
|
|
|
LOCAL_D KATS_MACRO *mac_play; /* macro being played back */
|
|
LOCAL_D INT play_keys;
|
|
|
|
LOCAL_D INT changed;
|
|
|
|
LOCAL_D INT pid;
|
|
|
|
LOCAL_D INT record;
|
|
LOCAL_D INT playback;
|
|
|
|
LOCAL_D WS_EV event;
|
|
LOCAL_D WORD rec_stat;
|
|
LOCAL_D WORD rec_active;
|
|
LOCAL_D WORD play_stat;
|
|
LOCAL_D WORD play_active;
|
|
|
|
LOCAL_D TEXT *pmac_name;
|
|
LOCAL_D ATS_DIAL_DEF dl_edit;
|
|
LOCAL_D ATS_DIAL_DEF dl_choose;
|
|
LOCAL_D ATS_DIAL_DEF dl_confirm;
|
|
LOCAL_D ATS_DIAL_DEF dl_save;
|
|
|
|
LOCAL_C INT GetForegroundClient(VOID)
|
|
{
|
|
UWORD pids[WS_MAX_CLIENTS+1];
|
|
|
|
wGetProcessList(&pids[0]);
|
|
return(pids[0]);
|
|
}
|
|
|
|
LOCAL_C INT GetTestForegroundClient(VOID)
|
|
{
|
|
INT pid;
|
|
|
|
pid=GetForegroundClient();
|
|
if (!p_send3(DatGate,O_GT_CHECK_ATS_ON,pid))
|
|
return(pid); /* okay */
|
|
p_sound(5,320);
|
|
p_sound(5,280);
|
|
p_sound(5,240);
|
|
return(NULL);
|
|
}
|
|
|
|
LOCAL_C VOID ForegroundAtsWait(INT type,ATS_MESS_BODY *pu)
|
|
{
|
|
INT pid;
|
|
|
|
pid=GetTestForegroundClient();
|
|
if (pid)
|
|
p_msendreceivew(pid,type,pu);
|
|
}
|
|
|
|
LOCAL_C VOID Message(TEXT *msg)
|
|
{
|
|
ATS_MESS_BODY u;
|
|
|
|
u.offs=msg;
|
|
ForegroundAtsWait(TY_ATS_MESSAGE,&u);
|
|
}
|
|
|
|
LOCAL_C VOID TellErr(INT err)
|
|
{
|
|
TEXT buf[64];
|
|
|
|
if (err==E_GEN_FAIL)
|
|
return;
|
|
p_errs(&buf[0],err);
|
|
Message(&buf[0]);
|
|
}
|
|
|
|
LOCAL_C VOID TellOom(VOID)
|
|
{
|
|
TellErr(E_GEN_NOMEMORY);
|
|
}
|
|
|
|
LOCAL_C VOID PlayNextKey(VOID)
|
|
{
|
|
ATS_MESS_BODY u;
|
|
|
|
u.k=mac_play->keys[play_keys];
|
|
play_active=TRUE;
|
|
p_msendreceivea(pid,TY_ATS_KEY,&u,&play_stat);
|
|
}
|
|
|
|
LOCAL_C VOID RequestNextKey(VOID)
|
|
{
|
|
ATS_MESS_BODY u;
|
|
|
|
u.offs=(&full_key);
|
|
rec_active=TRUE;
|
|
p_msendreceivea(pid,TY_ATS_GET_KEY,&u,&rec_stat);
|
|
}
|
|
|
|
LOCAL_C VOID TransmitRecordState(VOID)
|
|
{
|
|
ATS_MESS_BODY u;
|
|
|
|
u.par=record;
|
|
p_msendreceivew(pid,TY_ATS_RECORD,&u);
|
|
}
|
|
|
|
LOCAL_C KATS_MACRO *FindMacro(INT i)
|
|
{
|
|
return((KATS_MACRO *)p_send(vaxvar,O_VA_PBUF,i));
|
|
}
|
|
|
|
LOCAL_C VOID DeleteMacro(INT i)
|
|
{
|
|
p_send3(vaxvar,O_VA_DELETE,i);
|
|
nmacros--;
|
|
changed=TRUE;
|
|
}
|
|
|
|
LOCAL_C INT QueryOverwrite(VOID)
|
|
{
|
|
ATS_MESS_BODY u;
|
|
|
|
u.d=dl_confirm;
|
|
return(p_msendreceivew(pid,TY_ATS_DIALOG,&u));
|
|
}
|
|
|
|
LOCAL_C VOID SaveIfConfirmed(VOID)
|
|
{
|
|
INT pid;
|
|
ATS_MESS_BODY u;
|
|
|
|
pid=GetTestForegroundClient();
|
|
if (!pid)
|
|
return;
|
|
u.d=dl_save;
|
|
if (p_msendreceivew(pid,TY_ATS_DIALOG,&u)==W_KEY_RETURN)
|
|
{
|
|
Message("Should save now!");
|
|
changed=FALSE;
|
|
}
|
|
}
|
|
|
|
LOCAL_C INT CheckNotMatching(VOID)
|
|
{
|
|
INT i;
|
|
KATS_MACRO *pmac;
|
|
INT key;
|
|
|
|
for (i=0; i<nmacros; i++)
|
|
{
|
|
pmac=FindMacro(i);
|
|
if (p_scmpi(&pmac->name[0],&mac_rec.name[0]))
|
|
continue;
|
|
key=QueryOverwrite();
|
|
if (key==W_KEY_ESCAPE)
|
|
return(FALSE);
|
|
DeleteMacro(i);
|
|
return(key==' ');
|
|
}
|
|
return(TRUE);
|
|
}
|
|
|
|
LOCAL_C INT GetMacroName(VOID)
|
|
{
|
|
ATS_MESS_BODY u;
|
|
INT ret;
|
|
|
|
u.d=dl_edit;
|
|
ret=p_msendreceivew(pid,TY_ATS_DIALOG,&u);
|
|
if (ret<0)
|
|
{
|
|
TellErr(ret);
|
|
return(0);
|
|
}
|
|
return(CheckNotMatching());
|
|
}
|
|
|
|
LOCAL_C VOID StartRecording(VOID)
|
|
{
|
|
pid=GetTestForegroundClient();
|
|
if (!pid)
|
|
return;
|
|
if (GetMacroName())
|
|
{
|
|
record=TRUE;
|
|
TransmitRecordState();
|
|
Message("Recording...");
|
|
mac_rec.num_keys=0;
|
|
RequestNextKey();
|
|
}
|
|
}
|
|
|
|
#pragma save,ENTER_CALL
|
|
|
|
LOCAL_C INT AppendMacro(VOID)
|
|
{
|
|
RC_VAXVAR rcv;
|
|
|
|
rcv.buf=(UBYTE *)(&mac_rec);
|
|
rcv.len=MACRO_NAME_LEN+sizeof(WORD)+mac_rec.num_keys*sizeof(ATS_KEY_DEF);
|
|
p_send3(vaxvar,O_VA_APPEND,&rcv);
|
|
nmacros++;
|
|
return(0);
|
|
}
|
|
|
|
#pragma restore
|
|
|
|
LOCAL_C VOID StopRecording(VOID)
|
|
{
|
|
record=FALSE;
|
|
TransmitRecordState();
|
|
if (!mac_rec.num_keys)
|
|
{
|
|
Message("Recording cancelled");
|
|
return;
|
|
}
|
|
if (p_enter1(AppendMacro)<0)
|
|
TellOom();
|
|
else if (mac_rec.num_keys==MAX_NUM_KEYS)
|
|
Message("Maximum number of keystrokes reached");
|
|
else
|
|
Message("Finished recording");
|
|
}
|
|
|
|
LOCAL_C VOID BuildNameList(VOID)
|
|
{
|
|
UBYTE *pb;
|
|
UBYTE *new_pb;
|
|
INT i;
|
|
INT size;
|
|
INT this_size;
|
|
KATS_MACRO *pmac;
|
|
|
|
pb=p_alloc(1);
|
|
if (!pb)
|
|
return;
|
|
size=1;
|
|
*pb=0;
|
|
for (i=0; i<nmacros; i++)
|
|
{
|
|
pmac=FindMacro(i);
|
|
this_size=p_slen(&pmac->name[0])+2; /* include LBC and ZTS */
|
|
new_pb=p_realloc(pb,size+this_size);
|
|
if (!new_pb)
|
|
{
|
|
p_free(pb);
|
|
return;
|
|
}
|
|
pb=new_pb;
|
|
*(pb+size)=this_size-1; /* leading byte count */
|
|
p_scpy(pb+size+1,&pmac->name[0]);
|
|
size+=this_size;
|
|
}
|
|
*pb=i;
|
|
dl_choose.buts=(UWORD)pb;
|
|
dl_choose.butslen=size;
|
|
}
|
|
|
|
LOCAL_C VOID FreeNameList(VOID)
|
|
{
|
|
p_free((VOID *)dl_choose.buts);
|
|
dl_choose.buts=NULL;
|
|
}
|
|
|
|
LOCAL_C VOID StartPlayback(VOID)
|
|
{
|
|
ATS_MESS_BODY u;
|
|
INT ret;
|
|
|
|
pid=GetTestForegroundClient();
|
|
if (!pid)
|
|
return;
|
|
BuildNameList();
|
|
if (!dl_choose.buts)
|
|
{
|
|
TellOom();
|
|
return;
|
|
}
|
|
u.d=dl_choose;
|
|
ret=p_msendreceivew(pid,TY_ATS_DIALOG,&u);
|
|
FreeNameList();
|
|
if (ret<0)
|
|
{
|
|
TellErr(ret);
|
|
return;
|
|
}
|
|
mac_play=FindMacro(ret);
|
|
play_keys=0;
|
|
playback=TRUE;
|
|
PlayNextKey();
|
|
}
|
|
|
|
LOCAL_C VOID StopPlayback(VOID)
|
|
{
|
|
playback=FALSE;
|
|
}
|
|
|
|
LOCAL_C VOID NextStageInRecord(VOID)
|
|
{
|
|
ATS_KEY_DEF *short_key;
|
|
|
|
short_key=(&mac_rec.keys[mac_rec.num_keys++]);
|
|
short_key->key=full_key.keycode;
|
|
short_key->mod=full_key.modifiers;
|
|
changed=TRUE;
|
|
if (mac_rec.num_keys==MAX_NUM_KEYS)
|
|
StopRecording();
|
|
else
|
|
RequestNextKey();
|
|
}
|
|
|
|
LOCAL_C VOID NextStageInPlayback(VOID)
|
|
{
|
|
play_keys++;
|
|
if (play_keys==mac_play->num_keys)
|
|
{
|
|
StopPlayback();
|
|
Message("Playback complete");
|
|
}
|
|
else
|
|
PlayNextKey();
|
|
}
|
|
|
|
LOCAL_C VOID MainLoop(VOID)
|
|
{
|
|
FOREVER
|
|
{
|
|
wGetEvent(&event);
|
|
wait:
|
|
p_iowait();
|
|
switch (event.type)
|
|
{
|
|
case E_FILE_PENDING:
|
|
if (rec_active && rec_stat!=E_FILE_PENDING)
|
|
{
|
|
rec_active=FALSE;
|
|
if (record) /* else recording cancelled */
|
|
NextStageInRecord();
|
|
}
|
|
else if (play_active && play_stat!=E_FILE_PENDING)
|
|
{
|
|
play_active=FALSE;
|
|
if (playback) /* else playback cancelled */
|
|
NextStageInPlayback();
|
|
}
|
|
goto wait;
|
|
case WM_FOREGROUND:
|
|
wClientPosition(WS_LAST_CLIENT_POSITION,0);
|
|
break;
|
|
case WM_KEY:
|
|
switch (event.p.key.keycode)
|
|
{
|
|
case KATS_SAVE:
|
|
if (record)
|
|
Message("Can't save macros while recording");
|
|
else if (playback)
|
|
Message("Can't save macros while playing back");
|
|
else if (!changed)
|
|
Message("No macro changes to save");
|
|
else
|
|
SaveIfConfirmed();
|
|
break;
|
|
case KATS_RECORD:
|
|
if (record)
|
|
StopRecording();
|
|
else if (playback)
|
|
Message("Can't record while playing back");
|
|
else
|
|
StartRecording();
|
|
break;
|
|
case KATS_PLAYBACK:
|
|
case KATS_PLAYBACK2:
|
|
if (playback)
|
|
{
|
|
Message("Playback terminated");
|
|
StopPlayback();
|
|
}
|
|
else if (record)
|
|
Message("Can't play back while recording");
|
|
else if (!nmacros)
|
|
Message("Nothing to play back");
|
|
else
|
|
StartPlayback();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
LOCAL_C VOID FindOlib(VOID)
|
|
{
|
|
p_findlib("OLIB.DYL",&olib);
|
|
}
|
|
|
|
LOCAL_C VOID CreateGate(VOID)
|
|
{
|
|
HANDLE hwim;
|
|
|
|
p_findlib("HWIM.DYL",&hwim);
|
|
DatGate=f_newlibh(hwim,C_GATE);
|
|
}
|
|
|
|
LOCAL_C VOID LoadDialogData(VOID)
|
|
{
|
|
VOID *rcb;
|
|
|
|
rcb=f_newlibhsend(olib,C_RSCFILE,O_RS_INIT,DatCommandPtr);
|
|
dl_edit.mainlen=p_send4(rcb,O_RS_READ,KATS_DL_MAC_NAME,&dl_edit.main);
|
|
dl_choose.mainlen=p_send4(rcb,O_RS_READ,KATS_DL_PLAYBACK,&dl_choose.main);
|
|
dl_confirm.mainlen=p_send4(rcb,O_RS_READ,
|
|
KATS_DL_CONFIRM,&dl_confirm.main);
|
|
dl_confirm.butslen=p_send4(rcb,O_RS_READ,
|
|
KATS_AC_CONFIRM,&dl_confirm.buts);
|
|
dl_save.mainlen=p_send4(rcb,O_RS_READ,KATS_DL_SAVE,&dl_save.main);
|
|
dl_save.butslen=p_send4(rcb,O_RS_READ,KATS_AC_SAVE,&dl_save.buts);
|
|
p_send2(rcb,O_DESTROY);
|
|
dl_edit.butslen=(-2);
|
|
dl_edit.buts=(UWORD)(&pmac_name);
|
|
pmac_name=(&mac_rec.name[0]);
|
|
}
|
|
|
|
LOCAL_C VOID CreateMacroStorage(VOID)
|
|
{
|
|
vaxvar=f_newlibhsend(olib,C_VAXVAR,O_VA_INIT,48);
|
|
}
|
|
|
|
LOCAL_C VOID ConnectToWindowServer(VOID)
|
|
{
|
|
wConnect(f_alloc(sizeof(WSERV_SPEC)),0,W_CONNECT_AT_BACK);
|
|
}
|
|
|
|
LOCAL_C VOID CaptureKeys(VOID)
|
|
{
|
|
wCaptureKey(KATS_RECORD,KATS_MODS,KATS_MODS);
|
|
wCaptureKey(KATS_PLAYBACK,KATS_MODS,KATS_MODS);
|
|
wCaptureKey(KATS_PLAYBACK2,KATS_MODS,KATS_MODS);
|
|
wCaptureKey(KATS_SAVE,KATS_MODS,KATS_MODS);
|
|
}
|
|
|
|
#pragma save,ENTER_CALL
|
|
|
|
LOCAL_C INT Initialise(VOID)
|
|
{
|
|
FindOlib();
|
|
CreateGate();
|
|
LoadDialogData();
|
|
CreateMacroStorage();
|
|
ConnectToWindowServer();
|
|
CaptureKeys();
|
|
Message("Keyboard macro support loaded");
|
|
return(0);
|
|
}
|
|
|
|
#pragma restore
|
|
|
|
GLDEF_C INT main(VOID)
|
|
{
|
|
INT ret;
|
|
|
|
ret=p_enter1(Initialise);
|
|
if (!ret)
|
|
MainLoop();
|
|
return(ret);
|
|
}
|