cmd.c 38 KB

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