/* dir- and filerequester Written by Matthias Hensler Copyright WSPse 1999+2000 eMail: wsp@gmx.de Created: 2000/01/24 Updated: 2000/02/28 */ /* Copying: This program is free software; you can redistribute it and/or modify it under the terms of the GNU Gerneral Public License as published by the Free Soft- ware Foundation; either version 2 of License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILTY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* Requester (Dir and File) for ncurses-library - V2 * Written by Matthias Hensler * (C) WSPse 2000 * Licenced under GNU General Public Licence * * Interface: * char *req_get_dir (const char *path) * if(path == NULL) -> homedirectory will be used * returnvalue is dirname, or NULL if user quit * * char *req_get_file (const char *path) * if(path == NULL) -> homedirectory will be used * returnvalue is filename with complete path, or NULL if user quit * * Before calling get_dir/get_file, ncurses must be initialised (eg. initsrc(), * start_color(), cbreak(), etc). get_dir uses own window, you should * rebuild your windows after get_dir exits. */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include "mp3creat.h" #ifdef HAVE_DIRENT_H #include #endif #ifdef HAVE_SYS_STAT_H #include #endif #ifdef HAVE_SYS_TYPES_H #include #endif #ifdef HAVE_SYS_WAIT_H #include #endif extern WINDOW *c_newwin(int h, int l, int y, int x, void *proc, int arg1, int arg2); extern void c_delwin(WINDOW *win); extern void wuuush(int); extern char *input_line(int y_line, char *def_str, char *usage_str, BOOL select); extern void popup_error_win(char *tx); extern char *input_line2(int y_line, char *def_str, char *usage_str, char *des1, char *des2, char *des3, char *des4, char *des5, char *des6, BOOL select); extern char *file_glob_out_name(char *name); extern char *file_glob_in_name(char *name); extern char *kill_double_slashs(char *string); extern char *copy_char_str(char *old); extern BOOL config_curs_dir; extern BOOL config_req_hidden; typedef struct _content { char *name; struct _content *prev; struct _content *next; } content; BOOL req_refresh_needed = FALSE; /* build complete filename from current directory */ char *req_correct_dir(char *in_file) { char *cwd_name, *pat; /* if none file is given, just return */ if(! in_file) return NULL; if(*in_file != '/') { cwd_name = getcwd(NULL, 0); if(! cwd_name) { popup_error_win(_("getcwd() does not work")); free(in_file); in_file = NULL; return NULL; } pat = (char *) malloc(sizeof(char) * (strlen(in_file) + strlen(cwd_name) + 2)); if(! pat) { wuuush(1); } sprintf(pat, "%s/%s", cwd_name, in_file); free(cwd_name); free(in_file); cwd_name = NULL; in_file = NULL; in_file = pat; } in_file = kill_double_slashs(in_file); while(1) { cwd_name = strstr(in_file, "/./"); if(! cwd_name) break; memmove(cwd_name, cwd_name+2, strlen(cwd_name)-1); } while(1) { cwd_name = strstr(in_file, "/../"); if(! cwd_name) break; *cwd_name = 0; pat = strrchr(in_file, '/'); if(! pat) { popup_error_win(_("illegal directoryname")); free(in_file); in_file = NULL; return NULL; } memmove(pat, cwd_name+3, strlen(cwd_name+1)-1); } return in_file; } /* free content list */ void req_free_content_list(content **list) { content *curr, *next; curr = *list; while(curr) { if(curr->name) free(curr->name); next = curr; curr = curr->next; free(next); } *list = NULL; } /* insert a new entry into content list */ void req_insert_content(content *new, content **data) { content *curr, *next; curr = *data; if((! curr) || strcmp(new->name, curr->name) < 0) { new->next = curr; if(curr) curr->prev = new; *data = new; } else { next = curr->next; while(next && strcmp(new->name, next->name) > 0) { curr = next; next = next->next; } new->next = next; if(next) next->prev = new; new->prev = curr; curr->next = new; } } /* read data **file_data might be NULL, if only directorys are requested */ int req_read_dir_data(const char *path, content **dir_data, int *dir_count, content **file_data, int *file_count, BOOL hidden, char *old_dir_name, content **old_dir, BOOL *dir_found) { DIR *direc; struct stat st; struct dirent *de; content *new; char *name; *dir_count = 0; *file_count = 0; *dir_data = NULL; *dir_found = FALSE; if(file_data) *file_data = NULL; direc = opendir(path); if(! direc) return 1; while((de = readdir(direc)) != NULL) { /* skip "." and ".." */ if((strcmp(de->d_name, ".") != 0) && (strcmp(de->d_name, "..") != 0) && ((de->d_name[0] != '.') || hidden)) { name = (char *) malloc(sizeof(char) * (strlen(path) + strlen(de->d_name) + 2)); if(! name) { wuuush(1); } sprintf(name, "%s/%s", path, de->d_name); if(stat(name, &st) != -1) { if(S_ISDIR(st.st_mode)) { /* handle directory entry */ new = (content *) malloc(sizeof(content)); if(! new) { wuuush(1); } new->name = copy_char_str(de->d_name); new->next = NULL; new->prev = NULL; if(old_dir_name && (strcmp(de->d_name, old_dir_name) == 0)) { *old_dir = new; *dir_found = TRUE; } req_insert_content(new, &(*dir_data)); (*dir_count)++; } else if(file_data) { /* handle file entry */ new = (content *) malloc(sizeof(content)); if(! new) { wuuush(1); } new->name = copy_char_str(de->d_name); new->next = NULL; new->prev = NULL; req_insert_content(new, &(*file_data)); (*file_count)++; } } free(name); name = NULL; } } closedir(direc); if(strcmp(path, "/") != 0) { /* not root dir, so insert dir-up points */ new = (content *) malloc(sizeof(content)); if(! new) { wuuush(1); } new->name = copy_char_str(".."); new->next = *dir_data; if(new->next) new->next->prev = new; new->prev = NULL; *dir_data = new; (*dir_count)++; } return 0; } /* draw statusline win = window ys = first useable y-position ye = last useable y-position x = x-position abs = absolute position in list rel = relative position tot = total entries */ void req_draw_stat(WINDOW *win, int ys, int ye, int x, int abs, int rel, int tot) { int i, y1, y2, yb; yb = (ye-ys) + 1; if(yb >= tot) { wmove(win, ys, x); wvline(win, ACS_VLINE, yb); return; } ys--; if(! tot) { y1 = 0; y2 = 0; rel = 0; } else { y1 = (abs * yb) / tot; y2 = y1 + ((yb*yb) / tot) + 1; y1++; if(y2 > yb) y1 = (yb - (y2-y1)); if(tot <= yb) { rel = (yb*rel) / tot; } else { rel = y1 + ((((yb*yb)/tot)*rel)/yb); } if(rel < y1) rel = y1; if(rel > y2) rel = y2; if(rel < 1) rel = 1; if(rel > yb) rel = yb; } for(i=1;i<=yb;i++) { if((i>=y1) && (i<=y2)) mvwaddch(win, ys+i, x, ACS_BLOCK); else mvwaddch(win, ys+i, x, ACS_VLINE); if(i == rel) mvwaddch(win, ys+i, x, ACS_BOARD); } } /* mark one line win = window y = line xe = last useable x-position name= file name ch = color */ void req_draw_mark(WINDOW *win, int y, int xe, char *name, const chtype ch) { int i; chtype old_ch; old_ch = getbkgd(win); if(ch == A_REVERSE) { wbkgdset(win, COLOR_PAIR(3)); } else { wbkgdset(win, old_ch ^ ch); } if(name) { i = strlen(name); if(i > xe) i = xe; mvwaddnstr(win, y, 1, name, i); } else { i = 0; } for(;i