1 /* - cfn - completes filenames when pressing the "TAB" key */
3 /* written in 1993 by Andreas Günther */
5 /* ( compiled with aztec-C 5.2 ) */
6 /* for more information, please read the doc-file */
9 /* this is NOT great artwork, so */
11 /* FEEL FREE TO IMPROVE THIS CODE ! */
15 /* note: this piece of code is real public domain, do with */
16 /* it whatever you want, but I would be happy if you */
17 /* left my name in it :) */
25 #include <exec/types.h>
26 #include <exec/interrupts.h>
27 #include <exec/memory.h>
28 #include <intuition/intuitionbase.h>
29 //#include "functions.h"
30 #include <devices/input.h>
31 #include <dos/dosextens.h>
32 #include <dos/exall.h>
33 #include <proto/alib.h>
34 #include <proto/keymap.h>
35 #include <proto/utility.h>
37 #include <aros/oldprograms.h>
38 #include <aros/debug.h>
40 #define BUF_LEN 256 /* number of buffered characters from input stream */
41 #define COMPL_LEN 64 /* maximum length of filename completion */
42 #define FILTER "~(#?.info)"
45 #pragma amicall(SysBase, 0, observe_input(a0))
51 char *ver
="$VER: cfn 1.0 (21.6.93) by Andreas Günther";
53 struct IntuitionBase
*IntuitionBase
=NULL
;
54 struct Library
*KeymapBase
=NULL
;
55 struct UtilityBase
*UtilityBase
=NULL
;
58 struct InputEvent event
, *cur_ev
;
61 char buf
[BUF_LEN
]; /* recently typed characters */
62 struct InputEvent ie_buffer
[2*BUF_LEN
]; /* recently typed characters as InputEvents*/
65 char compl[COMPL_LEN
]; /* actual completion */
66 struct Interrupt
*handler
;
68 struct IOStdReq
*io_req
;
73 IntuitionBase
= (struct IntuitionBase
*) OpenLibrary("intuition.library",37);
74 KeymapBase
= OpenLibrary("keymap.library",37);
75 UtilityBase
= (struct UtilityBase
*)OpenLibrary("utility.library",37);
76 return(IntuitionBase
!=NULL
&& KeymapBase
!=NULL
&& UtilityBase
!=NULL
);
81 if(NULL
!=IntuitionBase
)
82 CloseLibrary((struct Library
*)IntuitionBase
);
84 CloseLibrary(KeymapBase
);
86 CloseLibrary((struct Library
*)UtilityBase
);
91 void filter_equal_part(char *file
)
93 /* leaves in compl[] only the first chars that are equal with "file" */
95 while(ToUpper(file
[i
])==ToUpper(compl[i
]) && compl[i
]!=0 && file
[i
]!=0)
100 void find_completion(char *part
, BPTR dir
)
102 /* scans the given dir and finds the longest unique completion */
103 char pat
[COMPL_LEN
*2+6];
104 struct ExAllControl
*eac
;
105 struct ExAllData
*alldata
, *ead
;
108 kprintf("cfn: find_completion(%s dir = %x)\n", part
, dir
);
111 if(NULL
!=(alldata
=(struct ExAllData
*)malloc(3000)))
114 ParsePatternNoCase(part
,pat
,COMPL_LEN
*2+6);
115 eac
=AllocDosObject(DOS_EXALLCONTROL
,NULL
);
118 eac
->eac_MatchString
=pat
;
120 ExAll(dir
,alldata
,3000,ED_NAME
,eac
);
121 if(eac
->eac_Entries
!=0)
123 strcpy(compl,&alldata
->ed_Name
[strlen(part
)-FILTER_LEN
]);
124 if(eac
->eac_Entries
==1)
126 struct FileInfoBlock
*fileinfo
;
127 if(NULL
!=(fileinfo
=AllocDosObject(DOS_FIB
,NULL
)))
130 lock
=Lock(alldata
->ed_Name
,ACCESS_READ
);
131 Examine(lock
,fileinfo
);
132 if(fileinfo
->fib_DirEntryType
>0) /* Directory ? */
135 FreeDosObject(DOS_FIB
,fileinfo
);
139 for(ead
=alldata
->ed_Next
; ead
!=NULL
; ead
=ead
->ed_Next
)
141 filter_equal_part(&ead
->ed_Name
[strlen(part
)-FILTER_LEN
]);
144 FreeDosObject(DOS_EXALLCONTROL
,eac
);
152 struct InputEvent
*observe_input(struct InputEvent
*oldevent
)
154 /* This is the handler itself.
155 It puts every rawkey into the buffer, clears the buffer when a
156 SPACE comes along and signals on arrival of a TAB */
160 for(cur_ev
=oldevent
; cur_ev
!=NULL
; cur_ev
=cur_ev
->ie_NextEvent
)
162 if(cur_ev
->ie_Class
==IECLASS_RAWKEY
/* && !(cur_ev->ie_Code&0x80)*/)
164 if(cur_ev
->ie_Code
==0x42) /* TAB */
166 kprintf("cfn: tab rawkey :-)\n");
170 cur_ev
->ie_Class
=IECLASS_NULL
;
172 else if(cur_ev
->ie_Code
==0x40 || /* SPACE */
173 cur_ev
->ie_Code
==0x44 || /* RETURN */
174 cur_ev
->ie_Code
==0x4c || /* Arrow Up */
175 cur_ev
->ie_Code
==0x4d || /* Arrow Down */
176 cur_ev
->ie_Code
==0x4e) /* Arrow Right */
180 ie_buffer
[bufpos
++]=*cur_ev
;
191 void put_into_stream(char *str
)
193 /* puts the given string into the input stream */
197 event
.ie_NextEvent
=NULL
; /* recycle received event */
198 for(i
=0; str
[i
]!=0; i
++)
200 MapANSI(&str
[i
],1,&raw_char
[0],1,NULL
);
201 event
.ie_Code
=raw_char
[0];
202 event
.ie_Qualifier
=raw_char
[1];
203 io_req
->io_Data
=(APTR
)&event
;
204 io_req
->io_Length
=sizeof(struct InputEvent
);
205 io_req
->io_Command
=IND_WRITEEVENT
;
206 DoIO((struct IORequest
*)io_req
);
210 void serve_handler(void)
212 /* Waits for a Signal from the handler, finds the appropriate completion
213 for the given part of the path and puts it into the input stream
214 (sends it to the input device) */
216 struct Process
*proc
; /* process of the current CLI */
217 BPTR old_lock
,path_lock
;
221 sig
=1<<AllocSignal(-1);
222 task
=FindTask(NULL
); /* for signaling from interrupt */
225 kprintf("cfn: waiting for sig\n");
227 kprintf("cfn: received sig\n");
229 proc
=(struct Process
*)IntuitionBase
->ActiveWindow
->UserData
; /* set by cfn_newshell */
231 kprintf("cfn: proc = %x\n", proc
);
232 if(proc
!=NULL
) /* set by "cfn_newshell" (should be started first) */
235 for(i
=0; i
<bufpos
; i
++)
237 ie_buffer
[i
].ie_NextEvent
=NULL
;
238 if(ie_buffer
[i
].ie_Code
==0x41) /* Backspace */
239 buf
[strpos
? strpos
:0]=0;
241 strpos
+=MapRawKey(&ie_buffer
[i
],&buf
[strpos
],20,NULL
);
245 buf
[strpos
]=0; /* buf is now the incomplete filename */
246 kprintf("cfn: buf = [%s]\n",buf
);
248 old_lock
=CurrentDir(proc
->pr_CurrentDir
); /* CDir of the input shell */
249 strpos
=(int)((IPTR
)PathPart(buf
)-(IPTR
)buf
);
252 path_lock
=Lock(buf
,ACCESS_READ
);
254 find_completion(FilePart(buf
),path_lock
);
255 put_into_stream(compl);
256 CurrentDir(old_lock
);
263 int main(int argc
, char **argv
)
267 if((port
=CreatePort(NULL
,0)))
269 if((handler
=AllocMem(sizeof(struct Interrupt
),MEMF_PUBLIC
|MEMF_CLEAR
)))
271 if((io_req
=(struct IOStdReq
*)CreateExtIO(port
,sizeof(struct IOStdReq
))))
273 if(!OpenDevice("input.device",0,(struct IORequest
*)io_req
,0))
275 handler
->is_Code
=(VOID_FUNC
)observe_input
;
276 handler
->is_Data
=NULL
;
277 handler
->is_Node
.ln_Pri
=1; /* just before console.device */
278 handler
->is_Node
.ln_Name
="cfn";
279 io_req
->io_Data
=(APTR
)handler
;
280 io_req
->io_Command
=IND_ADDHANDLER
;
281 DoIO((struct IORequest
*)io_req
);
282 serve_handler(); /* never returns... */
285 puts("cfn: ERROR: could not open input.device\n");
288 puts("cfn: ERROR: could not create IO-Request\n");
291 puts("cfn: ERROR: could not allocate memory for interrupt structure\n");
294 puts("cfn: ERROR: could not create port \n");
297 puts("cfn: ERROR: could not open intuition.library !\n");