main.c 59 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318
  1. /* Main program for the Midnight Commander
  2. Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
  3. 2003, 2004, 2005, 2006, 2007, 2009 Free Software Foundation, Inc.
  4. Written by: 1994, 1995, 1996, 1997 Miguel de Icaza
  5. 1994, 1995 Janne Kukonlehto
  6. 1997 Norbert Warmuth
  7. This program is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2 of the License, or
  10. (at your option) any later version.
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. GNU General Public License for more details.
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
  18. /** \file main.c
  19. * \brief Source: this is a main module
  20. */
  21. #include <config.h>
  22. #include <ctype.h>
  23. #include <errno.h>
  24. #include <locale.h>
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27. #include <string.h>
  28. #include <fcntl.h>
  29. #include <sys/types.h>
  30. #include <sys/stat.h>
  31. #include <sys/wait.h>
  32. #include <unistd.h>
  33. #include <pwd.h> /* for username in xterm title */
  34. #include "global.h"
  35. #include "../src/tty/tty.h"
  36. #include "../src/skin/skin.h"
  37. #include "../src/tty/mouse.h"
  38. #include "../src/tty/key.h" /* For init_key() */
  39. #include "../src/tty/win.h" /* xterm_flag */
  40. #include "../src/mcconfig/mcconfig.h"
  41. #include "../src/args.h"
  42. #include "../src/skin/skin.h"
  43. #include "../src/filehighlight/fhl.h"
  44. #include "dir.h"
  45. #include "dialog.h"
  46. #include "menu.h"
  47. #include "panel.h"
  48. #include "option.h"
  49. #include "tree.h"
  50. #include "treestore.h"
  51. #include "cons.saver.h"
  52. #include "subshell.h"
  53. #include "setup.h" /* save_setup() */
  54. #include "boxes.h" /* sort_box() */
  55. #include "layout.h"
  56. #include "cmd.h" /* Normal commands */
  57. #include "hotlist.h"
  58. #include "panelize.h"
  59. #include "learn.h" /* learn_keys() */
  60. #include "listmode.h"
  61. #include "execute.h"
  62. #include "ext.h" /* For flush_extension_file() */
  63. #include "strutil.h"
  64. #include "widget.h"
  65. #include "command.h"
  66. #include "wtools.h"
  67. #include "cmddef.h" /* CK_ cmd name const */
  68. #include "fileloc.h" /* MC_USERCONF_DIR */
  69. #include "user.h" /* user_file_menu_cmd() */
  70. #include "../vfs/vfs.h" /* vfs_translate_url() */
  71. #include "chmod.h"
  72. #include "chown.h"
  73. #include "achown.h"
  74. #include "main.h"
  75. #ifdef WITH_SMBFS
  76. #include "../vfs/smbfs.h" /* smbfs_set_debug() */
  77. #endif
  78. #ifdef USE_INTERNAL_EDIT
  79. # include "../edit/edit.h"
  80. #endif
  81. #ifdef HAVE_CHARSET
  82. #include "charsets.h"
  83. #endif /* HAVE_CHARSET */
  84. #ifdef USE_VFS
  85. #include "../vfs/gc.h"
  86. #endif
  87. #include "keybind.h" /* type global_keymap_t */
  88. /* When the modes are active, left_panel, right_panel and tree_panel */
  89. /* Point to a proper data structure. You should check with the functions */
  90. /* get_current_type and get_other_type the types of the panels before using */
  91. /* This pointer variables */
  92. /* The structures for the panels */
  93. WPanel *left_panel = NULL;
  94. WPanel *right_panel = NULL;
  95. mc_fhl_t *mc_filehighlight;
  96. /* The pointer to the tree */
  97. WTree *the_tree = NULL;
  98. /* The Menubar */
  99. struct WMenuBar *the_menubar = NULL;
  100. /* Pointers to the selected and unselected panel */
  101. WPanel *current_panel = NULL;
  102. /* Set if the command is being run from the "Right" menu */
  103. int is_right = 0;
  104. /* Set when main loop should be terminated */
  105. volatile int quit = 0;
  106. /* Set if you want the possible completions dialog for the first time */
  107. int show_all_if_ambiguous = 0;
  108. /* Set when cd symlink following is desirable (bash mode) */
  109. int cd_symlinks = 1;
  110. /* If set then dialogs just clean the screen when refreshing, else */
  111. /* they do a complete refresh, refreshing all the parts of the program */
  112. int fast_refresh = 0;
  113. /* If true, marking a files moves the cursor down */
  114. int mark_moves_down = 1;
  115. /* If true, at startup the user-menu is invoked */
  116. int auto_menu = 0;
  117. /* If true, then the +, - and \ keys have their special meaning only if the
  118. * command line is emtpy, otherwise they behave like regular letters
  119. */
  120. int only_leading_plus_minus = 1;
  121. int pause_after_run = pause_on_dumb_terminals;
  122. /* It true saves the setup when quitting */
  123. int auto_save_setup = 1;
  124. #ifdef HAVE_CHARSET
  125. /*
  126. * Don't restrict the output on the screen manager level,
  127. * the translation tables take care of it.
  128. */
  129. #define full_eight_bits (1)
  130. #define eight_bit_clean (1)
  131. #else /* HAVE_CHARSET */
  132. /* If true, allow characters in the range 160-255 */
  133. int eight_bit_clean = 1;
  134. /*
  135. * If true, also allow characters in the range 128-159.
  136. * This is reported to break on many terminals (xterm, qansi-m).
  137. */
  138. int full_eight_bits = 0;
  139. #endif /* !HAVE_CHARSET */
  140. /*
  141. * If utf-8 terminal utf8_display = 1
  142. * Display bits set UTF-8
  143. *
  144. */
  145. int utf8_display = 0;
  146. /* If true use the internal viewer */
  147. int use_internal_view = 1;
  148. /* Have we shown the fast-reload warning in the past? */
  149. int fast_reload_w = 0;
  150. /* Move page/item? When clicking on the top or bottom of a panel */
  151. int mouse_move_pages = 1;
  152. /* If true: l&r arrows are used to chdir if the input line is empty */
  153. int navigate_with_arrows = 0;
  154. /* If true program softkeys (HP terminals only) on startup and after every
  155. command ran in the subshell to the description found in the termcap/terminfo
  156. database */
  157. int reset_hp_softkeys = 0;
  158. /* The prompt */
  159. const char *prompt = NULL;
  160. /* The widget where we draw the prompt */
  161. WLabel *the_prompt;
  162. /* The hint bar */
  163. WLabel *the_hint;
  164. /* The button bar */
  165. WButtonBar *the_bar;
  166. /* Mouse type: GPM, xterm or none */
  167. Mouse_Type use_mouse_p = MOUSE_NONE;
  168. /* If on, default for "No" in delete operations */
  169. int safe_delete = 0;
  170. /* Controls screen clearing before an exec */
  171. int clear_before_exec = 1;
  172. /* Asks for confirmation before deleting a file */
  173. int confirm_delete = 1;
  174. /* Asks for confirmation before deleting a hotlist entry */
  175. int confirm_directory_hotlist_delete = 1;
  176. /* Asks for confirmation before overwriting a file */
  177. int confirm_overwrite = 1;
  178. /* Asks for confirmation before executing a program by pressing enter */
  179. int confirm_execute = 0;
  180. /* Asks for confirmation before leaving the program */
  181. int confirm_exit = 1;
  182. /* Asks for confirmation when using F3 to view a directory and there
  183. are tagged files */
  184. int confirm_view_dir = 0;
  185. /* This flag indicates if the pull down menus by default drop down */
  186. int drop_menus = 0;
  187. /* if skip_check_codeset = 1 do not show warning about
  188. * system and display codeset is different
  189. */
  190. int skip_check_codeset = 0;
  191. /* The dialog handle for the main program */
  192. Dlg_head *midnight_dlg = NULL;
  193. /* Subshell: if set, then the prompt was not saved on CONSOLE_SAVE */
  194. /* We need to paint it after CONSOLE_RESTORE, see: load_prompt */
  195. int update_prompt = 0;
  196. /* The home directory */
  197. const char *home_dir = NULL;
  198. /* Tab size */
  199. int option_tab_spacing = 8;
  200. /* The value of the other directory, only used when loading the setup */
  201. char *other_dir = NULL;
  202. /* Only used at program boot */
  203. int boot_current_is_left = 1;
  204. static char *this_dir = NULL;
  205. /* If this is true, then when browsing the tree the other window will
  206. * automatically reload it's directory with the contents of the currently
  207. * selected directory.
  208. */
  209. int xtree_mode = 0;
  210. /* If set, then print to the given file the last directory we were at */
  211. static char *last_wd_string = NULL;
  212. /* Set to 1 to suppress printing the last directory */
  213. static int print_last_revert = 0;
  214. /* File name to view if argument was supplied */
  215. const char *view_one_file = NULL;
  216. /* File name to edit if argument was supplied */
  217. const char *edit_one_file = NULL;
  218. /* Line to start the editor on */
  219. static int edit_one_file_start_line = 0;
  220. /* Used so that widgets know if they are being destroyed or
  221. shut down */
  222. int midnight_shutdown = 0;
  223. /* The user's shell */
  224. char *shell = NULL;
  225. /* mc_home: The home of MC - /etc/mc or defined by MC_DATADIR */
  226. char *mc_home = NULL;
  227. /* mc_home_alt: Alternative home of MC - deprecated /usr/share/mc */
  228. char *mc_home_alt = NULL;
  229. /* Define this function for glib-style error handling */
  230. GQuark
  231. mc_main_error_quark (void)
  232. {
  233. return g_quark_from_static_string (PACKAGE);
  234. }
  235. #ifdef USE_INTERNAL_EDIT
  236. GArray *editor_keymap = NULL;
  237. GArray *editor_x_keymap = NULL;
  238. #endif
  239. GArray *viewer_keymap = NULL;
  240. GArray *viewer_hex_keymap = NULL;
  241. GArray *main_keymap = NULL;
  242. GArray *main_x_keymap = NULL;
  243. GArray *panel_keymap = NULL;
  244. GArray *input_keymap = NULL;
  245. GArray *tree_keymap = NULL;
  246. GArray *help_keymap = NULL;
  247. const global_keymap_t *main_map;
  248. const global_keymap_t *main_x_map;
  249. /* Save current stat of directories to avoid reloading the panels */
  250. /* when no modifications have taken place */
  251. void
  252. save_cwds_stat (void)
  253. {
  254. if (fast_reload) {
  255. mc_stat (current_panel->cwd, &(current_panel->dir_stat));
  256. if (get_other_type () == view_listing)
  257. mc_stat (other_panel->cwd, &(other_panel->dir_stat));
  258. }
  259. }
  260. #ifdef HAVE_SUBSHELL_SUPPORT
  261. void
  262. do_update_prompt (void)
  263. {
  264. if (update_prompt) {
  265. printf ("\r\n%s", subshell_prompt);
  266. fflush (stdout);
  267. update_prompt = 0;
  268. }
  269. }
  270. #endif /* HAVE_SUBSHELL_SUPPORT */
  271. void
  272. change_panel (void)
  273. {
  274. free_completions (cmdline);
  275. dlg_one_down (midnight_dlg);
  276. }
  277. /* Stop MC main dialog and the current dialog if it exists.
  278. * Needed to provide fast exit from MC viewer or editor on shell exit */
  279. static void
  280. stop_dialogs (void)
  281. {
  282. midnight_dlg->running = 0;
  283. if (current_dlg) {
  284. current_dlg->running = 0;
  285. }
  286. }
  287. static int
  288. quit_cmd_internal (int quiet)
  289. {
  290. int q = quit;
  291. if (quiet || !confirm_exit) {
  292. q = 1;
  293. } else {
  294. if (query_dialog
  295. (_(" The Midnight Commander "),
  296. _(" Do you really want to quit the Midnight Commander? "), D_NORMAL,
  297. 2, _("&Yes"), _("&No")) == 0)
  298. q = 1;
  299. }
  300. if (q) {
  301. #ifdef HAVE_SUBSHELL_SUPPORT
  302. if (!use_subshell)
  303. stop_dialogs ();
  304. else if ((q = exit_subshell ()))
  305. #endif
  306. stop_dialogs ();
  307. }
  308. if (q)
  309. quit |= 1;
  310. return quit;
  311. }
  312. static void
  313. quit_cmd (void)
  314. {
  315. quit_cmd_internal (0);
  316. }
  317. void
  318. quiet_quit_cmd (void)
  319. {
  320. print_last_revert = 1;
  321. quit_cmd_internal (1);
  322. }
  323. /* Wrapper for do_subshell_chdir, check for availability of subshell */
  324. void
  325. subshell_chdir (const char *directory)
  326. {
  327. #ifdef HAVE_SUBSHELL_SUPPORT
  328. if (use_subshell) {
  329. if (vfs_current_is_local ())
  330. do_subshell_chdir (directory, 0, 1);
  331. }
  332. #endif /* HAVE_SUBSHELL_SUPPORT */
  333. }
  334. void
  335. directory_history_add (struct WPanel *panel, const char *dir)
  336. {
  337. char *tmp;
  338. tmp = g_strdup (dir);
  339. strip_password (tmp, 1);
  340. panel->dir_history = list_append_unique (panel->dir_history, tmp);
  341. }
  342. /*
  343. * If we moved to the parent directory move the selection pointer to
  344. * the old directory name; If we leave VFS dir, remove FS specificator.
  345. *
  346. * You do _NOT_ want to add any vfs aware code here. <pavel@ucw.cz>
  347. */
  348. static const char *
  349. get_parent_dir_name (const char *cwd, const char *lwd)
  350. {
  351. const char *p;
  352. if (strlen (lwd) > strlen (cwd))
  353. if ((p = strrchr (lwd, PATH_SEP)) && !strncmp (cwd, lwd, p - lwd) &&
  354. ((gsize)strlen (cwd) == (gsize) p - (gsize) lwd || (p == lwd && cwd[0] == PATH_SEP &&
  355. cwd[1] == '\0'))) {
  356. return (p + 1);
  357. }
  358. return NULL;
  359. }
  360. /*
  361. * Changes the current directory of the panel.
  362. * Don't record change in the directory history.
  363. */
  364. static int
  365. _do_panel_cd (WPanel *panel, const char *new_dir, enum cd_enum cd_type)
  366. {
  367. const char *directory;
  368. char *olddir;
  369. char temp[MC_MAXPATHLEN];
  370. char *translated_url;
  371. if (cd_type == cd_parse_command) {
  372. while (*new_dir == ' ')
  373. new_dir++;
  374. }
  375. olddir = g_strdup (panel->cwd);
  376. new_dir = translated_url = vfs_translate_url (new_dir);
  377. /* Convert *new_path to a suitable pathname, handle ~user */
  378. if (cd_type == cd_parse_command) {
  379. if (!strcmp (new_dir, "-")) {
  380. strcpy (temp, panel->lwd);
  381. new_dir = temp;
  382. }
  383. }
  384. directory = *new_dir ? new_dir : home_dir;
  385. if (mc_chdir (directory) == -1) {
  386. strcpy (panel->cwd, olddir);
  387. g_free (olddir);
  388. g_free (translated_url);
  389. return 0;
  390. }
  391. g_free (translated_url);
  392. /* Success: save previous directory, shutdown status of previous dir */
  393. strcpy (panel->lwd, olddir);
  394. free_completions (cmdline);
  395. mc_get_current_wd (panel->cwd, sizeof (panel->cwd) - 2);
  396. vfs_release_path (olddir);
  397. subshell_chdir (panel->cwd);
  398. /* Reload current panel */
  399. panel_clean_dir (panel);
  400. panel->count =
  401. do_load_dir (panel->cwd, &panel->dir, panel->current_sort_field->sort_routine,
  402. panel->reverse, panel->case_sensitive,
  403. panel->exec_first, panel->filter);
  404. try_to_select (panel, get_parent_dir_name (panel->cwd, olddir));
  405. load_hint (0);
  406. panel->dirty = 1;
  407. update_xterm_title_path ();
  408. g_free (olddir);
  409. return 1;
  410. }
  411. /*
  412. * Changes the current directory of the panel.
  413. * Record change in the directory history.
  414. */
  415. int
  416. do_panel_cd (struct WPanel *panel, const char *new_dir, enum cd_enum cd_type)
  417. {
  418. int r;
  419. r = _do_panel_cd (panel, new_dir, cd_type);
  420. if (r)
  421. directory_history_add (panel, panel->cwd);
  422. return r;
  423. }
  424. int
  425. do_cd (const char *new_dir, enum cd_enum exact)
  426. {
  427. return (do_panel_cd (current_panel, new_dir, exact));
  428. }
  429. void
  430. directory_history_next (WPanel *panel)
  431. {
  432. GList *nextdir;
  433. nextdir = g_list_next (panel->dir_history);
  434. if (!nextdir)
  435. return;
  436. if (_do_panel_cd (panel, (char *) nextdir->data, cd_exact))
  437. panel->dir_history = nextdir;
  438. }
  439. void
  440. directory_history_prev (WPanel *panel)
  441. {
  442. GList *prevdir;
  443. prevdir = g_list_previous (panel->dir_history);
  444. if (!prevdir)
  445. return;
  446. if (_do_panel_cd (panel, (char *) prevdir->data, cd_exact))
  447. panel->dir_history = prevdir;
  448. }
  449. void
  450. directory_history_list (WPanel *panel)
  451. {
  452. char *s;
  453. if (!panel->dir_history)
  454. return;
  455. s = show_hist (panel->dir_history, &panel->widget);
  456. if (!s)
  457. return;
  458. if (_do_panel_cd (panel, s, cd_exact))
  459. directory_history_add (panel, panel->cwd);
  460. else
  461. message (D_ERROR, MSG_ERROR, _("Cannot change directory"));
  462. g_free (s);
  463. }
  464. #ifdef HAVE_SUBSHELL_SUPPORT
  465. int
  466. load_prompt (int fd, void *unused)
  467. {
  468. (void) fd;
  469. (void) unused;
  470. if (!read_subshell_prompt ())
  471. return 0;
  472. /* Don't actually change the prompt if it's invisible */
  473. if (current_dlg == midnight_dlg && command_prompt) {
  474. char *tmp_prompt;
  475. int prompt_len;
  476. tmp_prompt = strip_ctrl_codes (subshell_prompt);
  477. prompt_len = str_term_width1 (tmp_prompt);
  478. /* Check for prompts too big */
  479. if (COLS > 8 && prompt_len > COLS - 8) {
  480. tmp_prompt[COLS - 8] = '\0';
  481. prompt_len = COLS - 8;
  482. }
  483. prompt = tmp_prompt;
  484. label_set_text (the_prompt, prompt);
  485. winput_set_origin ((WInput *) cmdline, prompt_len,
  486. COLS - prompt_len);
  487. /* since the prompt has changed, and we are called from one of the
  488. * tty_get_event channels, the prompt updating does not take place
  489. * automatically: force a cursor update and a screen refresh
  490. */
  491. update_cursor (midnight_dlg);
  492. mc_refresh ();
  493. }
  494. update_prompt = 1;
  495. return 0;
  496. }
  497. #endif /* HAVE_SUBSHELL_SUPPORT */
  498. void
  499. sort_cmd (void)
  500. {
  501. WPanel *p;
  502. const panel_field_t *sort_order;
  503. if (!SELECTED_IS_PANEL)
  504. return;
  505. p = MENU_PANEL;
  506. sort_order = sort_box (p->current_sort_field, &p->reverse,
  507. &p->case_sensitive,
  508. &p->exec_first);
  509. panel_set_sort_order (p, sort_order);
  510. }
  511. static void
  512. treebox_cmd (void)
  513. {
  514. char *sel_dir;
  515. sel_dir = tree_box (selection (current_panel)->fname);
  516. if (sel_dir) {
  517. do_cd (sel_dir, cd_exact);
  518. g_free (sel_dir);
  519. }
  520. }
  521. #ifdef LISTMODE_EDITOR
  522. static void
  523. listmode_cmd (void)
  524. {
  525. char *newmode;
  526. if (get_current_type () != view_listing)
  527. return;
  528. newmode = listmode_edit (current_panel->user_format);
  529. if (!newmode)
  530. return;
  531. g_free (current_panel->user_format);
  532. current_panel->list_type = list_user;
  533. current_panel->user_format = newmode;
  534. set_panel_formats (current_panel);
  535. do_refresh ();
  536. }
  537. #endif /* LISTMODE_EDITOR */
  538. /* NOTICE: hotkeys specified here are overriden in menubar_paint_idx (alex) */
  539. static GList *
  540. create_panel_menu (void)
  541. {
  542. GList *entries = NULL;
  543. entries = g_list_append (entries, menu_entry_create (_("&Listing mode..."), CK_ListingCmd));
  544. entries = g_list_append (entries, menu_entry_create (_("&Quick view"), CK_MenuQuickViewCmd));
  545. entries = g_list_append (entries, menu_entry_create (_("&Info" ), CK_MenuInfoCmd));
  546. entries = g_list_append (entries, menu_entry_create (_("&Tree"), CK_TreeCmd));
  547. entries = g_list_append (entries, menu_separator_create ());
  548. entries = g_list_append (entries, menu_entry_create (_("&Sort order..."), CK_Sort));
  549. entries = g_list_append (entries, menu_separator_create ());
  550. entries = g_list_append (entries, menu_entry_create (_("&Filter..."), CK_FilterCmd));
  551. #ifdef HAVE_CHARSET
  552. entries = g_list_append (entries, menu_separator_create ());
  553. entries = g_list_append (entries, menu_entry_create (_("&Encoding..."), CK_PanelSetPanelEncoding));
  554. #endif
  555. #ifdef USE_NETCODE
  556. entries = g_list_append (entries, menu_separator_create ());
  557. #ifdef ENABLE_VFS_MCFS
  558. entries = g_list_append (entries, menu_entry_create (_("&Network link..."), CK_NetlinkCmd));
  559. #endif
  560. entries = g_list_append (entries, menu_entry_create (_("FT&P link..."), CK_FtplinkCmd));
  561. entries = g_list_append (entries, menu_entry_create (_("S&hell link..."), CK_FishlinkCmd));
  562. #ifdef WITH_SMBFS
  563. entries = g_list_append (entries, menu_entry_create (_("SM&B link..."), CK_SmblinkCmd));
  564. #endif
  565. #endif
  566. entries = g_list_append (entries, menu_separator_create ());
  567. entries = g_list_append (entries, menu_entry_create (_("&Rescan"), CK_RereadCmd));
  568. return entries;
  569. }
  570. static GList *
  571. create_file_menu (void)
  572. {
  573. GList *entries = NULL;
  574. entries = g_list_append (entries, menu_entry_create (_("&View"), CK_ViewCmd));
  575. entries = g_list_append (entries, menu_entry_create (_("Vie&w file..."), CK_ViewFileCmd));
  576. entries = g_list_append (entries, menu_entry_create (_("&Filtered view"), CK_FilteredViewCmd));
  577. entries = g_list_append (entries, menu_entry_create (_("&Edit"), CK_EditCmd));
  578. entries = g_list_append (entries, menu_entry_create (_("&Copy"), CK_CopyCmd));
  579. entries = g_list_append (entries, menu_entry_create (_("C&hmod"), CK_ChmodCmd));
  580. entries = g_list_append (entries, menu_entry_create (_("&Link"), CK_LinkCmd));
  581. entries = g_list_append (entries, menu_entry_create (_("&SymLink"), CK_SymlinkCmd));
  582. entries = g_list_append (entries, menu_entry_create (_("Edit s&ymlink"), CK_EditSymlinkCmd));
  583. entries = g_list_append (entries, menu_entry_create (_("Ch&own"), CK_ChownCmd));
  584. entries = g_list_append (entries, menu_entry_create (_("&Advanced chown"), CK_ChownAdvancedCmd));
  585. entries = g_list_append (entries, menu_entry_create (_("&Rename/Move"), CK_RenameCmd));
  586. entries = g_list_append (entries, menu_entry_create (_("&Mkdir"), CK_MkdirCmd));
  587. entries = g_list_append (entries, menu_entry_create (_("&Delete"), CK_DeleteCmd));
  588. entries = g_list_append (entries, menu_entry_create (_("&Quick cd"), CK_QuickCdCmd));
  589. entries = g_list_append (entries, menu_separator_create ());
  590. entries = g_list_append (entries, menu_entry_create (_("Select &group"), CK_SelectCmd));
  591. entries = g_list_append (entries, menu_entry_create (_("U&nselect group"), CK_UnselectCmd));
  592. entries = g_list_append (entries, menu_entry_create (_("Reverse selec&tion"), CK_ReverseSelectionCmd));
  593. entries = g_list_append (entries, menu_separator_create ());
  594. entries = g_list_append (entries, menu_entry_create (_("E&xit"), CK_QuitCmd));
  595. return entries;
  596. }
  597. static GList *
  598. create_command_menu (void)
  599. {
  600. /* I know, I'm lazy, but the tree widget when it's not running
  601. * as a panel still has some problems, I have not yet finished
  602. * the WTree widget port, sorry.
  603. */
  604. GList *entries = NULL;
  605. entries = g_list_append (entries, menu_entry_create (_("&User menu"), CK_UserMenuCmd));
  606. entries = g_list_append (entries, menu_entry_create (_("&Directory tree"), CK_TreeBoxCmd));
  607. entries = g_list_append (entries, menu_entry_create (_("&Find file"), CK_FindCmd));
  608. entries = g_list_append (entries, menu_entry_create (_("S&wap panels"), CK_SwapCmd));
  609. entries = g_list_append (entries, menu_entry_create (_("Switch &panels on/off"), CK_ShowCommandLine));
  610. entries = g_list_append (entries, menu_entry_create (_("&Compare directories"), CK_CompareDirsCmd));
  611. entries = g_list_append (entries, menu_entry_create (_("E&xternal panelize"), CK_ExternalPanelize));
  612. entries = g_list_append (entries, menu_entry_create (_("Show directory s&izes"), CK_SingleDirsizeCmd));
  613. entries = g_list_append (entries, menu_separator_create ());
  614. entries = g_list_append (entries, menu_entry_create (_("Command &history"), CK_HistoryCmd));
  615. entries = g_list_append (entries, menu_entry_create (_("Di&rectory hotlist"), CK_QuickChdirCmd));
  616. #ifdef USE_VFS
  617. entries = g_list_append (entries, menu_entry_create (_("&Active VFS list"), CK_ReselectVfs));
  618. #endif
  619. #ifdef WITH_BACKGROUND
  620. entries = g_list_append (entries, menu_entry_create (_("&Background jobs"), CK_JobsCmd));
  621. #endif
  622. entries = g_list_append (entries, menu_separator_create ());
  623. #ifdef USE_EXT2FSLIB
  624. entries = g_list_append (entries, menu_entry_create (_("&Undelete files (ext2fs only)"), CK_UndeleteCmd));
  625. #endif
  626. #ifdef LISTMODE_EDITOR
  627. entries = g_list_append (entries, menu_entry_create (_("&Listing format edit"), CK_ListmodeCmd));
  628. #endif
  629. #if defined (USE_EXT2FSLIB) || defined (LISTMODE_EDITOR)
  630. entries = g_list_append (entries, menu_separator_create ());
  631. #endif
  632. entries = g_list_append (entries, menu_entry_create (_("Edit &extension file"), CK_EditExtFileCmd));
  633. entries = g_list_append (entries, menu_entry_create (_("Edit &menu file"), CK_EditMcMenuCmd));
  634. entries = g_list_append (entries, menu_entry_create (_("Edit hi&ghlighting group file"), CK_EditFhlFileCmd));
  635. return entries;
  636. }
  637. static GList *
  638. create_options_menu (void)
  639. {
  640. GList *entries = NULL;
  641. entries = g_list_append (entries, menu_entry_create (_("&Configuration..."), CK_ConfigureBox));
  642. entries = g_list_append (entries, menu_entry_create (_("&Layout..."), CK_LayoutCmd));
  643. entries = g_list_append (entries, menu_entry_create (_("C&onfirmation..."), CK_ConfirmBox));
  644. entries = g_list_append (entries, menu_entry_create (_("&Display bits..."), CK_DisplayBitsBox));
  645. entries = g_list_append (entries, menu_entry_create (_("Learn &keys..."), CK_LearnKeys));
  646. #ifdef USE_VFS
  647. entries = g_list_append (entries, menu_entry_create (_("&Virtual FS..."), CK_ConfigureVfs));
  648. #endif
  649. entries = g_list_append (entries, menu_separator_create ());
  650. entries = g_list_append (entries, menu_entry_create (_("&Save setup"), CK_SaveSetupCmd));
  651. return entries;
  652. }
  653. void
  654. init_menu (void)
  655. {
  656. menubar_add_menu (the_menubar,
  657. create_menu (horizontal_split ? _("&Above") : _("&Left"),
  658. create_panel_menu (), "[Left and Right Menus]"));
  659. menubar_add_menu (the_menubar,
  660. create_menu (_("&File"), create_file_menu (), "[File Menu]"));
  661. menubar_add_menu (the_menubar,
  662. create_menu (_("&Command"), create_command_menu (), "[Command Menu]"));
  663. menubar_add_menu (the_menubar,
  664. create_menu (_("&Options"), create_options_menu (), "[Options Menu]"));
  665. menubar_add_menu (the_menubar,
  666. create_menu (horizontal_split ? _("&Below") : _("&Right"),
  667. create_panel_menu (), "[Left and Right Menus]"));
  668. }
  669. void
  670. done_menu (void)
  671. {
  672. menubar_set_menu (the_menubar, NULL);
  673. }
  674. static void
  675. menu_last_selected_cmd (void)
  676. {
  677. the_menubar->is_active = TRUE;
  678. the_menubar->is_dropped = (drop_menus != 0);
  679. the_menubar->previous_widget = midnight_dlg->current->dlg_id;
  680. dlg_select_widget (the_menubar);
  681. }
  682. static void
  683. menu_cmd (void)
  684. {
  685. if (the_menubar->is_active)
  686. return;
  687. if ((get_current_index () == 0) == (current_panel->active != 0))
  688. the_menubar->selected = 0;
  689. else
  690. the_menubar->selected = g_list_length (the_menubar->menu) - 1;
  691. menu_last_selected_cmd ();
  692. }
  693. static char *
  694. midnight_get_shortcut (unsigned long command)
  695. {
  696. const char *ext_map;
  697. const char *shortcut = NULL;
  698. ext_map = lookup_keymap_shortcut (main_map, CK_StartExtMap1);
  699. if (ext_map != NULL)
  700. shortcut = lookup_keymap_shortcut (main_x_map, command);
  701. if (shortcut != NULL)
  702. return g_strdup_printf ("%s %s", ext_map, shortcut);
  703. shortcut = lookup_keymap_shortcut (main_map, command);
  704. if (shortcut != NULL)
  705. return g_strdup (shortcut);
  706. shortcut = lookup_keymap_shortcut (panel_map, command);
  707. if (shortcut != NULL)
  708. return g_strdup (shortcut);
  709. return NULL;
  710. }
  711. /* Flag toggling functions */
  712. void
  713. toggle_fast_reload (void)
  714. {
  715. fast_reload = !fast_reload;
  716. if (fast_reload_w == 0 && fast_reload) {
  717. message (D_NORMAL, _(" Information "),
  718. _
  719. (" Using the fast reload option may not reflect the exact \n"
  720. " directory contents. In this case you'll need to do a \n"
  721. " manual reload of the directory. See the man page for \n"
  722. " the details. "));
  723. fast_reload_w = 1;
  724. }
  725. }
  726. void
  727. toggle_mix_all_files (void)
  728. {
  729. mix_all_files = !mix_all_files;
  730. update_panels (UP_RELOAD, UP_KEEPSEL);
  731. }
  732. void
  733. toggle_show_backup (void)
  734. {
  735. show_backups = !show_backups;
  736. update_panels (UP_RELOAD, UP_KEEPSEL);
  737. }
  738. void
  739. toggle_show_hidden (void)
  740. {
  741. show_dot_files = !show_dot_files;
  742. update_panels (UP_RELOAD, UP_KEEPSEL);
  743. }
  744. void
  745. toggle_kilobyte_si (void)
  746. {
  747. kilobyte_si = !kilobyte_si;
  748. update_panels (UP_RELOAD, UP_KEEPSEL);
  749. }
  750. /*
  751. * Just a hack for allowing url-like pathnames to be accepted from the
  752. * command line.
  753. */
  754. static void
  755. translated_mc_chdir (char *dir)
  756. {
  757. char *newdir;
  758. newdir = vfs_translate_url (dir);
  759. mc_chdir (newdir);
  760. g_free (newdir);
  761. }
  762. static void
  763. create_panels (void)
  764. {
  765. int current_index;
  766. int other_index;
  767. int current_mode;
  768. int other_mode;
  769. char original_dir[1024];
  770. original_dir[0] = 0;
  771. if (boot_current_is_left) {
  772. current_index = 0;
  773. other_index = 1;
  774. current_mode = startup_left_mode;
  775. other_mode = startup_right_mode;
  776. } else {
  777. current_index = 1;
  778. other_index = 0;
  779. current_mode = startup_right_mode;
  780. other_mode = startup_left_mode;
  781. }
  782. /* Creates the left panel */
  783. if (this_dir) {
  784. if (other_dir) {
  785. /* Ok, user has specified two dirs, save the original one,
  786. * since we may not be able to chdir to the proper
  787. * second directory later
  788. */
  789. mc_get_current_wd (original_dir, sizeof (original_dir) - 2);
  790. }
  791. translated_mc_chdir (this_dir);
  792. }
  793. set_display_type (current_index, current_mode);
  794. /* The other panel */
  795. if (other_dir) {
  796. if (original_dir[0])
  797. translated_mc_chdir (original_dir);
  798. translated_mc_chdir (other_dir);
  799. }
  800. set_display_type (other_index, other_mode);
  801. if (startup_left_mode == view_listing) {
  802. current_panel = left_panel;
  803. } else {
  804. if (right_panel)
  805. current_panel = right_panel;
  806. else
  807. current_panel = left_panel;
  808. }
  809. /* Create the nice widgets */
  810. cmdline = command_new (0, 0, 0);
  811. the_prompt = label_new (0, 0, prompt);
  812. the_prompt->transparent = 1;
  813. the_bar = buttonbar_new (keybar_visible);
  814. the_hint = label_new (0, 0, 0);
  815. the_hint->transparent = 1;
  816. the_hint->auto_adjust_cols = 0;
  817. the_hint->widget.cols = COLS;
  818. the_menubar = menubar_new (0, 0, COLS, NULL);
  819. }
  820. static void
  821. copy_current_pathname (void)
  822. {
  823. char *cwd_path;
  824. if (!command_prompt)
  825. return;
  826. cwd_path = remove_encoding_from_path (current_panel->cwd);
  827. command_insert (cmdline, cwd_path, 0);
  828. if (cwd_path [strlen (cwd_path ) - 1] != PATH_SEP)
  829. command_insert (cmdline, PATH_SEP_STR, 0);
  830. g_free (cwd_path);
  831. }
  832. static void
  833. copy_other_pathname (void)
  834. {
  835. char *cwd_path;
  836. if (get_other_type () != view_listing)
  837. return;
  838. if (!command_prompt)
  839. return;
  840. cwd_path = remove_encoding_from_path (other_panel->cwd);
  841. command_insert (cmdline, cwd_path, 0);
  842. if (cwd_path [strlen (cwd_path ) - 1] != PATH_SEP)
  843. command_insert (cmdline, PATH_SEP_STR, 0);
  844. g_free (cwd_path);
  845. }
  846. static void
  847. copy_readlink (WPanel *panel)
  848. {
  849. if (!command_prompt)
  850. return;
  851. if (S_ISLNK (selection (panel)->st.st_mode)) {
  852. char buffer[MC_MAXPATHLEN];
  853. char *p =
  854. concat_dir_and_file (panel->cwd, selection (panel)->fname);
  855. int i;
  856. i = mc_readlink (p, buffer, MC_MAXPATHLEN - 1);
  857. g_free (p);
  858. if (i > 0) {
  859. buffer[i] = 0;
  860. command_insert (cmdline, buffer, 1);
  861. }
  862. }
  863. }
  864. static void
  865. copy_current_readlink (void)
  866. {
  867. copy_readlink (current_panel);
  868. }
  869. static void
  870. copy_other_readlink (void)
  871. {
  872. if (get_other_type () != view_listing)
  873. return;
  874. copy_readlink (other_panel);
  875. }
  876. /* Insert the selected file name into the input line */
  877. static void
  878. copy_prog_name (void)
  879. {
  880. char *tmp;
  881. if (!command_prompt)
  882. return;
  883. if (get_current_type () == view_tree) {
  884. WTree *tree = (WTree *) get_panel_widget (get_current_index ());
  885. tmp = tree_selected_name (tree);
  886. } else
  887. tmp = selection (current_panel)->fname;
  888. command_insert (cmdline, tmp, 1);
  889. }
  890. static void
  891. copy_tagged (WPanel *panel)
  892. {
  893. int i;
  894. if (!command_prompt)
  895. return;
  896. input_disable_update (cmdline);
  897. if (panel->marked) {
  898. for (i = 0; i < panel->count; i++) {
  899. if (panel->dir.list[i].f.marked)
  900. command_insert (cmdline, panel->dir.list[i].fname, 1);
  901. }
  902. } else {
  903. command_insert (cmdline, panel->dir.list[panel->selected].fname,
  904. 1);
  905. }
  906. input_enable_update (cmdline);
  907. }
  908. static void
  909. copy_current_tagged (void)
  910. {
  911. copy_tagged (current_panel);
  912. }
  913. static void
  914. copy_other_tagged (void)
  915. {
  916. if (get_other_type () != view_listing)
  917. return;
  918. copy_tagged (other_panel);
  919. }
  920. void
  921. midnight_set_buttonbar (WButtonBar *b)
  922. {
  923. buttonbar_set_label (b, 1, Q_("ButtonBar|Help"), main_map, NULL);
  924. buttonbar_set_label (b, 2, Q_("ButtonBar|Menu"), main_map, NULL);
  925. buttonbar_set_label (b, 3, Q_("ButtonBar|View"), main_map, NULL);
  926. buttonbar_set_label (b, 4, Q_("ButtonBar|Edit"), main_map, NULL);
  927. buttonbar_set_label (b, 5, Q_("ButtonBar|Copy"), main_map, NULL);
  928. buttonbar_set_label (b, 6, Q_("ButtonBar|RenMov"), main_map, NULL);
  929. buttonbar_set_label (b, 7, Q_("ButtonBar|Mkdir"), main_map, NULL);
  930. buttonbar_set_label (b, 8, Q_("ButtonBar|Delete"), main_map, NULL);
  931. buttonbar_set_label (b, 9, Q_("ButtonBar|PullDn"), main_map, NULL);
  932. buttonbar_set_label (b, 10, Q_("ButtonBar|Quit"), main_map, NULL);
  933. }
  934. static gboolean ctl_x_map_enabled = FALSE;
  935. static void
  936. ctl_x_cmd (void)
  937. {
  938. ctl_x_map_enabled = TRUE;
  939. }
  940. static cb_ret_t
  941. midnight_execute_cmd (Widget *sender, unsigned long command)
  942. {
  943. cb_ret_t res = MSG_HANDLED;
  944. (void) sender;
  945. switch (command) {
  946. case CK_AddHotlist:
  947. add2hotlist_cmd ();
  948. break;
  949. case CK_ChmodCmd:
  950. chmod_cmd ();
  951. break;
  952. case CK_ChownCmd:
  953. chown_cmd ();
  954. break;
  955. case CK_ChownAdvancedCmd:
  956. chown_advanced_cmd ();
  957. break;
  958. case CK_CompareDirsCmd:
  959. compare_dirs_cmd ();
  960. break;
  961. case CK_ConfigureBox:
  962. configure_box ();
  963. break;
  964. #ifdef USE_VFS
  965. case CK_ConfigureVfs:
  966. configure_vfs ();
  967. break;
  968. #endif
  969. case CK_ConfirmBox:
  970. confirm_box ();
  971. break;
  972. case CK_CopyCmd:
  973. copy_cmd ();
  974. break;
  975. case CK_CopyCurrentPathname:
  976. copy_current_pathname ();
  977. break;
  978. case CK_CopyCurrentReadlink:
  979. copy_current_readlink ();
  980. break;
  981. case CK_CopyCurrentTagged:
  982. copy_current_tagged ();
  983. break;
  984. case CK_CopyOtherPathname:
  985. copy_other_pathname ();
  986. break;
  987. case CK_CopyOtherReadlink:
  988. copy_other_readlink ();
  989. break;
  990. case CK_CopyOtherTagged:
  991. copy_other_tagged ();
  992. break;
  993. case CK_DeleteCmd:
  994. delete_cmd ();
  995. break;
  996. case CK_DisplayBitsBox:
  997. display_bits_box ();
  998. break;
  999. case CK_EditCmd:
  1000. edit_cmd ();
  1001. break;
  1002. case CK_EditExtFileCmd:
  1003. ext_cmd ();
  1004. break;
  1005. case CK_EditFhlFileCmd:
  1006. edit_fhl_cmd ();
  1007. break;
  1008. case CK_EditMcMenuCmd:
  1009. edit_mc_menu_cmd ();
  1010. break;
  1011. case CK_EditSymlinkCmd:
  1012. edit_symlink_cmd ();
  1013. break;
  1014. case CK_ExternalPanelize:
  1015. external_panelize ();
  1016. break;
  1017. case CK_FilterCmd:
  1018. filter_cmd ();
  1019. break;
  1020. case CK_FilteredViewCmd:
  1021. filtered_view_cmd ();
  1022. break;
  1023. case CK_FindCmd:
  1024. find_cmd ();
  1025. break;
  1026. #if defined (USE_NETCODE)
  1027. case CK_FishlinkCmd:
  1028. fishlink_cmd ();
  1029. break;
  1030. case CK_FtplinkCmd:
  1031. ftplink_cmd ();
  1032. break;
  1033. #endif
  1034. case CK_HelpCmd:
  1035. help_cmd ();
  1036. break;
  1037. case CK_HistoryCmd:
  1038. history_cmd ();
  1039. break;
  1040. case CK_InfoCmd:
  1041. info_cmd_no_menu ();
  1042. break;
  1043. #ifdef WITH_BACKGROUND
  1044. case CK_JobsCmd:
  1045. jobs_cmd ();
  1046. break;
  1047. #endif
  1048. case CK_LayoutCmd:
  1049. layout_cmd ();
  1050. break;
  1051. case CK_LearnKeys:
  1052. learn_keys ();
  1053. break;
  1054. case CK_LinkCmd:
  1055. link_cmd ();
  1056. break;
  1057. case CK_ListingCmd:
  1058. listing_cmd ();
  1059. break;
  1060. #ifdef LISTMODE_EDITOR
  1061. case CK_ListmodeCmd:
  1062. listmode_cmd ();
  1063. break;
  1064. #endif
  1065. case CK_MenuCmd:
  1066. menu_cmd ();
  1067. break;
  1068. case CK_MenuInfoCmd:
  1069. info_cmd ();
  1070. break;
  1071. case CK_MenuLastSelectedCmd:
  1072. menu_last_selected_cmd ();
  1073. break;
  1074. case CK_MenuQuickViewCmd:
  1075. quick_view_cmd ();
  1076. break;
  1077. case CK_MkdirCmd:
  1078. mkdir_cmd ();
  1079. break;
  1080. #if defined (USE_NETCODE) && defined (ENABLE_VFS_MCFS)
  1081. case CK_NetlinkCmd:
  1082. netlink_cmd ();
  1083. break;
  1084. #endif
  1085. #ifdef HAVE_CHARSET
  1086. case CK_PanelSetPanelEncoding:
  1087. encoding_cmd ();
  1088. break;
  1089. #endif
  1090. case CK_QuickCdCmd:
  1091. quick_cd_cmd ();
  1092. break;
  1093. case CK_QuickChdirCmd:
  1094. quick_chdir_cmd ();
  1095. break;
  1096. case CK_QuickViewCmd:
  1097. quick_cmd_no_menu ();
  1098. break;
  1099. case CK_QuietQuitCmd:
  1100. quiet_quit_cmd ();
  1101. break;
  1102. case CK_QuitCmd:
  1103. quit_cmd ();
  1104. break;
  1105. case CK_RenameCmd:
  1106. rename_cmd ();
  1107. break;
  1108. case CK_RereadCmd:
  1109. reread_cmd ();
  1110. break;
  1111. #ifdef USE_VFS
  1112. case CK_ReselectVfs:
  1113. reselect_vfs ();
  1114. break;
  1115. #endif
  1116. case CK_ReverseSelectionCmd:
  1117. reverse_selection_cmd ();
  1118. break;
  1119. case CK_SaveSetupCmd:
  1120. save_setup_cmd ();
  1121. break;
  1122. case CK_SelectCmd:
  1123. select_cmd ();
  1124. break;
  1125. case CK_ShowCommandLine:
  1126. view_other_cmd ();
  1127. break;
  1128. case CK_SingleDirsizeCmd:
  1129. smart_dirsize_cmd ();
  1130. break;
  1131. #if defined (USE_NETCODE) && defined (WITH_SMBFS)
  1132. case CK_SmblinkCmd:
  1133. smblink_cmd ();
  1134. break;
  1135. #endif
  1136. case CK_Sort:
  1137. sort_cmd ();
  1138. break;
  1139. case CK_StartExtMap1:
  1140. ctl_x_cmd ();
  1141. break;
  1142. case CK_SuspendCmd:
  1143. suspend_cmd ();
  1144. break;
  1145. case CK_SwapCmd:
  1146. swap_cmd ();
  1147. break;
  1148. case CK_SymlinkCmd:
  1149. symlink_cmd ();
  1150. break;
  1151. case CK_ToggleListingCmd:
  1152. toggle_listing_cmd ();
  1153. break;
  1154. case CK_ToggleShowHidden:
  1155. toggle_show_hidden ();
  1156. break;
  1157. case CK_TreeCmd:
  1158. tree_cmd ();
  1159. break;
  1160. case CK_TreeBoxCmd:
  1161. treebox_cmd ();
  1162. break;
  1163. #ifdef USE_EXT2FSLIB
  1164. case CK_UndeleteCmd:
  1165. undelete_cmd ();
  1166. break;
  1167. #endif
  1168. case CK_UnselectCmd:
  1169. unselect_cmd ();
  1170. break;
  1171. case CK_UserMenuCmd:
  1172. user_file_menu_cmd ();
  1173. break;
  1174. case CK_ViewCmd:
  1175. view_cmd ();
  1176. break;
  1177. case CK_ViewFileCmd:
  1178. view_file_cmd ();
  1179. break;
  1180. default:
  1181. res = MSG_NOT_HANDLED;
  1182. }
  1183. return res;
  1184. }
  1185. static void
  1186. setup_pre (void)
  1187. {
  1188. /* Call all the inits */
  1189. #ifdef HAVE_SLANG
  1190. tty_display_8bit (full_eight_bits != 0);
  1191. #else
  1192. tty_display_8bit (eight_bit_clean != 0);
  1193. #endif
  1194. }
  1195. static void
  1196. init_xterm_support (void)
  1197. {
  1198. const char *termvalue;
  1199. termvalue = getenv ("TERM");
  1200. if (!termvalue || !(*termvalue)) {
  1201. fputs (_("The TERM environment variable is unset!\n"), stderr);
  1202. exit (1);
  1203. }
  1204. /* Check mouse capabilities */
  1205. xmouse_seq = tty_tgetstr ("Km");
  1206. if (strcmp (termvalue, "cygwin") == 0) {
  1207. mc_args__force_xterm = 1;
  1208. use_mouse_p = MOUSE_DISABLED;
  1209. }
  1210. if (mc_args__force_xterm || strncmp (termvalue, "xterm", 5) == 0
  1211. || strncmp (termvalue, "konsole", 7) == 0
  1212. || strncmp (termvalue, "rxvt", 4) == 0
  1213. || strcmp (termvalue, "Eterm") == 0
  1214. || strcmp (termvalue, "dtterm") == 0) {
  1215. xterm_flag = 1;
  1216. /* Default to the standard xterm sequence */
  1217. if (!xmouse_seq) {
  1218. xmouse_seq = ESC_STR "[M";
  1219. }
  1220. /* Enable mouse unless explicitly disabled by --nomouse */
  1221. if (use_mouse_p != MOUSE_DISABLED) {
  1222. const char *color_term = getenv ("COLORTERM");
  1223. if (strncmp (termvalue, "rxvt", 4) == 0 ||
  1224. (color_term != NULL && strncmp (color_term, "rxvt", 4) == 0) ||
  1225. strcmp (termvalue, "Eterm") == 0) {
  1226. use_mouse_p = MOUSE_XTERM_NORMAL_TRACKING;
  1227. } else {
  1228. use_mouse_p = MOUSE_XTERM_BUTTON_EVENT_TRACKING;
  1229. }
  1230. }
  1231. }
  1232. }
  1233. static void
  1234. setup_mc (void)
  1235. {
  1236. setup_pre ();
  1237. create_panels ();
  1238. setup_panels ();
  1239. #ifdef HAVE_SUBSHELL_SUPPORT
  1240. if (use_subshell)
  1241. add_select_channel (subshell_pty, load_prompt, 0);
  1242. #endif /* !HAVE_SUBSHELL_SUPPORT */
  1243. tty_setup_sigwinch (sigwinch_handler);
  1244. verbose = !((tty_baudrate () < 9600) || tty_is_slow ());
  1245. init_xterm_support ();
  1246. init_mouse ();
  1247. }
  1248. static void
  1249. setup_dummy_mc (void)
  1250. {
  1251. char d[MC_MAXPATHLEN];
  1252. mc_get_current_wd (d, MC_MAXPATHLEN);
  1253. setup_mc ();
  1254. mc_chdir (d);
  1255. }
  1256. static void check_codeset()
  1257. {
  1258. const char *_system_codepage = NULL;
  1259. #ifdef HAVE_CHARSET
  1260. const char *_source_codepage = NULL;
  1261. const char *_display_codepage = NULL;
  1262. int profile_changed = 0;
  1263. #define CONFY 16
  1264. #define CONFX 54
  1265. if ( !skip_check_codeset ) {
  1266. QuickWidget ecs_widgets [] = {
  1267. QUICK_BUTTON (4, 6, 13, CONFY, N_("&Skip"), B_EXIT, NULL),
  1268. QUICK_BUTTON (1, 11, 13, CONFY, N_("&Fix it"), B_ENTER, NULL),
  1269. QUICK_CHECKBOX (1, 13, 11, CONFY, N_("don't ask again"), &skip_check_codeset),
  1270. QUICK_LABEL (2, 30, 3, CONFY, N_("Chosen display charset (Settings->Display bits)\n"
  1271. "or source codeset (in mcedit ctrl-t) \n"
  1272. "does not match one set via locale. \n"
  1273. "Set correct codeset manually or press <<Fix it>> \n"
  1274. "to set locale default.\n\n"
  1275. "Or set \'don't ask again\' and press <<Skip>>")),
  1276. QUICK_END
  1277. };
  1278. QuickDialog ecs =
  1279. {
  1280. CONFX, CONFY, -1, -1, N_(" Confirmation "),
  1281. "[Confirmation]", ecs_widgets, FALSE
  1282. };
  1283. _system_codepage = str_detect_termencoding();
  1284. _source_codepage = get_codepage_id (source_codepage);
  1285. _display_codepage = get_codepage_id (display_codepage);
  1286. if ( (strcmp (_system_codepage, _display_codepage)) ||
  1287. (strcmp (_system_codepage, _source_codepage)) ) {
  1288. if (quick_dialog (&ecs) == B_ENTER){
  1289. display_codepage = get_codepage_index (_system_codepage);
  1290. cp_display = get_codepage_id (display_codepage);
  1291. if ( !strcmp (cp_display, _system_codepage)) {
  1292. mc_config_set_string(mc_main_config, "Misc", "display_codepage", cp_display);
  1293. mc_config_set_string(mc_main_config, "Misc", "source_codepage", cp_display);
  1294. display_codepage = get_codepage_index ( cp_display );
  1295. utf8_display = str_isutf8 (_system_codepage);
  1296. source_codepage = display_codepage;
  1297. cp_source = cp_display;
  1298. profile_changed = 1;
  1299. } else {
  1300. utf8_display = str_isutf8 (_system_codepage);
  1301. cp_source = cp_display = _system_codepage;
  1302. }
  1303. } else {
  1304. if ( skip_check_codeset ) {
  1305. mc_config_set_int(mc_main_config, "Midnight-Commander", "skip_check_codeset", 1);
  1306. profile_changed = 1;
  1307. }
  1308. }
  1309. }
  1310. if ( profile_changed )
  1311. save_configure ();
  1312. }
  1313. #else /* HAVE_CHARSET */
  1314. _system_codepage = str_detect_termencoding();
  1315. utf8_display = str_isutf8 (_system_codepage);
  1316. #endif /* HAVE_CHARSET */
  1317. }
  1318. static void
  1319. done_screen (void)
  1320. {
  1321. if (!(quit & SUBSHELL_EXIT))
  1322. clr_scr ();
  1323. tty_reset_shell_mode ();
  1324. tty_noraw_mode ();
  1325. tty_keypad (FALSE);
  1326. tty_colors_done ();
  1327. }
  1328. static void
  1329. done_mc (void)
  1330. {
  1331. disable_mouse ();
  1332. done_menu ();
  1333. /* Setup shutdown
  1334. *
  1335. * We sync the profiles since the hotlist may have changed, while
  1336. * we only change the setup data if we have the auto save feature set
  1337. */
  1338. if (auto_save_setup)
  1339. save_setup (); /* does also call save_hotlist */
  1340. else {
  1341. save_hotlist ();
  1342. save_panel_types ();
  1343. }
  1344. done_screen ();
  1345. vfs_add_current_stamps ();
  1346. }
  1347. /* This should be called after destroy_dlg since panel widgets
  1348. * save their state on the profiles
  1349. */
  1350. static void
  1351. done_mc_profile (void)
  1352. {
  1353. done_setup ();
  1354. }
  1355. static cb_ret_t
  1356. midnight_callback (Dlg_head *h, Widget *sender,
  1357. dlg_msg_t msg, int parm, void *data)
  1358. {
  1359. unsigned long command;
  1360. switch (msg) {
  1361. case DLG_DRAW:
  1362. load_hint (1);
  1363. /* We handle the special case of the output lines */
  1364. if (console_flag && output_lines)
  1365. show_console_contents (output_start_y,
  1366. LINES - output_lines - keybar_visible -
  1367. 1, LINES - keybar_visible - 1);
  1368. return MSG_HANDLED;
  1369. case DLG_IDLE:
  1370. /* We only need the first idle event to show user menu after start */
  1371. set_idle_proc (h, 0);
  1372. if (auto_menu)
  1373. midnight_execute_cmd (NULL, CK_UserMenuCmd);
  1374. return MSG_HANDLED;
  1375. case DLG_KEY:
  1376. if (ctl_x_map_enabled) {
  1377. ctl_x_map_enabled = FALSE;
  1378. command = lookup_keymap_command (main_x_map, parm);
  1379. if (command != CK_Ignore_Key)
  1380. return midnight_execute_cmd (NULL, command);
  1381. }
  1382. /* FIXME: should handle all menu shortcuts before this point */
  1383. if (the_menubar->is_active)
  1384. return MSG_NOT_HANDLED;
  1385. if (parm == '\t')
  1386. free_completions (cmdline);
  1387. if (parm == '\n') {
  1388. size_t i;
  1389. for (i = 0; cmdline->buffer[i] && (cmdline->buffer[i] == ' ' ||
  1390. cmdline->buffer[i] == '\t'); i++)
  1391. ;
  1392. if (cmdline->buffer[i]) {
  1393. send_message ((Widget *) cmdline, WIDGET_KEY, parm);
  1394. return MSG_HANDLED;
  1395. }
  1396. stuff (cmdline, "", 0);
  1397. cmdline->point = 0;
  1398. }
  1399. /* Ctrl-Enter and Alt-Enter */
  1400. if (((parm & ~(KEY_M_CTRL | KEY_M_ALT)) == '\n')
  1401. && (parm & (KEY_M_CTRL | KEY_M_ALT))) {
  1402. copy_prog_name ();
  1403. return MSG_HANDLED;
  1404. }
  1405. /* Ctrl-Shift-Enter */
  1406. if (parm == (KEY_M_CTRL | KEY_M_SHIFT | '\n')) {
  1407. copy_current_pathname ();
  1408. copy_prog_name ();
  1409. return MSG_HANDLED;
  1410. }
  1411. if ((!alternate_plus_minus || !(console_flag || xterm_flag))
  1412. && !quote && !current_panel->searching) {
  1413. if (!only_leading_plus_minus) {
  1414. /* Special treatement, since the input line will eat them */
  1415. if (parm == '+') {
  1416. select_cmd ();
  1417. return MSG_HANDLED;
  1418. }
  1419. if (parm == '\\' || parm == '-') {
  1420. unselect_cmd ();
  1421. return MSG_HANDLED;
  1422. }
  1423. if (parm == '*') {
  1424. reverse_selection_cmd ();
  1425. return MSG_HANDLED;
  1426. }
  1427. } else if (!command_prompt || !cmdline->buffer[0]) {
  1428. /* Special treatement '+', '-', '\', '*' only when this is
  1429. * first char on input line
  1430. */
  1431. if (parm == '+') {
  1432. select_cmd ();
  1433. return MSG_HANDLED;
  1434. }
  1435. if (parm == '\\' || parm == '-') {
  1436. unselect_cmd ();
  1437. return MSG_HANDLED;
  1438. }
  1439. if (parm == '*') {
  1440. reverse_selection_cmd ();
  1441. return MSG_HANDLED;
  1442. }
  1443. }
  1444. }
  1445. return MSG_NOT_HANDLED;
  1446. case DLG_HOTKEY_HANDLED:
  1447. if ((get_current_type () == view_listing) && current_panel->searching) {
  1448. current_panel->searching = 0;
  1449. current_panel->dirty = 1;
  1450. }
  1451. return MSG_HANDLED;
  1452. case DLG_UNHANDLED_KEY:
  1453. if (command_prompt) {
  1454. cb_ret_t v;
  1455. v = send_message ((Widget *) cmdline, WIDGET_KEY, parm);
  1456. if (v == MSG_HANDLED)
  1457. return MSG_HANDLED;
  1458. }
  1459. if (ctl_x_map_enabled) {
  1460. ctl_x_map_enabled = FALSE;
  1461. command = lookup_keymap_command (main_x_map, parm);
  1462. } else
  1463. command = lookup_keymap_command (main_map, parm);
  1464. return (command == CK_Ignore_Key)
  1465. ? MSG_NOT_HANDLED
  1466. : midnight_execute_cmd (NULL, command);
  1467. case DLG_POST_KEY:
  1468. if (!the_menubar->is_active)
  1469. update_dirty_panels ();
  1470. return MSG_HANDLED;
  1471. case DLG_ACTION:
  1472. /* shortcut */
  1473. if (sender == NULL)
  1474. midnight_execute_cmd (NULL, parm);
  1475. /* message from menu */
  1476. else if (sender == (Widget *) the_menubar)
  1477. midnight_execute_cmd (sender, parm);
  1478. /* message from buttonbar */
  1479. else if (sender == (Widget *) the_bar) {
  1480. if (data == NULL)
  1481. midnight_execute_cmd (sender, parm);
  1482. else
  1483. return send_message ((Widget *) data, WIDGET_COMMAND, parm);
  1484. }
  1485. return MSG_HANDLED;
  1486. default:
  1487. return default_dlg_callback (h, sender, msg, parm, data);
  1488. }
  1489. }
  1490. /* Show current directory in the xterm title */
  1491. void
  1492. update_xterm_title_path (void)
  1493. {
  1494. const char *path;
  1495. char host[BUF_TINY];
  1496. char *p;
  1497. struct passwd *pw = NULL;
  1498. char *login = NULL;
  1499. int res = 0;
  1500. if (xterm_flag && xterm_title) {
  1501. path = strip_home_and_password (current_panel->cwd);
  1502. res = gethostname(host, sizeof (host));
  1503. if ( res ) { /* On success, res = 0 */
  1504. host[0] = '\0';
  1505. } else {
  1506. host[sizeof (host) - 1] = '\0';
  1507. }
  1508. pw = getpwuid(getuid());
  1509. if ( pw ) {
  1510. login = g_strdup_printf ("%s@%s", pw->pw_name, host);
  1511. } else {
  1512. login = g_strdup (host);
  1513. }
  1514. p = g_strdup_printf ("mc [%s]:%s", login, path);
  1515. fprintf (stdout, "\33]0;%s\7", str_term_form (p));
  1516. g_free (login);
  1517. g_free (p);
  1518. if (!alternate_plus_minus)
  1519. numeric_keypad_mode ();
  1520. fflush (stdout);
  1521. }
  1522. }
  1523. /*
  1524. * Load new hint and display it.
  1525. * IF force is not 0, ignore the timeout.
  1526. */
  1527. void
  1528. load_hint (int force)
  1529. {
  1530. char *hint;
  1531. if (!the_hint->widget.parent)
  1532. return;
  1533. if (!message_visible) {
  1534. label_set_text (the_hint, NULL);
  1535. return;
  1536. }
  1537. hint = get_random_hint (force);
  1538. if (hint != NULL) {
  1539. if (*hint)
  1540. set_hintbar (hint);
  1541. g_free (hint);
  1542. } else {
  1543. char text[BUF_SMALL];
  1544. g_snprintf (text, sizeof (text), _("GNU Midnight Commander %s\n"),
  1545. VERSION);
  1546. set_hintbar (text);
  1547. }
  1548. }
  1549. static void
  1550. setup_panels_and_run_mc (void)
  1551. {
  1552. midnight_dlg->get_shortcut = midnight_get_shortcut;
  1553. add_widget (midnight_dlg, the_menubar);
  1554. init_menu ();
  1555. add_widget (midnight_dlg, get_panel_widget (0));
  1556. add_widget (midnight_dlg, get_panel_widget (1));
  1557. add_widget (midnight_dlg, the_hint);
  1558. add_widget (midnight_dlg, cmdline);
  1559. add_widget (midnight_dlg, the_prompt);
  1560. add_widget (midnight_dlg, the_bar);
  1561. midnight_set_buttonbar (the_bar);
  1562. if (boot_current_is_left)
  1563. dlg_select_widget (get_panel_widget (0));
  1564. else
  1565. dlg_select_widget (get_panel_widget (1));
  1566. /* Run the Midnight Commander if no file was specified in the command line */
  1567. run_dlg (midnight_dlg);
  1568. }
  1569. /* result must be free'd (I think this should go in util.c) */
  1570. static char *
  1571. prepend_cwd_on_local (const char *filename)
  1572. {
  1573. char *d;
  1574. int l;
  1575. if (vfs_file_is_local (filename)) {
  1576. if (*filename == PATH_SEP) /* an absolute pathname */
  1577. return g_strdup (filename);
  1578. d = g_malloc (MC_MAXPATHLEN + strlen (filename) + 2);
  1579. mc_get_current_wd (d, MC_MAXPATHLEN);
  1580. l = strlen (d);
  1581. d[l++] = PATH_SEP;
  1582. strcpy (d + l, filename);
  1583. canonicalize_pathname (d);
  1584. return d;
  1585. } else
  1586. return g_strdup (filename);
  1587. }
  1588. static int
  1589. mc_maybe_editor_or_viewer (void)
  1590. {
  1591. if (!(view_one_file || edit_one_file))
  1592. return 0;
  1593. /* Invoke the internal view/edit routine with:
  1594. * the default processing and forcing the internal viewer/editor
  1595. */
  1596. if (view_one_file) {
  1597. char *path = NULL;
  1598. path = prepend_cwd_on_local (view_one_file);
  1599. view_file (path, 0, 1);
  1600. g_free (path);
  1601. }
  1602. #ifdef USE_INTERNAL_EDIT
  1603. else {
  1604. edit_file (edit_one_file, edit_one_file_start_line);
  1605. }
  1606. #endif /* USE_INTERNAL_EDIT */
  1607. midnight_shutdown = 1;
  1608. done_mc ();
  1609. return 1;
  1610. }
  1611. /* Run the main dialog that occupies the whole screen */
  1612. static void
  1613. do_nc (void)
  1614. {
  1615. int midnight_colors[DLG_COLOR_NUM];
  1616. midnight_colors[0] = mc_skin_color_get("dialog", "_default_");
  1617. midnight_colors[1] = mc_skin_color_get("dialog", "focus");
  1618. midnight_colors[2] = mc_skin_color_get("dialog", "hotnormal");
  1619. midnight_colors[3] = mc_skin_color_get("dialog", "hotfocus");
  1620. panel_init ();
  1621. midnight_dlg = create_dlg (0, 0, LINES, COLS, midnight_colors, midnight_callback,
  1622. "[main]", NULL, DLG_WANT_IDLE);
  1623. if (view_one_file || edit_one_file)
  1624. setup_dummy_mc ();
  1625. else
  1626. setup_mc ();
  1627. /* start check display_codepage and source_codepage */
  1628. check_codeset ();
  1629. main_map = default_main_map;
  1630. if (main_keymap && main_keymap->len > 0)
  1631. main_map = (global_keymap_t *) main_keymap->data;
  1632. main_x_map = default_main_x_map;
  1633. if (main_x_keymap && main_x_keymap->len > 0)
  1634. main_x_map = (global_keymap_t *) main_x_keymap->data;
  1635. panel_map = default_panel_keymap;
  1636. if (panel_keymap && panel_keymap->len > 0)
  1637. panel_map = (global_keymap_t *) panel_keymap->data;
  1638. input_map = default_input_keymap;
  1639. if (input_keymap && input_keymap->len > 0)
  1640. input_map = (global_keymap_t *) input_keymap->data;
  1641. tree_map = default_tree_keymap;
  1642. if (tree_keymap && tree_keymap->len > 0)
  1643. tree_map = (global_keymap_t *) tree_keymap->data;
  1644. help_map = default_help_keymap;
  1645. if (help_keymap && help_keymap->len > 0)
  1646. help_map = (global_keymap_t *) help_keymap->data;
  1647. /* Check if we were invoked as an editor or file viewer */
  1648. if (!mc_maybe_editor_or_viewer ()) {
  1649. setup_panels_and_run_mc ();
  1650. /* Program end */
  1651. midnight_shutdown = 1;
  1652. /* destroy_dlg destroys even current_panel->cwd, so we have to save a copy :) */
  1653. if (mc_args__last_wd_file && vfs_current_is_local ())
  1654. last_wd_string = g_strdup (current_panel->cwd);
  1655. done_mc ();
  1656. }
  1657. destroy_dlg (midnight_dlg);
  1658. panel_deinit ();
  1659. current_panel = 0;
  1660. done_mc_profile ();
  1661. }
  1662. /* POSIX version. The only version we support. */
  1663. static void
  1664. OS_Setup (void)
  1665. {
  1666. const char *shell_env = getenv ("SHELL");
  1667. const char *mc_libdir;
  1668. if ((shell_env == NULL) || (shell_env[0] == '\0')) {
  1669. struct passwd *pwd;
  1670. pwd = getpwuid (geteuid ());
  1671. if (pwd != NULL)
  1672. shell = g_strdup (pwd->pw_shell);
  1673. } else
  1674. shell = g_strdup (shell_env);
  1675. if ((shell == NULL) || (shell[0] == '\0')) {
  1676. g_free (shell);
  1677. shell = g_strdup ("/bin/sh");
  1678. }
  1679. /* This is the directory, where MC was installed, on Unix this is DATADIR */
  1680. /* and can be overriden by the MC_DATADIR environment variable */
  1681. mc_libdir = getenv ("MC_DATADIR");
  1682. if (mc_libdir != NULL) {
  1683. mc_home = g_strdup (mc_libdir);
  1684. mc_home_alt = g_strdup (SYSCONFDIR);
  1685. } else {
  1686. mc_home = g_strdup (SYSCONFDIR);
  1687. mc_home_alt = g_strdup (DATADIR);
  1688. }
  1689. /* This variable is used by the subshell */
  1690. home_dir = getenv ("HOME");
  1691. if (!home_dir)
  1692. home_dir = mc_home;
  1693. }
  1694. static void
  1695. sigchld_handler_no_subshell (int sig)
  1696. {
  1697. #ifdef __linux__
  1698. int pid, status;
  1699. if (!console_flag)
  1700. return;
  1701. /* COMMENT: if it were true that after the call to handle_console(..INIT)
  1702. the value of console_flag never changed, we could simply not install
  1703. this handler at all if (!console_flag && !use_subshell). */
  1704. /* That comment is no longer true. We need to wait() on a sigchld
  1705. handler (that's at least what the tarfs code expects currently). */
  1706. pid = waitpid (cons_saver_pid, &status, WUNTRACED | WNOHANG);
  1707. if (pid == cons_saver_pid) {
  1708. if (WIFSTOPPED (status)) {
  1709. /* Someone has stopped cons.saver - restart it */
  1710. kill (pid, SIGCONT);
  1711. } else {
  1712. /* cons.saver has died - disable console saving */
  1713. handle_console (CONSOLE_DONE);
  1714. console_flag = 0;
  1715. }
  1716. }
  1717. /* If we got here, some other child exited; ignore it */
  1718. #endif /* __linux__ */
  1719. (void) sig;
  1720. }
  1721. static void
  1722. init_sigchld (void)
  1723. {
  1724. struct sigaction sigchld_action;
  1725. sigchld_action.sa_handler =
  1726. #ifdef HAVE_SUBSHELL_SUPPORT
  1727. use_subshell ? sigchld_handler :
  1728. #endif /* HAVE_SUBSHELL_SUPPORT */
  1729. sigchld_handler_no_subshell;
  1730. sigemptyset (&sigchld_action.sa_mask);
  1731. #ifdef SA_RESTART
  1732. sigchld_action.sa_flags = SA_RESTART;
  1733. #else
  1734. sigchld_action.sa_flags = 0;
  1735. #endif /* !SA_RESTART */
  1736. if (sigaction (SIGCHLD, &sigchld_action, NULL) == -1) {
  1737. #ifdef HAVE_SUBSHELL_SUPPORT
  1738. /*
  1739. * This may happen on QNX Neutrino 6, where SA_RESTART
  1740. * is defined but not implemented. Fallback to no subshell.
  1741. */
  1742. use_subshell = 0;
  1743. #endif /* HAVE_SUBSHELL_SUPPORT */
  1744. }
  1745. }
  1746. static void
  1747. mc_main__setup_by_args (int argc, char *argv[])
  1748. {
  1749. const char *base;
  1750. char *tmp;
  1751. if (mc_args__nomouse)
  1752. use_mouse_p = MOUSE_DISABLED;
  1753. #ifdef USE_NETCODE
  1754. if (mc_args__netfs_logfile != NULL) {
  1755. mc_setctl ("/#ftp:", VFS_SETCTL_LOGFILE, (void *) mc_args__netfs_logfile);
  1756. #ifdef WITH_SMBFS
  1757. smbfs_set_debugf (mc_args__netfs_logfile);
  1758. #endif /* WITH_SMBFS */
  1759. }
  1760. #ifdef WITH_SMBFS
  1761. if (mc_args__debug_level != 0)
  1762. smbfs_set_debug (mc_args__debug_level);
  1763. #endif /* WITH_SMBFS */
  1764. #endif /* USE_NETCODE */
  1765. base = x_basename (argv[0]);
  1766. tmp = (argc > 0) ? argv[1] : NULL;
  1767. if (!STRNCOMP (base, "mce", 3) || !STRCOMP (base, "vi")) {
  1768. edit_one_file = "";
  1769. if (tmp) {
  1770. /*
  1771. * Check for filename:lineno, followed by an optional colon.
  1772. * This format is used by many programs (especially compilers)
  1773. * in error messages and warnings. It is supported so that
  1774. * users can quickly copy and paste file locations.
  1775. */
  1776. char *end = tmp + strlen (tmp), *p = end;
  1777. if (p > tmp && p[-1] == ':')
  1778. p--;
  1779. while (p > tmp && g_ascii_isdigit ((gchar) p[-1]))
  1780. p--;
  1781. if (tmp < p && p < end && p[-1] == ':') {
  1782. struct stat st;
  1783. gchar *fname = g_strndup (tmp, p - 1 - tmp);
  1784. /*
  1785. * Check that the file before the colon actually exists.
  1786. * If it doesn't exist, revert to the old behavior.
  1787. */
  1788. if (mc_stat (tmp, &st) == -1 && mc_stat (fname, &st) != -1) {
  1789. edit_one_file = fname;
  1790. edit_one_file_start_line = atoi (p);
  1791. } else {
  1792. g_free (fname);
  1793. goto try_plus_filename;
  1794. }
  1795. } else {
  1796. try_plus_filename:
  1797. if (*tmp == '+' && g_ascii_isdigit ((gchar) tmp[1])) {
  1798. int start_line = atoi (tmp);
  1799. if (start_line > 0) {
  1800. char *file = (argc > 1) ? argv[2] : NULL;
  1801. if (file) {
  1802. tmp = file;
  1803. edit_one_file_start_line = start_line;
  1804. }
  1805. }
  1806. }
  1807. edit_one_file = g_strdup (tmp);
  1808. }
  1809. }
  1810. } else if (!STRNCOMP (base, "mcv", 3) || !STRCOMP (base, "view")) {
  1811. if (tmp)
  1812. view_one_file = g_strdup (tmp);
  1813. else {
  1814. fputs ("No arguments given to the viewer\n", stderr);
  1815. exit (1);
  1816. }
  1817. } else {
  1818. /* sets the current dir and the other dir */
  1819. if (tmp) {
  1820. this_dir = g_strdup (tmp);
  1821. tmp = (argc > 1) ? argv[2] : NULL;
  1822. if (tmp)
  1823. other_dir = g_strdup (tmp);
  1824. }
  1825. }
  1826. }
  1827. int
  1828. main (int argc, char *argv[])
  1829. {
  1830. struct stat s;
  1831. char *mc_dir;
  1832. GError *error = NULL;
  1833. gboolean isInitialized;
  1834. /* We had LC_CTYPE before, LC_ALL includs LC_TYPE as well */
  1835. setlocale (LC_ALL, "");
  1836. bindtextdomain ("mc", LOCALEDIR);
  1837. textdomain ("mc");
  1838. /* Set up temporary directory */
  1839. mc_tmpdir ();
  1840. OS_Setup ();
  1841. str_init_strings (NULL);
  1842. vfs_init ();
  1843. #ifdef USE_INTERNAL_EDIT
  1844. edit_stack_init ();
  1845. #endif
  1846. #ifdef HAVE_SLANG
  1847. SLtt_Ignore_Beep = 1;
  1848. #endif
  1849. if ( !mc_args_handle (&argc, &argv, "mc"))
  1850. return 1;
  1851. mc_main__setup_by_args (argc,argv);
  1852. /* NOTE: This has to be called before tty_init or whatever routine
  1853. calls any define_sequence */
  1854. init_key ();
  1855. /* Must be done before installing the SIGCHLD handler [[FIXME]] */
  1856. handle_console (CONSOLE_INIT);
  1857. #ifdef HAVE_SUBSHELL_SUPPORT
  1858. /* Don't use subshell when invoked as viewer or editor */
  1859. if (edit_one_file || view_one_file)
  1860. use_subshell = 0;
  1861. if (use_subshell)
  1862. subshell_get_console_attributes ();
  1863. #endif /* HAVE_SUBSHELL_SUPPORT */
  1864. /* Install the SIGCHLD handler; must be done before init_subshell() */
  1865. init_sigchld ();
  1866. /* We need this, since ncurses endwin () doesn't restore the signals */
  1867. save_stop_handler ();
  1868. /* Must be done before init_subshell, to set up the terminal size: */
  1869. /* FIXME: Should be removed and LINES and COLS computed on subshell */
  1870. tty_init ((gboolean) mc_args__slow_terminal, (gboolean) mc_args__ugly_line_drawing);
  1871. load_setup ();
  1872. tty_init_colors (mc_args__disable_colors, mc_args__force_colors);
  1873. isInitialized = mc_skin_init(&error);
  1874. mc_filehighlight = mc_fhl_new (TRUE);
  1875. dlg_set_default_colors ();
  1876. if ( ! isInitialized ) {
  1877. message (D_ERROR, _("Warning"), error->message);
  1878. g_error_free(error);
  1879. error = NULL;
  1880. }
  1881. /* create home directory */
  1882. /* do it after the screen library initialization to show the error message */
  1883. mc_dir = concat_dir_and_file (home_dir, MC_USERCONF_DIR);
  1884. canonicalize_pathname (mc_dir);
  1885. if ((stat (mc_dir, &s) != 0) && (errno == ENOENT)
  1886. && mkdir (mc_dir, 0700) != 0)
  1887. message (D_ERROR, _("Warning"),
  1888. _("Cannot create %s directory"), mc_dir);
  1889. g_free (mc_dir);
  1890. #ifdef HAVE_SUBSHELL_SUPPORT
  1891. /* Done here to ensure that the subshell doesn't */
  1892. /* inherit the file descriptors opened below, etc */
  1893. if (use_subshell)
  1894. init_subshell ();
  1895. #endif /* HAVE_SUBSHELL_SUPPORT */
  1896. /* Removing this from the X code let's us type C-c */
  1897. load_key_defs ();
  1898. load_keymap_defs ();
  1899. /* Also done after init_subshell, to save any shell init file messages */
  1900. if (console_flag)
  1901. handle_console (CONSOLE_SAVE);
  1902. if (alternate_plus_minus)
  1903. application_keypad_mode ();
  1904. #ifdef HAVE_SUBSHELL_SUPPORT
  1905. if (use_subshell) {
  1906. prompt = strip_ctrl_codes (subshell_prompt);
  1907. if (!prompt)
  1908. prompt = "";
  1909. } else
  1910. #endif /* HAVE_SUBSHELL_SUPPORT */
  1911. prompt = (geteuid () == 0) ? "# " : "$ ";
  1912. /* Program main loop */
  1913. if (!midnight_shutdown)
  1914. do_nc ();
  1915. /* Save the tree store */
  1916. tree_store_save ();
  1917. free_keymap_defs ();
  1918. /* Virtual File System shutdown */
  1919. vfs_shut ();
  1920. flush_extension_file (); /* does only free memory */
  1921. mc_fhl_free (&mc_filehighlight);
  1922. mc_skin_deinit ();
  1923. tty_shutdown ();
  1924. if (console_flag && !(quit & SUBSHELL_EXIT))
  1925. handle_console (CONSOLE_RESTORE);
  1926. if (alternate_plus_minus)
  1927. numeric_keypad_mode ();
  1928. signal (SIGCHLD, SIG_DFL); /* Disable the SIGCHLD handler */
  1929. if (console_flag)
  1930. handle_console (CONSOLE_DONE);
  1931. putchar ('\n'); /* Hack to make shell's prompt start at left of screen */
  1932. if (mc_args__last_wd_file && last_wd_string && !print_last_revert
  1933. && !edit_one_file && !view_one_file) {
  1934. int last_wd_fd =
  1935. open (mc_args__last_wd_file, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL,
  1936. S_IRUSR | S_IWUSR);
  1937. if (last_wd_fd != -1) {
  1938. write (last_wd_fd, last_wd_string, strlen (last_wd_string));
  1939. close (last_wd_fd);
  1940. }
  1941. }
  1942. g_free (last_wd_string);
  1943. g_free (mc_home_alt);
  1944. g_free (mc_home);
  1945. g_free (shell);
  1946. done_key ();
  1947. #ifdef HAVE_CHARSET
  1948. free_codepages_list ();
  1949. #endif
  1950. str_uninit_strings ();
  1951. g_free (this_dir);
  1952. g_free (other_dir);
  1953. #ifdef USE_INTERNAL_EDIT
  1954. edit_stack_free ();
  1955. #endif
  1956. return 0;
  1957. }