void compare_dirs_cmd (void) { int choice; enum CompareMode thorough_flag; choice = query_dialog (_("Compare directories"), _("Select compare method:"), D_NORMAL, 4, _("&Quick"), _("&Size only"), _("&Thorough"), _("&Cancel")); if (choice < 0 || choice > 2) return; thorough_flag = choice; if (get_current_type () == view_listing && get_other_type () == view_listing) { compare_dir (current_panel, other_panel, thorough_flag); compare_dir (other_panel, current_panel, thorough_flag); } else { message (D_ERROR, MSG_ERROR, _("Both panels should be in the listing mode\nto use this command")); } }
static void mcview_hook (void *v) { mcview_t *view = (mcview_t *) v; WPanel *panel; /* If the user is busy typing, wait until he finishes to update the screen */ if (!is_idle ()) { if (!hook_present (idle_hook, mcview_hook)) add_hook (&idle_hook, mcview_hook, v); return; } delete_hook (&idle_hook, mcview_hook); if (get_current_type () == view_listing) panel = current_panel; else if (get_other_type () == view_listing) panel = other_panel; else return; mcview_done (view); mcview_init (view); mcview_load (view, 0, panel->dir.list[panel->selected].fname, 0, 0, 0); mcview_display (view); }
void vfs_stamp_create (struct vfs_class *oldvfs, vfsid oldvfsid) { struct vfs_class *nvfs, *n2vfs, *n3vfs; vfsid nvfsid, n2vfsid, n3vfsid; /* There are three directories we have to take care of: current_dir, current_panel->cwd and other_panel->cwd. Athough most of the time either current_dir and current_panel->cwd or current_dir and other_panel->cwd are the same, it's possible that all three are different -- Norbert */ if (current_panel == NULL) return; nvfs = vfs_get_class (vfs_get_current_dir ()); nvfsid = vfs_getid (nvfs, vfs_get_current_dir ()); vfs_rmstamp (nvfs, nvfsid); if ((nvfs == oldvfs && nvfsid == oldvfsid) || oldvfsid == NULL) { return; } if (get_current_type () == view_listing) { n2vfs = vfs_get_class (current_panel->cwd); n2vfsid = vfs_getid (n2vfs, current_panel->cwd); if (n2vfs == oldvfs && n2vfsid == oldvfsid) return; } else { n2vfs = NULL; n2vfsid = NULL; } if (get_other_type () == view_listing) { n3vfs = vfs_get_class (other_panel->cwd); n3vfsid = vfs_getid (n3vfs, other_panel->cwd); if (n3vfs == oldvfs && n3vfsid == oldvfsid) return; } else { n3vfs = NULL; n3vfsid = NULL; } if (!oldvfs || !oldvfs->nothingisopen || !(*oldvfs->nothingisopen) (oldvfsid)) return; vfs_addstamp (oldvfs, oldvfsid); }
void reread_cmd (void) { panel_update_flags_t flag = UP_ONLY_CURRENT; if (get_current_type () == view_listing && get_other_type () == view_listing && vfs_path_equal (current_panel->cwd_vpath, other_panel->cwd_vpath)) flag = UP_OPTIMIZE; update_panels (UP_RELOAD | flag, UP_KEEPSEL); repaint_screen (); }
void reread_cmd (void) { int flag; if (get_current_type () == view_listing && get_other_type () == view_listing) flag = strcmp (current_panel->cwd, other_panel->cwd) ? UP_ONLY_CURRENT : 0; else flag = UP_ONLY_CURRENT; update_panels (UP_RELOAD|flag, UP_KEEPSEL); repaint_screen (); }
static void do_link (link_type_t link_type, const char *fname) { char *dest = NULL, *src = NULL; if (link_type == LINK_HARDLINK) { src = g_strdup_printf (_("Link %s to:"), str_trunc (fname, 46)); dest = input_expand_dialog (_("Link"), src, MC_HISTORY_FM_LINK, ""); if (!dest || !*dest) goto cleanup; save_cwds_stat (); if (-1 == mc_link (fname, dest)) message (D_ERROR, MSG_ERROR, _("link: %s"), unix_error_string (errno)); } else { char *s; char *d; /* suggest the full path for symlink, and either the full or relative path to the file it points to */ s = concat_dir_and_file (current_panel->cwd, fname); if (get_other_type () == view_listing) d = concat_dir_and_file (other_panel->cwd, fname); else d = g_strdup (fname); if (link_type == LINK_SYMLINK_RELATIVE) s = diff_two_paths (other_panel->cwd, s); symlink_dialog (s, d, &dest, &src); g_free (d); g_free (s); if (!dest || !*dest || !src || !*src) goto cleanup; save_cwds_stat (); if (-1 == mc_symlink (dest, src)) message (D_ERROR, MSG_ERROR, _("symlink: %s"), unix_error_string (errno)); } update_panels (UP_OPTIMIZE, UP_KEEPSEL); repaint_screen (); cleanup: g_free (src); g_free (dest); }
void diff_view_cmd (void) { /* both panels must be in the list mode */ if (get_current_type () != view_listing || get_other_type () != view_listing) return; if (get_current_index () == 0) dview_diff_cmd (current_panel, other_panel); else dview_diff_cmd (other_panel, current_panel); if (mc_global.mc_run_mode == MC_RUN_FULL) update_panels (UP_OPTIMIZE, UP_KEEPSEL); dialog_switch_process_pending (); }
/* Calculates the truth value of the next condition starting from p. Returns the point after condition. */ static char *test_condition (char *p, int *condition) { WPanel *panel; char arg [256]; /* Handle one condition */ for (;*p != '\n' && *p != '&' && *p != '|'; p++){ if (*p == ' ' || *p == '\t') continue; if (*p >= 'a') panel = cpanel; else { if (get_other_type () == view_listing) panel = other_panel; else panel = NULL; } *p |= 0x20; switch (*p++){ case '!': p = test_condition (p, condition); *condition = ! *condition; p--; break; case 'f': p = extract_arg (p, arg); *condition = panel && regexp_match (arg, panel->dir.list [panel->selected].fname, match_file); break; case 'd': p = extract_arg (p, arg); *condition = panel && regexp_match (arg, panel->cwd, match_file); break; case 't': p = extract_arg (p, arg); *condition = panel && test_type (panel, arg); break; default: debug_error = 1; break; } /* switch */ } /* while */ return p; }
static void do_link (int symbolic_link, const char *fname) { char *dest = NULL, *src = NULL; if (!symbolic_link) { src = g_strdup_printf (_("Link %s to:"), name_trunc (fname, 46)); dest = input_expand_dialog (_(" Link "), src, ""); if (!dest || !*dest) goto cleanup; save_cwds_stat (); if (-1 == mc_link (fname, dest)) message (1, MSG_ERROR, _(" link: %s "), unix_error_string (errno)); } else { char *s; char *d; /* suggest the full path for symlink */ s = concat_dir_and_file (current_panel->cwd, fname); if (get_other_type () == view_listing) { d = concat_dir_and_file (other_panel->cwd, fname); } else { d = g_strdup (fname); } symlink_dialog (s, d, &dest, &src); g_free (d); g_free (s); if (!dest || !*dest || !src || !*src) goto cleanup; save_cwds_stat (); if (-1 == mc_symlink (dest, src)) message (1, MSG_ERROR, _(" symlink: %s "), unix_error_string (errno)); } update_panels (UP_OPTIMIZE, UP_KEEPSEL); repaint_screen (); cleanup: g_free (src); g_free (dest); }
void save_setup (void) { char *profile; #ifdef USE_VFS #ifdef USE_NETCODE extern char *ftpfs_anonymous_passwd; extern char *ftpfs_proxy_host; #endif #endif saving_setup = 1; profile = concat_dir_and_file (home_dir, PROFILE_NAME); save_layout (); save_configure (); save_string ("Dirs", "other_dir", get_other_type () == view_listing ? opanel->cwd : ".", profile); WritePrivateProfileString ("Dirs", "current_is_left", get_current_index () == 0 ? "1" : "0", profile); save_hotlist (); save_panelize (); save_panel_types (); /* directory_history_save (); */ #ifdef USE_VFS #ifdef USE_NETCODE WritePrivateProfileString ("Misc", "ftpfs_password", ftpfs_anonymous_passwd, profile); if (ftpfs_proxy_host) WritePrivateProfileString ("Misc", "ftp_proxy_host", ftpfs_proxy_host, profile); #endif #endif free (profile); saving_setup = 0; }
char * expand_format (struct WEdit *edit_widget, char c, gboolean do_quote) { WPanel *panel = NULL; char *(*quote_func) (const char *, int); char *fname = NULL; char *result; char c_lc; #ifndef USE_INTERNAL_EDIT (void) edit_widget; #endif if (c == '%') return g_strdup ("%"); switch (mc_global.mc_run_mode) { case MC_RUN_FULL: if (g_ascii_islower ((gchar) c)) panel = current_panel; else { if (get_other_type () != view_listing) return g_strdup (""); panel = other_panel; } fname = g_strdup (panel->dir.list[panel->selected].fname); break; #ifdef USE_INTERNAL_EDIT case MC_RUN_EDITOR: fname = edit_get_file_name (edit_widget); break; #endif default: /* other modes don't use formats */ return g_strdup (""); } if (do_quote) quote_func = name_quote; else quote_func = fake_name_quote; c_lc = g_ascii_tolower ((gchar) c); switch (c_lc) { case 'f': case 'p': result = (*quote_func) (fname, 0); goto ret; case 'x': result = (*quote_func) (extension (fname), 0); goto ret; case 'd': { char *cwd; char *qstr; if (panel) cwd = g_strdup (vfs_path_as_str (panel->cwd_vpath)); else cwd = vfs_get_current_dir (); qstr = (*quote_func) (cwd, 0); g_free (cwd); result = qstr; goto ret; } case 'i': /* indent equal number cursor position in line */ #ifdef USE_INTERNAL_EDIT if (edit_widget) { result = g_strnfill (edit_get_curs_col (edit_widget), ' '); goto ret; } #endif break; case 'y': /* syntax type */ #ifdef USE_INTERNAL_EDIT if (edit_widget) { const char *syntax_type = edit_get_syntax_type (edit_widget); if (syntax_type != NULL) { result = g_strdup (syntax_type); goto ret; } } #endif break; case 'k': /* block file name */ case 'b': /* block file name / strip extension */ { #ifdef USE_INTERNAL_EDIT if (edit_widget) { char *file; file = mc_config_get_full_path (EDIT_BLOCK_FILE); result = (*quote_func) (file, 0); g_free (file); goto ret; } #endif if (c_lc == 'b') { result = strip_ext ((*quote_func) (fname, 0)); goto ret; } break; } case 'n': /* strip extension in editor */ #ifdef USE_INTERNAL_EDIT if (edit_widget) { result = strip_ext ((*quote_func) (fname, 0)); goto ret; } #endif break; case 'm': /* menu file name */ if (menu) { result = (*quote_func) (menu, 0); goto ret; } break; case 's': if (!panel || !panel->marked) { result = (*quote_func) (fname, 0); goto ret; } /* Fall through */ case 't': case 'u': { GString *block; int i; if (panel == NULL) { result = g_strdup (""); goto ret; } block = g_string_sized_new (16); for (i = 0; i < panel->dir.len; i++) if (panel->dir.list[i].f.marked) { char *tmp; tmp = (*quote_func) (panel->dir.list[i].fname, 0); g_string_append (block, tmp); g_string_append_c (block, ' '); g_free (tmp); if (c_lc == 'u') do_file_mark (panel, i, 0); } result = g_string_free (block, FALSE); goto ret; } /* sub case block */ } /* switch */ result = g_strdup ("% "); result[1] = c; ret: g_free (fname); return result; }
char *expand_format (char c, int quote) { WPanel *panel; char *(*quote_func)(const char *, int); if (quote) quote_func = name_quote; else quote_func = fake_name_quote; if (c == '%') return strdup ("%"); if (islower (c)) panel = cpanel; else { if (get_other_type () == view_listing){ panel = other_panel; } else return strdup (""); } if (!panel) panel = cpanel; c = tolower (c); switch (c){ case 'f': case 'p': return (*quote_func) (panel->dir.list [panel->selected].fname, 0); case 'b': return strip_ext((*quote_func) (panel->dir.list [panel->selected].fname, 0)); case 'd': return (*quote_func) (panel->cwd, 0); case 's': if (!panel->marked) return (*quote_func) (panel->dir.list [panel->selected].fname, 0); /* Fall through */ case 't': case 'u': { int length = 2, i; char *block, *tmp; for (i = 0; i < panel->count; i++) if (panel->dir.list [i].f.marked) length += strlen (panel->dir.list [i].fname) + 1; block = xmalloc (length*2+1, "expand_format"); *block = 0; for (i = 0; i < panel->count; i++) if (panel->dir.list [i].f.marked){ strcat (block, tmp = (*quote_func) (panel->dir.list [i].fname, 0)); free (tmp); strcat (block, " "); if (c == 'u') do_file_mark (panel, i, 0); } return block; } /* sub case block */ } /* switch */ return strdup (""); }
static void do_link (link_type_t link_type, const char *fname) { char *dest = NULL, *src = NULL; vfs_path_t *fname_vpath, *dest_vpath = NULL; fname_vpath = vfs_path_from_str (fname); if (link_type == LINK_HARDLINK) { src = g_strdup_printf (_("Link %s to:"), str_trunc (fname, 46)); dest = input_expand_dialog (_("Link"), src, MC_HISTORY_FM_LINK, "", INPUT_COMPLETE_FILENAMES); if (!dest || !*dest) goto cleanup; save_cwds_stat (); dest_vpath = vfs_path_from_str (dest); if (-1 == mc_link (fname_vpath, dest_vpath)) message (D_ERROR, MSG_ERROR, _("link: %s"), unix_error_string (errno)); } else { vfs_path_t *s, *d; /* suggest the full path for symlink, and either the full or relative path to the file it points to */ s = vfs_path_append_new (current_panel->cwd_vpath, fname, NULL); if (get_other_type () == view_listing) d = vfs_path_append_new (other_panel->cwd_vpath, fname, NULL); else d = vfs_path_from_str (fname); if (link_type == LINK_SYMLINK_RELATIVE) { char *s_str; s_str = diff_two_paths (other_panel->cwd_vpath, s); vfs_path_free (s); s = vfs_path_from_str_flags (s_str, VPF_NO_CANON); g_free (s_str); } symlink_dialog (s, d, &dest, &src); vfs_path_free (d); vfs_path_free (s); if (!dest || !*dest || !src || !*src) goto cleanup; save_cwds_stat (); dest_vpath = vfs_path_from_str_flags (dest, VPF_NO_CANON); s = vfs_path_from_str (src); if (mc_symlink (dest_vpath, s) == -1) message (D_ERROR, MSG_ERROR, _("symlink: %s"), unix_error_string (errno)); vfs_path_free (s); } update_panels (UP_OPTIMIZE, UP_KEEPSEL); repaint_screen (); cleanup: vfs_path_free (fname_vpath); vfs_path_free (dest_vpath); g_free (src); g_free (dest); }
/* Calculates the truth value of the next condition starting from p. Returns the point after condition. */ static char *test_condition (WEdit *edit_widget, char *p, int *condition) { WPanel *panel; char arg [256]; /* Handle one condition */ for (;*p != '\n' && *p != '&' && *p != '|'; p++){ /* support quote space .mnu */ if ((*p == ' ' && *(p-1) != '\\') || *p == '\t') continue; if (*p >= 'a') panel = current_panel; else { if (get_other_type () == view_listing) panel = other_panel; else panel = NULL; } *p |= 0x20; switch (*p++){ case '!': p = test_condition (edit_widget, p, condition); *condition = ! *condition; p--; break; case 'f': /* file name pattern */ p = extract_arg (p, arg, sizeof (arg)); *condition = panel && regexp_match (arg, panel->dir.list [panel->selected].fname, match_file, 0); break; case 'y': /* syntax pattern */ if (edit_widget && edit_widget->syntax_type) { p = extract_arg (p, arg, sizeof (arg)); *condition = panel && regexp_match (arg, edit_widget->syntax_type, match_normal, 0); } break; case 'd': p = extract_arg (p, arg, sizeof (arg)); *condition = panel && regexp_match (arg, panel->cwd, match_file, 0); break; case 't': p = extract_arg (p, arg, sizeof (arg)); *condition = panel && test_type (panel, arg); break; case 'x': /* executable */ { struct stat status; p = extract_arg (p, arg, sizeof (arg)); if (stat (arg, &status) == 0) *condition = is_exe (status.st_mode); else *condition = 0; break; } default: debug_error = 1; break; } /* switch */ } /* while */ return p; }
char * expand_format (struct WEdit *edit_widget, char c, int quote) { WPanel *panel = NULL; char *(*quote_func) (const char *, int); char *fname; char *result; char c_lc; if (c == '%') return g_strdup ("%"); if (edit_one_file != NULL) fname = edit_widget->filename; else { if (islower ((unsigned char) c)) panel = current_panel; else { if (get_other_type () != view_listing) return g_strdup (""); panel = other_panel; } fname = panel->dir.list[panel->selected].fname; } if (quote) quote_func = name_quote; else quote_func = fake_name_quote; c_lc = tolower ((unsigned char) c); switch (c_lc) { case 'f': case 'p': return (*quote_func) (fname, 0); case 'x': return (*quote_func) (extension (fname), 0); case 'd': { char *cwd; char *qstr; cwd = g_malloc(MC_MAXPATHLEN + 1); if (panel) g_strlcpy(cwd, panel->cwd, MC_MAXPATHLEN + 1); else mc_get_current_wd(cwd, MC_MAXPATHLEN + 1); qstr = (*quote_func) (cwd, 0); g_free (cwd); return qstr; } case 'i': /* indent equal number cursor position in line */ if (edit_widget) return g_strnfill (edit_widget->curs_col, ' '); break; case 'y': /* syntax type */ if (edit_widget && edit_widget->syntax_type) return g_strdup (edit_widget->syntax_type); break; case 'k': /* block file name */ case 'b': /* block file name / strip extension */ { if (edit_widget) { char *file = g_strconcat (home_dir, PATH_SEP_STR BLOCK_FILE, (char *) NULL); fname = (*quote_func) (file, 0); g_free (file); return fname; } else if (c_lc == 'b') { return strip_ext ((*quote_func) (fname, 0)); } break; } case 'e': /* was "cooledit.error" */ return g_strdup("/dev/null"); case 'n': /* strip extension in editor */ if (edit_widget) return strip_ext ((*quote_func) (fname, 0)); break; case 'm': /* menu file name */ if (menu) return (*quote_func) (menu, 0); break; case 's': if (!panel || !panel->marked) return (*quote_func) (fname, 0); /* Fall through */ case 't': case 'u': { int length = 2, i; char *block, *tmp; if (!panel) return g_strdup (""); for (i = 0; i < panel->count; i++) if (panel->dir.list[i].f.marked) length += strlen (panel->dir.list[i].fname) + 1; /* for space */ block = g_malloc (length * 2 + 1); *block = 0; for (i = 0; i < panel->count; i++) if (panel->dir.list[i].f.marked) { strcat (block, tmp = (*quote_func) (panel->dir.list[i].fname, 0)); g_free (tmp); strcat (block, " "); if (c_lc == 'u') do_file_mark (panel, i, 0); } return block; } /* sub case block */ } /* switch */ result = g_strdup ("% "); result[1] = c; return result; }
static char * test_condition (WEdit * edit_widget, char *p, int *condition) { char arg[256]; const mc_search_type_t search_type = easy_patterns ? MC_SEARCH_T_GLOB : MC_SEARCH_T_REGEX; /* Handle one condition */ for (; *p != '\n' && *p != '&' && *p != '|'; p++) { WPanel *panel = NULL; /* support quote space .mnu */ if ((*p == ' ' && *(p - 1) != '\\') || *p == '\t') continue; if (*p >= 'a') panel = current_panel; else if (get_other_type () == view_listing) panel = other_panel; *p |= 0x20; switch (*p++) { case '!': p = test_condition (edit_widget, p, condition); *condition = !*condition; str_prev_char (&p); break; case 'f': /* file name pattern */ p = extract_arg (p, arg, sizeof (arg)); #ifdef USE_INTERNAL_EDIT if (edit_widget != NULL) { char *edit_filename; edit_filename = edit_get_file_name (edit_widget); *condition = mc_search (arg, DEFAULT_CHARSET, edit_filename, search_type) ? 1 : 0; g_free (edit_filename); } else #endif *condition = panel != NULL && mc_search (arg, DEFAULT_CHARSET, panel->dir.list[panel->selected].fname, search_type) ? 1 : 0; break; case 'y': /* syntax pattern */ #ifdef USE_INTERNAL_EDIT if (edit_widget != NULL) { const char *syntax_type = edit_get_syntax_type (edit_widget); if (syntax_type != NULL) { p = extract_arg (p, arg, sizeof (arg)); *condition = mc_search (arg, DEFAULT_CHARSET, syntax_type, MC_SEARCH_T_NORMAL) ? 1 : 0; } } #endif break; case 'd': p = extract_arg (p, arg, sizeof (arg)); *condition = panel != NULL && mc_search (arg, DEFAULT_CHARSET, vfs_path_as_str (panel->cwd_vpath), search_type) ? 1 : 0; break; case 't': p = extract_arg (p, arg, sizeof (arg)); *condition = panel != NULL && test_type (panel, arg) ? 1 : 0; break; case 'x': /* executable */ { struct stat status; p = extract_arg (p, arg, sizeof (arg)); if (stat (arg, &status) == 0) *condition = is_exe (status.st_mode) ? 1 : 0; else *condition = 0; break; } default: debug_error = 1; break; } /* switch */ } /* while */ return p; }
char * expand_format (struct WEdit *edit_widget, char c, gboolean do_quote) { WPanel *panel = NULL; char *(*quote_func) (const char *, int); char *fname = NULL; char *result; char c_lc; #ifndef USE_INTERNAL_EDIT (void) edit_widget; #endif if (c == '%') return g_strdup ("%"); if (mc_run_mode == MC_RUN_FULL) { if (g_ascii_islower ((gchar) c)) panel = current_panel; else { if (get_other_type () != view_listing) return g_strdup (""); panel = other_panel; } fname = panel->dir.list[panel->selected].fname; } #ifdef USE_INTERNAL_EDIT else if (mc_run_mode == MC_RUN_EDITOR) fname = (char *) edit_get_file_name (edit_widget); #endif if (do_quote) quote_func = name_quote; else quote_func = fake_name_quote; c_lc = g_ascii_tolower ((gchar) c); switch (c_lc) { case 'f': case 'p': return (*quote_func) (fname, 0); case 'x': return (*quote_func) (extension (fname), 0); case 'd': { char *cwd; char *qstr; cwd = g_malloc (MC_MAXPATHLEN + 1); if (panel) g_strlcpy (cwd, panel->cwd, MC_MAXPATHLEN + 1); else mc_get_current_wd (cwd, MC_MAXPATHLEN + 1); qstr = (*quote_func) (cwd, 0); g_free (cwd); return qstr; } case 'i': /* indent equal number cursor position in line */ #ifdef USE_INTERNAL_EDIT if (edit_widget) return g_strnfill (edit_get_curs_col (edit_widget), ' '); #endif break; case 'y': /* syntax type */ #ifdef USE_INTERNAL_EDIT if (edit_widget) { const char *syntax_type = edit_get_syntax_type (edit_widget); if (syntax_type != NULL) return g_strdup (syntax_type); } #endif break; case 'k': /* block file name */ case 'b': /* block file name / strip extension */ { #ifdef USE_INTERNAL_EDIT if (edit_widget) { char *file = concat_dir_and_file (mc_config_get_cache_path (), EDIT_BLOCK_FILE); fname = (*quote_func) (file, 0); g_free (file); return fname; } #endif if (c_lc == 'b') return strip_ext ((*quote_func) (fname, 0)); break; } case 'n': /* strip extension in editor */ #ifdef USE_INTERNAL_EDIT if (edit_widget) return strip_ext ((*quote_func) (fname, 0)); #endif break; case 'm': /* menu file name */ if (menu) return (*quote_func) (menu, 0); break; case 's': if (!panel || !panel->marked) return (*quote_func) (fname, 0); /* Fall through */ case 't': case 'u': { int length = 2, i; char *block, *tmp; if (!panel) return g_strdup (""); for (i = 0; i < panel->count; i++) if (panel->dir.list[i].f.marked) length += strlen (panel->dir.list[i].fname) + 1; /* for space */ block = g_malloc (length * 2 + 1); *block = 0; for (i = 0; i < panel->count; i++) if (panel->dir.list[i].f.marked) { tmp = (*quote_func) (panel->dir.list[i].fname, 0); strcat (block, tmp); g_free (tmp); strcat (block, " "); if (c_lc == 'u') do_file_mark (panel, i, 0); } return block; } /* sub case block */ } /* switch */ result = g_strdup ("% "); result[1] = c; return result; }