diff --git a/requesters/dos13.c b/requesters/dos13.c index 6989d5e..29690ed 100644 --- a/requesters/dos13.c +++ b/requesters/dos13.c @@ -11,6 +11,7 @@ extern struct Library *DOSBase; + /* accessing the list of logical volumes is hairy under AmigaOS 1.x - it is "hidden" in the DosBase structure, and shared among all tasks. @@ -26,7 +27,7 @@ extern struct Library *DOSBase; For now, we will omit device typed entries, because writing/reading to them usually doesn't make too much sense. */ -struct FileListEntry *scan_dir(const char *dirpath, int *num_entries) +static struct FileListEntry *all_volumes(int *num_entries) { struct DosLibrary *dosbase = (struct DosLibrary *) DOSBase; Forbid(); @@ -57,37 +58,60 @@ struct FileListEntry *scan_dir(const char *dirpath, int *num_entries) current = BADDR(current->dvi_Next); } Permit(); - /* scan current directory */ - /* - on AmigaOS versions before 36 (essentially all 1.x versions), the - function GetCurrentDirName() does not exist, but it's obtainable - by calling Cli() and querying the returned CommandLineInterface - structure - */ - /* - puts("scanning directory..."); - // on AmigaOS 1.x, this function does not exist !!! - GetCurrentDirName(dirname, PATHBUFFER_SIZE); - printf("current dir: '%s'\n", dirname); - flock = Lock(dirname, SHARED_LOCK); + *num_entries = n; + /* The result is an unsorted list, which is usually not what we want. + TODO: sort the list + */ + return result; +} + +static struct FileListEntry *dir_contents(const char *dirpath, int *num_entries) +{ + struct FileInfoBlock fileinfo; + struct FileListEntry *cur_entry = NULL, *result = NULL, *tmp; + int n = 0; + + BPTR flock = Lock(dirpath, SHARED_LOCK); if (Examine(flock, &fileinfo)) { while (ExNext(flock, &fileinfo)) { - print_fileinfo(&fileinfo); + tmp = calloc(1, sizeof(struct FileListEntry)); + if (fileinfo.fib_DirEntryType < 0) tmp->file_type = FILETYPE_FILE; + else if (fileinfo.fib_DirEntryType > 0) tmp->file_type = FILETYPE_DIR; + else tmp->file_type = FILETYPE_VOLUME; + tmp->index = n; + strncpy(tmp->name, fileinfo.fib_FileName, MAX_FILENAME_LEN); + + if (!cur_entry) result = cur_entry = tmp; + else { + cur_entry->next = tmp; + tmp->prev = cur_entry; + cur_entry = tmp; + } + n++; } - error = IoErr(); + LONG error = IoErr(); if (error != ERROR_NO_MORE_ENTRIES) { puts("unknown I/O error, TODO handle"); } } UnLock(flock); - */ - /* The result is an unsorted list, which is usually not what we want. - TODO: sort the list - */ *num_entries = n; return result; } +/* + scan current directory + on AmigaOS versions before 36 (essentially all 1.x versions), the + function GetCurrentDirName() does not exist, but it's obtainable + by calling Cli() and querying the returned CommandLineInterface + structure +*/ +struct FileListEntry *scan_dir(const char *dirpath, int *num_entries) +{ + if (!dirpath) return all_volumes(num_entries); + return dir_contents(dirpath, num_entries); +} + void free_file_list(struct FileListEntry *entries) { struct FileListEntry *cur = entries, *next; diff --git a/requesters/filereq.c b/requesters/filereq.c index b19b4c6..a5c29be 100644 --- a/requesters/filereq.c +++ b/requesters/filereq.c @@ -41,7 +41,6 @@ static int filelist_bm_width; static int filelist_bm_height; static struct FileListEntry *current_files; static int num_current_files; -static int select_index = 1; static int slider_increment; /* @@ -225,23 +224,8 @@ static int filelist_bm_depth = 1; static struct BitMap filelist_bitmap; static struct RastPort filelist_rastport; -#define PATHBUFFER_SIZE 200 -static char dirname[PATHBUFFER_SIZE + 1]; -static BPTR flock; -static LONG error; -static struct FileInfoBlock fileinfo; - static UWORD font_baseline, font_height; -static void print_fileinfo(struct FileInfoBlock *fileinfo) -{ - if (fileinfo->fib_DirEntryType > 0) { - printf("dir: '%s'\n", fileinfo->fib_FileName); - } else { - printf("file: '%s'\n", fileinfo->fib_FileName); - } -} - static void close_requester() { if (req_opened) { @@ -350,8 +334,6 @@ static void draw_list() cur = cur->next; count++; } - - // Done drawing, offscreen bitmap is rendered, copy to the requester's layer render_list_backbuffer(); } @@ -379,6 +361,38 @@ static void update_string_gadgets(struct FileListEntry *entry) RefreshGList(&dir_text, req_window, &requester, 1); } +static void reload_file_list(const char *dirpath) +{ + int num_files; + struct FileListEntry *dir_entries = scan_dir(dirpath, &num_files); + if (current_files) free_file_list(current_files); + current_files = dir_entries; + num_current_files = num_files; + first_visible_entry = current_files; + clear_list(); + draw_list(); + + // set the length of the slider thumb according to the current file list + int vertbody = MAXBODY; + int vertpot = MAXBODY; + if (num_current_files > NUM_FILE_ENTRIES) { + // because we can only use integer division, so we have to determine + // the body size by solving the equation + // MAXBODY / vertbody = num_current_files / NUM_FILE_ENTRIES + vertbody = (MAXBODY * NUM_FILE_ENTRIES) / num_current_files; + + // this is surprisingly different that I thought: + // we need to compute the increment over the drag space not over + // the vslider space, so we can ignore the VertBody setting (in short + // VertPot and VertBody are independent) + slider_increment = MAXBODY / (num_current_files - NUM_FILE_ENTRIES); + vertpot = first_visible_entry->index * slider_increment; + printf("vpot: %d, vbody: %d inc: %d\n", vertpot, vertbody, slider_increment); + } + NewModifyProp(&list_vslider, req_window, &requester, AUTOKNOB | FREEVERT, + 0, vertpot, MAXBODY, vertbody, 1); +} + static void handle_events() { BOOL done = FALSE; @@ -442,6 +456,9 @@ static void handle_events() update_string_gadgets(entry); } else if (entry != NULL && is_doubleclick) { printf("double click on: %s\n", entry->name); + if (entry->file_type == FILETYPE_VOLUME || entry->file_type == FILETYPE_DIR) { + reload_file_list(entry->name); + } } } ReplyMsg((struct Message *) msg); @@ -591,30 +608,10 @@ void open_file(struct Window *window) filelist_rastport.BitMap = &filelist_bitmap; if (req_opened = Request(&requester, req_window)) { - current_files = scan_dir(NULL, &num_current_files); - first_visible_entry = current_files; - // set the length of the slider thumb according to the current file list - int vertbody = MAXBODY; - int vertpot = MAXBODY; - if (num_current_files > NUM_FILE_ENTRIES) { - // because we can only use integer division, so we have to determine - // the body size by solving the equation - // MAXBODY / vertbody = num_current_files / NUM_FILE_ENTRIES - vertbody = (MAXBODY * NUM_FILE_ENTRIES) / num_current_files; - - // this is surprisingly different that I thought: - // we need to compute the increment over the drag space not over - // the vslider space, so we can ignore the VertBody setting (in short - // VertPot and VertBody are independent) - slider_increment = MAXBODY / (num_current_files - NUM_FILE_ENTRIES); - vertpot = first_visible_entry->index * slider_increment; - printf("vpot: %d, vbody: %d inc: %d\n", vertpot, vertbody, slider_increment); - } - NewModifyProp(&list_vslider, req_window, &requester, AUTOKNOB | FREEVERT, - 0, vertpot, MAXBODY, vertbody, 1); - draw_list(); + reload_file_list(NULL); handle_events(); free_file_list(current_files); + current_files = first_visible_entry = NULL; CloseWindow(req_window); req_window = NULL; } else {