home *** CD-ROM | disk | FTP | other *** search
- /* - cfn - completes filenames when pressing the "TAB" key */
-
- /* written in 1993 by Andreas Günther */
-
- /* ( compiled with aztec-C 5.2 ) */
- /* for more information, please read the doc-file */
-
-
- /* this is NOT great artwork, so */
-
- /* FEEL FREE TO IMPROVE THIS CODE ! */
-
-
-
- /* note: this piece of code is real public domain, do with */
- /* it whatever you want, but I would be happy if you */
- /* left my name in it :) */
-
-
-
- #include "string.h"
-
- #include "exec/types.h"
- #include "exec/interrupts.h"
- #include "exec/memory.h"
- #include "intuition/intuitionbase.h"
- #include "functions.h"
- #include "devices/input.h"
- #include "dos/exall.h"
-
- #define BUF_LEN 256 /* number of buffered characters from input stream */
- #define COMPL_LEN 64 /* maximum length of filename completion */
- #define FILTER "~(#?.info)"
- #define FILTER_LEN 10
- #pragma amicall(SysBase, 0, observe_input(a0))
-
- char *ver="$VER: cfn 1.0 (21.6.93) by Andreas Günther";
-
- struct IntuitionBase *IntuitionBase=NULL;
- struct Library *KeymapBase=NULL;
- struct Library *UtilityBase=NULL;
- ULONG ilock,sig;
- BOOL ready;
- struct InputEvent event, *cur_ev;
-
- struct Task *task;
- char buf[BUF_LEN]; /* recently typed characters */
- struct InputEvent ie_buffer[2*BUF_LEN]; /* recently typed characters as InputEvents*/
- int bufpos=0;
- BOOL buf_busy=FALSE;
- char compl[COMPL_LEN]; /* actual completion */
- struct Interrupt *handler;
- struct MsgPort *port;
- struct IOStdReq *io_req;
-
-
- BOOL open_libs()
- {
- IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library",37);
- KeymapBase = OpenLibrary("keymap.library",37);
- UtilityBase = OpenLibrary("utility.library",37);
- return(IntuitionBase!=NULL && KeymapBase!=NULL && UtilityBase!=NULL);
- }
-
- void close_libs()
- {
- if(NULL!=IntuitionBase)
- CloseLibrary(IntuitionBase);
- if(NULL!=KeymapBase)
- CloseLibrary(KeymapBase);
- if(NULL!=UtilityBase)
- CloseLibrary(UtilityBase);
- }
-
-
-
- void filter_equal_part(char *file)
- {
- /* leaves in compl[] only the first chars that are equal with "file" */
- int i=0;
- while(ToUpper(file[i])==ToUpper(compl[i]) && compl[i]!=0 && file[i]!=0)
- i++;
- compl[i]=0;
- }
-
- void find_completion(char *part, BPTR dir)
- {
- /* scans the given dir and finds the longest unique completion */
- char pat[COMPL_LEN*2+6];
- struct ExAllControl *eac;
- struct ExAllData *alldata, *ead;
- BPTR lock;
-
- compl[0]=0;
- if(NULL!=(alldata=(struct ExAllData *)malloc(3000)))
- {
- strcat(part,FILTER);
- ParsePatternNoCase(part,pat,COMPL_LEN*2+6);
- eac=AllocDosObject(DOS_EXALLCONTROL,NULL);
- if(eac!=NULL)
- {
- eac->eac_MatchString=pat;
- eac->eac_LastKey=0;
- ExAll(dir,alldata,3000,ED_NAME,eac);
- if(eac->eac_Entries!=0)
- {
- strcpy(compl,&alldata->ed_Name[strlen(part)-FILTER_LEN]);
- if(eac->eac_Entries==1)
- {
- struct FileInfoBlock *fileinfo;
- if(NULL!=(fileinfo=AllocDosObject(DOS_FIB,NULL)))
- {
- CurrentDir(dir);
- lock=Lock(alldata->ed_Name,ACCESS_READ);
- Examine(lock,fileinfo);
- if(fileinfo->fib_DirEntryType>0) /* Directory ? */
- strcat(compl,"/");
- UnLock(lock);
- FreeDosObject(DOS_FIB,fileinfo);
- }
- }
- else
- for(ead=alldata->ed_Next; ead!=NULL; ead=ead->ed_Next)
- {
- filter_equal_part(&ead->ed_Name[strlen(part)-FILTER_LEN]);
- }
- }
- FreeDosObject(DOS_EXALLCONTROL,eac);
- }
- free(alldata);
- }
- }
-
-
-
- struct InputEvent *observe_input(struct InputEvent *oldevent)
- {
- /* This is the handler itself.
- It puts every rawkey into the buffer, clears the buffer when a
- SPACE comes along and signals on arrival of a TAB */
-
- int_start();
- if(!buf_busy)
- for(cur_ev=oldevent; cur_ev!=NULL; cur_ev=cur_ev->ie_NextEvent)
- {
- if(cur_ev->ie_Class==IECLASS_RAWKEY/* && !(cur_ev->ie_Code&0x80)*/)
- {
- if(cur_ev->ie_Code==0x42) /* TAB */
- {
- event=*cur_ev;
- buf_busy=TRUE;
- Signal(task,sig);
- cur_ev->ie_Class=IECLASS_NULL;
- }
- else if(cur_ev->ie_Code==0x40 || /* SPACE */
- cur_ev->ie_Code==0x44 || /* RETURN */
- cur_ev->ie_Code==0x4c || /* Arrow Up */
- cur_ev->ie_Code==0x4d || /* Arrow Down */
- cur_ev->ie_Code==0x4e) /* Arrow Right */
- bufpos=0;
- else
- {
- ie_buffer[bufpos++]=*cur_ev;
- if(bufpos==BUF_LEN)
- bufpos=0;
- }
- }
- }
- int_end();
- return(oldevent);
- }
-
-
- void put_into_stream(char *str)
- {
- /* puts the given string into the input stream */
- int i;
- struct cq_pair {UBYTE code, qual;} raw_char;
-
- event.ie_NextEvent=NULL; /* recycle received event */
- for(i=0; str[i]!=0; i++)
- {
- MapANSI(&str[i],1,&raw_char,1,NULL);
- event.ie_Code=raw_char.code;
- event.ie_Qualifier=raw_char.qual;
- io_req->io_Data=(APTR)&event;
- io_req->io_Length=sizeof(struct InputEvent);
- io_req->io_Command=IND_WRITEEVENT;
- DoIO((struct IORequest *)io_req);
- }
- }
-
- serve_handler()
- {
- /* Waits for a Signal from the handler, finds the appropriate completion
- for the given part of the path and puts it into the input stream
- (sends it to the input device) */
-
- struct Process *proc; /* process of the current CLI */
- BPTR old_lock,path_lock;
- int i,strpos;
- char tmp;
-
- sig=1<<AllocSignal(-1);
- task=FindTask(NULL); /* for signaling from interrupt */
- for(;;)
- {
- Wait(sig);
- ilock=LockIBase(0);
- proc=IntuitionBase->ActiveWindow->UserData; /* set by cfn_newshell */
- UnlockIBase(ilock);
- if(proc!=NULL) /* set by "cfn_newshell" (should be started first) */
- {
- strpos=0;
- for(i=0; i<bufpos; i++)
- {
- ie_buffer[i].ie_NextEvent=NULL;
- if(ie_buffer[i].ie_Code==0x41) /* Backspace */
- buf[strpos ? strpos--:0]=0;
- else
- strpos+=MapRawKey(&ie_buffer[i],&buf[strpos],20,NULL);
- }
- buf_busy=FALSE;
- buf[strpos]=0; /* buf is now the incomplete filename */
- old_lock=CurrentDir(proc->pr_CurrentDir); /* CDir of the input shell */
- strpos=(int)(PathPart(buf)-buf);
- tmp=buf[strpos];
- buf[strpos]=0;
- path_lock=Lock(buf,ACCESS_READ);
- buf[strpos]=tmp;
- find_completion(FilePart(buf),path_lock);
- put_into_stream(compl);
- CurrentDir(old_lock);
- UnLock(path_lock);
- }
- }
- }
-
-
- main()
- {
- if(open_libs())
- {
- if(port=CreatePort(NULL,0))
- {
- if(handler=AllocMem(sizeof(struct Interrupt),MEMF_PUBLIC|MEMF_CLEAR))
- {
- if(io_req=(struct IOStdReq *)CreateExtIO(port,sizeof(struct IOStdReq)))
- {
- if(!OpenDevice("input.device",0,(struct IORequest *)io_req,0))
- {
- handler->is_Code=observe_input;
- handler->is_Data=NULL;
- handler->is_Node.ln_Pri=1; /* just before console.device */
- handler->is_Node.ln_Name="cfn";
- io_req->io_Data=(APTR)handler;
- io_req->io_Command=IND_ADDHANDLER;
- DoIO((struct IORequest *)io_req);
- serve_handler(); /* never returns... */
- }
- else
- puts("cfn: ERROR: could not open input.device\n");
- }
- else
- puts("cfn: ERROR: could not create IO-Request\n");
- }
- else
- puts("cfn: ERROR: could not allocate memory for interrupt structure\n");
- }
- else
- puts("cfn: ERROR: could not create port \n");
- }
- else
- puts("cfn: ERROR: could not open intuition.library !\n");
- close_libs();
- }
-