GFileScanner
- From: Mikael Hermansson <mikeh bahnhof se>
- To: gtk-devel-list gnome org
- Subject: GFileScanner
- Date: Sun, 27 Aug 2000 06:49:17 +0200
I wrote this because i needed it in my appliction :-)
Maybe this could me implemented in glib?
GFIleScanner is scans directory/file contents and supports
filecompletion (using GCompletion functions).
The API is simple and could be used in to search for files
or in a run application/command line prompt etc...
Three functions:
g_file_scanner_new(GFileScannerFunc func)
/* scan selected directory or show all matches */
g_file_scanner_set_path(GFileScanner *fc,gchar *source);
/* use this to update directory contents */
g_file_scanner_change_path(GFileScanner *fc,gchar *source);
The callback:
typedef gboolean (GFileScannerFunc *) (gchar *filename,struct stat *st,gpointer
data);
/* gchar *filename = filename :-) */
/* struct stat *st= a pointer to fileinformation from the stat() routine */
/* return: FALSE stop iteration TRUE continue */
Do we need it in glib? IMHO yes :-)
Greats
Mikael Hermansson
/* gfilescanner.c
* Copyright (C) 2000 by:
** Mikael Hermansson
*
* 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#include <string.h>
#include <glib.h>
#ifdef G_OS_WIN32
#include <direct.h>
#include <io.h>
#define mkdir(p,m) _mkdir(p)
#ifndef S_ISDIR
#define S_ISDIR(mode) ((mode)&_S_IFDIR)
#endif
#endif /* G_OS_WIN32 */
#include "gfilescanner.h"
static gboolean g_file_scanner_list(GFileScanner *fsc,GList *list);
static void g_file_scanner_clearall(GFileScanner *fsc);
static gboolean g_file_scandir(GFileScanner *fsc,gchar *search);
static void swapstrcat(gpointer data,gpointer data2);
GFileScanner* g_file_scanner_new(GFileScannerFunc func,gpointer data)
{
GFileScanner *fscanner;
g_return_val_if_fail(func!=NULL, NULL);
fscanner=g_new(GFileScanner,1);
fscanner->func=func;
fscanner->completion=g_completion_new(NULL);
fscanner->data=data;
fscanner->path=NULL;
return fscanner;
}
void g_file_scanner_free(GFileScanner *fsc)
{
g_return_if_fail(fsc!=NULL);
g_file_scanner_clearall(fsc);
g_completion_free(fsc->completion);
g_free(fsc);
}
gboolean g_file_scanner_set_path(GFileScanner *fsc, gchar *insearch)
{
struct stat st;
gboolean fileexist;
gchar *source=NULL;
g_return_val_if_fail(fsc!=NULL,FALSE);
g_return_val_if_fail(insearch!=NULL,FALSE);
g_file_scanner_clearall(fsc);
source=g_path_full(insearch);
fileexist=stat(source,&st) ? FALSE : TRUE;
/* source is a directory just scan contents normally */
if(fileexist && S_ISDIR(st.st_mode))
{
g_file_scandir(fsc,source);
return g_file_scanner_list(fsc,fsc->completion->items);
}
else if(fileexist) /* source is a file */
{
GList *list;
g_file_scanner_clearall(fsc);
list=g_list_alloc();
list->data=g_strdup(source);
g_completion_add_items(fsc->completion,list);
return g_file_scanner_list(fsc,list);
}
else /* source is not a file/directory */
{ /* need to scan for any filematches in parent directory */
GList *list;
gchar *tmp;
/* get parent dir and scan it */
tmp=g_path_get_dirname(source);
g_file_scandir(fsc,tmp);
g_free(tmp);
/* get all matches using GCompletion */
list=g_completion_complete(fsc->completion,source,NULL);
/* foreach loop */
return g_file_scanner_list(fsc,list);
}
return FALSE;
}
/* user should only call this after initiated with set_path
for example if file points to "/home/mikeh"
the user wants to go back to /home
you can call this by just add "../"
and it will scandirectory contents in /home
*/
gboolean g_file_scanner_change_path(GFileScanner *fsc,gchar *inpath)
{
gboolean ret=FALSE;
gchar *path=NULL;
if(g_path_is_absolute(inpath) || !fsc->path)
return g_file_scanner_set_path(fsc,inpath);
else
path=g_strdup_printf("%s%s",fsc->path,inpath);
ret=g_file_scanner_set_path(fsc,path);
g_free(path);
return ret;
}
/* DIR_SEPERATOR and ".." convertor */
/* removes [.] and [..] */
gchar * g_path_full(gchar *inp)
{
register gint i;
gint killnext=0;
gchar *newpath=NULL;
gchar *ap;
GList *list=NULL;
g_return_val_if_fail(inp,NULL);
list=g_list_alloc();
if(!g_path_is_absolute(inp)) {
gchar *tmp=g_get_current_dir();
ap=g_strdup_printf("%s%s%s",tmp,G_DIR_SEPARATOR_S,inp);
g_free(tmp);
}
else
ap=g_strdup(inp);
i=strlen(ap)-1;
newpath=g_malloc(i+1);
newpath[0]='\0';
while(i >= 0)
{
if(ap[i]=='~') {
i--;
list=g_list_prepend(list,g_get_home_dir());
ap[i]='\0';
}
else if(ap[i]=='*')
ap[i--]='\0';
else if(ap[i]=='.') {
if(i>0 && ap[i-1]=='.')
{ i-=2; killnext++; }
ap[i]='\0';
}
else if (ap[i]==G_DIR_SEPARATOR && killnext)
{ killnext--; ap[i]='\0'; }
else if (ap[i]==G_DIR_SEPARATOR)
{ ap[i]='\0'; if(ap[i+1]) list=g_list_prepend(list,g_strdup(&ap[i+1])); }
i--;
};
g_list_foreach(list,(GFunc)swapstrcat,newpath);
g_list_foreach(list,(GFunc)g_free,NULL);
g_list_free(list);
return newpath;
}
/* g_file_scanner_list */
/* this function is calling the users callbackfunc */
/* GFileScannerFunc(gchar *filename,struct stat *st,gpointer data) */
/* The filenames is NOT sorted */
/* user can return FALSE to stop iterate files */
gboolean g_file_scanner_list(GFileScanner *fsc,GList *list)
{
GList *cur;
struct stat st;
cur=g_list_first(list);
while(cur && cur->data)
{
if(stat((gchar*)cur->data,&st)!=0)
g_warning("Could not stat dir/file [%s]!?",(gchar *)cur->data);
if(!fsc->func((gchar *)cur->data,&st,fsc->data))
return FALSE; /* user stoped iteration */
cur=g_list_next(cur);
};
return TRUE;
}
/*-------------------------------------------*/
/* static member functions */
/*--------------------------------------------*/
gboolean g_file_scandir(GFileScanner *fsc,gchar *search)
{
GList* list;
DIR *dir;
struct dirent *direntry;
dir=opendir(search);
if(!dir)
return FALSE;
fsc->path=g_strdup(search);
if(fsc->completion->items)
g_completion_clear_items(fsc->completion);
list=g_list_alloc();
direntry=readdir(dir);
while(direntry)
{
list->data=g_strdup_printf("%s%s%s",search,G_DIR_SEPARATOR_S,direntry->d_name);
g_completion_add_items(fsc->completion,list);
direntry=readdir(dir);
}
closedir(dir);
return TRUE;
}
static void g_file_scanner_clearall(GFileScanner *fsc)
{
if(fsc->completion->items) {
g_list_foreach(fsc->completion->items,(GFunc)g_free,NULL);
g_completion_clear_items(fsc->completion);
}
if(fsc->path) {
g_free(fsc->path);
fsc->path=NULL;
}
}
void swapstrcat(gpointer data,gpointer data2)
{
if(!data)
return ;
strcat(data2,G_DIR_SEPARATOR_S);
strcat(data2,data);
}
/*-------------------------------------------*/
/* TESTAPPLICATION */
/*--------------------------------------------*/
gboolean cb(gchar *file,struct stat *st,gpointer data)
{
if(S_ISDIR(st->st_mode))
g_print("Directoryname %s\n",file);
else
g_print("Filename %s\n",file);
return TRUE;
};
int main(int argc, char *argv[])
{
GFileScanner *fc;
if(argc<2) {
g_print("filetest directory\n");
return -1;
}
fc=g_file_scanner_new(cb,NULL);
g_file_scanner_set_path(fc,argv[1]);
g_file_scanner_free(fc);
return 0;
}
/* gfilescanner.h
* Copyright (C) 2000 by:
** Mikael Hermansson
*
* 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __GFILESCANNER_H__
#define __GFILESCANNER_H__
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
typedef gboolean ( *GFileScannerFunc)(gchar *filename, struct stat *st, gpointer userdata);
typedef struct _GFileScanner GFileScanner;
struct _GFileScanner
{
GList* items;
GFileScannerFunc func;
GCompletion *completion;
gchar *path;
gpointer data;
};
GFileScanner* g_file_scanner_new(GFileScannerFunc func, gpointer userdata);
/* return false if callback is aborted when scann */
gboolean g_file_scanner_set_path(GFileScanner *fsc,gchar *filename);
gboolean g_file_scanner_change_path(GFileScanner *fsc,gchar *inpath);
gchar* g_path_full(gchar *filename);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* end of __GFILESCANNER_H__ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]