/* File: KATS.C */ #include #include #include #include #include #include #include #include #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; iname[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; iname[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); }