// // $Date: 1999/04/22 16:07:39 $ // $Revision: 1.1 $ // #include #include #include #include #include #include #include "mgl.h" #define FONTW 6 #define FONTH 12 int minsize = 0; int maxdepth = 0; #define MAXINODES 100000 char inodes[MAXINODES]; struct node { char *name; mode_t mode; int size; int x,y,w,h; struct node *children; struct node *next; }; struct node * du(char *dir) { DIR *dirp; struct dirent *direntp; struct node *nodep=NULL,*next=NULL,*p; struct stat statbuf; char path[1000]; int size; dirp = opendir(dir); if(dirp == NULL) return NULL; while((direntp = readdir(dirp))!=NULL){ if(strcmp(direntp->d_name,".")==0 || strcmp(direntp->d_name,"..")==0) continue; nodep = (struct node*)malloc(sizeof(struct node)); if(nodep == NULL) exit(0); nodep->next = next; nodep->children = NULL; next = nodep; sprintf(path,"%s%s",dir,direntp->d_name); nodep->name = strdup(direntp->d_name); nodep->size = 0; lstat(path,&statbuf); if(S_ISLNK(statbuf.st_mode)){ nodep->size = 1; continue; } if(S_ISDIR(statbuf.st_mode)){ strcat(path,"/"); nodep->children = du(path); size = 0; for(p=nodep->children;p;p=p->next){ size += p->size; } nodep->size = size; } else if(S_ISREG(statbuf.st_mode)){ int ino = statbuf.st_ino; if(ino < MAXINODES && inodes[ino]==0){ nodep->size = statbuf.st_size; inodes[ino]++; } else { nodep->size = 1; } } nodep->mode = statbuf.st_mode; } closedir(dirp); return nodep; } typedef enum { VERTICAL, HORIZONTAL } Orientation; int color; int curx,cury; int oldcurx,oldcury; dispnode(struct node *p) { int len,cols,rows; int offx,offy; char buf[100]; char name[100]; int i; int w,h; static int prevx=-1,prevy=-1,prevw=-1,prevh=-1; if(minsize && minsize > p->size) return; if(p->w == prevw && p->h == prevh && p->x == prevx && p->y == prevy) return; // if(p->w == 0 || p->h == 0) return; w = p->w; if(w == 0) w = 1; h = p->h; if(h == 0) h = 1; prevw = p->w; prevh = p->h; prevx = p->x; prevy = p->y; color = (color+1)%4; set_color(color); fill_rect(p->x,p->y,w,h); strcpy(name,p->name); if(S_ISDIR(p->mode)) strcat(name,"/"); len = strlen(name); if(len==0) return; cols = p->w / FONTW; rows = p->h / FONTH; if(cols * rows >= len){ set_color((color+2)%4); set_font(FONTH,0); rows = ((len-1)/cols)+1 ; cols = ((len-1)/rows)+1; offx = (p->w - cols*FONTW)/2; offy = (p->h - rows*FONTH)/2; for(i=0;ix+offx,p->y+offy+i*FONTH,buf); } } } display(struct node *porig,int x,int y,int w,int h,Orientation o,int level) { struct node *p; int total = 0; int v1,v2; Orientation newo; if(! porig) return 0; o = w > h ? VERTICAL : HORIZONTAL; if(level == 0){ set_color(0); clear_screen(); } for(p=porig;p;p=p->next){ total += p->size; } if(total == 0) return 0; v1 = v2 = 0; for(p=porig;p;p=p->next){ v2 = v1 + p->size; if(S_ISREG(p->mode) || (maxdepth && maxdepth <= level+1)){ if(o == VERTICAL){ p->x = x+(int)((float)v1*(float)w/(float)total); p->y = y; p->w = (int)((float)(v2-v1)*(float)w/(float)total); p->h = h; } else { p->x = x; p->y = y+(int)((float)v1*(float)h/(float)total); p->w = w; p->h = (int)((float)(v2-v1)*(float)h/(float)total); } dispnode(p); } else { newo = (o == VERTICAL ? HORIZONTAL : VERTICAL); if(o == VERTICAL){ p->x = x+(int)((float)v1*(float)w/(float)total); p->y = y; p->w = (int)((float)(v2-v1)*(float)w/(float)total); p->h = h; if(display(p->children,p->x,p->y,p->w,p->h,newo,level+1)) return 1; } else { p->x = x; p->y = y+(int)((float)v1*(float)h/(float)total); p->w = w; p->h = (int)((float)(v2-v1)*(float)h/(float)total); if(display(p->children,p->x,p->y,p->w,p->h,newo,level+1)) return 1; } } v1 = v2; } return 0; } #define CTRL(c) (c-0x40) extern char *optarg; extern int optind; main(int argc, char **argv) { struct node *nodep,*p; int c; int size; char buf[200]; char root[100] = "/"; int level; while((c = getopt(argc,argv,"d:s:")) != -1){ switch(c){ case 'd': maxdepth = atoi(optarg); break; case 's': minsize = atoi(optarg); break; } } argc -= optind; argv += optind; if(argc > 0){ strcpy(root,argv[0]); if(root[strlen(root)-1] != '/') strcat(root,"/"); } nodep = du(root); if(nodep == NULL) exit(0); open_graph(); color = 0; display(nodep,0,FONTH,640,240-FONTH,VERTICAL,0); for(;;){ set_color(4); // カーソル反転 fill_rect(curx-3,cury-3,7,7); set_color(3); set_font(FONTH,0); strcpy(buf,root); p = nodep; level = 0; while(p && (!maxdepth || level < maxdepth)){ size = p->size; if(curx >= p->x && curx <= p->x+p->w && cury >= p->y && cury <= p->y+p->h){ strcat(buf,p->name); if(S_ISREG(p->mode)) break; else{ strcat(buf,"/"); p=p->children; level++; } } else { p = p->next; } } sprintf(buf+strlen(buf)," (%dKB)",size/1024); set_color(0); fill_rect(0,0,600,FONTH); set_color(3); draw_string(0,0,buf); oldcurx = curx; oldcury = cury; switch(c = get_key(-1)){ case MK_DOWN: cury++; break; case MK_UP: cury--; break; case MK_RIGHT: curx++; break; case MK_LEFT: curx--; break; case CTRL('N'): case 'j': cury+=20; break; case CTRL('P'): case 'k': cury-=20; break; case CTRL('F'): case 'l': curx+=20; break; case CTRL('B'): case 'h': curx-=20; break; case CTRL('C'): case 0x1b: case 'q': case 'Q': exit(0); } if(curx < 0) curx = 0; if(curx >= 640) curx = 639; if(cury < FONTH) cury = FONTH; if(cury >= 240) cury = 239; set_color(4); // カーソル反転 fill_rect(oldcurx-3,oldcury-3,7,7); } close_graph(); }