cmd.c 48 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738
  1. /*
  2. Routines invoked by a function key
  3. They normally operate on the current panel.
  4. Copyright (C) 1994, 1995, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
  5. 2005, 2006, 2007, 2009, 2011
  6. The Free Software Foundation, Inc.
  7. This file is part of the Midnight Commander.
  8. The Midnight Commander is free software: you can redistribute it
  9. and/or modify it under the terms of the GNU General Public License as
  10. published by the Free Software Foundation, either version 3 of the License,
  11. or (at your option) any later version.
  12. The Midnight Commander is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. GNU General Public License for more details.
  16. You should have received a copy of the GNU General Public License
  17. along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. /** \file cmd.c
  20. * \brief Source: routines invoked by a function key
  21. *
  22. * They normally operate on the current panel.
  23. */
  24. #include <config.h>
  25. #include <errno.h>
  26. #include <stdio.h>
  27. #include <string.h>
  28. #include <sys/types.h>
  29. #include <sys/stat.h>
  30. #ifdef HAVE_MMAP
  31. #include <sys/mman.h>
  32. #endif
  33. #ifdef ENABLE_VFS_NET
  34. #include <netdb.h>
  35. #endif
  36. #include <unistd.h>
  37. #include <stdlib.h>
  38. #include <fcntl.h>
  39. #include <pwd.h>
  40. #include <grp.h>
  41. #include <sys/time.h>
  42. #include "lib/global.h"
  43. #include "lib/tty/tty.h" /* LINES, tty_touch_screen() */
  44. #include "lib/tty/key.h" /* ALT() macro */
  45. #include "lib/tty/win.h" /* do_enter_ca_mode() */
  46. #include "lib/mcconfig.h"
  47. #include "lib/search.h"
  48. #include "lib/filehighlight.h" /* MC_FHL_INI_FILE */
  49. #include "lib/vfs/vfs.h"
  50. #include "lib/fileloc.h"
  51. #include "lib/strutil.h"
  52. #include "lib/util.h"
  53. #include "lib/widget.h"
  54. #include "lib/keybind.h" /* CK_Down, CK_History */
  55. #include "lib/event.h" /* mc_event_raise() */
  56. #include "src/viewer/mcviewer.h"
  57. #include "src/setup.h"
  58. #include "src/execute.h" /* toggle_panels() */
  59. #include "src/history.h"
  60. #include "src/util.h" /* check_for_default() */
  61. #ifdef USE_INTERNAL_EDIT
  62. #include "src/editor/edit.h"
  63. #endif
  64. #ifdef USE_DIFF_VIEW
  65. #include "src/diffviewer/ydiff.h"
  66. #endif
  67. #include "fileopctx.h"
  68. #include "file.h" /* file operation routines */
  69. #include "find.h" /* find_file() */
  70. #include "filenot.h"
  71. #include "hotlist.h" /* hotlist_show() */
  72. #include "panel.h" /* WPanel */
  73. #include "tree.h" /* tree_chdir() */
  74. #include "midnight.h" /* change_panel() */
  75. #include "usermenu.h" /* MC_GLOBAL_MENU */
  76. #include "command.h" /* cmdline */
  77. #include "layout.h" /* get_current_type() */
  78. #include "ext.h" /* regex_command() */
  79. #include "boxes.h" /* cd_dialog() */
  80. #include "dir.h"
  81. #include "cmd.h" /* Our definitions */
  82. /*** global variables ****************************************************************************/
  83. int select_flags = SELECT_MATCH_CASE | SELECT_SHELL_PATTERNS;
  84. /*** file scope macro definitions ****************************************************************/
  85. #ifndef MAP_FILE
  86. #define MAP_FILE 0
  87. #endif
  88. /*** file scope type declarations ****************************************************************/
  89. enum CompareMode
  90. {
  91. compare_quick, compare_size_only, compare_thourough
  92. };
  93. /*** file scope variables ************************************************************************/
  94. #ifdef ENABLE_VFS_NET
  95. static const char *machine_str = N_("Enter machine name (F1 for details):");
  96. #endif /* ENABLE_VFS_NET */
  97. /*** file scope functions ************************************************************************/
  98. /* --------------------------------------------------------------------------------------------- */
  99. /**
  100. * Run viewer (internal or external) on the currently selected file.
  101. * If normal is TRUE, force internal viewer and raw mode (used for F13).
  102. */
  103. static void
  104. do_view_cmd (gboolean normal)
  105. {
  106. /* Directories are viewed by changing to them */
  107. if (S_ISDIR (selection (current_panel)->st.st_mode) || link_isdir (selection (current_panel)))
  108. {
  109. vfs_path_t *fname_vpath;
  110. if (confirm_view_dir && (current_panel->marked || current_panel->dirs_marked))
  111. {
  112. if (query_dialog
  113. (_("Confirmation"), _("Files tagged, want to cd?"), D_NORMAL, 2,
  114. _("&Yes"), _("&No")) != 0)
  115. {
  116. return;
  117. }
  118. }
  119. fname_vpath = vfs_path_from_str (selection (current_panel)->fname);
  120. if (!do_cd (fname_vpath, cd_exact))
  121. message (D_ERROR, MSG_ERROR, _("Cannot change directory"));
  122. vfs_path_free (fname_vpath);
  123. }
  124. else
  125. {
  126. int file_idx;
  127. vfs_path_t *filename_vpath;
  128. file_idx = current_panel->selected;
  129. filename_vpath = vfs_path_from_str (current_panel->dir.list[file_idx].fname);
  130. view_file (filename_vpath, normal, use_internal_view);
  131. vfs_path_free (filename_vpath);
  132. }
  133. repaint_screen ();
  134. }
  135. /* --------------------------------------------------------------------------------------------- */
  136. static inline void
  137. do_edit (const vfs_path_t * what_vpath)
  138. {
  139. do_edit_at_line (what_vpath, use_internal_edit, 0);
  140. }
  141. /* --------------------------------------------------------------------------------------------- */
  142. static void
  143. set_panel_filter_to (WPanel * p, char *allocated_filter_string)
  144. {
  145. g_free (p->filter);
  146. p->filter = 0;
  147. if (!(allocated_filter_string[0] == '*' && allocated_filter_string[1] == 0))
  148. p->filter = allocated_filter_string;
  149. else
  150. g_free (allocated_filter_string);
  151. reread_cmd ();
  152. }
  153. /* --------------------------------------------------------------------------------------------- */
  154. /** Set a given panel filter expression */
  155. static void
  156. set_panel_filter (WPanel * p)
  157. {
  158. char *reg_exp;
  159. const char *x;
  160. x = p->filter ? p->filter : easy_patterns ? "*" : ".";
  161. reg_exp = input_dialog_help (_("Filter"),
  162. _("Set expression for filtering filenames"),
  163. "[Filter...]", MC_HISTORY_FM_PANEL_FILTER, x, FALSE);
  164. if (!reg_exp)
  165. return;
  166. set_panel_filter_to (p, reg_exp);
  167. }
  168. /* --------------------------------------------------------------------------------------------- */
  169. static void
  170. select_unselect_cmd (const char *title, const char *history_name, gboolean do_select)
  171. {
  172. /* dialog sizes */
  173. const int DX = 50;
  174. const int DY = 7;
  175. int files_only = (select_flags & SELECT_FILES_ONLY) != 0;
  176. int case_sens = (select_flags & SELECT_MATCH_CASE) != 0;
  177. int shell_patterns = (select_flags & SELECT_SHELL_PATTERNS) != 0;
  178. char *reg_exp;
  179. mc_search_t *search;
  180. int i;
  181. QuickWidget quick_widgets[] = {
  182. QUICK_CHECKBOX (3, DX, DY - 3, DY, N_("&Using shell patterns"), &shell_patterns),
  183. QUICK_CHECKBOX (DX / 2 + 1, DX, DY - 4, DY, N_("&Case sensitive"), &case_sens),
  184. QUICK_CHECKBOX (3, DX, DY - 4, DY, N_("&Files only"), &files_only),
  185. QUICK_INPUT (3, DX, DY - 5, DY, INPUT_LAST_TEXT, DX - 6, 0, history_name, &reg_exp),
  186. QUICK_END
  187. };
  188. QuickDialog quick_dlg = {
  189. DX, DY, -1, -1, title,
  190. "[Select/Unselect Files]", quick_widgets, NULL, NULL, FALSE
  191. };
  192. if (quick_dialog (&quick_dlg) == B_CANCEL)
  193. return;
  194. if (!reg_exp)
  195. return;
  196. if (!*reg_exp)
  197. {
  198. g_free (reg_exp);
  199. return;
  200. }
  201. search = mc_search_new (reg_exp, -1);
  202. search->search_type = (shell_patterns != 0) ? MC_SEARCH_T_GLOB : MC_SEARCH_T_REGEX;
  203. search->is_entire_line = TRUE;
  204. search->is_case_sensitive = case_sens != 0;
  205. for (i = 0; i < current_panel->count; i++)
  206. {
  207. if (strcmp (current_panel->dir.list[i].fname, "..") == 0)
  208. continue;
  209. if (S_ISDIR (current_panel->dir.list[i].st.st_mode) && files_only != 0)
  210. continue;
  211. if (mc_search_run (search, current_panel->dir.list[i].fname,
  212. 0, current_panel->dir.list[i].fnamelen, NULL))
  213. do_file_mark (current_panel, i, do_select);
  214. }
  215. mc_search_free (search);
  216. g_free (reg_exp);
  217. /* result flags */
  218. select_flags = 0;
  219. if (case_sens != 0)
  220. select_flags |= SELECT_MATCH_CASE;
  221. if (files_only != 0)
  222. select_flags |= SELECT_FILES_ONLY;
  223. if (shell_patterns != 0)
  224. select_flags |= SELECT_SHELL_PATTERNS;
  225. }
  226. /* --------------------------------------------------------------------------------------------- */
  227. static int
  228. compare_files (const vfs_path_t * vpath1, const vfs_path_t * vpath2, off_t size)
  229. {
  230. int file1, file2;
  231. char *name;
  232. int result = -1; /* Different by default */
  233. if (size == 0)
  234. return 0;
  235. name = vfs_path_to_str (vpath1);
  236. file1 = open (name, O_RDONLY);
  237. g_free (name);
  238. if (file1 >= 0)
  239. {
  240. name = vfs_path_to_str (vpath2);
  241. file2 = open (name, O_RDONLY);
  242. g_free (name);
  243. if (file2 >= 0)
  244. {
  245. #ifdef HAVE_MMAP
  246. char *data1, *data2;
  247. /* Ugly if jungle */
  248. data1 = mmap (0, size, PROT_READ, MAP_FILE | MAP_PRIVATE, file1, 0);
  249. if (data1 != (char *) -1)
  250. {
  251. data2 = mmap (0, size, PROT_READ, MAP_FILE | MAP_PRIVATE, file2, 0);
  252. if (data2 != (char *) -1)
  253. {
  254. rotate_dash ();
  255. result = memcmp (data1, data2, size);
  256. munmap (data2, size);
  257. }
  258. munmap (data1, size);
  259. }
  260. #else
  261. /* Don't have mmap() :( Even more ugly :) */
  262. char buf1[BUFSIZ], buf2[BUFSIZ];
  263. int n1, n2;
  264. rotate_dash ();
  265. do
  266. {
  267. while ((n1 = read (file1, buf1, BUFSIZ)) == -1 && errno == EINTR);
  268. while ((n2 = read (file2, buf2, BUFSIZ)) == -1 && errno == EINTR);
  269. }
  270. while (n1 == n2 && n1 == BUFSIZ && !memcmp (buf1, buf2, BUFSIZ));
  271. result = (n1 != n2) || memcmp (buf1, buf2, n1);
  272. #endif /* !HAVE_MMAP */
  273. close (file2);
  274. }
  275. close (file1);
  276. }
  277. return result;
  278. }
  279. /* --------------------------------------------------------------------------------------------- */
  280. static void
  281. compare_dir (WPanel * panel, WPanel * other, enum CompareMode mode)
  282. {
  283. int i, j;
  284. /* No marks by default */
  285. panel->marked = 0;
  286. panel->total = 0;
  287. panel->dirs_marked = 0;
  288. /* Handle all files in the panel */
  289. for (i = 0; i < panel->count; i++)
  290. {
  291. file_entry *source = &panel->dir.list[i];
  292. /* Default: unmarked */
  293. file_mark (panel, i, 0);
  294. /* Skip directories */
  295. if (S_ISDIR (source->st.st_mode))
  296. continue;
  297. /* Search the corresponding entry from the other panel */
  298. for (j = 0; j < other->count; j++)
  299. {
  300. if (strcmp (source->fname, other->dir.list[j].fname) == 0)
  301. break;
  302. }
  303. if (j >= other->count)
  304. /* Not found -> mark */
  305. do_file_mark (panel, i, 1);
  306. else
  307. {
  308. /* Found */
  309. file_entry *target = &other->dir.list[j];
  310. if (mode != compare_size_only)
  311. {
  312. /* Older version is not marked */
  313. if (source->st.st_mtime < target->st.st_mtime)
  314. continue;
  315. }
  316. /* Newer version with different size is marked */
  317. if (source->st.st_size != target->st.st_size)
  318. {
  319. do_file_mark (panel, i, 1);
  320. continue;
  321. }
  322. if (mode == compare_size_only)
  323. continue;
  324. if (mode == compare_quick)
  325. {
  326. /* Thorough compare off, compare only time stamps */
  327. /* Mark newer version, don't mark version with the same date */
  328. if (source->st.st_mtime > target->st.st_mtime)
  329. {
  330. do_file_mark (panel, i, 1);
  331. }
  332. continue;
  333. }
  334. /* Thorough compare on, do byte-by-byte comparison */
  335. {
  336. vfs_path_t *src_name, *dst_name;
  337. src_name = vfs_path_append_new (panel->cwd_vpath, source->fname, NULL);
  338. dst_name = vfs_path_append_new (other->cwd_vpath, target->fname, NULL);
  339. if (compare_files (src_name, dst_name, source->st.st_size))
  340. do_file_mark (panel, i, 1);
  341. vfs_path_free (src_name);
  342. vfs_path_free (dst_name);
  343. }
  344. }
  345. } /* for (i ...) */
  346. }
  347. /* --------------------------------------------------------------------------------------------- */
  348. static void
  349. do_link (link_type_t link_type, const char *fname)
  350. {
  351. char *dest = NULL, *src = NULL;
  352. vfs_path_t *fname_vpath, *dest_vpath = NULL;
  353. fname_vpath = vfs_path_from_str (fname);
  354. if (link_type == LINK_HARDLINK)
  355. {
  356. src = g_strdup_printf (_("Link %s to:"), str_trunc (fname, 46));
  357. dest = input_expand_dialog (_("Link"), src, MC_HISTORY_FM_LINK, "");
  358. if (!dest || !*dest)
  359. goto cleanup;
  360. save_cwds_stat ();
  361. dest_vpath = vfs_path_from_str (dest);
  362. if (-1 == mc_link (fname_vpath, dest_vpath))
  363. message (D_ERROR, MSG_ERROR, _("link: %s"), unix_error_string (errno));
  364. }
  365. else
  366. {
  367. vfs_path_t *s, *d;
  368. /* suggest the full path for symlink, and either the full or
  369. relative path to the file it points to */
  370. s = vfs_path_append_new (current_panel->cwd_vpath, fname, NULL);
  371. if (get_other_type () == view_listing)
  372. d = vfs_path_append_new (other_panel->cwd_vpath, fname, NULL);
  373. else
  374. d = vfs_path_from_str (fname);
  375. if (link_type == LINK_SYMLINK_RELATIVE)
  376. {
  377. char *s_str;
  378. s_str = diff_two_paths (other_panel->cwd_vpath, s);
  379. vfs_path_free (s);
  380. s = vfs_path_from_str_flags (s_str, VPF_NO_CANON);
  381. g_free (s_str);
  382. }
  383. symlink_dialog (s, d, &dest, &src);
  384. vfs_path_free (d);
  385. vfs_path_free (s);
  386. if (!dest || !*dest || !src || !*src)
  387. goto cleanup;
  388. save_cwds_stat ();
  389. dest_vpath = vfs_path_from_str_flags (dest, VPF_NO_CANON);
  390. s = vfs_path_from_str (src);
  391. if (mc_symlink (dest_vpath, s) == -1)
  392. message (D_ERROR, MSG_ERROR, _("symlink: %s"), unix_error_string (errno));
  393. vfs_path_free (s);
  394. }
  395. update_panels (UP_OPTIMIZE, UP_KEEPSEL);
  396. repaint_screen ();
  397. cleanup:
  398. vfs_path_free (fname_vpath);
  399. vfs_path_free (dest_vpath);
  400. g_free (src);
  401. g_free (dest);
  402. }
  403. /* --------------------------------------------------------------------------------------------- */
  404. #if defined(ENABLE_VFS_UNDELFS) || defined(ENABLE_VFS_NET)
  405. static void
  406. nice_cd (const char *text, const char *xtext, const char *help,
  407. const char *history_name, const char *prefix, int to_home, gboolean strip_password)
  408. {
  409. char *machine;
  410. char *cd_path;
  411. if (!SELECTED_IS_PANEL)
  412. return;
  413. machine = input_dialog_help (text, xtext, help, history_name, "", strip_password);
  414. if (machine == NULL)
  415. return;
  416. to_home = 0; /* FIXME: how to solve going to home nicely? /~/ is
  417. ugly as hell and leads to problems in vfs layer */
  418. if (strncmp (prefix, machine, strlen (prefix)) == 0)
  419. cd_path = g_strconcat (machine, to_home ? "/~/" : (char *) NULL, (char *) NULL);
  420. else
  421. cd_path = g_strconcat (prefix, machine, to_home ? "/~/" : (char *) NULL, (char *) NULL);
  422. g_free (machine);
  423. if (*cd_path != PATH_SEP)
  424. {
  425. char *tmp = cd_path;
  426. cd_path = g_strconcat (PATH_SEP_STR, tmp, (char *) NULL);
  427. g_free (tmp);
  428. }
  429. {
  430. vfs_path_t *cd_vpath;
  431. cd_vpath = vfs_path_from_str_flags (cd_path, VPF_NO_CANON);
  432. if (!do_panel_cd (MENU_PANEL, cd_vpath, cd_parse_command))
  433. message (D_ERROR, MSG_ERROR, _("Cannot chdir to \"%s\""), cd_path);
  434. vfs_path_free (cd_vpath);
  435. }
  436. g_free (cd_path);
  437. }
  438. #endif /* ENABLE_VFS_UNDELFS || ENABLE_VFS_NET */
  439. /* --------------------------------------------------------------------------------------------- */
  440. static void
  441. configure_panel_listing (WPanel * p, int list_type, int use_msformat, char *user, char *status)
  442. {
  443. p->user_mini_status = use_msformat;
  444. p->list_type = list_type;
  445. if (list_type == list_user || use_msformat)
  446. {
  447. g_free (p->user_format);
  448. p->user_format = user;
  449. g_free (p->user_status_format[list_type]);
  450. p->user_status_format[list_type] = status;
  451. set_panel_formats (p);
  452. }
  453. else
  454. {
  455. g_free (user);
  456. g_free (status);
  457. }
  458. set_panel_formats (p);
  459. do_refresh ();
  460. }
  461. /* --------------------------------------------------------------------------------------------- */
  462. static void
  463. switch_to_listing (int panel_index)
  464. {
  465. if (get_display_type (panel_index) != view_listing)
  466. set_display_type (panel_index, view_listing);
  467. else
  468. {
  469. WPanel *p;
  470. p = (WPanel *) get_panel_widget (panel_index);
  471. if (p->is_panelized)
  472. {
  473. p->is_panelized = FALSE;
  474. panel_reload (p);
  475. }
  476. }
  477. }
  478. /* --------------------------------------------------------------------------------------------- */
  479. /** Handle the tree internal listing modes switching */
  480. static gboolean
  481. set_basic_panel_listing_to (int panel_index, int listing_mode)
  482. {
  483. WPanel *p = (WPanel *) get_panel_widget (panel_index);
  484. gboolean ok;
  485. switch_to_listing (panel_index);
  486. p->list_type = listing_mode;
  487. ok = set_panel_formats (p) == 0;
  488. if (ok)
  489. do_refresh ();
  490. return ok;
  491. }
  492. /* --------------------------------------------------------------------------------------------- */
  493. /*** public functions ****************************************************************************/
  494. /* --------------------------------------------------------------------------------------------- */
  495. gboolean
  496. view_file_at_line (const vfs_path_t * filename_vpath, int plain_view, int internal, int start_line)
  497. {
  498. static const char *viewer = NULL;
  499. gboolean ret = TRUE;
  500. if (plain_view)
  501. {
  502. int changed_hex_mode = 0;
  503. int changed_nroff_flag = 0;
  504. int changed_magic_flag = 0;
  505. mcview_altered_hex_mode = 0;
  506. mcview_altered_nroff_flag = 0;
  507. mcview_altered_magic_flag = 0;
  508. if (mcview_default_hex_mode)
  509. changed_hex_mode = 1;
  510. if (mcview_default_nroff_flag)
  511. changed_nroff_flag = 1;
  512. if (mcview_default_magic_flag)
  513. changed_magic_flag = 1;
  514. mcview_default_hex_mode = 0;
  515. mcview_default_nroff_flag = 0;
  516. mcview_default_magic_flag = 0;
  517. ret = mcview_viewer (NULL, filename_vpath, start_line);
  518. if (changed_hex_mode && !mcview_altered_hex_mode)
  519. mcview_default_hex_mode = 1;
  520. if (changed_nroff_flag && !mcview_altered_nroff_flag)
  521. mcview_default_nroff_flag = 1;
  522. if (changed_magic_flag && !mcview_altered_magic_flag)
  523. mcview_default_magic_flag = 1;
  524. dialog_switch_process_pending ();
  525. }
  526. else if (internal)
  527. {
  528. char view_entry[BUF_TINY];
  529. if (start_line != 0)
  530. g_snprintf (view_entry, sizeof (view_entry), "View:%d", start_line);
  531. else
  532. strcpy (view_entry, "View");
  533. ret = (regex_command (filename_vpath, view_entry) == 0);
  534. if (ret)
  535. {
  536. ret = mcview_viewer (NULL, filename_vpath, start_line);
  537. dialog_switch_process_pending ();
  538. }
  539. }
  540. else
  541. {
  542. if (viewer == NULL)
  543. {
  544. viewer = getenv ("VIEWER");
  545. if (viewer == NULL)
  546. viewer = getenv ("PAGER");
  547. if (viewer == NULL)
  548. viewer = "view";
  549. }
  550. execute_with_vfs_arg (viewer, filename_vpath);
  551. }
  552. return ret;
  553. }
  554. /* --------------------------------------------------------------------------------------------- */
  555. /** view_file (filename, plain_view, internal)
  556. *
  557. * Inputs:
  558. * filename_vpath: The file name to view
  559. * plain_view: If set does not do any fancy pre-processing (no filtering) and
  560. * always invokes the internal viewer.
  561. * internal: If set uses the internal viewer, otherwise an external viewer.
  562. */
  563. gboolean
  564. view_file (const vfs_path_t * filename_vpath, int plain_view, int internal)
  565. {
  566. return view_file_at_line (filename_vpath, plain_view, internal, 0);
  567. }
  568. /* --------------------------------------------------------------------------------------------- */
  569. /** Run user's preferred viewer on the currently selected file */
  570. void
  571. view_cmd (void)
  572. {
  573. do_view_cmd (FALSE);
  574. }
  575. /* --------------------------------------------------------------------------------------------- */
  576. /** Ask for file and run user's preferred viewer on it */
  577. void
  578. view_file_cmd (void)
  579. {
  580. char *filename;
  581. vfs_path_t *vpath;
  582. filename =
  583. input_expand_dialog (_("View file"), _("Filename:"),
  584. MC_HISTORY_FM_VIEW_FILE, selection (current_panel)->fname);
  585. if (!filename)
  586. return;
  587. vpath = vfs_path_from_str (filename);
  588. g_free (filename);
  589. view_file (vpath, 0, use_internal_view);
  590. vfs_path_free (vpath);
  591. }
  592. /* --------------------------------------------------------------------------------------------- */
  593. /** Run plain internal viewer on the currently selected file */
  594. void
  595. view_raw_cmd (void)
  596. {
  597. do_view_cmd (TRUE);
  598. }
  599. /* --------------------------------------------------------------------------------------------- */
  600. void
  601. view_filtered_cmd (void)
  602. {
  603. char *command;
  604. const char *initial_command;
  605. if (cmdline->buffer[0] == '\0')
  606. initial_command = selection (current_panel)->fname;
  607. else
  608. initial_command = cmdline->buffer;
  609. command =
  610. input_dialog (_("Filtered view"),
  611. _("Filter command and arguments:"),
  612. MC_HISTORY_FM_FILTERED_VIEW, initial_command);
  613. if (command != NULL)
  614. {
  615. mcview_viewer (command, NULL, 0);
  616. g_free (command);
  617. dialog_switch_process_pending ();
  618. }
  619. }
  620. /* --------------------------------------------------------------------------------------------- */
  621. void
  622. do_edit_at_line (const vfs_path_t * what_vpath, gboolean internal, int start_line)
  623. {
  624. static const char *editor = NULL;
  625. #ifdef USE_INTERNAL_EDIT
  626. if (internal)
  627. edit_file (what_vpath, start_line);
  628. else
  629. #else
  630. (void) start_line;
  631. #endif /* USE_INTERNAL_EDIT */
  632. {
  633. if (editor == NULL)
  634. {
  635. editor = getenv ("EDITOR");
  636. if (editor == NULL)
  637. editor = get_default_editor ();
  638. }
  639. execute_with_vfs_arg (editor, what_vpath);
  640. }
  641. if (mc_global.mc_run_mode == MC_RUN_FULL)
  642. update_panels (UP_OPTIMIZE, UP_KEEPSEL);
  643. #ifdef USE_INTERNAL_EDIT
  644. if (use_internal_edit)
  645. dialog_switch_process_pending ();
  646. else
  647. #endif /* USE_INTERNAL_EDIT */
  648. repaint_screen ();
  649. }
  650. /* --------------------------------------------------------------------------------------------- */
  651. void
  652. edit_cmd (void)
  653. {
  654. vfs_path_t *fname;
  655. fname = vfs_path_from_str (selection (current_panel)->fname);
  656. if (regex_command (fname, "Edit") == 0)
  657. do_edit (fname);
  658. vfs_path_free (fname);
  659. }
  660. /* --------------------------------------------------------------------------------------------- */
  661. #ifdef USE_INTERNAL_EDIT
  662. void
  663. edit_cmd_force_internal (void)
  664. {
  665. vfs_path_t *fname;
  666. fname = vfs_path_from_str (selection (current_panel)->fname);
  667. if (regex_command (fname, "Edit") == 0)
  668. do_edit_at_line (fname, TRUE, 0);
  669. vfs_path_free (fname);
  670. }
  671. #endif
  672. /* --------------------------------------------------------------------------------------------- */
  673. void
  674. edit_cmd_new (void)
  675. {
  676. #ifdef HAVE_CHARSET
  677. mc_global.source_codepage = default_source_codepage;
  678. #endif
  679. do_edit (NULL);
  680. }
  681. /* --------------------------------------------------------------------------------------------- */
  682. /** Invoked by F5. Copy, default to the other panel. */
  683. void
  684. copy_cmd (void)
  685. {
  686. save_cwds_stat ();
  687. if (panel_operate (current_panel, OP_COPY, FALSE))
  688. {
  689. update_panels (UP_OPTIMIZE, UP_KEEPSEL);
  690. repaint_screen ();
  691. }
  692. }
  693. /* --------------------------------------------------------------------------------------------- */
  694. /** Invoked by F6. Move/rename, default to the other panel, ignore marks. */
  695. void
  696. rename_cmd (void)
  697. {
  698. save_cwds_stat ();
  699. if (panel_operate (current_panel, OP_MOVE, FALSE))
  700. {
  701. update_panels (UP_OPTIMIZE, UP_KEEPSEL);
  702. repaint_screen ();
  703. }
  704. }
  705. /* --------------------------------------------------------------------------------------------- */
  706. /** Invoked by F15. Copy, default to the same panel, ignore marks. */
  707. void
  708. copy_cmd_local (void)
  709. {
  710. save_cwds_stat ();
  711. if (panel_operate (current_panel, OP_COPY, TRUE))
  712. {
  713. update_panels (UP_OPTIMIZE, UP_KEEPSEL);
  714. repaint_screen ();
  715. }
  716. }
  717. /* --------------------------------------------------------------------------------------------- */
  718. /** Invoked by F16. Move/rename, default to the same panel. */
  719. void
  720. rename_cmd_local (void)
  721. {
  722. save_cwds_stat ();
  723. if (panel_operate (current_panel, OP_MOVE, TRUE))
  724. {
  725. update_panels (UP_OPTIMIZE, UP_KEEPSEL);
  726. repaint_screen ();
  727. }
  728. }
  729. /* --------------------------------------------------------------------------------------------- */
  730. void
  731. mkdir_cmd (void)
  732. {
  733. char *dir;
  734. const char *name = "";
  735. /* If 'on' then automatically fills name with current selected item name */
  736. if (auto_fill_mkdir_name && strcmp (selection (current_panel)->fname, "..") != 0)
  737. name = selection (current_panel)->fname;
  738. dir =
  739. input_expand_dialog (_("Create a new Directory"),
  740. _("Enter directory name:"), MC_HISTORY_FM_MKDIR, name);
  741. if (!dir)
  742. return;
  743. if (*dir)
  744. {
  745. vfs_path_t *absdir;
  746. if (dir[0] == '/' || dir[0] == '~')
  747. absdir = vfs_path_from_str (dir);
  748. else
  749. absdir = vfs_path_append_new (current_panel->cwd_vpath, dir, NULL);
  750. save_cwds_stat ();
  751. if (my_mkdir (absdir, 0777) == 0)
  752. {
  753. update_panels (UP_OPTIMIZE, dir);
  754. repaint_screen ();
  755. select_item (current_panel);
  756. }
  757. else
  758. {
  759. message (D_ERROR, MSG_ERROR, "%s", unix_error_string (errno));
  760. }
  761. vfs_path_free (absdir);
  762. }
  763. g_free (dir);
  764. }
  765. /* --------------------------------------------------------------------------------------------- */
  766. void
  767. delete_cmd (void)
  768. {
  769. save_cwds_stat ();
  770. if (panel_operate (current_panel, OP_DELETE, FALSE))
  771. {
  772. update_panels (UP_OPTIMIZE, UP_KEEPSEL);
  773. repaint_screen ();
  774. }
  775. }
  776. /* --------------------------------------------------------------------------------------------- */
  777. /** Invoked by F18. Remove selected file, regardless of marked files. */
  778. void
  779. delete_cmd_local (void)
  780. {
  781. save_cwds_stat ();
  782. if (panel_operate (current_panel, OP_DELETE, TRUE))
  783. {
  784. update_panels (UP_OPTIMIZE, UP_KEEPSEL);
  785. repaint_screen ();
  786. }
  787. }
  788. /* --------------------------------------------------------------------------------------------- */
  789. void
  790. find_cmd (void)
  791. {
  792. find_file ();
  793. }
  794. /* --------------------------------------------------------------------------------------------- */
  795. /** Invoked from the left/right menus */
  796. void
  797. filter_cmd (void)
  798. {
  799. WPanel *p;
  800. if (!SELECTED_IS_PANEL)
  801. return;
  802. p = MENU_PANEL;
  803. set_panel_filter (p);
  804. }
  805. /* --------------------------------------------------------------------------------------------- */
  806. void
  807. reread_cmd (void)
  808. {
  809. panel_update_flags_t flag = UP_ONLY_CURRENT;
  810. if (get_current_type () == view_listing && get_other_type () == view_listing &&
  811. vfs_path_cmp (current_panel->cwd_vpath, other_panel->cwd_vpath) == 0)
  812. flag = UP_OPTIMIZE;
  813. update_panels (UP_RELOAD | flag, UP_KEEPSEL);
  814. repaint_screen ();
  815. }
  816. /* --------------------------------------------------------------------------------------------- */
  817. void
  818. select_invert_cmd (void)
  819. {
  820. int i;
  821. file_entry *file;
  822. for (i = 0; i < current_panel->count; i++)
  823. {
  824. file = &current_panel->dir.list[i];
  825. if (!panels_options.reverse_files_only || !S_ISDIR (file->st.st_mode))
  826. do_file_mark (current_panel, i, !file->f.marked);
  827. }
  828. }
  829. /* --------------------------------------------------------------------------------------------- */
  830. void
  831. select_cmd (void)
  832. {
  833. select_unselect_cmd (_("Select"), ":select_cmd: Select ", TRUE);
  834. }
  835. /* --------------------------------------------------------------------------------------------- */
  836. void
  837. unselect_cmd (void)
  838. {
  839. select_unselect_cmd (_("Unselect"), ":unselect_cmd: Unselect ", FALSE);
  840. }
  841. /* --------------------------------------------------------------------------------------------- */
  842. void
  843. ext_cmd (void)
  844. {
  845. vfs_path_t *buffer_vpath;
  846. vfs_path_t *extdir_vpath;
  847. int dir;
  848. dir = 0;
  849. if (geteuid () == 0)
  850. {
  851. dir = query_dialog (_("Extension file edit"),
  852. _("Which extension file you want to edit?"), D_NORMAL, 2,
  853. _("&User"), _("&System Wide"));
  854. }
  855. extdir_vpath = vfs_path_build_filename (mc_global.sysconfig_dir, MC_LIB_EXT, NULL);
  856. if (dir == 0)
  857. {
  858. buffer_vpath = mc_config_get_full_vpath (MC_FILEBIND_FILE);
  859. check_for_default (extdir_vpath, buffer_vpath);
  860. do_edit (buffer_vpath);
  861. vfs_path_free (buffer_vpath);
  862. }
  863. else if (dir == 1)
  864. {
  865. if (!exist_file (vfs_path_get_last_path_str (extdir_vpath)))
  866. {
  867. vfs_path_free (extdir_vpath);
  868. extdir_vpath = vfs_path_build_filename (mc_global.share_data_dir, MC_LIB_EXT, NULL);
  869. }
  870. do_edit (extdir_vpath);
  871. }
  872. vfs_path_free (extdir_vpath);
  873. flush_extension_file ();
  874. }
  875. /* --------------------------------------------------------------------------------------------- */
  876. /** edit file menu for mc */
  877. void
  878. edit_mc_menu_cmd (void)
  879. {
  880. vfs_path_t *buffer_vpath;
  881. vfs_path_t *menufile_vpath;
  882. int dir = 0;
  883. dir = query_dialog (_("Menu edit"),
  884. _("Which menu file do you want to edit?"),
  885. D_NORMAL, geteuid ()? 2 : 3, _("&Local"), _("&User"), _("&System Wide"));
  886. menufile_vpath = vfs_path_build_filename (mc_global.sysconfig_dir, MC_GLOBAL_MENU, NULL);
  887. if (!exist_file (vfs_path_get_last_path_str (menufile_vpath)))
  888. {
  889. vfs_path_free (menufile_vpath);
  890. menufile_vpath = vfs_path_build_filename (mc_global.share_data_dir, MC_GLOBAL_MENU, NULL);
  891. }
  892. switch (dir)
  893. {
  894. case 0:
  895. buffer_vpath = vfs_path_from_str (MC_LOCAL_MENU);
  896. check_for_default (menufile_vpath, buffer_vpath);
  897. chmod (vfs_path_get_last_path_str (buffer_vpath), 0600);
  898. break;
  899. case 1:
  900. buffer_vpath = mc_config_get_full_vpath (MC_USERMENU_FILE);
  901. check_for_default (menufile_vpath, buffer_vpath);
  902. break;
  903. case 2:
  904. buffer_vpath = vfs_path_build_filename (mc_global.sysconfig_dir, MC_GLOBAL_MENU, NULL);
  905. if (!exist_file (vfs_path_get_last_path_str (buffer_vpath)))
  906. {
  907. vfs_path_free (buffer_vpath);
  908. buffer_vpath = vfs_path_build_filename (mc_global.share_data_dir, MC_GLOBAL_MENU, NULL);
  909. }
  910. break;
  911. default:
  912. vfs_path_free (menufile_vpath);
  913. return;
  914. }
  915. do_edit (buffer_vpath);
  916. vfs_path_free (buffer_vpath);
  917. vfs_path_free (menufile_vpath);
  918. }
  919. /* --------------------------------------------------------------------------------------------- */
  920. void
  921. edit_fhl_cmd (void)
  922. {
  923. vfs_path_t *buffer_vpath = NULL;
  924. vfs_path_t *fhlfile_vpath = NULL;
  925. int dir;
  926. dir = 0;
  927. if (geteuid () == 0)
  928. {
  929. dir = query_dialog (_("Highlighting groups file edit"),
  930. _("Which highlighting file you want to edit?"), D_NORMAL, 2,
  931. _("&User"), _("&System Wide"));
  932. }
  933. fhlfile_vpath = vfs_path_build_filename (mc_global.sysconfig_dir, MC_FHL_INI_FILE, NULL);
  934. if (dir == 0)
  935. {
  936. buffer_vpath = mc_config_get_full_vpath (MC_FHL_INI_FILE);
  937. check_for_default (fhlfile_vpath, buffer_vpath);
  938. do_edit (buffer_vpath);
  939. vfs_path_free (buffer_vpath);
  940. }
  941. else if (dir == 1)
  942. {
  943. if (!exist_file (vfs_path_get_last_path_str (fhlfile_vpath)))
  944. {
  945. vfs_path_free (fhlfile_vpath);
  946. fhlfile_vpath =
  947. vfs_path_build_filename (mc_global.sysconfig_dir, MC_FHL_INI_FILE, NULL);
  948. }
  949. do_edit (fhlfile_vpath);
  950. }
  951. vfs_path_free (fhlfile_vpath);
  952. /* refresh highlighting rules */
  953. mc_fhl_free (&mc_filehighlight);
  954. mc_filehighlight = mc_fhl_new (TRUE);
  955. }
  956. /* --------------------------------------------------------------------------------------------- */
  957. void
  958. hotlist_cmd (void)
  959. {
  960. char *target;
  961. target = hotlist_show (LIST_HOTLIST);
  962. if (!target)
  963. return;
  964. if (get_current_type () == view_tree)
  965. tree_chdir (the_tree, target);
  966. else
  967. {
  968. vfs_path_t *deprecated_vpath;
  969. char *cmd, *normalized_target;
  970. deprecated_vpath = vfs_path_from_str_flags (target, VPF_USE_DEPRECATED_PARSER);
  971. normalized_target = vfs_path_to_str (deprecated_vpath);
  972. cmd = g_strconcat ("cd ", normalized_target, (char *) NULL);
  973. g_free (normalized_target);
  974. vfs_path_free (deprecated_vpath);
  975. do_cd_command (cmd);
  976. g_free (cmd);
  977. }
  978. g_free (target);
  979. }
  980. #ifdef ENABLE_VFS
  981. void
  982. vfs_list (void)
  983. {
  984. char *target;
  985. vfs_path_t *target_vpath;
  986. target = hotlist_show (LIST_VFSLIST);
  987. if (!target)
  988. return;
  989. target_vpath = vfs_path_from_str (target);
  990. if (!do_cd (target_vpath, cd_exact))
  991. message (D_ERROR, MSG_ERROR, _("Cannot change directory"));
  992. vfs_path_free (target_vpath);
  993. g_free (target);
  994. }
  995. #endif /* ENABLE_VFS */
  996. /* --------------------------------------------------------------------------------------------- */
  997. void
  998. compare_dirs_cmd (void)
  999. {
  1000. int choice;
  1001. enum CompareMode thorough_flag;
  1002. choice =
  1003. query_dialog (_("Compare directories"),
  1004. _("Select compare method:"), D_NORMAL, 4,
  1005. _("&Quick"), _("&Size only"), _("&Thorough"), _("&Cancel"));
  1006. if (choice < 0 || choice > 2)
  1007. return;
  1008. thorough_flag = choice;
  1009. if (get_current_type () == view_listing && get_other_type () == view_listing)
  1010. {
  1011. compare_dir (current_panel, other_panel, thorough_flag);
  1012. compare_dir (other_panel, current_panel, thorough_flag);
  1013. }
  1014. else
  1015. {
  1016. message (D_ERROR, MSG_ERROR,
  1017. _("Both panels should be in the listing mode\nto use this command"));
  1018. }
  1019. }
  1020. /* --------------------------------------------------------------------------------------------- */
  1021. #ifdef USE_DIFF_VIEW
  1022. void
  1023. diff_view_cmd (void)
  1024. {
  1025. /* both panels must be in the list mode */
  1026. if (get_current_type () != view_listing || get_other_type () != view_listing)
  1027. return;
  1028. if (get_current_index () == 0)
  1029. dview_diff_cmd (current_panel, other_panel);
  1030. else
  1031. dview_diff_cmd (other_panel, current_panel);
  1032. if (mc_global.mc_run_mode == MC_RUN_FULL)
  1033. update_panels (UP_OPTIMIZE, UP_KEEPSEL);
  1034. dialog_switch_process_pending ();
  1035. }
  1036. #endif
  1037. /* --------------------------------------------------------------------------------------------- */
  1038. void
  1039. swap_cmd (void)
  1040. {
  1041. swap_panels ();
  1042. tty_touch_screen ();
  1043. repaint_screen ();
  1044. }
  1045. /* --------------------------------------------------------------------------------------------- */
  1046. void
  1047. view_other_cmd (void)
  1048. {
  1049. static int message_flag = TRUE;
  1050. if (!mc_global.tty.xterm_flag && mc_global.tty.console_flag == '\0'
  1051. && !mc_global.tty.use_subshell && !output_starts_shell)
  1052. {
  1053. if (message_flag)
  1054. message (D_ERROR, MSG_ERROR,
  1055. _("Not an xterm or Linux console;\nthe panels cannot be toggled."));
  1056. message_flag = FALSE;
  1057. }
  1058. else
  1059. {
  1060. toggle_panels ();
  1061. }
  1062. }
  1063. /* --------------------------------------------------------------------------------------------- */
  1064. void
  1065. link_cmd (link_type_t link_type)
  1066. {
  1067. char *filename = selection (current_panel)->fname;
  1068. if (filename != NULL)
  1069. do_link (link_type, filename);
  1070. }
  1071. /* --------------------------------------------------------------------------------------------- */
  1072. void
  1073. edit_symlink_cmd (void)
  1074. {
  1075. if (S_ISLNK (selection (current_panel)->st.st_mode))
  1076. {
  1077. char buffer[MC_MAXPATHLEN];
  1078. char *p = NULL;
  1079. int i;
  1080. char *dest, *q;
  1081. vfs_path_t *p_vpath;
  1082. p = selection (current_panel)->fname;
  1083. p_vpath = vfs_path_from_str (p);
  1084. q = g_strdup_printf (_("Symlink `%s\' points to:"), str_trunc (p, 32));
  1085. i = readlink (p, buffer, MC_MAXPATHLEN - 1);
  1086. if (i > 0)
  1087. {
  1088. buffer[i] = 0;
  1089. dest = input_expand_dialog (_("Edit symlink"), q, MC_HISTORY_FM_EDIT_LINK, buffer);
  1090. if (dest)
  1091. {
  1092. if (*dest && strcmp (buffer, dest))
  1093. {
  1094. save_cwds_stat ();
  1095. if (mc_unlink (p_vpath) == -1)
  1096. {
  1097. message (D_ERROR, MSG_ERROR, _("edit symlink, unable to remove %s: %s"),
  1098. p, unix_error_string (errno));
  1099. }
  1100. else
  1101. {
  1102. vfs_path_t *dest_vpath;
  1103. dest_vpath = vfs_path_from_str_flags (dest, VPF_NO_CANON);
  1104. if (mc_symlink (dest_vpath, p_vpath) == -1)
  1105. message (D_ERROR, MSG_ERROR, _("edit symlink: %s"),
  1106. unix_error_string (errno));
  1107. vfs_path_free (dest_vpath);
  1108. }
  1109. update_panels (UP_OPTIMIZE, UP_KEEPSEL);
  1110. repaint_screen ();
  1111. }
  1112. g_free (dest);
  1113. }
  1114. }
  1115. g_free (q);
  1116. vfs_path_free (p_vpath);
  1117. }
  1118. else
  1119. {
  1120. message (D_ERROR, MSG_ERROR, _("`%s' is not a symbolic link"),
  1121. selection (current_panel)->fname);
  1122. }
  1123. }
  1124. /* --------------------------------------------------------------------------------------------- */
  1125. void
  1126. help_cmd (void)
  1127. {
  1128. ev_help_t event_data = { NULL, NULL };
  1129. if (current_panel->searching)
  1130. event_data.node = "[Quick search]";
  1131. else
  1132. event_data.node = "[main]";
  1133. mc_event_raise (MCEVENT_GROUP_CORE, "help", &event_data);
  1134. }
  1135. /* --------------------------------------------------------------------------------------------- */
  1136. void
  1137. user_file_menu_cmd (void)
  1138. {
  1139. (void) user_menu_cmd (NULL, NULL, -1);
  1140. }
  1141. /* --------------------------------------------------------------------------------------------- */
  1142. /**
  1143. * Return a random hint. If force is not 0, ignore the timeout.
  1144. */
  1145. char *
  1146. get_random_hint (int force)
  1147. {
  1148. char *data, *result = NULL, *eol;
  1149. int len;
  1150. int start;
  1151. static int last_sec;
  1152. static struct timeval tv;
  1153. GIConv conv;
  1154. /* Do not change hints more often than one minute */
  1155. gettimeofday (&tv, NULL);
  1156. if (!force && !(tv.tv_sec > last_sec + 60))
  1157. return g_strdup ("");
  1158. last_sec = tv.tv_sec;
  1159. data = load_mc_home_file (mc_global.share_data_dir, MC_HINT, NULL);
  1160. if (data == NULL)
  1161. return NULL;
  1162. /* get a random entry */
  1163. srand (tv.tv_sec);
  1164. len = strlen (data);
  1165. start = rand () % len;
  1166. for (; start != 0; start--)
  1167. if (data[start] == '\n')
  1168. {
  1169. start++;
  1170. break;
  1171. }
  1172. eol = strchr (data + start, '\n');
  1173. if (eol != NULL)
  1174. *eol = '\0';
  1175. /* hint files are stored in utf-8 */
  1176. /* try convert hint file from utf-8 to terminal encoding */
  1177. conv = str_crt_conv_from ("UTF-8");
  1178. if (conv != INVALID_CONV)
  1179. {
  1180. GString *buffer;
  1181. buffer = g_string_new ("");
  1182. if (str_convert (conv, &data[start], buffer) != ESTR_FAILURE)
  1183. result = g_string_free (buffer, FALSE);
  1184. else
  1185. g_string_free (buffer, TRUE);
  1186. str_close_conv (conv);
  1187. }
  1188. g_free (data);
  1189. return result;
  1190. }
  1191. /* --------------------------------------------------------------------------------------------- */
  1192. #ifdef ENABLE_VFS_FTP
  1193. void
  1194. ftplink_cmd (void)
  1195. {
  1196. nice_cd (_("FTP to machine"), _(machine_str),
  1197. "[FTP File System]", ":ftplink_cmd: FTP to machine ", "ftp://", 1, TRUE);
  1198. }
  1199. #endif /* ENABLE_VFS_FTP */
  1200. /* --------------------------------------------------------------------------------------------- */
  1201. #ifdef ENABLE_VFS_FISH
  1202. void
  1203. fishlink_cmd (void)
  1204. {
  1205. nice_cd (_("Shell link to machine"), _(machine_str),
  1206. "[FIle transfer over SHell filesystem]", ":fishlink_cmd: Shell link to machine ",
  1207. "sh://", 1, TRUE);
  1208. }
  1209. #endif /* ENABLE_VFS_FISH */
  1210. /* --------------------------------------------------------------------------------------------- */
  1211. #ifdef ENABLE_VFS_SMB
  1212. void
  1213. smblink_cmd (void)
  1214. {
  1215. nice_cd (_("SMB link to machine"), _(machine_str),
  1216. "[SMB File System]", ":smblink_cmd: SMB link to machine ", "smb://", 0, TRUE);
  1217. }
  1218. #endif /* ENABLE_VFS_SMB */
  1219. /* --------------------------------------------------------------------------------------------- */
  1220. #ifdef ENABLE_VFS_UNDELFS
  1221. void
  1222. undelete_cmd (void)
  1223. {
  1224. nice_cd (_("Undelete files on an ext2 file system"),
  1225. _("Enter device (without /dev/) to undelete\nfiles on: (F1 for details)"),
  1226. "[Undelete File System]", ":undelete_cmd: Undel on ext2 fs ", "undel://", 0, FALSE);
  1227. }
  1228. #endif /* ENABLE_VFS_UNDELFS */
  1229. /* --------------------------------------------------------------------------------------------- */
  1230. void
  1231. quick_cd_cmd (void)
  1232. {
  1233. char *p = cd_dialog ();
  1234. if (p && *p)
  1235. {
  1236. char *q = g_strconcat ("cd ", p, (char *) NULL);
  1237. do_cd_command (q);
  1238. g_free (q);
  1239. }
  1240. g_free (p);
  1241. }
  1242. /* --------------------------------------------------------------------------------------------- */
  1243. /*!
  1244. \brief calculate dirs sizes
  1245. calculate dirs sizes and resort panel:
  1246. dirs_selected = show size for selected dirs,
  1247. otherwise = show size for dir under cursor:
  1248. dir under cursor ".." = show size for all dirs,
  1249. otherwise = show size for dir under cursor
  1250. */
  1251. void
  1252. smart_dirsize_cmd (void)
  1253. {
  1254. WPanel *panel = current_panel;
  1255. file_entry *entry;
  1256. entry = &(panel->dir.list[panel->selected]);
  1257. if ((S_ISDIR (entry->st.st_mode) && (strcmp (entry->fname, "..") == 0)) || panel->dirs_marked)
  1258. dirsizes_cmd ();
  1259. else
  1260. single_dirsize_cmd ();
  1261. }
  1262. /* --------------------------------------------------------------------------------------------- */
  1263. void
  1264. single_dirsize_cmd (void)
  1265. {
  1266. WPanel *panel = current_panel;
  1267. file_entry *entry;
  1268. entry = &(panel->dir.list[panel->selected]);
  1269. if (S_ISDIR (entry->st.st_mode) && strcmp (entry->fname, "..") != 0)
  1270. {
  1271. size_t marked = 0;
  1272. uintmax_t total = 0;
  1273. ComputeDirSizeUI *ui;
  1274. vfs_path_t *p;
  1275. ui = compute_dir_size_create_ui ();
  1276. p = vfs_path_from_str (entry->fname);
  1277. if (compute_dir_size (p, ui, compute_dir_size_update_ui, &marked, &total, TRUE) ==
  1278. FILE_CONT)
  1279. {
  1280. entry->st.st_size = (off_t) total;
  1281. entry->f.dir_size_computed = 1;
  1282. }
  1283. vfs_path_free (p);
  1284. compute_dir_size_destroy_ui (ui);
  1285. }
  1286. if (panels_options.mark_moves_down)
  1287. send_message ((Widget *) panel, WIDGET_COMMAND, CK_Down);
  1288. recalculate_panel_summary (panel);
  1289. if (current_panel->sort_info.sort_field->sort_routine == (sortfn *) sort_size)
  1290. panel_re_sort (panel);
  1291. panel->dirty = 1;
  1292. }
  1293. /* --------------------------------------------------------------------------------------------- */
  1294. void
  1295. dirsizes_cmd (void)
  1296. {
  1297. WPanel *panel = current_panel;
  1298. int i;
  1299. ComputeDirSizeUI *ui;
  1300. ui = compute_dir_size_create_ui ();
  1301. for (i = 0; i < panel->count; i++)
  1302. if (S_ISDIR (panel->dir.list[i].st.st_mode)
  1303. && ((panel->dirs_marked && panel->dir.list[i].f.marked)
  1304. || !panel->dirs_marked) && strcmp (panel->dir.list[i].fname, "..") != 0)
  1305. {
  1306. vfs_path_t *p;
  1307. size_t marked = 0;
  1308. uintmax_t total = 0;
  1309. gboolean ok;
  1310. p = vfs_path_from_str (panel->dir.list[i].fname);
  1311. ok = compute_dir_size (p, ui, compute_dir_size_update_ui, &marked, &total,
  1312. TRUE) != FILE_CONT;
  1313. vfs_path_free (p);
  1314. if (ok)
  1315. break;
  1316. panel->dir.list[i].st.st_size = (off_t) total;
  1317. panel->dir.list[i].f.dir_size_computed = 1;
  1318. }
  1319. compute_dir_size_destroy_ui (ui);
  1320. recalculate_panel_summary (panel);
  1321. if (current_panel->sort_info.sort_field->sort_routine == (sortfn *) sort_size)
  1322. panel_re_sort (panel);
  1323. panel->dirty = 1;
  1324. }
  1325. /* --------------------------------------------------------------------------------------------- */
  1326. void
  1327. save_setup_cmd (void)
  1328. {
  1329. vfs_path_t *vpath;
  1330. char *path;
  1331. vpath = mc_config_get_full_vpath (MC_CONFIG_FILE);
  1332. path = vfs_path_to_str_flags (vpath, 0, VPF_STRIP_HOME);
  1333. vfs_path_free (vpath);
  1334. if (save_setup (TRUE, TRUE))
  1335. message (D_NORMAL, _("Setup"), _("Setup saved to %s"), path);
  1336. else
  1337. message (D_ERROR, _("Setup"), _("Unable to save setup to %s"), path);
  1338. g_free (path);
  1339. }
  1340. /* --------------------------------------------------------------------------------------------- */
  1341. void
  1342. info_cmd_no_menu (void)
  1343. {
  1344. if (get_display_type (0) == view_info)
  1345. set_display_type (0, view_listing);
  1346. else if (get_display_type (1) == view_info)
  1347. set_display_type (1, view_listing);
  1348. else
  1349. set_display_type (current_panel == left_panel ? 1 : 0, view_info);
  1350. }
  1351. /* --------------------------------------------------------------------------------------------- */
  1352. void
  1353. quick_cmd_no_menu (void)
  1354. {
  1355. if (get_display_type (0) == view_quick)
  1356. set_display_type (0, view_listing);
  1357. else if (get_display_type (1) == view_quick)
  1358. set_display_type (1, view_listing);
  1359. else
  1360. set_display_type (current_panel == left_panel ? 1 : 0, view_quick);
  1361. }
  1362. /* --------------------------------------------------------------------------------------------- */
  1363. void
  1364. listing_cmd (void)
  1365. {
  1366. switch_to_listing (MENU_PANEL_IDX);
  1367. }
  1368. /* --------------------------------------------------------------------------------------------- */
  1369. void
  1370. change_listing_cmd (void)
  1371. {
  1372. int list_type;
  1373. int use_msformat;
  1374. char *user, *status;
  1375. WPanel *p = NULL;
  1376. if (get_display_type (MENU_PANEL_IDX) == view_listing)
  1377. p = MENU_PANEL_IDX == 0 ? left_panel : right_panel;
  1378. list_type = display_box (p, &user, &status, &use_msformat, MENU_PANEL_IDX);
  1379. if (list_type != -1)
  1380. {
  1381. switch_to_listing (MENU_PANEL_IDX);
  1382. p = MENU_PANEL_IDX == 0 ? left_panel : right_panel;
  1383. configure_panel_listing (p, list_type, use_msformat, user, status);
  1384. }
  1385. }
  1386. /* --------------------------------------------------------------------------------------------- */
  1387. void
  1388. panel_tree_cmd (void)
  1389. {
  1390. set_display_type (MENU_PANEL_IDX, view_tree);
  1391. }
  1392. /* --------------------------------------------------------------------------------------------- */
  1393. void
  1394. info_cmd (void)
  1395. {
  1396. set_display_type (MENU_PANEL_IDX, view_info);
  1397. }
  1398. /* --------------------------------------------------------------------------------------------- */
  1399. void
  1400. quick_view_cmd (void)
  1401. {
  1402. if ((WPanel *) get_panel_widget (MENU_PANEL_IDX) == current_panel)
  1403. change_panel ();
  1404. set_display_type (MENU_PANEL_IDX, view_quick);
  1405. }
  1406. /* --------------------------------------------------------------------------------------------- */
  1407. void
  1408. toggle_listing_cmd (void)
  1409. {
  1410. int current = get_current_index ();
  1411. WPanel *p = (WPanel *) get_panel_widget (current);
  1412. set_basic_panel_listing_to (current, (p->list_type + 1) % LIST_TYPES);
  1413. }
  1414. /* --------------------------------------------------------------------------------------------- */
  1415. void
  1416. encoding_cmd (void)
  1417. {
  1418. if (SELECTED_IS_PANEL)
  1419. panel_change_encoding (MENU_PANEL);
  1420. }
  1421. /* --------------------------------------------------------------------------------------------- */