📄 main.c
字号:
/* Main program for the Midnight Commander
Copyright (C) 1994, 1995, 1996, 1997 The Free Software Foundation
Written by: 1994, 1995, 1996, 1997 Miguel de Icaza
1994, 1995 Janne Kukonlehto
1997 Norbert Warmuth
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., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <config.h>
#include <locale.h>
#ifdef _OS_NT
# include <windows.h>
#endif
#ifdef __os2__
# define INCL_DOS
# define INCL_DOSFILEMGR
# define INCL_DOSERRORS
# include <os2.h>
#endif
#include "tty.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/stat.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
/* unistd.h defines _POSIX_VERSION on POSIX.1 systems. */
#if defined(HAVE_DIRENT_H) || defined(_POSIX_VERSION)
# include <dirent.h>
# define NLENGTH(dirent) (strlen ((dirent)->d_name))
#else
# define dirent direct
# define NLENGTH(dirent) ((dirent)->d_namlen)
# ifdef HAVE_SYS_NDIR_H
# include <sys/ndir.h>
# endif /* HAVE_SYS_NDIR_H */
# ifdef HAVE_SYS_DIR_H
# include <sys/dir.h>
# endif /* HAVE_SYS_DIR_H */
# ifdef HAVE_NDIR_H
# include <ndir.h>
# endif /* HAVE_NDIR_H */
#endif /* not (HAVE_DIRENT_H or _POSIX_VERSION) */
#if HAVE_SYS_WAIT_H
# include <sys/wait.h> /* For waitpid() */
#endif
#include <errno.h>
#ifndef OS2_NT
# include <pwd.h>
#endif
#include <ctype.h>
#include <fcntl.h> /* For O_RDWR */
#include <signal.h>
/* Program include files */
#include "x.h"
#include "mad.h"
#include "dir.h"
#include "color.h"
#include "global.h"
#include "util.h"
#include "dialog.h"
#include "menu.h"
#include "file.h"
#include "panel.h"
#include "main.h"
#include "win.h"
#include "user.h"
#include "mem.h"
#include "mouse.h"
#include "option.h"
#include "tree.h"
#include "cons.saver.h"
#include "subshell.h"
#include "key.h" /* For init_key() and mi_getch() */
#include "setup.h" /* save_setup() */
#include "profile.h" /* free_profiles() */
#include "boxes.h"
#include "layout.h"
#include "cmd.h" /* Normal commands */
#include "hotlist.h"
#include "panelize.h"
#ifndef __os2__
# include "learn.h"
#endif
#include "listmode.h"
#include "background.h"
#include "ext.h" /* For flush_extension_file() */
/* Listbox for the command history feature */
#include "widget.h"
#include "command.h"
#include "wtools.h"
#include "complete.h" /* For the free_completion */
#include "chmod.h"
#include "chown.h"
#ifdef OS2_NT
# include <io.h>
# include <drive.h>
#endif
#include "../vfs/vfs.h"
#include "../vfs/extfs.h"
#include "popt.h"
/* "$Id: main.c 23951 2006-09-07 09:17:39Z greatlrd $" */
/* When the modes are active, left_panel, right_panel and tree_panel */
/* Point to a proper data structure. You should check with the functions */
/* get_current_type and get_other_type the types of the panels before using */
/* This pointer variables */
/* The structures for the panels */
WPanel *left_panel;
WPanel *right_panel;
/* The pointer to the tree */
WTree *the_tree;
/* The Menubar */
WMenu *the_menubar;
/* Pointers to the selected and unselected panel */
WPanel *current_panel = NULL;
/* Set when we want use advanced chmod command instead of chmod and/or chown */
int advanced_chfns = 0;
/* Set when main loop should be terminated */
volatile int quit = 0;
/* Set if you want the possible completions dialog for the first time */
int show_all_if_ambiguous = 0;
/* Set when cd symlink following is desirable (bash mode) */
int cd_symlinks = 1;
/* If set then dialogs just clean the screen when refreshing, else */
/* they do a complete refresh, refreshing all the parts of the program */
int fast_refresh = 0;
/* If true, marking a files moves the cursor down */
int mark_moves_down = 1;
/* If true, at startup the user-menu is invoked */
int auto_menu = 0;
/* If true, use + and \ keys normally and select/unselect do if M-+ / M-\ and M--
and keypad + / - */
int alternate_plus_minus = 0;
/* If true, then the +, - and \ keys have their special meaning only if the
* command line is emtpy, otherwise they behave like regular letters
*/
int only_leading_plus_minus = 1;
/* If true, after executing a command, wait for a keystroke */
enum { pause_never, pause_on_dumb_terminals, pause_always };
int pause_after_run = pause_on_dumb_terminals;
/* It true saves the setup when quitting */
int auto_save_setup = 1;
/* If true, be eight bit clean */
int eight_bit_clean = 0;
/* If true, then display chars 0-255, else iso-8859-1,
requires eight_bit_clean */
int full_eight_bits = 0;
/* If true use the internal viewer */
int use_internal_view = 1;
/* Have we shown the fast-reload warning in the past? */
int fast_reload_w = 0;
/* Move page/item? When clicking on the top or bottom of a panel */
int mouse_move_pages = 1;
/* If true: l&r arrows are used to chdir if the input line is empty */
int navigate_with_arrows = 0;
/* If it is set, the commander will iconify itself when executing a program */
int iconify_on_exec = 1;
/* If true use +, -, | for line drawing */
int force_ugly_line_drawing = 0;
/* If true message "The shell is already running a command" never */
int force_subshell_execution = 0;
/* If true program softkeys (HP terminals only) on startup and after every
command ran in the subshell to the description found in the termcap/terminfo
database */
int reset_hp_softkeys = 0;
/* The prompt */
char *prompt = 0;
/* The widget where we draw the prompt */
WLabel *the_prompt;
/* The hint bar */
WLabel *the_hint;
/* The button bar */
WButtonBar *the_bar;
#ifdef HAVE_X
WButtonBar *the_bar2;
#endif
/* For slow terminals */
int slow_terminal = 0;
/* use mouse? */
int use_mouse_p = GPM_MOUSE;
/* If true, assume we are running on an xterm terminal */
static int force_xterm = 0;
/* Controls screen clearing before an exec */
int clear_before_exec = 1;
/* Asks for confirmation before deleting a file */
int confirm_delete = 1;
/* Asks for confirmation before overwriting a file */
int confirm_overwrite = 1;
/* Asks for confirmation before executing a program by pressing enter */
int confirm_execute = 0;
/* Asks for confirmation before leaving the program */
int confirm_exit = 1;
/* Asks for confirmation when using F3 to view a directory and there
are tagged files */
int confirm_view_dir = 0;
/* This flag indicates if the pull down menus by default drop down */
int drop_menus = 0;
/* The dialog handle for the main program */
Dlg_head *midnight_dlg;
/* Subshell: if set, then the prompt was not saved on CONSOLE_SAVE */
/* We need to paint it after CONSOLE_RESTORE, see: load_prompt */
int update_prompt = 0;
/* The name which was used to invoke mc */
char *program_name;
/* The home directory */
char *home_dir;
/* The value of the other directory, only used when loading the setup */
char *other_dir = 0;
char *this_dir = 0;
/* If true, then print on stdout the last directory we were at */
static int print_last_wd = 0;
static char *last_wd_string;
static int print_last_revert = 0;
/* On OS/2 and on Windows NT, we need a batch file to do the -P magic */
#ifdef OS2_NT
static char *batch_file_name = 0;
#endif
/* widget colors for the midnight commander */
int midnight_colors [4];
/* Force colors, only used by Slang */
int force_colors = 0;
/* colors specified on the command line: they override any other setting */
char *command_line_colors;
/* File name to view if argument was supplied */
char *view_one_file = 0;
/* File name to view if argument was supplied */
char *edit_one_file = 0;
/* Used so that widgets know if they are being destroyed or
shut down */
int midnight_shutdown = 0;
/* to show nice prompts */
static int last_paused = 0;
/* Only used at program boot */
int boot_current_is_left = 1;
/* Used for keeping track of the original stdout */
int stdout_fd = 0;
/* The user's shell */
char *shell;
/* mc_home: The home of MC */
char *mc_home;
/* if on, it displays the information that files have been moved to ~/.mc */
int show_change_notice = 0;
char cmd_buf [512];
/* Used during argument processing */
int finish_program = 0;
/* Forward declarations */
char *get_mc_lib_dir ();
int panel_event (Gpm_Event *event, WPanel *panel);
int menu_bar_event (Gpm_Event *event, void *);
static void menu_cmd (void);
#ifndef HAVE_GNOME
WPanel *
get_current_panel ()
{
return current_panel;
}
WPanel *
get_other_panel ()
{
return (WPanel *) get_panel_widget (get_other_index ());
}
#endif
void
try_to_select (WPanel *panel, char *name)
{
Xtry_to_select (panel, name);
select_item (panel);
display_mini_info (panel);
}
/*
* cd_try_to_select:
*
* If we moved to the parent directory move the selection pointer to
* the old directory name
*/
void
cd_try_to_select (WPanel *panel)
{
#ifdef USE_VFS
char *p, *q;
#endif
int i, j = 4;
if (strlen (panel->lwd) > strlen (panel->cwd)
&& strncmp (panel->cwd, panel->lwd, strlen (panel->cwd)) == 0
&& strchr (panel->lwd + strlen (panel->cwd) + 1, PATH_SEP) == 0)
try_to_select (panel, panel->lwd);
else
#ifdef USE_VFS
if ((!strncmp (panel->lwd, "tar:", 4) &&
!strncmp (panel->lwd + 4, panel->cwd, strlen (panel->cwd))) ||
((i = extfs_prefix_to_type (panel->lwd)) != -1 &&
!strncmp (panel->lwd + (j = strlen (extfs_get_prefix (i)) + 1),
panel->cwd, strlen (panel->cwd)))) {
p = strdup (panel->lwd + j + strlen (panel->cwd));
q = strchr (p, PATH_SEP);
if (q != NULL && (q != p || (q = strchr (q + 1, PATH_SEP)) != NULL))
*q = 0;
try_to_select (panel, p);
free (p);
} else
#endif
try_to_select (panel, NULL);
}
void
reload_panelized (WPanel *panel)
{
int i, j;
dir_list *list = &panel->dir;
if (panel != cpanel)
mc_chdir (panel->cwd);
for (i = 0, j = 0; i < panel->count; i++){
if (list->list [i].f.marked) {
/* Unmark the file in advance. In case the following mc_lstat
* fails we are done, else we have to mark the file again
* (Note: do_file_mark depends on a valid "list->list [i].buf").
* IMO that's the best way to update the panel's summary status
* -- Norbert
*/
do_file_mark (panel, i, 0);
}
if (mc_lstat (list->list [i].fname, &list->list [i].buf)){
free (list->list [i].fname);
continue;
}
if (list->list [i].f.marked)
do_file_mark (panel, i, 1);
if (j != i)
list->list [j] = list->list [i];
j++;
}
if (j == 0)
panel->count = set_zero_dir (list);
else
panel->count = j;
if (panel != cpanel)
mc_chdir (cpanel->cwd);
}
void
update_one_panel_widget (WPanel *panel, int force_update, char *current_file)
{
int free_pointer;
if (force_update & UP_RELOAD){
panel->is_panelized = 0;
ftpfs_flushdir ();
bzero (&(panel->dir_stat), sizeof (panel->dir_stat));
}
/* If current_file == -1 (an invalid pointer) then preserve selection */
if (current_file == UP_KEEPSEL){
free_pointer = 1;
current_file = strdup (panel->dir.list [panel->selected].fname);
} else
free_pointer = 0;
if (panel->is_panelized)
reload_panelized (panel);
else
panel_reload (panel);
try_to_select (panel, current_file);
panel->dirty = 1;
if (free_pointer)
free (current_file);
}
#ifndef PORT_HAS_UPDATE_PANELS
void
update_one_panel (int which, int force_update, char *current_file)
{
WPanel *panel;
if (get_display_type (which) != view_listing)
return;
panel = (WPanel *) get_panel_widget (which);
update_one_panel_widget (panel, force_update, current_file);
}
/* This routine reloads the directory in both panels. It tries to
* select current_file in current_panel and other_file in other_panel.
* If current_file == -1 then it automatically sets current_file and
* other_file to the currently selected files in the panels.
*
* if force_update has the UP_ONLY_CURRENT bit toggled on, then it
* will not reload the other panel.
*/
void
update_panels (int force_update, char *current_file)
{
int reload_other = !(force_update & UP_ONLY_CURRENT);
WPanel *panel;
update_one_panel (get_current_index (), force_update, current_file);
if (reload_other)
update_one_panel (get_other_index (), force_update, UP_KEEPSEL);
if (get_current_type () == view_listing)
panel = (WPanel *) get_panel_widget (get_current_index ());
else
panel = (WPanel *) get_panel_widget (get_other_index ());
mc_chdir (panel->cwd);
}
#endif
#ifdef WANT_PARSE
static void select_by_index (WPanel *panel, int i);
/* Called by parse_control_file */
static int index_by_name (file_entry *list, int count)
{
char *name;
int i;
name = strtok (NULL, " \t\n");
if (!name || !*name)
return -1;
for (i = 0; i < count; i++){
if (strcmp (name, list[i].fname) == 0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -