libxputty  0.1
A damn tiny abstraction Layer to create X11 window/widgets with cairo surfaces
xfilepicker.c
Go to the documentation of this file.
1 /*
2  * 0BSD
3  *
4  * BSD Zero Clause License
5  *
6  * Copyright (c) 2019 Hermann Meyer
7  *
8  * Permission to use, copy, modify, and/or distribute this software for any
9  * purpose with or without fee is hereby granted.
10 
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
12  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13  * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
14  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
16  * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  *
19  */
20 
21 #include "xfilepicker.h"
22 
23 
24 static inline int fp_compare_fun (const void *p1, const void *p2) {
25  return strcasecmp(*(const char**) p1, *(const char**) p2);
26 }
27 
28 static inline int fp_compare_hidden_dirs_fun (const void *p1, const void *p2) {
29  if(strstr(*(const char**)p1, PATH_SEPARATOR".") && strstr(*(const char**)p2, PATH_SEPARATOR".")) return 0;
30  if(strstr(*(const char**)p1, PATH_SEPARATOR".")) return 1;
31  if(strstr(*(const char**)p2, PATH_SEPARATOR".")) return -1;
32  return strcasecmp(*(const char**) p1, *(const char**) p2);
33 }
34 
35 static inline int fp_compare_hidden_files_fun (const void *p1, const void *p2) {
36  if(strncmp(*(const char**)p1, ".",1)==0 && strncmp(*(const char**)p2, ".",1)==0) return 0;
37  if(strncmp(*(const char**)p1, ".",1)==0 ) return 1;
38  if(strncmp(*(const char**)p2, ".",1)==0 ) return -1;
39  return strcasecmp(*(const char**) p1, *(const char**) p2);
40 }
41 
42 static inline bool fp_show_hidden_files(FilePicker *filepicker, char* file) {
43  return (filepicker->show_hidden) ? strcmp(file,".")!=0 : (file[0] != '.');
44 }
45 
46 static inline bool fp_show_filter_files(FilePicker *filepicker, char* file) {
47  if (!filepicker->use_filter) {
48  return true;
49  } else {
50  if(strstr(filepicker->filter,"."))
51  return strstr(file, filepicker->filter);
52 #ifdef __XDG_MIME_H__
53  return strstr(xdg_mime_get_mime_type_from_file_name(file), filepicker->filter);
54 #else
55  return true;
56 #endif
57  }
58 }
59 
60 static void fp_sort_buffers(FilePicker *filepicker, int get_dirs) {
61  if (filepicker->dir_counter>1 && get_dirs) {
62  qsort (filepicker->dir_names, filepicker->dir_counter,
63  sizeof filepicker->dir_names[0], (filepicker->show_hidden) ?
64  fp_compare_hidden_dirs_fun : fp_compare_fun);
65  }
66  if (filepicker->file_counter>1) {
67  qsort (filepicker->file_names, filepicker->file_counter,
68  sizeof filepicker->file_names[0], (filepicker->show_hidden) ?
69  fp_compare_hidden_files_fun : fp_compare_fun);
70  }
71 }
72 
73 static void fp_clear_filebuffer(FilePicker *filepicker) {
74  unsigned int j = 0;
75  for(; j<filepicker->file_counter;j++) {
76  free(filepicker->file_names[j]);
77  filepicker->file_names[j] = NULL;
78  }
79  if(filepicker->file_counter) {
80  free(filepicker->file_names);
81  filepicker->file_names = NULL;
82  filepicker->file_counter=0;
83  }
84 }
85 
86 static void fp_clear_dirbuffer(FilePicker *filepicker) {
87  unsigned int j = 0;
88  for(; j<filepicker->dir_counter;j++) {
89  free(filepicker->dir_names[j]);
90  filepicker->dir_names[j] = NULL;
91  }
92  if(filepicker->dir_counter) {
93  free(filepicker->dir_names);
94  filepicker->dir_names = NULL;
95  filepicker->dir_counter=0;
96  }
97 }
98 
99 static inline int fp_prefill_dirbuffer(FilePicker *filepicker, char *path) {
100  int ret = 0;
101  if (strcmp (path, PATH_SEPARATOR) == 0) {
102  filepicker->dir_names = (char **)realloc(filepicker->dir_names,
103  (filepicker->dir_counter + 1) * sizeof(char *));
104  assert(filepicker->dir_names != NULL);
105  asprintf(&filepicker->dir_names[filepicker->dir_counter++], "%s",path);
106  assert(&filepicker->dir_names[filepicker->dir_counter] != NULL);
107  } else {
108  char *ho;
109  asprintf(&ho, "%s",path);
110  assert(ho != NULL);
111  while (strcmp (ho, PATH_SEPARATOR) != 0) {
112  filepicker->dir_names = (char **)realloc(filepicker->dir_names,
113  (filepicker->dir_counter + 1) * sizeof(char *));
114  assert(filepicker->dir_names != NULL);
115  asprintf(&filepicker->dir_names[filepicker->dir_counter++], "%s",dirname(ho));
116  assert(&filepicker->dir_names[filepicker->dir_counter] != NULL);
117  ret++;
118  }
119  if (strcmp (path, PATH_SEPARATOR) != 0) {
120  filepicker->dir_names = (char **)realloc(filepicker->dir_names,
121  (filepicker->dir_counter + 1) * sizeof(char *));
122  assert(filepicker->dir_names != NULL);
123  asprintf(&filepicker->dir_names[filepicker->dir_counter++], "%s",path);
124  assert(&filepicker->dir_names[filepicker->dir_counter] != NULL);
125  }
126  free(ho);
127  }
128  return ret;
129 }
130 
131 int fp_get_files(FilePicker *filepicker, char *path, int get_dirs) {
132  int ret = 0;
133  fp_clear_filebuffer(filepicker);
134 
135  DIR *dirp;
136  struct dirent *dp;
137  if((dirp = opendir(path)) == NULL) {
138  path =(char*)PATH_SEPARATOR;
139  dirp = opendir(PATH_SEPARATOR);
140  assert(dirp);
141  }
142 
143  if(get_dirs) {
144  fp_clear_dirbuffer(filepicker);
145  ret = fp_prefill_dirbuffer(filepicker, path);
146  }
147 
148  while ((dp = readdir(dirp)) != NULL) {
149 
150  if(dp-> d_type != DT_DIR && strlen(dp->d_name)!=0 && dp->d_type != DT_UNKNOWN
151  && strcmp(dp->d_name,"..")!=0 && fp_show_hidden_files(filepicker, dp->d_name) &&
152  fp_show_filter_files(filepicker, dp->d_name)) {
153 
154  filepicker->file_names = (char **)realloc(filepicker->file_names,
155  (filepicker->file_counter + 1) * sizeof(char *));
156  assert(filepicker->file_names != NULL);
157  asprintf(&filepicker->file_names[filepicker->file_counter++],"%s",dp->d_name);
158  assert(&filepicker->file_names[filepicker->file_counter] != NULL);
159 
160  } else if(get_dirs && dp -> d_type == DT_DIR && strlen(dp->d_name)!=0
161  && strcmp(dp->d_name,"..")!=0 && fp_show_hidden_files(filepicker, dp->d_name)) {
162 
163  filepicker->dir_names = (char **)realloc(filepicker->dir_names,
164  (filepicker->dir_counter + 1) * sizeof(char *));
165  assert(filepicker->dir_names != NULL);
166  asprintf(&filepicker->dir_names[filepicker->dir_counter++], (strcmp(path, PATH_SEPARATOR) != 0) ?
167  "%s" PATH_SEPARATOR "%s" : "%s%s" , path,dp->d_name);
168  assert(&filepicker->dir_names[filepicker->dir_counter] != NULL);
169  }
170  }
171  closedir(dirp);
172  fp_sort_buffers(filepicker, get_dirs);
173  return ret;
174 }
175 
176 void fp_free(FilePicker *filepicker) {
177  fp_clear_filebuffer(filepicker);
178  fp_clear_dirbuffer(filepicker);
179  free(filepicker->selected_file);
180  free(filepicker->path);
181  free(filepicker->filter);
182 }
183 
184 void fp_init(FilePicker *filepicker, const char *path) {
185  filepicker->file_counter=0;
186  filepicker->dir_counter=0;
187  filepicker->use_filter = 0;
188  filepicker->show_hidden = false;
189  filepicker->file_names = NULL;
190  filepicker->dir_names = NULL;
191  filepicker->selected_file = NULL;
192  filepicker->path = NULL;
193  filepicker->filter = NULL;
194  asprintf(&filepicker->path, path);
195  assert(filepicker->path != NULL);
196 }
xfilepicker.h
FilePicker::selected_file
char * selected_file
Definition: xfilepicker.h:68
FilePicker::path
char * path
Definition: xfilepicker.h:67
FilePicker::file_names
char ** file_names
Definition: xfilepicker.h:69
fp_get_files
int fp_get_files(FilePicker *filepicker, char *path, int get_dirs)
fp_get_files - fill file_names and dir_names with the results from readdir path
Definition: xfilepicker.c:131
fp_init
void fp_init(FilePicker *filepicker, const char *path)
fp_init - set default values used by the filepicker
Definition: xfilepicker.c:184
FilePicker::filter
char * filter
Definition: xfilepicker.h:66
FilePicker
Definition: xfilepicker.h:61
PATH_SEPARATOR
#define PATH_SEPARATOR
Definition: xfilepicker.h:58
FilePicker::file_counter
unsigned int file_counter
Definition: xfilepicker.h:64
FilePicker::show_hidden
bool show_hidden
Definition: xfilepicker.h:63
asprintf
int asprintf(char *strp[], const char *fmt,...)
Definition: xasprintf.c:36
FilePicker::use_filter
int use_filter
Definition: xfilepicker.h:62
fp_free
void fp_free(FilePicker *filepicker)
fp_free - release all memory used by the filepicker
Definition: xfilepicker.c:176
FilePicker::dir_counter
unsigned int dir_counter
Definition: xfilepicker.h:65
FilePicker::dir_names
char ** dir_names
Definition: xfilepicker.h:70