GRASS Programmer's Manual  6.4.2(2012)
ls.c
Go to the documentation of this file.
00001 
00016 #include <stdio.h>
00017 #include <stdlib.h>
00018 #include <string.h>
00019 #include <sys/types.h>
00020 #include <dirent.h>
00021 #include <unistd.h>
00022 
00023 #include <grass/gis.h>
00024 #include <grass/config.h>
00025 #include <grass/glocale.h>
00026 
00027 #ifdef HAVE_SYS_IOCTL_H
00028 #  include <sys/ioctl.h>
00029 #endif
00030 
00031 typedef int ls_filter_func(const char * /*filename */ , void * /*closure */ );
00032 
00033 static ls_filter_func *ls_filter;
00034 static void *ls_closure;
00035 
00036 static ls_filter_func *ls_ex_filter;
00037 static void *ls_ex_closure;
00038 
00039 static int cmp_names(const void *aa, const void *bb)
00040 {
00041     char *const *a = (char *const *)aa;
00042     char *const *b = (char *const *)bb;
00043 
00044     return strcmp(*a, *b);
00045 }
00046 
00060 void G_set_ls_filter(ls_filter_func *func, void *closure)
00061 {
00062     ls_filter = func;
00063     ls_closure = closure;
00064 }
00065 
00066 void G_set_ls_exclude_filter(ls_filter_func *func, void *closure)
00067 {
00068     ls_ex_filter = func;
00069     ls_ex_closure = closure;
00070 }
00071 
00088 char **G__ls(const char *dir, int *num_files)
00089 {
00090     struct dirent *dp;
00091     DIR *dfd;
00092     char **dir_listing = NULL;
00093     int n = 0;
00094 
00095     if ((dfd = opendir(dir)) == NULL)
00096         G_fatal_error(_("Unable to open directory %s"), dir);
00097 
00098     while ((dp = readdir(dfd)) != NULL) {
00099         if (dp->d_name[0] == '.')       /* Don't list hidden files */
00100             continue;
00101         if (ls_filter && !(*ls_filter)(dp->d_name, ls_closure))
00102             continue;
00103         if (ls_ex_filter && (*ls_ex_filter)(dp->d_name, ls_ex_closure))
00104             continue;
00105         dir_listing = (char **)G_realloc(dir_listing, (1 + n) * sizeof(char *));
00106         dir_listing[n] = G_store(dp->d_name);
00107         n++;
00108     }
00109 
00110     /* Sort list of filenames alphabetically */
00111     qsort(dir_listing, n, sizeof(char *), cmp_names);
00112 
00113     *num_files = n;
00114     return dir_listing;
00115 }
00116 
00129 void G_ls(const char *dir, FILE * stream)
00130 {
00131     int i, n;
00132     char **dir_listing = G__ls(dir, &n);
00133 
00134     G_ls_format(dir_listing, n, 0, stream);
00135 
00136     for (i = 0; i < n; i++)
00137         G_free(dir_listing[i]);
00138 
00139     G_free(dir_listing);
00140 
00141     return;
00142 }
00143 
00159 void G_ls_format(char **list, int num_items, int perline, FILE * stream)
00160 {
00161     int i;
00162 
00163     int field_width, column_height;
00164     int screen_width = 80;      /* Default width of 80 columns */
00165 
00166     if (num_items < 1)
00167         return;                 /* Nothing to print */
00168 
00169 #ifdef TIOCGWINSZ
00170     /* Determine screen_width if possible */
00171     {
00172         struct winsize size;
00173 
00174         if (ioctl(fileno(stream), TIOCGWINSZ, (char *)&size) == 0)
00175             screen_width = size.ws_col;
00176     }
00177 #endif
00178 
00179     if (perline == 0) {
00180         int max_len = 0;
00181 
00182         for (i = 0; i < num_items; i++) {
00183             /* Find maximum filename length */
00184             if (strlen(list[i]) > max_len)
00185                 max_len = strlen(list[i]);
00186         }
00187         /* Auto-fit the number of items that will
00188          * fit per line (+1 because of space after item) */
00189         perline = screen_width / (max_len + 1);
00190         if (perline < 1)
00191             perline = 1;
00192     }
00193 
00194     /* Field width to accomodate longest filename */
00195     field_width = screen_width / perline;
00196     /* Longest column height (i.e. num_items <= perline * column_height) */
00197     column_height = (num_items / perline) + ((num_items % perline) > 0);
00198 
00199     {
00200         const int max
00201             = num_items + column_height - (num_items % column_height);
00202         char **next;
00203 
00204         for (i = 1, next = list; i <= num_items; i++) {
00205             char **cur = next;
00206 
00207             next += column_height;
00208             if (next >= list + num_items) {
00209                 /* the next item has to be on the other line */
00210                 next -= (max - 1 - (next < list + max ? column_height : 0));
00211                 fprintf(stream, "%s\n", *cur);
00212             }
00213             else {
00214                 fprintf(stream, "%-*s", field_width, *cur);
00215             }
00216         }
00217     }
00218 
00219     return;
00220 }
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines