home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume38 / menushell / part03 / dl.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-30  |  5.3 KB  |  333 lines

  1. /* ============================== dl.c ============================== */
  2. #include "dl.h"
  3.  
  4. void *malloc();
  5.  
  6. char *getnode(size)
  7. {
  8.     DL_NODE *n;
  9.  
  10.     if (n = (DL_NODE *) malloc(size)) {
  11.         memset(n, '\0', size);
  12.         n->size = size;
  13.     }
  14.     return(n);
  15. }
  16.  
  17. freenode(n)
  18. DL_NODE *n;
  19. {
  20.     free(n);
  21. }
  22.  
  23. /*
  24.  * Create an empty list
  25.  */
  26. DLIST dl_create(flags)
  27. int flags;
  28. {
  29.     DLIST l;
  30.  
  31.     if ((l = (DLIST) malloc(sizeof(struct dl))) == NULL)
  32.         return NULL;
  33.  
  34.     l->head = l->tail = l->curr = NULL;
  35.     l->size = 0;
  36.     l->flags = flags;
  37.     return(l);
  38. }
  39.  
  40. /*
  41.  * Free entire list
  42.  */
  43. dl_destroy(l)
  44. DLIST l;
  45. {
  46.     while (dl_shead(l))
  47.         dl_delete(l);
  48.     /*
  49.      * it is assumed that the list head structure itself was
  50.      * from dl_create, thus will always be free'd.
  51.      */
  52.     free(l);
  53. }
  54.  
  55. /*
  56.  * Delete specific node
  57.  */
  58. dl_delete_node(l, n)
  59. DLIST l;
  60. DL_NODE *n;
  61. {
  62.     if (n) {
  63.         dl_detach_node(l, n);
  64.  
  65.         if ((l->flags & DL_FREE) == DL_FREE)
  66.             freenode(n);
  67.     }
  68. }
  69.  
  70. /*
  71.  * Delete node, but leave memory alone
  72.  */
  73. dl_detach_node(l, n)
  74. DLIST l;
  75. DL_NODE *n;
  76. {
  77.     l->size--;
  78.  
  79.     l->curr = n->next;
  80.     if (n->prev)
  81.         n->prev->next = n->next;
  82.     else
  83.         l->head = n->next;
  84.     if (n->next)
  85.         n->next->prev = n->prev;
  86.     else
  87.         l->tail = n->prev;
  88. }
  89.  
  90. /*
  91.  * Insert node n before the current location in list l
  92.  */
  93. dl_ins_before_node(l, n_on_list, new_n)
  94. DLIST l;
  95. DL_NODE *n_on_list, *new_n;
  96. {
  97.     l->size++;
  98.  
  99.     if (l->head == NULL) {
  100.         l->head = l->tail = l->curr = new_n;
  101.         new_n->next = new_n->prev = NULL;
  102.         return;
  103.     }
  104.  
  105.     dl_set(l, n_on_list);
  106.     if (l->curr == NULL)
  107.         l->curr = l->head;
  108.  
  109.     new_n->prev = l->curr->prev;
  110.     new_n->next = l->curr;
  111.     if (l->curr->prev)
  112.         l->curr->prev->next = new_n;
  113.     else
  114.         l->head = new_n;        /* else l->curr == l->head */
  115.     l->curr->prev = new_n;
  116.  
  117.     l->curr = new_n;
  118. }
  119.  
  120. dl_ins_after_node(l, n_on_list, new_n)
  121. DLIST l;
  122. DL_NODE *n_on_list, *new_n;
  123. {
  124.     l->size++;
  125.  
  126.     if (l->head == NULL) {
  127.         l->head = l->tail = l->curr = new_n;
  128.         new_n->next = new_n->prev = NULL;
  129.         return;
  130.     }
  131.  
  132.     dl_set(l, n_on_list);
  133.     if (l->curr == NULL)
  134.         l->curr = l->tail;
  135.  
  136.     new_n->prev = l->curr;
  137.     new_n->next = l->curr->next;
  138.     if (l->curr->next)
  139.         l->curr->next->prev = new_n;
  140.     else
  141.         l->tail = new_n;        /* else l->curr == l->tail */
  142.     l->curr->next = new_n;
  143.  
  144.     l->curr = new_n;
  145. }
  146.  
  147. /*
  148.  * Join l2 to the end of l1; l2 is no longer usable
  149.  */
  150. dl_cat(l1, l2)
  151. DLIST l1, l2;
  152. {
  153.     l1->size += l2->size;
  154.     l1->tail->next = l2->head;
  155.     l2->head->prev = l1->tail;
  156.     l1->tail = l2->tail;
  157.  
  158.     free(l2);
  159. }
  160.  
  161. /*
  162.  *  Split list 'l' into two, so that 'n' is the first node of the new list,
  163.  *  return pointer to new list.
  164.  */
  165. /*  Uncomment and do as exercise
  166. DLIST dl_split_at_node(l, n)
  167. DLIST l;
  168. DL_NODE *n;
  169. {
  170.     DLIST newl;
  171.  
  172.     if ((newl = dl_create(dl_flags(l))) == NULL)
  173.         return(NULL);
  174.  
  175.     newl->size = count from current pos to end
  176.     l->size = count up to current pos (l->size - newl->size)
  177.  
  178.     adjust pointers (last of l, first of newl (i.e., n))
  179.  
  180.     return newl
  181. }
  182. */
  183.  
  184. DLIST dl_copy(l)
  185. DLIST l;
  186. {
  187.     DLIST newl;
  188.     DL_NODE *n, *newn;
  189.  
  190.     if ((newl = dl_create(dl_flags(l))) == NULL)
  191.         return(NULL);
  192.  
  193.     foreachnode(l, n) {
  194.         newn = getnode(n->size);
  195.         if (newn == NULL) {
  196.             dl_destroy(newl);
  197.             return(NULL);
  198.         }
  199.         memcpy(newn, n, n->size);    /* copies ptrs, but is ok */
  200.         dl_append(newl, newn);
  201.     }
  202.  
  203.     return(newl);
  204. }
  205.  
  206. dl_compare(l1, l2, func)
  207. DLIST l1, l2;
  208. int (*func)();
  209. {
  210.     int comp;
  211.  
  212.     for (dl_shead(l1), dl_shead(l2);
  213.          dl_curr(l1) && dl_curr(l2);
  214.          dl_snext(l1), dl_snext(l2))
  215.         if ((comp = (*func)(dl_curr(l1), dl_curr(l2))) != 0)
  216.             return(comp);
  217.  
  218.     if (dl_curr(l1))
  219.         return(1);    /* l2 ran out first */
  220.     else if (dl_curr(l2))
  221.         return(-1);    /* l1 ran out first */
  222.     else
  223.         return(0);    /* both ran out at same time */
  224. }
  225.  
  226. dl_apply(l, func, arg)
  227. DLIST l;
  228. int (*func)();
  229. char *arg;
  230. {
  231.     foreach(l)
  232.         (*func)(dl_curr(l), arg);
  233. }
  234.  
  235. /*
  236.  * Do a linear search on the list, given a start/end point
  237.  */
  238. dl_lsearch(l, begin, end, key, func)
  239. DLIST l;
  240. DL_NODE *begin, *end;
  241. void *key;
  242. int (*func)();
  243. {
  244.     DL_NODE *n;
  245.  
  246.     for (n = begin; n != end; n = n->next)
  247.         if ((*func)(n, key)) {
  248.             l->curr = n;
  249.             return(TRUE);
  250.         }
  251.  
  252.     return(FALSE);
  253. }
  254.  
  255. /*
  256.  * dl_sort - take a list and a 'qsort' type cmp func & sort
  257.  *
  258.  * since we make an array of ptrs, qsort really needs a cmp func
  259.  * that follows a pointer to pointer to user struct; but this is
  260.  * ugly for users, so dl_sort_cmp_fun does one indirection then
  261.  * calls the users cmp func.
  262.  */
  263.  
  264. static int (*dl_sort_user_cmp_fun)();
  265.  
  266. dl_sort_cmp_fun(p1, p2)
  267. DL_NODE **p1, **p2;
  268. {
  269.     return((*dl_sort_user_cmp_fun)(*p1, *p2));
  270. }
  271.  
  272. dl_sort(l, func)
  273. DLIST l;
  274. int (*func)();
  275. {
  276.     DL_NODE **array;
  277.     int i, last;
  278.  
  279.     if (l->size <= 1)
  280.         return(0);
  281.  
  282.     if ((array = dl_l2a(l)) == NULL)
  283.         return(-1);
  284.  
  285.     dl_sort_user_cmp_fun = func;
  286.     qsort(array, l->size, sizeof(DL_NODE *), dl_sort_cmp_fun);
  287.  
  288.     dl_a2l(l, array);
  289.  
  290.     free(array);
  291.  
  292.     return(0);
  293. }
  294.  
  295. /* from a list, make an array of pointers to the list items */
  296. DL_NODE **
  297. dl_l2a(l)
  298. DLIST l;
  299. {
  300.     DL_NODE *n, **array, **a;
  301.  
  302.     array = (DL_NODE **) malloc(l->size*sizeof(DL_NODE *));
  303.     if (array == NULL)
  304.         return(NULL);
  305.     
  306.     for (n = l->head, a = array; n != NULL; n = n->next, a++)
  307.         *a = n;
  308.  
  309.     return(array);
  310. }
  311.  
  312. /* turn an array of pointers to the list items into a list */
  313. dl_a2l(l, array)
  314. DLIST l;
  315. DL_NODE **array;
  316. {
  317.     int i, last;
  318.  
  319.     l->head = array[0];
  320.     l->head->prev = NULL;
  321.     l->head->next = array[1];
  322.  
  323.     last = l->size - 1;
  324.     for (i = 1; i < last; i++) {
  325.         array[i]->next = array[i+1];
  326.         array[i]->prev = array[i-1];
  327.     }
  328.  
  329.     l->tail = array[last];
  330.     l->tail->next = NULL;
  331.     l->tail->prev = array[last-1];
  332. }
  333.