16458Sache/* 26458Sache * program: fselect.c 36458Sache * author: Marc van Kempen (wmbfmk@urc.tue.nl) 48858Srgrimes * Desc: File selection routine 56458Sache * 66458Sache * Copyright (c) 1995, Marc van Kempen 76458Sache * 86458Sache * All rights reserved. 96458Sache * 106458Sache * This software may be used, modified, copied, distributed, and 116458Sache * sold, in both source and binary form provided that the above 126458Sache * copyright and these terms are retained, verbatim, as the first 136458Sache * lines of this file. Under no circumstances is the author 146458Sache * responsible for the proper functioning of this software, nor does 156458Sache * the author assume any responsibility for damages incurred with 166458Sache * its use. 178858Srgrimes * 186458Sache */ 196458Sache 206458Sache#include <stdlib.h> 216458Sache#include <unistd.h> 226458Sache#include <sys/param.h> 236458Sache#include <dialog.h> 246458Sache#include "ui_objects.h" 256458Sache#include "dir.h" 266458Sache#include "dialog.priv.h" 276458Sache 288548Sjkh/* 298548Sjkh * Local prototypes 308548Sjkh */ 318548Sjkh 328548Sjkhchar *dialog_dfselect(char *dir, char *fmask, int is_fselect); 338548Sjkh 348858Srgrimes/* 358548Sjkh * Functions 368548Sjkh */ 378548Sjkh 386458Sachevoid 396458Sacheget_directories(DirList *d, int n, char ***names, int *nd) 406458Sache/* 416458Sache * Desc: return the directorienames in <dir> as an array in 426458Sache * <names>, the # of entries in <nd>, memory allocated 436458Sache * to *names should be freed when done with it. 446458Sache */ 456458Sache{ 466458Sache int i; 476458Sache 486458Sache /* count the directories, which are in front */ 496458Sache *nd = 0; 506458Sache while ((*nd < n) && (S_ISDIR(d[*nd].filestatus.st_mode))) (*nd)++; 516458Sache *names = (char **) malloc( *nd * sizeof(char *) ); 526458Sache for (i=0; i<*nd; i++) { 536458Sache (*names)[i] = (char *) malloc( strlen(d[i].filename) + 1); 546458Sache strcpy((*names)[i], d[i].filename); 556458Sache } 566458Sache 576458Sache return; 586458Sache} /* get_directories() */ 596458Sache 606458Sachevoid 616458Sacheget_filenames(DirList *d, int n, char ***names, int *nf) 626458Sache/* 638858Srgrimes * Desc: return the filenames in <dir> as an arry in 646458Sache * <names>, the # of entries in <nf>, memory allocated 656458Sache * to *names should be freed when done. 666458Sache */ 676458Sache{ 686458Sache int nd, i; 696458Sache 706458Sache /* the # of regular files is the total # of files - # of directories */ 716458Sache /* count the # of directories */ 726458Sache nd = 0; 736458Sache while ((nd < n) && (S_ISDIR(d[nd].filestatus.st_mode))) nd++; 746458Sache 756458Sache *names = (char **) malloc( (n-nd) * sizeof(char *) ); 766458Sache *nf = n - nd; 776458Sache for (i=0; i<*nf; i++) { 786458Sache (*names)[i] = (char *) malloc( strlen(d[i+nd].filename) + 1); 796458Sache strcpy((*names)[i], d[i+nd].filename); 806458Sache } 818858Srgrimes 826458Sache return; 836458Sache} /* get_filenames() */ 846458Sache 856458Sachevoid 866458SacheFreeNames(char **names, int n) 876458Sache/* 886458Sache * Desc: free the space occupied by names 896458Sache */ 906458Sache{ 916458Sache int i; 926458Sache 936458Sache /* free the space occupied by names */ 946458Sache for (i=0; i<n; i++) { 956458Sache free(names[i]); 966458Sache } 976458Sache free(names); 986458Sache 996458Sache return; 1006458Sache} /* FreeNames() */ 1016458Sache 1027959Sacheint 1038548Sjkhdialog_dselect_old(void) 1047959Sache/* 1058858Srgrimes * Desc: starting from the current directory, 1068858Srgrimes * choose a new current directory 1077959Sache */ 1087959Sache{ 1097959Sache DirList *d = NULL; 1107959Sache char **names, old_dir[MAXPATHLEN]; 1117959Sache WINDOW *ds_win; 1127959Sache ButtonObj *okbut, *cancelbut; 1137959Sache ListObj *dirs_obj; 1147959Sache StringObj *dir_obj; 1157959Sache char o_dir[MAXPATHLEN]; 1167959Sache struct ComposeObj *obj = NULL; 1178858Srgrimes int n, nd, okbutton, cancelbutton, 1187959Sache quit, cancel, ret; 1197959Sache 1207959Sache ds_win = newwin(LINES-8, COLS-30, 4, 15); 1217959Sache if (ds_win == NULL) { 1228858Srgrimes fprintf(stderr, "\nnewwin(%d,%d,%d,%d) failed, maybe wrong dims\n", 1237959Sache LINES-8, COLS-30, 4, 15); 1247959Sache exit(1); 1257959Sache } 1267959Sache draw_box(ds_win, 0, 0, LINES-8, COLS-30, dialog_attr, border_attr); 1277959Sache wattrset(ds_win, dialog_attr); 1287959Sache mvwaddstr(ds_win, 0, (COLS-30)/2 - 9, " Directory Select "); 1297959Sache draw_shadow(stdscr, 4, 15, LINES-8, COLS-30); 1307959Sache display_helpline(ds_win, LINES-9, COLS-30); 1317959Sache 1327959Sache /* the Directory string input field */ 1337959Sache getcwd(o_dir, MAXPATHLEN); 1347959Sache dir_obj = NewStringObj(ds_win, "Directory:", o_dir, 1, 2, COLS-34, MAXPATHLEN-1); 1357959Sache AddObj(&obj, STRINGOBJ, (void *) dir_obj); 1367959Sache 1377959Sache /* the list of directories */ 1387959Sache get_dir(".", "*", &d, &n); 1397959Sache get_directories(d, n, &names, &nd); 1408858Srgrimes dirs_obj = NewListObj(ds_win, "Directories:", names, o_dir, 5, 2, 1417959Sache LINES-15, COLS-48, nd); 1427959Sache AddObj(&obj, LISTOBJ, (void *) dirs_obj); 1437959Sache 1447959Sache /* the Ok-button */ 1457959Sache okbutton = FALSE; 1468548Sjkh okbut = NewButtonObj(ds_win, "Continue", &okbutton, 7, COLS-45); 1477959Sache AddObj(&obj, BUTTONOBJ, (void *) okbut); 1488858Srgrimes 1497959Sache /* the Cancel-button */ 1507959Sache cancelbutton = FALSE; 1518548Sjkh cancelbut = NewButtonObj(ds_win, "Return", &cancelbutton, 11, COLS-44); 1527959Sache AddObj(&obj, BUTTONOBJ, (void *) cancelbut); 1537959Sache 1547959Sache quit = FALSE; 1557959Sache cancel = FALSE; 1567959Sache strcpy(old_dir, o_dir); 1577959Sache while (!quit) { 1587959Sache ret = PollObj(&obj); 1597959Sache switch(ret) { 1607959Sache case SEL_BUTTON: 1617959Sache if (okbutton) { 1627959Sache quit = TRUE; 1637959Sache } 1647959Sache if (cancelbutton) { 1657959Sache quit = TRUE; 1667959Sache cancel = TRUE; 1677959Sache } 1687959Sache break; 1697959Sache case SEL_CR: 1707959Sache if (strcmp(old_dir, o_dir)) { 1717959Sache /* the directory was changed, cd into it */ 1727959Sache if (chdir(o_dir)) { 1737959Sache dialog_notify("Could not change into directory"); 17422879Sache strcpy(o_dir, old_dir); 1757959Sache } else { 1767959Sache getcwd(o_dir, MAXPATHLEN); 1777959Sache strcpy(old_dir, o_dir); 1787959Sache } 17922879Sache RefreshStringObj(dir_obj); 1808858Srgrimes } 1817959Sache get_dir(".", "*", &d, &n); 1827959Sache FreeNames(names, nd); 1837959Sache get_directories(d, n, &names, &nd); 1847959Sache UpdateListObj(dirs_obj, names, nd); 1857959Sache if (((obj->prev)->obj == (void *) dirs_obj)) { 1867959Sache obj=obj->prev; 1877959Sache } 1887959Sache break; 1897959Sache case SEL_ESC: 1907959Sache quit = TRUE; 1917959Sache cancel = TRUE; 1927959Sache break; 1937959Sache case KEY_F(1): 1947959Sache display_helpfile(); 1957959Sache break; 1967959Sache } 1977959Sache } 1988858Srgrimes 1997959Sache FreeNames(names, nd); 2007959Sache DelObj(obj); 2017959Sache delwin(ds_win); 2027959Sache 2037959Sache return(cancel); 2047959Sache 2057959Sache} /* dialog_dselect() */ 2067959Sache 2078548Sjkhint 2088548Sjkhdialog_dselect(char *dir, char *fmask) 2098548Sjkh/* 2108548Sjkh * Desc: Choose a directory 2118548Sjkh */ 2128548Sjkh{ 2138548Sjkh if (dialog_dfselect(dir, fmask, FALSE)) { 2148548Sjkh return(FALSE); /* esc or cancel was pressed */ 2158548Sjkh } else { 2168548Sjkh return(TRUE); /* directory was selected */ 2178548Sjkh } 2188548Sjkh} /* dialog_dselect() */ 2198548Sjkh 2206458Sachechar * 2216458Sachedialog_fselect(char *dir, char *fmask) 2226458Sache/* 2238548Sjkh * Desc: Choose a file from a directory 2248548Sjkh */ 2258548Sjkh{ 2268548Sjkh return(dialog_dfselect(dir, fmask, TRUE)); 2278548Sjkh} /* dialog_fselect() */ 2288548Sjkh 2298548Sjkhchar * 2308548Sjkhdialog_dfselect(char *dir, char *fmask, int is_fselect) 2318548Sjkh/* 2326458Sache * Desc: choose a file from the directory <dir>, which 2338858Srgrimes * initially display files with the mask <filemask> 2346458Sache * pre: <dir> is the initial directory 2356458Sache * only files corresponding to the mask <fmask> are displayed 2366458Sache * post: returns NULL if no file was selected 2376458Sache * else returns pointer to filename, space is allocated, should 2386458Sache * be freed after use. 2396458Sache */ 2406458Sache{ 2416458Sache DirList *d = NULL; 2426458Sache char msg[512]; 2437959Sache char **fnames, **dnames, *ret_name; 2446458Sache WINDOW *fs_win; 2456458Sache int n, nd, nf, ret; 2466458Sache StringObj *fm_obj, *dir_obj, *sel_obj; 2476458Sache char o_fm[255], o_dir[MAXPATHLEN], o_sel[MAXPATHLEN]; 2486458Sache char old_fmask[255], old_dir[MAXPATHLEN]; 2496458Sache ListObj *dirs_obj, *files_obj; 2506458Sache struct ComposeObj *obj = NULL, *o; 2516458Sache int quit, cancel; 2526458Sache ButtonObj *okbut_obj, *canbut_obj; 2536458Sache int ok_button, cancel_button; 2546458Sache 2556458Sache if (chdir(dir)) { 2566458Sache sprintf(msg, "Could not move into specified directory: %s", dir); 2576458Sache dialog_notify(msg); 2586458Sache return(NULL); 2596458Sache } 2606458Sache getcwd(o_dir, MAXPATHLEN); 2616458Sache 2626458Sache /* setup the fileselect-window and initialize its components */ 2636458Sache fs_win = newwin(LINES-2, COLS-20, 1, 10); 2646458Sache if (fs_win == NULL) { 2656458Sache endwin(); 2668858Srgrimes fprintf(stderr, "\nnewwin(%d,%d,%d,%d) failed, maybe wrong dims\n", 2676458Sache LINES-2, COLS-20, 2, 10); 2686458Sache exit(1); 2696458Sache } 2706458Sache draw_box(fs_win, 0, 0, LINES-2, COLS-20, dialog_attr, border_attr); 2716458Sache wattrset(fs_win, dialog_attr); 2728548Sjkh if (is_fselect) { 2738548Sjkh mvwaddstr(fs_win, 0, (COLS-20)/2 - 7, " File Select "); 2748548Sjkh } else { 2758548Sjkh mvwaddstr(fs_win, 0, (COLS-20)/2 - 9, " Directory Select "); 2768548Sjkh } 2776458Sache draw_shadow(stdscr, 1, 10, LINES-2, COLS-20); 2788548Sjkh display_helpline(fs_win, LINES-3, COLS-20); 2796458Sache 2806458Sache /* Filemask entry */ 2816458Sache strcpy(o_fm, fmask); 2826458Sache fm_obj = NewStringObj(fs_win, "Filemask:", o_fm, 1, 2, 19, 255); 2836458Sache AddObj(&obj, STRINGOBJ, (void *) fm_obj); 2846458Sache 2856458Sache /* Directory entry */ 2866458Sache dir_obj = NewStringObj(fs_win, "Directory:", o_dir, 1, 22, COLS-44, 255); 2876458Sache AddObj(&obj, STRINGOBJ, (void *) dir_obj); 2886458Sache 2896458Sache /* Directory list */ 2906458Sache get_dir(".", fmask, &d, &n); /* read the entire directory */ 2917959Sache get_directories(d, n, &dnames, &nd); /* extract the dir-entries */ 2928548Sjkh if (is_fselect) { 2938858Srgrimes dirs_obj = NewListObj(fs_win, "Directories:", dnames, o_dir, 5, 2, 2948548Sjkh LINES-16, (COLS-20)/2-2, nd); 2958548Sjkh } else { 2968548Sjkh dirs_obj = NewListObj(fs_win, "Directories:", dnames, o_dir, 5, 2, 2978548Sjkh LINES-12, (COLS-20)/2-2, nd); 2988548Sjkh } 2996458Sache AddObj(&obj, LISTOBJ, (void *) dirs_obj); 3006458Sache 3016458Sache /* Filenames list */ 3027959Sache get_filenames(d, n, &fnames, &nf); /* extract the filenames */ 3038548Sjkh if (is_fselect) { 3048548Sjkh files_obj = NewListObj(fs_win, "Files:", fnames, o_sel, 5, (COLS-20)/2+1, 3058548Sjkh LINES-16, (COLS-20)/2-3, nf); 3068548Sjkh } else { 3078548Sjkh files_obj = NewListObj(fs_win, "Files:", fnames, o_sel, 5, (COLS-20)/2+1, 3088548Sjkh LINES-12, (COLS-20)/2-3, nf); 3098548Sjkh } 3106458Sache AddObj(&obj, LISTOBJ, (void *) files_obj); 3116458Sache 3128548Sjkh if (is_fselect) { 3138548Sjkh /* Selection entry */ 3148548Sjkh o_sel[0] = '\0'; 3158548Sjkh sel_obj = NewStringObj(fs_win, "Selection:", o_sel, LINES-10, 2, COLS-24, 255); 3168548Sjkh AddObj(&obj, STRINGOBJ, (void *) sel_obj); 3178548Sjkh } 3186458Sache 3196458Sache /* Ok button */ 3206458Sache ok_button = FALSE; 3216458Sache okbut_obj = NewButtonObj(fs_win, "Ok", &ok_button, LINES-6, 20); 3226458Sache AddObj(&obj, BUTTONOBJ, (void *) okbut_obj); 3236458Sache 3246458Sache /* Cancel button */ 3256458Sache cancel_button = FALSE; 3266458Sache canbut_obj = NewButtonObj(fs_win, "Cancel", &cancel_button, LINES-6, 30); 3276458Sache AddObj(&obj, BUTTONOBJ, (void *) canbut_obj); 3286458Sache 3296458Sache /* Make sure all objects on the window are drawn */ 3306458Sache wrefresh(fs_win); 3316458Sache keypad(fs_win, TRUE); 3326458Sache 3336458Sache /* Start the reading */ 3346458Sache o = obj; 3356458Sache strcpy(old_fmask, o_fm); 3366458Sache strcpy(old_dir, o_dir); 3376458Sache quit = FALSE; 3386458Sache cancel = FALSE; 3396458Sache while (!quit) { 3406458Sache ret = PollObj(&o); 3416458Sache switch(ret) { 3426458Sache case SEL_CR: 3436458Sache if (strcmp(old_fmask, o_fm) || strcmp(old_dir, o_dir)) { 3448858Srgrimes /* reread directory and update the listobjects */ 3456458Sache if (strcmp(old_dir, o_dir)) { /* dir entry was changed */ 3466458Sache if (chdir(o_dir)) { 3476458Sache dialog_notify("Could not change into directory"); 34822879Sache strcpy(o_dir, old_dir); 3496458Sache } else { 3506458Sache getcwd(o_dir, MAXPATHLEN); 3516458Sache strcpy(old_dir, o_dir); 3526458Sache } 35322879Sache RefreshStringObj(dir_obj); 3546458Sache } else { /* fmask entry was changed */ 3556458Sache strcpy(old_fmask, o_fm); 3566458Sache } 3576458Sache get_dir(".", o_fm, &d, &n); 3587959Sache FreeNames(dnames, nd); 3597959Sache get_directories(d, n, &dnames, &nd); 3607959Sache UpdateListObj(dirs_obj, dnames, nd); 3617959Sache FreeNames(fnames, nf); 3627959Sache get_filenames(d, n, &fnames, &nf); 3637959Sache UpdateListObj(files_obj, fnames, nf); 3646458Sache if (((o->prev)->obj == (void *) dirs_obj)) { 3656458Sache o=o->prev; 3666458Sache } 3676458Sache } 3686458Sache break; 3696458Sache case SEL_BUTTON: 3706458Sache /* check which button was pressed */ 3716458Sache if (ok_button) { 3726458Sache quit = TRUE; 3736458Sache } 3746458Sache if (cancel_button) { 3756458Sache quit = TRUE; 3766458Sache cancel = TRUE; 3776458Sache } 3786458Sache break; 3796458Sache case SEL_ESC: 3806458Sache quit = TRUE; 3816458Sache cancel = TRUE; 3826458Sache break; 3836458Sache case KEY_F(1): 3846458Sache case '?': 3856458Sache display_helpfile(); 3866458Sache break; 3876458Sache } 3886458Sache } 3896458Sache DelObj(obj); 3907959Sache FreeNames(dnames, nd); 3917959Sache FreeNames(fnames, nf); 3927959Sache delwin(fs_win); 3936458Sache 3946458Sache if (cancel || (strlen(o_sel) == 0)) { 3956458Sache return(NULL); 3966458Sache } else { 3976458Sache ret_name = (char *) malloc( strlen(o_sel) + 1 ); 3986458Sache strcpy(ret_name, o_sel); 3996458Sache return(ret_name); 4006458Sache } 4016458Sache} /* dialog_fselect() */ 4026458Sache 403