/* *INDENT-OFF* */ START_PARAMETRIZED_TEST (test_path_to_str_flags, test_path_to_str_flags_ds) /* *INDENT-ON* */ { /* given */ vfs_path_t *vpath; char *str_path; test_init_vfs ("UTF-8"); test_subclass1.flags = VFS_S_REMOTE; vfs_s_init_class (&vfs_test_ops1, &test_subclass1); vfs_test_ops1.name = "testfs1"; vfs_test_ops1.flags = VFSF_NOLINKS; vfs_test_ops1.prefix = "test1"; vfs_register_class (&vfs_test_ops1); /* when */ vpath = vfs_path_from_str_flags (data->input_path, data->input_from_str_flags); str_path = vfs_path_to_str_flags (vpath, 0, data->input_to_str_flags); /* then */ mctest_assert_str_eq (str_path, data->expected_path); g_free (str_path); vfs_path_free (vpath); test_deinit_vfs (); }
void title_path_prepare (char **path, char **login) { char host[BUF_TINY]; struct passwd *pw = NULL; int res = 0; *login = NULL; *path = vfs_path_to_str_flags (current_panel->cwd_vpath, 0, VPF_STRIP_HOME | VPF_STRIP_PASSWORD); res = gethostname (host, sizeof (host)); if (res) { /* On success, res = 0 */ host[0] = '\0'; } else { host[sizeof (host) - 1] = '\0'; } pw = getpwuid (getuid ()); if (pw) { *login = g_strdup_printf ("%s@%s", pw->pw_name, host); } else { *login = g_strdup (host); } }
const char * path_trunc (const char *path, size_t trunc_len) { vfs_path_t *vpath; char *secure_path; const char *ret; vpath = vfs_path_from_str (path); secure_path = vfs_path_to_str_flags (vpath, 0, VPF_STRIP_PASSWORD); vfs_path_free (vpath); ret = str_trunc (secure_path, trunc_len); g_free (secure_path); return ret; }
/* *INDENT-OFF* */ END_PARAMETRIZED_TEST /* *INDENT-ON* */ /* --------------------------------------------------------------------------------------------- */ /* Relative to panel_correct_path_to_show() */ /* @Test */ /* *INDENT-OFF* */ START_TEST (test_vpath_to_str_filter) /* *INDENT-ON* */ { /* given */ vfs_path_t *vpath, *last_vpath; char *filtered_path; const vfs_path_element_t *path_element; /* when */ vpath = vfs_path_from_str ("/test1://some.host/dir"); path_element = vfs_path_element_clone (vfs_path_get_by_index (vpath, -1)); vfs_path_free (vpath); last_vpath = vfs_path_new (); last_vpath->relative = TRUE; vfs_path_add_element (last_vpath, path_element); filtered_path = vfs_path_to_str_flags (last_vpath, 0, VPF_STRIP_HOME | VPF_STRIP_PASSWORD | VPF_HIDE_CHARSET); /* then */ mctest_assert_str_eq (filtered_path, "test1://some.host/dir"); vfs_path_free (last_vpath); g_free (filtered_path); }
/** If it actually changed the directory it returns true */ void do_subshell_chdir (const vfs_path_t * vpath, gboolean update_prompt) { char *pcwd; pcwd = vfs_path_to_str_flags (current_panel->cwd_vpath, 0, VPF_RECODE); if (!(subshell_state == INACTIVE && strcmp (subshell_cwd, pcwd) != 0)) { /* We have to repaint the subshell prompt if we read it from * the main program. Please note that in the code after this * if, the cd command that is sent will make the subshell * repaint the prompt, so we don't have to paint it. */ if (update_prompt) do_update_prompt (); g_free (pcwd); return; } /* The initial space keeps this out of the command history (in bash because we set "HISTCONTROL=ignorespace") */ write_all (mc_global.tty.subshell_pty, " cd ", 4); if (vpath != NULL) { char *translate; translate = vfs_translate_path_n (vfs_path_as_str (vpath)); if (translate != NULL) { GString *temp; temp = subshell_name_quote (translate); write_all (mc_global.tty.subshell_pty, temp->str, temp->len); g_string_free (temp, TRUE); g_free (translate); } else { write_all (mc_global.tty.subshell_pty, ".", 1); } } else { write_all (mc_global.tty.subshell_pty, "/", 1); } write_all (mc_global.tty.subshell_pty, "\n", 1); subshell_state = RUNNING_COMMAND; feed_subshell (QUIETLY, FALSE); if (subshell_alive) { int bPathNotEq = strcmp (subshell_cwd, pcwd); if (bPathNotEq && subshell_type == TCSH) { char rp_subshell_cwd[PATH_MAX]; char rp_current_panel_cwd[PATH_MAX]; char *p_subshell_cwd = mc_realpath (subshell_cwd, rp_subshell_cwd); char *p_current_panel_cwd = mc_realpath (pcwd, rp_current_panel_cwd); if (p_subshell_cwd == NULL) p_subshell_cwd = subshell_cwd; if (p_current_panel_cwd == NULL) p_current_panel_cwd = pcwd; bPathNotEq = strcmp (p_subshell_cwd, p_current_panel_cwd); } if (bPathNotEq && !DIR_IS_DOT (pcwd)) { char *cwd; cwd = vfs_path_to_str_flags (current_panel->cwd_vpath, 0, VPF_STRIP_PASSWORD); vfs_print_message (_("Warning: Cannot change to %s.\n"), cwd); g_free (cwd); } } update_subshell_prompt = FALSE; g_free (pcwd); /* Make sure that MC never stores the CWD in a silly format */ /* like /usr////lib/../bin, or the strcmp() above will fail */ }
/* * FIXME: probably it is better to replace this with quick dialog machinery, * but actually I'm not familiar with it and have not much time :( * alex */ static replace_action_t overwrite_query_dialog (file_op_context_t * ctx, enum OperationMode mode) { #define ADD_RD_BUTTON(i, ypos) \ add_widget_autopos (ui->replace_dlg, \ button_new (ypos, rd_widgets [i].xpos, rd_widgets [i].value, \ NORMAL_BUTTON, rd_widgets [i].text, NULL), \ rd_widgets [i].pos_flags, ui->replace_dlg->current->data) #define ADD_RD_LABEL(i, p1, p2, ypos) \ g_snprintf (buffer, sizeof (buffer), rd_widgets [i].text, p1, p2); \ label2 = WIDGET (label_new (ypos, rd_widgets [i].xpos, buffer)); \ add_widget_autopos (ui->replace_dlg, label2, rd_widgets [i].pos_flags, \ ui->replace_dlg->current != NULL ? ui->replace_dlg->current->data : NULL) /* dialog sizes */ const int rd_ylen = 1; int rd_xlen = 60; int y = 2; unsigned long yes_id; struct { const char *text; int ypos, xpos; widget_pos_flags_t pos_flags; int value; /* 0 for labels */ } rd_widgets[] = { /* *INDENT-OFF* */ /* 0 */ { N_("Target file already exists!"), 3, 4, WPOS_KEEP_TOP | WPOS_CENTER_HORZ, 0 }, /* 1 */ { "%s", 4, 4, WPOS_KEEP_TOP | WPOS_CENTER_HORZ, 0 }, /* 2 */ { N_("New : %s, size %s"), 6, 4, WPOS_KEEP_DEFAULT, 0 }, /* 3 */ { N_("Existing: %s, size %s"), 7, 4, WPOS_KEEP_DEFAULT, 0 }, /* 4 */ { N_("Overwrite this target?"), 9, 4, WPOS_KEEP_DEFAULT, 0 }, /* 5 */ { N_("&Yes"), 9, 28, WPOS_KEEP_DEFAULT, REPLACE_YES }, /* 6 */ { N_("&No"), 9, 37, WPOS_KEEP_DEFAULT, REPLACE_NO }, /* 7 */ { N_("A&ppend"), 9, 45, WPOS_KEEP_DEFAULT, REPLACE_APPEND }, /* 8 */ { N_("&Reget"), 10, 28, WPOS_KEEP_DEFAULT, REPLACE_REGET }, /* 9 */ { N_("Overwrite all targets?"), 11, 4, WPOS_KEEP_DEFAULT, 0 }, /* 10 */ { N_("A&ll"), 11, 28, WPOS_KEEP_DEFAULT, REPLACE_ALWAYS }, /* 11 */ { N_("&Update"), 11, 36, WPOS_KEEP_DEFAULT, REPLACE_UPDATE }, /* 12 */ { N_("Non&e"), 11, 47, WPOS_KEEP_DEFAULT, REPLACE_NEVER }, /* 13 */ { N_("If &size differs"), 12, 28, WPOS_KEEP_DEFAULT, REPLACE_SIZE }, /* 14 */ { N_("&Abort"), 14, 25, WPOS_KEEP_TOP | WPOS_CENTER_HORZ, REPLACE_ABORT } /* *INDENT-ON* */ }; const size_t num = G_N_ELEMENTS (rd_widgets); int *widgets_len; file_op_context_ui_t *ui = ctx->ui; char buffer[BUF_SMALL]; char fsize_buffer[BUF_SMALL]; Widget *label1, *label2; const char *title; vfs_path_t *stripped_vpath; const char *stripped_name; char *stripped_name_orig; int result; widgets_len = g_new0 (int, num); if (mode == Foreground) title = _("File exists"); else title = _("Background process: File exists"); stripped_vpath = vfs_path_from_str (ui->replace_filename); stripped_name = stripped_name_orig = vfs_path_to_str_flags (stripped_vpath, 0, VPF_STRIP_HOME | VPF_STRIP_PASSWORD); vfs_path_free (stripped_vpath); { size_t i; int l1, l2, l, row; int stripped_name_len; for (i = 0; i < num; i++) { #ifdef ENABLE_NLS if (i != 1) /* skip filename */ rd_widgets[i].text = _(rd_widgets[i].text); #endif /* ENABLE_NLS */ widgets_len[i] = str_term_width1 (rd_widgets[i].text); } /* * longest of "Overwrite..." labels * (assume "Target date..." are short enough) */ l1 = max (widgets_len[9], widgets_len[4]); /* longest of button rows */ l = l2 = 0; row = 0; for (i = 1; i < num - 1; i++) if (rd_widgets[i].value != 0) { if (row != rd_widgets[i].ypos) { row = rd_widgets[i].ypos; l2 = max (l2, l); l = 0; } l += widgets_len[i] + 4; } l2 = max (l2, l); /* last row */ rd_xlen = max (rd_xlen, l1 + l2 + 8); /* rd_xlen = max (rd_xlen, str_term_width1 (title) + 2); */ stripped_name_len = str_term_width1 (stripped_name); rd_xlen = max (rd_xlen, min (COLS, stripped_name_len + 8)); /* Now place widgets */ l1 += 5; /* start of first button in the row */ l = l1; row = 0; for (i = 2; i < num - 1; i++) if (rd_widgets[i].value != 0) { if (row != rd_widgets[i].ypos) { row = rd_widgets[i].ypos; l = l1; } rd_widgets[i].xpos = l; l += widgets_len[i] + 4; } } /* FIXME - missing help node */ ui->replace_dlg = dlg_create (TRUE, 0, 0, rd_ylen, rd_xlen, alarm_colors, NULL, NULL, "[Replace]", title, DLG_CENTER); /* prompt */ ADD_RD_LABEL (0, "", "", y++); /* file name */ ADD_RD_LABEL (1, "", "", y++); label1 = label2; add_widget (ui->replace_dlg, hline_new (y++, -1, -1)); /* source date and size */ size_trunc_len (fsize_buffer, sizeof (fsize_buffer), ui->s_stat->st_size, 0, panels_options.kilobyte_si); ADD_RD_LABEL (2, file_date (ui->s_stat->st_mtime), fsize_buffer, y++); rd_xlen = max (rd_xlen, label2->cols + 8); /* destination date and size */ size_trunc_len (fsize_buffer, sizeof (fsize_buffer), ui->d_stat->st_size, 0, panels_options.kilobyte_si); ADD_RD_LABEL (3, file_date (ui->d_stat->st_mtime), fsize_buffer, y++); rd_xlen = max (rd_xlen, label2->cols + 8); add_widget (ui->replace_dlg, hline_new (y++, -1, -1)); ADD_RD_LABEL (4, 0, 0, y); /* Overwrite this target? */ yes_id = ADD_RD_BUTTON (5, y); /* Yes */ ADD_RD_BUTTON (6, y); /* No */ /* "this target..." widgets */ if (!S_ISDIR (ui->d_stat->st_mode)) { ADD_RD_BUTTON (7, y++); /* Append */ if ((ctx->operation == OP_COPY) && (ui->d_stat->st_size != 0) && (ui->s_stat->st_size > ui->d_stat->st_size)) ADD_RD_BUTTON (8, y++); /* Reget */ } add_widget (ui->replace_dlg, hline_new (y++, -1, -1)); ADD_RD_LABEL (9, 0, 0, y); /* Overwrite all targets? */ ADD_RD_BUTTON (10, y); /* All" */ ADD_RD_BUTTON (11, y); /* Update */ ADD_RD_BUTTON (12, y++); /* None */ ADD_RD_BUTTON (13, y++); /* If size differs */ add_widget (ui->replace_dlg, hline_new (y++, -1, -1)); ADD_RD_BUTTON (14, y); /* Abort */ label_set_text (LABEL (label1), str_trunc (stripped_name, rd_xlen - 8)); dlg_set_size (ui->replace_dlg, y + 3, rd_xlen); dlg_select_by_id (ui->replace_dlg, yes_id); result = dlg_run (ui->replace_dlg); dlg_destroy (ui->replace_dlg); g_free (widgets_len); g_free (stripped_name_orig); return (result == B_CANCEL) ? REPLACE_ABORT : (replace_action_t) result; #undef ADD_RD_LABEL #undef ADD_RD_BUTTON }
char * file_mask_dialog (file_op_context_t * ctx, FileOperation operation, gboolean only_one, const char *format, const void *text, const char *def_text, gboolean * do_bg) { size_t fmd_xlen; vfs_path_t *vpath; int source_easy_patterns = easy_patterns; char fmd_buf[BUF_MEDIUM]; char *dest_dir, *tmp; char *def_text_secure; if (ctx == NULL) return NULL; /* unselect checkbox if target filesystem don't support attributes */ ctx->op_preserve = filegui__check_attrs_on_fs (def_text); ctx->stable_symlinks = FALSE; *do_bg = FALSE; /* filter out a possible password from def_text */ vpath = vfs_path_from_str_flags (def_text, only_one ? VPF_NO_CANON : VPF_NONE); tmp = vfs_path_to_str_flags (vpath, 0, VPF_STRIP_PASSWORD); vfs_path_free (vpath); if (source_easy_patterns) def_text_secure = strutils_glob_escape (tmp); else def_text_secure = strutils_regex_escape (tmp); g_free (tmp); if (only_one) { int format_len, text_len; int max_len; format_len = str_term_width1 (format); text_len = str_term_width1 (text); max_len = COLS - 2 - 6; if (format_len + text_len <= max_len) { fmd_xlen = format_len + text_len + 6; fmd_xlen = max (fmd_xlen, 68); } else { text = str_trunc ((const char *) text, max_len - format_len); fmd_xlen = max_len + 6; } g_snprintf (fmd_buf, sizeof (fmd_buf), format, (const char *) text); } else { fmd_xlen = COLS * 2 / 3; fmd_xlen = max (fmd_xlen, 68); g_snprintf (fmd_buf, sizeof (fmd_buf), format, *(const int *) text); } { char *source_mask, *orig_mask; int val; struct stat buf; quick_widget_t quick_widgets[] = { /* *INDENT-OFF* */ QUICK_LABELED_INPUT (fmd_buf, input_label_above, easy_patterns ? "*" : "^(.*)$", "input-def", &source_mask, NULL, FALSE, FALSE, INPUT_COMPLETE_FILENAMES), QUICK_START_COLUMNS, QUICK_SEPARATOR (FALSE), QUICK_NEXT_COLUMN, QUICK_CHECKBOX (N_("&Using shell patterns"), &source_easy_patterns, NULL), QUICK_STOP_COLUMNS, QUICK_LABELED_INPUT (N_("to:"), input_label_above, def_text_secure, "input2", &dest_dir, NULL, FALSE, FALSE, INPUT_COMPLETE_FILENAMES), QUICK_SEPARATOR (TRUE), QUICK_START_COLUMNS, QUICK_CHECKBOX (N_("Follow &links"), &ctx->follow_links, NULL), QUICK_CHECKBOX (N_("Preserve &attributes"), &ctx->op_preserve, NULL), QUICK_NEXT_COLUMN, QUICK_CHECKBOX (N_("Di&ve into subdir if exists"), &ctx->dive_into_subdirs, NULL), QUICK_CHECKBOX (N_("&Stable symlinks"), &ctx->stable_symlinks, NULL), QUICK_STOP_COLUMNS, QUICK_START_BUTTONS (TRUE, TRUE), QUICK_BUTTON (N_("&OK"), B_ENTER, NULL, NULL), #ifdef ENABLE_BACKGROUND QUICK_BUTTON (N_("&Background"), B_USER, NULL, NULL), #endif /* ENABLE_BACKGROUND */ QUICK_BUTTON (N_("&Cancel"), B_CANCEL, NULL, NULL), QUICK_END /* *INDENT-ON* */ }; quick_dialog_t qdlg = { -1, -1, fmd_xlen, op_names[operation], "[Mask Copy/Rename]", quick_widgets, NULL, NULL }; ask_file_mask: val = quick_dialog_skip (&qdlg, 4); if (val == B_CANCEL) { g_free (def_text_secure); return NULL; } if (ctx->follow_links) ctx->stat_func = mc_stat; else ctx->stat_func = mc_lstat; if (ctx->op_preserve) { ctx->preserve = TRUE; ctx->umask_kill = 0777777; ctx->preserve_uidgid = (geteuid () == 0); } else { int i2; ctx->preserve = ctx->preserve_uidgid = FALSE; i2 = umask (0); umask (i2); ctx->umask_kill = i2 ^ 0777777; } if ((dest_dir == NULL) || (*dest_dir == '\0')) { g_free (def_text_secure); g_free (source_mask); return dest_dir; } ctx->search_handle = mc_search_new (source_mask, -1, NULL); if (ctx->search_handle == NULL) { message (D_ERROR, MSG_ERROR, _("Invalid source pattern '%s'"), source_mask); g_free (dest_dir); g_free (source_mask); goto ask_file_mask; } g_free (def_text_secure); g_free (source_mask); ctx->search_handle->is_case_sensitive = TRUE; if (source_easy_patterns) ctx->search_handle->search_type = MC_SEARCH_T_GLOB; else ctx->search_handle->search_type = MC_SEARCH_T_REGEX; vpath = vfs_path_from_str (dest_dir); ctx->dest_mask = strrchr (dest_dir, PATH_SEP); if (ctx->dest_mask == NULL) ctx->dest_mask = dest_dir; else ctx->dest_mask++; orig_mask = ctx->dest_mask; if (*ctx->dest_mask == '\0' || (!ctx->dive_into_subdirs && !is_wildcarded (ctx->dest_mask) && (!only_one || (mc_stat (vpath, &buf) == 0 && S_ISDIR (buf.st_mode)))) || (ctx->dive_into_subdirs && ((!only_one && !is_wildcarded (ctx->dest_mask)) || (only_one && mc_stat (vpath, &buf) == 0 && S_ISDIR (buf.st_mode))))) ctx->dest_mask = g_strdup ("\\0"); else { ctx->dest_mask = g_strdup (ctx->dest_mask); *orig_mask = '\0'; } if (*dest_dir == '\0') { g_free (dest_dir); dest_dir = g_strdup ("./"); } vfs_path_free (vpath); if (val == B_USER) *do_bg = TRUE; } return dest_dir; }
void do_cd_command (char *orig_cmd) { int len; int operand_pos = CD_OPERAND_OFFSET; const char *cmd; /* Any final whitespace should be removed here (to see why, try "cd fred "). */ /* NOTE: I think we should not remove the extra space, that way, we can cd into hidden directories */ /* FIXME: what about interpreting quoted strings like the shell. so one could type "cd <tab> M-a <enter>" and it would work. */ len = strlen (orig_cmd) - 1; while (len >= 0 && (orig_cmd[len] == ' ' || orig_cmd[len] == '\t' || orig_cmd[len] == '\n')) { orig_cmd[len] = 0; len--; } cmd = orig_cmd; if (cmd[CD_OPERAND_OFFSET - 1] == 0) cmd = "cd "; /* 0..2 => given text, 3 => \0 */ /* allow any amount of white space in front of the path operand */ while (cmd[operand_pos] == ' ' || cmd[operand_pos] == '\t') operand_pos++; if (get_current_type () == view_tree) { if (cmd[0] == 0) { sync_tree (mc_config_get_home_dir ()); } else if (DIR_IS_DOTDOT (cmd + operand_pos)) { if (vfs_path_elements_count (current_panel->cwd_vpath) != 1 || strlen (vfs_path_get_by_index (current_panel->cwd_vpath, 0)->path) > 1) { vfs_path_t *tmp_vpath = current_panel->cwd_vpath; current_panel->cwd_vpath = vfs_path_vtokens_get (tmp_vpath, 0, vfs_path_tokens_count (tmp_vpath) - 1); vfs_path_free (tmp_vpath); } sync_tree (vfs_path_as_str (current_panel->cwd_vpath)); } else if (cmd[operand_pos] == PATH_SEP) { sync_tree (cmd + operand_pos); } else { vfs_path_t *new_vpath; new_vpath = vfs_path_append_new (current_panel->cwd_vpath, cmd + operand_pos, NULL); sync_tree (vfs_path_as_str (new_vpath)); vfs_path_free (new_vpath); } } else { char *path; vfs_path_t *q_vpath; gboolean ok; path = examine_cd (&cmd[operand_pos]); if (*path == '\0') q_vpath = vfs_path_from_str (mc_config_get_home_dir ()); else q_vpath = vfs_path_from_str_flags (path, VPF_NO_CANON); ok = do_cd (q_vpath, cd_parse_command); if (!ok) ok = handle_cdpath (path); if (!ok) { char *d; d = vfs_path_to_str_flags (q_vpath, 0, VPF_STRIP_PASSWORD); message (D_ERROR, MSG_ERROR, _("Cannot chdir to \"%s\"\n%s"), d, unix_error_string (errno)); g_free (d); } vfs_path_free (q_vpath); g_free (path); } }
/* * FIXME: probably it is better to replace this with quick dialog machinery, * but actually I'm not familiar with it and have not much time :( * alex */ static replace_action_t overwrite_query_dialog (FileOpContext * ctx, enum OperationMode mode) { #define ADD_RD_BUTTON(i) \ add_widget (ui->replace_dlg, \ button_new (rd_widgets [i].ypos, rd_widgets [i].xpos, rd_widgets [i].value, \ NORMAL_BUTTON, rd_widgets [i].text, 0)) #define ADD_RD_LABEL(i, p1, p2) \ g_snprintf (buffer, sizeof (buffer), rd_widgets [i].text, p1, p2); \ add_widget (ui->replace_dlg, label_new (rd_widgets [i].ypos, rd_widgets [i].xpos, buffer)) /* dialog sizes */ const int rd_ylen = 17; int rd_xlen = 60; struct { const char *text; int ypos, xpos; int value; /* 0 for labels */ } rd_widgets[] = { /* *INDENT-OFF* */ /* 0 */ { N_("Target file already exists!"), 3, 4, 0 }, /* 1 */ { "%s", 4, 4, 0 }, /* 2 */ /* cannot use PRIuMAX here; %llu is used instead */ { N_("Source date: %s, size %llu"), 6, 4, 0 }, /* 3 */ /* cannot use PRIuMAX here; %llu is used instead */ { N_("Target date: %s, size %llu"), 7, 4, 0 }, /* 4 */ { N_("&Abort"), 14, 25, REPLACE_ABORT }, /* 5 */ { N_("If &size differs"), 12, 28, REPLACE_SIZE }, /* 6 */ { N_("Non&e"), 11, 47, REPLACE_NEVER }, /* 7 */ { N_("&Update"), 11, 36, REPLACE_UPDATE }, /* 8 */ { N_("A&ll"), 11, 28, REPLACE_ALWAYS }, /* 9 */ { N_("Overwrite all targets?"), 11, 4, 0 }, /* 10 */ { N_("&Reget"), 10, 28, REPLACE_REGET }, /* 11 */ { N_("A&ppend"), 9, 45, REPLACE_APPEND }, /* 12 */ { N_("&No"), 9, 37, REPLACE_NO }, /* 13 */ { N_("&Yes"), 9, 28, REPLACE_YES }, /* 14 */ { N_("Overwrite this target?"), 9, 4, 0 } /* *INDENT-ON* */ }; const int num = sizeof (rd_widgets) / sizeof (rd_widgets[0]); int *widgets_len; FileOpContextUI *ui = ctx->ui; char buffer[BUF_SMALL]; const char *title; int stripped_name_len; vfs_path_t *stripped_vpath; const char *stripped_name; char *stripped_name_orig; int result; widgets_len = g_new0 (int, num); if (mode == Foreground) title = _("File exists"); else title = _("Background process: File exists"); stripped_vpath = vfs_path_from_str (ui->replace_filename); stripped_name = stripped_name_orig = vfs_path_to_str_flags (stripped_vpath, 0, VPF_STRIP_HOME | VPF_STRIP_PASSWORD); vfs_path_free (stripped_vpath); stripped_name_len = str_term_width1 (stripped_name); { int i, l1, l2, l, row; for (i = 0; i < num; i++) { #ifdef ENABLE_NLS if (i != 1) /* skip filename */ rd_widgets[i].text = _(rd_widgets[i].text); #endif /* ENABLE_NLS */ widgets_len[i] = str_term_width1 (rd_widgets[i].text); } /* * longest of "Overwrite..." labels * (assume "Target date..." are short enough) */ l1 = max (widgets_len[9], widgets_len[14]); /* longest of button rows */ i = num; for (row = l = l2 = 0; i--;) if (rd_widgets[i].value != 0) { if (row != rd_widgets[i].ypos) { row = rd_widgets[i].ypos; l2 = max (l2, l); l = 0; } l += widgets_len[i] + 4; } l2 = max (l2, l); /* last row */ rd_xlen = max (rd_xlen, l1 + l2 + 8); rd_xlen = max (rd_xlen, str_term_width1 (title) + 2); rd_xlen = max (rd_xlen, min (COLS, stripped_name_len + 8)); /* Now place widgets */ l1 += 5; /* start of first button in the row */ i = num; for (l = l1, row = 0; --i > 1;) if (rd_widgets[i].value != 0) { if (row != rd_widgets[i].ypos) { row = rd_widgets[i].ypos; l = l1; } rd_widgets[i].xpos = l; l += widgets_len[i] + 4; } /* Abort button is centered */ rd_widgets[4].xpos = (rd_xlen - widgets_len[4] - 3) / 2; } /* FIXME - missing help node */ ui->replace_dlg = create_dlg (TRUE, 0, 0, rd_ylen, rd_xlen, alarm_colors, NULL, NULL, "[Replace]", title, DLG_CENTER | DLG_REVERSE); /* prompt -- centered */ add_widget (ui->replace_dlg, label_new (rd_widgets[0].ypos, (rd_xlen - widgets_len[0]) / 2, rd_widgets[0].text)); /* file name -- centered */ stripped_name = str_trunc (stripped_name, rd_xlen - 8); stripped_name_len = str_term_width1 (stripped_name); add_widget (ui->replace_dlg, label_new (rd_widgets[1].ypos, (rd_xlen - stripped_name_len) / 2, stripped_name)); /* source date and size */ ADD_RD_LABEL (2, file_date (ui->s_stat->st_mtime), (unsigned long long) ui->s_stat->st_size); /* destination date and size */ ADD_RD_LABEL (3, file_date (ui->d_stat->st_mtime), (unsigned long long) ui->d_stat->st_size); ADD_RD_BUTTON (4); /* Abort */ ADD_RD_BUTTON (5); /* If size differs */ ADD_RD_BUTTON (6); /* None */ ADD_RD_BUTTON (7); /* Update */ ADD_RD_BUTTON (8); /* All" */ ADD_RD_LABEL (9, 0, 0); /* Overwrite all targets? */ /* "this target..." widgets */ if (!S_ISDIR (ui->d_stat->st_mode)) { if ((ctx->operation == OP_COPY) && (ui->d_stat->st_size != 0) && (ui->s_stat->st_size > ui->d_stat->st_size)) ADD_RD_BUTTON (10); /* Reget */ ADD_RD_BUTTON (11); /* Append */ } ADD_RD_BUTTON (12); /* No */ ADD_RD_BUTTON (13); /* Yes */ ADD_RD_LABEL (14, 0, 0); /* Overwrite this target? */ result = run_dlg (ui->replace_dlg); destroy_dlg (ui->replace_dlg); g_free (widgets_len); g_free (stripped_name_orig); return (result == B_CANCEL) ? REPLACE_ABORT : (replace_action_t) result; #undef ADD_RD_LABEL #undef ADD_RD_BUTTON }
char * file_mask_dialog (FileOpContext * ctx, FileOperation operation, gboolean only_one, const char *format, const void *text, const char *def_text, gboolean * do_bg) { const size_t FMDY = 13; const size_t FMDX = 68; size_t fmd_xlen; /* buttons */ const size_t gap = 1; size_t b0_len, b2_len; size_t b1_len = 0; int source_easy_patterns = easy_patterns; size_t i, len; char fmd_buf[BUF_MEDIUM]; char *source_mask, *orig_mask, *dest_dir, *tmp; char *def_text_secure; int val; QuickWidget fmd_widgets[] = { /* 0 */ QUICK_BUTTON (42, 64, 10, FMDY, N_("&Cancel"), B_CANCEL, NULL), #ifdef ENABLE_BACKGROUND /* 1 */ QUICK_BUTTON (25, 64, 10, FMDY, N_("&Background"), B_USER, NULL), #define OFFSET 0 #else #define OFFSET 1 #endif /* ENABLE_BACKGROUND */ /* 2 - OFFSET */ QUICK_BUTTON (14, FMDX, 10, FMDY, N_("&OK"), B_ENTER, NULL), /* 3 - OFFSET */ QUICK_CHECKBOX (42, FMDX, 8, FMDY, N_("&Stable Symlinks"), &ctx->stable_symlinks), /* 4 - OFFSET */ QUICK_CHECKBOX (31, FMDX, 7, FMDY, N_("Di&ve into subdir if exists"), &ctx->dive_into_subdirs), /* 5 - OFFSET */ QUICK_CHECKBOX (3, FMDX, 8, FMDY, N_("Preserve &attributes"), &ctx->op_preserve), /* 6 - OFFSET */ QUICK_CHECKBOX (3, FMDX, 7, FMDY, N_("Follow &links"), &ctx->follow_links), /* 7 - OFFSET */ QUICK_INPUT (3, FMDX, 6, FMDY, "", 58, 0, "input2", &dest_dir), /* 8 - OFFSET */ QUICK_LABEL (3, FMDX, 5, FMDY, N_("to:")), /* 9 - OFFSET */ QUICK_CHECKBOX (37, FMDX, 4, FMDY, N_("&Using shell patterns"), &source_easy_patterns), /* 10 - OFFSET */ QUICK_INPUT (3, FMDX, 3, FMDY, easy_patterns ? "*" : "^(.*)$", 58, 0, "input-def", &source_mask), /* 11 - OFFSET */ QUICK_LABEL (3, FMDX, 2, FMDY, fmd_buf), QUICK_END }; g_return_val_if_fail (ctx != NULL, NULL); #ifdef ENABLE_NLS /* buttons */ for (i = 0; i <= 2 - OFFSET; i++) fmd_widgets[i].u.button.text = _(fmd_widgets[i].u.button.text); /* checkboxes */ for (i = 3 - OFFSET; i <= 9 - OFFSET; i++) if (i != 7 - OFFSET) fmd_widgets[i].u.checkbox.text = _(fmd_widgets[i].u.checkbox.text); #endif /* !ENABLE_NLS */ fmd_xlen = max (FMDX, (size_t) COLS * 2 / 3); len = str_term_width1 (fmd_widgets[6 - OFFSET].u.checkbox.text) + str_term_width1 (fmd_widgets[4 - OFFSET].u.checkbox.text) + 15; fmd_xlen = max (fmd_xlen, len); len = str_term_width1 (fmd_widgets[5 - OFFSET].u.checkbox.text) + str_term_width1 (fmd_widgets[3 - OFFSET].u.checkbox.text) + 15; fmd_xlen = max (fmd_xlen, len); /* buttons */ b2_len = str_term_width1 (fmd_widgets[2 - OFFSET].u.button.text) + 6 + gap; /* OK */ #ifdef ENABLE_BACKGROUND b1_len = str_term_width1 (fmd_widgets[1].u.button.text) + 4 + gap; /* Background */ #endif b0_len = str_term_width1 (fmd_widgets[0].u.button.text) + 4; /* Cancel */ len = b0_len + b1_len + b2_len; fmd_xlen = min (max (fmd_xlen, len + 6), (size_t) COLS); if (only_one) { int flen; flen = str_term_width1 (format); i = fmd_xlen - flen - 4; /* FIXME */ g_snprintf (fmd_buf, sizeof (fmd_buf), format, str_trunc ((const char *) text, i)); } else { g_snprintf (fmd_buf, sizeof (fmd_buf), format, *(const int *) text); fmd_xlen = max (fmd_xlen, (size_t) str_term_width1 (fmd_buf) + 6); } for (i = sizeof (fmd_widgets) / sizeof (fmd_widgets[0]); i > 0;) fmd_widgets[--i].x_divisions = fmd_xlen; i = (fmd_xlen - len) / 2; /* OK button */ fmd_widgets[2 - OFFSET].relative_x = i; i += b2_len; #ifdef ENABLE_BACKGROUND /* Background button */ fmd_widgets[1].relative_x = i; i += b1_len; #endif /* Cancel button */ fmd_widgets[0].relative_x = i; #define chkbox_xpos(i) \ fmd_widgets [i].relative_x = fmd_xlen - str_term_width1 (fmd_widgets [i].u.checkbox.text) - 6 chkbox_xpos (3 - OFFSET); chkbox_xpos (4 - OFFSET); chkbox_xpos (9 - OFFSET); #undef chkbox_xpos /* inputs */ fmd_widgets[7 - OFFSET].u.input.len = fmd_widgets[10 - OFFSET].u.input.len = fmd_xlen - 6; /* unselect checkbox if target filesystem don't support attributes */ ctx->op_preserve = filegui__check_attrs_on_fs (def_text); /* filter out a possible password from def_text */ { vfs_path_t *vpath; vpath = vfs_path_from_str_flags (def_text, (only_one) ? VPF_NO_CANON : VPF_NONE); tmp = vfs_path_to_str_flags (vpath, 0, VPF_STRIP_PASSWORD); vfs_path_free (vpath); } if (source_easy_patterns) def_text_secure = strutils_glob_escape (tmp); else def_text_secure = strutils_regex_escape (tmp); g_free (tmp); /* destination */ fmd_widgets[7 - OFFSET].u.input.text = def_text_secure; ctx->stable_symlinks = FALSE; *do_bg = FALSE; { struct stat buf; vfs_path_t *vpath; QuickDialog Quick_input = { fmd_xlen, FMDY, -1, -1, op_names[operation], "[Mask Copy/Rename]", fmd_widgets, NULL, NULL, TRUE }; ask_file_mask: val = quick_dialog_skip (&Quick_input, 4); if (val == B_CANCEL) { g_free (def_text_secure); return NULL; } if (ctx->follow_links) ctx->stat_func = mc_stat; else ctx->stat_func = mc_lstat; if (ctx->op_preserve) { ctx->preserve = TRUE; ctx->umask_kill = 0777777; ctx->preserve_uidgid = (geteuid () == 0); } else { int i2; ctx->preserve = ctx->preserve_uidgid = FALSE; i2 = umask (0); umask (i2); ctx->umask_kill = i2 ^ 0777777; } if ((dest_dir == NULL) || (*dest_dir == '\0')) { g_free (def_text_secure); g_free (source_mask); return dest_dir; } ctx->search_handle = mc_search_new (source_mask, -1); if (ctx->search_handle == NULL) { message (D_ERROR, MSG_ERROR, _("Invalid source pattern `%s'"), source_mask); g_free (dest_dir); g_free (source_mask); goto ask_file_mask; } g_free (def_text_secure); g_free (source_mask); ctx->search_handle->is_case_sensitive = TRUE; if (source_easy_patterns) ctx->search_handle->search_type = MC_SEARCH_T_GLOB; else ctx->search_handle->search_type = MC_SEARCH_T_REGEX; tmp = dest_dir; dest_dir = tilde_expand (tmp); g_free (tmp); vpath = vfs_path_from_str (dest_dir); ctx->dest_mask = strrchr (dest_dir, PATH_SEP); if (ctx->dest_mask == NULL) ctx->dest_mask = dest_dir; else ctx->dest_mask++; orig_mask = ctx->dest_mask; if (*ctx->dest_mask == '\0' || (!ctx->dive_into_subdirs && !is_wildcarded (ctx->dest_mask) && (!only_one || (mc_stat (vpath, &buf) == 0 && S_ISDIR (buf.st_mode)))) || (ctx->dive_into_subdirs && ((!only_one && !is_wildcarded (ctx->dest_mask)) || (only_one && mc_stat (vpath, &buf) == 0 && S_ISDIR (buf.st_mode))))) ctx->dest_mask = g_strdup ("\\0"); else { ctx->dest_mask = g_strdup (ctx->dest_mask); *orig_mask = '\0'; } if (!*dest_dir) { g_free (dest_dir); dest_dir = g_strdup ("./"); } vfs_path_free (vpath); if (val == B_USER) *do_bg = TRUE; } return dest_dir; }