Files
sibo-playground/code/SIBOSDK/ats/kats.c
2026-07-06 18:01:36 +01:00

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);
}