/* vifm * Copyright (C) 2001 Ken Steen. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #include<curses.h> //#include<unistd.h> /* for chdir */ #include<string.h> /* strncpy */ #include<sys/time.h> /* select() */ #include<sys/types.h> /* select() */ #include<unistd.h> /* select() */ #include<windows.h> #include "background.h" #include "bookmarks.h" #include "color_scheme.h" #include "commands.h" #include "config.h" #include "file_info.h" #include "filelist.h" #include "fileops.h" #include "keys.h" #include "menus.h" #include "registers.h" #include "search.h" #include "signals.h" #include "sort.h" #include "status.h" #include "ui.h" #include "utils.h" #include "visual.h" void switch_views(void) { FileView *tmp = curr_view; curr_view = other_view; other_view = tmp; } void clean_status_bar(FileView *view) { werase(status_bar); wnoutrefresh(status_bar); } static void update_num_window(char *text) { werase(num_win); mvwaddstr(num_win, 0, 0, text); wrefresh(num_win); } static void clear_num_window(void) { werase(num_win); wrefresh(num_win); } static void reload_window(FileView *view) { struct stat s; stat(view->curr_dir, &s); if(view != curr_view) change_directory(view, view->curr_dir); load_dir_list(view, 1); view->dir_mtime = s.st_mtime; if(view != curr_view) { change_directory(curr_view, curr_view->curr_dir); mvwaddstr(view->win, view->curr_line, 0, "*"); wrefresh(view->win); } else moveto_list_pos(view, view->list_pos); } /* * This checks the modified times of the directories. */ static void check_if_filelists_have_changed(FileView *view) { struct stat s; stat(view->curr_dir, &s); if(s.st_mtime != view->dir_mtime) reload_window(view); if (curr_stats.number_of_windows != 1 && curr_stats.view != 1) { stat(other_view->curr_dir, &s); if(s.st_mtime != other_view->dir_mtime) reload_window(other_view); } } static void repeat_last_command(FileView *view) { if (0 > cfg.cmd_history_num) show_error_msg(" Command Error ", "Command history list is empty. "); else execute_command(view, cfg.cmd_history[0]); } void rename_file(FileView *view) { char * filename = get_current_file_name(view); char command[1024]; int key; int pos = strlen(filename) + 1; int index = pos - 1; int done = 0; int abort = 0; int len = pos; int found = -1; char buf[view->window_width -2]; wattroff(view->win, COLOR_PAIR(CURR_LINE_COLOR)); wmove(view->win, view->curr_line, 0); wclrtoeol(view->win); wmove(view->win, view->curr_line, 1); waddstr(view->win, filename); memset(buf, '\0', view->window_width -2); strncpy(buf, filename, sizeof(buf)); len = strlen(filename); wmove(view->win, view->curr_line, strlen(filename) + 1); curs_set(1); while(!done) { if(curr_stats.freeze) continue; curs_set(1); flushinp(); curr_stats.getting_input = 1; key = wgetch(view->win); switch(key) { case 27: /* ascii Escape */ case 3: /* ascii Ctrl C */ done = 1; abort = 1; break; case 13: /* ascii Return */ done = 1; break; /* This needs to be changed to a value that is read from * the termcap file. */ case 0x7f: /* This is the one that works on my machine */ case 8: /* ascii Backspace ascii Ctrl H */ case KEY_BACKSPACE: /* ncurses BACKSPACE KEY */ { /* if(index == len) { */ pos--; index--; len--; if(pos < 1) pos = 1; if(index < 0) index = 0; mvwdelch(view->win, view->curr_line, pos); buf[index] = '\0'; buf[len] = '\0'; // } } break; case KEY_LEFT: { index--; pos--; if(index < 0) index = 0; if(pos < 1) pos = 1; wmove(view->win, view->curr_line, pos); } break; case KEY_RIGHT: { index++; pos++; if(index > len) index = len; if(pos > len + 1) pos = len + 1; wmove(view->win, view->curr_line, pos); } break; default: if(key > 31 && key < 127) { mvwaddch(view->win, view->curr_line, pos, key); buf[index] = key; index++; buf[index] = '\0'; if(len < index) { len++; buf[index] = '\0'; } if(index > 62) { abort = 1; done = 1; } pos++; len++; } break; } curr_stats.getting_input = 0; } curs_set(0); if(abort) { load_dir_list(view, 1); moveto_list_pos(view, view->list_pos); return; } if (access(buf, F_OK) == 0 && strncmp(filename, buf, len) != 0) { show_error_msg("File exists", "That file already exists. Will not overwrite."); load_dir_list(view, 1); moveto_list_pos(view, view->list_pos); return; } snprintf(command, sizeof(command), "mv -f \'%s\' \'%s\'", filename, buf); my_system(command); load_dir_list(view, 0); found = find_file_pos_in_list(view, buf); if(found >= 0) moveto_list_pos(view, found); else moveto_list_pos(view, view->list_pos); } void remove_filename_filter(FileView *view) { int found; char file[PATH_MAX]; snprintf(file, sizeof(file), "%s", view->dir_entry[view->list_pos].name); view->prev_filter = (char *)realloc(view->prev_filter, strlen(view->filename_filter) +1); snprintf(view->prev_filter, sizeof(view->prev_filter), view->filename_filter); view->filename_filter = (char *)realloc(view->filename_filter, strlen("*") +1); snprintf(view->filename_filter, sizeof(view->filename_filter), "*"); view->prev_invert = view->invert; view->invert = 0; load_dir_list(view, 0); found = find_file_pos_in_list(view, file); if(found >= 0) moveto_list_pos(view, found); else moveto_list_pos(view, view->list_pos); } static void restore_filename_filter(FileView *view) { int found; char file[PATH_MAX]; snprintf(file, sizeof(file), "%s", view->dir_entry[view->list_pos].name); view->filename_filter = (char *)realloc(view->filename_filter, strlen(view->prev_filter) +1); snprintf(view->filename_filter, sizeof(view->filename_filter), "%s", view->prev_filter); view->invert = view->prev_invert; load_dir_list(view, 0); found = find_file_pos_in_list(view, file); if(found >= 0) moveto_list_pos(view, found); else moveto_list_pos(view, view->list_pos); } static void yank_files(FileView *view, int count, char *count_buf) { int x; char buf[32]; if(count) { int y = view->list_pos; for(x = 0; x < view->list_rows; x++) view->dir_entry[x].selected = 0; for(x = 0; x < atoi(count_buf); x++) { view->dir_entry[y].selected = 1; y++; if (y >= view->list_rows) break; } view->selected_files = y - view->list_pos; } else if(!view->selected_files) { view->dir_entry[view->list_pos].selected = 1; view->selected_files = 1; } get_all_selected_files(view); yank_selected_files(view); free_selected_file_array(view); count = view->selected_files; for(x = 0; x < view->list_rows; x++) view->dir_entry[x].selected = 0; view->selected_files = 0; draw_dir_list(view, view->top_line, view->list_pos); moveto_list_pos(view, view->list_pos); snprintf(buf, sizeof(buf), " %d %s yanked.", count, count == 1 ? "file" : "files"); status_bar_message(buf); } static void tag_file(FileView *view) { if(view->dir_entry[view->list_pos].selected == 0) { /* The ../ dir cannot be selected */ if (!strcmp(view->dir_entry[view->list_pos].name, "../")) return; view->dir_entry[view->list_pos].selected = 1; view->selected_files++; } else { view->dir_entry[view->list_pos].selected = 0; view->selected_files--; } draw_dir_list(view, view->top_line, view->list_pos); wattron(view->win, COLOR_PAIR(CURR_LINE_COLOR) | A_BOLD); mvwaddstr(view->win, view->curr_line, 0, " "); wattroff(view->win, COLOR_PAIR(CURR_LINE_COLOR)); wmove(view->win, view->curr_line, 0); } int put_files_from_register(FileView *view) { int x; int i = -1; int y = 0; char buf[PATH_MAX + 4]; for (x = 0; x < NUM_REGISTERS; x++) { if (reg[x].name == curr_stats.curr_register) { i = x; break; } } if ((i < 0) || (reg[i].num_files < 1)) { status_bar_message("Register is empty"); wrefresh(status_bar); return 1; } for (x = 0; x < reg[i].num_files; x++) { snprintf(buf, sizeof(buf), "%s/%s", cfg.trash_dir, reg[i].files[x]); if (!access(buf, F_OK)) { snprintf(buf, sizeof(buf), "mv \"%s/%s\" %s", cfg.trash_dir, reg[i].files[x], view->curr_dir); if ( background_and_wait_for_errors(buf)) y++; } } clear_register(curr_stats.curr_register); curr_stats.use_register = 0; curr_stats.register_saved = 0; if (y) { snprintf(buf, sizeof(buf), " %d %s inserted", y, y==1 ? "file" : "files"); load_dir_list(view, 0); moveto_list_pos(view, view->curr_line); status_bar_message(buf); return 1; } return 0; } int put_files(FileView *view) { int x; char buf[PATH_MAX]; char newbuf[PATH_MAX]; int y = 0; int retval = 1; int answer = 0; if (curr_stats.use_register && curr_stats.register_saved) return put_files_from_register(view); if (!curr_stats.num_yanked_files) return 0; for(x = 0; x < curr_stats.num_yanked_files; x++) { if(!strcmp("../", curr_stats.yanked_files[x])) { show_error_msg(" Background Process Error ", "You cannot move the ../ directory "); continue; } snprintf(buf, sizeof(buf), "%s\\%s", curr_stats.yanked_files_dir, curr_stats.yanked_files[x]); snprintf(newbuf, sizeof(newbuf), "%s\\%s", view->curr_dir, curr_stats.yanked_files[x]); retval = CopyFile(buf, newbuf, TRUE); y++; if(!retval) { DWORD dw = GetLastError(); if((int)dw == 80) { if (answer != 1) answer = show_overwrite_file_menu(curr_stats.yanked_files[x]); if (answer != 2) retval = CopyFile(buf, newbuf, FALSE); } else { snprintf(newbuf, sizeof(newbuf), "-%d- is error code ", (int)dw); show_error_msg(" Error in copyinging file ", newbuf); show_error_msg(" Old buf is ", buf); } } } if (y) { snprintf(buf, sizeof(buf), " %d %s inserted", y, y==1 ? "file" : "files"); load_dir_list(view, 0); moveto_list_pos(view, view->curr_line); status_bar_message(buf); return 1; } return 0; } void show_dot_files(FileView *view) { int found; char file[256]; snprintf(file, sizeof(file), "%s", view->dir_entry[view->list_pos].name); view->hide_dot = 0; load_dir_list(view, 1); found = find_file_pos_in_list(view, file); if(found >= 0) moveto_list_pos(view, found); else moveto_list_pos(view, view->list_pos); } static void hide_dot_files(FileView *view) { int found; char file[PATH_MAX]; snprintf(file, sizeof(file), "%s", view->dir_entry[view->list_pos].name); view->hide_dot = 1; load_dir_list(view, 1); found = find_file_pos_in_list(view, file); if(found >= 0) moveto_list_pos(view, found); else moveto_list_pos(view, view->list_pos); } static void toggle_dot_files(FileView *view) { int found; char file[PATH_MAX]; snprintf(file, sizeof(file), "%s", view->dir_entry[view->list_pos].name); if(view->hide_dot) view->hide_dot = 0; else view->hide_dot = 1; load_dir_list(view, 1); found = find_file_pos_in_list(view, file); if(found >= 0) moveto_list_pos(view, found); else moveto_list_pos(view, view->list_pos); } void change_window(FileView **view) { switch_views(); *view = curr_view; if (curr_stats.number_of_windows != 1) { wattroff(other_view->title, A_BOLD); wattroff(other_view->win, COLOR_PAIR(CURR_LINE_COLOR) | A_BOLD); mvwaddstr(other_view->win, other_view->curr_line, 0, "*"); erase_current_line_bar(other_view); werase(other_view->title); wprintw(other_view->title, "%s", other_view->curr_dir); wnoutrefresh(other_view->title); } if (curr_stats.view) { wbkgdset(curr_view->title, COLOR_PAIR(BORDER_COLOR + curr_view->color_scheme)); wbkgdset(curr_view->win, COLOR_PAIR(WIN_COLOR + curr_view->color_scheme)); change_directory(other_view, other_view->curr_dir); load_dir_list(other_view, 0); change_directory(curr_view, curr_view->curr_dir); load_dir_list(curr_view, 0); } change_directory(curr_view, curr_view->curr_dir); wattron(curr_view->title, A_BOLD); werase(curr_view->title); wprintw(curr_view->title, "%s", curr_view->curr_dir); wattroff(curr_view->title, A_BOLD); wnoutrefresh(curr_view->title); wnoutrefresh(other_view->win); wnoutrefresh(curr_view->win); if (curr_stats.number_of_windows == 1) load_dir_list(curr_view, 1); moveto_list_pos(curr_view, curr_view->list_pos); werase(status_bar); wnoutrefresh(status_bar); if (curr_stats.number_of_windows == 1) update_all_windows(); refresh(); } static void filter_selected_files(FileView *view) { size_t buf_size = 0; int x; if(!view->selected_files) view->dir_entry[view->list_pos].selected = 1; for(x = 0; x < view->list_rows; x++) { if(view->dir_entry[x].selected) { if(view->filtered) { char *buf = NULL; buf_size = strlen(view->dir_entry[x].name) +7; buf = (char *)realloc(buf, strlen(view->dir_entry[x].name) +7); snprintf(buf, buf_size, "|\\<%s\\>$", view->dir_entry[x].name); view->filename_filter = (char *) realloc(view->filename_filter, strlen(view->filename_filter) + strlen(buf) +1); strcat(view->filename_filter, buf); view->filtered++; my_free(buf); } else { buf_size = strlen(view->dir_entry[x].name) +6; view->filename_filter = (char *) realloc(view->filename_filter, strlen(view->dir_entry[x].name) +6); snprintf(view->filename_filter, buf_size, "\\<%s\\>$", view->dir_entry[x].name); view->filtered = 1; } } } view->invert = 1; clean_status_bar(view); load_dir_list(view, 1); moveto_list_pos(view, 0); } void update_all_windows(void) { /* In One window view */ if (curr_stats.number_of_windows == 1) { if (curr_view == &lwin) { touchwin(lwin.title); touchwin(lwin.win); touchwin(lborder); touchwin(stat_win); touchwin(status_bar); touchwin(pos_win); touchwin(num_win); touchwin(rborder); /* * redrawwin() shouldn't be needed. But without it there is a * lot of flickering when redrawing the windows? */ redrawwin(lborder); redrawwin(stat_win); redrawwin(status_bar); redrawwin(pos_win); redrawwin(lwin.title); redrawwin(lwin.win); redrawwin(num_win); redrawwin(rborder); wnoutrefresh(lwin.title); wnoutrefresh(lwin.win); } else { touchwin(rwin.title); touchwin(rwin.win); touchwin(lborder); touchwin(stat_win); touchwin(status_bar); touchwin(pos_win); touchwin(num_win); touchwin(rborder); redrawwin(rwin.title); redrawwin(rwin.win); redrawwin(lborder); redrawwin(stat_win); redrawwin(status_bar); redrawwin(pos_win); redrawwin(num_win); redrawwin(rborder); wnoutrefresh(rwin.title); wnoutrefresh(rwin.win); } } /* Two Pane View */ else { touchwin(lwin.title); touchwin(lwin.win); touchwin(mborder); touchwin(rwin.title); touchwin(rwin.win); touchwin(lborder); touchwin(stat_win); touchwin(status_bar); touchwin(pos_win); touchwin(num_win); touchwin(rborder); redrawwin(lwin.title); redrawwin(lwin.win); redrawwin(mborder); redrawwin(rwin.title); redrawwin(rwin.win); redrawwin(lborder); redrawwin(stat_win); redrawwin(status_bar); redrawwin(pos_win); redrawwin(num_win); redrawwin(rborder); wnoutrefresh(lwin.title); wnoutrefresh(lwin.win); wnoutrefresh(mborder); wnoutrefresh(rwin.title); wnoutrefresh(rwin.win); } wnoutrefresh(lborder); wnoutrefresh(stat_win); wnoutrefresh(status_bar); wnoutrefresh(pos_win); wnoutrefresh(num_win); wnoutrefresh(rborder); doupdate(); } /* * Main Loop * Everything is driven from this function with the exception of * signals which are handled in signals.c */ void main_key_press_cb(FileView *view) { int done = 0; int reset_last_char = 0; int save_count = 0; int count = 0; int key = 0; char count_buf[64] = ""; char status_buf[64] = ""; int save_reg = 0; curs_set(0); wattroff(view->win, COLOR_PAIR(CURR_LINE_COLOR)); /* Set keypress timeout to 1 second */ wtimeout(curr_view->win, 1000); wtimeout(other_view->win, 1000); update_stat_window(view); if (view->selected_files) { snprintf(status_buf, sizeof(status_buf), "%d %s Selected", view->selected_files, view->selected_files == 1 ? "File" : "Files"); status_bar_message(status_buf); } while (!done) { if (curr_stats.freeze) continue; /* Everything from here to if (key == ERR) gets called once a second */ check_if_filelists_have_changed(view); check_background_jobs(); check_messages(); if (!curr_stats.save_msg) { clean_status_bar(view); wrefresh(status_bar); } /* This waits for 1 second then skips if no keypress. */ key = wgetch(view->win); if (key == ERR) continue; else /* Puts the cursor at the start of the line for speakup */ { /* int x, y; char buf[256]; getyx(view->win, y, x); snprintf(buf, sizeof(buf), "x is %d y is %d ", x, y); show_error_msg("cursor curr_win", buf); wmove(stdscr, y + 2, 0); wrefresh(stdscr); getyx(stdscr, y, x); snprintf(buf, sizeof(buf), "x is %d y is %d ", x, y); show_error_msg("stdscr win", buf); */ } /* This point down gets called only when a key is actually pressed */ curr_stats.save_msg = 0; if (curr_stats.use_register && !curr_stats.register_saved) { if (is_valid_register(key)) { curr_stats.curr_register = key; curr_stats.register_saved = 1; save_reg = 1; continue; } else { status_bar_message("Invalid Register Key"); curr_stats.save_msg = 1; wrefresh(status_bar); curr_stats.use_register = 0; curr_stats.curr_register = -1; curr_stats.register_saved = 0; save_reg = 0; continue; } } else if((key > 47) && (key < 58)) /* ascii 0 - 9 */ { if (count > 62) { show_error_msg(" Number is too large ", "Vifm cannot handle that large of a number as a count. "); clear_num_window(); continue; } count_buf[count] = key; count++; count_buf[count] = '\0'; update_num_window(count_buf); continue; } else clear_num_window(); switch(key) { case '"': /* "register */ curr_stats.use_register = 1; break; case 2: /* ascii Ctrl B */ case KEY_PPAGE: view->list_pos = view->list_pos - view->window_rows; moveto_list_pos(view, view->list_pos); break; case 3: /* ascii Ctrl C */ case 27: /* ascii Escape */ { int x; for(x = 0; x < view->list_rows; x++) view->dir_entry[x].selected = 0; view->selected_files = 0; load_dir_list(curr_view, 1);// redraw_window(); curs_set(0); } break; case 6: /* ascii Ctrl F */ case KEY_NPAGE: view->list_pos = view->list_pos + view->window_rows; moveto_list_pos(view, view->list_pos); break; case 7: /* ascii Ctrl G */ if(!curr_stats.show_full) curr_stats.show_full = 1; break; case 9: /* ascii Tab */ case 32: /* ascii Spacebar */ change_window(&view); break; case 12: /* ascii Ctrl L - clear screen and redraw */ redraw_window(); curs_set(0); break; case 13: /* ascii Return */ handle_file(view); break; case 23: /* ascii Ctrl W - change windows */ { int letter; curr_stats.getting_input = 1; letter = wgetch(view->win); curr_stats.getting_input = 0; if((letter == 'h') && (view->win == rwin.win)) change_window(&view); else if((letter == 'l') && (view->win == lwin.win)) change_window(&view); } break; case '.': /* repeat last change */ repeat_last_command(view); break; case ':': /* command */ curr_stats.save_msg = get_command(view, GET_COMMAND, NULL); break; case '/': /* search */ curr_stats.save_msg = get_command(view, GET_SEARCH_PATTERN, NULL); break; case '?': /* search backwards */ break; case '\'': /* mark */ curr_stats.save_msg = get_bookmark(view); break; case '%': /* Jump to percent of file. */ if(count) { int percent = atoi(count_buf); int line = (percent * (view->list_rows)/100); moveto_list_pos(view, line -1); reset_last_char = 1; } break; case 'G': /* Jump to bottom of list. */ { if(count) moveto_list_pos(view, atoi(count_buf) -1); else moveto_list_pos(view, view->list_rows - 1); reset_last_char = 1; } break; /* tbrown */ case 'H': /* go to first file in window */ view->list_pos = view->top_line; moveto_list_pos(view, view->list_pos); reset_last_char =1; break; /* tbrown */ case 'L': /* go to last file in window */ view->list_pos = view->top_line + view->window_rows; moveto_list_pos(view, view->list_pos); reset_last_char =1; break; case 'M': /* zM Restore filename filter and hide dot files. */ if(curr_stats.last_char == 'z') { restore_filename_filter(view); hide_dot_files(view); reset_last_char = 1; } else { /* tbrown go to middle of window */ if (view->list_rows<view->window_rows) { view->list_pos = view->list_rows/2; } else { view->list_pos = view->top_line + (view->window_rows/2); } moveto_list_pos(view, view->list_pos); reset_last_char = 1; } break; case 'N': find_previous_pattern(view); break; case 'O': /* zO Remove filename filter. */ if(curr_stats.last_char == 'z') remove_filename_filter(view); reset_last_char = 1; break; case 'R': /* zR Show all hidden files */ { if(curr_stats.last_char == 'z') { remove_filename_filter(view); show_dot_files(view); } reset_last_char = 1; } break; case 'a': /* zo Show dot files */ if(curr_stats.last_char == 'z') toggle_dot_files(view); reset_last_char = 1; break; case 'c': /* cw change word */ { save_count = 1; update_num_window("c"); } break; case 'd': /* dd delete file */ { save_count = 1; update_num_window("d"); if(curr_stats.last_char == 'd') { clear_num_window(); if(view->selected_files) delete_file(view); else if(count) { int x; int y = view->list_pos; for(x = 0; x < atoi(count_buf); x++) { view->dir_entry[y].selected = 1; y++; } delete_file(view); } else delete_file(view); reset_last_char = 1; } } break; case 'f': /* zf filter selected files */ if(curr_stats.last_char == 'z') filter_selected_files(view); break; case 'g': /* gg Jump to top of the list. */ { save_count = 1; if(curr_stats.last_char == 'g') { if(count) moveto_list_pos(view, atoi(count_buf) -1); else moveto_list_pos(view, 0); reset_last_char = 1; } } break; case KEY_LEFT: case 'h': /* updir */ { change_directory(view, "../"); load_dir_list(view, 0); moveto_list_pos(view, view->list_pos); } break; case KEY_DOWN: case 'j': /* Move down one line */ { if(count) view->list_pos += atoi(count_buf); else view->list_pos++; moveto_list_pos(view, view->list_pos); reset_last_char =1; } break; case KEY_UP: case 'k': /* Move up one line */ { if(count) view->list_pos -= atoi(count_buf); else view->list_pos--; moveto_list_pos(view, view->list_pos); reset_last_char = 1; } break; case KEY_RIGHT: case 'l': handle_file(view); break; case 'm': /* 'm' set mark and 'zm' hide dot files */ { if(curr_stats.last_char == 'z') { hide_dot_files(view); reset_last_char = 1; } else { int mark; curr_stats.getting_input = 1; wtimeout(curr_view->win, -1); mark = wgetch(view->win); wtimeout(curr_view->win, 1000); curr_stats.getting_input = 0; if(key == ERR) continue; add_bookmark(mark, view->curr_dir, get_current_file_name(view)); } } break; case 'n': find_next_pattern(view); break; case 'o': /* zo Show dot files */ if(curr_stats.last_char == 'z') show_dot_files(view); reset_last_char = 1; break; case 'p': /* put files */ curr_stats.save_msg = put_files(view); break; case 's': /* tmp shellout **** This should be done with key mapping */ shellout(NULL, 0); break; case 't': /* Tag file. */ tag_file(view); break; /* tbrown */ case 'V': case 'v': /* Visual selection of files. */ curr_stats.save_msg = start_visual_mode(view); break; case 'w': /* cw change word */ { if (curr_stats.last_char == 'c') rename_file(view); } break; /* tbrown */ case 'Y': /* Y yank file */ yank_files(view, count, count_buf); reset_last_char++; curr_stats.save_msg = 1; break; case 'y': /* yy yank file */ { if(curr_stats.last_char == 'y') { yank_files(view, count, count_buf); reset_last_char++; curr_stats.save_msg = 1; save_reg = 0; } else { update_num_window("y"); save_reg = 1; } save_count = 1; } break; case 'z': /* zz redraw with file in center of list */ if(curr_stats.last_char == 'z') { } break; default: break; } /* end of switch(key) */ curr_stats.last_char = key; if(!save_count) count = 0; if(reset_last_char) { curr_stats.last_char = 0; reset_last_char = 0; count = 0; } if(curr_stats.show_full) show_full_file_properties(view); else update_stat_window(view); if(view->selected_files) { static int number = 0; if(number != view->selected_files) { snprintf(status_buf, sizeof(status_buf), "%d %s Selected", view->selected_files, view->selected_files == 1 ? "File" : "Files"); status_bar_message(status_buf); curr_stats.save_msg = 1; } } else if(!curr_stats.save_msg) clean_status_bar(view); if (curr_stats.use_register && curr_stats.register_saved) { if (!save_reg) { curr_stats.use_register = 0; curr_stats.curr_register = -1; curr_stats.register_saved = 0; } } if(curr_stats.need_redraw) load_dir_list(curr_view, 1);// redraw_window(); update_all_windows(); } /* end of while(!done) */ }