| author | Jens Thoms Toerring <jt@toerring.de> | 2015年03月14日 22:29:07 +0100 |
|---|---|---|
| committer | Jens Thoms Toerring <jt@toerring.de> | 2015年03月14日 22:29:07 +0100 |
| commit | 21aa9a88ab461a71f40b2ed2202d77d7c289c3b6 (patch) | |
| tree | c942a75419cc51560dd6094f70549ebee53a98ff | |
| parent | cca9dbdbaed4e37f37a763bea2d1e3b714f5c971 (diff) | |
| download | xforms-21aa9a88ab461a71f40b2ed2202d77d7c289c3b6.tar.gz | |
| -rw-r--r-- | demos/dirlist.c | 11 | ||||
| -rwxr-xr-x | demos/positioner_overlay | 228 | ||||
| -rw-r--r-- | doc/part1_goodies.texi | 29 | ||||
| -rw-r--r-- | lib/fselect.c | 24 | ||||
| -rw-r--r-- | lib/listdir.c | 229 |
diff --git a/demos/dirlist.c b/demos/dirlist.c index 931e56e..c03a265 100644 --- a/demos/dirlist.c +++ b/demos/dirlist.c @@ -53,16 +53,15 @@ fill_browser( FL_OBJECT * ob ) fl_set_object_label( fdui->total, buf ); fl_clear_browser( fdui->browser ); - for ( ds = dl; dl < dlend; dl++ ) + for ( ds = dl; ds < dlend; ds++ ) { - sprintf( buf, "%-10s\t\t%5ldK\t%s", dl->name, dl->dl_size >> 10, - ctime( &dl->dl_mtime ) + 3 ); + sprintf( buf, "%-20s\t\t%5ldK\t%s", ds->name, ds->dl_size >> 10, + ctime( &ds->dl_mtime ) + 3 ); fl_addto_browser_chars( fdui->browser, buf ); } + fl_free_dirlist( dl ); fl_unfreeze_form( ob->form ); - - fl_free_dirlist( ( FL_Dirlist * ) ds ); } @@ -101,7 +100,7 @@ main( int argc, { FD_fbform *fd_fbform; - fl_initialize( &argc, argv, 0, 0, 0 ); + fl_initialize( &argc, argv, "FormDemo", NULL, 0 ); fd_fbform = create_form_fbform( ); fl_set_browser_fontstyle( fd_fbform->browser, FL_FIXED_STYLE ); diff --git a/demos/positioner_overlay b/demos/positioner_overlay deleted file mode 100755 index 0852d87..0000000 --- a/demos/positioner_overlay +++ /dev/null @@ -1,228 +0,0 @@ -#! /bin/bash - -# positioner_overlay - temporary wrapper script for .libs/positioner_overlay -# Generated by libtool (GNU libtool) 2.4.2 Debian-2.4.2-1ubuntu1 -# -# The positioner_overlay program cannot be directly executed until all the libtool -# libraries that it depends on are installed. -# -# This wrapper script should never be moved out of the build directory. -# If it is, it will not operate correctly. - -# Sed substitution that helps us do robust quoting. It backslashifies -# metacharacters that are still active within double-quoted strings. -sed_quote_subst='s/\([`"$\\]\)/\\1円/g' - -# Be Bourne compatible -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then - emulate sh - NULLCMD=: - # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' - setopt NO_GLOB_SUBST -else - case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac -fi -BIN_SH=xpg4; export BIN_SH # for Tru64 -DUALCASE=1; export DUALCASE # for MKS sh - -# The HP-UX ksh and POSIX shell print the target directory to stdout -# if CDPATH is set. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - -relink_command="(cd /home/jens/Programming/XForms/xforms/demos; { test -z \"\${LIBRARY_PATH+set}\" || unset LIBRARY_PATH || { LIBRARY_PATH=; export LIBRARY_PATH; }; }; { test -z \"\${COMPILER_PATH+set}\" || unset COMPILER_PATH || { COMPILER_PATH=; export COMPILER_PATH; }; }; { test -z \"\${GCC_EXEC_PREFIX+set}\" || unset GCC_EXEC_PREFIX || { GCC_EXEC_PREFIX=; export GCC_EXEC_PREFIX; }; }; { test -z \"\${LD_RUN_PATH+set}\" || unset LD_RUN_PATH || { LD_RUN_PATH=; export LD_RUN_PATH; }; }; LD_LIBRARY_PATH=:/home/jens/Programming/P/Yaba/yaba/; export LD_LIBRARY_PATH; PATH=/home/jens/Tools/Android/adt/sdk/tools:/home/jens/Tools/Android/adt/sdk/platform-tools:/home/jens/bin:/usr/local/bin:/usr/bin:/bin:/usr/games:/home/jens/bin:/sbin; export PATH; gcc -g -O0 -W -Wall -o \$progdir/\$file positioner_overlay.o ../lib/.libs/libforms.so -lSM -lICE -lc -lm -Wl,-rpath -Wl,/home/jens/Programming/XForms/xforms/lib/.libs)" - -# This environment variable determines our operation mode. -if test "$libtool_install_magic" = "%%%MAGIC variable%%%"; then - # install mode needs the following variables: - generated_by_libtool_version='2.4.2' - notinst_deplibs=' ../lib/libforms.la' -else - # When we are sourced in execute mode, $file and $ECHO are already set. - if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then - file="0ドル" - -# A function that is used when there is no print builtin or printf. -func_fallback_echo () -{ - eval 'cat <<_LTECHO_EOF -1ドル -_LTECHO_EOF' -} - ECHO="printf %s\\n" - fi - -# Very basic option parsing. These options are (a) specific to -# the libtool wrapper, (b) are identical between the wrapper -# /script/ and the wrapper /executable/ which is used only on -# windows platforms, and (c) all begin with the string --lt- -# (application programs are unlikely to have options which match -# this pattern). -# -# There are only two supported options: --lt-debug and -# --lt-dump-script. There is, deliberately, no --lt-help. -# -# The first argument to this parsing function should be the -# script's ../libtool value, followed by no. -lt_option_debug= -func_parse_lt_options () -{ - lt_script_arg0=0ドル - shift - for lt_opt - do - case "$lt_opt" in - --lt-debug) lt_option_debug=1 ;; - --lt-dump-script) - lt_dump_D=`$ECHO "X$lt_script_arg0" | /bin/sed -e 's/^X//' -e 's%/[^/]*$%%'` - test "X$lt_dump_D" = "X$lt_script_arg0" && lt_dump_D=. - lt_dump_F=`$ECHO "X$lt_script_arg0" | /bin/sed -e 's/^X//' -e 's%^.*/%%'` - cat "$lt_dump_D/$lt_dump_F" - exit 0 - ;; - --lt-*) - $ECHO "Unrecognized --lt- option: '$lt_opt'" 1>&2 - exit 1 - ;; - esac - done - - # Print the debug banner immediately: - if test -n "$lt_option_debug"; then - echo "positioner_overlay:positioner_overlay:${LINENO}: libtool wrapper (GNU libtool) 2.4.2 Debian-2.4.2-1ubuntu1" 1>&2 - fi -} - -# Used when --lt-debug. Prints its arguments to stdout -# (redirection is the responsibility of the caller) -func_lt_dump_args () -{ - lt_dump_args_N=1; - for lt_arg - do - $ECHO "positioner_overlay:positioner_overlay:${LINENO}: newargv[$lt_dump_args_N]: $lt_arg" - lt_dump_args_N=`expr $lt_dump_args_N + 1` - done -} - -# Core function for launching the target application -func_exec_program_core () -{ - - if test -n "$lt_option_debug"; then - $ECHO "positioner_overlay:positioner_overlay:${LINENO}: newargv[0]: $progdir/$program" 1>&2 - func_lt_dump_args ${1+"$@"} 1>&2 - fi - exec "$progdir/$program" ${1+"$@"} - - $ECHO "0ドル: cannot exec $program $*" 1>&2 - exit 1 -} - -# A function to encapsulate launching the target application -# Strips options in the --lt-* namespace from $@ and -# launches target application with the remaining arguments. -func_exec_program () -{ - case " $* " in - *\ --lt-*) - for lt_wr_arg - do - case $lt_wr_arg in - --lt-*) ;; - *) set x "$@" "$lt_wr_arg"; shift;; - esac - shift - done ;; - esac - func_exec_program_core ${1+"$@"} -} - - # Parse options - func_parse_lt_options "0ドル" ${1+"$@"} - - # Find the directory that this script lives in. - thisdir=`$ECHO "$file" | /bin/sed 's%/[^/]*$%%'` - test "x$thisdir" = "x$file" && thisdir=. - - # Follow symbolic links until we get to the real thisdir. - file=`ls -ld "$file" | /bin/sed -n 's/.*-> //p'` - while test -n "$file"; do - destdir=`$ECHO "$file" | /bin/sed 's%/[^/]*$%%'` - - # If there was a directory component, then change thisdir. - if test "x$destdir" != "x$file"; then - case "$destdir" in - [\\/]* | [A-Za-z]:[\\/]*) thisdir="$destdir" ;; - *) thisdir="$thisdir/$destdir" ;; - esac - fi - - file=`$ECHO "$file" | /bin/sed 's%^.*/%%'` - file=`ls -ld "$thisdir/$file" | /bin/sed -n 's/.*-> //p'` - done - - # Usually 'no', except on cygwin/mingw when embedded into - # the cwrapper. - WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=no - if test "$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR" = "yes"; then - # special case for '.' - if test "$thisdir" = "."; then - thisdir=`pwd` - fi - # remove .libs from thisdir - case "$thisdir" in - *[\\/].libs ) thisdir=`$ECHO "$thisdir" | /bin/sed 's%[\\/][^\\/]*$%%'` ;; - .libs ) thisdir=. ;; - esac - fi - - # Try to get the absolute directory name. - absdir=`cd "$thisdir" && pwd` - test -n "$absdir" && thisdir="$absdir" - - program=lt-'positioner_overlay' - progdir="$thisdir/.libs" - - if test ! -f "$progdir/$program" || - { file=`ls -1dt "$progdir/$program" "$progdir/../$program" 2>/dev/null | /bin/sed 1q`; \ - test "X$file" != "X$progdir/$program"; }; then - - file="$$-$program" - - if test ! -d "$progdir"; then - mkdir "$progdir" - else - rm -f "$progdir/$file" - fi - - # relink executable if necessary - if test -n "$relink_command"; then - if relink_command_output=`eval $relink_command 2>&1`; then : - else - printf %s\n "$relink_command_output" >&2 - rm -f "$progdir/$file" - exit 1 - fi - fi - - mv -f "$progdir/$file" "$progdir/$program" 2>/dev/null || - { rm -f "$progdir/$program"; - mv -f "$progdir/$file" "$progdir/$program"; } - rm -f "$progdir/$file" - fi - - if test -f "$progdir/$program"; then - if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then - # Run the actual program with our arguments. - func_exec_program ${1+"$@"} - fi - else - # The program doesn't exist. - $ECHO "0ドル: error: \`$progdir/$program' does not exist" 1>&2 - $ECHO "This script is just a wrapper for $program." 1>&2 - $ECHO "See the libtool documentation for more information." 1>&2 - exit 1 - fi -fi diff --git a/doc/part1_goodies.texi b/doc/part1_goodies.texi index a12b395..bbce1ef 100644 --- a/doc/part1_goodies.texi +++ b/doc/part1_goodies.texi @@ -79,7 +79,7 @@ can only be removed programmatically @findex fl_hide_oneliner() @anchor{fl_hide_oneliner()} @example -void fl_show_oneliner(const char *str, FL_Coord x, FL_Coord y); +void fl_show_oneliner(const char *str, FL_COORD x, FL_COORD y); void fl_hide_oneliner(void); @end example @noindent @@ -885,9 +885,12 @@ on return is the total number of entries in directory @code{dirname} that match the pattern specified by @code{pattern} (not exactly true, see below). The function returns the address of an array of type @code{FL_Dirlist} with @code{nfiles} if successful and @code{NULL} -otherwise. By default, directory entries are cached. Passing the -function a true (non-zero) value for the @code{rescan} argument requests -a re-read. +otherwise. By default, directory entries are cached, i.e. when called +with the same arguments for @code{dirname} and @code{pattern} again +the exact same list is usually returned (and no checks are done if +any files have been added or removed in the mean time). By passing +the function a true (non-zero) value for the @code{rescan} argument +requests a re-read, whch then returns @code{FL_Dirlist} is a structure defined as follows @example @@ -901,9 +904,11 @@ typedef struct @{ @noindent where @code{type} is one of the following file types @table @code +@tindex FT_REG +@item FT_REG +a regular file (note: in older versions instead @tindex FT_FILE -@item FT_FILE -a regular file +@code{FT_FILE} was used!) @tindex FT_DIR @item FT_DIR a directory @@ -926,18 +931,18 @@ a character device ? @end table -To free the list cache returned by @code{@ref{fl_get_dirlist()}}, use -the following call +Once you're done with the directory list obtained from +@code{@ref{fl_get_dirlist()}} you must free it, using the following +call: @findex fl_free_dirlist() @anchor{fl_free_dirlist()} @example void fl_free_dirlist(const FL_Dirlist *dl); @end example @noindent -Note that a cast may be required to get rid of compiler warnings due -to the @code{const} qualifier of the return value of -@code{@ref{fl_get_dirlist()}}. See demo program @file{dirlist.c} for -an example use of @code{@ref{fl_get_dirlist()}}. +Of course, the argument passed to @code{@ref{fl_free_dirlist()}} must +be a pointer you obtained from a call of @code{@ref{fl_get_dirlist()}}. +See demo program @file{dirlist.c} for an example use of these functions. Per default not all types of files are returned by @code{@ref{fl_get_dirlist()}}. The specific rules for which diff --git a/lib/fselect.c b/lib/fselect.c index 3ab51b6..e522080 100644 --- a/lib/fselect.c +++ b/lib/fselect.c @@ -102,7 +102,7 @@ typedef struct static FD_fselect * create_form_fselect( void ); -static FD_fselect *fd_fselector[ FL_MAX_FSELECTOR ] = { 0 }, +static FD_fselect *fd_fselector[ FL_MAX_FSELECTOR ] = { NULL }, *fs; @@ -298,7 +298,11 @@ fli_del_tail_slash( char * d ) { int i = strlen( d ) - 1; +#ifndef FL_WIN32 if ( d[ i ] == '/' ) +#else + if ( d[ i ] == '/' || d[ i ] == '\\' ) +#endif d[ i ] = '0円'; return d; } @@ -317,17 +321,19 @@ select_cb( FL_OBJECT * obj, char seltext[ FL_PATH_MAX ]; int thisline; FD_fselect *lfs = obj->form->fdui; + int is_dir; if ( ( thisline = fl_get_browser( obj ) ) <= 0 ) return; fli_sstrcpy( seltext, fl_get_browser_line( obj, thisline ), sizeof seltext ); + is_dir = seltext[ 0 ] == dirmarker && seltext[ 1 ] == ' '; lfs->last_len = strlen( seltext + 2 ); lfs->last_line = thisline; memmove( seltext, seltext + 2, lfs->last_len + 1 ); - if ( seltext[ 0 ] == dirmarker && seltext[ 1 ] == ' ' ) /* directory */ + if ( is_dir ) /* directory */ { if ( isdblclick ) { @@ -469,7 +475,7 @@ fill_entries( FL_OBJECT * br, { const FL_Dirlist *dirlist, *dl; - char tt[ FL_FLEN ]; + char * tt = NULL; int n, i; FD_fselect *lfs = br->form->fdui; int dcount = 1; @@ -485,12 +491,12 @@ fill_entries( FL_OBJECT * br, if ( ! ( dirlist = fl_get_dirlist( lfs->dname, lfs->pattern, &n, lfs->rescan || lfs->disabled_cache ) ) ) { - char tmpbuf[ 256 ], + char * tmpbuf, *p; - fli_snprintf( tmpbuf, sizeof tmpbuf, "Can't read %s", lfs->dname ); - tmpbuf[ sizeof tmpbuf - 1 ] = '0円'; + asprintf( tmpbuf, "Can't read %s", lfs->dname ); fl_show_alert( "ReadDir", tmpbuf, fli_get_syserror_msg( ), 0 ); + fl_free( tmpbuf ); M_err( "fill_entries", "Can't read %s", lfs->dname ); /* Backup */ @@ -506,7 +512,7 @@ fill_entries( FL_OBJECT * br, fl_set_object_label( lfs->dirbutt, contract_dirname( lfs->dname, 38 ) ); fl_clear_browser( br ); - for ( i = 0, dl = dirlist; dl->name; i++, dl++ ) + for ( i = 0, dl = dirlist; i < n; i++, dl++ ) { int cur_line; char marker; @@ -534,7 +540,7 @@ fill_entries( FL_OBJECT * br, marker = filemarker; } - fli_snprintf( tt, sizeof tt, "%c %s", marker, dl->name ); + asprintf( &tt, "%c %s", marker, dl->name ); if ( dl->type == FT_DIR && listdirfirst ) { @@ -549,6 +555,8 @@ fill_entries( FL_OBJECT * br, fl_add_browser_line( br, tt ); } + fli_safe_free( tt ); + lcount++; if ( sel_line <= 0 diff --git a/lib/listdir.c b/lib/listdir.c index dea7125..f739640 100644 --- a/lib/listdir.c +++ b/lib/listdir.c @@ -42,7 +42,7 @@ #include <ctype.h> #include <sys/types.h> -#ifndef _WIN32 +#ifndef FL_WIN32 #include <unistd.h> #else #include <io.h> @@ -112,8 +112,12 @@ # endif /* !S_IFSOCK && S_ISNAM */ #endif /* !S_ISSOCK */ -#define MAXCACHE 10 /* upto MAXCACHE dir will be cached */ -#define MAXFL ( FL_PATH_MAX + FL_FLEN )/* maximum file length */ +#if defined NEED_DIRECT +#define DIRENT direct +#else +#define DIRENT dirent +#endif + #ifndef StrReDup #define StrReDup( a, b ) do \ @@ -124,11 +128,6 @@ } while( 0 ) #endif -#if defined NEED_DIRECT -#define DIRENT direct -#else -#define DIRENT dirent -#endif #if defined NEED_GETCWD #if defined Lynx @@ -172,8 +171,6 @@ fl_b2f_slash( char *dir ) /************* local variables ****************/ -static char fname[ MAXFL + 2 ]; - #define FL_NONE 0 /******* local function forward dec **********/ @@ -194,14 +191,11 @@ int fli_sort_method = FL_ALPHASORT; static FL_DIRLIST_FILTER ffilter = default_filter; static int filter_directory = 0; /* true to filter directory entries */ -/* - * convert native file types to FL - */ - #ifndef FL_WIN32 /* [ */ /*************************************** + * Convert native file types to FL ***************************************/ static void @@ -230,7 +224,7 @@ mode2type( unsigned int mode, /****************************************************************** - * Filter the filename before handing it over to the "file is here" + * Filter filename before handing it over to the "file is here" * list. Per default only files (including links) are shown. ******************************************************************/ @@ -241,10 +235,12 @@ fselect( const char * d_name, const char * dir, const char * pat ) { + char * fname; int ret = 0; unsigned int mode; - strcat( strcpy( fname, dir), d_name ); + + asprintf( &fname, "%s%s", dir, d_name ); stat( fname, ffstat ); mode = ffstat->st_mode; mode2type( mode, type ); @@ -255,7 +251,7 @@ fselect( const char * d_name, { /* Always keep directory and links */ - ret = S_ISDIR(mode) + ret = S_ISDIR( mode ) || ( ( S_ISREG( mode ) || S_ISLNK( mode ) ) && fli_wildmat( d_name, pat ) ); } @@ -271,6 +267,8 @@ fselect( const char * d_name, && ffilter( fname, *type ); } + fl_free( fname ); + return ret; } @@ -294,21 +292,24 @@ fselect( struct _finddata_t * c_file, type = FT_FILE; if ( ! ffilter ) - ret = 1; + ret 1; else if ( ffilter == default_filter ) /* always keep directory and links */ ret = type == FT_DIR || fli_wildmat( c_file->name, pat ); else { - strcat( strcpy( fname, dir ), c_file->name ); + char * fname; + + asprintf( &fname, "%s%s" dir, c_file->name ); ret = type == FT_DIR || ( flo_wildmat( c_file->name, pat ) && ffilter( fname, type ) ); + fl_free( fname ); } if ( ret ) { - dl->name = fl_strdup( c_file->name ); - dl->type = type; + dl->name = fl_strdup( c_file->name ); + dl->type = type; dl->dl_mtime = c_file->time_write; dl->dl_size = c_file->size; } @@ -362,8 +363,8 @@ tc_sort( const void * a, /******************************************************************* - * On entry, dir must be no zero and be terminated properly, i.e., - * ends with / + * On entry, dir must be non-zero and terminated properly, i.e., + * ends with a '/' *******************************************************************/ #ifndef FL_WIN32 @@ -373,31 +374,17 @@ scandir_get_entries( const char * dir, const char * pat, FL_Dirlist ** dirlist ) { - static struct DIRENT **dlist; - FL_Dirlist *dl; - static int lastn; - static struct stat ffstat; + struct DIRENT **dlist; + int max_n; + struct stat ffstat; int n = 0; - /* Free all memory used last time we were here */ - - if ( dlist ) - { - while ( --lastn >= 0 ) - if ( dlist[ lastn ] ) - fl_free( dlist[ lastn ]); - fl_free( dlist ); - dlist = NULL; - } - - if ( ( lastn = tc_scandir( dir, &dlist ) ) > 0 ) + if ( ( max_n = tc_scandir( dir, &dlist ) ) > 0 ) { + FL_Dirlist *dl = *dirlist = fl_malloc( max_n * sizeof **dirlist ); int i; - dl = *dirlist = fl_malloc( ( lastn + 1 ) * sizeof **dirlist ); - - for ( i = n = 0; i < lastn; i++ ) - { + for ( i = 0; i < max_n; i++ ) if ( fselect( dlist[ i ]->d_name, &ffstat, &dl->type, dir, pat ) ) { dl->name = fl_strdup( dlist[ i ]->d_name ); @@ -406,9 +393,10 @@ scandir_get_entries( const char * dir, dl++; n++; } - } - dl->name = NULL; /* sentinel */ + fl_free( dlist ); + + *dirlist = fl_realloc( *dirlist, n * sizeof **dirlist ); if ( fli_sort_method != FL_NONE ) qsort( *dirlist, n, sizeof **dirlist, tc_sort ); @@ -501,46 +489,38 @@ scandir_get_entries( const char * dir, * ********************************************************************/ -static char *lastdir[ MAXCACHE ], - *lastpat[ MAXCACHE ]; -static int lastn[ MAXCACHE ], - last_sort[ MAXCACHE ]; -static FL_Dirlist *dirlist[ MAXCACHE ]; +typedef struct +{ + char * dirname; + char * pattern; + FL_Dirlist * list; + int list_len; +} Dirlist_Cache; + +static Dirlist_Cache * cache = NULL; +static int cache_size = 0; + /******************************************************************** * Check if a particular directory is cached ********************************************************************/ -static int +static +int is_cached( const char * dir, - const char * pat, - int * c ) + const char * pat ) { - int cached = 0, - i = 0; - static int lastcache; + int i; - do + for ( i = 0; i < cache_size; i++ ) { - cached = lastpat[ i ] - && lastdir[ i ] - && strcmp( lastdir[ i ], dir ) == 0 - && strcmp( lastpat[ i ], pat ) == 0 - && dirlist[ i ] - && dirlist[ i ]->name; - *c = i++; + if ( ! strcmp( cache[ i ].dirname, dir ) + && ! strcmp( cache[ i ].pattern, pat ) ) + return i; } - while ( ! cached && i < MAXCACHE ); - - /* search for the least used slot if not cached */ - if ( ! cached ) - *c = ++lastcache % MAXCACHE; - - lastcache = *c; - M_info( "is_cached", "%s is %s cached", dir, cached ? "" : "not" ); - return cached; + return -1; } @@ -550,29 +530,34 @@ is_cached( const char * dir, void fl_free_dirlist( const FL_Dirlist * dl ) { - size_t i; + int i, j; - for ( i = 0; i < MAXCACHE; i++ ) - if ( dl == dirlist[ i ] ) + for ( i = 0; i < cache_size; ++i ) + if ( dl == cache[ i ].list ) break; - if ( i >= MAXCACHE ) + if ( i == cache_size ) { M_err( "fl_free_dirlist", "Bad list" ); return; } + + fl_free( cache[ i ].dirname ); + fl_free( cache[ i ].pattern ); + for ( j = 0; j < cache[ i ].list_len; ++j ) + fl_free( cache[ i ].list[ j ].name ); + fl_free( cache[ i ].list ); - while ( dl && dl->name ) - { - fli_safe_free( ( ( FL_Dirlist * ) dl )->name ); - dl++; - } + cache_size--; - if ( dirlist[ i ] ) + if ( i < cache_size ) { - fl_free( dirlist[ i ] ); - dirlist[ i ] = NULL; + cache[ i ].dirname = cache[ cache_size ].dirname; + cache[ i ].pattern = cache[ cache_size ].pattern; + cache[ i ].list = cache[ cache_size ].list; } + + cache = fl_realloc( cache, cache_size * sizeof *cache ); } @@ -581,50 +566,61 @@ fl_free_dirlist( const FL_Dirlist * dl ) *********************************************************************/ const FL_Dirlist * -fl_get_dirlist( const char * dir, +fl_get_dirlist( const char * directory, const char * pattern, int * n, int rescan ) { - int i, - c; - const char *pat = pattern; - char okdir[ FL_PATH_MAX + 1 ]; + char * dir; + char * pat; + FL_Dirlist * dl; + int i; - if ( ! dir || ! *dir ) + if ( ! directory || ! *directory ) return NULL; - if ( ! pat || ! *pat ) - pat = "*"; + if ( ! pattern || ! *pattern ) + pat = fl_strdup( "*" ); + else + pat = fl_strdup( pattern ); - /* Fix the directory on the fly */ + /* Make sure the directory has a slash at the end (or, oprionally, a + backslash under Windows) */ - i = strlen( strcpy( okdir, dir ) ); - if ( okdir[ i - 1 ] != '/' ) - { - okdir[ i ] = '/'; - okdir[ ++i ] = '0円'; - } +#ifndef FL_WIN32 + if ( directory[ strlen( directory ) - 1 ] == '/' ) +#else + if ( directory[ strlen( directory ) - 1 ] == '/' + || directory[ strlen( directory ) - 1 ] == '\\') +#endif + dir = fl_strdup( directory ); + else + asprintf( &dir, "%s/", directory ); - /* is_cached must go first to get correct cache location */ + /* First check if it's not already cached (unless we're asked to rescan + anyway) */ - if ( ! is_cached( okdir, pat, &c ) || rescan ) + if ( ( i = is_cached( dir, pat ) ) >= 0 && ! rescan ) { - fl_free_dirlist( dirlist[ c ] ); - lastn[ c ] = scandir_get_entries( okdir, pat, dirlist + c ); - last_sort[ c ] = fli_sort_method; - StrReDup( lastpat[ c ], pat ); - StrReDup( lastdir[ c ], okdir ); + fl_free( dir ); + fl_free( pat ); + *n = cache[ i ].list_len; + return cache[ i ].list; } - *n = lastn[ c ]; - if ( last_sort[ c ] != fli_sort_method ) + *n = scandir_get_entries( dir, pat, &dl ); + if ( ! dl ) { - qsort( dirlist[ c ], *n, sizeof **dirlist, tc_sort ); - last_sort[ c ] = fli_sort_method; + fl_free( dir ); + fl_free( pat ); + return NULL; } - return dirlist[ c ]; + cache = fl_realloc( cache, ++cache_size * sizeof *cache ); + cache[ cache_size - 1 ].dirname = dir; + cache[ cache_size - 1 ].pattern = pat; + cache[ cache_size - 1 ].list_len = *n; + return cache[ cache_size - 1 ].list = dl; } @@ -633,11 +629,11 @@ fl_get_dirlist( const char * dir, **********************************************************************/ int -fli_is_valid_dir( const char *name ) +fli_is_valid_dir( const char * name ) { struct stat stbuf; -#ifdef __EMX__ +#ifdef __EMX__ || defined FL_WIN32 if ( name && isalpha( ( unsigned char ) name[ 0 ] ) && name[ 1 ] == ':' @@ -968,7 +964,8 @@ tc_scandir( const char * dirname, #else total = dname_is_1 ? dentry->d_reclen : sizeof *dentry; #endif - memcpy( head[ n ] = fl_malloc( total ), dentry, total ); + head[ n ] = fl_malloc( total ); + memcpy( head[ n ], dentry, total ); } closedir( dir ); @@ -1047,8 +1044,6 @@ fli_getcwd( char * buf, #else return getcwd( buf, len ); #endif - - } |