GRASS Programmer's Manual
6.4.2(2012)
|
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 }