diff options
author | wiktor w brodlo <wiktor@brodlo.net> | 2011-06-15 16:59:54 +0000 |
---|---|---|
committer | wiktor w brodlo <wiktor@brodlo.net> | 2011-06-15 16:59:54 +0000 |
commit | 2590d96369d0217e31dc2812690dde61dac417b5 (patch) | |
tree | 82276f787b08a28548e342c7921486f1acefab9f /loader/dirbrowser.c | |
parent | first commit (diff) | |
download | anaconda-2590d96369d0217e31dc2812690dde61dac417b5.tar.gz anaconda-2590d96369d0217e31dc2812690dde61dac417b5.tar.bz2 anaconda-2590d96369d0217e31dc2812690dde61dac417b5.zip |
Initial import from Sabayon (ver 0.9.9.56)
Diffstat (limited to 'loader/dirbrowser.c')
-rw-r--r-- | loader/dirbrowser.c | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/loader/dirbrowser.c b/loader/dirbrowser.c new file mode 100644 index 0000000..9199850 --- /dev/null +++ b/loader/dirbrowser.c @@ -0,0 +1,199 @@ +/* + * dirbrowser.c - newt-based directory browser to get a file name + * + * Copyright (C) 2004 Red Hat, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the 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 + * MERCHANTABILITY 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, see <http://www.gnu.org/licenses/>. + * + * Author(s): Jeremy Katz <katzj@redhat.com> + */ + +#include <newt.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include <sys/types.h> +#include <dirent.h> +#include <errno.h> +#include <string.h> +#include <sys/stat.h> + +#ifndef STANDALONE +#include "../isys/log.h" + +#include "loader.h" +#include "loadermisc.h" +#include "lang.h" +#endif + +#ifdef STANDALONE +#define _(x) x + +static int simpleStringCmp(const void * a, const void * b) { + const char * first = *((const char **) a); + const char * second = *((const char **) b); + + return strcmp(first, second); +} +#endif + +#define FSTEP 10 + +static char ** get_file_list(char * dirname, + int (*filterfunc)(char *, struct dirent *)) { + DIR * dir; + struct dirent *entry; + char ** files; + int numfiles = FSTEP, i = 0; + + dir = opendir(dirname); + if (dir == NULL) { + fprintf(stderr, "error opening %s: %m", dirname); + return NULL; + } + + files = malloc(numfiles * sizeof(char *)); + + while ((entry = readdir(dir))) { + if ((strlen(entry->d_name) == 1) && !strncmp(entry->d_name, ".", 1)) + continue; + if ((strlen(entry->d_name) == 2) && !strncmp(entry->d_name, "..", 2)) + continue; + if (filterfunc && filterfunc(dirname, entry)) + continue; + + files[i] = strdup(entry->d_name); + if (i++ >= (numfiles - 1)) { + numfiles += FSTEP; + files = realloc(files, numfiles * sizeof(char *)); + } + } + files[i] = NULL; + closedir(dir); + + qsort(files, i, sizeof(*files), simpleStringCmp); + return files; +} + +/* Browse through a directory structure looking for a file. + * Returns the full path to the file. + * + * Parameters: + * title: Title for newt dialog window + * dirname: Directory to use for root of browsing. NOTE: you cannot go + * up above this root. + * filterfunc: An (optional) function to filter out files based on whatever + * criteria you want. Returns 1 if it passes, 0 if not. + * Function should take arguments of the directory name and + * the dirent for the file. + */ +char * newt_select_file(char * title, char * text, char * dirname, + int (*filterfunc)(char *, struct dirent *)) { + char ** files; + char * fn = NULL; + int i, done = 0; + char * topdir = dirname; + char * dir = malloc(PATH_MAX); + char * path = NULL; + newtGrid grid, buttons; + newtComponent f, tb, listbox, ok, cancel; + struct stat sb; + struct newtExitStruct es; + + dir = realpath(dirname, dir); + + do { + files = get_file_list(dir, filterfunc); + + f = newtForm(NULL, NULL, 0); + grid = newtCreateGrid(1, 4); + + tb = newtTextboxReflowed(-1, -1, text, 60, 0, 10, 0); + + listbox = newtListbox(12, 65, 10, + NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT); + + newtListboxSetWidth(listbox, 55); + buttons = newtButtonBar(_("OK"), &ok, _("Cancel"), &cancel, NULL); + newtGridSetField(grid, 0, 0, NEWT_GRID_COMPONENT, tb, + 0, 0, 0, 1, 0, 0); + newtGridSetField(grid, 0, 1, NEWT_GRID_COMPONENT, listbox, + 0, 0, 0, 1, 0, 0); + newtGridSetField(grid, 0, 3, NEWT_GRID_SUBGRID, buttons, + 0, 0, 0, 0, 0, NEWT_GRID_FLAG_GROWX); + + /* if this isn't our topdir, we want to let them go up a dir */ + if (strcmp(topdir, dir)) + newtListboxAppendEntry(listbox, "../", ".."); + + for (i = 0; (files[i] != NULL); i++) { + if ((files[i] == NULL) || (strlen(files[i]) == 0)) continue; + path = malloc(strlen(files[i]) + strlen(dir) + 2); + sprintf(path, "%s/%s", dir, files[i]); + stat(path, &sb); + free(path); + if (S_ISDIR(sb.st_mode)) { + char *dir = malloc(strlen(files[i]) + 2); + sprintf(dir, "%s/", files[i]); + newtListboxAppendEntry(listbox, dir, files[i]); + } else { + newtListboxAppendEntry(listbox, files[i], files[i]); + } + } + + newtGridWrappedWindow(grid, title); + newtGridAddComponentsToForm(grid, f, 1); + newtFormRun(f, &es); + + if (es.reason == NEWT_EXIT_COMPONENT && es.u.co == cancel) { + fn = NULL; + done = -1; + } else { + fn = (char *) newtListboxGetCurrent(listbox); + path = malloc(strlen(fn) + strlen(dir) + 2); + sprintf(path, "%s/%s", dir, fn); + + stat(path, &sb); + if (!S_ISDIR(sb.st_mode)) { + fn = path; + done = 1; + } else { + dir = realpath(path, dir); + free(path); + } + } + + newtGridFree(grid, 1); + newtFormDestroy(f); + newtPopWindow(); + } while (done == 0); + + return fn; +} + +#ifdef STANDALONE +int main(int argc, char ** argv) { + char * foo; + + newtInit(); + newtCls(); + + foo = newt_select_file("Get File Name", "foo, blah blah blah", + "/etc", NULL); + newtFinished(); + printf("got %s\n", foo); + return 0; +} +#endif |