From db920f8dab8ca51e90c51afcd2445bb84d74c3f0 Mon Sep 17 00:00:00 2001
From: yorhel <yorhel@ce56bc8d-f834-0410-b703-f827bd498a76>
Date: Thu, 16 Aug 2007 08:36:58 +0000
Subject: [PATCH] * Added error handling for the import feature * Created own
 window-functions and removed ncurses window usage * Rewrote fullsize

git-svn-id: svn://blicky.net/ncdu/trunk@27 ce56bc8d-f834-0410-b703-f827bd498a76
---
 src/browser.c |  37 ++++++-------
 src/calc.c    |  46 ++++++----------
 src/delete.c  |  84 +++++++++++-----------------
 src/export.c  |  58 +++++++++++++++----
 src/help.c    | 150 ++++++++++++++++++++++++--------------------------
 src/main.c    |   3 +-
 src/ncdu.h    |  10 +++-
 src/util.c    |  85 ++++++++++++++++++++++++----
 8 files changed, 267 insertions(+), 206 deletions(-)

diff --git a/src/browser.c b/src/browser.c
index 1684851..7bac33b 100644
--- a/src/browser.c
+++ b/src/browser.c
@@ -29,31 +29,26 @@ struct dir *bcur;
 
 
 void drawInfo(struct dir *dr) {
-  WINDOW *nfo;
   char path[PATH_MAX];
 
-  nfo = newwin(11, 60, winrows/2-5, wincols/2-30);
-  box(nfo, 0, 0);
-  wattron(nfo, A_BOLD);
-  mvwaddstr(nfo, 0, 4, "Item info");
-
-  mvwaddstr(nfo, 2, 3, "Name:");
-  mvwaddstr(nfo, 3, 3, "Path:");
-  mvwaddstr(nfo, 4, 3, "Type:");
-  mvwaddstr(nfo, 6, 3, "   Disk usage:");
-  mvwaddstr(nfo, 7, 3, "Apparent size:");
-  wattroff(nfo, A_BOLD);
-
-  mvwaddstr(nfo, 2,  9, cropdir(dr->name, 49));
-  mvwaddstr(nfo, 3,  9, cropdir(getpath(dr, path), 49));
-  mvwaddstr(nfo, 4,  9, dr->flags & FF_DIR ? "Directory"
+  nccreate(11, 60, "Item info");
+
+  attron(A_BOLD);
+  ncaddstr(2, 3, "Name:");
+  ncaddstr(3, 3, "Path:");
+  ncaddstr(4, 3, "Type:");
+  ncaddstr(6, 3, "   Disk usage:");
+  ncaddstr(7, 3, "Apparent size:");
+  attroff(A_BOLD);
+
+  ncaddstr(2,  9, cropdir(dr->name, 49));
+  ncaddstr(3,  9, cropdir(getpath(dr, path), 49));
+  ncaddstr(4,  9, dr->flags & FF_DIR ? "Directory"
       : dr->flags & FF_FILE ? "File" : "Other (link, device, socket, ..)");
-  mvwprintw(nfo, 6, 18, "%s (%s B)", cropsize(dr->size),  fullsize(dr->size));
-  mvwprintw(nfo, 7, 18, "%s (%s B)", cropsize(dr->asize), fullsize(dr->asize));
+  ncprint(6, 18, "%s (%s B)", cropsize(dr->size),  fullsize(dr->size));
+  ncprint(7, 18, "%s (%s B)", cropsize(dr->asize), fullsize(dr->asize));
 
-  mvwaddstr(nfo, 9, 32, "Press any key to continue");
-  wrefresh(nfo);
-  delwin(nfo);
+  ncaddstr(9, 32, "Press any key to continue");
 }
 
 
diff --git a/src/calc.c b/src/calc.c
index 607371b..ff1963b 100644
--- a/src/calc.c
+++ b/src/calc.c
@@ -135,28 +135,23 @@ char *rpath(const char *from, char *to) {
 
 /* the progress window */
 static void drawProgress(char *cdir) {
-  WINDOW *prg;
   char ani[15];
   int i;
 
-  prg = newwin(10, 60, winrows/2-3, wincols/2-30);
-  box(prg, 0, 0);
-  wattron(prg, A_BOLD);
-  mvwaddstr(prg, 0, 4, dat == NULL ? "Calculating..." : "Recalculating...");
-  wattroff(prg, A_BOLD);
+  nccreate(10, 60, dat == NULL ? "Calculating..." : "Recalculating...");
 
-  mvwprintw(prg, 2, 2, "Total items: %-8d size: %s",
+  ncprint(2, 2, "Total items: %-8d size: %s",
     parent->items, cropsize(parent->size));
-  mvwprintw(prg, 3, 2, "Current dir: %s", cropdir(cdir, 43));
-  mvwaddstr(prg, 8, 43, "Press q to quit");
+  ncprint(3, 2, "Current dir: %s", cropdir(cdir, 43));
+  ncaddstr(8, 43, "Press q to quit");
 
  /* show warning if we couldn't open a dir */
   if(lasterr[0] != '\0') {
-     wattron(prg, A_BOLD);
-     mvwaddstr(prg, 5, 2, "Warning:");
-     wattroff(prg, A_BOLD);
-     mvwprintw(prg, 5, 11, "could not open %-32s", cropdir(lasterr, 32));
-     mvwaddstr(prg, 6, 3, "some directory sizes may not be correct");  
+     attron(A_BOLD);
+     ncaddstr(5, 2, "Warning:");
+     attroff(A_BOLD);
+     ncprint(5, 11, "could not open %-32s", cropdir(lasterr, 32));
+     ncaddstr(6, 3, "some directory sizes may not be correct");  
   }
 
  /* animation - but only if the screen refreshes more than or once every second */
@@ -171,30 +166,24 @@ static void drawProgress(char *cdir) {
           ani[i] = antext[i];
   } else
     strcpy(ani, antext);
-  mvwaddstr(prg, 8, 3, ani);
+  ncaddstr(8, 3, ani);
 
-  wrefresh(prg);
-  delwin(prg);
+  refresh();
 }
 
 
 /* show error if can't open parent dir */
 static void drawError(char *dir) {
-  WINDOW *err;
+  nccreate(10, 60, "Error!");
 
-  err = newwin(10, 60, winrows/2-3, wincols/2-30);
-  box(err, 0, 0);
-  wattron(err, A_BOLD);
-  mvwaddstr(err, 0, 4, "Error!");
+  attron(A_BOLD);
+  ncaddstr(5, 2, "Error:");
+  attroff(A_BOLD);
 
-  mvwaddstr(err, 5, 2, "Error:");
-  wattroff(err, A_BOLD);
-  mvwprintw(err, 5, 9, "could not open %s", cropdir(dir, 34));
-  mvwaddstr(err, 6, 3, "press any key to continue...");
+  ncprint(5, 9, "could not open %s", cropdir(dir, 34));
+  ncaddstr(6, 3, "press any key to continue...");
 
   refresh();
-  wrefresh(err);
-  delwin(err);
 }
 
 
@@ -380,7 +369,6 @@ struct dir *showCalc(char *path) {
       if(dat != NULL)
         drawBrowser(0);
       drawError(path);
-      refresh();
     } while (getch() == KEY_RESIZE);
     return(NULL);
   }
diff --git a/src/delete.c b/src/delete.c
index f8b85e9..043e4fa 100644
--- a/src/delete.c
+++ b/src/delete.c
@@ -29,84 +29,62 @@ suseconds_t lastupdate;
 
 
 void drawConfirm(struct dir *del, int sel) {
-  WINDOW *cfm;
+  nccreate(6, 60, "Confirm delete");
 
-  cfm = newwin(6, 60, winrows/2-3, wincols/2-30);
-  box(cfm, 0, 0);
-  wattron(cfm, A_BOLD);
-  mvwaddstr(cfm, 0, 4, "Confirm delete");
-  wattroff(cfm, A_BOLD);
-
-  mvwprintw(cfm, 1, 2, "Are you sure you want to delete \"%s\"%c",
+  ncprint(1, 2, "Are you sure you want to delete \"%s\"%c",
     cropdir(del->name, 21), del->flags & FF_DIR ? ' ' : '?');
   if(del->flags & FF_DIR) 
-    mvwprintw(cfm, 2, 18, "and all of its contents?");
+    ncprint(2, 18, "and all of its contents?");
 
   if(sel == 0)
-    wattron(cfm, A_REVERSE);
-  mvwaddstr(cfm, 4, 15, "yes");
-  wattroff(cfm, A_REVERSE);
+    attron(A_REVERSE);
+  ncaddstr(4, 15, "yes");
+  attroff(A_REVERSE);
   if(sel == 1)
-    wattron(cfm, A_REVERSE);
-  mvwaddstr(cfm, 4, 24, "no");
-  wattroff(cfm, A_REVERSE);
+    attron(A_REVERSE);
+  ncaddstr(4, 24, "no");
+  attroff(A_REVERSE);
   if(sel == 2)
-    wattron(cfm, A_REVERSE);
-  mvwaddstr(cfm, 4, 31, "don't ask me again");
-  wattroff(cfm, A_REVERSE);
-
-  wrefresh(cfm);
-  delwin(cfm);
+    attron(A_REVERSE);
+  ncaddstr(4, 31, "don't ask me again");
+  attroff(A_REVERSE);
+  
+  refresh();
 }
 
 
 /* show progress */
 static void drawProgress(char *file) {
-  WINDOW *prg;
+  nccreate(6, 60, "Deleting...");
 
-  prg = newwin(6, 60, winrows/2-3, wincols/2-30);
-  nodelay(prg, 1);
-  box(prg, 0, 0);
-  wattron(prg, A_BOLD);
-  mvwaddstr(prg, 0, 4, "Deleting...");
-  wattroff(prg, A_BOLD); 
+  ncaddstr(1, 2, cropdir(file, 47));
+  ncaddstr(4, 41, "Press q to abort");
 
-  mvwaddstr(prg, 1, 2, cropdir(file, 47));
-  mvwaddstr(prg, 4, 41, "Press q to abort");
-
-  wrefresh(prg);
-  delwin(prg);
+  refresh();
 }
 
 
 /* show error dialog */
 static void drawError(int sel, char *file) {
-  WINDOW *err;
-
-  err = newwin(6, 60, winrows/2-3, wincols/2-30);
-  box(err, 0, 0);
-  wattron(err, A_BOLD);
-  mvwaddstr(err, 0, 4, "Error!");
-  wattroff(err, A_BOLD);
+  nccreate(6, 60, "Error!");
 
-  mvwprintw(err, 1, 2, "Can't delete %s:", cropdir(file, 42));
-  mvwaddstr(err, 2, 4, strerror(errno));
+  ncprint(1, 2, "Can't delete %s:", cropdir(file, 42));
+  ncaddstr(2, 4, strerror(errno));
 
   if(sel == 0)
-    wattron(err, A_REVERSE);
-  mvwaddstr(err, 4, 14, "abort");
-  wattroff(err, A_REVERSE);
+    attron(A_REVERSE);
+  ncaddstr(4, 14, "abort");
+  attroff(A_REVERSE);
   if(sel == 1)
-    wattron(err, A_REVERSE);
-  mvwaddstr(err, 4, 23, "ignore");
-  wattroff(err, A_REVERSE);
+    attron(A_REVERSE);
+  ncaddstr(4, 23, "ignore");
+  attroff(A_REVERSE);
   if(sel == 2)
-    wattron(err, A_REVERSE);
-  mvwaddstr(err, 4, 33, "ignore all");
-  wattroff(err, A_REVERSE);
+    attron(A_REVERSE);
+  ncaddstr(4, 33, "ignore all");
+  attroff(A_REVERSE);
 
-  wrefresh(err);
-  delwin(err); 
+  refresh();
 }
 
 
diff --git a/src/export.c b/src/export.c
index 303e3b7..0f81839 100644
--- a/src/export.c
+++ b/src/export.c
@@ -39,7 +39,7 @@ unsigned int ilevel;
 
 #define writeInt(hl, word, bytes) _writeInt(hl, (unsigned char *) &word, bytes, sizeof(word))
 
-/* Write any integer in network byte order.
+/* Write any unsigned integer in network byte order.
  * This function always writes the number of bytes specified by storage to the
  * file, disregarding the actual size of word. If the actual size is smaller
  * than the storage, the number will be preceded by null-bytes. If the actual
@@ -116,6 +116,7 @@ void exportFile(char *dest, struct dir *src) {
   /* header */
   fprintf(wr, "ncdu%c%s%c", 1, PACKAGE_STRING, 0);
 
+ /* we assume timestamp > 0 */
   gettimeofday(&tv, NULL);
   writeInt(wr, tv.tv_sec, 8);
 
@@ -137,10 +138,10 @@ void exportFile(char *dest, struct dir *src) {
 */
 
 
-#define readInt(hl, word, bytes) _readInt(hl, (unsigned char *) &word, bytes, sizeof(word))
+#define readInt(hl, word, bytes) if(!_readInt(hl, (unsigned char *) &word, bytes, sizeof(word))) return(NULL)
 
 /* reverse of writeInt */
-void _readInt(FILE *rd, unsigned char *word, int storage, int size) {
+int _readInt(FILE *rd, unsigned char *word, int storage, int size) {
   unsigned char buf[8];
   int i;
 
@@ -148,7 +149,8 @@ void _readInt(FILE *rd, unsigned char *word, int storage, int size) {
   memset(buf, 0, 8);
 
  /* read integer to the end of the buffer */
-  fread(buf+(8-storage), 1, storage, rd);
+  if(fread(buf+(8-storage), 1, storage, rd) != storage)
+    return(0);
 
  /* copy buf to word, in host byte order */
   if(IS_BIG_ENDIAN)
@@ -156,6 +158,7 @@ void _readInt(FILE *rd, unsigned char *word, int storage, int size) {
   else
     for(i=0; i<size; i++)
       word[i] = buf[7-i];
+  return(1);
 }
 
 
@@ -167,17 +170,21 @@ struct dir *importFile(char *filename) {
   unsigned int level;
   struct dir *prev, *cur, *tmp, *parent;
 
-  rd = fopen(filename, "r");
+  if(!(rd = fopen(filename, "r")))
+    return(NULL);
 
  /* check filetype */
-  fread(buf, 1, 5, rd);
+  if(fread(buf, 1, 5, rd) != 5)
+    return(NULL);
+  
   if(buf[0] != 'n' || buf[1] != 'c' || buf[2] != 'd'
       || buf[3] != 'u' || buf[4] != (char) 1)
     return(NULL);
 
  /* package name, version and timestamp are ignored for now */
   for(i=0; i<=64 && fgetc(rd) != 0; i++) ;
-  fread(buf, 1, 8, rd);
+  if(fread(buf, 1, 8, rd) != 8)
+    return(NULL);
 
  /* number of items is not ignored */
   readInt(rd, items, 4);
@@ -187,21 +194,21 @@ struct dir *importFile(char *filename) {
   prev = NULL;
   for(item=0; item<items; item++) {
     unsigned int curlev;
-    unsigned char flags, name[8192];
-    int ch;
+    unsigned char name[8192];
+    int ch, flags;
     
     readInt(rd, curlev, 2);
     flags = fgetc(rd);
 
+    if(flags == EOF || (prev && curlev == 0) || (!prev && curlev != 0) || curlev > level+1)
+      return(NULL);
+
     cur = calloc(sizeof(struct dir), 1);
     if(!prev)
       parent = cur;
     else if(curlev > level) {
       prev->sub = cur;
       cur->parent = prev;
-    } else if(curlev == level) {
-      prev->next = cur;
-      cur->parent = prev->parent;
     } else {
       for(i=level; i>curlev; i--)
         prev = prev->parent;
@@ -227,6 +234,8 @@ struct dir *importFile(char *filename) {
    /* name */
     for(i=0; i<8192; i++) {
       ch = fgetc(rd);
+      if(ch == EOF)
+        return(NULL);
       name[i] = (unsigned char) ch;
       if(ch == 0)
         break;
@@ -247,4 +256,29 @@ struct dir *importFile(char *filename) {
 }
 
 
+struct dir *showImport(char *path) {
+  struct dir *ret;
+
+  nccreate(3, 60, "Importing...");
+  ncprint(1, 2, "Importing '%s'...", cropdir(path, 43));
+  refresh();
+  sleep(2);
+
+  ret = importFile(path);
+  if(ret)
+    return(ret);
+
+  if(s_export) {
+    printf("Error importing '%s'\n", path);
+    exit(1);
+  }
+
+ /* show an error message */
+  nccreate(5, 60, "Error...");
+  ncprint(1, 2, "Can't import '%s'", cropdir(path, 43));
+  ncprint(3, 3, "press any key to continue...");
+  getch();
+
+  return(NULL);
+}
 
diff --git a/src/help.c b/src/help.c
index 0482971..d07a278 100644
--- a/src/help.c
+++ b/src/help.c
@@ -48,110 +48,104 @@ char *keys[KEYS*2] = {
 
 
 void drawHelp(int page, int start) {
-  WINDOW *hlp;
   int i, line;
 
-  hlp = newwin(15, 60, winrows/2-7, wincols/2-30);
-  box(hlp, 0, 0);
-  wattron(hlp, A_BOLD);
-  mvwaddstr(hlp, 0, 4, "ncdu help");
-  wattroff(hlp, A_BOLD);
-  mvwaddstr(hlp, 13, 38, "Press q to continue");
+  nccreate(15, 60, "ncdu help");
+  ncaddstr(13, 38, "Press q to continue");
 
   if(page == 1)
-    wattron(hlp, A_REVERSE);
-  mvwaddstr(hlp, 0, 30, "1:Keys");
-  wattroff(hlp, A_REVERSE);
+    attron(A_REVERSE);
+  ncaddstr(0, 30, "1:Keys");
+  attroff(A_REVERSE);
   if(page == 2)
-    wattron(hlp, A_REVERSE);
-  mvwaddstr(hlp, 0, 39, "2:Format");
-  wattroff(hlp, A_REVERSE);
+    attron(A_REVERSE);
+  ncaddstr(0, 39, "2:Format");
+  attroff(A_REVERSE);
   if(page == 3)
-    wattron(hlp, A_REVERSE);
-  mvwaddstr(hlp, 0, 50, "3:About");
-  wattroff(hlp, A_REVERSE);
+    attron(A_REVERSE);
+  ncaddstr(0, 50, "3:About");
+  attroff(A_REVERSE);
 
   switch(page) {
     case 1:
       line = 1;
       for(i=start*2; i<start*2+20; i+=2) {
-        wattron(hlp, A_BOLD);
-        mvwaddstr(hlp, ++line, 13-strlen(keys[i]), keys[i]);
-        wattroff(hlp, A_BOLD);
-        mvwaddstr(hlp, line, 15, keys[i+1]);
+        attron(A_BOLD);
+        ncaddstr(++line, 13-strlen(keys[i]), keys[i]);
+        attroff(A_BOLD);
+        ncaddstr(line, 15, keys[i+1]);
       }
       if(start != KEYS-10)
-        mvwaddstr(hlp, 12, 25, "-- more --");
+        ncaddstr(12, 25, "-- more --");
       break;
     case 2:
-      wattron(hlp, A_BOLD);
-      mvwaddstr(hlp, 2, 3, "X  [size] [graph] [file or directory]");
-      wattroff(hlp, A_BOLD);
-      mvwaddstr(hlp, 3, 4, "The X is only present in the following cases:");
-      wattron(hlp, A_BOLD);
-      mvwaddch(hlp, 5, 4, '!');
-      mvwaddch(hlp, 6, 4, '.');
-      mvwaddch(hlp, 7, 4, '<');
-      mvwaddch(hlp, 8, 4, '>');
-      mvwaddch(hlp, 9, 4, '@');
-      mvwaddch(hlp,10, 4, 'e');
-      wattroff(hlp, A_BOLD);
-      mvwaddstr(hlp, 5, 7, "An error occured while reading this directory");
-      mvwaddstr(hlp, 6, 7, "An error occured while reading a subdirectory");
-      mvwaddstr(hlp, 7, 7, "File or directory is excluded from the statistics");
-      mvwaddstr(hlp, 8, 7, "Directory was on an other filesystem");
-      mvwaddstr(hlp, 9, 7, "This is not a file nor a dir (symlink, socket, ...)");
-      mvwaddstr(hlp,10, 7, "Empty directory");
+      attron(A_BOLD);
+      ncaddstr(2, 3, "X  [size] [graph] [file or directory]");
+      attroff(A_BOLD);
+      ncaddstr(3, 4, "The X is only present in the following cases:");
+      attron(A_BOLD);
+      ncaddch( 5, 4, '!');
+      ncaddch( 6, 4, '.');
+      ncaddch( 7, 4, '<');
+      ncaddch( 8, 4, '>');
+      ncaddch( 9, 4, '@');
+      ncaddch(10, 4, 'e');
+      attroff(A_BOLD);
+      ncaddstr( 5, 7, "An error occured while reading this directory");
+      ncaddstr( 6, 7, "An error occured while reading a subdirectory");
+      ncaddstr( 7, 7, "File or directory is excluded from the statistics");
+      ncaddstr( 8, 7, "Directory was on an other filesystem");
+      ncaddstr( 9, 7, "This is not a file nor a dir (symlink, socket, ...)");
+      ncaddstr(10, 7, "Empty directory");
       break;
     case 3:
       /* Indeed, too much spare time */
-      wattron(hlp, A_REVERSE);
+      attron(A_REVERSE);
 #define x 12
 #define y 3
       /* N */
-      mvwaddstr(hlp, y+0, x+0, "      ");
-      mvwaddstr(hlp, y+1, x+0, "  ");
-      mvwaddstr(hlp, y+2, x+0, "  ");
-      mvwaddstr(hlp, y+3, x+0, "  ");
-      mvwaddstr(hlp, y+4, x+0, "  ");
-      mvwaddstr(hlp, y+1, x+4, "  ");
-      mvwaddstr(hlp, y+2, x+4, "  ");
-      mvwaddstr(hlp, y+3, x+4, "  ");
-      mvwaddstr(hlp, y+4, x+4, "  ");
+      ncaddstr(y+0, x+0, "      ");
+      ncaddstr(y+1, x+0, "  ");
+      ncaddstr(y+2, x+0, "  ");
+      ncaddstr(y+3, x+0, "  ");
+      ncaddstr(y+4, x+0, "  ");
+      ncaddstr(y+1, x+4, "  ");
+      ncaddstr(y+2, x+4, "  ");
+      ncaddstr(y+3, x+4, "  ");
+      ncaddstr(y+4, x+4, "  ");
       /* C */
-      mvwaddstr(hlp, y+0, x+8, "     ");
-      mvwaddstr(hlp, y+1, x+8, "  ");
-      mvwaddstr(hlp, y+2, x+8, "  ");
-      mvwaddstr(hlp, y+3, x+8, "  ");
-      mvwaddstr(hlp, y+4, x+8, "     ");
+      ncaddstr(y+0, x+8, "     ");
+      ncaddstr(y+1, x+8, "  ");
+      ncaddstr(y+2, x+8, "  ");
+      ncaddstr(y+3, x+8, "  ");
+      ncaddstr(y+4, x+8, "     ");
       /* D */
-      mvwaddstr(hlp, y+0, x+19, "  ");
-      mvwaddstr(hlp, y+1, x+19, "  ");
-      mvwaddstr(hlp, y+2, x+15, "      ");
-      mvwaddstr(hlp, y+3, x+15, "  ");
-      mvwaddstr(hlp, y+3, x+19, "  ");
-      mvwaddstr(hlp, y+4, x+15, "      ");
+      ncaddstr(y+0, x+19, "  ");
+      ncaddstr(y+1, x+19, "  ");
+      ncaddstr(y+2, x+15, "      ");
+      ncaddstr(y+3, x+15, "  ");
+      ncaddstr(y+3, x+19, "  ");
+      ncaddstr(y+4, x+15, "      ");
       /* U */
-      mvwaddstr(hlp, y+0, x+23, "  ");
-      mvwaddstr(hlp, y+1, x+23, "  ");
-      mvwaddstr(hlp, y+2, x+23, "  ");
-      mvwaddstr(hlp, y+3, x+23, "  ");
-      mvwaddstr(hlp, y+0, x+27, "  ");
-      mvwaddstr(hlp, y+1, x+27, "  ");
-      mvwaddstr(hlp, y+2, x+27, "  ");
-      mvwaddstr(hlp, y+3, x+27, "  ");
-      mvwaddstr(hlp, y+4, x+23, "      ");
-      wattroff(hlp, A_REVERSE);
-      mvwaddstr(hlp, y+0, x+30, "NCurses");
-      mvwaddstr(hlp, y+1, x+30, "Disk");
-      mvwaddstr(hlp, y+2, x+30, "Usage");
-      mvwprintw(hlp, y+4, x+30, "%s", PACKAGE_VERSION);
-      mvwaddstr(hlp, 9,  7, "Written by Yoran Heling <projects@yorhel.nl>");
-      mvwaddstr(hlp,10, 16, "http://dev.yorhel.nl/ncdu/");
+      ncaddstr(y+0, x+23, "  ");
+      ncaddstr(y+1, x+23, "  ");
+      ncaddstr(y+2, x+23, "  ");
+      ncaddstr(y+3, x+23, "  ");
+      ncaddstr(y+0, x+27, "  ");
+      ncaddstr(y+1, x+27, "  ");
+      ncaddstr(y+2, x+27, "  ");
+      ncaddstr(y+3, x+27, "  ");
+      ncaddstr(y+4, x+23, "      ");
+      attroff(A_REVERSE);
+      ncaddstr(y+0, x+30, "NCurses");
+      ncaddstr(y+1, x+30, "Disk");
+      ncaddstr(y+2, x+30, "Usage");
+      ncprint( y+4, x+30, "%s", PACKAGE_VERSION);
+      ncaddstr( 9,  7, "Written by Yoran Heling <projects@yorhel.nl>");
+      ncaddstr(10, 16, "http://dev.yorhel.nl/ncdu/");
       break;
   }
-  wrefresh(hlp);
-  delwin(hlp); /* no need to use it anymore - free it */
+  refresh();
 }
 
 
diff --git a/src/main.c b/src/main.c
index 2d50ab4..63471f3 100644
--- a/src/main.c
+++ b/src/main.c
@@ -30,6 +30,7 @@ struct dir *dat;
 int winrows, wincols;
 char sdir[PATH_MAX], *s_export;
 int sflags, bflags, sdelay, bgraph;
+int subwinc, subwinr;
 
 
 /* parse command line */
@@ -110,7 +111,7 @@ struct dir *loadDir(char *path) {
   }
 
   if(S_ISREG(st.st_mode))
-    return(importFile(path));
+    return(showImport(path));
   else
     return(showCalc(path));
 }
diff --git a/src/ncdu.h b/src/ncdu.h
index b410ede..dc5d0af 100644
--- a/src/ncdu.h
+++ b/src/ncdu.h
@@ -29,6 +29,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <stdarg.h>
 #include <ctype.h>
 #include <limits.h>
 #include <errno.h>
@@ -81,6 +82,9 @@
 static unsigned int endian_test = 1;
 #define IS_BIG_ENDIAN (!(*(char *) &endian_test))
 
+/* check nccreate in util.c for more info on these defines */
+#define ncaddstr(r, c, s) mvaddstr(subwinr+(r), subwinc+(c), s)
+#define  ncaddch(r, c, s)  mvaddch(subwinr+(r), subwinc+(c), s)
 
 
 /*
@@ -145,6 +149,8 @@ extern int winrows, wincols;
 /* global settings */
 extern char sdir[PATH_MAX], *s_export;
 extern int sflags, bflags, sdelay, bgraph;
+/* used for creating windows */
+extern int subwinr, subwinc;
 
 
 /*
@@ -155,6 +161,8 @@ extern char *cropdir(const char *, int);
 extern char *cropsize(const off_t);
 extern char *fullsize(const off_t);
 extern void ncresize(void);
+extern void nccreate(int, int, char *);
+extern void ncprint(int, int, char *, ...);
 extern struct dir * freedir(struct dir *);
 extern char *getpath(struct dir *, char *);
 /* settings.c */
@@ -174,4 +182,4 @@ extern int addExcludeFile(char *);
 extern int matchExclude(char *);
 /* export.c */
 extern void exportFile(char *, struct dir *);
-extern struct dir *importFile(char *);
+extern struct dir *showImport(char *);
diff --git a/src/util.c b/src/util.c
index 77363de..2ea5df6 100644
--- a/src/util.c
+++ b/src/util.c
@@ -73,18 +73,26 @@ char *cropsize(const off_t from) {
    BUG: Uses a dot as seperator, ignores current locale */
 char *fullsize(const off_t from) {
   char tmp[20];
-  int i, j, len;
-
-  sprintf(tmp, "%lld", from);
-  
-  fullsizedat[19] = '\0';
-  len = strlen(tmp);
-  for(i=len, j=18; i >= 0; i--) {
-    if(len-i != 1 && (len-i-1) % 3 == 0)
-      fullsizedat[j--] = '.';
-    fullsizedat[j--] = tmp[i];
+  off_t n = from;
+  int i, j;
+
+ /* the K&R method - more portable than sprintf with %lld */
+  i = 0;
+  do {
+    tmp[i++] = n % 10 + '0';
+  } while((n /= 10) > 0);
+  tmp[i] = '\0';
+
+ /* reverse and add thousand seperators */
+  j = 0;
+  while(i--) {
+    fullsizedat[j++] = tmp[i];
+    if(i != 0 && i%3 == 0)
+      fullsizedat[j++] = '.';
   }
-  return fullsizedat+j+1;
+  fullsizedat[j] = '\0';
+
+  return(fullsizedat);
 }
 
 
@@ -114,6 +122,61 @@ void ncresize(void) {
 }
 
 
+/* Instead of using several ncurses windows, we only draw to stdscr.
+ * the functions nccreate, ncprint and the macros ncaddstr and ncaddch
+ * mimic the behaviour of ncurses windows.
+ * This works better than using ncurses windows when all windows are
+ * created in the correct order: it paints directly on stdscr, so
+ * wrefresh, wnoutrefresh and other window-specific functions are not
+ * necessary.
+ * Also, this method doesn't require any window objects, as you can
+ * only create one window at a time.
+ *
+ * This function creates a new window in the center of the screen
+ * with a border and a title.
+*/
+void nccreate(int height, int width, char *title) {
+  int i;
+
+  subwinr = winrows/2-height/2;
+  subwinc = wincols/2-width/2;
+
+ /* clear window */
+  for(i=0; i<height; i++)
+    mvhline(subwinr+i, subwinc, ' ', width);
+
+ /* box() only works around curses windows, so create our own */
+  move(subwinr, subwinc);
+  addch(ACS_ULCORNER);
+  for(i=0; i<width-2; i++)
+    addch(ACS_HLINE);
+  addch(ACS_URCORNER);
+
+  move(subwinr+height-1, subwinc);
+  addch(ACS_LLCORNER);
+  for(i=0; i<width-2; i++)
+    addch(ACS_HLINE);
+  addch(ACS_LRCORNER);
+
+  mvvline(subwinr+1, subwinc, ACS_VLINE, height-2);
+  mvvline(subwinr+1, subwinc+width-1, ACS_VLINE, height-2);
+
+ /* title */
+  attron(A_BOLD);
+  mvaddstr(subwinr, subwinc+4, title);
+  attroff(A_BOLD);
+}
+
+
+void ncprint(int r, int c, char *fmt, ...) {
+  va_list arg;
+  va_start(arg, fmt);
+  move(subwinr+r, subwinc+c);
+  vw_printw(stdscr, fmt, arg);
+  va_end(arg);
+}
+
+
 
 void freedir_rec(struct dir *dr) {
   struct dir *tmp, *tmp2;
-- 
GitLab