home *** CD-ROM | disk | FTP | other *** search
/ Computer Club Elmshorn Atari PD / CCE_PD.iso / pc / 0600 / CCE_0638.ZIP / CCE_0638 / UPDATE / UPDATE29.ZOO / editline / complete.c < prev    next >
C/C++ Source or Header  |  1993-03-28  |  4KB  |  246 lines

  1. /*  $Revision: 1.2 $
  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. #ifdef atarist
  97. /*
  98. ** find the last slash in a path name.
  99. ** returns position of last slash or NULL
  100. */
  101. STATIC char *
  102. lastslash(p)
  103.     char    *p;
  104. {
  105.     char    *e;
  106.  
  107.     if(!p) return NULL;
  108.  
  109.     for(e = p + strlen(p) - 1; (e != p) && (*e != '/') && (*e != '\\'); e--)
  110.     ;
  111.     return (e == p) ? NULL : e;
  112. }
  113. #endif
  114.  
  115. /*
  116. **  Split a pathname into allocated directory and trailing filename parts.
  117. */
  118. STATIC int
  119. SplitPath(path, dirpart, filepart)
  120.     char    *path;
  121.     char    **dirpart;
  122.     char    **filepart;
  123. {
  124.     static char    DOT[] = ".";
  125.     char    *dpart;
  126.     char    *fpart;
  127.  
  128. #ifdef atarist
  129.     if ((fpart = lastslash(path)) == NULL) {
  130. #else
  131.     if ((fpart = strrchr(path, '/')) == NULL) {
  132. #endif
  133.     if ((dpart = strdup(DOT)) == NULL)
  134.         return -1;
  135.     if ((fpart = strdup(path)) == NULL) {
  136.         DISPOSE(dpart);
  137.         return -1;
  138.     }
  139.     }
  140.     else {
  141.     if ((dpart = strdup(path)) == NULL)
  142.         return -1;
  143.     dpart[fpart - path] = '\0';
  144.     if ((fpart = strdup(++fpart)) == NULL) {
  145.         DISPOSE(dpart);
  146.         return -1;
  147.     }
  148.     }
  149.     *dirpart = dpart;
  150.     *filepart = fpart;
  151.     return 0;
  152. }
  153.  
  154. /*
  155. **  Attempt to complete the pathname, returning an allocated copy.
  156. **  Fill in *unique if we completed it, or set it to 0 if ambiguous.
  157. */
  158. char *
  159. rl_complete(pathname, unique)
  160.     char    *pathname;
  161.     int        *unique;
  162. {
  163.     char    **av;
  164.     char    *dir;
  165.     char    *file;
  166.     char    *new;
  167.     char    *p;
  168.     SIZE_T    ac;
  169.     SIZE_T    end;
  170.     SIZE_T    i;
  171.     SIZE_T    j;
  172.     SIZE_T    len;
  173.  
  174.     if (SplitPath(pathname, &dir, &file) < 0)
  175.     return NULL;
  176.     if ((ac = FindMatches(dir, file, &av)) == 0) {
  177.     DISPOSE(dir);
  178.     DISPOSE(file);
  179.     return NULL;
  180.     }
  181.  
  182.     p = NULL;
  183.     len = strlen(file);
  184.     if (ac == 1) {
  185.     /* Exactly one match -- finish it off. */
  186.     *unique = 1;
  187.     j = strlen(av[0]) - len + 2;
  188.     if ((p = NEW(char, j + 1)) != NULL) {
  189.         COPYFROMTO(p, av[0] + len, j);
  190.         if ((new = NEW(char, strlen(dir) + strlen(av[0]) + 2)) != NULL) {
  191.         (void)strcpy(new, dir);
  192.         (void)strcat(new, "/");
  193.         (void)strcat(new, av[0]);
  194.         rl_add_slash(new, p);
  195.         DISPOSE(new);
  196.         }
  197.     }
  198.     }
  199.     else {
  200.     *unique = 0;
  201.     if (len) {
  202.         /* Find largest matching substring. */
  203.         for (i = len, end = strlen(av[0]); i < end; i++)
  204.         for (j = 1; j < ac; j++)
  205.             if (av[0][i] != av[j][i])
  206.             goto breakout;
  207.   breakout:
  208.         if (i > len) {
  209.         j = i - len + 1;
  210.         if ((p = NEW(char, j)) != NULL) {
  211.             COPYFROMTO(p, av[0] + len, j);
  212.             p[j - 1] = '\0';
  213.         }
  214.         }
  215.     }
  216.     }
  217.  
  218.     /* Clean up and return. */
  219.     DISPOSE(dir);
  220.     DISPOSE(file);
  221.     for (i = 0; i < ac; i++)
  222.     DISPOSE(av[i]);
  223.     DISPOSE(av);
  224.     return p;
  225. }
  226.  
  227. /*
  228. **  Return all possible completions.
  229. */
  230. int
  231. rl_list_possib(pathname, avp)
  232.     char    *pathname;
  233.     char    ***avp;
  234. {
  235.     char    *dir;
  236.     char    *file;
  237.     int        ac;
  238.  
  239.     if (SplitPath(pathname, &dir, &file) < 0)
  240.     return 0;
  241.     ac = FindMatches(dir, file, avp);
  242.     DISPOSE(dir);
  243.     DISPOSE(file);
  244.     return ac;
  245. }
  246.