1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
|
// dir-tree.c
// wolf 10/95
// very simple demo for the Tree classes in grafix
#include "tree.h"
#include "files.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
class DirTree;
typedef list <DirTree> Dlist;
// a popup window which appears when directory button is pressed
class dir_popup : public main_window {
Bool unmapped;
char entries[10000]; // the whole thing as one string
int ent;
public:
dir_popup(char *name, char *path, int ww, int wh, int x, int y) :
main_window(name,ww,wh,1,x,y) {
int nc = 0; // should be the length of text !!
DIR *dirp = opendir(path);
// if (dirp == 0) printf("can't open %s\n",path);
struct dirent *dp;
ent = 0; char *ep = entries+1; // why +1 ?????
for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
int length = strlen(dp->d_name);
if (dp->d_name[length-1] == '.') continue;
// if last char == . not display it ( . or .. )
char *fina = new char[length+strlen(path)+2];
sprintf(fina,"%s/%s",path,dp->d_name); // complete path
struct stat st;
if (!lstat(fina, &st)) {
// boundary check for ep should take place
sprintf(ep,"%8ld %-20s\n",st.st_size,dp->d_name);
// on stupid SUNs sprintf returns char* instead of int (char count)!!!
// so ep += sprintf(..) does not work there
while (*ep) ep++; // get position of string end;
ent++;
}
}
new text_viewer(*this,ww,wh,0,0,entries,nc);
unmapped = True;
}
void toggle() { // toggle between mappd/unmapped state
int y = (13*ent + 6 <? height); // 13 = font height
if (y < height) resize(width, y); // -> make window as small as needed
if (unmapped) RealizeChildren(); else Unmap();
unmapped = ! unmapped;
}
};
class DirTree : public Tree {
char *path;
dir_popup *dir_pop;
public:
DirTree(char *name, char *path, DirTree *parent = 0) :
Tree(name,parent), path(path) { dir_pop = 0; }
// popup a window with directory content
virtual void Press_cb(XButtonEvent *ev) {
if (dir_pop == 0) {
char title[200]; sprintf(title,"%s",path);
// raise popup just below the button, second press unmaps again
dir_pop = new dir_popup(title,path, 400, 200, ev->x_root, ev->y_root+20);
}
dir_pop->toggle();
}
virtual void Enter_cb(window *infw) { infw->clear(); infw->PlaceText(path); }
};
char *help_text[] = {
"call with directory name (default = $HOME)","",
"button press pops up the contents of directory",0 };
class Dir_main : public Tree_main {
public:
Dir_main(char * WMName, int w, int h) :
Tree_main(WMName,w,h, lin_tree) {
new help_button(*mb,"help",help_text);
}
// virtual void init() { Tree_main::init(); }
};
// recursively read directory tree, parent the parent Node
void rec_dir(char *path, DirTree* parent) {
printf("reading directory %s\n",path);
DIR *dirp = opendir(path);
if (dirp == 0) printf("can't open %s\n",path);
struct dirent *dp;
for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
int length = strlen(dp->d_name);
if (dp->d_name[length-1] != '.') { // not for . or .. file
int plen = strlen(path);
if (path[plen-1] == '/') path[plen-1] = 0; // eliminate tail-slashes
char *fina = new char[length+strlen(path)+2];
sprintf(fina,"%s/%s",path,dp->d_name); // complete path
struct stat st;
if (!lstat(fina, &st) && S_ISDIR(st.st_mode)) {
// *** problem with symbolic links : how to exclude ???? ***
// ********** use 'lstat' instead of 'stat' ************
// ********** !!!! because 'stat' follows the links !!! ********
// printf("reading directory %s %o\n",fina,st.st_mode);
char *tail = strrchr(fina,'/'); // eliminate trailing path
if (tail == 0) tail = fina; else tail++;
DirTree *dt = new DirTree(tail,fina,parent);
rec_dir(fina,dt);
}
}
}
closedir(dirp);
}
// if commandline arg given use it as search path, else use ".."
int main(int argc, char* argv[]) {
char *path = (argc > 1) ? argv[1] : getenv("HOME");
DirTree *top = new DirTree(path,path);
rec_dir(path,top);
Dir_main *mw = new Dir_main(argv[0],400,450);
mw->init();
mw->main_loop();
}
|