12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550 |
- /* Routines invoked by a function key
- They normally operate on the current panel.
- Copyright (C) 1994, 1995, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
- 2005, 2006, 2007, 2009 Free Software Foundation, Inc.
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
- /** \file cmd.c
- * \brief Source: routines invoked by a function key
- *
- * They normally operate on the current panel.
- */
- #include <config.h>
- #include <errno.h>
- #include <stdio.h>
- #include <string.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #ifdef HAVE_MMAP
- # include <sys/mman.h>
- #endif
- #ifdef ENABLE_VFS_NET
- #include <netdb.h>
- #endif
- #include <unistd.h>
- #include <stdlib.h>
- #include <fcntl.h>
- #include <pwd.h>
- #include <grp.h>
- #include <sys/time.h>
- #include "lib/global.h"
- #include "lib/tty/tty.h" /* LINES, tty_touch_screen() */
- #include "lib/tty/key.h" /* ALT() macro */
- #include "lib/tty/win.h" /* do_enter_ca_mode() */
- #include "lib/mcconfig.h"
- #include "lib/search.h"
- #include "src/viewer/mcviewer.h"
- #include "lib/filehighlight.h" /* MC_FHL_INI_FILE */
- #include "lib/vfs/mc-vfs/vfs.h"
- #include "lib/fileloc.h"
- #include "lib/strutil.h"
- #include "cmd.h" /* Our definitions */
- #include "fileopctx.h"
- #include "file.h" /* file operation routines */
- #include "find.h" /* do_find() */
- #include "hotlist.h" /* hotlist_cmd() */
- #include "tree.h" /* tree_chdir() */
- #include "subshell.h" /* use_subshell */
- #include "consaver/cons.saver.h" /* console_flag */
- #include "dialog.h" /* Widget */
- #include "dialog-switch.h"
- #include "wtools.h" /* message() */
- #include "main.h" /* change_panel() */
- #include "panel.h" /* current_panel */
- #include "help.h" /* interactive_display() */
- #include "user.h" /* MC_GLOBAL_MENU */
- #include "command.h" /* cmdline */
- #include "layout.h" /* get_current_type() */
- #include "ext.h" /* regex_command() */
- #include "boxes.h" /* cd_dialog() */
- #include "setup.h"
- #include "execute.h" /* toggle_panels() */
- #include "history.h"
- #include "dir.h"
- #include "cmddef.h" /* CK_InputHistoryShow */
- #ifndef MAP_FILE
- # define MAP_FILE 0
- #endif
- #ifdef USE_INTERNAL_EDIT
- # include "src/editor/edit.h"
- #endif
- #ifdef USE_DIFF_VIEW
- # include "src/diffviewer/ydiff.h"
- #endif
- /* If set and you don't have subshell support,then C-o will give you a shell */
- int output_starts_shell = 0;
- /* If set, use the builtin editor */
- int use_internal_edit = 1;
- /* Automatically fills name with current selected item name on mkdir */
- int auto_fill_mkdir_name = 1;
- /* selection flags */
- typedef enum
- {
- SELECT_FILES_ONLY = 1 << 0,
- SELECT_MATCH_CASE = 1 << 1,
- SELECT_SHELL_PATTERNS = 1 << 2
- } select_flags_t;
- int select_flags = SELECT_MATCH_CASE | SELECT_SHELL_PATTERNS;
- int
- view_file_at_line (const char *filename, int plain_view, int internal, int start_line)
- {
- static const char *viewer = NULL;
- int move_dir = 0;
- if (plain_view)
- {
- int changed_hex_mode = 0;
- int changed_nroff_flag = 0;
- int changed_magic_flag = 0;
- mcview_altered_hex_mode = 0;
- mcview_altered_nroff_flag = 0;
- mcview_altered_magic_flag = 0;
- if (mcview_default_hex_mode)
- changed_hex_mode = 1;
- if (mcview_default_nroff_flag)
- changed_nroff_flag = 1;
- if (mcview_default_magic_flag)
- changed_magic_flag = 1;
- mcview_default_hex_mode = 0;
- mcview_default_nroff_flag = 0;
- mcview_default_magic_flag = 0;
- switch (mcview_viewer (NULL, filename, start_line))
- {
- case MCVIEW_WANT_NEXT:
- move_dir = 1;
- break;
- case MCVIEW_WANT_PREV:
- move_dir = -1;
- break;
- default:
- move_dir = 0;
- }
- if (changed_hex_mode && !mcview_altered_hex_mode)
- mcview_default_hex_mode = 1;
- if (changed_nroff_flag && !mcview_altered_nroff_flag)
- mcview_default_nroff_flag = 1;
- if (changed_magic_flag && !mcview_altered_magic_flag)
- mcview_default_magic_flag = 1;
- dialog_switch_process_pending ();
- }
- else if (internal)
- {
- char view_entry[BUF_TINY];
- if (start_line != 0)
- g_snprintf (view_entry, sizeof (view_entry), "View:%d", start_line);
- else
- strcpy (view_entry, "View");
- if (regex_command (filename, view_entry, &move_dir) == 0)
- {
- switch (mcview_viewer (NULL, filename, start_line))
- {
- case MCVIEW_WANT_NEXT:
- move_dir = 1;
- break;
- case MCVIEW_WANT_PREV:
- move_dir = -1;
- break;
- default:
- move_dir = 0;
- }
- dialog_switch_process_pending ();
- }
- }
- else
- {
- if (viewer == NULL)
- {
- viewer = getenv ("VIEWER");
- if (viewer == NULL)
- viewer = getenv ("PAGER");
- if (viewer == NULL)
- viewer = "view";
- }
- execute_with_vfs_arg (viewer, filename);
- }
- return move_dir;
- }
- /* view_file (filename, plain_view, internal)
- *
- * Inputs:
- * filename: The file name to view
- * plain_view: If set does not do any fancy pre-processing (no filtering) and
- * always invokes the internal viewer.
- * internal: If set uses the internal viewer, otherwise an external viewer.
- */
- int
- view_file (const char *filename, int plain_view, int internal)
- {
- return view_file_at_line (filename, plain_view, internal, 0);
- }
- /* scan_for_file (panel, idx, direction)
- *
- * Inputs:
- * panel: pointer to the panel on which we operate
- * idx: starting file.
- * direction: 1, or -1
- */
- static int
- scan_for_file (WPanel * panel, int idx, int direction)
- {
- int i = idx + direction;
- while (i != idx)
- {
- if (i < 0)
- i = panel->count - 1;
- if (i == panel->count)
- i = 0;
- if (!S_ISDIR (panel->dir.list[i].st.st_mode))
- return i;
- i += direction;
- }
- return i;
- }
- /*
- * Run viewer (internal or external) on the currently selected file.
- * If normal is 1, force internal viewer and raw mode (used for F13).
- */
- static void
- do_view_cmd (int normal)
- {
- /* Directories are viewed by changing to them */
- if (S_ISDIR (selection (current_panel)->st.st_mode) || link_isdir (selection (current_panel)))
- {
- if (confirm_view_dir && (current_panel->marked || current_panel->dirs_marked))
- {
- if (query_dialog
- (_("Confirmation"), _("Files tagged, want to cd?"), D_NORMAL, 2,
- _("&Yes"), _("&No")) != 0)
- {
- return;
- }
- }
- if (!do_cd (selection (current_panel)->fname, cd_exact))
- message (D_ERROR, MSG_ERROR, _("Cannot change directory"));
- }
- else
- {
- int dir, file_idx;
- char *filename;
- file_idx = current_panel->selected;
- while (1)
- {
- filename = current_panel->dir.list[file_idx].fname;
- dir = view_file (filename, normal, use_internal_view);
- if (dir == 0)
- break;
- file_idx = scan_for_file (current_panel, file_idx, dir);
- }
- }
- repaint_screen ();
- }
- /* Run user's preferred viewer on the currently selected file */
- void
- view_cmd (void)
- {
- do_view_cmd (0);
- }
- /* Ask for file and run user's preferred viewer on it */
- void
- view_file_cmd (void)
- {
- char *filename;
- filename =
- input_expand_dialog (_("View file"), _("Filename:"),
- MC_HISTORY_FM_VIEW_FILE, selection (current_panel)->fname);
- if (!filename)
- return;
- view_file (filename, 0, use_internal_view);
- g_free (filename);
- }
- /* Run plain internal viewer on the currently selected file */
- void
- view_simple_cmd (void)
- {
- do_view_cmd (1);
- }
- void
- filtered_view_cmd (void)
- {
- char *command;
- command =
- input_dialog (_("Filtered view"),
- _("Filter command and arguments:"),
- MC_HISTORY_FM_FILTERED_VIEW, selection (current_panel)->fname);
- if (command != NULL)
- {
- mcview_viewer (command, "", 0);
- g_free (command);
- dialog_switch_process_pending ();
- }
- }
- void
- do_edit_at_line (const char *what, gboolean internal, int start_line)
- {
- static const char *editor = NULL;
- #ifdef USE_INTERNAL_EDIT
- if (internal)
- edit_file (what, start_line);
- else
- #else
- (void) start_line;
- #endif /* USE_INTERNAL_EDIT */
- {
- if (editor == NULL)
- {
- editor = getenv ("EDITOR");
- if (editor == NULL)
- editor = get_default_editor ();
- }
- execute_with_vfs_arg (editor, what);
- }
- if (mc_run_mode == MC_RUN_FULL)
- update_panels (UP_OPTIMIZE, UP_KEEPSEL);
- #ifdef USE_INTERNAL_EDIT
- if (use_internal_edit)
- dialog_switch_process_pending ();
- else
- #endif /* USE_INTERNAL_EDIT */
- repaint_screen ();
- }
- static inline void
- do_edit (const char *what)
- {
- do_edit_at_line (what, use_internal_edit, 0);
- }
- void
- edit_cmd (void)
- {
- if (regex_command (selection (current_panel)->fname, "Edit", NULL) == 0)
- do_edit (selection (current_panel)->fname);
- }
- #ifdef USE_INTERNAL_EDIT
- void
- edit_cmd_force_internal (void)
- {
- if (regex_command (selection (current_panel)->fname, "Edit", NULL) == 0)
- do_edit_at_line (selection (current_panel)->fname, TRUE, 0);
- }
- #endif
- void
- edit_cmd_new (void)
- {
- #if HAVE_CHARSET
- source_codepage = default_source_codepage;
- #endif
- do_edit (NULL);
- }
- /* Invoked by F5. Copy, default to the other panel. */
- void
- copy_cmd (void)
- {
- save_cwds_stat ();
- if (panel_operate (current_panel, OP_COPY, FALSE))
- {
- update_panels (UP_OPTIMIZE, UP_KEEPSEL);
- repaint_screen ();
- }
- }
- /* Invoked by F6. Move/rename, default to the other panel, ignore marks. */
- void
- rename_cmd (void)
- {
- save_cwds_stat ();
- if (panel_operate (current_panel, OP_MOVE, FALSE))
- {
- update_panels (UP_OPTIMIZE, UP_KEEPSEL);
- repaint_screen ();
- }
- }
- /* Invoked by F15. Copy, default to the same panel, ignore marks. */
- void
- copy_cmd_local (void)
- {
- save_cwds_stat ();
- if (panel_operate (current_panel, OP_COPY, TRUE))
- {
- update_panels (UP_OPTIMIZE, UP_KEEPSEL);
- repaint_screen ();
- }
- }
- /* Invoked by F16. Move/rename, default to the same panel. */
- void
- rename_cmd_local (void)
- {
- save_cwds_stat ();
- if (panel_operate (current_panel, OP_MOVE, TRUE))
- {
- update_panels (UP_OPTIMIZE, UP_KEEPSEL);
- repaint_screen ();
- }
- }
- void
- mkdir_cmd (void)
- {
- char *dir, *absdir;
- const char *name = "";
- /* If 'on' then automatically fills name with current selected item name */
- if (auto_fill_mkdir_name && strcmp (selection (current_panel)->fname, "..") != 0)
- name = selection (current_panel)->fname;
- dir =
- input_expand_dialog (_("Create a new Directory"),
- _("Enter directory name:"), MC_HISTORY_FM_MKDIR, name);
- if (!dir)
- return;
- if (*dir)
- {
- if (dir[0] == '/' || dir[0] == '~')
- absdir = g_strdup (dir);
- else
- absdir = concat_dir_and_file (current_panel->cwd, dir);
- save_cwds_stat ();
- if (my_mkdir (absdir, 0777) == 0)
- {
- update_panels (UP_OPTIMIZE, dir);
- repaint_screen ();
- select_item (current_panel);
- }
- else
- {
- message (D_ERROR, MSG_ERROR, "%s", unix_error_string (errno));
- }
- g_free (absdir);
- }
- g_free (dir);
- }
- void
- delete_cmd (void)
- {
- save_cwds_stat ();
- if (panel_operate (current_panel, OP_DELETE, FALSE))
- {
- update_panels (UP_OPTIMIZE, UP_KEEPSEL);
- repaint_screen ();
- }
- }
- /* Invoked by F18. Remove selected file, regardless of marked files. */
- void
- delete_cmd_local (void)
- {
- save_cwds_stat ();
- if (panel_operate (current_panel, OP_DELETE, TRUE))
- {
- update_panels (UP_OPTIMIZE, UP_KEEPSEL);
- repaint_screen ();
- }
- }
- void
- find_cmd (void)
- {
- do_find ();
- }
- static void
- set_panel_filter_to (WPanel * p, char *allocated_filter_string)
- {
- g_free (p->filter);
- p->filter = 0;
- if (!(allocated_filter_string[0] == '*' && allocated_filter_string[1] == 0))
- p->filter = allocated_filter_string;
- else
- g_free (allocated_filter_string);
- reread_cmd ();
- }
- /* Set a given panel filter expression */
- static void
- set_panel_filter (WPanel * p)
- {
- char *reg_exp;
- const char *x;
- x = p->filter ? p->filter : easy_patterns ? "*" : ".";
- reg_exp = input_dialog_help (_("Filter"),
- _("Set expression for filtering filenames"),
- "[Filter...]", MC_HISTORY_FM_PANEL_FILTER, x);
- if (!reg_exp)
- return;
- set_panel_filter_to (p, reg_exp);
- }
- /* Invoked from the left/right menus */
- void
- filter_cmd (void)
- {
- WPanel *p;
- if (!SELECTED_IS_PANEL)
- return;
- p = MENU_PANEL;
- set_panel_filter (p);
- }
- 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 ();
- }
- void
- reverse_selection_cmd (void)
- {
- int i;
- file_entry *file;
- for (i = 0; i < current_panel->count; i++)
- {
- file = ¤t_panel->dir.list[i];
- if (!panels_options.reverse_files_only || !S_ISDIR (file->st.st_mode))
- do_file_mark (current_panel, i, !file->f.marked);
- }
- }
- static void
- select_unselect_cmd (const char *title, const char *history_name, gboolean do_select)
- {
- /* dialog sizes */
- const int DX = 50;
- const int DY = 7;
- int files_only = (select_flags & SELECT_FILES_ONLY) != 0;
- int case_sens = (select_flags & SELECT_MATCH_CASE) != 0;
- int shell_patterns = (select_flags & SELECT_SHELL_PATTERNS) != 0;
- char *reg_exp;
- mc_search_t *search;
- int i;
- QuickWidget quick_widgets[] = {
- QUICK_CHECKBOX (3, DX, DY - 3, DY, N_("&Using shell patterns"), &shell_patterns),
- QUICK_CHECKBOX (DX / 2 + 1, DX, DY - 4, DY, N_("&Case sensitive"), &case_sens),
- QUICK_CHECKBOX (3, DX, DY - 4, DY, N_("&Files only"), &files_only),
- QUICK_INPUT (3, DX, DY - 5, DY, INPUT_LAST_TEXT, DX - 6, 0, history_name, ®_exp),
- QUICK_END
- };
- QuickDialog quick_dlg = {
- DX, DY, -1, -1, title,
- "[Select/Unselect Files]", quick_widgets, NULL, FALSE
- };
- if (quick_dialog (&quick_dlg) == B_CANCEL)
- return;
- if (!reg_exp)
- return;
- if (!*reg_exp)
- {
- g_free (reg_exp);
- return;
- }
- search = mc_search_new (reg_exp, -1);
- search->search_type = (shell_patterns != 0) ? MC_SEARCH_T_GLOB : MC_SEARCH_T_REGEX;
- search->is_entire_line = TRUE;
- search->is_case_sensitive = case_sens != 0;
- for (i = 0; i < current_panel->count; i++)
- {
- if (strcmp (current_panel->dir.list[i].fname, "..") == 0)
- continue;
- if (S_ISDIR (current_panel->dir.list[i].st.st_mode) && files_only != 0)
- continue;
- if (mc_search_run (search, current_panel->dir.list[i].fname,
- 0, current_panel->dir.list[i].fnamelen, NULL))
- do_file_mark (current_panel, i, do_select);
- }
- mc_search_free (search);
- g_free (reg_exp);
- /* result flags */
- select_flags = 0;
- if (case_sens != 0)
- select_flags |= SELECT_MATCH_CASE;
- if (files_only != 0)
- select_flags |= SELECT_FILES_ONLY;
- if (shell_patterns != 0)
- select_flags |= SELECT_SHELL_PATTERNS;
- }
- void
- select_cmd (void)
- {
- select_unselect_cmd (_("Select"), ":select_cmd: Select ", TRUE);
- }
- void
- unselect_cmd (void)
- {
- select_unselect_cmd (_("Unselect"), ":unselect_cmd: Unselect ", FALSE);
- }
- void
- ext_cmd (void)
- {
- char *buffer;
- char *extdir;
- int dir;
- dir = 0;
- if (geteuid () == 0)
- {
- dir = query_dialog (_("Extension file edit"),
- _("Which extension file you want to edit?"), D_NORMAL, 2,
- _("&User"), _("&System Wide"));
- }
- extdir = concat_dir_and_file (mc_home, MC_LIB_EXT);
- if (dir == 0)
- {
- buffer = g_build_filename (home_dir, MC_USERCONF_DIR, MC_FILEBIND_FILE, NULL);
- check_for_default (extdir, buffer);
- do_edit (buffer);
- g_free (buffer);
- }
- else if (dir == 1)
- {
- if (!exist_file (extdir))
- {
- g_free (extdir);
- extdir = concat_dir_and_file (mc_home_alt, MC_LIB_EXT);
- }
- do_edit (extdir);
- }
- g_free (extdir);
- flush_extension_file ();
- }
- /* edit file menu for mc */
- void
- edit_mc_menu_cmd (void)
- {
- char *buffer;
- char *menufile;
- int dir = 0;
- dir = query_dialog (_("Menu edit"),
- _("Which menu file do you want to edit?"),
- D_NORMAL, geteuid ()? 2 : 3, _("&Local"), _("&User"), _("&System Wide"));
- menufile = concat_dir_and_file (mc_home, MC_GLOBAL_MENU);
- if (!exist_file (menufile))
- {
- g_free (menufile);
- menufile = concat_dir_and_file (mc_home_alt, MC_GLOBAL_MENU);
- }
- switch (dir)
- {
- case 0:
- buffer = g_strdup (MC_LOCAL_MENU);
- check_for_default (menufile, buffer);
- chmod (buffer, 0600);
- break;
- case 1:
- buffer = g_build_filename (home_dir, MC_USERCONF_DIR, MC_USERMENU_FILE, NULL);
- check_for_default (menufile, buffer);
- break;
- case 2:
- buffer = concat_dir_and_file (mc_home, MC_GLOBAL_MENU);
- if (!exist_file (buffer))
- {
- g_free (buffer);
- buffer = concat_dir_and_file (mc_home_alt, MC_GLOBAL_MENU);
- }
- break;
- default:
- g_free (menufile);
- return;
- }
- do_edit (buffer);
- g_free (buffer);
- g_free (menufile);
- }
- void
- edit_fhl_cmd (void)
- {
- char *buffer = NULL;
- char *fhlfile = NULL;
- int dir;
- dir = 0;
- if (geteuid () == 0)
- {
- dir = query_dialog (_("Highlighting groups file edit"),
- _("Which highlighting file you want to edit?"), D_NORMAL, 2,
- _("&User"), _("&System Wide"));
- }
- fhlfile = concat_dir_and_file (mc_home, MC_FHL_INI_FILE);
- if (dir == 0)
- {
- buffer = g_build_filename (home_dir, MC_USERCONF_DIR, MC_FHL_INI_FILE, NULL);
- check_for_default (fhlfile, buffer);
- do_edit (buffer);
- g_free (buffer);
- }
- else if (dir == 1)
- {
- if (!exist_file (fhlfile))
- {
- g_free (fhlfile);
- fhlfile = concat_dir_and_file (mc_home, MC_FHL_INI_FILE);
- }
- do_edit (fhlfile);
- }
- g_free (fhlfile);
- /* refresh highlighting rules */
- mc_fhl_free (&mc_filehighlight);
- mc_filehighlight = mc_fhl_new (TRUE);
- }
- void
- quick_chdir_cmd (void)
- {
- char *target;
- target = hotlist_cmd (LIST_HOTLIST);
- if (!target)
- return;
- if (get_current_type () == view_tree)
- tree_chdir (the_tree, target);
- else
- {
- char *cmd = g_strconcat ("cd ", target, (char *) NULL);
- do_cd_command (cmd);
- g_free (cmd);
- }
- g_free (target);
- }
- #ifdef ENABLE_VFS
- void
- reselect_vfs (void)
- {
- char *target;
- target = hotlist_cmd (LIST_VFSLIST);
- if (!target)
- return;
- if (!do_cd (target, cd_exact))
- message (D_ERROR, MSG_ERROR, _("Cannot change directory"));
- g_free (target);
- }
- #endif /* ENABLE_VFS */
- static int
- compare_files (char *name1, char *name2, off_t size)
- {
- int file1, file2;
- int result = -1; /* Different by default */
- if (size == 0)
- return 0;
- file1 = open (name1, O_RDONLY);
- if (file1 >= 0)
- {
- file2 = open (name2, O_RDONLY);
- if (file2 >= 0)
- {
- #ifdef HAVE_MMAP
- char *data1, *data2;
- /* Ugly if jungle */
- data1 = mmap (0, size, PROT_READ, MAP_FILE | MAP_PRIVATE, file1, 0);
- if (data1 != (char *) -1)
- {
- data2 = mmap (0, size, PROT_READ, MAP_FILE | MAP_PRIVATE, file2, 0);
- if (data2 != (char *) -1)
- {
- rotate_dash ();
- result = memcmp (data1, data2, size);
- munmap (data2, size);
- }
- munmap (data1, size);
- }
- #else
- /* Don't have mmap() :( Even more ugly :) */
- char buf1[BUFSIZ], buf2[BUFSIZ];
- int n1, n2;
- rotate_dash ();
- do
- {
- while ((n1 = read (file1, buf1, BUFSIZ)) == -1 && errno == EINTR);
- while ((n2 = read (file2, buf2, BUFSIZ)) == -1 && errno == EINTR);
- }
- while (n1 == n2 && n1 == BUFSIZ && !memcmp (buf1, buf2, BUFSIZ));
- result = (n1 != n2) || memcmp (buf1, buf2, n1);
- #endif /* !HAVE_MMAP */
- close (file2);
- }
- close (file1);
- }
- return result;
- }
- enum CompareMode
- {
- compare_quick, compare_size_only, compare_thourough
- };
- static void
- compare_dir (WPanel * panel, WPanel * other, enum CompareMode mode)
- {
- int i, j;
- char *src_name, *dst_name;
- /* No marks by default */
- panel->marked = 0;
- panel->total = 0;
- panel->dirs_marked = 0;
- /* Handle all files in the panel */
- for (i = 0; i < panel->count; i++)
- {
- file_entry *source = &panel->dir.list[i];
- /* Default: unmarked */
- file_mark (panel, i, 0);
- /* Skip directories */
- if (S_ISDIR (source->st.st_mode))
- continue;
- /* Search the corresponding entry from the other panel */
- for (j = 0; j < other->count; j++)
- {
- if (strcmp (source->fname, other->dir.list[j].fname) == 0)
- break;
- }
- if (j >= other->count)
- /* Not found -> mark */
- do_file_mark (panel, i, 1);
- else
- {
- /* Found */
- file_entry *target = &other->dir.list[j];
- if (mode != compare_size_only)
- {
- /* Older version is not marked */
- if (source->st.st_mtime < target->st.st_mtime)
- continue;
- }
- /* Newer version with different size is marked */
- if (source->st.st_size != target->st.st_size)
- {
- do_file_mark (panel, i, 1);
- continue;
- }
- if (mode == compare_size_only)
- continue;
- if (mode == compare_quick)
- {
- /* Thorough compare off, compare only time stamps */
- /* Mark newer version, don't mark version with the same date */
- if (source->st.st_mtime > target->st.st_mtime)
- {
- do_file_mark (panel, i, 1);
- }
- continue;
- }
- /* Thorough compare on, do byte-by-byte comparison */
- src_name = concat_dir_and_file (panel->cwd, source->fname);
- dst_name = concat_dir_and_file (other->cwd, target->fname);
- if (compare_files (src_name, dst_name, source->st.st_size))
- do_file_mark (panel, i, 1);
- g_free (src_name);
- g_free (dst_name);
- }
- } /* for (i ...) */
- }
- 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"));
- }
- }
- #ifdef USE_DIFF_VIEW
- void
- diff_view_cmd (void)
- {
- dview_diff_cmd ();
- if (mc_run_mode == MC_RUN_FULL)
- update_panels (UP_OPTIMIZE, UP_KEEPSEL);
- dialog_switch_process_pending ();
- }
- #endif
- void
- history_cmd (void)
- {
- /* show the history of command line widget */
- send_message (&cmdline->widget, WIDGET_COMMAND, CK_InputHistoryShow);
- }
- void
- swap_cmd (void)
- {
- swap_panels ();
- tty_touch_screen ();
- repaint_screen ();
- }
- void
- view_other_cmd (void)
- {
- static int message_flag = TRUE;
- if (!xterm_flag && !console_flag && !use_subshell && !output_starts_shell)
- {
- if (message_flag)
- message (D_ERROR, MSG_ERROR,
- _("Not an xterm or Linux console;\nthe panels cannot be toggled."));
- message_flag = FALSE;
- }
- else
- {
- toggle_panels ();
- }
- }
- 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
- link_cmd (link_type_t link_type)
- {
- char *filename = selection (current_panel)->fname;
- if (filename != NULL)
- do_link (link_type, filename);
- }
- void
- edit_symlink_cmd (void)
- {
- if (S_ISLNK (selection (current_panel)->st.st_mode))
- {
- char buffer[MC_MAXPATHLEN];
- char *p = NULL;
- int i;
- char *dest, *q;
- p = selection (current_panel)->fname;
- q = g_strdup_printf (_("Symlink `%s\' points to:"), str_trunc (p, 32));
- i = readlink (p, buffer, MC_MAXPATHLEN - 1);
- if (i > 0)
- {
- buffer[i] = 0;
- dest = input_expand_dialog (_("Edit symlink"), q, MC_HISTORY_FM_EDIT_LINK, buffer);
- if (dest)
- {
- if (*dest && strcmp (buffer, dest))
- {
- save_cwds_stat ();
- if (-1 == mc_unlink (p))
- {
- message (D_ERROR, MSG_ERROR, _("edit symlink, unable to remove %s: %s"),
- p, unix_error_string (errno));
- }
- else
- {
- if (-1 == mc_symlink (dest, p))
- message (D_ERROR, MSG_ERROR, _("edit symlink: %s"),
- unix_error_string (errno));
- }
- update_panels (UP_OPTIMIZE, UP_KEEPSEL);
- repaint_screen ();
- }
- g_free (dest);
- }
- }
- g_free (q);
- }
- else
- {
- message (D_ERROR, MSG_ERROR, _("`%s' is not a symbolic link"),
- selection (current_panel)->fname);
- }
- }
- void
- help_cmd (void)
- {
- if (current_panel->searching)
- interactive_display (NULL, "[Quick search]");
- else
- interactive_display (NULL, "[main]");
- }
- void
- user_file_menu_cmd (void)
- {
- user_menu_cmd (NULL);
- }
- /*
- * Return a random hint. If force is not 0, ignore the timeout.
- */
- char *
- get_random_hint (int force)
- {
- char *data, *result = NULL, *eol;
- int len;
- int start;
- static int last_sec;
- static struct timeval tv;
- GIConv conv;
- GString *buffer;
- /* Do not change hints more often than one minute */
- gettimeofday (&tv, NULL);
- if (!force && !(tv.tv_sec > last_sec + 60))
- return g_strdup ("");
- last_sec = tv.tv_sec;
- data = load_mc_home_file (mc_home_alt, MC_HINT, NULL);
- if (data == NULL)
- return NULL;
- /* get a random entry */
- srand (tv.tv_sec);
- len = strlen (data);
- start = rand () % len;
- for (; start != 0; start--)
- if (data[start] == '\n')
- {
- start++;
- break;
- }
- eol = strchr (data + start, '\n');
- if (eol != NULL)
- *eol = '\0';
- /* hint files are stored in utf-8 */
- /* try convert hint file from utf-8 to terminal encoding */
- conv = str_crt_conv_from ("UTF-8");
- if (conv != INVALID_CONV)
- {
- buffer = g_string_new ("");
- if (str_convert (conv, &data[start], buffer) != ESTR_FAILURE)
- result = g_strdup (buffer->str);
- g_string_free (buffer, TRUE);
- str_close_conv (conv);
- }
- g_free (data);
- return result;
- }
- #if defined(ENABLE_VFS_UNDELFS) || defined(ENABLE_VFS_NET)
- static void
- nice_cd (const char *text, const char *xtext, const char *help,
- const char *history_name, const char *prefix, int to_home)
- {
- char *machine;
- char *cd_path;
- if (!SELECTED_IS_PANEL)
- return;
- machine = input_dialog_help (text, xtext, help, history_name, "");
- if (!machine)
- return;
- to_home = 0; /* FIXME: how to solve going to home nicely? /~/ is
- ugly as hell and leads to problems in vfs layer */
- if (strncmp (prefix, machine, strlen (prefix)) == 0)
- cd_path = g_strconcat (machine, to_home ? "/~/" : (char *) NULL, (char *) NULL);
- else
- cd_path = g_strconcat (prefix, machine, to_home ? "/~/" : (char *) NULL, (char *) NULL);
- if (!do_panel_cd (MENU_PANEL, cd_path, cd_parse_command))
- message (D_ERROR, MSG_ERROR, _("Cannot chdir to \"%s\""), cd_path);
- g_free (cd_path);
- g_free (machine);
- }
- #endif /* ENABLE_VFS_UNDELFS || ENABLE_VFS_NET*/
- #ifdef ENABLE_VFS_NET
- static const char *machine_str = N_("Enter machine name (F1 for details):");
- #ifdef ENABLE_VFS_FTP
- void
- ftplink_cmd (void)
- {
- nice_cd (_("FTP to machine"), _(machine_str),
- "[FTP File System]", ":ftplink_cmd: FTP to machine ", "/#ftp:", 1);
- }
- #endif /* ENABLE_VFS_FTP */
- #ifdef ENABLE_VFS_FISH
- void
- fishlink_cmd (void)
- {
- nice_cd (_("Shell link to machine"), _(machine_str),
- "[FIle transfer over SHell filesystem]", ":fishlink_cmd: Shell link to machine ",
- "/#sh:", 1);
- }
- #endif /* ENABLE_VFS_FISH */
- #ifdef ENABLE_VFS_SMB
- void
- smblink_cmd (void)
- {
- nice_cd (_("SMB link to machine"), _(machine_str),
- "[SMB File System]", ":smblink_cmd: SMB link to machine ", "/#smb:", 0);
- }
- #endif /* ENABLE_VFS_SMB */
- #endif /* ENABLE_VFS_NET */
- #ifdef ENABLE_VFS_UNDELFS
- void
- undelete_cmd (void)
- {
- nice_cd (_("Undelete files on an ext2 file system"),
- _("Enter device (without /dev/) to undelete\nfiles on: (F1 for details)"),
- "[Undelete File System]", ":undelete_cmd: Undel on ext2 fs ", "/#undel:", 0);
- }
- #endif /* ENABLE_VFS_UNDELFS */
- void
- quick_cd_cmd (void)
- {
- char *p = cd_dialog ();
- if (p && *p)
- {
- char *q = g_strconcat ("cd ", p, (char *) NULL);
- do_cd_command (q);
- g_free (q);
- }
- g_free (p);
- }
- /*!
- \brief calculate dirs sizes
- calculate dirs sizes and resort panel:
- dirs_selected = show size for selected dirs,
- otherwise = show size for dir under cursor:
- dir under cursor ".." = show size for all dirs,
- otherwise = show size for dir under cursor
- */
- void
- smart_dirsize_cmd (void)
- {
- WPanel *panel = current_panel;
- file_entry *entry;
- entry = &(panel->dir.list[panel->selected]);
- if ((S_ISDIR (entry->st.st_mode) && (strcmp (entry->fname, "..") == 0)) || panel->dirs_marked)
- dirsizes_cmd ();
- else
- single_dirsize_cmd ();
- }
- void
- single_dirsize_cmd (void)
- {
- WPanel *panel = current_panel;
- file_entry *entry;
- off_t marked;
- double total;
- ComputeDirSizeUI *ui;
- entry = &(panel->dir.list[panel->selected]);
- if (S_ISDIR (entry->st.st_mode) && strcmp (entry->fname, "..") != 0)
- {
- ui = compute_dir_size_create_ui ();
- total = 0.0;
- if (compute_dir_size (entry->fname, ui, compute_dir_size_update_ui,
- &marked, &total, TRUE) == FILE_CONT)
- {
- entry->st.st_size = (off_t) total;
- entry->f.dir_size_computed = 1;
- }
- compute_dir_size_destroy_ui (ui);
- }
- if (panels_options.mark_moves_down)
- send_message (&panel->widget, WIDGET_KEY, KEY_DOWN);
- recalculate_panel_summary (panel);
- if (current_panel->current_sort_field->sort_routine == (sortfn *) sort_size)
- panel_re_sort (panel);
- panel->dirty = 1;
- }
- void
- dirsizes_cmd (void)
- {
- WPanel *panel = current_panel;
- int i;
- off_t marked;
- double total;
- ComputeDirSizeUI *ui;
- ui = compute_dir_size_create_ui ();
- for (i = 0; i < panel->count; i++)
- if (S_ISDIR (panel->dir.list[i].st.st_mode)
- && ((panel->dirs_marked && panel->dir.list[i].f.marked)
- || !panel->dirs_marked) && strcmp (panel->dir.list[i].fname, "..") != 0)
- {
- total = 0.0l;
- if (compute_dir_size (panel->dir.list[i].fname,
- ui, compute_dir_size_update_ui, &marked, &total, TRUE) != FILE_CONT)
- break;
- panel->dir.list[i].st.st_size = (off_t) total;
- panel->dir.list[i].f.dir_size_computed = 1;
- }
- compute_dir_size_destroy_ui (ui);
- recalculate_panel_summary (panel);
- if (current_panel->current_sort_field->sort_routine == (sortfn *) sort_size)
- panel_re_sort (panel);
- panel->dirty = 1;
- }
- void
- save_setup_cmd (void)
- {
- if (!save_setup ())
- return;
- message (D_NORMAL, _("Setup"), _("Setup saved to ~/%s"),
- MC_USERCONF_DIR PATH_SEP_STR MC_CONFIG_FILE);
- }
- static void
- configure_panel_listing (WPanel * p, int list_type, int use_msformat, char *user, char *status)
- {
- p->user_mini_status = use_msformat;
- p->list_type = list_type;
- if (list_type == list_user || use_msformat)
- {
- g_free (p->user_format);
- p->user_format = user;
- g_free (p->user_status_format[list_type]);
- p->user_status_format[list_type] = status;
- set_panel_formats (p);
- }
- else
- {
- g_free (user);
- g_free (status);
- }
- set_panel_formats (p);
- do_refresh ();
- }
- void
- info_cmd_no_menu (void)
- {
- if (get_display_type (0) == view_info)
- set_display_type (0, view_listing);
- else if (get_display_type (1) == view_info)
- set_display_type (1, view_listing);
- else
- set_display_type (current_panel == left_panel ? 1 : 0, view_info);
- }
- void
- quick_cmd_no_menu (void)
- {
- if (get_display_type (0) == view_quick)
- set_display_type (0, view_listing);
- else if (get_display_type (1) == view_quick)
- set_display_type (1, view_listing);
- else
- set_display_type (current_panel == left_panel ? 1 : 0, view_quick);
- }
- static void
- switch_to_listing (int panel_index)
- {
- if (get_display_type (panel_index) != view_listing)
- set_display_type (panel_index, view_listing);
- }
- void
- listing_cmd (void)
- {
- switch_to_listing (MENU_PANEL_IDX);
- }
- void
- change_listing_cmd (void)
- {
- int list_type;
- int use_msformat;
- char *user, *status;
- WPanel *p = NULL;
- if (get_display_type (MENU_PANEL_IDX) == view_listing)
- p = MENU_PANEL_IDX == 0 ? left_panel : right_panel;
- list_type = display_box (p, &user, &status, &use_msformat, MENU_PANEL_IDX);
- if (list_type != -1)
- {
- switch_to_listing (MENU_PANEL_IDX);
- p = MENU_PANEL_IDX == 0 ? left_panel : right_panel;
- configure_panel_listing (p, list_type, use_msformat, user, status);
- }
- }
- void
- tree_cmd (void)
- {
- set_display_type (MENU_PANEL_IDX, view_tree);
- }
- void
- info_cmd (void)
- {
- set_display_type (MENU_PANEL_IDX, view_info);
- }
- void
- quick_view_cmd (void)
- {
- if ((WPanel *) get_panel_widget (MENU_PANEL_IDX) == current_panel)
- change_panel ();
- set_display_type (MENU_PANEL_IDX, view_quick);
- }
- /* Handle the tree internal listing modes switching */
- static gboolean
- set_basic_panel_listing_to (int panel_index, int listing_mode)
- {
- WPanel *p = (WPanel *) get_panel_widget (panel_index);
- gboolean ok;
- switch_to_listing (panel_index);
- p->list_type = listing_mode;
- ok = set_panel_formats (p) == 0;
- if (ok)
- do_refresh ();
- return ok;
- }
- void
- toggle_listing_cmd (void)
- {
- int current = get_current_index ();
- WPanel *p = (WPanel *) get_panel_widget (current);
- set_basic_panel_listing_to (current, (p->list_type + 1) % LIST_TYPES);
- }
- void
- encoding_cmd (void)
- {
- if (SELECTED_IS_PANEL)
- panel_change_encoding (MENU_PANEL);
- }
|