home *** CD-ROM | disk | FTP | other *** search
/ BURKS 2 / BURKS_AUG97.ISO / SLAKWARE / D10 / TOOLS.TGZ / TOOLS.tar / usr / doc / tools-2.17 / example / complete.c next >
C/C++ Source or Header  |  1993-02-03  |  4KB  |  223 lines

  1. /*  $Revision: 1.3 $
  2. **
  3. **  History and file completion functions for editline library.
  4. */
  5. #include "editline.h"
  6.  
  7.  
  8. #if    defined(NEED_STRDUP)
  9. /*
  10. **  Return an allocated copy of a string.
  11. */
  12. char *
  13. strdup(p)
  14.     char    *p;
  15. {
  16.     char    *new;
  17.  
  18.     if ((new = NEW(char, strlen(p) + 1)) != NULL)
  19.     (void)strcpy(new, p);
  20.     return new;
  21. }
  22. #endif    /* defined(NEED_STRDUP) */
  23.  
  24. /*
  25. **  strcmp-like sorting predicate for qsort.
  26. */
  27. STATIC int
  28. compare(p1, p2)
  29.     CONST void    *p1;
  30.     CONST void    *p2;
  31. {
  32.     CONST char    **v1;
  33.     CONST char    **v2;
  34.  
  35.     v1 = (CONST char **)p1;
  36.     v2 = (CONST char **)p2;
  37.     return strcmp(*v1, *v2);
  38. }
  39.  
  40. /*
  41. **  Fill in *avp with an array of names that match file, up to its length.
  42. **  Ignore . and .. .
  43. */
  44. STATIC int
  45. FindMatches(dir, file, avp)
  46.     char    *dir;
  47.     char    *file;
  48.     char    ***avp;
  49. {
  50.     char    **av;
  51.     char    **new;
  52.     char    *p;
  53.     DIR        *dp;
  54.     DIRENTRY    *ep;
  55.     SIZE_T    ac;
  56.     SIZE_T    len;
  57.  
  58.     if ((dp = opendir(dir)) == NULL)
  59.     return 0;
  60.  
  61.     av = NULL;
  62.     ac = 0;
  63.     len = strlen(file);
  64.     while ((ep = readdir(dp)) != NULL) {
  65.     p = ep->d_name;
  66.     if (p[0] == '.' && (p[1] == '\0' || (p[1] == '.' && p[2] == '\0')))
  67.         continue;
  68.     if (len && strncmp(p, file, len) != 0)
  69.         continue;
  70.  
  71.     if ((ac % MEM_INC) == 0) {
  72.         if ((new = NEW(char*, ac + MEM_INC)) == NULL)
  73.         break;
  74.         if (ac) {
  75.         COPYFROMTO(new, av, ac * sizeof (char **));
  76.         DISPOSE(av);
  77.         }
  78.         *avp = av = new;
  79.     }
  80.  
  81.     if ((av[ac] = strdup(p)) == NULL) {
  82.         if (ac == 0)
  83.         DISPOSE(av);
  84.         break;
  85.     }
  86.     ac++;
  87.     }
  88.  
  89.     /* Clean up and return. */
  90.     (void)closedir(dp);
  91.     if (ac)
  92.     qsort(av, ac, sizeof (char **), compare);
  93.     return ac;
  94. }
  95.  
  96. /*
  97. **  Split a pathname into allocated directory and trailing filename parts.
  98. */
  99. STATIC int
  100. SplitPath(path, dirpart, filepart)
  101.     char    *path;
  102.     char    **dirpart;
  103.     char    **filepart;
  104. {
  105.     static char    DOT[] = ".";
  106.     char    *dpart;
  107.     char    *fpart;
  108.  
  109.     if ((fpart = strrchr(path, '/')) == NULL) {
  110.     if ((dpart = strdup(DOT)) == NULL)
  111.         return -1;
  112.     if ((fpart = strdup(path)) == NULL) {
  113.         DISPOSE(dpart);
  114.         return -1;
  115.     }
  116.     }
  117.     else {
  118.     if ((dpart = strdup(path)) == NULL)
  119.         return -1;
  120.     dpart[fpart - path] = '\0';
  121.     if ((fpart = strdup(++fpart)) == NULL) {
  122.         DISPOSE(dpart);
  123.         return -1;
  124.     }
  125.     }
  126.     *dirpart = dpart;
  127.     *filepart = fpart;
  128.     return 0;
  129. }
  130.  
  131. /*
  132. **  Attempt to complete the pathname, returning an allocated copy.
  133. **  Fill in *unique if we completed it, or set it to 0 if ambiguous.
  134. */
  135. char *
  136. rl_complete(pathname, unique)
  137.     char    *pathname;
  138.     int        *unique;
  139. {
  140.     char    **av;
  141.     char    *dir;
  142.     char    *file;
  143.     char    *new;
  144.     char    *p;
  145.     SIZE_T    ac;
  146.     SIZE_T    end;
  147.     SIZE_T    i;
  148.     SIZE_T    j;
  149.     SIZE_T    len;
  150.  
  151.     if (SplitPath(pathname, &dir, &file) < 0)
  152.     return NULL;
  153.     if ((ac = FindMatches(dir, file, &av)) == 0) {
  154.     DISPOSE(dir);
  155.     DISPOSE(file);
  156.     return NULL;
  157.     }
  158.  
  159.     p = NULL;
  160.     len = strlen(file);
  161.     if (ac == 1) {
  162.     /* Exactly one match -- finish it off. */
  163.     *unique = 1;
  164.     j = strlen(av[0]) - len + 2;
  165.     if ((p = NEW(char, j + 1)) != NULL) {
  166.         COPYFROMTO(p, av[0] + len, j);
  167.         if ((new = NEW(char, strlen(dir) + strlen(av[0]) + 2)) != NULL) {
  168.         (void)strcpy(new, dir);
  169.         (void)strcat(new, "/");
  170.         (void)strcat(new, av[0]);
  171.         rl_add_slash(new, p);
  172.         DISPOSE(new);
  173.         }
  174.     }
  175.     }
  176.     else {
  177.     *unique = 0;
  178.     if (len) {
  179.         /* Find largest matching substring. */
  180.         for (i = len, end = strlen(av[0]); i < end; i++)
  181.         for (j = 1; j < ac; j++)
  182.             if (av[0][i] != av[j][i])
  183.             goto breakout;
  184.   breakout:
  185.         if (i > len) {
  186.         j = i - len + 1;
  187.         if ((p = NEW(char, j)) != NULL) {
  188.             COPYFROMTO(p, av[0] + len, j);
  189.             p[j - 1] = '\0';
  190.         }
  191.         }
  192.     }
  193.     }
  194.  
  195.     /* Clean up and return. */
  196.     DISPOSE(dir);
  197.     DISPOSE(file);
  198.     for (i = 0; i < ac; i++)
  199.     DISPOSE(av[i]);
  200.     DISPOSE(av);
  201.     return p;
  202. }
  203.  
  204. /*
  205. **  Return all possible completions.
  206. */
  207. int
  208. rl_list_possib(pathname, avp)
  209.     char    *pathname;
  210.     char    ***avp;
  211. {
  212.     char    *dir;
  213.     char    *file;
  214.     int        ac;
  215.  
  216.     if (SplitPath(pathname, &dir, &file) < 0)
  217.     return 0;
  218.     ac = FindMatches(dir, file, avp);
  219.     DISPOSE(dir);
  220.     DISPOSE(file);
  221.     return ac;
  222. }
  223.