📄 file.c
字号:
for (i = 0; i < panel->count; i++)
if (panel->dir.list [i].f.marked){
*stat_buf = panel->dir.list [i].buf;
return panel->dir.list [i].fname;
}
} else {
*stat_buf = panel->dir.list [panel->selected].buf;
return panel->dir.list [panel->selected].fname;
}
fprintf (stderr, _(" Internal error: get_file \n"));
mi_getch ();
return "";
}
static int
is_wildcarded (char *p)
{
for (; *p; p++) {
if (*p == '*')
return 1;
else if (*p == '\\' && p [1] >= '1' && p [1] <= '9')
return 1;
}
return 0;
}
/* Sets all global variables used by copy_file_file/move_file_file to a
resonable default
(file_mask_dialog sets these global variables interactively)
*/
void
file_mask_defaults (void)
{
stable_symlinks = 0;
op_follow_links = 0;
dive_into_subdirs = 0;
xstat = mc_lstat;
preserve = 1;
umask_kill = 0777777;
preserve_uidgid = (geteuid () == 0) ? 1 : 0;
}
#define FMDY 13
#define FMD_XLEN 64
static int fmd_xlen = FMD_XLEN, fmd_i18n_flag = 0;
static QuickWidget fmd_widgets [] = {
#define FMCB0 FMDC
#define FMCB12 0
#define FMCB11 1
/* follow symlinks and preserve Attributes must be the first */
{ quick_checkbox, 3, 64, 8, FMDY, N_("preserve &Attributes"), 9, 0,
&op_preserve, 0, XV_WLAY_BELOWCLOSE, "preserve" },
{ quick_checkbox, 3, 64, 7, FMDY, N_("follow &Links"), 7, 0,
&op_follow_links, 0, XV_WLAY_BELOWCLOSE, "follow" },
#ifdef HAVE_XVIEW
#define FMDI1 5
#define FMDI2 2
#define FMDC 4
{ quick_input, 3, 64, 6, FMDY, "", 58, 0,
0, 0, XV_WLAY_BELOWCLOSE, "input2" },
#endif
{ quick_label, 3, 64, 5, FMDY, N_("to:"), 0, 0, 0, 0, XV_WLAY_BELOWOF,"to"},
{ quick_checkbox, 37, 64, 4, FMDY, N_("&Using shell patterns"), 0, 0,
0/* &source_easy_patterns */, 0, XV_WLAY_BELOWCLOSE, "using-shell" },
{ quick_input, 3, 64, 3, FMDY, "", 58,
0, 0, 0, XV_WLAY_BELOWCLOSE, "input-def" },
#ifndef HAVE_XVIEW
#define FMDI1 4
#define FMDI2 5
#define FMDC 3
{ quick_input, 3, 64, 6, FMDY, "", 58, 0,
0, 0, XV_WLAY_BELOWCLOSE, "input2" },
#endif
#define FMDI0 6
{ quick_label, 3, 64, 2, FMDY, "", 0, 0, 0, 0, XV_WLAY_DONTCARE, "ql" },
#define FMBRGT 7
{ quick_button, 42, 64, 9, FMDY, N_("&Cancel"), 0, B_CANCEL, 0, 0, XV_WLAY_DONTCARE,
"cancel" },
#undef SKIP
#ifdef WITH_BACKGROUND
# define SKIP 5
# define FMCB21 11
# define FMCB22 10
# define FMBLFT 9
# define FMBMID 8
{ quick_button, 25, 64, 9, FMDY, N_("&Background"), 0, B_USER, 0, 0, XV_WLAY_DONTCARE, "back" },
#else /* WITH_BACKGROUND */
# define SKIP 4
# define FMCB21 10
# define FMCB22 9
# define FMBLFT 8
# undef FMBMID
#endif
{ quick_button, 14, 64, 9, FMDY, N_("&Ok"), 0, B_ENTER, 0, 0, XV_WLAY_NEXTROW, "ok" },
{ quick_checkbox, 42, 64, 8, FMDY, N_("&Stable Symlinks"), 0, 0,
&stable_symlinks, 0, XV_WLAY_BELOWCLOSE, "stab-sym" },
{ quick_checkbox, 31, 64, 7, FMDY, N_("&Dive into subdir if exists"), 0, 0,
&dive_into_subdirs, 0, XV_WLAY_BELOWOF, "dive" },
{ 0 } };
void
fmd_init_i18n()
{
#ifdef ENABLE_NLS
register int i;
int len;
for (i = sizeof (op_names) / sizeof (op_names[0]); i--;)
op_names [i] = _(op_names [i]);
i = sizeof (fmd_widgets) / sizeof (fmd_widgets [0]) - 1;
while (i--)
if (fmd_widgets [i].text[0] != '\0')
fmd_widgets [i].text = _(fmd_widgets [i].text);
len = strlen (fmd_widgets [FMCB11].text)
+ strlen (fmd_widgets [FMCB21].text) + 15;
fmd_xlen = max (fmd_xlen, len);
len = strlen (fmd_widgets [FMCB12].text)
+ strlen (fmd_widgets [FMCB22].text) + 15;
fmd_xlen = max (fmd_xlen, len);
len = strlen (fmd_widgets [FMBRGT].text)
+ strlen (fmd_widgets [FMBLFT].text) + 11;
#ifdef FMBMID
len += strlen (fmd_widgets [FMBMID].text) + 6;
#endif
fmd_xlen = max (fmd_xlen, len + 4);
len = (fmd_xlen - (len + 6)) / 2;
i = fmd_widgets [FMBLFT].relative_x = len + 3;
i += strlen (fmd_widgets [FMBLFT].text) + 8;
#ifdef FMBMID
fmd_widgets [FMBMID].relative_x = i;
i += strlen (fmd_widgets [FMBMID].text) + 6;
#endif
fmd_widgets [FMBRGT].relative_x = i;
#define chkbox_xpos(i) \
fmd_widgets [i].relative_x = fmd_xlen - strlen (fmd_widgets [i].text) - 6
chkbox_xpos(FMCB0);
chkbox_xpos(FMCB21);
chkbox_xpos(FMCB22);
if (fmd_xlen != FMD_XLEN)
{
i = sizeof (fmd_widgets) / sizeof (fmd_widgets [0]) - 1;
while (i--)
fmd_widgets [i].x_divisions = fmd_xlen;
fmd_widgets [FMDI1].hotkey_pos =
fmd_widgets [FMDI2].hotkey_pos = fmd_xlen - 6;
}
#undef chkbox_xpos
#endif /* ENABLE_NLS */
fmd_i18n_flag = 1;
}
char *
file_mask_dialog (int operation, char *text, char *def_text, int only_one, int *do_background)
{
int source_easy_patterns = easy_patterns;
char *source_mask, *orig_mask, *dest_dir;
const char *error;
struct stat buf;
int val;
QuickDialog Quick_input;
if (!fmd_i18n_flag)
fmd_init_i18n();
stable_symlinks = 0;
fmd_widgets [FMDC].result = &source_easy_patterns;
fmd_widgets [FMDI1].text = easy_patterns ? "*" : "^\\(.*\\)$";
Quick_input.xlen = fmd_xlen;
Quick_input.xpos = -1;
Quick_input.title = op_names [operation];
Quick_input.help = "[Mask Copy/Rename]";
Quick_input.ylen = FMDY;
Quick_input.i18n = 1;
if (operation == OP_COPY) {
Quick_input.class = "quick_file_mask_copy";
Quick_input.widgets = fmd_widgets;
} else { /* operation == OP_MOVE */
Quick_input.class = "quick_file_mask_move";
Quick_input.widgets = fmd_widgets + 2;
}
fmd_widgets [FMDI0].text = text;
fmd_widgets [FMDI2].text = def_text;
fmd_widgets [FMDI2].str_result = &dest_dir;
fmd_widgets [FMDI1].str_result = &source_mask;
*do_background = 0;
ask_file_mask:
if ((val = quick_dialog_skip (&Quick_input, SKIP)) == B_CANCEL)
return 0;
if (op_follow_links && operation != OP_MOVE)
xstat = mc_stat;
else
xstat = mc_lstat;
if (op_preserve || operation == OP_MOVE) {
preserve = 1;
umask_kill = 0777777;
preserve_uidgid = (geteuid () == 0) ? 1 : 0;
}
else {
int i;
preserve = preserve_uidgid = 0;
i = umask (0);
umask (i);
umask_kill = i ^ 0777777;
}
orig_mask = source_mask;
if (!dest_dir || !*dest_dir) {
if (source_mask)
free (source_mask);
return dest_dir;
}
if (source_easy_patterns) {
source_easy_patterns = easy_patterns;
easy_patterns = 1;
source_mask = convert_pattern (source_mask, match_file, 1);
easy_patterns = source_easy_patterns;
error = re_compile_pattern (source_mask, strlen (source_mask), &rx);
free (source_mask);
} else
error = re_compile_pattern (source_mask, strlen (source_mask), &rx);
if (error) {
message_3s (1, MSG_ERROR, _("Invalid source pattern `%s' \n %s "),
orig_mask, error);
if (orig_mask)
free (orig_mask);
goto ask_file_mask;
}
if (orig_mask)
free (orig_mask);
dest_mask = strrchr (dest_dir, PATH_SEP);
if (dest_mask == NULL)
dest_mask = dest_dir;
else
dest_mask++;
orig_mask = dest_mask;
if (!*dest_mask || (!dive_into_subdirs && !is_wildcarded (dest_mask) &&
(!only_one || (!mc_stat (dest_dir, &buf) && S_ISDIR (buf.st_mode)))) ||
(dive_into_subdirs && ((!only_one && !is_wildcarded (dest_mask)) ||
(only_one && !mc_stat (dest_dir, &buf) && S_ISDIR (buf.st_mode)))))
dest_mask = strdup ("*");
else {
dest_mask = strdup (dest_mask);
*orig_mask = 0;
}
if (!*dest_dir) {
free (dest_dir);
dest_dir = strdup ("./");
}
if (val == B_USER)
*do_background = 1;
return dest_dir;
}
/*
* This array introduced to avoid translation problems. The former (op_names)
* is assumed to be nouns, suitable in dialog box titles; this one should
* contain whatever is used in prompt itself (i.e. in russian, it's verb).
* Notice first symbol - it is to fool gettext and force these strings to
* be different for it. First symbol is skipped while building a prompt.
* (I don't use spaces around the words, because someday they could be
* dropped, when widgets get smarter)
*/
static char *op_names1 [] = { N_("1Copy"), N_("1Move"), N_("1Delete") };
/*
* These are formats for building a prompt. Parts encoded as follows:
* %o - operation from op_names1
* %f - file/files or files/directories, as appropriate
* %m - "with source mask" or question mark for delete
* %s - source name (truncated)
* %d - number of marked files
*/
static char* one_format = N_("%o %f \"%s\"%m");
static char* many_format = N_("%o %d %f%m");
static char* prompt_parts [] =
{
N_("file"), N_("files"), N_("directory"), N_("directories"),
N_("files/directories"), N_(" with source mask:")
};
static char*
generate_prompt(char* cmd_buf, WPanel* panel, int operation, int only_one,
struct stat* src_stat)
{
register char *sp, *cp;
register int i;
char format_string [200];
char *dp = format_string;
char* source = NULL;
#ifdef ENABLE_NLS
static int i18n_flag = 0;
if (!i18n_flag)
{
if (!fmd_i18n_flag)
fmd_init_i18n(); /* to get proper fmd_xlen */
for (i = sizeof (op_names1) / sizeof (op_names1 [0]); i--;)
op_names1 [i] = _(op_names1 [i]);
for (i = sizeof (prompt_parts) / sizeof (prompt_parts [0]); i--;)
prompt_parts [i] = _(prompt_parts [i]);
one_format = _(one_format);
many_format = _(many_format);
i18n_flag = 1;
}
#endif /* ENABLE_NLS */
sp = only_one ? one_format : many_format;
if (only_one)
source = get_file (panel, src_stat);
while (*sp)
{
switch (*sp)
{
case '%':
cp = NULL;
switch (sp[1])
{
case 'o':
cp = op_names1 [operation] + 1;
break;
case 'm':
cp = operation == OP_DELETE ? "?" : prompt_parts [5];
break;
case 'f':
if (only_one)
{
cp = S_ISDIR (src_stat->st_mode) ?
prompt_parts [2] : prompt_parts [0];
}
else
{
cp = (panel->marked == panel->dirs_marked)
? prompt_parts [3]
: (panel->dirs_marked ? prompt_parts [4]
: prompt_parts [1]);
}
break;
default:
*dp++ = *sp++;
}
if (cp)
{
sp += 2;
while (*cp)
*dp++ = *cp++;
}
break;
default:
*dp++ = *sp++;
}
}
*dp = '\0';
if (only_one)
{
i = fmd_xlen - strlen(format_string) - 4;
sprintf (cmd_buf, format_string, name_trunc (source, i));
}
else
{
sprintf (cmd_buf, format_string, panel->marked);
i = strlen (cmd_buf) + 6 - fmd_xlen;
if (i > 0)
{
fmd_xlen += i;
fmd_init_i18n(); /* to recalculate positions of child widgets */
}
}
return source;
}
/* Returns 1 if did change the directory structure,
Returns 0 if user aborted */
int
panel_operate (void *source_panel, int operation, char *thedefault)
{
WPanel *panel = source_panel;
#ifdef WITH_FULL_PATHS
char *source_with_path = NULL;
#else
# define source_with_path source
#endif
char *source = NULL;
char *dest = NULL;
char *temp = NULL;
int only_one = (get_current_type () == view_tree) || (panel->marked <= 1);
struct stat src_stat, dst_stat;
int i, value;
long marked, total;
long count = 0, bytes = 0;
int dst_result;
int do_bg; /* do background operation? */
do_bg = 0;
rx.buffer = NULL;
free_linklist (&linklist);
free_linklist (&dest_dirs);
if (get_current_type () == view_listing)
if (!panel->marked && !strcmp (selection (panel)->fname, "..")){
message (1, MSG_ERROR, _(" Can't operate on \"..\"! "));
return 0;
}
if (operation < OP_COPY || operation > OP_DELETE)
return 0;
/* Generate confirmation prompt */
source = generate_prompt(cmd_buf, panel, operation, only_one, &src_stat);
/* Show confirmation dialog */
if (operation == OP_DELETE && confirm_delete){
if (know_not_what_am_i_doing)
query_set_sel (1);
i = query_dialog (_(op_names [operation]), cmd_buf,
D_ERROR, 2, _("&Yes"), _("&No"));
if (i != 0)
return 0;
} else if (operation != OP_DELETE) {
char *dest_dir;
if (thedefault != NULL)
dest_dir = thedefault;
else if (get_other_type () == view_listing)
dest_dir = opanel->cwd;
else
dest_dir = panel->cwd;
rx.buffer = (unsigned char *) xmalloc (MC_MAXPATHLEN, "mask copying");
rx.allocated = MC_MAXPATHLEN;
rx.translate = 0;
dest = file_mask_dialog (operation, cmd_buf, dest_dir, only_one, &do_bg);
if (!dest) {
free (rx.buffer);
return 0;
}
if (!*dest){
free (rx.buffer);
free (dest);
return 0;
}
}
#ifdef WITH_BACKGROUND
/* Did the user select to do a background operation? */
if (do_bg){
int v;
v = do_background (copy_strings (operation_names [operation], ": ", panel->cwd, 0));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -