1 /* vim:tw=78:ts=8:sw=4:set ft=c: */
3 Copyright (C) 2007-2018 Ben Kibbey <bjk@luxsci.net>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 #include <sys/types.h>
48 #include "filebrowser.h"
60 for (i
= 0; files
[i
]; i
++)
62 free (files
[i
]->name
);
63 free (files
[i
]->path
);
72 static struct menu_item_s
**
73 get_file_items (WIN
* win
)
75 struct menu_input_s
*m
= win
->data
;
76 struct input_s
*in
= m
->data
;
78 struct menu_item_s
**items
= m
->items
;
86 #ifdef HAVE_GLOB_NOMATCH
92 * First find hidden directories in the working directory. Then non-hidden
93 * directories, then apply the config.pattern to regular files.
95 snprintf (pattern
, sizeof (pattern
), "%s/.?*", path
);
99 for (i
= 0; items
[i
]; i
++)
104 items
= m
->items
= NULL
;
105 free_file_browser ();
109 #ifdef HAVE_GLOB_NOMATCH
110 if ((ret
= glob (pattern
, x
, NULL
, &g
)) != 0 && ret
!= GLOB_NOMATCH
)
113 if (glob (pattern
, x
, NULL
, &g
) != 0)
116 cmessage (ERROR_STR
, ANY_KEY_STR
, "glob() failed:\n%s", pattern
);
120 for (i
= 0; i
< g
.gl_pathc
; i
++)
126 if (stat (g
.gl_pathv
[i
], &st
) == -1)
129 if ((p
= strrchr (g
.gl_pathv
[i
], '/')) != NULL
)
136 if (!S_ISDIR (st
.st_mode
))
139 if (p
[0] == '.' && p
[1] == 0)
144 if (S_ISDIR (st
.st_mode
))
148 files
= Realloc (files
, (n
+ 2) * sizeof (struct file_s
*));
149 files
[n
] = Malloc (sizeof (struct file_s
));
150 files
[n
]->path
= strdup (g
.gl_pathv
[i
]);
151 len
= strlen (p
) + 2;
152 files
[n
]->name
= Malloc (len
);
153 strcpy (files
[n
]->name
, p
);
155 if (S_ISDIR (st
.st_mode
))
157 files
[n
]->name
[len
- 2] = '/';
158 files
[n
]->name
[len
- 1] = 0;
159 p
= files
[n
]->path
+ strlen (files
[n
]->path
) - 1;
161 if (*p
== '.' && *(p
- 1) == '.' && *(p
- 2) == '/')
166 if (strlen (files
[n
]->path
))
174 if (!strlen (files
[n
]->path
))
183 tp
= localtime (&st
.st_mtime
);
184 strftime (tbuf
, sizeof (tbuf
), "%b %d %T", tp
);
185 snprintf (sbuf
, sizeof (sbuf
), "%s %6i", tbuf
, (int) st
.st_size
);
186 files
[n
]->st
= strdup (sbuf
);
195 snprintf (pattern
, sizeof (pattern
), "%s/*", path
);
201 snprintf (pattern
, sizeof (pattern
), "%s/%s", path
, config
.pattern
);
208 for (i
= 0; files
[i
]; i
++)
210 items
= Realloc (items
, (i
+ 2) * sizeof (struct menu_item_s
*));
211 items
[i
] = Malloc (sizeof (struct menu_item_s
));
212 items
[i
]->name
= files
[i
]->name
;
213 items
[i
]->value
= files
[i
]->st
;
214 items
[i
]->selected
= 0;
218 win
->title
= strdup (path
);
225 file_browser_help (struct menu_input_s
*m
)
227 message (_("File Browser Keys"), ANY_KEY_STR
, "%s",
228 _(" UP/DOWN - previous/next menu item\n"
229 " HOME/END - first/last menu item\n"
230 " PGDN/PGUP - next/previous page\n"
231 " a-zA-Z0-9 - jump to item\n"
232 " ENTER - select item\n"
233 " ~ - change to home directory\n"
234 " CTRL-e - change filename expression\n"
239 file_browser_select (struct menu_input_s
*m
)
241 struct input_s
*in
= m
->data
;
242 char *path
= in
->arg
;
245 if (stat (files
[m
->selected
]->path
, &st
) == -1)
247 message (ERROR_STR
, ANY_KEY_STR
, "%s", strerror (errno
));
251 if (S_ISDIR (st
.st_mode
))
253 if (access (files
[m
->selected
]->path
, R_OK
) != 0)
255 cmessage (files
[m
->selected
]->path
, ANY_KEY_STR
, "%s",
261 path
= strdup (files
[m
->selected
]->path
);
268 oldwd
= strdup (path
);
272 strncpy (in
->buf
, files
[m
->selected
]->path
, sizeof (in
->buf
) - 1);
273 in
->buf
[sizeof (in
->buf
) - 1] = 0;
274 set_field_buffer (in
->fields
[0], 0, in
->buf
);
279 file_browser_finalize (WIN
* win
)
281 struct input_s
*in
= win
->data
;
284 free_file_browser ();
288 file_browser_home (struct menu_input_s
*m
)
290 struct input_s
*in
= m
->data
;
291 char *path
= in
->arg
;
295 pw
= getpwuid (getuid ());
296 path
= strdup (pw
->pw_dir
);
303 oldwd
= strdup (path
);
307 do_file_browser_expression_finalize (WIN
* win
)
309 struct input_data_s
*in
= win
->data
;
315 free (config
.pattern
);
317 config
.pattern
= strdup (in
->str
);
320 pushkey
= REFRESH_MENU
;
324 file_browser_expression (struct menu_input_s
*m
)
326 struct input_data_s
*in
;
328 in
= Calloc (1, sizeof (struct input_data_s
));
329 in
->efunc
= do_file_browser_expression_finalize
;
330 construct_input (_("Filename Expression"), config
.pattern
, 1, 1, NULL
, NULL
,
331 NULL
, 0, in
, -1, NULL
, -1);
335 file_browser_abort (struct menu_input_s
*m
)
341 file_browser_print (WIN
* win
)
344 struct menu_input_s
*m
= win
->data
;
346 for (i
= 0; m
->items
[i
]; i
++)
348 int n
= strlen (m
->items
[i
]->value
);
354 mvwprintw (win
->w
, m
->print_line
, 1, "%*s %-*s", len
, m
->item
->value
,
355 win
->cols
- len
- 3, m
->item
->name
);
359 file_browser (void *arg
)
361 struct menu_key_s
**keys
= NULL
;
362 struct input_s
*in
= arg
;
364 char path
[FILENAME_MAX
] = { 0 };
366 if (!oldwd
&& config
.savedirectory
)
368 if ((p
= pathfix (config
.savedirectory
)) == NULL
)
371 strncpy (path
, p
, sizeof (path
) - 1);
373 if (access (path
, R_OK
) == -1)
375 cmessage (ERROR_STR
, ANY_KEY_STR
, "%s: %s", path
, strerror (errno
));
376 getcwd (path
, sizeof (path
));
380 getcwd (path
, sizeof (path
) - 1);
382 strncpy (path
, oldwd
, sizeof (path
) - 1);
384 in
->arg
= strdup (path
);
385 add_menu_key (&keys
, '\n', file_browser_select
);
386 add_menu_key (&keys
, KEY_F (1), file_browser_help
);
387 add_menu_key (&keys
, '~', file_browser_home
);
388 add_menu_key (&keys
, CTRL_KEY ('e'), file_browser_expression
);
389 add_menu_key (&keys
, KEY_ESCAPE
, file_browser_abort
);
390 construct_menu (LINES
- 4, 0, -1, -1, NULL
, 0, get_file_items
, keys
, in
,
391 file_browser_print
, file_browser_finalize
, NULL
);