GRASS GIS 7 Programmer's Manual  7.0.3(2016)-r00000
ls.c
Go to the documentation of this file.
1 
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <sys/types.h>
20 #include <dirent.h>
21 #include <unistd.h>
22 
23 #include <grass/gis.h>
24 #include <grass/config.h>
25 #include <grass/glocale.h>
26 
27 #ifdef HAVE_TERMIOS_H
28 # include <termios.h>
29 #endif
30 
31 #ifdef HAVE_SYS_IOCTL_H
32 # include <sys/ioctl.h>
33 #endif
34 
35 typedef int ls_filter_func(const char * /*filename */ , void * /*closure */ );
36 
37 static struct state {
38  ls_filter_func *ls_filter;
39  void *ls_closure;
40  ls_filter_func *ls_ex_filter;
41  void *ls_ex_closure;
42 } state;
43 
44 static struct state *st = &state;
45 
46 static int cmp_names(const void *aa, const void *bb)
47 {
48  char *const *a = (char *const *)aa;
49  char *const *b = (char *const *)bb;
50 
51  return strcmp(*a, *b);
52 }
53 
67 void G_set_ls_filter(ls_filter_func *func, void *closure)
68 {
69  st->ls_filter = func;
70  st->ls_closure = closure;
71 }
72 
73 void G_set_ls_exclude_filter(ls_filter_func *func, void *closure)
74 {
75  st->ls_ex_filter = func;
76  st->ls_ex_closure = closure;
77 }
78 
95 char **G_ls2(const char *dir, int *num_files)
96 {
97  struct dirent *dp;
98  DIR *dfd;
99  char **dir_listing = NULL;
100  int n = 0;
101 
102  if ((dfd = opendir(dir)) == NULL)
103  G_fatal_error(_("Unable to open directory %s"), dir);
104 
105  while ((dp = readdir(dfd)) != NULL) {
106  if (dp->d_name[0] == '.') /* Don't list hidden files */
107  continue;
108  if (st->ls_filter && !(*st->ls_filter)(dp->d_name, st->ls_closure))
109  continue;
110  if (st->ls_ex_filter && (*st->ls_ex_filter)(dp->d_name, st->ls_ex_closure))
111  continue;
112  dir_listing = (char **)G_realloc(dir_listing, (1 + n) * sizeof(char *));
113  dir_listing[n] = G_store(dp->d_name);
114  n++;
115  }
116  closedir(dfd);
117 
118  /* Sort list of filenames alphabetically */
119  qsort(dir_listing, n, sizeof(char *), cmp_names);
120 
121  *num_files = n;
122  return dir_listing;
123 }
124 
137 void G_ls(const char *dir, FILE * stream)
138 {
139  int i, n;
140  char **dir_listing = G_ls2(dir, &n);
141 
142  G_ls_format(dir_listing, n, 0, stream);
143 
144  for (i = 0; i < n; i++)
145  G_free(dir_listing[i]);
146 
147  G_free(dir_listing);
148 }
149 
165 void G_ls_format(char **list, int num_items, int perline, FILE * stream)
166 {
167  int i;
168 
169  int field_width, column_height;
170  int screen_width = 80; /* Default width of 80 columns */
171 
172  if (num_items < 1)
173  return; /* Nothing to print */
174 
175 #ifdef TIOCGWINSZ
176  /* Determine screen_width if possible */
177  {
178  struct winsize size;
179 
180  if (ioctl(fileno(stream), TIOCGWINSZ, (char *)&size) == 0)
181  screen_width = size.ws_col;
182  }
183 #endif
184 
185  if (perline == 0) {
186  int max_len = 0;
187 
188  for (i = 0; i < num_items; i++) {
189  /* Find maximum filename length */
190  if (strlen(list[i]) > max_len)
191  max_len = strlen(list[i]);
192  }
193  /* Auto-fit the number of items that will
194  * fit per line (+1 because of space after item) */
195  perline = screen_width / (max_len + 1);
196  if (perline < 1)
197  perline = 1;
198  }
199 
200  /* Field width to accomodate longest filename */
201  field_width = screen_width / perline;
202  /* Longest column height (i.e. num_items <= perline * column_height) */
203  column_height = (num_items / perline) + ((num_items % perline) > 0);
204 
205  {
206  const int max
207  = num_items + column_height - (num_items % column_height);
208  char **next;
209 
210  for (i = 1, next = list; i <= num_items; i++) {
211  char **cur = next;
212 
213  next += column_height;
214  if (next >= list + num_items) {
215  /* the next item has to be on the other line */
216  next -= (max - 1 - (next < list + max ? column_height : 0));
217  fprintf(stream, "%s\n", *cur);
218  }
219  else {
220  fprintf(stream, "%-*s", field_width, *cur);
221  }
222  }
223  }
224 }
void G_ls_format(char **list, int num_items, int perline, FILE *stream)
Prints a listing of items to a stream, in prettified column format.
Definition: ls.c:165
int screen_width
Definition: driver/init.c:29
char * G_store(const char *s)
Copy string to allocated memory.
Definition: strings.c:86
void G_ls(const char *dir, FILE *stream)
Prints a directory listing to a stream, in prettified column format.
Definition: ls.c:137
#define NULL
Definition: ccmath.h:32
void G_fatal_error(const char *msg,...)
Print a fatal error message to stderr.
Definition: gis/error.c:159
double b
struct state * st
Definition: parser.c:101
char ** G_ls2(const char *dir, int *num_files)
Stores a sorted directory listing in an array.
Definition: ls.c:95
struct list * list
Definition: read_list.c:24
void G_set_ls_filter(ls_filter_func *func, void *closure)
Sets a function and its complementary data for G_ls2 filtering.
Definition: ls.c:67
int ls_filter_func(const char *, void *)
Definition: ls.c:35
#define max(a, b)
void G_free(void *buf)
Free allocated memory.
Definition: alloc.c:149
struct state state
Definition: parser.c:100
void G_set_ls_exclude_filter(ls_filter_func *func, void *closure)
Definition: ls.c:73