/* macros.c routines to bind keyboard macros to individual keys */ #include #include "ed.h" #define FLEN 14 static FILE *mp; /* file pointer for LOAD and SAVE */ static char macfile[NFILEN+1] = "uemail.mcr"; static short macstr[NKBDM]; typedef struct MACTAB { struct MACTAB *m_fmac; /* next MACTAB */ short *keymac; /* pointer to the macro */ char key; /* the key */ } MACTAB; MACTAB *mheadp = NULL; /* pointer to header structure */ /* GETMACRO eXtended command to store a macro in the table above. * Copies the current keyboard macro to the appropriate array. * Bound to ^X-`. */ getmacro(f, n) int f,n; { register int c,i; short *maccpy(); register MACTAB *mt; MACTAB *mcralloc(); /* is there currently a macro being defined ? */ if (kbdmip != NULL || kbdmop != NULL) { mlwrite("Not now"); return (FALSE); } mlwrite("Key to bind to current macro: "); c = ttgetc(); ttputc(c); if((mt=mcralloc(TRUE,c))==NULL) return(FALSE); i = maclen(kbdm); mt->key = c; /* install the key */ if ((mt->keymac=(short *)malloc((i+1)*sizeof(short)))==NULL) { mlwrite("Cannot allocate space for macro"); return(FALSE); } maccpy(mt->keymac,kbdm); /* copy the macro */ return(TRUE); } /* PUTMACRO AGRAVE command finds macro associated with key returned * by ttgetc and executes the macro. */ putmacro(f, n) register int f, n; { register int c; short *maccpy(); register MACTAB *mt; MACTAB *mcralloc(); c = ttgetc(); /* get next char */ switch(c) { case 0x07: /* abort */ return(ctrlg(FALSE,0)); case 0x0c: /* load a macro file */ return(loadmac(TRUE)); case 0x0d: /* "make" a macro file */ return(savemac()); case 0x12: /* incremental search back */ return(backisearch(f, n)); case 0x13: /* incremental search forward */ return(forwisearch(f, n)); case 0x14: /* get time */ return(showtime(f,n)); case '`': return(linsert(1,c)); } if (kbdmip!=NULL || kbdmop!=NULL) { mlwrite("Not now"); return (FALSE); } /* actually, there should be no way mheadp could != NULL and * its forward pointer == NULL, but it's best to check */ if (mheadp==NULL || mheadp->m_fmac == NULL) { mlwrite("No defineable macros assigned"); return(FALSE); } if((mt=mcralloc(FALSE,c))!= (MACTAB *)NULL) { /* save current macro to restore later */ maccpy(macstr,kbdm); maccpy(kbdm,mt->keymac); c=ctlxe(f, n); /* execute mac in keybrd.c */ maccpy(kbdm,macstr); return(c); } (*term.t_beep)(); return(FALSE); } /* LOADMAC load a macro file and install the macros into memory. * Bound to `^L. */ loadmac(f) int f; { short *maccpy(); register int c,i; register short s; register MACTAB *mt; MACTAB *mcralloc(); if (f==TRUE) /* FALSE == Called from main */ { if(readpattern("Load macros: ",macfile)==ABORT) return(ABORT); } else strcpy(macfile,"uemail.mcr"); if (macfile[0] == '~') parsefn(macfile); if ((mp=fopen(macfile,"r"))==NULL) { mlwrite("Cannot open %s",macfile); return(FALSE); } if ((s=getw(mp))!=(CTLX|'(')) { mlwrite("Macro file format error: %s",macfile); fclose(mp); return(FALSE); } while((c=fgetc(mp))!=EOF) { i=0; mlwrite("[Installing macro for key %c]",c); if((mt=mcralloc(TRUE,c))==NULL) { fclose(mp); return(FALSE); } while ((s=getw(mp))!=(CTLX|')')) { if (feof(mp)) { mlwrite("Read error on: %s",macfile); break; } macstr[i++]=s; } macstr[i] = CTLX|')'; mt->key = c; /* install the key */ if ((mt->keymac=(short *)malloc((i+1)*sizeof(short)))==NULL) { fclose(mp); mlwrite("Cannot allocate space for macro"); return(FALSE); } maccpy(mt->keymac,macstr); /* copy the macro */ } fclose(mp); return(TRUE); } /* SAVEMAC function to save current keyboard macros to a file. * Bound to `^M (makemac). */ savemac() { short *maccpy(); register int i; register short s; register MACTAB *mt; if(readpattern("Save macros: ",macfile)==ABORT) return(ABORT); if (macfile[0] == '~') parsefn(macfile); if ((mp=fopen(macfile,"w"))==NULL) { mlwrite("Cannot open %s",macfile); return(FALSE); } /* actually, there should be no way mheadp could != NULL and * its forward pointer == NULL, but it's best to check */ if (mheadp==NULL || mheadp->m_fmac == NULL) { mlwrite("No defineable macros assigned"); return(FALSE); } /* don't change the file format or the load function * will fail */ mt=mheadp->m_fmac; putw(CTLX|'(',mp); while(mt != NULL) { i=0; mlwrite("[Saving key: %c]",mt->key); maccpy(macstr,mt->keymac); fputc(mt->key,mp); while(macstr[i]!=(CTLX|')')) putw(macstr[i++],mp); putw(CTLX|')',mp); mt=mt->m_fmac; /* next pointer */ } fclose(mp); return(TRUE); } /* find an existing keyboard macro or get space for a new one. Return * a pointer to the MACTAB structure so others can do with it what they * will. */ MACTAB * mcralloc(f,c) register int f,c; { register MACTAB *mt; if (mheadp == NULL) { if ((mheadp=(MACTAB *)malloc(sizeof(MACTAB))) == NULL) { mlwrite("Cannot allocate %d bytes",sizeof(MACTAB)); return(FALSE); } mheadp->m_fmac = (MACTAB *)NULL; } /* check to see if this one has already been allocated */ mt=mheadp; while(mt->m_fmac != (MACTAB *)NULL) { if (mt->m_fmac->key == c) { if (f == TRUE) /* reallocate old */ free(mt->m_fmac->keymac); return(mt->m_fmac); } mt=mt->m_fmac; /* next pointer */ } /* this was a get request. return if no macro found */ if (f==FALSE) return(FALSE); /* otherwise must be a new request */ if ((mt->m_fmac=(MACTAB *)malloc(sizeof(MACTAB)))==NULL) { mlwrite("Cannot allocate %d bytes",sizeof(MACTAB)); return(FALSE); } mt->m_fmac->m_fmac = (MACTAB *)NULL; /* new pointer */ return(mt->m_fmac); } /* PUTLIN function to service putmacro() also used by enumerate and showtime */ putlin(lin) register char *lin; { while(*lin) linsert(1,*lin++); } /* get actual length of macro to allocate spacr */ maclen(mac) register short *mac; { register int i; i = 1; while(*mac++ != (CTLX|')')) ++i; return(i); } /* similar to strcpy but copies one keyboard macro to another returning * the address of the destination string. */ short * maccpy(dest, sour) register short *dest; register short *sour; { register short *dptr; register short s; dptr = dest; while ((s = *sour++) != (CTLX|')')) *dest++ = s; *dest = CTLX|')'; return(dptr); }