21 #include "libmpcodecs/img_format.h"
22 #include "libmpcodecs/mp_image.h"
25 #include "menu_list.h"
26 #include "input/input.h"
27 #include "osdep/keycodes.h"
36 char* dir
; // current dir
47 static struct menu_priv_s cfg_dflt
= {
60 #define ST_OFF(m) M_ST_OFF(struct menu_priv_s,m)
62 static m_option_t cfg_fields
[] = {
63 MENU_LIST_PRIV_FIELDS
,
64 { "path", ST_OFF(path
), CONF_TYPE_STRING
, 0, 0, 0, NULL
},
65 { "title", ST_OFF(title
), CONF_TYPE_STRING
, 0, 0, 0, NULL
},
66 { "file-action", ST_OFF(file_action
), CONF_TYPE_STRING
, 0, 0, 0, NULL
},
67 { "dir-action", ST_OFF(dir_action
), CONF_TYPE_STRING
, 0, 0, 0, NULL
},
68 { "auto-close", ST_OFF(auto_close
), CONF_TYPE_FLAG
, 0, 0, 1, NULL
},
69 { "actions", ST_OFF(actions
), CONF_TYPE_STRING_LIST
, 0, 0, 0, NULL
},
70 { "filter", ST_OFF(filter
), CONF_TYPE_STRING
, 0, 0, 0, NULL
},
71 { NULL
, NULL
, NULL
, 0,0,0,NULL
}
74 #define mpriv (menu->priv)
76 static void free_entry(list_entry_t
* entry
) {
81 static char* replace_path(char* title
, char* dir
) {
82 char *p
= strstr(title
,"%p");
84 int tl
= strlen(title
);
88 char *r
, *n
, *d
= dir
;
92 if (*d
== '\\' || *d
== term
)
99 if (*dir
== '\\' || *dir
== term
)
101 } while ((*n
++ = *dir
++));
109 typedef int (*kill_warn
)(const void*, const void*);
111 static int mylstat(char *dir
, char *file
,struct stat
* st
) {
112 int l
= strlen(dir
) + strlen(file
);
114 sprintf(s
,"%s/%s",dir
,file
);
118 static int compare(char **a
, char **b
){
119 if((*a
)[strlen(*a
) - 1] == '/') {
120 if((*b
)[strlen(*b
) - 1] == '/')
121 return strcmp(*b
, *a
) ;
125 if((*b
)[strlen(*b
) - 1] == '/')
128 return strcmp(*b
, *a
);
132 static char **get_extensions(menu_t
*menu
){
133 char **extensions
, ext
[32];
140 fp
= fopen(mpriv
->filter
, "r");
144 extensions
= (char **) malloc(sizeof(*extensions
));
147 while(fgets(ext
,sizeof(ext
),fp
)) {
149 int s
= strlen (ext
);
151 if(ext
[s
-1] == '\n') {
155 e
= (char *) malloc(s
+1);
156 extensions
= (char **) realloc(extensions
, ++n
* sizeof(*extensions
));
157 extensions
= (char **) realloc(extensions
, ++n
* sizeof(*extensions
));
159 for (l
=extensions
; *l
; l
++);
168 static void free_extensions(char **extensions
){
170 char **l
= extensions
;
177 static int open_dir(menu_t
* menu
,char* args
) {
178 char **namelist
, **tp
;
185 extern int file_filter
;
186 char **extensions
, **elem
, *ext
;
188 menu_list_init(menu
);
192 mpriv
->dir
= strdup(args
);
193 if(mpriv
->p
.title
&& mpriv
->p
.title
!= mpriv
->title
&& mpriv
->p
.title
!= cfg_dflt
.p
.title
)
194 free(mpriv
->p
.title
);
195 p
= strstr(mpriv
->title
,"%p");
197 mpriv
->p
.title
= replace_path(mpriv
->title
,mpriv
->dir
);
199 if ((dirp
= opendir (mpriv
->dir
)) == NULL
){
200 mp_msg(MSGT_GLOBAL
,MSGL_ERR
,MSGTR_LIBMENU_OpendirError
, strerror(errno
));
204 namelist
= (char **) malloc(sizeof(char *));
205 extensions
= get_extensions(menu
);
208 while ((dp
= readdir(dirp
)) != NULL
) {
209 if(dp
->d_name
[0] == '.' && strcmp(dp
->d_name
,"..") != 0)
211 mylstat(args
,dp
->d_name
,&st
);
212 if (file_filter
&& extensions
&& !S_ISDIR(st
.st_mode
)) {
213 if((ext
= strrchr(dp
->d_name
,'.')) == NULL
)
218 if (!strcasecmp(ext
, *elem
))
224 if(n
%20 == 0){ // Get some more mem
225 if((tp
= (char **) realloc(namelist
, (n
+20) * sizeof (char *)))
227 mp_msg(MSGT_GLOBAL
,MSGL_ERR
,MSGTR_LIBMENU_ReallocError
, strerror(errno
));
234 namelist
[n
] = (char *) malloc(strlen(dp
->d_name
) + 2);
235 if(namelist
[n
] == NULL
){
236 mp_msg(MSGT_GLOBAL
,MSGL_ERR
,MSGTR_LIBMENU_MallocError
, strerror(errno
));
241 strcpy(namelist
[n
], dp
->d_name
);
242 if(S_ISDIR(st
.st_mode
))
243 strcat(namelist
[n
], "/");
248 free_extensions (extensions
);
251 qsort(namelist
, n
, sizeof(char *), (kill_warn
)compare
);
254 mp_msg(MSGT_GLOBAL
,MSGL_ERR
,MSGTR_LIBMENU_ReaddirError
,strerror(errno
));
258 if((e
= calloc(1,sizeof(list_entry_t
))) != NULL
){
260 e
->p
.txt
= strdup(namelist
[n
]);
261 if(strchr(namelist
[n
], '/') != NULL
)
263 menu_list_add_entry(menu
,e
);
265 mp_msg(MSGT_GLOBAL
,MSGL_ERR
,MSGTR_LIBMENU_MallocError
, strerror(errno
));
277 static void read_cmd(menu_t
* menu
,int cmd
) {
281 mpriv
->p
.current
= mpriv
->p
.menu
; // Hack : we consider that the first entry is ../
285 if(mpriv
->p
.current
->d
) {
286 if(mpriv
->dir_action
) {
287 int fname_len
= strlen(mpriv
->dir
) + strlen(mpriv
->p
.current
->p
.txt
) + 1;
288 char filename
[fname_len
];
290 sprintf(filename
,"%s%s",mpriv
->dir
,mpriv
->p
.current
->p
.txt
);
291 str
= replace_path(mpriv
->dir_action
,filename
);
292 c
= mp_input_parse_cmd(str
);
293 if(str
!= mpriv
->dir_action
)
295 } else { // Default action : open this dirctory ourself
296 int l
= strlen(mpriv
->dir
);
297 char *slash
= NULL
, *p
= NULL
;
298 if(strcmp(mpriv
->p
.current
->p
.txt
,"../") == 0) {
300 mpriv
->dir
[l
-1] = '\0';
301 slash
= strrchr(mpriv
->dir
,'/');
302 #if defined(__MINGW32__) || defined(__CYGWIN__)
304 slash
= strrchr(mpriv
->dir
,'\\');
308 p
= strdup(mpriv
->dir
);
310 p
= malloc(l
+ strlen(mpriv
->p
.current
->p
.txt
) + 1);
311 sprintf(p
,"%s%s",mpriv
->dir
,mpriv
->p
.current
->p
.txt
);
313 menu_list_uninit(menu
,free_entry
);
314 if(!open_dir(menu
,p
)) {
315 mp_msg(MSGT_GLOBAL
,MSGL_ERR
,MSGTR_LIBMENU_CantOpenDirectory
,p
);
321 int fname_len
= strlen(mpriv
->dir
) + strlen(mpriv
->p
.current
->p
.txt
) + 1;
322 char filename
[fname_len
];
324 sprintf(filename
,"%s%s",mpriv
->dir
,mpriv
->p
.current
->p
.txt
);
325 str
= replace_path(mpriv
->file_action
,filename
);
326 c
= mp_input_parse_cmd(str
);
327 if(str
!= mpriv
->file_action
)
331 mp_input_queue_cmd(c
);
332 if(mpriv
->auto_close
)
336 case MENU_CMD_ACTION
: {
337 int fname_len
= strlen(mpriv
->dir
) + strlen(mpriv
->p
.current
->p
.txt
) + 1;
338 char filename
[fname_len
];
340 sprintf(filename
,"%s%s",mpriv
->dir
,mpriv
->p
.current
->p
.txt
);
341 str
= replace_path(action
, filename
);
342 mp_input_queue_cmd(mp_input_parse_cmd(str
));
347 menu_list_read_cmd(menu
,cmd
);
351 static void read_key(menu_t
* menu
,int c
){
353 read_cmd(menu
,MENU_CMD_LEFT
);
356 for (str
=mpriv
->actions
; str
&& *str
; str
++)
357 if (c
== (*str
)[0]) {
359 read_cmd(menu
,MENU_CMD_ACTION
);
363 menu_list_read_key(menu
,c
,1);
367 static void clos(menu_t
* menu
) {
368 menu_list_uninit(menu
,free_entry
);
372 static int open_fs(menu_t
* menu
, char* args
) {
373 char *path
= mpriv
->path
;
376 args
= NULL
; // Warning kill
378 menu
->draw
= menu_list_draw
;
379 menu
->read_cmd
= read_cmd
;
380 menu
->read_key
= read_key
;
384 if(!path
|| path
[0] == '\0') {
385 int l
= strlen(wd
) + 2;
388 r
= open_dir(menu
,b
);
389 } else if(path
[0] != '/') {
390 int al
= strlen(path
);
391 int l
= strlen(wd
) + al
+ 3;
394 sprintf(b
,"%s/%s/",wd
,path
);
396 sprintf(b
,"%s/%s",wd
,path
);
397 r
= open_dir(menu
,b
);
399 r
= open_dir(menu
,path
);
404 const menu_info_t menu_info_filesel
= {
411 sizeof(struct menu_priv_s
),