#include #include #include "complete.h" static int longestprefixlength(char *a, char *b, int n) { int i, w; Rune ra, rb; for(i=0; ifilename); free(c); } } static int strpcmp(const void *va, const void *vb) { char *a, *b; a = *(char**)va; b = *(char**)vb; return strcmp(a, b); } Completion* complete(char *dir, char *s) { long i, l, n, nfile, len, nbytes; int fd, minlen; Dir *dirp; char **name, *p; ulong* mode; Completion *c; if(strchr(s, '/') != nil){ werrstr("slash character in name argument to complete()"); return nil; } fd = open(dir, OREAD); if(fd < 0) return nil; n = dirreadall(fd, &dirp); if(n <= 0){ close(fd); return nil; } /* find longest string, for allocation */ len = 0; for(i=0; i len) len = l; } name = malloc(n*sizeof(char*)); mode = malloc(n*sizeof(ulong)); c = malloc(sizeof(Completion) + len); if(name == nil || mode == nil || c == nil) goto Return; memset(c, 0, sizeof(Completion)); /* find the matches */ len = strlen(s); nfile = 0; minlen = 1000000; for(i=0; i strlen(dirp[i].name)) minlen = strlen(dirp[i].name); nfile++; } if(nfile > 0) { /* report interesting results */ /* trim length back to longest common initial string */ for(i=1; icomplete = (nfile == 1); c->advance = c->complete || (minlen > len); c->string = (char*)(c+1); memmove(c->string, name[0]+len, minlen-len); if(c->complete) c->string[minlen++ - len] = (mode[0]&DMDIR)? '/' : ' '; c->string[minlen - len] = '\0'; c->nmatch = nfile; } else { /* no match, so return all possible strings */ for(i=0; inmatch = 0; } /* attach list of names */ nbytes = nfile * sizeof(char*); for(i=0; ifilename = malloc(nbytes); if(c->filename == nil) goto Return; p = (char*)(c->filename + nfile); for(i=0; ifilename[i] = p; strcpy(p, name[i]); p += strlen(p); if(mode[i] & DMDIR) *p++ = '/'; *p++ = '\0'; } c->nfile = nfile; qsort(c->filename, c->nfile, sizeof(c->filename[0]), strpcmp); Return: free(name); free(mode); free(dirp); close(fd); return c; }