diff --git a/src/calc.c b/src/calc.c
index 8ae299e21ca63992209e8f6dd8d9b5703629d7c0..30df0c0cf6dba1fa6cd2790e0cdd2f0d50840cd6 100644
--- a/src/calc.c
+++ b/src/calc.c
@@ -53,7 +53,7 @@ char calc_smfs  = 0;
 
 /* global vars for internal use */
 char failed;             /* 1 on fatal error */
-char *curpath;           /* last lstat()'ed item */
+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 */
@@ -64,10 +64,34 @@ int anpos;               /* position of the animation string */
 int curpathl = 0, lasterrl = 0;
 
 
+/* adds name to curpath */
+void calc_enterpath(char *name) {
+  int n;
+
+  n = strlen(curpath)+strlen(name)+2;
+  if(n > curpathl) {
+    curpathl = n;
+    curpath = realloc(curpath, curpathl);
+  }
+  if(curpath[1])
+    strcat(curpath, "/");
+  strcat(curpath, name);
+}
+
+
+/* removes last component from curpath */
+void calc_leavepath() {
+  char *tmp;
+  if((tmp = strrchr(curpath, '/')) != curpath)
+    tmp[0] = 0;
+  else
+    tmp[1] = 0;
+}
+
+
 int calc_item(struct dir *par, char *name) {
   struct dir *t, *d;
   struct stat fs;
-  char *tmp;
 
   if(name[0] == '.' && (name[1] == '\0' || (name[1] == '.' && name[2] == '\0')))
     return 0;
@@ -75,13 +99,8 @@ int calc_item(struct dir *par, char *name) {
   /* allocate dir and fix references */
   d = calloc(sizeof(struct dir), 1);
   d->parent = par;
-  if(par->sub == NULL)
-    par->sub = d;
-  else {
-    for(t=par->sub; t->next!=NULL; t=t->next)
-      ;
-    t->next = d;
-  }
+  d->next = par->sub;
+  par->sub = d;
   d->name = malloc(strlen(name)+1);
   strcpy(d->name, name);
 
@@ -93,22 +112,14 @@ int calc_item(struct dir *par, char *name) {
   }
 #endif
 
-  /* update curpath */
-  tmp = getpath(d);
-  if((int)strlen(tmp)+1 > curpathl) {
-    curpathl = strlen(tmp)+1;
-    curpath = realloc(curpath, curpathl);
-  }
-  strcpy(curpath, tmp);
-
   /* lstat */
-  if(lstat(d->name, &fs)) {
+  if(lstat(name, &fs)) {
     d->flags |= FF_ERR;
     return 0;
   }
 
   /* check for excludes and same filesystem */
-  if(exclude_match(curpath))
+  if(exclude_match(d->name))
     d->flags |= FF_EXL;
 
   if(calc_smfs && curdev != fs.st_dev)
@@ -134,6 +145,7 @@ int calc_item(struct dir *par, char *name) {
       t->asize += d->asize;
     }
   }
+
   return 0;
 }
 
@@ -143,21 +155,22 @@ int calc_item(struct dir *par, char *name) {
 int calc_dir(struct dir *dest, char *name) {
   struct dir *t;
   DIR *dir;
-  char *tmp;
   struct dirent *dr;
   int ch;
 
   if(input_handle(1))
     return 1;
 
-  /* open directory */
-  if((dir = opendir(name)) == NULL) {
-    tmp = getpath(dest);
-    if(lasterrl < (int)strlen(tmp)+1) {
-      lasterrl = strlen(tmp)+1;
+  /* curpath */
+  calc_enterpath(name);
+
+  /* open & chdir into directory */
+  if((dir = opendir(name)) == NULL || chdir(name) < 0) {
+    if(lasterrl < (int)strlen(curpath)) {
+      lasterrl = strlen(curpath)+1;
       lasterr = realloc(lasterr, lasterrl);
     }
-    strcpy(lasterr, tmp);
+    strcpy(lasterr, curpath);
     dest->flags |= FF_ERR;
     t = dest;
     while((t = t->parent) != NULL)
@@ -165,18 +178,14 @@ int calc_dir(struct dir *dest, char *name) {
     return 0;
   }
 
-  /* chdir */
-  if(chdir(name) < 0) {
-      dest->flags |= FF_ERR;
-    return 0;
-  }
-
   /* read directory */
   while((dr = readdir(dir)) != NULL) {
+    calc_enterpath(dr->d_name);
     if(calc_item(dest, dr->d_name))
       dest->flags |= FF_ERR;
     if(input_handle(1))
       return 1;
+    calc_leavepath();
     errno = 0;
   }
 
@@ -209,6 +218,7 @@ int calc_dir(struct dir *dest, char *name) {
     strcpy(errmsg, "Couldn't chdir to previous directory");
     return 1;
   }
+  calc_leavepath();
 
   return 0;
 }
@@ -343,6 +353,13 @@ void calc_process() {
   root = t;
   curdev = fs.st_dev;
 
+  /* update curpath */
+  if((int)strlen(path)+1 > curpathl) {
+    curpathl = strlen(path)+1;
+    curpath = realloc(curpath, curpathl);
+  }
+  strcpy(curpath, path);
+
   /* start calculating */
   if(!calc_dir(root, name) && !failed) {
     free(path);