diff --git a/src/browser.c b/src/browser.c
index a5a5a8c079eeca3ceaf5a9aa074d8a467e9f45e6..f53f68f4128ed36eeca87f70e8065550200563bf 100644
--- a/src/browser.c
+++ b/src/browser.c
@@ -38,13 +38,14 @@ int graph = 0,
 
 
 
-void browse_draw_info(struct dir *dr) {
-  struct dir *t;
+void browse_draw_info(compll_t dr) {
+  const struct dir *tmp = DR(dr);
+  compll_t t;
   int i;
 
   nccreate(11, 60, "Item info");
 
-  if(dr->hlnk) {
+  if(tmp->hlnk) {
     if(info_page == 0)
       attron(A_REVERSE);
     ncaddstr(0, 41, "1:Info");
@@ -65,16 +66,16 @@ void browse_draw_info(struct dir *dr) {
     ncaddstr(7, 3, "Apparent size:");
     attroff(A_BOLD);
 
-    ncaddstr(2,  9, cropstr(dr->name, 49));
-    ncaddstr(3,  9, cropstr(getpath(dr->parent), 49));
-    ncaddstr(4,  9, dr->flags & FF_DIR ? "Directory"
-        : dr->flags & FF_FILE ? "File" : "Other (link, device, socket, ..)");
-    ncprint(6, 18, "%s (%s B)", formatsize(dr->size),  fullsize(dr->size));
-    ncprint(7, 18, "%s (%s B)", formatsize(dr->asize), fullsize(dr->asize));
+    ncaddstr(2,  9, cropstr(tmp->name, 49));
+    ncaddstr(3,  9, cropstr(getpath(tmp->parent), 49));
+    ncaddstr(4,  9, tmp->flags & FF_DIR ? "Directory"
+        : DR(dr)->flags & FF_FILE ? "File" : "Other (link, device, socket, ..)");
+    ncprint(6, 18, "%s (%s B)", formatsize(tmp->size),  fullsize(tmp->size));
+    ncprint(7, 18, "%s (%s B)", formatsize(tmp->asize), fullsize(tmp->asize));
     break;
 
   case 1:
-    for(i=0,t=dr->hlnk; t!=dr; t=t->hlnk,i++) {
+    for(i=0,t=tmp->hlnk; t!=dr; t=DR(t)->hlnk,i++) {
       if(info_start > i)
         continue;
       if(i-info_start > 5)
@@ -90,12 +91,13 @@ void browse_draw_info(struct dir *dr) {
 }
 
 
-void browse_draw_item(struct dir *n, int row, char *line) {
+void browse_draw_item(compll_t n, int row, char *line) {
   char ct, dt, *size, gr[11];
+  const struct dir *t = DR(n);
   int i, o;
   float pc;
 
-  if(n->flags & FF_BSEL)
+  if(t->flags & FF_BSEL)
     attron(A_REVERSE);
 
   /* reference to parent dir has a different format */
@@ -106,34 +108,35 @@ void browse_draw_item(struct dir *n, int row, char *line) {
         graph == 2 ? 20 :
                      31 ;
     mvaddstr(row, o, "/..");
-    if(n->flags & FF_BSEL)
+    if(t->flags & FF_BSEL)
       attroff(A_REVERSE);
     return;
   }
 
   /* determine indication character */
-  ct =  n->flags & FF_EXL ? '<' :
-        n->flags & FF_ERR ? '!' :
-       n->flags & FF_SERR ? '.' :
-      n->flags & FF_OTHFS ? '>' :
-      n->flags & FF_HLNKC ? 'H' :
-     !(n->flags & FF_FILE
-    || n->flags & FF_DIR) ? '@' :
-        n->flags & FF_DIR
-        && n->sub == NULL ? 'e' :
+  ct =  t->flags & FF_EXL ? '<' :
+        t->flags & FF_ERR ? '!' :
+       t->flags & FF_SERR ? '.' :
+      t->flags & FF_OTHFS ? '>' :
+      t->flags & FF_HLNKC ? 'H' :
+     !(t->flags & FF_FILE
+    || t->flags & FF_DIR) ? '@' :
+        t->flags & FF_DIR
+               && !t->sub ? 'e' :
                             ' ' ;
-  dt = n->flags & FF_DIR ? '/' : ' ';
-  size = formatsize(show_as ? n->asize : n->size);
+  dt = t->flags & FF_DIR ? '/' : ' ';
+  size = formatsize(show_as ? t->asize : t->size);
 
   /* create graph (if necessary) */
   if(graph) {
     /* percentage */
-    if((pc = (float)(show_as ? n->parent->asize : n->parent->size)) < 1)
+    if((pc = (float)(show_as ? DR(t->parent)->asize : DR(t->parent)->size)) < 1)
       pc = 1.0f;
-    pc = ((float)(show_as ? n->asize : n->size) / pc) * 100.0f;
+    t = DR(n);
+    pc = ((float)(show_as ? t->asize : t->size) / pc) * 100.0f;
     /* graph */
     if(graph == 1 || graph == 3) {
-      o = (int)(10.0f*(float)(show_as ? n->asize : n->size) / (float)(show_as ? dirlist_maxa : dirlist_maxs));
+      o = (int)(10.0f*(float)(show_as ? t->asize : t->size) / (float)(show_as ? dirlist_maxa : dirlist_maxs));
       for(i=0; i<10; i++)
         gr[i] = i < o ? '#' : ' ';
       gr[10] = '\0';
@@ -142,19 +145,19 @@ void browse_draw_item(struct dir *n, int row, char *line) {
 
   /* format and add item to the list */
   switch(graph) {
-    case 0: mvprintw(row, 0, line, ct, size, dt, cropstr(n->name, wincols-13)); break;
-    case 1: mvprintw(row, 0, line, ct, size, gr, dt, cropstr(n->name, wincols-25)); break;
-    case 2: mvprintw(row, 0, line, ct, size, pc, dt, cropstr(n->name, wincols-21)); break;
-    case 3: mvprintw(row, 0, line, ct, size, pc, gr, dt, cropstr(n->name, wincols-32));
+    case 0: mvprintw(row, 0, line, ct, size, dt, cropstr(t->name, wincols-13)); break;
+    case 1: mvprintw(row, 0, line, ct, size, gr, dt, cropstr(t->name, wincols-25)); break;
+    case 2: mvprintw(row, 0, line, ct, size, pc, dt, cropstr(t->name, wincols-21)); break;
+    case 3: mvprintw(row, 0, line, ct, size, pc, gr, dt, cropstr(t->name, wincols-32));
   }
 
-  if(n->flags & FF_BSEL)
+  if(t->flags & FF_BSEL)
     attroff(A_REVERSE);
 }
 
 
 void browse_draw() {
-  struct dir *t;
+  compll_t t;
   char fmtsize[9], *tmp, line[35];
   int selected, i;
 
@@ -172,7 +175,7 @@ void browse_draw() {
   mvhline(1, 0, '-', wincols);
   if(t) {
     mvaddch(1, 3, ' ');
-    tmp = getpath(t->parent);
+    tmp = getpath(DR(t)->parent);
     mvaddstr(1, 4, cropstr(tmp, wincols-8));
     mvaddch(1, 4+((int)strlen(tmp) > wincols-8 ? wincols-8 : (int)strlen(tmp)), ' ');
   }
@@ -180,9 +183,9 @@ void browse_draw() {
   /* bottom line - stats */
   attron(A_REVERSE);
   if(t) {
-    strcpy(fmtsize, formatsize(t->parent->size));
+    strcpy(fmtsize, formatsize(DR(DR(t)->parent)->size));
     mvprintw(winrows-1, 0, " Total disk usage: %s  Apparent size: %s  Items: %d",
-      fmtsize, formatsize(t->parent->asize), t->parent->items);
+      fmtsize, formatsize(DR(DR(t)->parent)->asize), DR(DR(t)->parent)->items);
   } else
     mvaddstr(winrows-1, 0, " No items to display.");
   attroff(A_REVERSE);
@@ -206,7 +209,7 @@ void browse_draw() {
   for(i=0; t && i<winrows-3; t=dirlist_next(t),i++) {
     browse_draw_item(t, 2+i, line);
     /* save the selected row number for later */
-    if(t->flags & FF_BSEL)
+    if(DR(t)->flags & FF_BSEL)
       selected = i;
   }
 
@@ -221,7 +224,7 @@ void browse_draw() {
 
 
 int browse_key(int ch) {
-  struct dir *t, *sel;
+  compll_t t, sel;
   int i, catch = 0;
 
   sel = dirlist_get(0);
@@ -233,26 +236,26 @@ int browse_key(int ch) {
       info_page = 0;
       break;
     case '2':
-      if(sel->hlnk)
+      if(DR(sel)->hlnk)
         info_page = 1;
       break;
     case KEY_RIGHT:
     case 'l':
-      if(sel->hlnk) {
+      if(DR(sel)->hlnk) {
         info_page = 1;
         catch++;
       }
       break;
     case KEY_LEFT:
     case 'h':
-      if(sel->hlnk) {
+      if(DR(sel)->hlnk) {
         info_page = 0;
         catch++;
       }
       break;
     case KEY_UP:
     case 'k':
-      if(sel->hlnk && info_page == 1) {
+      if(DR(sel)->hlnk && info_page == 1) {
         if(info_start > 0)
           info_start--;
         catch++;
@@ -261,8 +264,8 @@ int browse_key(int ch) {
     case KEY_DOWN:
     case 'j':
     case ' ':
-      if(sel->hlnk && info_page == 1) {
-        for(i=0,t=sel->hlnk; t!=sel; t=t->hlnk)
+      if(DR(sel)->hlnk && info_page == 1) {
+        for(i=0,t=DR(sel)->hlnk; t!=sel; t=DR(t)->hlnk)
           i++;
         if(i > info_start+6)
           info_start++;
@@ -287,7 +290,7 @@ int browse_key(int ch) {
       info_start = 0;
       break;
     case KEY_HOME:
-      dirlist_select(dirlist_next(NULL));
+      dirlist_select(dirlist_next((compll_t)0));
       dirlist_top(2);
       info_start = 0;
       break;
@@ -337,8 +340,8 @@ int browse_key(int ch) {
     case 10:
     case KEY_RIGHT:
     case 'l':
-      if(sel != NULL && sel->sub != NULL) {
-        dirlist_open(sel->sub);
+      if(sel && DR(sel)->sub) {
+        dirlist_open(DR(sel)->sub);
         dirlist_top(-3);
       }
       info_show = 0;
@@ -346,8 +349,8 @@ int browse_key(int ch) {
     case KEY_LEFT:
     case 'h':
     case '<':
-      if(sel != NULL && sel->parent->parent != NULL) {
-        dirlist_open(sel->parent);
+      if(sel && DR(DR(sel)->parent)->parent) {
+        dirlist_open(DR(sel)->parent);
         dirlist_top(-3);
       }
       info_show = 0;
@@ -355,8 +358,8 @@ int browse_key(int ch) {
 
     /* and other stuff */
     case 'r':
-      if(sel != NULL)
-        calc_init(getpath(sel->parent), sel->parent);
+      if(sel)
+        calc_init(getpath(DR(sel)->parent), DR(sel)->parent);
       info_show = 0;
       break;
     case 'q':
@@ -378,12 +381,12 @@ int browse_key(int ch) {
       info_show = 0;
       break;
     case 'd':
-      if(sel == NULL || sel == dirlist_parent)
+      if(!sel || sel == dirlist_parent)
         break;
       info_show = 0;
       if((t = dirlist_get(1)) == sel)
         if((t = dirlist_get(-1)) == sel || t == dirlist_parent)
-          t = sel->parent;
+          t = DR(sel)->parent;
       delete_init(sel, t);
       break;
     }
@@ -392,14 +395,14 @@ int browse_key(int ch) {
   sel = dirlist_get(0);
   if(!info_show || sel == dirlist_parent)
     info_show = info_page = info_start = 0;
-  else if(sel && !sel->hlnk)
+  else if(sel && !DR(sel)->hlnk)
     info_page = info_start = 0;
 
   return 0;
 }
 
 
-void browse_init(struct dir *cur) {
+void browse_init(compll_t cur) {
   pstate = ST_BROWSE;
   dirlist_open(cur);
 }
diff --git a/src/browser.h b/src/browser.h
index 0643b17ab4e2a23a3bea1e3a472d4ab70fbb2300..83f70d6345033f1d36f6907d38a0bba167874051 100644
--- a/src/browser.h
+++ b/src/browser.h
@@ -30,7 +30,7 @@
 
 int  browse_key(int);
 void browse_draw(void);
-void browse_init(struct dir *);
+void browse_init(compll_t);
 
 
 #endif
diff --git a/src/calc.c b/src/calc.c
index 4a0bc7df15417d3f65d45ea5bd1e41f337388f5b..3cc5c4c307b9856a03b7f3c4381c81a5729fd62d 100644
--- a/src/calc.c
+++ b/src/calc.c
@@ -49,19 +49,19 @@ char failed;             /* 1 on fatal error */
 char *curpath;           /* last lstat()'ed item, used for excludes matching and display */
 char *lasterr;           /* last unreadable dir/item */
 char errmsg[128];        /* error message, when failed=1 */
-struct dir *root;        /* root directory struct we're calculating */
-struct dir *orig;        /* original directory, when recalculating */
+compll_t root;           /* root directory struct we're calculating */
+compll_t orig;           /* original directory, when recalculating */
 dev_t curdev;            /* current device we're calculating on */
 int anpos;               /* position of the animation string */
 int curpathl = 0, lasterrl = 0;
 
-struct dir **links = NULL;
+compll_t *links = NULL;
 int linksl, linkst;
 
 
 
 /* adds name to curpath */
-void calc_enterpath(char *name) {
+void calc_enterpath(const char *name) {
   int n;
 
   n = strlen(curpath)+strlen(name)+2;
@@ -88,11 +88,11 @@ void calc_leavepath() {
 
 
 /* looks in the links list and adds the file when not found */
-int calc_hlink_add(struct dir *d) {
+int calc_hlink_add(compll_t d) {
   int i;
   /* check the list */
   for(i=0; i<linkst; i++)
-    if(links[i]->dev == d->dev && links[i]->ino == d->ino)
+    if(DR(links[i])->dev == DR(d)->dev && DR(links[i])->ino == DR(d)->ino)
       break;
   /* found, do nothing and return the index */
   if(i != linkst)
@@ -102,9 +102,9 @@ int calc_hlink_add(struct dir *d) {
     linksl *= 2;
     if(!linksl) {
       linksl = 64;
-      links = malloc(linksl*sizeof(struct dir *));
+      links = malloc(linksl*sizeof(compll_t));
     } else
-      links = realloc(links, linksl*sizeof(struct dir *));
+      links = realloc(links, linksl*sizeof(compll_t));
   }
   links[linkst-1] = d;
   return -1;
@@ -112,13 +112,13 @@ int calc_hlink_add(struct dir *d) {
 
 
 /* recursively checks a dir structure for hard links and fills the lookup array */
-void calc_hlink_init(struct dir *d) {
-  struct dir *t;
+void calc_hlink_init(compll_t d) {
+  compll_t t;
 
-  for(t=d->sub; t!=NULL; t=t->next)
+  for(t=DR(d)->sub; t; t=DR(t)->next)
     calc_hlink_init(t);
 
-  if(!(d->flags & FF_HLNKC))
+  if(!(DR(d)->flags & FF_HLNKC))
     return;
   calc_hlink_add(d);
 }
@@ -126,103 +126,103 @@ void calc_hlink_init(struct dir *d) {
 
 /* checks an individual file and updates the flags and cicrular linked list,
  * also updates the sizes of the parent dirs */
-void calc_hlink_check(struct dir *d) {
-  struct dir *t, *pt, *par;
+void calc_hlink_check(compll_t d) {
+  compll_t t, pt, par;
   int i;
 
-  d->flags |= FF_HLNKC;
+  DW(d)->flags |= FF_HLNKC;
   i = calc_hlink_add(d);
 
   /* found in the list? update hlnk */
   if(i >= 0) {
-    t = d->hlnk = links[i];
-    if(t->hlnk != NULL)
-      for(t=t->hlnk; t->hlnk!=d->hlnk; t=t->hlnk)
+    t = DW(d)->hlnk = links[i];
+    if(DR(t)->hlnk)
+      for(t=DR(t)->hlnk; DR(t)->hlnk!=DR(d)->hlnk; t=DR(t)->hlnk)
         ;
-    t->hlnk = d;
+    DW(t)->hlnk = d;
   }
 
   /* now update the sizes of the parent directories,
    * This works by only counting this file in the parent directories where this
    * file hasn't been counted yet, which can be determined from the hlnk list.
    * XXX: This may not be the most efficient algorithm to do this */
-  for(i=1,par=d->parent; i&&par; par=par->parent) {
-    if(d->hlnk)
-      for(t=d->hlnk; i&&t!=d; t=t->hlnk)
-        for(pt=t->parent; i&&pt; pt=pt->parent)
+  for(i=1,par=DR(d)->parent; i&&par; par=DR(par)->parent) {
+    if(DR(d)->hlnk)
+      for(t=DR(d)->hlnk; i&&t!=d; t=DR(t)->hlnk)
+        for(pt=DR(t)->parent; i&&pt; pt=DR(pt)->parent)
           if(pt==par)
             i=0;
     if(i) {
-      par->size += d->size;
-      par->asize += d->asize;
+      DW(par)->size += DR(d)->size;
+      DW(par)->asize += DR(d)->asize;
     }
   }
 }
 
 
-int calc_item(struct dir *par, char *name) {
-  struct dir *t, *d;
+int calc_item(compll_t par, char *name) {
+  compll_t t, d;
   struct stat fs;
 
   if(name[0] == '.' && (name[1] == '\0' || (name[1] == '.' && name[2] == '\0')))
     return 0;
 
   /* allocate dir and fix references */
-  d = calloc(SDIRSIZE+strlen(name), 1);
-  d->parent = par;
-  d->next = par->sub;
-  par->sub = d;
-  if(d->next)
-    d->next->prev = d;
-  strcpy(d->name, name);
+  d = compll_alloc(SDIRSIZE+strlen(name));
+  DW(d)->parent = par;
+  DW(d)->next = DR(par)->sub;
+  DW(par)->sub = d;
+  if(DR(d)->next)
+    DW(DR(d)->next)->prev = d;
+  strcpy(DW(d)->name, name);
 
 #ifdef __CYGWIN__
   /* /proc/registry names may contain slashes */
-  if(strchr(d->name, '/') || strchr(d->name,  '\\')) {
-    d->flags |= FF_ERR;
+  if(strchr(name, '/') || strchr(name,  '\\')) {
+    DW(d)->flags |= FF_ERR;
     return 0;
   }
 #endif
 
   /* lstat */
   if(lstat(name, &fs)) {
-    d->flags |= FF_ERR;
+    DW(d)->flags |= FF_ERR;
     return 0;
   }
 
   /* check for excludes and same filesystem */
   if(exclude_match(curpath))
-    d->flags |= FF_EXL;
+    DW(d)->flags |= FF_EXL;
 
   if(calc_smfs && curdev != fs.st_dev)
-    d->flags |= FF_OTHFS;
+    DW(d)->flags |= FF_OTHFS;
 
   /* determine type of this item */
   if(S_ISREG(fs.st_mode))
-    d->flags |= FF_FILE;
+    DW(d)->flags |= FF_FILE;
   else if(S_ISDIR(fs.st_mode))
-    d->flags |= FF_DIR;
+    DW(d)->flags |= FF_DIR;
 
   /* update the items count of the parent dirs */
-  if(!(d->flags & FF_EXL))
-    for(t=d->parent; t!=NULL; t=t->parent)
-      t->items++;
+  if(!(DR(d)->flags & FF_EXL))
+    for(t=DR(d)->parent; t; t=DR(t)->parent)
+      DW(t)->items++;
 
   /* count the size */
-  if(!(d->flags & FF_EXL || d->flags & FF_OTHFS)) {
-    d->size = fs.st_blocks * S_BLKSIZE;
-    d->asize = fs.st_size;
+  if(!(DR(d)->flags & FF_EXL || DR(d)->flags & FF_OTHFS)) {
+    DW(d)->size = fs.st_blocks * S_BLKSIZE;
+    DW(d)->asize = fs.st_size;
     /* only update the sizes of the parents if it's not a hard link */
     if(S_ISDIR(fs.st_mode) || fs.st_nlink <= 1)
-      for(t=d->parent; t!=NULL; t=t->parent) {
-        t->size += d->size;
-        t->asize += d->asize;
+      for(t=DR(d)->parent; t; t=DR(t)->parent) {
+        DW(t)->size += DR(d)->size;
+        DW(t)->asize += DR(d)->asize;
       }
   }
 
   /* Hard link checking (also takes care of updating the sizes of the parents) */
-  d->ino = fs.st_ino;
-  d->dev = fs.st_dev;
+  DW(d)->ino = fs.st_ino;
+  DW(d)->dev = fs.st_dev;
   if(!S_ISDIR(fs.st_mode) && fs.st_nlink > 1)
     calc_hlink_check(d);
 
@@ -232,8 +232,8 @@ int calc_item(struct dir *par, char *name) {
 
 /* recursively walk through the directory tree,
    assumes path resides in the cwd */
-int calc_dir(struct dir *dest, char *name) {
-  struct dir *t;
+int calc_dir(compll_t dest, const char *name) {
+  compll_t t;
   DIR *dir;
   struct dirent *dr;
   int ch;
@@ -251,10 +251,10 @@ int calc_dir(struct dir *dest, char *name) {
       lasterr = realloc(lasterr, lasterrl);
     }
     strcpy(lasterr, curpath);
-    dest->flags |= FF_ERR;
+    DW(dest)->flags |= FF_ERR;
     t = dest;
-    while((t = t->parent) != NULL)
-      t->flags |= FF_SERR;
+    while((t = DR(t)->parent))
+      DW(t)->flags |= FF_SERR;
     calc_leavepath();
     if(dir != NULL)
       closedir(dir);
@@ -265,7 +265,7 @@ int calc_dir(struct dir *dest, char *name) {
   while((dr = readdir(dir)) != NULL) {
     calc_enterpath(dr->d_name);
     if(calc_item(dest, dr->d_name))
-      dest->flags |= FF_ERR;
+      DW(dest)->flags |= FF_ERR;
     if(input_handle(1)) {
       calc_leavepath();
       closedir(dir);
@@ -276,26 +276,25 @@ int calc_dir(struct dir *dest, char *name) {
   }
 
   if(errno) {
-    if(dest->flags & FF_SERR)
-      dest->flags -= FF_SERR;
-    dest->flags |= FF_ERR;
+    DW(dest)->flags &= ~FF_SERR;
+    DW(dest)->flags |= FF_ERR;
   }
   closedir(dir);
 
   /* error occured while reading this dir, update parent dirs */
-  for(t=dest->sub; t!=NULL; t=t->next)
-    if(t->flags & FF_ERR || t->flags & FF_SERR)
-      dest->flags |= FF_SERR;
-  if(dest->flags & FF_ERR || dest->flags & FF_SERR) {
-    for(t = dest; (t = t->parent) != NULL; )
-      t->flags |= FF_SERR;
+  for(t=DR(dest)->sub; t; t=DR(t)->next)
+    if(DR(t)->flags & FF_ERR || DR(t)->flags & FF_SERR)
+      DW(dest)->flags |= FF_SERR;
+  if(DR(dest)->flags & FF_ERR || DR(dest)->flags & FF_SERR) {
+    for(t = dest; (t = DR(t)->parent); )
+      DW(t)->flags |= FF_SERR;
   }
 
   /* calculate subdirectories */
   ch = 0;
-  for(t=dest->sub; t!=NULL; t=t->next)
-    if(t->flags & FF_DIR && !(t->flags & FF_EXL || t->flags & FF_OTHFS))
-      if(calc_dir(t, t->name)) {
+  for(t=DR(dest)->sub; t; t=DR(t)->next)
+    if(DR(t)->flags & FF_DIR && !(DR(t)->flags & FF_EXL || DR(t)->flags & FF_OTHFS))
+      if(calc_dir(t, DR(t)->name)) {
         calc_leavepath();
         return 1;
       }
@@ -321,7 +320,7 @@ void calc_draw_progress() {
   nccreate(10, 60, !orig ? "Calculating..." : "Recalculating...");
 
   ncprint(2, 2, "Total items: %-8d size: %s",
-    root->items, formatsize(root->size));
+    DR(root)->items, formatsize(DR(root)->size));
   ncprint(3, 2, "Current dir: %s", cropstr(curpath, 43));
   ncaddstr(8, 43, "Press q to quit");
 
@@ -385,13 +384,13 @@ int calc_key(int ch) {
 int calc_process() {
   char *path, *name;
   struct stat fs;
-  struct dir *t;
+  compll_t t;
   int n;
 
   /* create initial links array */
   linksl = linkst = 0;
   if(orig) {
-    for(t=orig; t->parent!=NULL; t=t->parent)
+    for(t=orig; DR(t)->parent; t=DR(t)->parent)
       ;
     calc_hlink_init(t);
   }
@@ -433,21 +432,21 @@ int calc_process() {
   }
 
   /* initialize parent dir */
-  n = orig ? strlen(orig->name) : strlen(path)+strlen(name)+1;
-  t = (struct dir *) calloc(1, SDIRSIZE+n);
-  t->size = fs.st_blocks * S_BLKSIZE;
-  t->asize = fs.st_size;
-  t->flags |= FF_DIR;
+  n = orig ? strlen(DR(orig)->name) : strlen(path)+strlen(name)+1;
+  t = compll_alloc(SDIRSIZE+n);
+  DW(t)->size = fs.st_blocks * S_BLKSIZE;
+  DW(t)->asize = fs.st_size;
+  DW(t)->flags |= FF_DIR;
   if(orig) {
-    strcpy(t->name, orig->name);
-    t->parent = orig->parent;
+    strcpy(DW(t)->name, DR(orig)->name);
+    DW(t)->parent = DR(orig)->parent;
   } else {
-    t->name[0] = 0;
+    DW(t)->name[0] = 0;
     if(strcmp(path, "/"))
-      strcpy(t->name, path);
+      strcpy(DW(t)->name, path);
     if(strcmp(name, ".")) {
-      strcat(t->name, "/");
-      strcat(t->name, name);
+      strcat(DW(t)->name, "/");
+      strcat(DW(t)->name, name);
     }
   }
   root = t;
@@ -455,10 +454,10 @@ int calc_process() {
 
   /* make sure to count this directory entry in its parents at this point */
   if(orig)
-    for(t=root->parent; t!=NULL; t=t->parent) {
-      t->size += root->size;
-      t->asize += root->asize;
-      t->items += 1;
+    for(t=DR(root)->parent; t; t=DR(t)->parent) {
+      DW(t)->size += DR(root)->size;
+      DW(t)->asize += DR(root)->asize;
+      DW(t)->items += 1;
     }
 
   /* update curpath */
@@ -486,7 +485,7 @@ int calc_process() {
 
   /* success */
   if(!n && !failed) {
-    if(root->sub == NULL) {
+    if(!DR(root)->sub) {
       freedir(root);
       failed = 1;
       strcpy(errmsg, "Directory empty.");
@@ -495,18 +494,18 @@ int calc_process() {
 
     /* update references and free original item */
     if(orig) {
-      root->next = orig->next;
-      root->prev = orig->prev;
-      if(root->parent && root->parent->sub == orig)
-        root->parent->sub = root;
-      if(root->prev)
-        root->prev->next = root;
-      if(root->next)
-        root->next->prev = root;
-      orig->next = orig->prev = NULL;
+      DW(root)->next = DR(orig)->next;
+      DW(root)->prev = DR(orig)->prev;
+      if(DR(root)->parent && DR(DR(root)->parent)->sub == orig)
+        DW(DR(root)->parent)->sub = root;
+      if(DR(root)->prev)
+        DW(DR(root)->prev)->next = root;
+      if(DR(root)->next)
+        DW(DR(root)->next)->prev = root;
+      DW(orig)->next = DW(orig)->prev = (compll_t)0;
       freedir(orig);
     }
-    browse_init(root->sub);
+    browse_init(DR(root)->sub);
     dirlist_top(-3);
     return 0;
   }
@@ -516,7 +515,7 @@ int calc_process() {
 calc_fail:
   while(failed && !input_handle(0))
     ;
-  if(orig == NULL)
+  if(!orig)
     return 1;
   else {
     browse_init(orig);
@@ -525,7 +524,7 @@ calc_fail:
 }
 
 
-void calc_init(char *dir, struct dir *org) {
+void calc_init(char *dir, compll_t org) {
   failed = anpos = 0;
   orig = org;
   if(curpathl == 0) {
diff --git a/src/calc.h b/src/calc.h
index 2d98ca8e8035a727370f39f29a42cbb1e4f0f594..cbafb6c67db4436facfa2d8233c9713181b9faa8 100644
--- a/src/calc.h
+++ b/src/calc.h
@@ -33,7 +33,7 @@ extern char calc_smfs;  /* stay on the same filesystem */
 int  calc_process(void);
 int  calc_key(int);
 void calc_draw(void);
-void calc_init(char *, struct dir *);
+void calc_init(char *, compll_t);
 
 
 #endif
diff --git a/src/delete.c b/src/delete.c
index fdc4467978fd4349135292f1c9d416cf7db7f84e..810b183064675d9ba25f45f19baebee1d5d85c13 100644
--- a/src/delete.c
+++ b/src/delete.c
@@ -36,7 +36,7 @@
 #define DS_FAILED   2
 
 
-struct dir *root, *nextsel, *curdir;
+compll_t root, nextsel, curdir;
 char noconfirm = 0,
      ignoreerr = 0,
      state, seloption;
@@ -47,8 +47,8 @@ void delete_draw_confirm() {
   nccreate(6, 60, "Confirm delete");
 
   ncprint(1, 2, "Are you sure you want to delete \"%s\"%c",
-    cropstr(root->name, 21), root->flags & FF_DIR ? ' ' : '?');
-  if(root->flags & FF_DIR)
+    cropstr(DR(root)->name, 21), DR(root)->flags & FF_DIR ? ' ' : '?');
+  if(DR(root)->flags & FF_DIR)
     ncprint(2, 18, "and all of its contents?");
 
   if(seloption == 0)
@@ -165,8 +165,8 @@ int delete_key(int ch) {
 }
 
 
-int delete_dir(struct dir *dr) {
-  struct dir *nxt, *cur;
+int delete_dir(compll_t dr) {
+  compll_t nxt, cur;
   int r;
 
   /* check for input or screen resizes */
@@ -175,23 +175,23 @@ int delete_dir(struct dir *dr) {
     return 1;
 
   /* do the actual deleting */
-  if(dr->flags & FF_DIR) {
-    if((r = chdir(dr->name)) < 0)
+  if(DR(dr)->flags & FF_DIR) {
+    if((r = chdir(DR(dr)->name)) < 0)
       goto delete_nxt;
-    if(dr->sub != NULL) {
-      nxt = dr->sub;
-      while(nxt != NULL) {
+    if(DR(dr)->sub) {
+      nxt = DR(dr)->sub;
+      while(nxt) {
         cur = nxt;
-        nxt = cur->next;
+        nxt = DR(cur)->next;
         if(delete_dir(cur))
           return 1;
       }
     }
     if((r = chdir("..")) < 0)
       goto delete_nxt;
-    r = dr->sub == NULL ? rmdir(dr->name) : 0;
+    r = DR(dr)->sub ? 0 : rmdir(DR(dr)->name);
   } else
-    r = unlink(dr->name);
+    r = unlink(DR(dr)->name);
 
 delete_nxt:
   /* error occured, ask user what to do */
@@ -202,7 +202,7 @@ delete_nxt:
     while(state == DS_FAILED)
       if(input_handle(0))
         return 1;
-  } else if(!(dr->flags & FF_DIR && dr->sub != NULL)) {
+  } else if(!(DR(dr)->flags & FF_DIR && DR(dr)->sub)) {
     freedir(dr);
     return 0;
   }
@@ -220,7 +220,7 @@ void delete_process() {
     }
 
   /* chdir */
-  if(path_chdir(getpath(root->parent)) < 0) {
+  if(path_chdir(getpath(DR(root)->parent)) < 0) {
     state = DS_FAILED;
     lasterrno = errno;
     while(state == DS_FAILED)
@@ -234,14 +234,14 @@ void delete_process() {
   if(delete_dir(root))
     browse_init(root);
   else {
-    nextsel->flags |= FF_BSEL;
+    DW(nextsel)->flags |= FF_BSEL;
     browse_init(nextsel);
     dirlist_top(-4);
   }
 }
 
 
-void delete_init(struct dir *dr, struct dir *s) {
+void delete_init(compll_t dr, compll_t s) {
   state = DS_CONFIRM;
   root = curdir = dr;
   pstate = ST_DEL;
diff --git a/src/delete.h b/src/delete.h
index f604eaa0efb0925205805ed55c8d3f19be410eca..29b66196a94e72af4f896780af82e3c84b614f27 100644
--- a/src/delete.h
+++ b/src/delete.h
@@ -31,7 +31,7 @@
 void delete_process(void);
 int  delete_key(int);
 void delete_draw(void);
-void delete_init(struct dir *, struct dir *);
+void delete_init(compll_t, compll_t);
 
 
 #endif
diff --git a/src/dirlist.c b/src/dirlist.c
index 6fbe07f02e6a9dd3a5784b6b33b97558de39a908..f29dc215158d3f822c7c69a7cf16005e784a9fb1 100644
--- a/src/dirlist.c
+++ b/src/dirlist.c
@@ -25,39 +25,40 @@
 
 #include "global.h"
 
+#include <stdlib.h>
 #include <string.h>
 
 
 /* public variables */
-struct dir *dirlist_parent = NULL;
-off_t  dirlist_maxs        = 0,
-       dirlist_maxa        = 0;
+compll_t dirlist_parent    = (compll_t)0;
+off_t    dirlist_maxs      = 0,
+         dirlist_maxa      = 0;
 
-int    dirlist_sort_desc   = 1,
-       dirlist_sort_col    = DL_COL_SIZE,
-       dirlist_sort_df     = 0,
-       dirlist_hidden      = 0;
+int      dirlist_sort_desc = 1,
+         dirlist_sort_col  = DL_COL_SIZE,
+         dirlist_sort_df   = 0,
+         dirlist_hidden    = 0;
 
 /* private state vars */
-struct dir dirlist_parent_alloc;
-struct dir *head, *head_real, *selected, *top = NULL;
+compll_t dirlist_parent_alloc = (compll_t)0;
+compll_t head, head_real, selected, top = (compll_t)0;
 
 
 
-#define ISHIDDEN(d) (dirlist_hidden && (d) != dirlist_parent && (\
-    (d)->flags & FF_EXL || (d)->name[0] == '.' || (d)->name[strlen((d)->name)-1] == '~'\
+#define ISHIDDEN(d) (dirlist_hidden && d != dirlist_parent && (\
+    DR(d)->flags & FF_EXL || DR(d)->name[0] == '.' || DR(d)->name[strlen(DR(d)->name)-1] == '~'\
   ))
 
 
 
-int dirlist_cmp(struct dir *x, struct dir *y) {
+int dirlist_cmp(compll_t x, compll_t y) {
   int r;
 
   /* dirs are always before files when that option is set */
   if(dirlist_sort_df) {
-    if(y->flags & FF_DIR && !(x->flags & FF_DIR))
+    if(DR(y)->flags & FF_DIR && !(DR(x)->flags & FF_DIR))
       return 1;
-    else if(!(y->flags & FF_DIR) && x->flags & FF_DIR)
+    else if(!(DR(y)->flags & FF_DIR) && DR(x)->flags & FF_DIR)
       return -1;
   }
 
@@ -69,9 +70,9 @@ int dirlist_cmp(struct dir *x, struct dir *y) {
    *
    * Note that the method used below is supposed to be fast, not readable :-)
    */
-#define CMP_NAME  strcmp(x->name, y->name)
-#define CMP_SIZE  (x->size  > y->size  ? 1 : (x->size  == y->size  ? 0 : -1))
-#define CMP_ASIZE (x->asize > y->asize ? 1 : (x->asize == y->asize ? 0 : -1))
+#define CMP_NAME  strcmp(DR(x)->name, DR(y)->name)
+#define CMP_SIZE  (DR(x)->size  > DR(y)->size  ? 1 : (DR(x)->size  == DR(y)->size  ? 0 : -1))
+#define CMP_ASIZE (DR(x)->asize > DR(y)->asize ? 1 : (DR(x)->asize == DR(y)->asize ? 0 : -1))
 
   /* try 1 */
   r = dirlist_sort_col == DL_COL_NAME ? CMP_NAME : dirlist_sort_col == DL_COL_SIZE ? CMP_SIZE : CMP_ASIZE;
@@ -90,15 +91,15 @@ int dirlist_cmp(struct dir *x, struct dir *y) {
 }
 
 
-struct dir *dirlist_sort(struct dir *list) {
-  struct dir *p, *q, *e, *tail;
+compll_t dirlist_sort(compll_t list) {
+  compll_t p, q, e, tail;
   int insize, nmerges, psize, qsize, i;
 
   insize = 1;
   while(1) {
     p = list;
-    list = NULL;
-    tail = NULL;
+    list = (compll_t)0;
+    tail = (compll_t)0;
     nmerges = 0;
     while(p) {
       nmerges++;
@@ -106,31 +107,31 @@ struct dir *dirlist_sort(struct dir *list) {
       psize = 0;
       for(i=0; i<insize; i++) {
         psize++;
-        q = q->next;
+        q = DR(q)->next;
         if(!q) break;
       }
       qsize = insize;
       while(psize > 0 || (qsize > 0 && q)) {
         if(psize == 0) {
-          e = q; q = q->next; qsize--;
+          e = q; q = DR(q)->next; qsize--;
         } else if(qsize == 0 || !q) {
-          e = p; p = p->next; psize--;
+          e = p; p = DR(p)->next; psize--;
         } else if(dirlist_cmp(p,q) <= 0) {
-          e = p; p = p->next; psize--;
+          e = p; p = DR(p)->next; psize--;
         } else {
-          e = q; q = q->next; qsize--;
+          e = q; q = DR(q)->next; qsize--;
         }
-        if(tail) tail->next = e;
+        if(tail) DW(tail)->next = e;
         else     list = e;
-        e->prev = tail;
+        DW(e)->prev = tail;
         tail = e;
       }
       p = q;
     }
-    tail->next = NULL;
+    DW(tail)->next = (compll_t)0;
     if(nmerges <= 1) {
-      if(list->parent)
-        list->parent->sub = list;
+      if(DR(list)->parent)
+        DW(DR(list)->parent)->sub = list;
       return list;
     }
     insize *= 2;
@@ -143,109 +144,115 @@ struct dir *dirlist_sort(struct dir *list) {
  * - updates the dirlist_(maxs|maxa) values
  * - makes sure that the FF_BSEL bits are correct */
 void dirlist_fixup() {
-  struct dir *t;
+  compll_t t;
 
   /* we're going to determine the selected items from the list itself, so reset this one */
-  selected = NULL;
+  selected = (compll_t)0;
 
-  for(t=head; t; t=t->next) {
+  for(t=head; t; t=DR(t)->next) {
     /* not visible? not selected! */
-    if(ISHIDDEN(t))
-      t->flags &= ~FF_BSEL;
-    else {
+    if(ISHIDDEN(t)) {
+      if(DR(t)->flags & FF_BSEL)
+        DW(t)->flags &= ~FF_BSEL;
+    } else {
       /* visible and selected? make sure only one item is selected */
-      if(t->flags & FF_BSEL) {
+      if(DR(t)->flags & FF_BSEL) {
         if(!selected)
           selected = t;
         else
-          t->flags &= ~FF_BSEL;
+          DW(t)->flags &= ~FF_BSEL;
       }
     }
 
     /* update dirlist_(maxs|maxa) */
-    if(t->size > dirlist_maxs)
-      dirlist_maxs = t->size;
-    if(t->asize > dirlist_maxa)
-      dirlist_maxa = t->asize;
+    if(DR(t)->size > dirlist_maxs)
+      dirlist_maxs = DR(t)->size;
+    if(DR(t)->asize > dirlist_maxa)
+      dirlist_maxa = DR(t)->asize;
   }
 
   /* no selected items found after one pass? select the first visible item */
   if(!selected)
-    if((selected = dirlist_next(NULL)))
-      selected->flags |= FF_BSEL;
+    if((selected = dirlist_next((compll_t)0)))
+      DW(selected)->flags |= FF_BSEL;
 }
 
 
-void dirlist_open(struct dir *d) {
+void dirlist_open(compll_t d) {
   /* set the head of the list */
-  head_real = head = d == NULL ? NULL : d->parent == NULL ? d->sub : d->parent->sub;
+  head_real = head = !d ? d : !DR(d)->parent ? DR(d)->sub : DR(DR(d)->parent)->sub;
 
   /* reset internal status */
   dirlist_maxs = dirlist_maxa = 0;
 
   /* stop if this is not a directory list we can work with */
-  if(head == NULL) {
-    dirlist_parent = NULL;
+  if(!head) {
+    dirlist_parent = (compll_t)0;
     return;
   }
 
   /* sort the dir listing */
   head_real = head = dirlist_sort(head);
 
+  /* allocate reference to parent dir if we don't have one yet */
+  if(!dirlist_parent_alloc) {
+    dirlist_parent_alloc = compll_alloc(SDIRSIZE+2);
+    strcpy(DW(dirlist_parent_alloc)->name, "..");
+  }
+
   /* set the reference to the parent dir */
-  dirlist_parent_alloc.flags &= ~FF_BSEL;
-  if(head->parent->parent) {
-    dirlist_parent = &dirlist_parent_alloc;
-    strcpy(dirlist_parent->name, "..");
-    dirlist_parent->next = head;
-    dirlist_parent->parent = head->parent;
-    dirlist_parent->sub = head->parent;
+  DW(dirlist_parent_alloc)->flags &= ~FF_BSEL;
+  if(DR(DR(head)->parent)->parent) {
+    dirlist_parent = dirlist_parent_alloc;
+    DW(dirlist_parent)->next = head;
+    DW(dirlist_parent)->parent = DR(head)->parent;
+    DW(dirlist_parent)->sub = DR(head)->parent;
     head = dirlist_parent;
   } else
-    dirlist_parent = NULL;
+    dirlist_parent = (compll_t)0;
 
   dirlist_fixup();
 }
 
 
-struct dir *dirlist_next(struct dir *d) {
+compll_t dirlist_next(compll_t d) {
   if(!head)
-    return NULL;
+    return (compll_t)0;
   if(!d) {
     if(!ISHIDDEN(head))
       return head;
     else
       d = head;
   }
-  while((d = d->next)) {
+  while((d = DR(d)->next)) {
     if(!ISHIDDEN(d))
       return d;
   }
-  return NULL;
+  return (compll_t)0;
 }
 
 
-struct dir *dirlist_prev(struct dir *d) {
+compll_t dirlist_prev(compll_t d) {
   if(!head || !d)
-    return NULL;
-  while((d = d->prev)) {
+    return (compll_t)0;
+  while((d = DR(d)->prev)) {
     if(!ISHIDDEN(d))
       return d;
   }
   if(dirlist_parent)
     return dirlist_parent;
-  return NULL;
+  return (compll_t)0;
 }
 
 
-struct dir *dirlist_get(int i) {
-  struct dir *t = selected, *d;
+compll_t dirlist_get(int i) {
+  compll_t t = selected, d;
 
   if(!head)
-    return NULL;
+    return (compll_t)0;
 
   if(ISHIDDEN(selected)) {
-    selected = dirlist_next(NULL);
+    selected = dirlist_next((compll_t)0);
     return selected;
   }
 
@@ -275,13 +282,13 @@ struct dir *dirlist_get(int i) {
 }
 
 
-void dirlist_select(struct dir *d) {
-  if(!d || !head || ISHIDDEN(d) || d->parent != head->parent)
+void dirlist_select(compll_t d) {
+  if(!d || !head || ISHIDDEN(d) || DR(d)->parent != DR(head)->parent)
     return;
 
-  selected->flags &= ~FF_BSEL;
+  DW(selected)->flags &= ~FF_BSEL;
   selected = d;
-  selected->flags |= FF_BSEL;
+  DW(selected)->flags |= FF_BSEL;
 }
 
 
@@ -304,12 +311,12 @@ void dirlist_select(struct dir *d) {
  * Regardless of the hint, the returned top will always be chosen such that the
  * selected item is visible.
  */
-struct dir *dirlist_top(int hint) {
-  struct dir *t;
+compll_t dirlist_top(int hint) {
+  compll_t t;
   int i = winrows-3, visible = 0;
 
   if(hint == -2 || hint == -3)
-    top = NULL;
+    top = (compll_t)0;
 
   /* check whether the current selected item is within the visible window */
   if(top) {
@@ -358,7 +365,7 @@ void dirlist_set_sort(int col, int desc, int df) {
   /* sort the list (excluding the parent, which is always on top) */
   head_real = dirlist_sort(head_real);
   if(dirlist_parent)
-    dirlist_parent->next = head_real;
+    DW(dirlist_parent)->next = head_real;
   else
     head = head_real;
   dirlist_top(-3);
diff --git a/src/dirlist.h b/src/dirlist.h
index e8174d5f46763b029bb3f3e1efdd11f70fc3c277..6271b29dd62f295916cf9ecf9e996c92aeb8571d 100644
--- a/src/dirlist.h
+++ b/src/dirlist.h
@@ -38,22 +38,22 @@
 #define DL_COL_ASIZE   2
 
 
-void dirlist_open(struct dir *);
+void dirlist_open(compll_t);
 
 /* Get the next non-hidden item,
  * NULL = get first non-hidden item */
-struct dir *dirlist_next(struct dir *);
+compll_t dirlist_next(compll_t);
 
 /* Get the struct dir item relative to the selected item, or the item nearest to the requested item
  * i = 0 get selected item
  * hidden items aren't considered */
-struct dir *dirlist_get(int i);
+compll_t dirlist_get(int i);
 
 /* Get/set the first visible item in the list on the screen */
-struct dir *dirlist_top(int hint);
+compll_t dirlist_top(int hint);
 
 /* Set selected dir (must be in the currently opened directory, obviously) */
-void dirlist_select(struct dir *);
+void dirlist_select(compll_t);
 
 /* Change sort column (arguments should have a NO_CHANGE option) */
 void dirlist_set_sort(int column, int desc, int df);
@@ -65,7 +65,7 @@ void dirlist_set_hidden(int hidden);
 /* DO NOT WRITE TO ANY OF THE BELOW VARIABLES FROM OUTSIDE OF dirlist.c! */
 
 /* The 'reference to parent dir' */
-extern struct dir *dirlist_parent;
+extern compll_t dirlist_parent;
 
 /* current sorting configuration (set with dirlist_set_sort()) */
 extern int dirlist_sort_desc, dirlist_sort_col, dirlist_sort_df;
diff --git a/src/global.h b/src/global.h
index ceb1a2b59ba8eced5568a2ac6794dbdf9b06a42c..f4eda23977b0b085a25e6b07399f8ae35d3ed7ce 100644
--- a/src/global.h
+++ b/src/global.h
@@ -30,6 +30,7 @@
 #include <stdio.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include "compll.h"
 
 /* File Flags (struct dir -> flags) */
 #define FF_DIR    0x01
@@ -48,17 +49,15 @@
 #define ST_HELP   3
 
 
-/* structure representing a file or directory
- * XXX: probably a good idea to get rid of the custom _t types and use
- *      fixed-size integers instead, which are much more predictable */
+/* structure representing a file or directory */
 struct dir {
-  struct dir *parent, *next, *prev, *sub, *hlnk;
+  compll_t parent, next, prev, sub, hlnk;
   off_t size, asize;
   ino_t ino;
   unsigned long items;
   dev_t dev;
   unsigned char flags;
-  char name[3]; /* must be large enough to hold ".." */
+  char name[3];
 }; 
 /* sizeof(total dir) = SDIRSIZE + strlen(name) = sizeof(struct dir) - 3 + strlen(name) + 1 */
 #define SDIRSIZE (sizeof(struct dir)-2)
diff --git a/src/main.c b/src/main.c
index 35aaae929e6bba6e0f105ce66a03b69b457e8e59..eb208889bf81911a6206020b74c2517abe31ae86 100644
--- a/src/main.c
+++ b/src/main.c
@@ -33,6 +33,11 @@
 #include <sys/time.h>
 #include <locale.h>
 
+#ifndef COMPLL_NOLIB
+#include <zlib.h>
+#endif
+
+
 int pstate;
 
 int min_rows = 17,
@@ -143,6 +148,23 @@ char *argv_parse(int argc, char **argv) {
 }
 
 
+/* compression and decompression functions for compll */
+#ifndef COMPLL_NOLIB
+
+unsigned int block_compress(const unsigned char *src, unsigned int srclen, unsigned char *dst, unsigned int dstlen) {
+  uLongf len = dstlen;
+  compress2(dst, &len, src, srclen, 6);
+  return len;
+}
+
+void block_decompress(const unsigned char *src, unsigned int srclen, unsigned char *dst, unsigned int dstlen) {
+  uLongf len = dstlen;
+  uncompress(dst, &len, src, srclen);
+}
+
+#endif
+
+
 /* main program */
 int main(int argc, char **argv) {
   char *dir;
@@ -152,7 +174,12 @@ int main(int argc, char **argv) {
   if((dir = argv_parse(argc, argv)) == NULL)
     dir = ".";
 
-  calc_init(dir, NULL);
+#ifndef COMPLL_NOLIB
+  /* we probably want to make these options configurable */
+  compll_init(32*1024, sizeof(off_t), 50, block_compress, block_decompress);
+#endif
+
+  calc_init(dir, (compll_t)0);
 
   initscr();
   cbreak();
diff --git a/src/util.c b/src/util.c
index bea2483c4fbf0f195a38149d55b35ba8f7cc6b3b..6899c96619eac1b70eaad33e717426b2e7be5441 100644
--- a/src/util.c
+++ b/src/util.c
@@ -38,9 +38,6 @@ char fullsizedat[20]; /* max: 999.999.999.999.999 */
 char *getpathdat;
 int getpathdatl = 0;
 
-struct dir **links;
-int linksl = 0, linkst = 0;
-
 
 char *cropstr(const char *from, int s) {
   int i, j, o = strlen(from);
@@ -170,11 +167,11 @@ void ncprint(int r, int c, char *fmt, ...) {
 
 
 /* removes item from the hlnk circular linked list and size counts of the parents */
-void freedir_hlnk(struct dir *d) {
-  struct dir *t, *par, *pt;
+void freedir_hlnk(compll_t d) {
+  compll_t t, par, pt;
   int i;
 
-  if(!(d->flags & FF_HLNKC))
+  if(!(DR(d)->flags & FF_HLNKC))
     return;
 
   /* remove size from parents.
@@ -183,81 +180,80 @@ void freedir_hlnk(struct dir *d) {
    * exists within the parent it shouldn't get removed from the count.
    * XXX: Same note as for calc.c / calc_hlnk_check():
    *      this is probably not the most efficient algorithm */
-  for(i=1,par=d->parent; i&&par; par=par->parent) {
-    if(d->hlnk)
-      for(t=d->hlnk; i&&t!=d; t=t->hlnk)
-        for(pt=t->parent; i&&pt; pt=pt->parent)
+  for(i=1,par=DR(d)->parent; i&&par; par=DR(par)->parent) {
+    if(DR(d)->hlnk)
+      for(t=DR(d)->hlnk; i&&t!=d; t=DR(t)->hlnk)
+        for(pt=DR(t)->parent; i&&pt; pt=DR(pt)->parent)
           if(pt==par)
             i=0;
     if(i) {
-      par->size -= d->size;
-      par->asize -= d->asize;
+      DW(par)->size -= DR(d)->size;
+      DW(par)->asize -= DR(d)->asize;
     }
   }
 
   /* remove from hlnk */
-  if(d->hlnk) {
-    for(t=d->hlnk; t->hlnk!=d; t=t->hlnk)
+  if(DR(d)->hlnk) {
+    for(t=DR(d)->hlnk; DR(t)->hlnk!=d; t=DR(t)->hlnk)
       ;
-    t->hlnk = d->hlnk;
+    DW(t)->hlnk = DR(d)->hlnk;
   }
 }
 
 
-void freedir_rec(struct dir *dr) {
-  struct dir *tmp, *tmp2;
+void freedir_rec(compll_t dr) {
+  compll_t tmp, tmp2;
   tmp2 = dr;
-  while((tmp = tmp2) != NULL) {
+  while((tmp = tmp2)) {
     freedir_hlnk(tmp);
     /* remove item */
-    if(tmp->sub) freedir_rec(tmp->sub);
-    tmp2 = tmp->next;
-    free(tmp);
+    if(DR(tmp)->sub) freedir_rec(DR(tmp)->sub);
+    tmp2 = DR(tmp)->next;
+    compll_free(tmp);
   }
 }
 
-
-void freedir(struct dir *dr) {
-  struct dir *tmp;
+void freedir(compll_t dr) {
+  compll_t tmp;
 
   /* free dr->sub recursively */
-  if(dr->sub)
-    freedir_rec(dr->sub);
+  if(DR(dr)->sub)
+    freedir_rec(DR(dr)->sub);
  
   /* update references */
-  if(dr->parent && dr->parent->sub == dr)
-    dr->parent->sub = dr->next;
-  if(dr->prev)
-    dr->prev->next = dr->next;
-  if(dr->next)
-    dr->next->prev = dr->prev;
+  if(DR(dr)->parent && DR(DR(dr)->parent)->sub == dr)
+    DW(DR(dr)->parent)->sub = DR(dr)->next;
+  if(DR(dr)->prev)
+    DW(DR(dr)->prev)->next = DR(dr)->next;
+  if(DR(dr)->next)
+    DW(DR(dr)->next)->prev = DR(dr)->prev;
 
   freedir_hlnk(dr);
 
   /* update sizes of parent directories if this isn't a hard link.
    * If this is a hard link, freedir_hlnk() would have done so already */
-  for(tmp=dr->parent; tmp; tmp=tmp->parent) {
-    if(!(dr->flags & FF_HLNKC)) {
-      tmp->size -= dr->size;
-      tmp->asize -= dr->asize;
+  for(tmp=DR(dr)->parent; tmp; tmp=DR(tmp)->parent) {
+    if(!(DR(dr)->flags & FF_HLNKC)) {
+      DW(tmp)->size -= DR(dr)->size;
+      DW(tmp)->asize -= DR(dr)->asize;
     }
-    tmp->items -= dr->items+1;
+    DW(tmp)->items -= DR(dr)->items+1;
   }
 
-  free(dr);
+  compll_free(dr);
 }
 
 
-char *getpath(struct dir *cur) {
-  struct dir *d, **list;
+char *getpath(compll_t cur) {
+  compll_t d, *list;
   int c, i;
 
-  if(!cur->name[0])
+  if(!DR(cur)->name[0])
     return "/";
 
   c = i = 1;
-  for(d=cur; d!=NULL; d=d->parent) {
-    i += strlen(d->name)+1;
+  for(d=cur; d; d=DR(d)->parent) {
+    i += strlen(DR(d)->name)+1;
     c++;
   }
 
@@ -268,17 +264,17 @@ char *getpath(struct dir *cur) {
     getpathdatl = i;
     getpathdat = realloc(getpathdat, i);
   }
-  list = malloc(c*sizeof(struct dir *));
+  list = malloc(c*sizeof(compll_t));
 
   c = 0;
-  for(d=cur; d!=NULL; d=d->parent)
+  for(d=cur; d; d=DR(d)->parent)
     list[c++] = d;
 
   getpathdat[0] = '\0';
   while(c--) {
-    if(list[c]->parent)
+    if(DR(list[c])->parent)
       strcat(getpathdat, "/");
-    strcat(getpathdat, list[c]->name);
+    strcat(getpathdat, DR(list[c])->name);
   }
   free(list);
   return getpathdat;
diff --git a/src/util.h b/src/util.h
index fc7e29b985e3f621e0dc3f7e5f36a8e20042d449..af49d221bb5b7fd6453bf6ad64629c2c58cab9f9 100644
--- a/src/util.h
+++ b/src/util.h
@@ -35,6 +35,9 @@ extern int winrows, wincols;
 /* used by the nc* functions and macros */
 extern int subwinr, subwinc;
 
+/* handy macros for accessing nodes */
+#define DR(n) ((const struct dir *) compll_read(n))
+#define DW(n) ((struct dir *) compll_write(n))
 
 /* Instead of using several ncurses windows, we only draw to stdscr.
  * the functions nccreate, ncprint and the macros ncaddstr and ncaddch
@@ -72,11 +75,11 @@ char *formatsize(const off_t);
 char *fullsize(const off_t);
 
 /* recursively free()s a directory tree */
-void freedir(struct dir *);
+void freedir(compll_t);
 
 /* generates full path from a dir item,
    returned pointer will be overwritten with a subsequent call */
-char *getpath(struct dir *);
+char *getpath(compll_t);
 
 #endif