updated: [035fa47] manually merged 228_replace_g_strdup



The following commit has been merged in the master branch:
commit 035fa47c06127a201b4285cb35381fadfea7da67
Merge: 7015de5db51b00fe6c5ea6c49556ffcb526aca13 f921cc40cddc155ce54d51054171e231575034ad
Author: Enrico Weigelt, metux IT service <weigelt metux de>
Date:   Mon Feb 2 21:28:01 2009 +0100

    manually merged 228_replace_g_strdup

diff --combined ChangeLog
index b78cdd6,d5f2a56..f350557
--- a/ChangeLog
+++ b/ChangeLog
@@@ -1,25 -1,6 +1,26 @@@
 -2009-01-30 Enrico Weigelt, metux IT service <weigelt metux de>
 +2009-02-01 Enrico Weigelt, metux ITS <weigelt metux de>
  
 +	* src/util.c: fixed name_trunc() on NULL or empty parameters
 +	* src/achown.c: fixed unitialized var in init_chown_advanced()
 +	  (patch from andrew_b)
 +	* replaced gboolean by bool (from mhl/types.h)
 +
 +2009-01-31 Enrico Weigelt, metux ITS <weigelt metux de>, Patrick Winnertz <winnie debian org>, Slava Zanko <slavazanko gmail com>, Sergei Trofimovich  <slyfox inbox ru>
 +
 +	* edit/editcmd.c, mhl/escape.h, mhl/string.h, mhl/types.h, src/Makefile.am,
 +	* src/boxes.c, src/command.c, src/complete.c, src/complete.h, src/file.c,
 +	* src/find.c, src/main.c, src/panelize.c, src/util.c, src/utilunix.c,
 +	* src/widget.c, src/widget.h, src/wtools.c, vfs/fish.c:
 +	  fixed shell escaping issues in commandline completion engine
 +	* replaced buggy concat_dir_and_file() by mhl_str_dir_plus_file() (in mhl/string.h)
 +	* replaced g_snprintf() by snprintf()
 +
 +2009-01-30 Enrico Weigelt, metux ITS <weigelt metux de>
 +
 +	* src/Makefile.am, edit/Makefile.am vfs/Makefile.am: fixed #208
 +	  (out-of-tree builds)
 +	* syntax/Syntax, syntax/Makefile.am, syntax/vhdl.syntax: added VHDL syntax (#193)
+ 	* replaced calls to g_strdup() by mhl_str_dup()
  
  2009-01-29 Mikhail S. Pobolovets <styx mp gmail com>
  	* lib/mc.ext.in: update for OpenOffice and StarOffice viewer.
@@@ -31,10 -12,8 +32,10 @@@
  	  This solves "strange" rename cases, when copying/moving is performed into
  	  deleted directory.
  
 -2009-01-27 Enrico Weigelt, metux IT service <weigelt metux de>
 +2009-01-27 Enrico Weigelt, metux ITS <weigelt metux de>
  
 +	* mhl/escape.h, src/complete.c, vfs/fish.c: introduced new type 
 +	  SHELL_ESCAPED_STR for more type safety
  	* mhl/escape.h, mhl/string.h: fixed comments to use /* ... */
  
  2009-01-27 Sergei Trofimovich  <slyfox inbox ru>
@@@ -42,11 -21,6 +43,11 @@@
  	* syntax/python.syntax: Added syntax highlighting for
  	pytnoh-2.6+ keywords (patch sent by NNemec)
  
 +2009-01-26 Mikhail S. Pobolovets <styx mp gmail com>
 +
 +	* vfs/fish.c: Iterpret SUP.flags as port number if SUP.flags is not in
 +	  0, FISH_FLAG_COMPRESSED and FISH_FLAG_RSH. Weakness: port number
 +
  2009-01-25 Ilia Maslakov <il smind gmail com>
  
  	* src/boxes.c, src/boxes.h, src/dir.c, src/dir.h:
@@@ -62,7 -36,7 +63,7 @@@
  	* src/cmd.c src/option.c src/setup.c src/main.h: Automatic new directory(Mkdir, F7)
  	  name filling. Can be configured (on|off) in 'Configure options'
  
 -2009-01-25 Enrico Weigelt <weigelt metux de>
 +2009-01-25 Enrico Weigelt, metux ITS <weigelt metux de>
  
  	* edit/editcmd.c, src/cmd.c, src/ext.c, src/history.h:
  	* src/hotlist.c, src/panelize.c, src/tree.c, src/user.c: 
@@@ -71,11 -45,9 +72,11 @@@
  	  translated strings. This breaks now once every history file
  	  but afterwards this will be stable
  
 -2009-01-24 Enrico Weigelt <weigelt metux de>
 +2009-01-24 Enrico Weigelt, metux ITS <weigelt metux de>
  
  	* src/cmd.c: fixed bug #35 (do_view_cmd is now calling repaint_screen())
 +	* syntax/Syntax, syntax/nemerle.syntax: Added syntax rules 
 +	  for Nemerle source files
  
  2009-01-24 Patrick Winnertz <winnie debian org>
  
@@@ -83,6 -55,11 +84,6 @@@
  	  - prevent . to match a newline (\n)
  	  - match from start of line and not from cursor position
  
 -2009-01-24  Enrico Weigelt, metux IT service <weigelt metux de>
 -
 -	* syntax/Syntax, syntax/nemerle.syntax: Added syntax rules 
 -	  for Nemerle source files
 -
  2009-01-19 Patrick Winnertz <winnie debian org>
  
  	* edit/edit.h: Add two more ints
@@@ -97,7 -74,7 +98,7 @@@
  	* src/main.c: Removed unused function do_mc_filename_rename
  	* src/util.c: Removed unused struct whentm
  
 -2009-01-16 Enrico Weigelt, metux IT service <weigelt metux de>
 +2009-01-16 Enrico Weigelt, metux ITS <weigelt metux de>
  
  	* src/subshell: setting subshell pty to close-on-exec 
  	  (taken from mandriva patches)
@@@ -135,6 -112,9 +136,6 @@@
  	* syntax/Makefile.am syntax/Syntax syntax/haskell.syntax:
  	added syntax definition for Haskell (taken from rhclub-tree)
  	* syntax: added ebuild Syntax defition (taken from rhclub-tree)
 -
 -2009-01-10  Enrico Weigelt, metux ITS <weigelt metux de>
 -
  	* edit/editcmd.c:
  	* src/achown.c src/background.c src/boxes.c src/chmod.c:
  	* src/chown.c src/cmd.c src/command.c src/dir.c src/execute.c:
diff --combined edit/editcmd.c
index 7dae88a,1b54e7c..33c0671
--- a/edit/editcmd.c
+++ b/edit/editcmd.c
@@@ -28,6 -28,7 +28,6 @@@
  
  #include <assert.h>
  #include <ctype.h>
 -
  #include <stdio.h>
  #include <stdarg.h>
  #include <sys/types.h>
@@@ -235,7 -236,7 +235,7 @@@ edit_save_file (WEdit *edit, const cha
  	return 0;
  
      if (*filename != PATH_SEP && edit->dir) {
 -	savename = concat_dir_and_file (edit->dir, filename);
 +	savename = mhl_str_dir_plus_file (edit->dir, filename);
  	filename = catstrs (savename, (char *) NULL);
  	g_free (savename);
      }
@@@ -297,14 -298,14 +297,14 @@@
  	const char *slashpos;
  	slashpos = strrchr (filename, PATH_SEP);
  	if (slashpos) {
- 	    savedir = g_strdup (filename);
+ 	    savedir = mhl_str_dup (filename);
  	    savedir[slashpos - filename + 1] = '\0';
  	} else
- 	    savedir = g_strdup (".");
+ 	    savedir = mhl_str_dup (".");
 -	saveprefix = concat_dir_and_file (savedir, "cooledit");
 -	g_free (savedir);
 +	saveprefix = mhl_str_dir_plus_file (savedir, "cooledit");
- 	g_free (savedir);
++	mhl_mem_free (savedir);
  	fd = mc_mkstemps (&savename, saveprefix, NULL);
--	g_free (saveprefix);
++	mhl_mem_free (saveprefix);
  	if (!savename)
  	    return 0;
  	/* FIXME:
@@@ -314,7 -315,7 +314,7 @@@
  	 */
  	close (fd);
      } else
- 	savename = g_strdup (filename);
+ 	savename = mhl_str_dup (filename);
  
      mc_chown (savename, edit->stat1.st_uid, edit->stat1.st_gid);
      mc_chmod (savename, edit->stat1.st_mode);
@@@ -503,10 -504,10 +503,10 @@@ edit_set_filename (WEdit *edit, const c
      g_free (edit->filename);
      if (!f)
  	f = "";
-     edit->filename = g_strdup (f);
+     edit->filename = mhl_str_dup (f);
      if (edit->dir == NULL && *f != PATH_SEP)
  #ifdef USE_VFS
- 	edit->dir = g_strdup (vfs_get_current_dir ());
+ 	edit->dir = mhl_str_dup (vfs_get_current_dir ());
  #else
  	edit->dir = g_get_current_dir ();
  #endif
@@@ -626,7 -627,7 +626,7 @@@ edit_raw_key_query (const char *heading
  		    NULL, heading,
  		    DLG_CENTER | DLG_TRYUP | DLG_WANT_TAB);
      add_widget (raw_dlg,
 -		input_new (3 - cancel, w - 5, INPUT_COLOR, 2, "", 0));
 +		input_new (3 - cancel, w - 5, INPUT_COLOR, 2, "", 0, INPUT_COMPLETE_DEFAULT));
      add_widget (raw_dlg, label_new (3 - cancel, 2, query));
      if (cancel)
  	add_widget (raw_dlg,
@@@ -877,7 -878,7 +877,7 @@@ static in
  edit_load_file_from_filename (WEdit * edit, char *exp)
  {
      int prev_locked = edit->locked;
-     char *prev_filename = g_strdup (edit->filename);
+     char *prev_filename = mhl_str_dup (edit->filename);
  
      if (!edit_reload (edit, exp)) {
  	g_free (prev_filename);
@@@ -1458,7 -1459,7 +1458,7 @@@ string_regexp_search (char *pattern, ch
  	    *found_len = 0;
  	    return -3;
  	}
- 	old_pattern = g_strdup (pattern);
+ 	old_pattern = mhl_str_dup (pattern);
  	old_type = match_type;
  	old_icase = icase;
      }
@@@ -1840,13 -1841,13 +1840,13 @@@ edit_replace_cmd (WEdit *edit, int agai
  	again = 0;
  
      if (again) {
- 	input1 = g_strdup (saved1 ? saved1 : "");
- 	input2 = g_strdup (saved2 ? saved2 : "");
- 	input3 = g_strdup (saved3 ? saved3 : "");
+ 	input1 = mhl_str_dup (saved1 ? saved1 : "");
+ 	input2 = mhl_str_dup (saved2 ? saved2 : "");
+ 	input3 = mhl_str_dup (saved3 ? saved3 : "");
      } else {
- 	char *disp1 = g_strdup (saved1 ? saved1 : "");
- 	char *disp2 = g_strdup (saved2 ? saved2 : "");
- 	char *disp3 = g_strdup (saved3 ? saved3 : "");
+ 	char *disp1 = mhl_str_dup (saved1 ? saved1 : "");
+ 	char *disp2 = mhl_str_dup (saved2 ? saved2 : "");
+ 	char *disp3 = mhl_str_dup (saved3 ? saved3 : "");
  
  	convert_to_display (disp1);
  	convert_to_display (disp2);
@@@ -1870,9 -1871,9 +1870,9 @@@
  	    goto cleanup;
  	}
  
- 	g_free (saved1), saved1 = g_strdup (input1);
- 	g_free (saved2), saved2 = g_strdup (input2);
- 	g_free (saved3), saved3 = g_strdup (input3);
+ 	g_free (saved1), saved1 = mhl_str_dup (input1);
+ 	g_free (saved2), saved2 = mhl_str_dup (input2);
+ 	g_free (saved3), saved3 = mhl_str_dup (input3);
  
      }
  
@@@ -2087,7 -2088,7 +2087,7 @@@ void edit_search_cmd (WEdit * edit, in
      if (again) {		/*ctrl-hotkey for search again. */
  	if (!old)
  	    return;
- 	exp = g_strdup (old);
+ 	exp = mhl_str_dup (old);
      } else {
  
  #ifdef HAVE_CHARSET
@@@ -2109,7 -2110,7 +2109,7 @@@
  	if (*exp) {
  	    int len = 0;
  	    g_free (old);
- 	    old = g_strdup (exp);
+ 	    old = mhl_str_dup (exp);
  
  	    if (search_create_bookmark) {
  		int found = 0, books = 0;
@@@ -2337,7 -2338,7 +2337,7 @@@ edit_goto_cmd (WEdit *edit
      char *error;
      char s[32];
  
 -    g_snprintf (s, sizeof (s), "%ld", line);
 +    snprintf (s, sizeof (s), "%ld", line);
      f = input_dialog (_(" Goto line "), _(" Enter line: "), MC_HISTORY_EDIT_GOTO_LINE,
  		      line ? s : "");
      if (!f)
diff --combined edit/syntax.c
index 2cfe976,fd82122..df6a47e
--- a/edit/syntax.c
+++ b/edit/syntax.c
@@@ -668,7 -668,7 +668,7 @@@ static FILE *open_include_file (const c
      FILE *f;
  
      syntax_g_free (error_file_name);
-     error_file_name = g_strdup (filename);
+     error_file_name = mhl_str_dup (filename);
      if (*filename == PATH_SEP)
  	return fopen (filename, "r");
  
@@@ -774,8 -774,8 +774,8 @@@ edit_read_syntax_rules (WEdit *edit, FI
  		}
  		a++;
  		c = r[0] = g_malloc0 (sizeof (struct context_rule));
- 		c->left = g_strdup (" ");
- 		c->right = g_strdup (" ");
+ 		c->left = mhl_str_dup (" ");
+ 		c->right = mhl_str_dup (" ");
  		num_contexts = 0;
  	    } else {
  		/* Terminate previous context.  */
@@@ -788,14 -788,14 +788,14 @@@
  		check_a;
  		if (!strcmp (*a, "whole")) {
  		    a++;
- 		    c->whole_word_chars_left = g_strdup (whole_left);
- 		    c->whole_word_chars_right = g_strdup (whole_right);
+ 		    c->whole_word_chars_left = mhl_str_dup (whole_left);
+ 		    c->whole_word_chars_right = mhl_str_dup (whole_right);
  		} else if (!strcmp (*a, "wholeleft")) {
  		    a++;
- 		    c->whole_word_chars_left = g_strdup (whole_left);
+ 		    c->whole_word_chars_left = mhl_str_dup (whole_left);
  		} else if (!strcmp (*a, "wholeright")) {
  		    a++;
- 		    c->whole_word_chars_right = g_strdup (whole_right);
+ 		    c->whole_word_chars_right = mhl_str_dup (whole_right);
  		}
  		check_a;
  		if (!strcmp (*a, "linestart")) {
@@@ -803,14 -803,14 +803,14 @@@
  		    c->line_start_left = 1;
  		}
  		check_a;
- 		c->left = g_strdup (*a++);
+ 		c->left = mhl_str_dup (*a++);
  		check_a;
  		if (!strcmp (*a, "linestart")) {
  		    a++;
  		    c->line_start_right = 1;
  		}
  		check_a;
- 		c->right = g_strdup (*a++);
+ 		c->right = mhl_str_dup (*a++);
  		c->first_left = *c->left;
  		c->first_right = *c->right;
  	    }
@@@ -827,7 -827,7 +827,7 @@@
  	    g_strlcpy (last_fg, fg ? fg : "", sizeof (last_fg));
  	    g_strlcpy (last_bg, bg ? bg : "", sizeof (last_bg));
  	    c->keyword[0]->color = this_try_alloc_color_pair (fg, bg);
- 	    c->keyword[0]->keyword = g_strdup (" ");
+ 	    c->keyword[0]->keyword = mhl_str_dup (" ");
  	    check_not_a;
  
  	    alloc_words_per_context = MAX_WORDS_PER_CONTEXT;
@@@ -853,14 -853,14 +853,14 @@@
  	    k = r[num_contexts - 1]->keyword[num_words] = g_malloc0 (sizeof (struct key_word));
  	    if (!strcmp (*a, "whole")) {
  		a++;
- 		k->whole_word_chars_left = g_strdup (whole_left);
- 		k->whole_word_chars_right = g_strdup (whole_right);
+ 		k->whole_word_chars_left = mhl_str_dup (whole_left);
+ 		k->whole_word_chars_right = mhl_str_dup (whole_right);
  	    } else if (!strcmp (*a, "wholeleft")) {
  		a++;
- 		k->whole_word_chars_left = g_strdup (whole_left);
+ 		k->whole_word_chars_left = mhl_str_dup (whole_left);
  	    } else if (!strcmp (*a, "wholeright")) {
  		a++;
- 		k->whole_word_chars_right = g_strdup (whole_right);
+ 		k->whole_word_chars_right = mhl_str_dup (whole_right);
  	    }
  	    check_a;
  	    if (!strcmp (*a, "linestart")) {
@@@ -871,7 -871,7 +871,7 @@@
  	    if (!strcmp (*a, "whole")) {
  		break_a;
  	    }
- 	    k->keyword = g_strdup (*a++);
+ 	    k->keyword = mhl_str_dup (*a++);
  	    k->first = *k->keyword;
  	    subst_defines (edit->defines, a, &args[1024]);
  	    fg = *a;
@@@ -911,12 -911,12 +911,12 @@@
  	    if ((argv = g_tree_lookup (edit->defines, key))) {
  		mc_defines_destroy (NULL, argv, NULL);
  	    } else {
- 		key = g_strdup (key);
+ 		key = mhl_str_dup (key);
  	    }
  	    argv = g_new (char *, argc - 1);
  	    g_tree_insert (edit->defines, key, argv);
  	    while (*a) {
- 		*argv++ = g_strdup (*a++);
+ 		*argv++ = mhl_str_dup (*a++);
  	    };
  	    *argv = NULL;
  	} else {		/* anything else is an error */
@@@ -956,7 -956,7 +956,7 @@@
  	    for (j = 1; c->keyword[j]; j++)
  		*p++ = c->keyword[j]->first;
  	    *p = '\0';
- 	    c->keyword_first_chars = g_strdup (first_chars);
+ 	    c->keyword_first_chars = mhl_str_dup (first_chars);
  	}
  
  	g_free (first_chars);
@@@ -1027,7 -1027,7 +1027,7 @@@ edit_read_syntax_file (WEdit * edit, ch
  
      f = fopen (syntax_file, "r");
      if (!f){
 -	lib_file = concat_dir_and_file (mc_home, "syntax" PATH_SEP_STR "Syntax");
 +	lib_file = mhl_str_dir_plus_file (mc_home, "syntax" PATH_SEP_STR "Syntax");
  	f = fopen (lib_file, "r");
  	g_free (lib_file);
  	if (!f)
@@@ -1077,7 -1077,7 +1077,7 @@@
  		else
  		    abort ();
  	    }
- 	    (*pnames)[count++] = g_strdup (args[2]);
+ 	    (*pnames)[count++] = mhl_str_dup (args[2]);
  	    (*pnames)[count] = NULL;
  	} else if (type) {
  
@@@ -1119,7 -1119,7 +1119,7 @@@
  			result = line_error;
  		} else {
  		    syntax_g_free (edit->syntax_type);
- 		    edit->syntax_type = g_strdup (syntax_type);
+ 		    edit->syntax_type = mhl_str_dup (syntax_type);
  
  /* if there are no rules then turn off syntax highlighting for speed */
  		    if (!g && !edit->rules[1])
@@@ -1189,7 -1189,7 +1189,7 @@@ edit_load_syntax (WEdit *edit, char ***
  	if (!*edit->filename && !type)
  	    return;
      }
 -    f = concat_dir_and_file (home_dir, SYNTAX_FILE);
 +    f = mhl_str_dir_plus_file (home_dir, SYNTAX_FILE);
      r = edit_read_syntax_file (edit, pnames, f, edit ? edit->filename : 0,
  			       get_first_editor_line (edit), type);
      if (r == -1) {
diff --combined edit/usermap.c
index 271658c,914ba39..f5d5e4f
--- a/edit/usermap.c
+++ b/edit/usermap.c
@@@ -30,7 -30,6 +30,7 @@@
  #include <sys/stat.h>
  #include <unistd.h>
  
 +#include <mhl/types.h>
  #include <mhl/string.h>
  
  #include "../src/global.h"
@@@ -58,7 -57,7 +58,7 @@@ typedef struct Config 
  
  typedef struct Command {
      const char *name;
 -    int (*handler) (config_t *cfg, int argc, char *argv[]);
 +    bool (*handler) (config_t *cfg, int argc, char *argv[]);
  } command_t;
  
  static char error_msg[200] = "Nobody see this";
@@@ -254,7 -253,7 +254,7 @@@ cfg_free_maps(config_t *cfg
  static GPtrArray *
  split_line(char *str)
  {
 -    gboolean inside_quote = FALSE;
 +    bool inside_quote = false;
      int move = 0;
      GPtrArray *args;    
  
@@@ -344,7 -343,7 +344,7 @@@ keymap_add(GArray *keymap, int key, in
  }
  
  /* bind <key> <command> */
 -static gboolean
 +static bool
  cmd_bind(config_t *cfg, int argc, char *argv[])
  {
      char *keyname, *command;
@@@ -355,7 -354,7 +355,7 @@@
      if (argc != 3) {
  	snprintf(error_msg, sizeof(error_msg),
  		 _("bind: Wrong argument number, bind <key> <command>"));
 -	return FALSE;
 +	return false;
      }
  
      keyname = argv[1];
@@@ -377,7 -376,7 +377,7 @@@
  	    if (!m) {		/* incorrect key */
  		snprintf(error_msg, sizeof(error_msg),
  			 _("bind: Bad key value `%s'"), keyname);
 -		return FALSE;
 +		return false;
  	    }
  	    mod |= m;
  	    m = 0;
@@@ -390,7 -389,7 +390,7 @@@
      /* no key */
      if (keyname[0] == '\0') {
  	snprintf(error_msg, sizeof(error_msg), _("bind: Ehh...no key?"));
 -	return FALSE;
 +	return false;
      }
  
      /* ordinary key */
@@@ -404,7 -403,7 +404,7 @@@
      if (k < 0 && !key->name) {
  	snprintf(error_msg, sizeof(error_msg),
  		 _("bind: Unknown key: `%s'"), keyname);
 -	return FALSE;
 +	return false;
      }
  
      while (cmd->name && strcasecmp(cmd->name, command) != 0)
@@@ -413,7 -412,7 +413,7 @@@
      if (!cmd->name) {
  	snprintf(error_msg, sizeof(error_msg),
  		 _("bind: Unknown command: `%s'"), command);
 -	return FALSE;
 +	return false;
      }
  
      if (mod & KEY_M_CTRL) {
@@@ -434,7 -433,7 +434,7 @@@
      else
  	keymap_add(cfg->keymap, k, cmd->val);
  
 -    return TRUE;
 +    return true;
  }
  
  #if 0
@@@ -470,7 -469,7 +470,7 @@@ static void edit_my_define (Dlg_head * 
  #endif
  
  /* label <number> <command> <label> */
 -static gboolean
 +static bool
  cmd_label(config_t *cfg, int argc, char *argv[])
  {
      const name_map_t *cmd = command_names;
@@@ -481,7 -480,7 +481,7 @@@
  	snprintf(error_msg, sizeof(error_msg),
  		 _("%s: Syntax: %s <n> <command> <label>"), 
  		argv[0], argv[0]);
 -	return FALSE;
 +	return false;
      }
      
      fn	= strtol(argv[1], NULL, 0);
@@@ -494,23 -493,23 +494,23 @@@
      if (!cmd->name) {
  	snprintf(error_msg, sizeof(error_msg),
  		 _("%s: Unknown command: `%s'"), argv[0], command);
 -	return FALSE;
 +	return false;
      }
      
      if (fn < 1 || fn > 10) {
  	snprintf(error_msg, sizeof(error_msg),
  		 _("%s: fn should be 1-10"), argv[0]);
 -	return FALSE;
 +	return false;
      }
  
      keymap_add(cfg->keymap, KEY_F(fn), cmd->val);
-     cfg->labels[fn - 1] = g_strdup(label);
+     cfg->labels[fn - 1] = mhl_str_dup(label);
  
 -    return TRUE;
 +    return true;
  }
  
  
 -static gboolean
 +static bool
  parse_file(config_t *cfg, const char *file, const command_t *cmd)
  {
      char buf[200];
@@@ -521,7 -520,7 +521,7 @@@
      if (!fp) {
  	snprintf(error_msg, sizeof(error_msg), _("%s: fopen(): %s"),
  		 file, strerror(errno));
 -	return FALSE;
 +	return false;
      }
  
      while (fgets(buf, sizeof(buf), fp)) {
@@@ -548,26 -547,26 +548,26 @@@
  		     argv[0]);
  	    g_ptr_array_free(args, TRUE);
  	    fclose(fp);
 -	    return FALSE;
 +	    return false;
  	}
  
  	if (!(c->handler(cfg, args->len, argv))) {
- 	    char *ss = g_strdup(error_msg);
+ 	    char *ss = mhl_str_dup(error_msg);
  	    snprintf(error_msg, sizeof(error_msg),
  			 _("%s:%d: %s"), file, line, ss);
  	    g_free(ss);
  	    g_ptr_array_free(args, TRUE);
  	    fclose(fp);
 -	    return FALSE;
 +	    return false;
  	}
  	g_ptr_array_free(args, TRUE);
      }
  
      fclose(fp);
 -    return TRUE;
 +    return true;
  }
  
 -static gboolean
 +static bool
  load_user_keymap(config_t *cfg, const char *file)
  {
      const command_t cmd[] = {
@@@ -581,13 -580,13 +581,13 @@@
      cfg->ext_keymap = g_array_new(TRUE, FALSE, sizeof(edit_key_map_type));
  
      if (!parse_file(cfg, file, cmd)) {
 -	return FALSE;
 +	return false;
      }
  
 -    return TRUE;
 +    return true;
  }
  
 -gboolean
 +bool
  edit_load_user_map(WEdit *edit)
  {
      static config_t cfg;
@@@ -596,16 -595,16 +596,16 @@@
      struct stat s;
  
      if (edit_key_emulation != EDIT_KEY_EMULATION_USER)
 -	return TRUE;
 +	return true;
  
 -    file = concat_dir_and_file(home_dir, MC_USERMAP);
 +    file = mhl_str_dir_plus_file(home_dir, MC_USERMAP);
  
      if (stat(file, &s) < 0) {
  	char *msg = g_strdup_printf(_("%s not found!"), file);
  	edit_error_dialog(_("Error"), msg);
  	g_free(msg);
  	g_free(file);
 -	return FALSE;
 +	return false;
      }
  
      if (s.st_mtime != cfg.mtime) {
@@@ -616,7 -615,7 +616,7 @@@
  	    edit_error_dialog(_("Error"), error_msg);
  	    cfg_free_maps(&new_cfg);
  	    g_free(file);
 -	    return FALSE;
 +	    return false;
  	} else {
  	    cfg_free_maps(&cfg);
  	    cfg = new_cfg;
@@@ -629,5 -628,5 +629,5 @@@
  
      g_free(file);
  
 -    return TRUE;
 +    return true;
  }
diff --combined src/boxes.c
index a46aeec,ad9fe6a..33ec10e
--- a/src/boxes.c
+++ b/src/boxes.c
@@@ -27,10 -27,11 +27,11 @@@
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
  #include <sys/types.h>
  #include <sys/stat.h>
  
+ #include <mhl/string.h>
+ 
  #include "global.h"
  #include "tty.h"
  #include "win.h"		/* Our window tools */
@@@ -197,7 -198,7 +198,7 @@@ display_init (int radio_sel, char *init
  
      status =
  	input_new (10, 9, INPUT_COLOR, DISPLAY_X - 14, _status[radio_sel],
 -		   "mini-input");
 +		   "mini-input", INPUT_COMPLETE_DEFAULT);
      add_widget (dd, status);
      input_set_point (status, 0);
  
@@@ -207,7 -208,7 +208,7 @@@
  
      user =
  	input_new (7, 9, INPUT_COLOR, DISPLAY_X - 14, init_text,
 -		   "user-fmt-input");
 +		   "user-fmt-input", INPUT_COMPLETE_DEFAULT);
      add_widget (dd, user);
      input_set_point (user, 0);
  
@@@ -227,14 -228,14 +228,14 @@@ display_box (WPanel *panel, char **user
          p = get_nth_panel_name (num);
          panel = g_new (WPanel, 1);
          panel->list_type = list_full;
-         panel->user_format = g_strdup (DEFAULT_USER_FORMAT);
+         panel->user_format = mhl_str_dup (DEFAULT_USER_FORMAT);
          panel->user_mini_status = 0;
  	for (i = 0; i < LIST_TYPES; i++)
-     	    panel->user_status_format[i] = g_strdup (DEFAULT_USER_FORMAT);
+     	    panel->user_status_format[i] = mhl_str_dup (DEFAULT_USER_FORMAT);
          section = g_strconcat ("Temporal:", p, (char *) NULL);
          if (!profile_has_section (section, profile_name)) {
              g_free (section);
-             section = g_strdup (p);
+             section = mhl_str_dup (p);
          }
          panel_load_setup (panel, section);
          g_free (section);
@@@ -257,8 -258,8 +258,8 @@@
      
      if (dd->ret_value != B_CANCEL){
  	result = my_radio->sel;
- 	*userp = g_strdup (user->buffer);
- 	*minip = g_strdup (status->buffer);
+ 	*userp = mhl_str_dup (user->buffer);
+ 	*minip = mhl_str_dup (status->buffer);
  	*use_msformat = check_status->state & C_BOOL;
      }
      destroy_dlg (dd);
@@@ -571,7 -572,7 +572,7 @@@ sel_charset_button (int action
  	: codepages[new_display_codepage].name;
  
      /* avoid strange bug with label repainting */
 -    g_snprintf (buf, sizeof (buf), "%-27s", cpname);
 +    snprintf (buf, sizeof (buf), "%-27s", cpname);
      label_set_text (cplabel, buf);
      return 0;
  }
@@@ -691,7 -692,7 +692,7 @@@ tree_box (const char *current_dir
      
      run_dlg (dlg);
      if (dlg->ret_value == B_ENTER)
- 	val = g_strdup (tree_selected_name (mytree));
+ 	val = mhl_str_dup (tree_selected_name (mytree));
      else
  	val = 0;
      
@@@ -772,12 -773,12 +773,12 @@@ configure_vfs (void
      ret_use_netrc = use_netrc;
      ret_ftpfs_use_passive_connections = ftpfs_use_passive_connections;
      ret_ftpfs_use_passive_connections_over_proxy = ftpfs_use_passive_connections_over_proxy;
 -    g_snprintf(buffer3, sizeof (buffer3), "%i", ftpfs_directory_timeout);
 +    snprintf(buffer3, sizeof (buffer3), "%i", ftpfs_directory_timeout);
      confvfs_widgets[8].text = buffer3;
      confvfs_widgets[10].text = ftpfs_anonymous_passwd;
      confvfs_widgets[5].text = ftpfs_proxy_host;
  #endif
 -    g_snprintf (buffer2, sizeof (buffer2), "%i", vfs_timeout);
 +    snprintf (buffer2, sizeof (buffer2), "%i", vfs_timeout);
      confvfs_widgets [3 + VFS_WIDGETBASE].text = buffer2;
  
      if (quick_dialog (&confvfs_dlg) != B_CANCEL) {
@@@ -1085,17 -1086,17 +1086,17 @@@ vfs_smb_get_authinfo (const char *host
  
      g_free (title);
  
 -    in_user  = input_new (5, istart, INPUT_COLOR, ilen, user, "auth_name");
 +    in_user  = input_new (5, istart, INPUT_COLOR, ilen, user, "auth_name", INPUT_COMPLETE_DEFAULT);
      add_widget (auth_dlg, in_user);
  
 -    in_domain = input_new (3, istart, INPUT_COLOR, ilen, domain, "auth_domain");
 +    in_domain = input_new (3, istart, INPUT_COLOR, ilen, domain, "auth_domain", INPUT_COMPLETE_DEFAULT);
      add_widget (auth_dlg, in_domain);
      add_widget (auth_dlg, button_new (9, b2, B_CANCEL, NORMAL_BUTTON,
                   buts[1], 0));
      add_widget (auth_dlg, button_new (9, b0, B_ENTER, DEFPUSH_BUTTON,
                   buts[0], 0));
  
 -    in_password  = input_new (7, istart, INPUT_COLOR, ilen, "", "auth_password");
 +    in_password  = input_new (7, istart, INPUT_COLOR, ilen, "", "auth_password", INPUT_COMPLETE_DEFAULT);
      in_password->completion_flags = 0;
      in_password->is_password = 1;
      add_widget (auth_dlg, in_password);
@@@ -1113,11 -1114,11 +1114,11 @@@
      default:
          return_value = g_new (struct smb_authinfo, 1);
          if (return_value) {
-             return_value->host = g_strdup (host);
-             return_value->share = g_strdup (share);
-             return_value->domain = g_strdup (in_domain->buffer);
-             return_value->user = g_strdup (in_user->buffer);
-             return_value->password = g_strdup (in_password->buffer);
+             return_value->host = mhl_str_dup (host);
+             return_value->share = mhl_str_dup (share);
+             return_value->domain = mhl_str_dup (in_domain->buffer);
+             return_value->user = mhl_str_dup (in_user->buffer);
+             return_value->password = mhl_str_dup (in_password->buffer);
          }
      }
  
diff --combined src/charsets.c
index 4e807c0,142fcab..cb45a52
--- a/src/charsets.c
+++ b/src/charsets.c
@@@ -27,8 -27,6 +27,8 @@@
  
  #include <iconv.h>
  
 +#include <mhl/string.h>
 +
  #include "global.h"
  #include "charsets.h"
  
@@@ -50,7 -48,7 +50,7 @@@ load_codepages_list (void
      extern int display_codepage;
      char *default_codepage = NULL;
  
 -    fname = concat_dir_and_file (mc_home, CHARSETS_INDEX);
 +    fname = mhl_str_dir_plus_file (mc_home, CHARSETS_INDEX);
      if (!(f = fopen (fname, "r"))) {
  	fprintf (stderr, _("Warning: file %s not found\n"), fname);
  	g_free (fname);
@@@ -88,12 -86,12 +88,12 @@@
  	    goto fail;
  
  	if (strcmp (buf, "default") == 0) {
- 	    default_codepage = g_strdup (p);
+ 	    default_codepage = mhl_str_dup (p);
  	    continue;
  	}
  
- 	codepages[n_codepages].id = g_strdup (buf);
- 	codepages[n_codepages].name = g_strdup (p);
+ 	codepages[n_codepages].id = mhl_str_dup (buf);
+ 	codepages[n_codepages].name = mhl_str_dup (p);
  	++n_codepages;
      }
  
@@@ -198,7 -196,7 +198,7 @@@ init_translation_table (int cpsource, i
  
      cd = iconv_open (cpdisp, cpsour);
      if (cd == (iconv_t) - 1) {
 -	g_snprintf (errbuf, sizeof (errbuf),
 +	snprintf (errbuf, sizeof (errbuf),
  		    _("Cannot translate from %s to %s"), cpsour, cpdisp);
  	return errbuf;
      }
@@@ -212,7 -210,7 +212,7 @@@
  
      cd = iconv_open (cpsour, cpdisp);
      if (cd == (iconv_t) - 1) {
 -	g_snprintf (errbuf, sizeof (errbuf),
 +	snprintf (errbuf, sizeof (errbuf),
  		    _("Cannot translate from %s to %s"), cpdisp, cpsour);
  	return errbuf;
      }
diff --combined src/cmd.c
index ee9a3dd,f897cc5..e4b934f
--- a/src/cmd.c
+++ b/src/cmd.c
@@@ -23,7 -23,6 +23,6 @@@
  #include <errno.h>
  #include <stdio.h>
  #include <string.h>
- 
  #include <sys/types.h>
  #include <sys/stat.h>
  #ifdef HAVE_MMAP
@@@ -121,7 -120,7 +120,7 @@@ view_file_at_line (const char *filename
  	char view_entry[BUF_TINY];
  
  	if (start_line != 0)
 -	    g_snprintf (view_entry, sizeof (view_entry), "View:%d",
 +	    snprintf (view_entry, sizeof (view_entry), "View:%d",
  			start_line);
  	else
  	    strcpy (view_entry, "View");
@@@ -371,9 -370,9 +370,9 @@@ mkdir_cmd (void
  	return;
  
      if (dir[0] == '/' || dir[0] == '~')
- 	absdir = g_strdup (dir);
+ 	absdir = mhl_str_dup (dir);
      else
 -	absdir = concat_dir_and_file (current_panel->cwd, dir);
 +	absdir = mhl_str_dir_plus_file (current_panel->cwd, dir);
  
      save_cwds_stat ();
      if (my_mkdir (absdir, 0777) == 0) {
@@@ -579,10 -578,10 +578,10 @@@ void ext_cmd (void
  			    _(" Which extension file you want to edit? "), D_NORMAL, 2,
  			    _("&User"), _("&System Wide"));
      }
 -    extdir = concat_dir_and_file (mc_home, MC_LIB_EXT);
 +    extdir = mhl_str_dir_plus_file (mc_home, MC_LIB_EXT);
  
      if (dir == 0){
 -	buffer = concat_dir_and_file (home_dir, MC_USER_EXT);
 +	buffer = mhl_str_dir_plus_file (home_dir, MC_USER_EXT);
  	check_for_default (extdir, buffer);
  	do_edit (buffer);
  	g_free (buffer);
@@@ -609,21 -608,21 +608,21 @@@ menu_edit_cmd (int where
  	_("&Local"), _("&User"), _("&System Wide")
      );
  
 -    menufile = concat_dir_and_file (mc_home, where ? CEDIT_GLOBAL_MENU : MC_GLOBAL_MENU);
 +    menufile = mhl_str_dir_plus_file (mc_home, where ? CEDIT_GLOBAL_MENU : MC_GLOBAL_MENU);
  
      switch (dir) {
  	case 0:
- 	    buffer = g_strdup (where ? CEDIT_LOCAL_MENU : MC_LOCAL_MENU);
+ 	    buffer = mhl_str_dup (where ? CEDIT_LOCAL_MENU : MC_LOCAL_MENU);
  	    check_for_default (menufile, buffer);
  	    break;
  
  	case 1:
 -	    buffer = concat_dir_and_file (home_dir, where ? CEDIT_HOME_MENU : MC_HOME_MENU);
 +	    buffer = mhl_str_dir_plus_file (home_dir, where ? CEDIT_HOME_MENU : MC_HOME_MENU);
  	    check_for_default (menufile, buffer);
  	    break;
  	
  	case 2:
 -	    buffer = concat_dir_and_file (mc_home, where ? CEDIT_GLOBAL_MENU : MC_GLOBAL_MENU);
 +	    buffer = mhl_str_dir_plus_file (mc_home, where ? CEDIT_GLOBAL_MENU : MC_GLOBAL_MENU);
  	    break;
  
  	default:
@@@ -682,10 -681,10 +681,10 @@@ edit_syntax_cmd (void
  			  _(" Which syntax file you want to edit? "), D_NORMAL, 2,
  			  _("&User"), _("&System Wide"));
      }
 -    extdir = concat_dir_and_file (mc_home, "syntax" PATH_SEP_STR "Syntax");
 +    extdir = mhl_str_dir_plus_file (mc_home, "syntax" PATH_SEP_STR "Syntax");
  
      if (dir == 0) {
 -	buffer = concat_dir_and_file (home_dir, SYNTAX_FILE);
 +	buffer = mhl_str_dir_plus_file (home_dir, SYNTAX_FILE);
  	check_for_default (extdir, buffer);
  	do_edit (buffer);
  	g_free (buffer);
@@@ -816,8 -815,8 +815,8 @@@ compare_dir (WPanel *panel, WPanel *oth
  	    }
  
  	    /* Thorough compare on, do byte-by-byte comparison */
 -	    src_name = concat_dir_and_file (panel->cwd, source->fname);
 -	    dst_name = concat_dir_and_file (other->cwd, target->fname);
 +	    src_name = mhl_str_dir_plus_file (panel->cwd, source->fname);
 +	    dst_name = mhl_str_dir_plus_file (other->cwd, target->fname);
  	    if (compare_files (src_name, dst_name, source->st.st_size))
  		do_file_mark (panel, i, 1);
  	    g_free (src_name);
@@@ -931,12 -930,12 +930,12 @@@ do_link (int symbolic_link, const char 
  	char *d;
  
  	/* suggest the full path for symlink */
 -	s = concat_dir_and_file (current_panel->cwd, fname);
 +	s = mhl_str_dir_plus_file (current_panel->cwd, fname);
  
  	if (get_other_type () == view_listing) {
 -	    d = concat_dir_and_file (other_panel->cwd, fname);
 +	    d = mhl_str_dir_plus_file (other_panel->cwd, fname);
  	} else {
- 	    d = g_strdup (fname);
+ 	    d = mhl_str_dup (fname);
  	}
  
  	symlink_dialog (s, d, &dest, &src);
@@@ -1055,7 -1054,7 +1054,7 @@@ char *guess_message_value (void
      if (locale == NULL)
  	locale = "";
  
-     return g_strdup (locale);
+     return mhl_str_dup (locale);
  }
  
  /*
@@@ -1073,7 -1072,7 +1072,7 @@@ get_random_hint (int force
      /* Do not change hints more often than one minute */
      gettimeofday (&tv, NULL);
      if (!force && !(tv.tv_sec > last_sec + 60))
- 	return g_strdup ("");
+ 	return mhl_str_dup ("");
      last_sec = tv.tv_sec;
  
      data = load_mc_home_file (MC_HINT, NULL);
@@@ -1094,7 -1093,7 +1093,7 @@@
      eol = strchr (&data[start], '\n');
      if (eol)
  	*eol = 0;
-     result = g_strdup (&data[start]);
+     result = mhl_str_dup (&data[start]);
      g_free (data);
      return result;
  }
diff --combined src/command.c
index 7b7b7c9,49cf09c..644a35c
--- a/src/command.c
+++ b/src/command.c
@@@ -27,14 -27,13 +27,14 @@@
  #include <errno.h>
  #include <string.h>
  
 +#include <mhl/memory.h>
 +#include <mhl/escape.h>
  #include <mhl/string.h>
  
  #include "global.h"		/* home_dir */
  #include "tty.h"
  #include "widget.h"		/* WInput */
  #include "command.h"
 -#include "complete.h"		/* completion constants */
  #include "wtools.h"		/* message () */
  #include "panel.h"		/* view_tree enum. Also, needed by main.h */
  #include "main.h"		/* do_cd */
@@@ -67,7 -66,6 +67,7 @@@ examine_cd (char *path
      const char *t;
  
      /* Tilde expansion */
 +    path = mhl_shell_unescape_buf(path);
      path_tilde = tilde_expand (path);
  
      /* Leave space for further expansion */
@@@ -115,7 -113,7 +115,7 @@@
  
      /* CDPATH handling */
      if (*q != PATH_SEP && !result) {
- 	char * const cdpath = g_strdup (getenv ("CDPATH"));
+ 	char * const cdpath = mhl_str_dup (getenv ("CDPATH"));
  	char *p = cdpath;
  	if (p == NULL)
  	    c = 0;
@@@ -128,7 -126,7 +128,7 @@@
  	    c = *s;
  	    *s = 0;
  	    if (*p) {
 -		r = concat_dir_and_file (p, q);
 +		r = mhl_str_dir_plus_file (p, q);
  		result = do_cd (r, cd_parse_command);
  		g_free (r);
  	    }
@@@ -139,7 -137,6 +139,7 @@@
      }
      g_free (q);
      g_free (path_tilde);
 +//    mhl_mem_free(path);
      return result;
  }
  
@@@ -181,13 -178,13 +181,13 @@@ void do_cd_command (char *cmd
  	} else {
  	    char *old = current_panel->cwd;
  	    char *new;
 -	    new = concat_dir_and_file (old, cmd+3);
 +	    new = mhl_str_dir_plus_file (old, cmd+3);
  	    sync_tree (new);
  	    g_free (new);
  	}
      } else
  	if (!examine_cd (&cmd [3])) {
- 	    char *d = strip_password (g_strdup (&cmd [3]), 1);
+ 	    char *d = strip_password (mhl_str_dup (&cmd [3]), 1);
  	    message (D_ERROR, MSG_ERROR, _(" Cannot chdir to \"%s\" \n %s "),
  		     d, unix_error_string (errno));
  	    g_free (d);
@@@ -295,8 -292,7 +295,8 @@@ command_new (int y, int x, int cols
  {
      WInput *cmd;
  
 -    cmd = input_new (y, x, DEFAULT_COLOR, cols, "", "cmdline");
 +    cmd = input_new (y, x, DEFAULT_COLOR, cols, "", "cmdline",
 +	INPUT_COMPLETE_DEFAULT | INPUT_COMPLETE_CD | INPUT_COMPLETE_COMMANDS | INPUT_COMPLETE_SHELL_ESC);
  
      /* Add our hooks */
      cmd->widget.callback = command_callback;
diff --combined src/complete.c
index 94e1895,4fcd088..d8c7f07
--- a/src/complete.c
+++ b/src/complete.c
@@@ -30,8 -30,6 +30,8 @@@
  #include <sys/stat.h>
  #include <unistd.h>
  
 +#include <mhl/memory.h>
 +#include <mhl/escape.h>
  #include <mhl/string.h>
  
  #include "global.h"
@@@ -41,38 -39,21 +41,38 @@@
  #include "dialog.h"
  #include "widget.h"
  #include "wtools.h"
 -#include "complete.h"
  #include "main.h"
 +#include "util.h"
  #include "key.h"		/* XCTRL and ALT macros */
  
 -typedef char *CompletionFunction (char *, int);
 +typedef char *CompletionFunction (char * text, int state, INPUT_COMPLETE_FLAGS flags);
  
 -/* This flag is used in filename_completion_function */
 -static int ignore_filenames = 0;
 +//#define DO_COMPLETION_DEBUG
 +#ifdef DO_COMPLETION_DEBUG
 +/*
 + * Useful to print/debug completion flags
 + */
 +static const char * show_c_flags(INPUT_COMPLETE_FLAGS flags)
 +{
 +    static char s_cf[] = "FHCVUDS";
  
 -/* This flag is used by command_completion_function */
 -/* to hint the filename_completion_function */
 -static int look_for_executables = 0;
 +    s_cf[0] = (flags & INPUT_COMPLETE_FILENAMES) ? 'F' : ' ';
 +    s_cf[1] = (flags & INPUT_COMPLETE_HOSTNAMES) ? 'H' : ' ';
 +    s_cf[2] = (flags & INPUT_COMPLETE_COMMANDS)  ? 'C' : ' ';
 +    s_cf[3] = (flags & INPUT_COMPLETE_VARIABLES) ? 'V' : ' ';
 +    s_cf[4] = (flags & INPUT_COMPLETE_USERNAMES) ? 'U' : ' ';
 +    s_cf[5] = (flags & INPUT_COMPLETE_CD)        ? 'D' : ' ';
 +    s_cf[6] = (flags & INPUT_COMPLETE_SHELL_ESC) ? 'S' : ' ';
 +
 +    return s_cf;
 +}
 +#define SHOW_C_CTX(func) fprintf(stderr, "%s: text='%s' flags=%s\n", func, text, show_c_flags(flags))
 +#else
 +#define SHOW_C_CTX(func)
 +#endif /* DO_CMPLETION_DEBUG */
  
  static char *
 -filename_completion_function (char *text, int state)
 +filename_completion_function (char *text, int state, INPUT_COMPLETE_FLAGS flags)
  {
      static DIR *directory;
      static char *filename = NULL;
@@@ -83,11 -64,6 +83,11 @@@
  
      struct dirent *entry = NULL;
  
 +    SHOW_C_CTX("filename_completion_function");
 +
 +    if (text && (flags & INPUT_COMPLETE_SHELL_ESC))
 +        text = mhl_shell_unescape_buf (text);
 +
      /* If we're starting the match process, initialize us a bit. */
      if (!state){
          const char *temp;
@@@ -97,11 -73,11 +97,11 @@@
          g_free (users_dirname);
  
  	if ((*text) && (temp = strrchr (text, PATH_SEP))){
- 	    filename = g_strdup (++temp);
+ 	    filename = mhl_str_dup (++temp);
  	    dirname = g_strndup (text, temp - text);
  	} else {
- 	    dirname = g_strdup (".");
- 	    filename = g_strdup (text);
+ 	    dirname = mhl_str_dup (".");
+ 	    filename = mhl_str_dup (text);
  	}
  
          /* We aren't done yet.  We also support the "~user" syntax. */
@@@ -109,7 -85,6 +109,7 @@@
          /* Save the version of the directory that the user typed. */
          users_dirname = dirname;
          {
 +	    // FIXME: memleak ?
  	    dirname = tilde_expand (dirname);
  	    canonicalize_pathname (dirname);
  	    /* Here we should do something with variable expansion
@@@ -161,15 -136,18 +161,15 @@@
  	    }
  	   g_free (tmp);
  	}
 -	switch (look_for_executables)
 -	{
 -	    case 2: if (!isexec)
 -	    	        continue;
 -	    	    break;
 -	    case 1: if (!isexec && !isdir)
 -	    	        continue;
 -	    	    break;
 -	}
 -	if (ignore_filenames && !isdir)
 -	    continue;
 -	break;
 +	if ((flags & INPUT_COMPLETE_COMMANDS)
 +	    && (isexec || isdir))
 +	    break;
 +	if ((flags & INPUT_COMPLETE_CD)
 +	    && isdir)
 +	    break;
 +	if (flags & (INPUT_COMPLETE_FILENAMES))
 +	    break;
 +	continue;
      }
  
      if (!entry){
@@@ -203,28 -181,18 +203,28 @@@
  	}
  	if (isdir)
  	    strcat (temp, PATH_SEP_STR);
 -        return temp;
 +
 +	if (temp && (flags & INPUT_COMPLETE_SHELL_ESC))
 +	{
 +	    SHELL_ESCAPED_STR e_temp = mhl_shell_escape_dup(temp);
 +	    mhl_mem_free (temp);
 +	    temp = e_temp.s;
 +	}
 +	return temp;
      }
  }
  
  /* We assume here that text[0] == '~' , if you want to call it in another way,
     you have to change the code */
  static char *
 -username_completion_function (char *text, int state)
 +username_completion_function (char *text, int state, INPUT_COMPLETE_FLAGS flags)
  {
      static struct passwd *entry;
      static int userlen;
  
 +    SHOW_C_CTX("username_completion_function");
 +
 +    if (text[0] == '\\' && text[1] == '~') text++;
      if (!state){ /* Initialization stuff */
          setpwent ();
          userlen = strlen (text + 1);
@@@ -259,14 -227,12 +259,14 @@@ extern char **environ
  /* We assume text [0] == '$' and want to have a look at text [1], if it is
     equal to '{', so that we should append '}' at the end */
  static char *
 -variable_completion_function (char *text, int state)
 +variable_completion_function (char *text, int state, INPUT_COMPLETE_FLAGS flags)
  {
      static char **env_p;
      static int varlen, isbrace;
      const char *p = NULL;
  
 +    SHOW_C_CTX("variable_completion_function");
 +
      if (!state){ /* Initialization stuff */
  	isbrace = (text [1] == '{');
          varlen = strlen (text + 1 + isbrace);
@@@ -376,13 -342,11 +376,13 @@@ static void fetch_hosts (const char *fi
  }
  
  static char *
 -hostname_completion_function (char *text, int state)
 +hostname_completion_function (char *text, int state, INPUT_COMPLETE_FLAGS flags)
  {
      static char **host_p;
      static int textstart, textlen;
  
 +    SHOW_C_CTX("hostname_completion_function");
 +
      if (!state){ /* Initialization stuff */
          const char *p;
          
@@@ -432,7 -396,7 +432,7 @@@
   * table of shell built-ins.
   */
  static char *
 -command_completion_function (char *text, int state)
 +command_completion_function (char *text, int state, INPUT_COMPLETE_FLAGS flags)
  {
      static const char *path_end;
      static int isabsolute;
@@@ -458,21 -422,14 +458,21 @@@
      };
      char *p, *found;
  
 +    SHOW_C_CTX("command_completion_function");
 +
 +    if (!(flags & INPUT_COMPLETE_COMMANDS))
 +        return 0;
 +
 +    text = mhl_shell_unescape_buf(text);
 +    flags &= ~INPUT_COMPLETE_SHELL_ESC;
 +
      if (!state) {		/* Initialize us a little bit */
  	isabsolute = strchr (text, PATH_SEP) != 0;
 -	look_for_executables = isabsolute ? 1 : 2;
  	if (!isabsolute) {
  	    words = bash_reserved;
  	    phase = 0;
  	    text_len = strlen (text);
- 	    if (!path && (path = g_strdup (getenv ("PATH"))) != NULL) {
+ 	    if (!path && (path = mhl_str_dup (getenv ("PATH"))) != NULL) {
  		p = path;
  		path_end = strchr (p, 0);
  		while ((p = strchr (p, PATH_ENV_SEP))) {
@@@ -483,12 -440,10 +483,12 @@@
      }
  
      if (isabsolute) {
 -	p = filename_completion_function (text, state);
 +	p = filename_completion_function (text, state, flags);
  	if (!p)
 -	    look_for_executables = 0;
 -	return p;
 +	    return 0;
 +	SHELL_ESCAPED_STR e_p = mhl_shell_escape_dup(p);
 +	mhl_mem_free(p);
 +	return e_p.s;
      }
  
      found = NULL;
@@@ -496,7 -451,7 +496,7 @@@
      case 0:			/* Reserved words */
  	while (*words) {
  	    if (!strncmp (*words, text, text_len))
- 		return g_strdup (*(words++));
+ 		return mhl_str_dup (*(words++));
  	    words++;
  	}
  	phase++;
@@@ -504,7 -459,7 +504,7 @@@
      case 1:			/* Builtin commands */
  	while (*words) {
  	    if (!strncmp (*words, text, text_len))
- 		return g_strdup (*(words++));
+ 		return mhl_str_dup (*(words++));
  	    words++;
  	}
  	phase++;
@@@ -520,7 -475,7 +520,7 @@@
  		if (cur_path >= path_end)
  		    break;
  		expanded = tilde_expand (*cur_path ? cur_path : ".");
 -		cur_word = concat_dir_and_file (expanded, text);
 +		cur_word = mhl_str_dir_plus_file (expanded, text);
  		g_free (expanded);
  		canonicalize_pathname (cur_word);
  		cur_path = strchr (cur_path, 0) + 1;
@@@ -528,7 -483,7 +528,7 @@@
  	    }
  	    found =
  		filename_completion_function (cur_word,
 -					      state - init_state);
 +					      state - init_state, flags);
  	    if (!found) {
  		g_free (cur_word);
  		cur_word = NULL;
@@@ -537,16 -492,16 +537,16 @@@
      }
  
      if (!found) {
 -	look_for_executables = 0;
  	g_free (path);
  	path = NULL;
  	return NULL;
      }
      if ((p = strrchr (found, PATH_SEP)) != NULL) {
  	p++;
 -	p = mhl_str_dup (p);
 -	g_free (found);
 -	return p;
 +
 +	SHELL_ESCAPED_STR e_p = mhl_shell_escape_dup(p);
 +	mhl_mem_free(found);
 +	return e_p.s;
      }
      return found;
  
@@@ -566,7 -521,7 +566,7 @@@ match_compare (const void *a, const voi
     as the second. 
     In case no matches were found we return NULL. */
  static char **
 -completion_matches (char *text, CompletionFunction entry_function)
 +completion_matches (char *text, CompletionFunction entry_function, INPUT_COMPLETE_FLAGS flags)
  {
      /* Number of slots in match_list. */
      int match_list_size;
@@@ -582,7 -537,7 +582,7 @@@
  
      match_list[1] = NULL;
  
 -    while ((string = (*entry_function) (text, matches)) != NULL){
 +    while ((string = (*entry_function) (text, matches, flags)) != NULL){
          if (matches + 1 == match_list_size)
  	    match_list = (char **) g_realloc (match_list, ((match_list_size += 30) + 1) * sizeof (char *));
          match_list[++matches] = string;
@@@ -642,12 -597,14 +642,12 @@@
  
  /* Check if directory completion is needed */
  static int
 -check_is_cd (const char *text, int start, int flags)
 +check_is_cd (const char *text, int start, INPUT_COMPLETE_FLAGS flags)
  {
      const char *p, *q;
  
 -    if (flags & INPUT_COMPLETE_CD)
 -	return 1;
 -
 -    if (!(flags & INPUT_COMPLETE_COMMANDS))
 +    SHOW_C_CTX("check_is_cd");
 +    if (!(flags & INPUT_COMPLETE_CD))
  	return 0;
  
      /* Skip initial spaces */
@@@ -666,20 -623,19 +666,20 @@@
  
  /* Returns an array of matches, or NULL if none. */
  static char **
 -try_complete (char *text, int *start, int *end, int flags)
 +try_complete (char *text, int *start, int *end, INPUT_COMPLETE_FLAGS flags)
  {
 -    int in_command_position = 0, i;
 +    int in_command_position = 0;
      char *word, c;
      char **matches = NULL;
      const char *command_separator_chars = ";|&{(`";
      char *p = NULL, *q = NULL, *r = NULL;
      int is_cd = check_is_cd (text, *start, flags);
  
 -    ignore_filenames = 0;
 +    SHOW_C_CTX("try_complete");
 +
      c = text [*end];
      text [*end] = 0;
-     word = g_strdup (text + *start);
+     word = mhl_str_dup (text + *start);
      text [*end] = c;
  
      /* Determine if this could be a command word. It is if it appears at
@@@ -687,16 -643,9 +687,16 @@@
         appears after a character that separates commands. And we have to
         be in a INPUT_COMPLETE_COMMANDS flagged Input line. */
      if (!is_cd && (flags & INPUT_COMPLETE_COMMANDS)){
 -        i = *start - 1;
 -        while (i > -1 && (text[i] == ' ' || text[i] == '\t'))
 -            i--;
 +        int i = *start - 1;
 +	for (i = *start - 1; i > -1; i--) {
 +	    if (text[i] == ' ' || text[i] == '\t'){
 +		if (i == 0 ) continue;
 +		if (text[i-1] != '\\') {
 +		    i--;
 +		    break;
 +		}
 +	    }
 +	}
          if (i < 0)
  	    in_command_position++;
          else if (strchr (command_separator_chars, text[i])){
@@@ -730,19 -679,17 +730,19 @@@
      	    p = q + 1;
      	q = NULL;
      }
 -    
 +
      /* Command substitution? */
      if (p > q && p > r){
 -        matches = completion_matches (p + 1, command_completion_function);
 +        SHOW_C_CTX("try_complete:cmd_backq_subst");
 +        matches = completion_matches (p + 1, command_completion_function, flags & (~INPUT_COMPLETE_FILENAMES));
          if (matches)
              *start += p + 1 - word;
      }
  
      /* Variable name? */
      else if  (q > p && q > r){
 -        matches = completion_matches (q, variable_completion_function);
 +        SHOW_C_CTX("try_complete:var_subst");
 +        matches = completion_matches (q, variable_completion_function, flags);
          if (matches)
              *start += q - word;
      }
@@@ -750,8 -697,7 +750,8 @@@
      /* Starts with '@', then look through the known hostnames for 
         completion first. */
      else if (r > p && r > q){
 -        matches = completion_matches (r, hostname_completion_function);
 +        SHOW_C_CTX("try_complete:host_subst");
 +        matches = completion_matches (r, hostname_completion_function, flags);
          if (matches)
              *start += r - word;
      }
@@@ -759,48 -705,28 +759,48 @@@
      /* Starts with `~' and there is no slash in the word, then
         try completing this word as a username. */
      if (!matches && *word == '~' && (flags & INPUT_COMPLETE_USERNAMES) && !strchr (word, PATH_SEP))
 -        matches = completion_matches (word, username_completion_function);
 +    {
 +        SHOW_C_CTX("try_complete:user_subst");
 +        matches = completion_matches (word, username_completion_function, flags);
 +    }
  
  
      /* And finally if this word is in a command position, then
         complete over possible command names, including aliases, functions,
         and command names. */
      if (!matches && in_command_position)
 -        matches = completion_matches (word, command_completion_function);
 +    {
 +        SHOW_C_CTX("try_complete:cmd_subst");
 +        matches = completion_matches (word, command_completion_function, flags & (~INPUT_COMPLETE_FILENAMES));
 +    }
          
      else if (!matches && (flags & INPUT_COMPLETE_FILENAMES)){
 -    	if (is_cd)
 -    	    ignore_filenames = 1;
 -    	matches = completion_matches (word, filename_completion_function);
 -    	ignore_filenames = 0;
 +	if (is_cd)
 +	    flags &= ~(INPUT_COMPLETE_FILENAMES | INPUT_COMPLETE_COMMANDS);
 +	SHOW_C_CTX("try_complete:filename_subst_1");
 +	matches = completion_matches (word, filename_completion_function, flags);
      	if (!matches && is_cd && *word != PATH_SEP && *word != '~'){
      	    char *p, *q = text + *start;
 -    	    
 -    	    for (p = text; *p && p < q && (*p == ' ' || *p == '\t'); p++);
 +
 +	    for (p = text; *p && p < q; p++){
 +		if (*p == ' ' || *p == '\t') {
 +		    if (p == text) continue;
 +		    if (*(p-1) == '\\') {
 +			p--;
 +			break;
 +		    }
 +		}
 +	    }
      	    if (!strncmp (p, "cd", 2))
 -    	        for (p += 2; *p && p < q && (*p == ' ' || *p == '\t'); p++);
 +		for (p += 2; *p && p < q && (*p == ' ' || *p == '\t'); p++){
 +		    if (p == text) continue;
 +		    if (*(p-1) == '\\') {
 +			p--;
 +			break;
 +		    }
 +		}
      	    if (p == q){
- 		char * const cdpath_ref = g_strdup (getenv ("CDPATH"));
+ 		char * const cdpath_ref = mhl_str_dup (getenv ("CDPATH"));
  		char *cdpath = cdpath_ref;
  		char c, *s, *r;
  
@@@ -815,10 -741,11 +815,10 @@@
  		    c = *s; 
  		    *s = 0;
  		    if (*cdpath){
 -			r = concat_dir_and_file (cdpath, word);
 -		        ignore_filenames = 1;
 -    	    		matches = completion_matches (r, filename_completion_function);
 -    	    		ignore_filenames = 0;
 -    	    		g_free (r);
 +			r = mhl_str_dir_plus_file (cdpath, word);
 +			SHOW_C_CTX("try_complete:filename_subst_2");
 +			matches = completion_matches (r, filename_completion_function, flags);
 +			g_free (r);
  		    }
  		    *s = c;
  		    cdpath = s + 1;
@@@ -990,21 -917,15 +990,21 @@@ complete_engine (WInput *in, int what_t
      if (!in->completions){
      	end = in->point;
          for (start = end ? end - 1 : 0; start > -1; start--)
 -    	    if (strchr (" \t;|<>", in->buffer [start]))
 -    	        break;
 +    	    if (strchr (" \t;|<>", in->buffer [start])){
 +    		if (start > 0 && in->buffer [start-1] == '\\')
 +    		    continue;
 +    		else
 +    		    break;
 +    	    }
      	if (start < end)
      	    start++;
      	in->completions = try_complete (in->buffer, &start, &end, in->completion_flags);
      }
 +    
      if (in->completions){
      	if (what_to_do & DO_INSERTION || ((what_to_do & DO_QUERY) && !in->completions[1])) {
 -    	    if (insert_text (in, in->completions [0], strlen (in->completions [0]))){
 +	        char * complete = in->completions [0];
 +	    if (insert_text (in, complete, strlen (complete))){
      	        if (in->completions [1])
      	    	    beep ();
  		else
@@@ -1019,11 -940,10 +1019,11 @@@
      	    char **p, *q;
      	    Dlg_head *query_dlg;
      	    WListbox *query_list;
 -    	    
 -    	    for (p=in->completions + 1; *p; count++, p++)
 -    	    	if ((i = strlen (*p)) > maxlen)
 -    	    	    maxlen = i;
 +
 +    	    for (p=in->completions + 1; *p; count++, p++) {
 +		if ((i = strlen (*p)) > maxlen)
 +		    maxlen = i;
 +	    }
      	    start_x = in->widget.x;
      	    start_y = in->widget.y;
      	    if (start_y - 2 >= count) {
diff --combined src/ecs.c
index 33e9897,2b0df72..3fa3da6
--- a/src/ecs.c
+++ b/src/ecs.c
@@@ -27,7 -27,7 +27,8 @@@
  #include <assert.h>
  #include <ctype.h>
  
 +#include <mhl/types.h>
+ #include <mhl/string.h>
  
  #include "global.h"
  #include "ecs.h"
@@@ -36,7 -36,7 +37,7 @@@
   * String type conversion
   */
  
 -extern gboolean ecs_mbstr_to_str(ecs_char **ret_str, const char *s)
 +extern bool ecs_mbstr_to_str(ecs_char **ret_str, const char *s)
  {
  #ifdef EXTCHARSET_ENABLED
  	size_t maxlen, len;
@@@ -55,12 -55,12 +56,12 @@@
  	*ret_str = g_renew(ecs_char, str, len + 1);
  	return TRUE;
  #else
- 	*ret_str = g_strdup(s);
+ 	*ret_str = mhl_str_dup(s);
  	return TRUE;
  #endif
  }
  
 -extern gboolean ecs_str_to_mbstr(char **ret_str, const ecs_char *s)
 +extern bool ecs_str_to_mbstr(char **ret_str, const ecs_char *s)
  {
  #ifdef EXTCHARSET_ENABLED
  	size_t maxlen, len;
@@@ -79,7 -79,7 +80,7 @@@
  	*ret_str = g_renew(char, str, len + 1);
  	return TRUE;
  #else
- 	*ret_str = g_strdup(s);
+ 	*ret_str = mhl_str_dup(s);
  	return TRUE;
  #endif
  }
@@@ -102,57 -102,57 +103,57 @@@
  	(cf(c))
  #endif
  
 -extern gboolean ecs_isalnum(ecs_char c)
 +extern bool ecs_isalnum(ecs_char c)
  {
  	return ECS_CTYPE(iswalnum, isalnum, c);
  }
  
 -extern gboolean ecs_isalpha(ecs_char c)
 +extern bool ecs_isalpha(ecs_char c)
  {
  	return ECS_CTYPE(iswalpha, isalpha, c);
  }
  
 -extern gboolean ecs_iscntrl(ecs_char c)
 +extern bool ecs_iscntrl(ecs_char c)
  {
  	return ECS_CTYPE(iswcntrl, iscntrl, c);
  }
  
 -extern gboolean ecs_isdigit(ecs_char c)
 +extern bool ecs_isdigit(ecs_char c)
  {
  	return ECS_CTYPE(iswdigit, isdigit, c);
  }
  
 -extern gboolean ecs_isgraph(ecs_char c)
 +extern bool ecs_isgraph(ecs_char c)
  {
  	return ECS_CTYPE(iswgraph, isgraph, c);
  }
  
 -extern gboolean ecs_islower(ecs_char c)
 +extern bool ecs_islower(ecs_char c)
  {
  	return ECS_CTYPE(iswlower, islower, c);
  }
  
 -extern gboolean ecs_isprint(ecs_char c)
 +extern bool ecs_isprint(ecs_char c)
  {
  	return ECS_CTYPE(iswprint, isprint, c);
  }
  
 -extern gboolean ecs_ispunct(ecs_char c)
 +extern bool ecs_ispunct(ecs_char c)
  {
  	return ECS_CTYPE(iswpunct, ispunct, c);
  }
  
 -extern gboolean ecs_isspace(ecs_char c)
 +extern bool ecs_isspace(ecs_char c)
  {
  	return ECS_CTYPE(iswspace, isspace, c);
  }
  
 -extern gboolean ecs_isupper(ecs_char c)
 +extern bool ecs_isupper(ecs_char c)
  {
  	return ECS_CTYPE(iswupper, isupper, c);
  }
  
 -extern gboolean ecs_isxdigit(ecs_char c)
 +extern bool ecs_isxdigit(ecs_char c)
  {
  	return ECS_CTYPE(iswxdigit, isxdigit, c);
  }
@@@ -316,7 -316,7 +317,7 @@@ ecs_strlcat(ecs_char *dst, const ecs_ch
  	return di + ecs_strlcpy(dst + di, src, dstsize - di);
  }
  
 -gboolean
 +bool
  ecs_strbox(const ecs_char *s, size_t *ret_width, size_t *ret_height)
  {
  	size_t nlines = 0, ncolumns = 0, colindex = 0, i;
diff --combined src/ext.c
index 2699bd8,58da082..329928b
--- a/src/ext.c
+++ b/src/ext.c
@@@ -441,11 -441,11 +441,11 @@@ regex_command (const char *filename, co
  	int mc_user_ext = 1;
  	int home_error = 0;
  
 -	extension_file = concat_dir_and_file (home_dir, MC_USER_EXT);
 +	extension_file = mhl_str_dir_plus_file (home_dir, MC_USER_EXT);
  	if (!exist_file (extension_file)) {
  	    g_free (extension_file);
  	  check_stock_mc_ext:
 -	    extension_file = concat_dir_and_file (mc_home, MC_LIB_EXT);
 +	    extension_file = mhl_str_dir_plus_file (mc_home, MC_LIB_EXT);
  	    mc_user_ext = 0;
  	}
  	data = load_file (extension_file);
@@@ -591,7 -591,7 +591,7 @@@
  			 * we get filename as a pointer from current_panel->dir).
  			 */
  			if (p < q) {
- 			    char *filename_copy = g_strdup (filename);
+ 			    char *filename_copy = mhl_str_dup (filename);
  
  			    exec_extension (filename_copy, r + 1, move_dir,
  					    view_at_line_number);
diff --combined src/file.c
index ffc93dd,ec56d78..c5dac13
--- a/src/file.c
+++ b/src/file.c
@@@ -45,14 -45,10 +45,13 @@@
  #include <errno.h>
  #include <stdio.h>
  #include <string.h>
- 
  #include <sys/types.h>
  #include <sys/stat.h>
  #include <unistd.h>
  
 +#include <mhl/types.h>
 +#include <mhl/memory.h>
 +#include <mhl/escape.h>
  #include <mhl/string.h>
  
  #include "global.h"
@@@ -68,7 -64,6 +67,7 @@@
  #include "widget.h"
  #include "wtools.h"
  #include "background.h"		/* we_are_background */
 +#include "util.h"
  
  /* Needed for current_panel, other_panel and WTree */
  #include "dir.h"
@@@ -182,43 -177,37 +181,43 @@@ do_transform_source (FileOpContext *ctx
      for (next_reg = 1, j = 0, k = 0; j < strlen (ctx->dest_mask); j++) {
  	switch (ctx->dest_mask[j]) {
  	case '\\':
 -	    j++;
 -	    if (!isdigit ((unsigned char) ctx->dest_mask[j])) {
 -		/* Backslash followed by non-digit */
 -		switch (ctx->dest_mask[j]) {
 -		case 'U':
 -		    case_conv |= UP_SECT;
 -		    case_conv &= ~LOW_SECT;
 -		    break;
 -		case 'u':
 -		    case_conv |= UP_CHAR;
 -		    break;
 -		case 'L':
 -		    case_conv |= LOW_SECT;
 -		    case_conv &= ~UP_SECT;
 -		    break;
 -		case 'l':
 -		    case_conv |= LOW_CHAR;
 -		    break;
 -		case 'E':
 -		    case_conv = NO_CONV;
 -		    break;
 -		default:
 -		    /* Backslash as quote mark */
 -		    fntarget[k++] =
 -			convert_case (ctx->dest_mask[j], &case_conv);
 -		}
 +	    if (mhl_shell_is_char_escaped (&ctx->dest_mask[j])){
 +		fntarget[k++] = ctx->dest_mask[j++];
 +		fntarget[k++] = ctx->dest_mask[j];
  		break;
  	    } else {
 -		/* Backslash followed by digit */
 -		next_reg = ctx->dest_mask[j] - '0';
 -		/* Fall through */
 +		j++;
 +		if (!isdigit ((unsigned char) ctx->dest_mask[j])) {
 +		    /* Backslash followed by non-digit */
 +		    switch (ctx->dest_mask[j]) {
 +		    case 'U':
 +			case_conv |= UP_SECT;
 +			case_conv &= ~LOW_SECT;
 +			break;
 +		    case 'u':
 +			case_conv |= UP_CHAR;
 +			break;
 +		    case 'L':
 +			case_conv |= LOW_SECT;
 +			case_conv &= ~UP_SECT;
 +			break;
 +		    case 'l':
 +			case_conv |= LOW_CHAR;
 +			break;
 +		    case 'E':
 +			case_conv = NO_CONV;
 +			break;
 +		    default:
 +			/* Backslash as quote mark */
 +			fntarget[k++] =
 +			    convert_case (ctx->dest_mask[j], &case_conv);
 +		    }
 +		    break;
 +		} else {
 +		    /* Backslash followed by digit */
 +		    next_reg = ctx->dest_mask[j] - '0';
 +		    /* Fall through */
 +		}
  	    }
  
  	case '*':
@@@ -246,7 -235,7 +245,7 @@@
  static const char *
  transform_source (FileOpContext *ctx, const char *source)
  {
-     char *s = g_strdup (source);
+     char *s = mhl_str_dup (source);
      char *q;
      const char *p;
  
@@@ -393,7 -382,7 +392,7 @@@ make_symlink (FileOpContext *ctx, cons
  	if (r) {
  	    p = g_strndup (src_path, r - src_path + 1);
  	    if (*dst_path == PATH_SEP)
- 		q = g_strdup (dst_path);
+ 		q = mhl_str_dup (dst_path);
  	    else
  		q = g_strconcat (p, dst_path, (char *) NULL);
  	    s = strrchr (q, PATH_SEP);
@@@ -803,7 -792,7 +802,7 @@@ copy_file_file (FileOpContext *ctx, con
  	    }
  	}
  
 -	if (!appending) {
 +	if (!appending && ctx->preserve) {
  	    while (mc_chmod (dst_path, (src_mode & ctx->umask_kill))) {
  		temp_status = file_error (
  			_(" Cannot chmod target file \"%s\" \n %s "), dst_path);
@@@ -903,7 -892,7 +902,7 @@@ copy_dir_dir (FileOpContext *ctx, cons
  		return FILE_CONT;
  	    }
  	}
- 	dest_dir = g_strdup (d);
+ 	dest_dir = mhl_str_dup (d);
      } else {
  	/*
  	 * If the destination directory exists, we want to copy the whole
@@@ -923,9 -912,9 +922,9 @@@
  	}
  	/* Dive into subdir if exists */
  	if (toplevel && ctx->dive_into_subdirs) {
 -	    dest_dir = concat_dir_and_file (d, x_basename (s));
 +	    dest_dir = mhl_str_dir_plus_file (d, x_basename (s));
  	} else {
- 	    dest_dir = g_strdup (d);
+ 	    dest_dir = mhl_str_dup (d);
  	    goto dont_mkdir;
  	}
      }
@@@ -969,11 -958,11 +968,11 @@@
  	    continue;
  
  	/* get the filename and add it to the src directory */
 -	path = concat_dir_and_file (s, next->d_name);
 +	path = mhl_str_dir_plus_file (s, next->d_name);
  
  	(*ctx->stat_func) (path, &buf);
  	if (S_ISDIR (buf.st_mode)) {
 -	    mdpath = concat_dir_and_file (dest_dir, next->d_name);
 +	    mdpath = mhl_str_dir_plus_file (dest_dir, next->d_name);
  	    /*
  	     * From here, we just intend to recursively copy subdirs, not
  	     * the double functionality of copying different when the target
@@@ -984,7 -973,7 +983,7 @@@
  				parent_dirs, progress_count, progress_bytes);
  	    g_free (mdpath);
  	} else {
 -	    dest_file = concat_dir_and_file (dest_dir, x_basename (path));
 +	    dest_file = mhl_str_dir_plus_file (dest_dir, x_basename (path));
  	    return_status = copy_file_file (ctx, path, dest_file, 1,
  					    progress_count, progress_bytes, 0);
  	    g_free (dest_file);
@@@ -1035,7 -1024,7 +1034,7 @@@ move_file_file (FileOpContext *ctx, con
  {
      struct stat src_stats, dst_stats;
      int return_status = FILE_CONT;
 -    gboolean copy_done = FALSE;
 +    bool copy_done = FALSE;
  
      if (file_progress_show_source (ctx, s) == FILE_ABORT
  	|| file_progress_show_target (ctx, d) == FILE_ABORT)
@@@ -1169,12 -1158,12 +1168,12 @@@ move_dir_dir (FileOpContext *ctx, cons
  
      mc_stat (s, &sbuf);
      if (mc_stat (d, &dbuf))
- 	destdir = g_strdup (d);	/* destination doesn't exist */
+ 	destdir = mhl_str_dup (d);	/* destination doesn't exist */
      else if (!ctx->dive_into_subdirs) {
- 	destdir = g_strdup (d);
+ 	destdir = mhl_str_dup (d);
  	move_over = 1;
      } else
 -	destdir = concat_dir_and_file (d, x_basename (s));
 +	destdir = mhl_str_dir_plus_file (d, x_basename (s));
  
      if (sbuf.st_dev == dbuf.st_dev && sbuf.st_ino == dbuf.st_ino) {
  	int msize = COLS - 36;
@@@ -1331,7 -1320,7 +1330,7 @@@ recursive_erase (FileOpContext *ctx, co
  	    continue;
  	if (!strcmp (next->d_name, ".."))
  	    continue;
 -	path = concat_dir_and_file (s, next->d_name);
 +	path = mhl_str_dir_plus_file (s, next->d_name);
  	if (mc_lstat (path, &buf)) {
  	    g_free (path);
  	    mc_closedir (reading);
@@@ -1522,7 -1511,7 +1521,7 @@@ compute_dir_size (const char *dirname, 
  	if (strcmp (dirent->d_name, "..") == 0)
  	    continue;
  
 -	fullname = concat_dir_and_file (dirname, dirent->d_name);
 +	fullname = mhl_str_dir_plus_file (dirname, dirent->d_name);
  
  	res = mc_lstat (fullname, &s);
  
@@@ -1579,7 -1568,7 +1578,7 @@@ panel_compute_totals (WPanel *panel, of
  	    double subdir_bytes = 0;
  
  	    dir_name =
 -		concat_dir_and_file (panel->cwd, panel->dir.list[i].fname);
 +		mhl_str_dir_plus_file (panel->cwd, panel->dir.list[i].fname);
  	    compute_dir_size (dir_name, &subdir_count, &subdir_bytes);
  
  	    *ret_marked += subdir_count;
@@@ -1702,10 -1691,10 +1701,10 @@@ panel_operate_generate_prompt (const WP
  
      if (single_source) {
  	i = fmd_xlen - strlen (format_string) - 4;
 -	g_snprintf (cmd_buf, sizeof (cmd_buf), format_string,
 +	snprintf (cmd_buf, sizeof (cmd_buf), format_string,
  		    name_trunc (single_source, i));
      } else {
 -	g_snprintf (cmd_buf, sizeof (cmd_buf), format_string,
 +	snprintf (cmd_buf, sizeof (cmd_buf), format_string,
  		    panel->marked);
  	i = strlen (cmd_buf) + 6 - fmd_xlen;
  	if (i > 0) {
@@@ -1863,11 -1852,11 +1862,11 @@@ panel_operate (void *source_panel, File
         invalid data. */
      if (dest) {
  	if (mc_setctl (dest, VFS_SETCTL_STALE_DATA, (void *) 1))
- 	    save_dest = g_strdup (dest);
+ 	    save_dest = mhl_str_dup (dest);
      }
      if (panel->cwd) {
  	if (mc_setctl (panel->cwd, VFS_SETCTL_STALE_DATA, (void *) 1))
- 	    save_cwd = g_strdup (panel->cwd);
+ 	    save_cwd = mhl_str_dup (panel->cwd);
      }
  
      /* Now, let's do the job */
@@@ -1887,7 -1876,7 +1886,7 @@@
  
  	/* The source and src_stat variables have been initialized before */
  #ifdef WITH_FULL_PATHS
 -	source_with_path = concat_dir_and_file (panel->cwd, source);
 +	source_with_path = mhl_str_dir_plus_file (panel->cwd, source);
  #endif				/* WITH_FULL_PATHS */
  
  	if (operation == OP_DELETE) {
@@@ -1902,11 -1891,11 +1901,11 @@@
  	    if (temp == NULL) {
  		value = transform_error;
  	    } else {
 -		char *temp2 = concat_dir_and_file (dest, temp);
 +		char *temp2 = mhl_str_dir_plus_file (dest, temp);
  		g_free (dest);
  		dest = temp2;
  		temp = NULL;
 -
 +		
  		switch (operation) {
  		case OP_COPY:
  		    /*
@@@ -1980,7 -1969,7 +1979,7 @@@
  
  #ifdef WITH_FULL_PATHS
  	    g_free (source_with_path);
 -	    source_with_path = concat_dir_and_file (panel->cwd, source);
 +	    source_with_path = mhl_str_dir_plus_file (panel->cwd, source);
  #endif				/* WITH_FULL_PATHS */
  
  	    if (operation == OP_DELETE) {
@@@ -1996,10 -1985,7 +1995,10 @@@
  		if (temp == NULL)
  		    value = transform_error;
  		else {
 -		    char *temp2 = concat_dir_and_file (dest, temp);
 +		    char *temp2 = mhl_str_dir_plus_file (dest, temp);
 +
 +		    source_with_path = mhl_shell_unescape_buf(source_with_path);
 +		    temp2 = mhl_shell_unescape_buf(temp2);
  
  		    switch (operation) {
  		    case OP_COPY:
@@@ -2127,7 -2113,7 +2126,7 @@@ real_do_file_error (enum OperationMode 
  int
  file_error (const char *format, const char *file)
  {
 -    g_snprintf (cmd_buf, sizeof (cmd_buf), format,
 +    snprintf (cmd_buf, sizeof (cmd_buf), format,
  		path_trunc (file, 30), unix_error_string (errno));
  
      return do_file_error (cmd_buf);
@@@ -2143,7 -2129,7 +2142,7 @@@ files_error (const char *format, const 
      strcpy (nfile1, path_trunc (file1, 15));
      strcpy (nfile2, path_trunc (file2, 15));
  
 -    g_snprintf (cmd_buf, sizeof (cmd_buf), format, nfile1, nfile2,
 +    snprintf (cmd_buf, sizeof (cmd_buf), format, nfile1, nfile2,
  		unix_error_string (errno));
  
      return do_file_error (cmd_buf);
diff --combined src/filegui.c
index 68e3677,c2c71f5..9a4fc2f
--- a/src/filegui.c
+++ b/src/filegui.c
@@@ -48,11 -48,12 +48,12 @@@
  #include <ctype.h>
  #include <stdio.h>
  #include <string.h>
- 
  #include <sys/types.h>
  #include <sys/stat.h>
  #include <unistd.h>
  
+ #include <mhl/string.h>
+ 
  #include "global.h"
  #include "setup.h"		/* verbose */
  #include "dialog.h"		/* do_refresh() */
@@@ -320,7 -321,7 +321,7 @@@ file_eta_show (FileOpContext *ctx
  	eta_hours = ctx->eta_secs / (60 * 60);
  	eta_mins = (ctx->eta_secs - (eta_hours * 60 * 60)) / 60;
  	eta_s = ctx->eta_secs - (eta_hours * 60 * 60 + eta_mins * 60);
 -	g_snprintf (eta_buffer, sizeof (eta_buffer), _("ETA %d:%02d.%02d"),
 +	snprintf (eta_buffer, sizeof (eta_buffer), _("ETA %d:%02d.%02d"),
  		    eta_hours, eta_mins, eta_s);
      } else
  	*eta_buffer = 0;
@@@ -343,13 -344,13 +344,13 @@@ file_bps_show (FileOpContext *ctx
  	return;
  
      if (ctx->bps > 1024 * 1024) {
 -	g_snprintf (bps_buffer, sizeof (bps_buffer), _("%.2f MB/s"),
 +	snprintf (bps_buffer, sizeof (bps_buffer), _("%.2f MB/s"),
  		    ctx->bps / (1024 * 1024.0));
      } else if (ctx->bps > 1024) {
 -	g_snprintf (bps_buffer, sizeof (bps_buffer), _("%.2f KB/s"),
 +	snprintf (bps_buffer, sizeof (bps_buffer), _("%.2f KB/s"),
  		    ctx->bps / 1024.0);
      } else if (ctx->bps > 1) {
 -	g_snprintf (bps_buffer, sizeof (bps_buffer), _("%ld B/s"),
 +	snprintf (bps_buffer, sizeof (bps_buffer), _("%ld B/s"),
  		    ctx->bps);
      } else
  	*bps_buffer = 0;
@@@ -540,7 -541,7 +541,7 @@@ static struct 
  		NORMAL_BUTTON, rd_widgets [i].text, 0))
  
  #define ADD_RD_LABEL(ui,i,p1,p2)\
 -	g_snprintf (buffer, sizeof (buffer), rd_widgets [i].text, p1, p2);\
 +	snprintf (buffer, sizeof (buffer), rd_widgets [i].text, p1, p2);\
  	add_widget (ui->replace_dlg,\
  		label_new (rd_widgets [i].ypos, rd_widgets [i].xpos, buffer))
  
@@@ -881,7 -882,7 +882,7 @@@ file_mask_dialog (FileOpContext *ctx, F
      fmd_widgets[FMCB21].result = &ctx->dive_into_subdirs;
  
      /* filter out a possible password from def_text */
-     def_text_secure = strip_password (g_strdup (def_text), 1);
+     def_text_secure = strip_password (mhl_str_dup (def_text), 1);
  
      /* Create the dialog */
  
@@@ -971,14 -972,14 +972,14 @@@
  	    && ((!only_one && !is_wildcarded (ctx->dest_mask))
  		|| (only_one && !mc_stat (dest_dir, &buf)
  		    && S_ISDIR (buf.st_mode)))))
- 	ctx->dest_mask = g_strdup ("*");
+ 	ctx->dest_mask = mhl_str_dup ("*");
      else {
- 	ctx->dest_mask = g_strdup (ctx->dest_mask);
+ 	ctx->dest_mask = mhl_str_dup (ctx->dest_mask);
  	*orig_mask = 0;
      }
      if (!*dest_dir) {
  	g_free (dest_dir);
- 	dest_dir = g_strdup ("./");
+ 	dest_dir = mhl_str_dup ("./");
      }
      if (val == B_USER)
  	*do_background = 1;
diff --combined src/filenot.c
index 01e0d78,25e6a8a..7a67a0a
--- a/src/filenot.c
+++ b/src/filenot.c
@@@ -37,9 -37,9 +37,9 @@@ get_absolute_name (const char *file
      char dir[MC_MAXPATHLEN];
  
      if (file[0] == PATH_SEP)
- 	return g_strdup (file);
+ 	return mhl_str_dup (file);
      mc_get_current_wd (dir, MC_MAXPATHLEN);
 -    return concat_dir_and_file (dir, file);
 +    return mhl_str_dir_plus_file (dir, file);
  }
  
  static int
@@@ -62,7 -62,7 +62,7 @@@ my_mkdir_rec (char *s, mode_t mode
  	return -1;
      }
  
 -    p = concat_dir_and_file (s, "..");
 +    p = mhl_str_dir_plus_file (s, "..");
      q = vfs_canon (p);
      g_free (p);
  
diff --combined src/find.c
index 141a4cf,58d700b..01f75c9
--- a/src/find.c
+++ b/src/find.c
@@@ -27,7 -27,6 +27,7 @@@
  #include <string.h>
  #include <sys/stat.h>
  
 +#include <mhl/types.h>
  #include <mhl/string.h>
  
  #include "global.h"
@@@ -144,7 -143,7 +144,7 @@@ static void get_list_info (char **file
  static regex_t *r; /* Pointer to compiled content_pattern */
   
  static int case_sensitive = 1;
 -static gboolean find_regex_flag = TRUE;
 +static bool find_regex_flag = TRUE;
  static int find_recursively = 1;
  
  /*
@@@ -249,11 -248,11 +249,11 @@@ find_parameters (char **start_dir, cha
  
    find_par_start:
      if (!in_start_dir)
- 	in_start_dir = g_strdup (".");
+ 	in_start_dir = mhl_str_dup (".");
      if (!in_start_name)
- 	in_start_name = g_strdup (easy_patterns ? "*" : ".");
+ 	in_start_name = mhl_str_dup (easy_patterns ? "*" : ".");
      if (!in_contents)
- 	in_contents = g_strdup ("");
+ 	in_contents = mhl_str_dup ("");
  
      find_dlg =
  	create_dlg (0, 0, FIND_Y, FIND_X, dialog_colors,
@@@ -277,16 -276,16 +277,16 @@@
      add_widget (find_dlg, case_sense);
  
      in_with =
 -	input_new (8, istart, INPUT_COLOR, ilen, in_contents, "content");
 +	input_new (8, istart, INPUT_COLOR, ilen, in_contents, "content", INPUT_COMPLETE_DEFAULT);
      add_widget (find_dlg, in_with);
  
      add_widget (find_dlg, recursively_cbox);
      in_name =
 -	input_new (5, istart, INPUT_COLOR, ilen, in_start_name, "name");
 +	input_new (5, istart, INPUT_COLOR, ilen, in_start_name, "name", INPUT_COMPLETE_DEFAULT);
      add_widget (find_dlg, in_name);
  
      in_start =
 -	input_new (3, istart, INPUT_COLOR, ilen, in_start_dir, "start");
 +	input_new (3, istart, INPUT_COLOR, ilen, in_start_dir, "start", INPUT_COMPLETE_DEFAULT);
      add_widget (find_dlg, in_start);
  
      add_widget (find_dlg, label_new (8, 3, labs[2]));
@@@ -303,7 -302,7 +303,7 @@@
  	break;
  
      case B_TREE:
- 	temp_dir = g_strdup (in_start->buffer);
+ 	temp_dir = mhl_str_dup (in_start->buffer);
  	case_sensitive = case_sense->state & C_BOOL;
  	find_regex_flag = find_regex_cbox->state & C_BOOL;
   	find_recursively = recursively_cbox->state & C_BOOL;
@@@ -311,7 -310,7 +311,7 @@@
  	g_free (in_start_dir);
  	if (strcmp (temp_dir, ".") == 0) {
  	    g_free (temp_dir);
- 	    temp_dir = g_strdup (current_panel->cwd);
+ 	    temp_dir = mhl_str_dup (current_panel->cwd);
  	}
  	in_start_dir = tree_box (temp_dir);
  	if (in_start_dir)
@@@ -325,8 -324,8 +325,8 @@@
      default:
  	g_free (in_contents);
  	if (in_with->buffer[0]) {
- 	    *content = g_strdup (in_with->buffer);
- 	    in_contents = g_strdup (*content);
+ 	    *content = mhl_str_dup (in_with->buffer);
+ 	    in_contents = mhl_str_dup (*content);
  	} else {
  	    *content = in_contents = NULL;
  	    r = 0;
@@@ -336,13 -335,13 +336,13 @@@
  	find_regex_flag = find_regex_cbox->state & C_BOOL;
   	find_recursively = recursively_cbox->state & C_BOOL;
  	return_value = 1;
- 	*start_dir = g_strdup (in_start->buffer);
- 	*pattern = g_strdup (in_name->buffer);
+ 	*start_dir = mhl_str_dup (in_start->buffer);
+ 	*pattern = mhl_str_dup (in_name->buffer);
  
  	g_free (in_start_dir);
- 	in_start_dir = g_strdup (*start_dir);
+ 	in_start_dir = mhl_str_dup (*start_dir);
  	g_free (in_start_name);
- 	in_start_name = g_strdup (*pattern);
+ 	in_start_name = mhl_str_dup (*pattern);
      }
  
      destroy_dlg (find_dlg);
@@@ -356,7 -355,7 +356,7 @@@ push_directory (const char *dir
      dir_stack *new;
  
      new = g_new (dir_stack, 1);
 -    new->name = concat_dir_and_file (dir, "");
 +    new->name = mhl_str_dir_plus_file (dir, NULL);
      new->prev = dir_stack_base;
      dir_stack_base = new;
  }
@@@ -389,11 -388,11 +389,11 @@@ insert_file (const char *dir, const cha
      if (old_dir){
  	if (strcmp (old_dir, dir)){
  	    g_free (old_dir);
- 	    old_dir = g_strdup (dir);
+ 	    old_dir = mhl_str_dup (dir);
  	    dirname = add_to_list (dir, NULL);
  	}
      } else {
- 	old_dir = g_strdup (dir);
+ 	old_dir = mhl_str_dup (dir);
  	dirname = add_to_list (dir, NULL);
      }
      
@@@ -518,7 -517,7 +518,7 @@@ search_content (Dlg_head *h, const cha
      int file_fd;
      int ret_val = 0;
  
 -    fname = concat_dir_and_file (directory, filename);
 +    fname = mhl_str_dir_plus_file (directory, filename);
  
      if (mc_stat (fname, &s) != 0 || !S_ISREG (s.st_mode)){
  	g_free (fname);
@@@ -531,7 -530,7 +531,7 @@@
      if (file_fd == -1)
  	return 0;
  
 -    g_snprintf (buffer, sizeof (buffer), _("Grepping in %s"), name_trunc (filename, FIND2_X_USE));
 +    snprintf (buffer, sizeof (buffer), _("Grepping in %s"), name_trunc (filename, FIND2_X_USE));
  
      status_update (buffer);
      mc_refresh ();
@@@ -667,7 -666,7 +667,7 @@@ do_search (struct Dlg_head *h
  	    if (verbose){
  		char buffer [BUF_SMALL];
  
 -		g_snprintf (buffer, sizeof (buffer), _("Searching %s"), 
 +		snprintf (buffer, sizeof (buffer), _("Searching %s"), 
  			    name_trunc (directory, FIND2_X_USE));
  		status_update (buffer);
  	    }
@@@ -694,7 -693,7 +694,7 @@@
      }
  
      if (subdirs_left && find_recursively && directory) { /* Can directory be NULL ? */
 -	char *tmp_name = concat_dir_and_file (directory, dp->d_name);
 +	char *tmp_name = mhl_str_dir_plus_file (directory, dp->d_name);
  	if (!mc_lstat (tmp_name, &tmp_stat)
  	    && S_ISDIR (tmp_stat.st_mode)) {
  	    push_directory (tmp_name);
@@@ -752,10 -751,10 +752,10 @@@ make_fullname (const char *dirname, con
  {
  
      if (strcmp(dirname, ".") == 0 || strcmp(dirname, "."PATH_SEP_STR) == 0)
- 	return g_strdup (filename);
+ 	return mhl_str_dup (filename);
      if (strncmp(dirname, "."PATH_SEP_STR, 2) == 0)
 -	return concat_dir_and_file (dirname + 2, filename);
 -    return concat_dir_and_file (dirname, filename);
 +	return mhl_str_dir_plus_file (dirname + 2, filename);
 +    return mhl_str_dir_plus_file (dirname, filename);
  }
  
  static void
@@@ -983,9 -982,9 +983,9 @@@ find_file (char *start_dir, char *patte
      get_list_info (&file_tmp, &dir_tmp);
  
      if (dir_tmp)
- 	*dirname = g_strdup (dir_tmp);
+ 	*dirname = mhl_str_dup (dir_tmp);
      if (file_tmp)
- 	*filename = g_strdup (file_tmp);
+ 	*filename = mhl_str_dup (file_tmp);
  
      if (return_value == B_PANELIZE && *filename) {
  	int status, link_to_dir, stale_link;
diff --combined src/hotlist.c
index 737c9c1,083542b..ef5fc17
--- a/src/hotlist.c
+++ b/src/hotlist.c
@@@ -934,7 -934,7 +934,7 @@@ static void add_new_entry_cmd (void
      int ret;
  
      /* Take current directory as default value for input fields */
-     to_free = title = url = strip_password (g_strdup (current_panel->cwd), 1);
+     to_free = title = url = strip_password (mhl_str_dup (current_panel->cwd), 1);
  
      ret = add_new_entry_input (_("New hotlist entry"), _("Directory label"),
  			       _("Directory path"), "[Hotlist]", &title, &url);
@@@ -1039,7 -1039,7 +1039,7 @@@ void add2hotlist_cmd (void
      char *prompt, *label;
      const char *cp = _("Label for \"%s\":");
      int l = strlen (cp);
-     char *label_string = g_strdup (current_panel->cwd);
+     char *label_string = mhl_str_dup (current_panel->cwd);
  
      strip_password (label_string, 1);
  
@@@ -1156,9 -1156,9 +1156,9 @@@ char *hotlist_cmd (int vfs_or_hotlist
      case B_ENTER:
  	if (l_hotlist->current->data) {
  	    struct hotlist *hlp = (struct hotlist*) l_hotlist->current->data;
- 	    target = g_strdup (hlp->directory);
+ 	    target = mhl_str_dup (hlp->directory);
  	} else
- 	    target = g_strdup (l_hotlist->current->text);
+ 	    target = mhl_str_dup (l_hotlist->current->text);
  	break;
      }
  
@@@ -1182,7 -1182,7 +1182,7 @@@ load_group (struct hotlist *grp
  
      while (profile_keys){
  	profile_keys = profile_iterator_next (profile_keys, &key, &value);
- 	add2hotlist (g_strdup (value), g_strdup (key), HL_TYPE_GROUP, 0);
+ 	add2hotlist (mhl_str_dup (value), mhl_str_dup (key), HL_TYPE_GROUP, 0);
      }
      g_free (group_section);
  
@@@ -1190,7 -1190,7 +1190,7 @@@
  
      while (profile_keys){
  	profile_keys = profile_iterator_next (profile_keys, &key, &value);
- 	add2hotlist (g_strdup (value),g_strdup (key), HL_TYPE_ENTRY, 0);
+ 	add2hotlist (mhl_str_dup (value),mhl_str_dup (key), HL_TYPE_ENTRY, 0);
      }
  
      for (current = grp->head; current; current = current->next)
@@@ -1332,22 -1332,22 +1332,22 @@@ hot_load_group (struct hotlist * grp
  	switch (tkn) {
  	case TKN_GROUP:
  	    CHECK_TOKEN(TKN_STRING);
- 	    new_grp = add2hotlist (g_strdup (tkn_buf), 0, HL_TYPE_GROUP, 0);
+ 	    new_grp = add2hotlist (mhl_str_dup (tkn_buf), 0, HL_TYPE_GROUP, 0);
  	    SKIP_TO_EOL;
  	    hot_load_group (new_grp);
  	    current_group = grp;
  	    break;
  	case TKN_ENTRY:
  	    CHECK_TOKEN(TKN_STRING);
- 	    label = g_strdup (tkn_buf);
+ 	    label = mhl_str_dup (tkn_buf);
  	    CHECK_TOKEN(TKN_URL);
  	    CHECK_TOKEN(TKN_STRING);
- 	    url = g_strdup (tkn_buf);
+ 	    url = mhl_str_dup (tkn_buf);
  	    add2hotlist (label, url, HL_TYPE_ENTRY, 0);
  	    SKIP_TO_EOL;
  	    break;
  	case TKN_COMMENT:
- 	    label = g_strdup (tkn_buf);
+ 	    label = mhl_str_dup (tkn_buf);
  	    add2hotlist (label, 0, HL_TYPE_COMMENT, 0);
  	    break;
  	case TKN_EOF:
@@@ -1380,22 -1380,22 +1380,22 @@@ hot_load_file (struct hotlist * grp
  	switch (tkn) {
  	case TKN_GROUP:
  	    CHECK_TOKEN(TKN_STRING);
- 	    new_grp = add2hotlist (g_strdup (tkn_buf), 0, HL_TYPE_GROUP, 0);
+ 	    new_grp = add2hotlist (mhl_str_dup (tkn_buf), 0, HL_TYPE_GROUP, 0);
  	    SKIP_TO_EOL;
  	    hot_load_group (new_grp);
  	    current_group = grp;
  	    break;
  	case TKN_ENTRY:
  	    CHECK_TOKEN(TKN_STRING);
- 	    label = g_strdup (tkn_buf);
+ 	    label = mhl_str_dup (tkn_buf);
  	    CHECK_TOKEN(TKN_URL);
  	    CHECK_TOKEN(TKN_STRING);
- 	    url = g_strdup (tkn_buf);
+ 	    url = mhl_str_dup (tkn_buf);
  	    add2hotlist (label, url, HL_TYPE_ENTRY, 0);
  	    SKIP_TO_EOL;
  	    break;
  	case TKN_COMMENT:
- 	    label = g_strdup (tkn_buf);
+ 	    label = mhl_str_dup (tkn_buf);
  	    add2hotlist (label, 0, HL_TYPE_COMMENT, 0);
  	    break;
  	case TKN_EOL:
@@@ -1448,16 -1448,16 +1448,16 @@@ load_hotlist (void
      }
  
      if (!hotlist_file_name)
 -	hotlist_file_name = concat_dir_and_file (home_dir, HOTLIST_FILENAME);
 +	hotlist_file_name = mhl_str_dir_plus_file (home_dir, HOTLIST_FILENAME);
      
      hotlist	       = new_hotlist ();
      hotlist->type      = HL_TYPE_GROUP;
-     hotlist->label     = g_strdup (_(" Top level group "));
+     hotlist->label     = mhl_str_dup (_(" Top level group "));
      hotlist->up        = hotlist;
      /*
       * compatibility :-(
       */
-     hotlist->directory = g_strdup ("Hotlist");
+     hotlist->directory = mhl_str_dup ("Hotlist");
  
      if ((hotlist_file = fopen (hotlist_file_name, "r")) == 0) {
  	int	result;
@@@ -1612,6 -1612,6 +1612,6 @@@ add_dotdot_to_list (void
  {
      if (current_group != hotlist) {
  	if (hotlist_has_dot_dot != 0)
- 	    add2hotlist (g_strdup (".."), g_strdup (".."), HL_TYPE_DOTDOT, 0);
+ 	    add2hotlist (mhl_str_dup (".."), mhl_str_dup (".."), HL_TYPE_DOTDOT, 0);
      }
  }
diff --combined src/key.c
index 6467eb3,8e30697..6869091
--- a/src/key.c
+++ b/src/key.c
@@@ -29,11 -29,10 +29,11 @@@
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
  #include <sys/types.h>
  #include <unistd.h>
  
 +#include <mhl/types.h>
+ #include <mhl/string.h>
  
  #include "global.h"
  #include "tty.h"
@@@ -183,7 -182,7 +183,7 @@@ inline static int add_selects (fd_set *
  static void check_selects (fd_set *select_set)
  {
      SelectList *p;
 -    gboolean retry;
 +    bool retry;
  
      if (disabled_channels)
  	return;
@@@ -1234,7 -1233,7 +1234,7 @@@ char *learn_key (void
      keypad(stdscr, TRUE);
      nodelay (stdscr, FALSE);
      *p = 0;
-     return g_strdup (buffer);
+     return mhl_str_dup (buffer);
  }
  
  /* xterm and linux console only: set keypad to numeric or application
diff --combined src/layout.c
index a9386a5,b802c6e..9e25dea
--- a/src/layout.c
+++ b/src/layout.c
@@@ -26,9 -26,9 +26,9 @@@
  #include <stdarg.h>
  #include <stdio.h>
  #include <string.h>
- 
  #include <sys/types.h>
  #include <sys/stat.h>
+ 
       /*
        * If TIOCGWINSZ supported, make it available here, because window-
        * resizing code depends on it...
@@@ -41,6 -41,8 +41,8 @@@
  #endif
  #include <unistd.h>
  
+ #include <mhl/string.h>
+ 
  #include "global.h"
  #include "tty.h"		/* COLS */
  #include "win.h"
@@@ -873,7 -875,7 +875,7 @@@ const char *get_nth_panel_name (int num
      else if (num == 1)
          return "New Right Panel";
      else {
 -        g_snprintf (buffer, sizeof (buffer), "%ith Panel", num);
 +        snprintf (buffer, sizeof (buffer), "%ith Panel", num);
          return buffer;
      }
  }
@@@ -1051,13 -1053,13 +1053,13 @@@ void swap_panels (
  	if (panels [0].type == view_listing) {
              if (!strcmp (panel1->panel_name, get_nth_panel_name (0))) {
                  g_free (panel1->panel_name);
-                 panel1->panel_name = g_strdup (get_nth_panel_name (1));
+                 panel1->panel_name = mhl_str_dup (get_nth_panel_name (1));
              }
          }
          if (panels [1].type == view_listing) {
              if (!strcmp (panel2->panel_name, get_nth_panel_name (1))) {
                  g_free (panel2->panel_name);
-                 panel2->panel_name = g_strdup (get_nth_panel_name (0));
+                 panel2->panel_name = mhl_str_dup (get_nth_panel_name (0));
              }
          }
          
diff --combined src/main.c
index a24c337,39687f5..6c867a5
--- a/src/main.c
+++ b/src/main.c
@@@ -67,6 -67,7 +67,6 @@@
  #include "widget.h"
  #include "command.h"
  #include "wtools.h"
 -#include "complete.h"		/* For the free_completion */
  
  #include "chmod.h"
  #include "chown.h"
@@@ -335,7 -336,7 +335,7 @@@ update_one_panel_widget (WPanel *panel
      /* If current_file == -1 (an invalid pointer) then preserve selection */
      if (current_file == UP_KEEPSEL) {
  	free_pointer = 1;
- 	my_current_file = g_strdup (panel->dir.list[panel->selected].fname);
+ 	my_current_file = mhl_str_dup (panel->dir.list[panel->selected].fname);
  	current_file = my_current_file;
      } else
  	free_pointer = 0;
@@@ -532,7 -533,7 +532,7 @@@ directory_history_add (struct WPanel *p
  {
      char *tmp;
  
-     tmp = g_strdup (dir);
+     tmp = mhl_str_dup (dir);
      strip_password (tmp, 1);
  
      panel->dir_history = list_append_unique (panel->dir_history, tmp);
@@@ -574,7 -575,7 +574,7 @@@ _do_panel_cd (WPanel *panel, const cha
  	    new_dir++;
      }
  
-     olddir = g_strdup (panel->cwd);
+     olddir = mhl_str_dup (panel->cwd);
      new_dir = translated_url = vfs_translate_url (new_dir);
  
      /* Convert *new_path to a suitable pathname, handle ~user */
@@@ -1137,7 -1138,7 +1137,7 @@@ copy_readlink (WPanel *panel
      if (S_ISLNK (selection (panel)->st.st_mode)) {
  	char buffer[MC_MAXPATHLEN];
  	char *p =
 -	    concat_dir_and_file (panel->cwd, selection (panel)->fname);
 +	    mhl_str_dir_plus_file (panel->cwd, selection (panel)->fname);
  	int i;
  
  	i = mc_readlink (p, buffer, MC_MAXPATHLEN - 1);
@@@ -1612,7 -1613,7 +1612,7 @@@ update_xterm_title_path (void
      char *p, *s;
  
      if (xterm_flag && xterm_title) {
- 	p = s = g_strdup (strip_home_and_password (current_panel->cwd));
+ 	p = s = mhl_str_dup (strip_home_and_password (current_panel->cwd));
  	do {
  	    if (!is_printable ((unsigned char) *s))
  		*s = '?';
@@@ -1649,7 -1650,7 +1649,7 @@@ load_hint (int force
      } else {
  	char text[BUF_SMALL];
  
 -	g_snprintf (text, sizeof (text), _("GNU Midnight Commander %s\n"),
 +	snprintf (text, sizeof (text), _("GNU Midnight Commander %s\n"),
  		    VERSION);
  	set_hintbar (text);
      }
@@@ -1686,7 -1687,7 +1686,7 @@@ prepend_cwd_on_local (const char *filen
  
      if (vfs_file_is_local (filename)) {
  	if (*filename == PATH_SEP)	/* an absolute pathname */
- 	    return g_strdup (filename);
+ 	    return mhl_str_dup (filename);
  	d = g_malloc (MC_MAXPATHLEN + strlen (filename) + 2);
  	mc_get_current_wd (d, MC_MAXPATHLEN);
  	l = strlen (d);
@@@ -1695,7 -1696,7 +1695,7 @@@
  	canonicalize_pathname (d);
  	return d;
      } else
- 	return g_strdup (filename);
+ 	return mhl_str_dup (filename);
  }
  
  static int
@@@ -1753,7 -1754,7 +1753,7 @@@ do_nc (void
  
      /* destroy_dlg destroys even current_panel->cwd, so we have to save a copy :) */
      if (last_wd_file && vfs_current_is_local ()) {
- 	last_wd_string = g_strdup (current_panel->cwd);
+ 	last_wd_string = mhl_str_dup (current_panel->cwd);
      }
      done_mc ();
  
@@@ -1772,7 -1773,7 +1772,7 @@@ OS_Setup (void
          struct passwd *pwd;
          pwd = getpwuid (geteuid ());
          if (pwd != NULL)
-            shell = g_strdup (pwd->pw_shell);
+            shell = mhl_str_dup (pwd->pw_shell);
      }
      if (!shell || !*shell)
  	shell = "/bin/sh";
@@@ -1780,9 -1781,9 +1780,9 @@@
      /* This is the directory, where MC was installed, on Unix this is DATADIR */
      /* and can be overriden by the MC_DATADIR environment variable */
      if ((mc_libdir = getenv ("MC_DATADIR")) != NULL) {
- 	mc_home = g_strdup (mc_libdir);
+ 	mc_home = mhl_str_dup (mc_libdir);
      } else {
- 	mc_home = g_strdup (DATADIR);
+ 	mc_home = mhl_str_dup (DATADIR);
      }
  }
  
@@@ -2097,12 -2098,12 +2097,12 @@@ handle_args (int argc, char *argv[]
  			}
  		    }
  		}
- 		edit_one_file = g_strdup (tmp);
+ 		edit_one_file = mhl_str_dup (tmp);
  	    }
  	}
      } else if (!STRNCOMP (base, "mcv", 3) || !STRCOMP (base, "view")) {
  	if (tmp)
- 	    view_one_file = g_strdup (tmp);
+ 	    view_one_file = mhl_str_dup (tmp);
  	else {
  	    fputs ("No arguments given to the viewer\n", stderr);
  	    exit (1);
@@@ -2110,9 -2111,9 +2110,9 @@@
      } else {
  	/* sets the current dir and the other dir */
  	if (tmp) {
- 	    this_dir = g_strdup (tmp);
+ 	    this_dir = mhl_str_dup (tmp);
  	    if ((tmp = poptGetArg (ctx)))
- 		other_dir = g_strdup (tmp);
+ 		other_dir = mhl_str_dup (tmp);
  	}
      }
  
diff --combined src/panelize.c
index d15f093,26c6196..28a62c0
--- a/src/panelize.c
+++ b/src/panelize.c
@@@ -25,11 -25,12 +25,12 @@@
  #include <errno.h>
  #include <stdio.h>
  #include <string.h>
- 
  #include <sys/types.h>
  #include <sys/stat.h>
  #include <unistd.h>
  
+ #include <mhl/string.h>
+ 
  #include "global.h"
  #include "tty.h"		/* attrset() */
  #include "win.h"
@@@ -165,7 -166,7 +166,7 @@@ init_panelize (void
  
      pname =
  	input_new (UY + 14, UX, INPUT_COLOR, panelize_dlg->cols - 10, "",
 -		   "in");
 +		   "in", INPUT_COMPLETE_DEFAULT);
      add_widget (panelize_dlg, pname);
  
      add_widget (panelize_dlg, label_new (UY + 13, UX, _("Command")));
@@@ -236,7 -237,7 +237,7 @@@ add2panelize_cmd (void
  	    return;
  	}
  	
- 	add2panelize (label, g_strdup (pname->buffer));
+ 	add2panelize (label, mhl_str_dup (pname->buffer));
      }
  }
  
@@@ -293,7 -294,7 +294,7 @@@ external_panelize (void
      case B_ENTER:
  	target = pname->buffer;
  	if (target != NULL && *target) {
- 	    char *cmd = g_strdup (target);
+ 	    char *cmd = mhl_str_dup (target);
  	    destroy_dlg (panelize_dlg);
  	    do_external_panelize (cmd);
  	    g_free (cmd);
@@@ -313,18 -314,18 +314,18 @@@ void load_panelize (void
      
      profile_keys = profile_init_iterator (panelize_section, profile_name);
      
-     add2panelize (g_strdup (_("Other command")), g_strdup (""));
+     add2panelize (mhl_str_dup (_("Other command")), mhl_str_dup (""));
  
      if (!profile_keys){
- 	add2panelize (g_strdup (_("Find rejects after patching")), g_strdup ("find . -name \\*.rej -print"));
- 	add2panelize (g_strdup (_("Find *.orig after patching")), g_strdup ("find . -name \\*.orig -print"));
- 	add2panelize (g_strdup (_("Find SUID and SGID programs")), g_strdup ("find . \\( \\( -perm -04000 -a -perm +011 \\) -o \\( -perm -02000 -a -perm +01 \\) \\) -print"));
+ 	add2panelize (mhl_str_dup (_("Find rejects after patching")), mhl_str_dup ("find . -name \\*.rej -print"));
+ 	add2panelize (mhl_str_dup (_("Find *.orig after patching")), mhl_str_dup ("find . -name \\*.orig -print"));
+ 	add2panelize (mhl_str_dup (_("Find SUID and SGID programs")), mhl_str_dup ("find . \\( \\( -perm -04000 -a -perm +011 \\) -o \\( -perm -02000 -a -perm +01 \\) \\) -print"));
  	return;
      }
      
      while (profile_keys){
  	profile_keys = profile_iterator_next (profile_keys, &key, &value);
- 	add2panelize (g_strdup (key), g_strdup (value));
+ 	add2panelize (mhl_str_dup (key), mhl_str_dup (value));
      }
  }
  
@@@ -398,7 -399,7 +399,7 @@@ static void do_external_panelize (char 
  	if (status == -1)
  	    break;
  	list->list [next_free].fnamelen = strlen (name);
- 	list->list [next_free].fname = g_strdup (name);
+ 	list->list [next_free].fname = mhl_str_dup (name);
  	file_mark (current_panel, next_free, 0);
  	list->list [next_free].f.link_to_dir = link_to_dir;
  	list->list [next_free].f.stale_link = stale_link;
diff --combined src/profile.c
index 67a2992,05d774c..6b27d63
--- a/src/profile.c
+++ b/src/profile.c
@@@ -26,9 -26,10 +26,10 @@@
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
- 
  #include <sys/types.h>
  
+ #include <mhl/string.h>
+ 
  #include "global.h"
  #include "profile.h"
  
@@@ -168,7 -169,7 +169,7 @@@ static TSecHeader *load (const char *fi
  	    if (c == ']' || overflow){
  		*next = '\0';
  		next = CharBuffer;
- 		SecHeader->AppName = g_strdup (CharBuffer);
+ 		SecHeader->AppName = mhl_str_dup (CharBuffer);
  		state = IgnoreToEOL;
  	    } else
  		*next++ = c;
@@@ -214,7 -215,7 +215,7 @@@
  		*next = '\0';
  		SecHeader->Keys =g_new (TKeys, 1);
  		SecHeader->Keys->link = temp;
- 		SecHeader->Keys->KeyName = g_strdup (CharBuffer);
+ 		SecHeader->Keys->KeyName = mhl_str_dup (CharBuffer);
  		state = KeyValue;
  		next = CharBuffer;
  	    } else {
@@@ -265,8 -266,8 +266,8 @@@ static void new_key (TSecHeader *sectio
      TKeys *key;
      
      key = g_new (TKeys, 1);
-     key->KeyName = g_strdup (KeyName);
-     key->Value   = g_strdup (Value);
+     key->KeyName = mhl_str_dup (KeyName);
+     key->Value   = mhl_str_dup (Value);
      key->link = section->Keys;
      section->Keys = key;
  }
@@@ -284,7 -285,7 +285,7 @@@ GetSetProfileChar (int set, const char 
      if (!Current) {
  	Current = g_new (TProfile, 1);
  	Current->link = Base;
- 	Current->FileName = g_strdup (FileName);
+ 	Current->FileName = mhl_str_dup (FileName);
  	Current->Section = load (FileName);
  	Base = Current;
  	section = Current->Section;
@@@ -299,7 -300,7 +300,7 @@@
  		continue;
  	    if (set){
  		g_free (key->Value);
- 		key->Value = g_strdup (Default);
+ 		key->Value = mhl_str_dup (Default);
  	    }
  	    return key->Value;
  	}
@@@ -315,7 -316,7 +316,7 @@@
      /* Non existent section */
      if (set && Default){
  	section = g_new (TSecHeader, 1);
- 	section->AppName = g_strdup (AppName);
+ 	section->AppName = mhl_str_dup (AppName);
  	section->Keys = 0;
  	new_key (section, KeyName, Default);
  	section->link = Current->Section;
@@@ -357,7 -358,7 +358,7 @@@ int GetPrivateProfileInt (const char * 
      char IntBuf [BUF_TINY];
      char buf [BUF_TINY];
  
 -    g_snprintf (buf, sizeof (buf), "%d", Default);
 +    snprintf (buf, sizeof (buf), "%d", Default);
      
      /* Check the exact semantic with the SDK */
      GetPrivateProfileString (AppName, KeyName, buf, IntBuf, BUF_TINY, File);
@@@ -483,7 -484,7 +484,7 @@@ void *profile_init_iterator (const cha
      if (!Current) {
  	Current = g_new (TProfile, 1);
  	Current->link = Base;
- 	Current->FileName = g_strdup (file);
+ 	Current->FileName = mhl_str_dup (file);
  	Current->Section = load (file);
  	Base = Current;
  	section = Current->Section;
diff --combined src/screen.c
index b5b337c,03effee..7a6683a
--- a/src/screen.c
+++ b/src/screen.c
@@@ -212,7 -212,7 +212,7 @@@ static void format_device_number (char 
  
      g_assert(bufsize >= 1);
      if (major_digits + 1 + minor_digits + 1 <= bufsize) {
 -        g_snprintf(buf, bufsize, "%lu,%lu", (unsigned long) major_dev,
 +        snprintf(buf, bufsize, "%lu,%lu", (unsigned long) major_dev,
                     (unsigned long) minor_dev);
      } else {
          g_strlcpy(buf, _("[dev]"), bufsize);
@@@ -337,7 -337,7 +337,7 @@@ string_file_perm_octal (file_entry *fe
  {
      static char buffer [10];
  
 -    g_snprintf (buffer, sizeof (buffer), "0%06lo", (unsigned long) fe->st.st_mode);
 +    snprintf (buffer, sizeof (buffer), "0%06lo", (unsigned long) fe->st.st_mode);
      return buffer;
  }
  
@@@ -347,7 -347,7 +347,7 @@@ string_file_nlinks (file_entry *fe, in
  {
      static char buffer[BUF_TINY];
  
 -    g_snprintf (buffer, sizeof (buffer), "%16d", (int) fe->st.st_nlink);
 +    snprintf (buffer, sizeof (buffer), "%16d", (int) fe->st.st_nlink);
      return buffer;
  }
  
@@@ -357,7 -357,7 +357,7 @@@ string_inode (file_entry *fe, int len
  {
      static char buffer [10];
  
 -    g_snprintf (buffer, sizeof (buffer), "%lu",
 +    snprintf (buffer, sizeof (buffer), "%lu",
  		(unsigned long) fe->st.st_ino);
      return buffer;
  }
@@@ -368,7 -368,7 +368,7 @@@ string_file_nuid (file_entry *fe, int l
  {
      static char buffer [10];
  
 -    g_snprintf (buffer, sizeof (buffer), "%lu",
 +    snprintf (buffer, sizeof (buffer), "%lu",
  		(unsigned long) fe->st.st_uid);
      return buffer;
  }
@@@ -379,7 -379,7 +379,7 @@@ string_file_ngid (file_entry *fe, int l
  {
      static char buffer [10];
  
 -    g_snprintf (buffer, sizeof (buffer), "%lu",
 +    snprintf (buffer, sizeof (buffer), "%lu",
  		(unsigned long) fe->st.st_gid);
      return buffer;
  }
@@@ -686,11 -686,11 +686,11 @@@ display_mini_info (WPanel *panel
  	 * This is a trick to use two ngettext() calls in one sentence.
  	 * First make "N bytes", then insert it into "X in M files".
  	 */
 -	g_snprintf(b_bytes, sizeof (b_bytes),
 +	snprintf(b_bytes, sizeof (b_bytes),
  		   ngettext("%s byte", "%s bytes",
  			    (unsigned long)panel->total),
  		   size_trunc_sep(panel->total));
 -	g_snprintf(buffer, sizeof (buffer),
 +	snprintf(buffer, sizeof (buffer),
  		   ngettext("%s in %d file", "%s in %d files", panel->marked),
  		   b_bytes, panel->marked);
  
@@@ -710,7 -710,7 +710,7 @@@
  	char *link, link_target [MC_MAXPATHLEN];
  	int  len;
  
 -	link = concat_dir_and_file (panel->cwd, panel->dir.list [panel->selected].fname);
 +	link = mhl_str_dir_plus_file (panel->cwd, panel->dir.list [panel->selected].fname);
  	len = mc_readlink (link, link_target, MC_MAXPATHLEN - 1);
  	g_free (link);
  	if (len > 0){
@@@ -945,7 -945,7 +945,7 @@@ panel_save_name (WPanel *panel
  
      /* If the program is shuting down */
      if ((midnight_shutdown && auto_save_setup) || saving_setup)
- 	return  g_strdup (panel->panel_name);
+ 	return  mhl_str_dup (panel->panel_name);
      else
  	return  g_strconcat ("Temporal:", panel->panel_name, (char *) NULL);
  }
@@@ -1030,18 -1030,18 +1030,18 @@@ panel_new (const char *panel_name
      panel->status_format = 0;
      panel->format_modified = 1;
  
-     panel->panel_name = g_strdup (panel_name);
-     panel->user_format = g_strdup (DEFAULT_USER_FORMAT);
+     panel->panel_name = mhl_str_dup (panel_name);
+     panel->user_format = mhl_str_dup (DEFAULT_USER_FORMAT);
  
      for (i = 0; i < LIST_TYPES; i++)
- 	panel->user_status_format[i] = g_strdup (DEFAULT_USER_FORMAT);
+ 	panel->user_status_format[i] = mhl_str_dup (DEFAULT_USER_FORMAT);
  
      panel->search_buffer[0] = 0;
      panel->frame_size = frame_half;
      section = g_strconcat ("Temporal:", panel->panel_name, (char *) NULL);
      if (!profile_has_section (section, profile_name)) {
  	g_free (section);
- 	section = g_strdup (panel->panel_name);
+ 	section = mhl_str_dup (panel->panel_name);
      }
      panel_load_setup (panel, section);
      g_free (section);
@@@ -1321,7 -1321,7 +1321,7 @@@ parse_display_format (WPanel *panel, co
  	    break;
  	}
  	if (!found){
- 	    char *tmp_format = g_strdup (format);
+ 	    char *tmp_format = mhl_str_dup (format);
  
  	    int pos = min (8, strlen (format));
  	    delete_format (home);
@@@ -1449,11 -1449,11 +1449,11 @@@ set_panel_formats (WPanel *p
        message( 1, _("Warning" ), _( "User supplied format looks invalid, reverting to default." ) );
      if (retcode & 0x01){
        g_free (p->user_format);
-       p->user_format = g_strdup (DEFAULT_USER_FORMAT);
+       p->user_format = mhl_str_dup (DEFAULT_USER_FORMAT);
      }
      if (retcode & 0x02){
        g_free (p->user_status_format [p->list_type]);
-       p->user_status_format [p->list_type] = g_strdup (DEFAULT_USER_FORMAT);
+       p->user_status_format [p->list_type] = mhl_str_dup (DEFAULT_USER_FORMAT);
      }
  
      return retcode;
@@@ -1975,7 -1975,7 +1975,7 @@@ do_enter_on_file_entry (file_entry *fe
  	return 1;
  
      /* Check if the file is executable */
 -    full_name = concat_dir_and_file (current_panel->cwd, fe->fname);
 +    full_name = mhl_str_dir_plus_file (current_panel->cwd, fe->fname);
      if (!is_exe (fe->st.st_mode) || !if_link_is_exe (full_name, fe)) {
  	g_free (full_name);
  	return 0;
@@@ -1994,7 -1994,7 +1994,7 @@@
  	char *tmp;
  	int ret;
  
 -	tmp = concat_dir_and_file (vfs_get_current_dir (), fe->fname);
 +	tmp = mhl_str_dir_plus_file (vfs_get_current_dir (), fe->fname);
  	ret = mc_setctl (tmp, VFS_SETCTL_RUN, NULL);
  	g_free (tmp);
  	/* We took action only if the dialog was shown or the execution
@@@ -2031,10 -2031,10 +2031,10 @@@ chdir_other_panel (WPanel *panel
      }
  
      if (!S_ISDIR (panel->dir.list [panel->selected].st.st_mode)) {
 -        new_dir = concat_dir_and_file (panel->cwd, "..");
 +        new_dir = mhl_str_dir_plus_file (panel->cwd, "..");
  	sel_entry = strrchr(panel->cwd, PATH_SEP);
      } else
 -        new_dir = concat_dir_and_file (panel->cwd, panel->dir.list [panel->selected].fname);
 +        new_dir = mhl_str_dir_plus_file (panel->cwd, panel->dir.list [panel->selected].fname);
  
      change_panel ();
      do_cd (new_dir, cd_exact);
@@@ -2098,9 -2098,9 +2098,9 @@@ chdir_to_readlink (WPanel *panel
  	    p[1] = 0;
  	}
  	if (*buffer == PATH_SEP)
- 	    new_dir = g_strdup (buffer);
+ 	    new_dir = mhl_str_dup (buffer);
  	else
 -	    new_dir = concat_dir_and_file (panel->cwd, buffer);
 +	    new_dir = mhl_str_dir_plus_file (panel->cwd, buffer);
  
  	change_panel ();
  	do_cd (new_dir, cd_exact);
@@@ -2252,7 -2252,7 +2252,7 @@@ panel_callback (Widget *w, widget_msg_
  	current_panel = panel;
  	panel->active = 1;
  	if (mc_chdir (panel->cwd) != 0) {
- 	    char *cwd = strip_password (g_strdup (panel->cwd), 1);
+ 	    char *cwd = strip_password (mhl_str_dup (panel->cwd), 1);
  	    message (D_ERROR, MSG_ERROR, _(" Cannot chdir to \"%s\" \n %s "),
  		     cwd, unix_error_string (errno));
  	    g_free(cwd);
@@@ -2464,7 -2464,7 +2464,7 @@@ panel_re_sort (WPanel *panel
      if (panel == NULL)
  	    return;
  
-     filename = g_strdup (selection (panel)->fname);
+     filename = mhl_str_dup (selection (panel)->fname);
      unselect_item (panel);
      do_sort (&panel->dir, panel->sort_type, panel->count-1, panel->reverse,
               panel->case_sensitive, panel->exec_first);
@@@ -2495,7 -2495,7 +2495,7 @@@ panel_set_sort_order (WPanel *panel, so
      if (sort_order == (sortfn *) unsorted){
  	char *current_file;
  
- 	current_file = g_strdup (panel->dir.list [panel->selected].fname);
+ 	current_file = mhl_str_dup (panel->dir.list [panel->selected].fname);
  	panel_reload (panel);
  	try_to_select (panel, current_file);
  	g_free (current_file);
diff --combined src/setup.c
index 1913361,4e044ac..02df102
--- a/src/setup.c
+++ b/src/setup.c
@@@ -245,11 -245,11 +245,11 @@@ panel_save_setup (struct WPanel *panel
      char buffer [BUF_TINY];
      int  i;
  
 -    g_snprintf (buffer, sizeof (buffer), "%d", panel->reverse);
 +    snprintf (buffer, sizeof (buffer), "%d", panel->reverse);
      save_string (section, "reverse", buffer, profile_name);
 -    g_snprintf (buffer, sizeof (buffer), "%d", panel->case_sensitive);
 +    snprintf (buffer, sizeof (buffer), "%d", panel->case_sensitive);
      save_string (section, "case_sensitive", buffer, profile_name);
 -    g_snprintf (buffer, sizeof (buffer), "%d", panel->exec_first);
 +    snprintf (buffer, sizeof (buffer), "%d", panel->exec_first);
      save_string (section, "exec_first", buffer, profile_name);
      for (i = 0; sort_names [i].key; i++)
  	if (sort_names [i].sort_type == (sortfn *) panel->sort_type){
@@@ -268,12 -268,12 +268,12 @@@
  			       panel->user_format, profile_name);
  
      for (i = 0; i < LIST_TYPES; i++){
 -	g_snprintf (buffer, sizeof (buffer), "user_status%d", i);
 +	snprintf (buffer, sizeof (buffer), "user_status%d", i);
  	save_string (section, buffer,
  	    panel->user_status_format [i], profile_name);
      }
  
 -    g_snprintf (buffer, sizeof (buffer), "%d", panel->user_mini_status);
 +    snprintf (buffer, sizeof (buffer), "%d", panel->user_mini_status);
      save_string (section, "user_mini_status", buffer,
  			       profile_name);
  }
@@@ -285,11 -285,11 +285,11 @@@ save_layout (void
      int  i;
      char buffer [BUF_TINY];
  
 -    profile = concat_dir_and_file (home_dir, PROFILE_NAME);
 +    profile = mhl_str_dir_plus_file (home_dir, PROFILE_NAME);
  
      /* Save integer options */
      for (i = 0; layout [i].opt_name; i++){
 -	g_snprintf (buffer, sizeof (buffer), "%d", *layout [i].opt_addr);
 +	snprintf (buffer, sizeof (buffer), "%d", *layout [i].opt_addr);
  	save_string ("Layout", layout [i].opt_name, buffer, profile);
      }
  
@@@ -302,7 -302,7 +302,7 @@@ save_configure (void
      char *profile;
      int  i;
  
 -    profile = concat_dir_and_file (home_dir, PROFILE_NAME);
 +    profile = mhl_str_dir_plus_file (home_dir, PROFILE_NAME);
  
      /* Save integer options */
      for (i = 0; int_options[i].opt_name; i++)
@@@ -350,7 -350,7 +350,7 @@@ save_setup (void
      char *profile;
  
      saving_setup = 1;
 -    profile = concat_dir_and_file (home_dir, PROFILE_NAME);
 +    profile = mhl_str_dir_plus_file (home_dir, PROFILE_NAME);
  
      save_configure ();
  
@@@ -414,14 -414,14 +414,14 @@@ panel_load_setup (WPanel *panel, const 
  
      /* User formats */
      g_free (panel->user_format);
-     panel->user_format = g_strdup (get_profile_string (section, "user_format",
+     panel->user_format = mhl_str_dup (get_profile_string (section, "user_format",
  						     DEFAULT_USER_FORMAT,
  						     profile_name));
      for (i = 0; i < LIST_TYPES; i++){
  	g_free (panel->user_status_format [i]);
 -	g_snprintf (buffer, sizeof (buffer), "user_status%d", i);
 +	snprintf (buffer, sizeof (buffer), "user_status%d", i);
  	panel->user_status_format [i] =
- 	    g_strdup (get_profile_string (section, buffer,
+ 	    mhl_str_dup (get_profile_string (section, buffer,
  			DEFAULT_USER_FORMAT, profile_name));
      }
  
@@@ -470,7 -470,7 +470,7 @@@ do_load_string (const char *s, const ch
  
      load_string (s, ss, def, buffer, BUF_SMALL);
  
-     p = g_strdup (buffer);
+     p = mhl_str_dup (buffer);
      g_free (buffer);
      return p;
  }
@@@ -485,9 -485,9 +485,9 @@@ setup_init (void
      if (profile_name)
  	    return profile_name;
  
 -    profile = concat_dir_and_file (home_dir, PROFILE_NAME);
 +    profile = mhl_str_dir_plus_file (home_dir, PROFILE_NAME);
      if (!exist_file (profile)){
 -	inifile = concat_dir_and_file (mc_home, "mc.ini");
 +	inifile = mhl_str_dir_plus_file (mc_home, "mc.ini");
  	if (exist_file (inifile)){
  	    g_free (profile);
  	    profile = inifile;
@@@ -510,7 -510,7 +510,7 @@@ load_setup (void
  
      /* mc.lib is common for all users, but has priority lower than
         ~/.mc/ini.  FIXME: it's only used for keys and treestore now */
 -    global_profile_name = concat_dir_and_file (mc_home, "mc.lib");
 +    global_profile_name = mhl_str_dir_plus_file (mc_home, "mc.lib");
  
      /* Load integer boolean options */
      for (i = 0; int_options[i].opt_name; i++)
@@@ -595,7 -595,7 +595,7 @@@ load_anon_passwd (
  
      load_string ("Misc", "ftpfs_password", "", buffer, sizeof (buffer));
      if (buffer [0])
- 	return g_strdup (buffer);
+ 	return mhl_str_dup (buffer);
      else
  	return 0;
  }
diff --combined src/subshell.c
index 05e177f,6c7fc34..8fcc7e4
--- a/src/subshell.c
+++ b/src/subshell.c
@@@ -44,6 -44,8 +44,8 @@@
  #  include <stropts.h> /* For I_PUSH */
  #endif /* HAVE_STROPTS_H */
  
+ #include <mhl/string.h>
+ 
  #include "global.h"
  #include "tty.h"	/* LINES */
  #include "panel.h"	/* current_panel */
@@@ -227,9 -229,9 +229,9 @@@ init_subshell_child (const char *pty_na
      mc_sid = getsid (0);
      if (mc_sid != -1) {
  	char sid_str[BUF_SMALL];
 -	g_snprintf (sid_str, sizeof (sid_str), "MC_SID=%ld",
 +	snprintf (sid_str, sizeof (sid_str), "MC_SID=%ld",
  		    (long) mc_sid);
- 	putenv (g_strdup (sid_str));
+ 	putenv (mhl_str_dup (sid_str));
      }
  #endif				/* HAVE_GETSID */
  
@@@ -420,7 -422,7 +422,7 @@@ init_subshell (void
  	/* Create a pipe for receiving the subshell's CWD */
  
  	if (subshell_type == TCSH) {
 -	    g_snprintf (tcsh_fifo, sizeof (tcsh_fifo), "%s/mc.pipe.%d",
 +	    snprintf (tcsh_fifo, sizeof (tcsh_fifo), "%s/mc.pipe.%d",
  			mc_tmpdir (), (int) getpid ());
  	    if (mkfifo (tcsh_fifo, 0600) == -1) {
  		fprintf (stderr, "mkfifo(%s) failed: %s\r\n", tcsh_fifo,
@@@ -468,19 -470,19 +470,19 @@@
  
      switch (subshell_type) {
      case BASH:
 -	g_snprintf (precmd, sizeof (precmd),
 +	snprintf (precmd, sizeof (precmd),
  		    " PROMPT_COMMAND='pwd>&%d;kill -STOP $$'\n",
  		    subshell_pipe[WRITE]);
  	break;
  
      case ZSH:
 -	g_snprintf (precmd, sizeof (precmd),
 +	snprintf (precmd, sizeof (precmd),
  		    " precmd(){ pwd>&%d;kill -STOP $$ }\n",
  		    subshell_pipe[WRITE]);
  	break;
  
      case TCSH:
 -	g_snprintf (precmd, sizeof (precmd),
 +	snprintf (precmd, sizeof (precmd),
  		    "set echo_style=both;"
  		    "alias precmd 'echo $cwd:q >>%s;kill -STOP $$'\n",
  		    tcsh_fifo);
@@@ -796,7 -798,7 +798,7 @@@ do_subshell_chdir (const char *director
  	}
  
  	if (bPathNotEq && strcmp (current_panel->cwd, ".")) {
- 	    char *cwd = strip_password (g_strdup (current_panel->cwd), 1);
+ 	    char *cwd = strip_password (mhl_str_dup (current_panel->cwd), 1);
  	    fprintf (stderr, _("Warning: Cannot change to %s.\n"), cwd);
  	    g_free (cwd);
  	}
diff --combined src/treestore.c
index fddd4e7,483d7fa..a9f2e81
--- a/src/treestore.c
+++ b/src/treestore.c
@@@ -41,7 -41,6 +41,7 @@@
  #include <sys/stat.h>
  #include <unistd.h>
  
 +#include <mhl/types.h>
  #include <mhl/string.h>
  
  #include "global.h"
@@@ -136,7 -135,7 +136,7 @@@ tree_store_get(void
  static char *
  decode(char *buffer)
  {
-     char *res = g_strdup(buffer);
+     char *res = mhl_str_dup(buffer);
      char *p, *q;
  
      for (p = q = res; *p; p++, q++) {
@@@ -267,7 -266,7 +267,7 @@@ tree_store_load(void
      char *name;
      int retval;
  
 -    name = concat_dir_and_file(home_dir, MC_TREE);
 +    name = mhl_str_dir_plus_file(home_dir, MC_TREE);
      retval = tree_store_load_from(name);
      g_free(name);
  
@@@ -373,7 -372,7 +373,7 @@@ tree_store_save(void
      char *name;
      int retval;
  
 -    tmp = concat_dir_and_file(home_dir, MC_TREE_TMP);
 +    tmp = mhl_str_dir_plus_file(home_dir, MC_TREE_TMP);
      retval = tree_store_save_to(tmp);
  
      if (retval) {
@@@ -381,7 -380,7 +381,7 @@@
  	return retval;
      }
  
 -    name = concat_dir_and_file(home_dir, MC_TREE);
 +    name = mhl_str_dir_plus_file(home_dir, MC_TREE);
      retval = rename(tmp, name);
  
      g_free(tmp);
@@@ -445,7 -444,7 +445,7 @@@ tree_store_add_entry(const char *name
      }
  
      /* Calculate attributes */
-     new->name = g_strdup(name);
+     new->name = mhl_str_dup(name);
      len = strlen(new->name);
      new->sublevel = 0;
      for (i = 0; i < len; i++)
@@@ -473,7 -472,7 +473,7 @@@
  
      if (new->sublevel > 1) {
  	/* Let's check if the parent directory is in the tree */
- 	char *parent = g_strdup(new->name);
+ 	char *parent = mhl_str_dup(new->name);
  	int i;
  
  	for (i = strlen(parent) - 1; i > 1; i--) {
@@@ -607,7 -606,7 +607,7 @@@ tree_store_mark_checked(const char *sub
      if (ts.check_name[0] == PATH_SEP && ts.check_name[1] == 0)
  	name = g_strconcat(PATH_SEP_STR, subname, (char *) NULL);
      else
 -	name = concat_dir_and_file(ts.check_name, subname);
 +	name = mhl_str_dir_plus_file(ts.check_name, subname);
  
      /* Search for the subdirectory */
      current = ts.check_start;
@@@ -617,7 -616,7 +617,7 @@@
      if (flag != 0) {
  	/* Doesn't exist -> add it */
  	current = tree_store_add_entry(name);
- 	ts.add_queue = g_list_prepend(ts.add_queue, g_strdup(name));
+ 	ts.add_queue = g_list_prepend(ts.add_queue, mhl_str_dup(name));
      }
      g_free(name);
  
@@@ -662,12 -661,12 +662,12 @@@ tree_store_start_check(const char *path
  	    return NULL;
  
  	current = tree_store_add_entry(path);
- 	ts.check_name = g_strdup(path);
+ 	ts.check_name = mhl_str_dup(path);
  
  	return current;
      }
  
-     ts.check_name = g_strdup(path);
+     ts.check_name = mhl_str_dup(path);
  
      retval = current;
  
@@@ -739,13 -738,13 +739,13 @@@ process_special_dirs(GList ** special_d
  			    "", buffer, 4096, file);
      s = buffer;
      while ((token = strtok(s, ",")) != NULL) {
- 	*special_dirs = g_list_prepend(*special_dirs, g_strdup(token));
+ 	*special_dirs = g_list_prepend(*special_dirs, mhl_str_dup(token));
  	s = NULL;
      }
      g_free(buffer);
  }
  
 -static gboolean
 +static bool
  should_skip_directory(const char *dir)
  {
      static GList *special_dirs;
@@@ -797,7 -796,7 +797,7 @@@ tree_store_rescan(const char *dir
  		    continue;
  	    }
  
 -	    full_name = concat_dir_and_file(dir, dp->d_name);
 +	    full_name = mhl_str_dir_plus_file(dir, dp->d_name);
  	    if (mc_lstat(full_name, &buf) != -1) {
  		if (S_ISDIR(buf.st_mode))
  		    tree_store_mark_checked(dp->d_name);
diff --combined src/user.c
index faa0ba9,8f65dc5..84d59ab
--- a/src/user.c
+++ b/src/user.c
@@@ -146,7 -146,7 +146,7 @@@ int check_format_var (const char *p, ch
  	value = getenv (var_name);
  	g_free (var_name);
  	if (value){
- 	    *v = g_strdup (value);
+ 	    *v = mhl_str_dup (value);
  	    return q-p;
  	}	
  	var_name = g_strndup (dots, q - dots);
@@@ -181,7 -181,7 +181,7 @@@ expand_format (struct WEdit *edit_widge
      char c_lc;
  
      if (c == '%')
- 	return g_strdup ("%");
+ 	return mhl_str_dup ("%");
  
      if (edit_one_file != NULL)
  	fname = edit_widget->filename;
@@@ -190,7 -190,7 +190,7 @@@
  	    panel = current_panel;
  	else {
  	    if (get_other_type () != view_listing)
- 		return g_strdup ("");
+ 		return mhl_str_dup ("");
  	    panel = other_panel;
  	}
  	fname = panel->dir.list[panel->selected].fname;
@@@ -233,7 -233,7 +233,7 @@@
  	break;
      case 'y':			/* syntax type */
  	if (edit_widget && edit_widget->syntax_type)
- 	    return g_strdup (edit_widget->syntax_type);
+ 	    return mhl_str_dup (edit_widget->syntax_type);
  	break;
      case 'k':			/* block file name */
      case 'b':			/* block file name / strip extension */  {
@@@ -268,7 -268,7 +268,7 @@@
  	    char *block, *tmp;
  
  	    if (!panel)
- 		return g_strdup ("");
+ 		return mhl_str_dup ("");
  
  	    for (i = 0; i < panel->count; i++)
  		if (panel->dir.list[i].f.marked)
@@@ -288,7 -288,7 +288,7 @@@
  	    return block;
  	}			/* sub case block */
      }				/* switch */
-     result = g_strdup ("% ");
+     result = mhl_str_dup ("% ");
      result[1] = c;
      return result;
  }
@@@ -720,14 -720,14 +720,14 @@@ user_menu_cmd (struct WEdit *edit_widge
  	return;
      }
      
-     menu = g_strdup (edit_widget ? CEDIT_LOCAL_MENU : MC_LOCAL_MENU);
+     menu = mhl_str_dup (edit_widget ? CEDIT_LOCAL_MENU : MC_LOCAL_MENU);
      if (!exist_file (menu) || !menu_file_own (menu)){
  	g_free (menu);
 -        menu = concat_dir_and_file \
 +        menu = mhl_str_dir_plus_file \
                              (home_dir, edit_widget ? CEDIT_HOME_MENU : MC_HOME_MENU);
  	if (!exist_file (menu)){
  	    g_free (menu);
 -	    menu = concat_dir_and_file \
 +	    menu = mhl_str_dir_plus_file \
                          (mc_home, edit_widget ? CEDIT_GLOBAL_MENU : MC_GLOBAL_MENU);
  	}
      }
diff --combined src/util.c
index deeff58,a7f06ff..9e20751
--- a/src/util.c
+++ b/src/util.c
@@@ -30,12 -30,10 +30,11 @@@
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
- 
  #include <sys/types.h>
  #include <sys/stat.h>
  #include <unistd.h>
  
 +#include <mhl/escape.h>
  #include <mhl/string.h>
  
  #include "global.h"
@@@ -221,7 -219,7 +220,7 @@@ char 
  fake_name_quote (const char *s, int quote_percent)
  {
      (void) quote_percent;
-     return g_strdup (s);
+     return mhl_str_dup (s);
  }
  
  /*
@@@ -230,27 -228,22 +229,27 @@@
   * Return static buffer, no need to free() it.
   */
  const char *
 -name_trunc (const char *txt, int trunc_len)
 +name_trunc (const char *txt, size_t trunc_len)
  {
      static char x[MC_MAXPATHLEN + MC_MAXPATHLEN];
 -    int txt_len;
 +    size_t txt_len;
      char *p;
  
 -    if ((size_t) trunc_len > sizeof (x) - 1) {
 +    if (!txt)
 +	return NULL;
 +    if (!*txt)
 +	return txt;
 +
 +    if (trunc_len > sizeof (x) - 1) {
  	trunc_len = sizeof (x) - 1;
      }
      txt_len = strlen (txt);
      if (txt_len <= trunc_len) {
  	strcpy (x, txt);
      } else {
 -	int y = (trunc_len / 2) + (trunc_len % 2);
 -	strncpy (x, txt, y);
 -	strncpy (x + y, txt + txt_len - (trunc_len / 2), trunc_len / 2);
 +	size_t y = (trunc_len / 2) + (trunc_len % 2);
 +	strncpy (x, txt, (size_t) y);
 +	strncpy (x + y, txt + (txt_len - (trunc_len / 2)), trunc_len / 2);
  	x[y] = '~';
      }
      x[trunc_len] = 0;
@@@ -266,9 -259,9 +265,9 @@@
   * reasons.
   */
  const char *
 -path_trunc (const char *path, int trunc_len) {
 +path_trunc (const char *path, size_t trunc_len) {
      const char *ret;
-     char *secure_path = strip_password (g_strdup (path), 1);
+     char *secure_path = strip_password (mhl_str_dup (path), 1);
      
      ret = name_trunc (secure_path, trunc_len);
      g_free (secure_path);
@@@ -291,7 -284,7 +290,7 @@@ size_trunc (double size
  	    xtra = "M";
  	}
      }
 -    g_snprintf (x, sizeof (x), "%.0f%s", (size/divisor), xtra);
 +    snprintf (x, sizeof (x), "%.0f%s", (size/divisor), xtra);
      return x;
  }
  
@@@ -350,18 -343,18 +349,18 @@@ size_trunc_len (char *buffer, int len, 
  	if (size == 0) {
  	    if (j == units) {
  		/* Empty files will print "0" even with minimal width.  */
 -		g_snprintf (buffer, len + 1, "0");
 +		snprintf (buffer, len + 1, "0");
  		break;
  	    }
  
  	    /* Use "~K" or just "K" if len is 1.  Use "B" for bytes.  */
 -	    g_snprintf (buffer, len + 1, (len > 1) ? "~%s" : "%s",
 +	    snprintf (buffer, len + 1, (len > 1) ? "~%s" : "%s",
  			(j > 1) ? suffix[j - 1] : "B");
  	    break;
  	}
  
  	if (size < power10 [len - (j > 0)]) {
 -	    g_snprintf (buffer, len + 1, "%lu%s", (unsigned long) size, suffix[j]);
 +	    snprintf (buffer, len + 1, "%lu%s", (unsigned long) size, suffix[j]);
  	    break;
  	}
  
@@@ -587,7 -580,7 +586,7 @@@ convert_pattern (const char *pattern, i
  	*d = 0;
  	return new_pattern;
      } else
- 	return  g_strdup (pattern);
+ 	return  mhl_str_dup (pattern);
  }
  
  int
@@@ -635,7 -628,7 +634,7 @@@ set_int (const char *file, const char *
  {
      char buffer [BUF_TINY];
  
 -    g_snprintf (buffer, sizeof (buffer), "%d", value);
 +    snprintf (buffer, sizeof (buffer), "%d", value);
      return WritePrivateProfileString (app_text, key, buffer, file);
  }
  
@@@ -644,7 -637,7 +643,7 @@@ get_config_string (const char *file, co
  {
      char buffer[1024];
      (void)GetPrivateProfileString (app_text, key, defval, buffer, sizeof(buffer), file);
-     return g_strdup (buffer);
+     return mhl_str_dup (buffer);
  }
  
  extern void
@@@ -694,7 -687,7 +693,7 @@@ load_mc_home_file (const char *filename
      char *lang;
      char *data;
  
 -    hintfile_base = concat_dir_and_file (mc_home, filename);
 +    hintfile_base = mhl_str_dir_plus_file (mc_home, filename);
      lang = guess_message_value ();
  
      hintfile = g_strconcat (hintfile_base, ".", lang, (char *) NULL);
@@@ -851,11 -844,11 +850,11 @@@ unix_error_string (int error_num
      gchar *strerror_currentlocale;
  	
      strerror_currentlocale = g_locale_from_utf8(g_strerror (error_num), -1, NULL, NULL, NULL);
 -    g_snprintf (buffer, sizeof (buffer), "%s (%d)",
 +    snprintf (buffer, sizeof (buffer), "%s (%d)",
  		strerror_currentlocale, error_num);
      g_free(strerror_currentlocale);
  #else
 -    g_snprintf (buffer, sizeof (buffer), "%s (%d)",
 +    snprintf (buffer, sizeof (buffer), "%s (%d)",
  		g_strerror (error_num), error_num);
  #endif
      return buffer;
@@@ -1098,7 -1091,7 +1097,7 @@@ wipe_password (char *passwd
  char *
  convert_controls (const char *p)
  {
-     char *valcopy = g_strdup (p);
+     char *valcopy = mhl_str_dup (p);
      char *q;
  
      /* Parse the escape special character */
@@@ -1253,6 -1246,18 +1252,6 @@@ diff_two_paths (const char *first, cons
      return buf;
  }
  
 -/* If filename is NULL, then we just append PATH_SEP to the dir */
 -char *
 -concat_dir_and_file (const char *dir, const char *file)
 -{
 -    int i = strlen (dir);
 -    
 -    if (dir [i-1] == PATH_SEP)
 -	return  g_strconcat (dir, file, (char *) NULL);
 -    else
 -	return  g_strconcat (dir, PATH_SEP_STR, file, (char *) NULL);
 -}
 -
  /* Append text to GList, remove all entries with the same text */
  GList *
  list_append_unique (GList *list, char *text)
@@@ -1313,9 -1318,9 +1312,9 @@@ mc_mkstemps (char **pname, const char *
  
      if (strchr (prefix, PATH_SEP) == NULL) {
  	/* Add prefix first to find the position of XXXXXX */
 -	tmpbase = concat_dir_and_file (mc_tmpdir (), prefix);
 +	tmpbase = mhl_str_dir_plus_file (mc_tmpdir (), prefix);
      } else {
- 	tmpbase = g_strdup (prefix);
+ 	tmpbase = mhl_str_dup (prefix);
      }
  
      tmpname = g_strconcat (tmpbase, "XXXXXX", suffix, (char *) NULL);
@@@ -1381,7 -1386,7 +1380,7 @@@ load_file_position (const char *filenam
      *column = 0;
  
      /* open file with positions */
 -    fn = concat_dir_and_file (home_dir, MC_FILEPOS);
 +    fn = mhl_str_dir_plus_file (home_dir, MC_FILEPOS);
      f = fopen (fn, "r");
      g_free (fn);
      if (!f)
@@@ -1428,8 -1433,8 +1427,8 @@@ save_file_position (const char *filenam
  
      len = strlen (filename);
  
 -    tmp = concat_dir_and_file (home_dir, MC_FILEPOS_TMP);
 -    fn = concat_dir_and_file (home_dir, MC_FILEPOS);
 +    tmp = mhl_str_dir_plus_file (home_dir, MC_FILEPOS_TMP);
 +    fn = mhl_str_dir_plus_file (home_dir, MC_FILEPOS);
  
      /* open temporary file */
      t = fopen (tmp, "w");
@@@ -1522,3 -1527,4 +1521,3 @@@ Q_ (const char *s
      sep = strchr(result, '|');
      return (sep != NULL) ? sep + 1 : result;
  }
 -
diff --combined src/utilunix.c
index bc558f9,ef5dfef..b550f44
--- a/src/utilunix.c
+++ b/src/utilunix.c
@@@ -41,7 -41,6 +41,7 @@@
  #endif
  #include <unistd.h>
  
 +#include <mhl/types.h>
  #include <mhl/string.h>
  
  #include "global.h"
@@@ -75,7 -74,7 +75,7 @@@ static void i_cache_add (int id, int_ca
  			 int *last)
  {
      g_free (cache [*last].string);
-     cache [*last].string = g_strdup (text);
+     cache [*last].string = mhl_str_dup (text);
      cache [*last].index = id;
      *last = ((*last)+1) % size;
  }
@@@ -96,7 -95,7 +96,7 @@@ char *get_owner (int uid
  	return pwd->pw_name;
      }
      else {
 -	g_snprintf (ibuf, sizeof (ibuf), "%d", uid);
 +	snprintf (ibuf, sizeof (ibuf), "%d", uid);
  	return ibuf;
      }
  }
@@@ -116,7 -115,7 +116,7 @@@ char *get_group (int gid
  	i_cache_add (gid, gid_cache, GID_CACHE_SIZE, grp->gr_name, &gid_last);
  	return grp->gr_name;
      } else {
 -	g_snprintf (gbuf, sizeof (gbuf), "%d", gid);
 +	snprintf (gbuf, sizeof (gbuf), "%d", gid);
  	return gbuf;
      }
  }
@@@ -189,7 -188,7 +189,7 @@@ tilde_expand (const char *directory
      char *name;
  
      if (*directory != '~')
- 	return g_strdup (directory);
+ 	return mhl_str_dup (directory);
  
      p = directory + 1;
  
@@@ -211,7 -210,7 +211,7 @@@
  
      /* If we can't figure the user name, leave tilde unexpanded */
      if (!passwd)
- 	return g_strdup (directory);
+ 	return mhl_str_dup (directory);
  
      return g_strconcat (passwd->pw_dir, PATH_SEP_STR, q, (char *) NULL);
  }
@@@ -257,10 -256,10 +257,10 @@@ mc_tmpdir (void
      pwd = getpwuid (getuid ());
  
      if (pwd)
 -	g_snprintf (buffer, sizeof (buffer), "%s/mc-%s", sys_tmp,
 +	snprintf (buffer, sizeof (buffer), "%s/mc-%s", sys_tmp,
  		pwd->pw_name);
      else
 -	g_snprintf (buffer, sizeof (buffer), "%s/mc-%lu", sys_tmp,
 +	snprintf (buffer, sizeof (buffer), "%s/mc-%lu", sys_tmp,
  		(unsigned long) getuid ());
  
      canonicalize_pathname (buffer);
@@@ -309,11 -308,11 +309,11 @@@
  	if (fallback_ok) {
  	    fprintf (stderr, _("Temporary files will be created in %s\n"),
  		     sys_tmp);
 -	    g_snprintf (buffer, sizeof (buffer), "%s", sys_tmp);
 +	    snprintf (buffer, sizeof (buffer), "%s", sys_tmp);
  	    error = NULL;
  	} else {
  	    fprintf (stderr, _("Temporary files will not be created\n"));
 -	    g_snprintf (buffer, sizeof (buffer), "%s", "/dev/null/");
 +	    snprintf (buffer, sizeof (buffer), "%s", "/dev/null/");
  	}
  
  	fprintf (stderr, "%s\n", _("Press any key to continue..."));
@@@ -429,7 -428,7 +429,7 @@@ canonicalize_pathname (char *path
  	if (p[0] == PATH_SEP && p[1] == PATH_SEP) {
  	    s = p + 1;
  	    while (*(++s) == PATH_SEP);
 -	    strcpy (p + 1, s);
 +	    mhl_strmove (p + 1, s);
  	}
  	p++;
      }
@@@ -438,7 -437,7 +438,7 @@@
      p = lpath;
      while (*p) {
  	if (p[0] == PATH_SEP && p[1] == '.' && p[2] == PATH_SEP)
 -	    strcpy (p, p + 2);
 +	    mhl_strmove (p, p + 2);
  	else
  	    p++;
      }
@@@ -454,7 -453,7 +454,7 @@@
  	    lpath[1] = 0;
  	    return;
  	} else {
 -	    strcpy (lpath, lpath + 2);
 +	    mhl_strmove (lpath, lpath + 2);
  	}
      }
  
@@@ -500,10 -499,10 +500,10 @@@
  	if (p[3] != 0) {
  	    if (s == lpath && *s == PATH_SEP) {
  		/* "/../foo" -> "/foo" */
 -		strcpy (s + 1, p + 4);
 +		mhl_strmove (s + 1, p + 4);
  	    } else {
  		/* "token/../foo" -> "foo" */
 -		strcpy (s, p + 4);
 +		mhl_strmove (s, p + 4);
  	    }
  	    p = (s > lpath) ? s - 1 : s;
  	    continue;
@@@ -722,7 -721,7 +722,7 @@@ mc_realpath (const char *path, char res
  /* Return the index of the permissions triplet */
  int
  get_user_permissions (struct stat *st) {
 -    static gboolean initialized = FALSE;
 +    static bool initialized = FALSE;
      static gid_t *groups;
      static int ngroups;
      static uid_t uid;
diff --combined src/view.c
index f7ebe84,79e2f68..5a3de16
--- a/src/view.c
+++ b/src/view.c
@@@ -43,7 -43,7 +43,8 @@@
  #include <sys/stat.h>
  #include <unistd.h>
  
 +#include <mhl/types.h>
+ #include <mhl/string.h>
  
  #include "global.h"
  #include "tty.h"
@@@ -143,23 -143,23 +144,23 @@@ struct WView 
      size_t ds_string_len;	/* The length of the string */
  
      /* Growing buffers information */
 -    gboolean growbuf_in_use;	/* Use the growing buffers? */
 +    bool growbuf_in_use;	/* Use the growing buffers? */
      byte   **growbuf_blockptr;	/* Pointer to the block pointers */
      size_t   growbuf_blocks;	/* The number of blocks in *block_ptr */
      size_t   growbuf_lastindex;	/* Number of bytes in the last page of the
  				   growing buffer */
 -    gboolean growbuf_finished;	/* TRUE when all data has been read. */
 +    bool growbuf_finished;	/* TRUE when all data has been read. */
  
      /* Editor modes */
 -    gboolean hex_mode;		/* Hexview or Hexedit */
 -    gboolean hexedit_mode;	/* Hexedit */
 -    gboolean hexview_in_text;	/* Is the hexview cursor in the text area? */
 -    gboolean text_nroff_mode;	/* Nroff-style highlighting */
 -    gboolean text_wrap_mode;	/* Wrap text lines to fit them on the screen */
 -    gboolean magic_mode;	/* Preprocess the file using external programs */
 +    bool hex_mode;		/* Hexview or Hexedit */
 +    bool hexedit_mode;	/* Hexedit */
 +    bool hexview_in_text;	/* Is the hexview cursor in the text area? */
 +    bool text_nroff_mode;	/* Nroff-style highlighting */
 +    bool text_wrap_mode;	/* Wrap text lines to fit them on the screen */
 +    bool magic_mode;	/* Preprocess the file using external programs */
  
      /* Additional editor state */
 -    gboolean hexedit_lownibble;	/* Are we editing the last significant nibble? */
 +    bool hexedit_lownibble;	/* Are we editing the last significant nibble? */
      GArray *coord_cache;	/* Cache for mapping offsets to cursor positions */
  
      /* Display information */
@@@ -177,7 -177,7 +178,7 @@@
      struct area data_area;	/* Where the data is displayed */
  
      int dirty;			/* Number of skipped updates */
 -    gboolean dpy_bbar_dirty;	/* Does the button bar need to be updated? */
 +    bool dpy_bbar_dirty;	/* Does the button bar need to be updated? */
  
      /* Mode variables */
      int bytes_per_line;		/* Number of bytes per line in hex mode */
@@@ -189,7 -189,7 +190,7 @@@
      int  direction;		/* 1= forward; -1 backward */
      void (*last_search)(WView *);
  				/* Pointer to the last search command */
 -    gboolean want_to_quit;	/* Prepare for cleanup ... */
 +    bool want_to_quit;	/* Prepare for cleanup ... */
  
      /* Markers */
      int marker;			/* mark to use */
@@@ -280,7 -280,7 +281,7 @@@ offset_rounddown (offset_type a, offset
  
  /* {{{ Simple Primitive Functions for WView }}} */
  
 -static inline gboolean
 +static inline bool
  view_is_in_panel (WView *view)
  {
      return (view->dpy_frame_size != 0);
@@@ -400,7 -400,7 +401,7 @@@ view_growbuf_read_until (WView *view, o
      ssize_t nread;
      byte *p;
      size_t bytesfree;
 -    gboolean short_read;
 +    bool short_read;
  
      assert (view->growbuf_in_use);
  
@@@ -515,7 -515,7 +516,7 @@@ view_get_filesize (WView *view
      }
  }
  
 -static inline gboolean
 +static inline bool
  view_may_still_grow (WView *view)
  {
      return (view->growbuf_in_use && !view->growbuf_finished);
@@@ -524,7 -524,7 +525,7 @@@
  /* returns TRUE if the idx lies in the half-open interval
   * [offset; offset + size), FALSE otherwise.
   */
 -static inline gboolean
 +static inline bool
  already_loaded (offset_type offset, offset_type idx, size_t size)
  {
      return (offset <= idx && idx - offset < size);
@@@ -665,7 -665,7 +666,7 @@@ static voi
  view_set_datasource_string (WView *view, const char *s)
  {
      view->datasource = DS_STRING;
-     view->ds_string_data = (byte *) g_strdup (s);
+     view->ds_string_data = (byte *) mhl_str_dup (s);
      view->ds_string_len  = strlen (s);
  }
  
@@@ -740,10 -740,10 +741,10 @@@ enum ccache_type 
      CCACHE_LINECOL
  };
  
 -static inline gboolean
 +static inline bool
  coord_cache_entry_less (const struct coord_cache_entry *a,
  	const struct coord_cache_entry *b, enum ccache_type crit,
 -	gboolean nroff_mode)
 +	bool nroff_mode)
  {
      if (crit == CCACHE_OFFSET)
  	return (a->cc_offset < b->cc_offset);
@@@ -829,7 -829,7 +830,7 @@@ view_ccache_dump (WView *view
  }
  #endif
  
 -static inline gboolean
 +static inline bool
  is_nroff_sequence (WView *view, offset_type offset)
  {
      int c0, c1, c2;
@@@ -1089,7 -1089,7 +1090,7 @@@ view_scroll_to_cursor (WView *view
  }
  
  static void
 -view_movement_fixups (WView *view, gboolean reset_search)
 +view_movement_fixups (WView *view, bool reset_search)
  {
      view_scroll_to_cursor (view);
      if (reset_search) {
@@@ -1393,8 -1393,8 +1394,8 @@@ view_toggle_magic_mode (WView *view
  
      altered_magic_flag = 1;
      view->magic_mode = !view->magic_mode;
-     filename = g_strdup (view->filename);
-     command = g_strdup (view->command);
+     filename = mhl_str_dup (view->filename);
+     command = mhl_str_dup (view->command);
  
      view_done (view);
      view_load (view, command, filename, 0);
@@@ -1455,7 -1455,7 +1456,7 @@@ view_show_error (WView *view, const cha
      }
  }
  
 -static gboolean
 +static bool
  view_load_command_output (WView *view, const char *command)
  {
      FILE *fp;
@@@ -1485,7 -1485,7 +1486,7 @@@
      return TRUE;
  }
  
 -gboolean
 +bool
  view_load (WView *view, const char *command, const char *file,
  	   int start_line)
  {
@@@ -1493,14 -1493,14 +1494,14 @@@
      int fd = -1;
      char tmp[BUF_MEDIUM];
      struct stat st;
 -    gboolean retval = FALSE;
 +    bool retval = FALSE;
  
      assert (view->bytes_per_line != 0);
      view_done (view);
  
      /* Set up the state */
      view_set_datasource_none (view);
-     view->filename = g_strdup (file);
+     view->filename = mhl_str_dup (file);
      view->command = 0;
  
      /* Clear the markers */
@@@ -1517,7 -1517,7 +1518,7 @@@
      } else if (file != NULL && file[0] != '\0') {
  	/* Open the file */
  	if ((fd = mc_open (file, O_RDONLY | O_NONBLOCK)) == -1) {
 -	    g_snprintf (tmp, sizeof (tmp), _(" Cannot open \"%s\"\n %s "),
 +	    snprintf (tmp, sizeof (tmp), _(" Cannot open \"%s\"\n %s "),
  			file, unix_error_string (errno));
  	    view_show_error (view, tmp);
  	    goto finish;
@@@ -1526,7 -1526,7 +1527,7 @@@
  	/* Make sure we are working with a regular file */
  	if (mc_fstat (fd, &st) == -1) {
  	    mc_close (fd);
 -	    g_snprintf (tmp, sizeof (tmp), _(" Cannot stat \"%s\"\n %s "),
 +	    snprintf (tmp, sizeof (tmp), _(" Cannot stat \"%s\"\n %s "),
  			file, unix_error_string (errno));
  	    view_show_error (view, tmp);
  	    goto finish;
@@@ -1554,7 -1554,7 +1555,7 @@@
      }
  
    finish:
-     view->command = g_strdup (command);
+     view->command = mhl_str_dup (command);
      view->dpy_start = 0;
      view->search_start = 0;
      view->search_length = 0;
@@@ -1742,7 -1742,7 +1743,7 @@@ view_display_ruler (WView *view
  	}
  
  	if ((cl != 0) && (cl % 10) == 0) {
 -	    g_snprintf (r_buff, sizeof (r_buff), "%"OFFSETTYPE_PRId, cl);
 +	    snprintf (r_buff, sizeof (r_buff), "%"OFFSETTYPE_PRId, cl);
  	    if (nums_row < height) {
  		widget_move (view, top + nums_row, left + c - 1);
  		tty_print_string (r_buff);
@@@ -1790,7 -1790,7 +1791,7 @@@ view_display_hex (WView *view
  	col = 0;
  
  	/* Print the hex offset */
 -	g_snprintf (hex_buff, sizeof (hex_buff), "%08"OFFSETTYPE_PRIX" ", from);
 +	snprintf (hex_buff, sizeof (hex_buff), "%08"OFFSETTYPE_PRIX" ", from);
  	widget_move (view, top + row, left);
  	tty_setcolor (MARKED_COLOR);
  	for (i = 0; col < width && hex_buff[i] != '\0'; i++) {
@@@ -2137,7 -2137,7 +2138,7 @@@ view_handle_editkey (WView *view, int k
      return MSG_HANDLED;
  }
  
 -static gboolean
 +static bool
  view_hexedit_save_changes (WView *view)
  {
      struct hexedit_change_node *curr, *next;
@@@ -2168,7 -2168,7 +2169,7 @@@
      }
  
      if (mc_close (fp) == -1) {
- 	error = g_strdup (strerror (errno));
+ 	error = mhl_str_dup (strerror (errno));
  	message (D_ERROR, _(" Save file "),
  	    _(" Error while closing the file: \n %s \n"
  	      " Data may have been written or not. "), error);
@@@ -2178,7 -2178,7 +2179,7 @@@
      return TRUE;
  
    save_error:
-     error = g_strdup (strerror (errno));
+     error = mhl_str_dup (strerror (errno));
      text = g_strdup_printf (_(" Cannot save file: \n %s "), error);
      g_free (error);
      (void) mc_close (fp);
@@@ -2194,7 -2194,7 +2195,7 @@@
  
  /* {{{ Miscellaneous functions }}} */
  
 -static gboolean
 +static bool
  view_ok_to_quit (WView *view)
  {
      int r;
@@@ -2652,7 -2652,7 +2653,7 @@@ regexp_view_search (WView *view, char *
  	    message (D_ERROR, MSG_ERROR, _(" Invalid regular expression "));
  	    return -1;
  	}
- 	old_pattern = g_strdup (pattern);
+ 	old_pattern = mhl_str_dup (pattern);
  	old_type = match_type;
      }
      if (regexec (&r, string, 1, pmatch, 0) != 0)
@@@ -2732,7 -2732,7 +2733,7 @@@ view_moveto_line_cmd (WView *view
  
      view_offset_to_coord (view, &line, &col, view->dpy_start);
  
 -    g_snprintf (prompt, sizeof (prompt),
 +    snprintf (prompt, sizeof (prompt),
  		_(" The current line number is %d.\n"
  		  " Enter the new line number:"), (int) (line + 1));
      answer = input_dialog (_(" Goto line "), prompt, MC_HISTORY_VIEW_GOTO_LINE, "");
@@@ -2753,7 -2753,7 +2754,7 @@@ view_moveto_addr_cmd (WView *view
      char *line, *error, prompt[BUF_SMALL];
      offset_type addr;
  
 -    g_snprintf (prompt, sizeof (prompt),
 +    snprintf (prompt, sizeof (prompt),
  		_(" The current address is 0x%lx.\n"
  		  " Enter the new address:"), view->hex_cursor);
      line = input_dialog (_(" Goto Address "), prompt, MC_HISTORY_VIEW_GOTO_ADDR, "");
@@@ -2847,7 -2847,7 +2848,7 @@@ view_normal_search_cmd (WView *view
  	"[Input Line Keys]", quick_widgets, 0
      };
  
-     defval = g_strdup (last_search_string != NULL ? last_search_string : "");
+     defval = mhl_str_dup (last_search_string != NULL ? last_search_string : "");
      convert_to_display (defval);
  
      quick_widgets[2].result = &treplace_backwards;
@@@ -3318,7 -3318,7 +3319,7 @@@ in
  mc_internal_viewer (const char *command, const char *file,
  	int *move_dir_p, int start_line)
  {
 -    gboolean succeeded;
 +    bool succeeded;
      WView *wview;
      WButtonBar *bar;
      Dlg_head *view_dlg;
diff --combined src/widget.c
index 7a3309b,6d93d26..70f208e
--- a/src/widget.c
+++ b/src/widget.c
@@@ -34,7 -34,6 +34,7 @@@
  #include <string.h>
  #include <sys/types.h>
  
 +#include <mhl/types.h>
  #include <mhl/string.h>
  
  #include "global.h"
@@@ -44,6 -43,7 +44,6 @@@
  #include "dialog.h"
  #include "widget.h"
  #include "win.h"
 -#include "complete.h"
  #include "key.h"	/* XCTRL and ALT macros  */
  #include "profile.h"	/* for history loading and saving */
  #include "wtools.h"	/* For common_dialog_repaint() */
@@@ -70,7 -70,7 +70,7 @@@ static int button_event (Gpm_Event *eve
  int quote = 0;
  
  static void
 -widget_selectcolor (Widget *w, gboolean focused, gboolean hotkey)
 +widget_selectcolor (Widget *w, bool focused, bool hotkey)
  {
      Dlg_head *h = w->parent;
  
@@@ -158,15 -158,15 +158,15 @@@ button_callback (Widget *w, widget_msg_
  
  	switch (b->flags) {
  	case DEFPUSH_BUTTON:
 -	    g_snprintf (buf, sizeof (buf), "[< %s >]", b->text);
 +	    snprintf (buf, sizeof (buf), "[< %s >]", b->text);
  	    off = 3;
  	    break;
  	case NORMAL_BUTTON:
 -	    g_snprintf (buf, sizeof (buf), "[ %s ]", b->text);
 +	    snprintf (buf, sizeof (buf), "[ %s ]", b->text);
  	    off = 2;
  	    break;
  	case NARROW_BUTTON:
 -	    g_snprintf (buf, sizeof (buf), "[%s]", b->text);
 +	    snprintf (buf, sizeof (buf), "[%s]", b->text);
  	    off = 1;
  	    break;
  	case HIDDEN_BUTTON:
@@@ -263,7 -263,7 +263,7 @@@ button_new (int y, int x, int action, i
      b->action = action;
      b->flags  = flags;
      b->selected = 0;
-     b->text   = g_strdup (text);
+     b->text   = mhl_str_dup (text);
      b->callback = callback;
      widget_want_hotkey (b->widget, 1);
      b->hotkey = 0;
@@@ -283,7 -283,7 +283,7 @@@ voi
  button_set_text (WButton *b, const char *text)
  {
     g_free (b->text);
-     b->text = g_strdup (text);
+     b->text = mhl_str_dup (text);
      b->widget.cols = button_len (text, b->flags);
      button_scan_hotkey(b);
      dlg_redraw (b->widget.parent);
@@@ -359,7 -359,7 +359,7 @@@ radio_callback (Widget *w, widget_msg_
      case WIDGET_DRAW:
  	for (i = 0; i < r->count; i++) {
  	    register const char *cp;
 -	    const gboolean focused = (i == r->pos && msg == WIDGET_FOCUS);
 +	    const bool focused = (i == r->pos && msg == WIDGET_FOCUS);
  	    widget_selectcolor (w, focused, FALSE);
  	    widget_move (&r->widget, i, 0);
  
@@@ -513,7 -513,7 +513,7 @@@ check_new (int y, int x, int state, con
      init_widget (&c->widget, y, x, 1, strlen (text),
  	check_callback, check_event);
      c->state = state ? C_BOOL : 0;
-     c->text = g_strdup (text);
+     c->text = mhl_str_dup (text);
      c->hotkey = 0;
      c->hotpos = -1;
      widget_want_hotkey (c->widget, 1);
@@@ -606,7 -606,7 +606,7 @@@ label_set_text (WLabel *label, const ch
      g_free (label->text);
  
      if (text){
- 	label->text = g_strdup (text);
+ 	label->text = mhl_str_dup (text);
  	if (label->auto_adjust_cols) {
  	    newcols = strlen (text);
  	    if (newcols > label->widget.cols)
@@@ -636,7 -636,7 +636,7 @@@ label_new (int y, int x, const char *te
  
      l = g_new (WLabel, 1);
      init_widget (&l->widget, y, x, 1, width, label_callback, NULL);
-     l->text = text ? g_strdup (text) : 0;
+     l->text = text ? mhl_str_dup (text) : 0;
      l->auto_adjust_cols = 1;
      l->transparent = 0;
      widget_want_cursor (l->widget, 0);
@@@ -867,17 -867,17 +867,17 @@@ history_get (const char *input_name
  	return NULL;
      if (!*input_name)
  	return NULL;
 -    profile = concat_dir_and_file (home_dir, HISTORY_FILE_NAME);
 +    profile = mhl_str_dir_plus_file (home_dir, HISTORY_FILE_NAME);
      for (i = 0;; i++) {
  	char key_name[BUF_TINY];
  	char this_entry[BUF_LARGE];
 -	g_snprintf (key_name, sizeof (key_name), "%d", i);
 +	snprintf (key_name, sizeof (key_name), "%d", i);
  	GetPrivateProfileString (input_name, key_name, "", this_entry,
  				 sizeof (this_entry), profile);
  	if (!*this_entry)
  	    break;
  
- 	hist = list_append_unique (hist, g_strdup (this_entry));
+ 	hist = list_append_unique (hist, mhl_str_dup (this_entry));
      }
      g_free (profile);
  
@@@ -905,7 -905,7 +905,7 @@@ history_put (const char *input_name, GL
      if (!num_history_items_recorded)	/* this is how to disable */
  	return;
  
 -    profile = concat_dir_and_file (home_dir, HISTORY_FILE_NAME);
 +    profile = mhl_str_dir_plus_file (home_dir, HISTORY_FILE_NAME);
  
      if ((i = open (profile, O_CREAT | O_EXCL, S_IRUSR | S_IWUSR)) != -1)
  	close (i);
@@@ -935,7 -935,7 +935,7 @@@
  	/* We shouldn't have null entries, but let's be sure */
  	if (text && *text) {
  	    char key_name[BUF_TINY];
 -	    g_snprintf (key_name, sizeof (key_name), "%d", i++);
 +	    snprintf (key_name, sizeof (key_name), "%d", i++);
  	    WritePrivateProfileString (input_name, key_name, text,
  				       profile);
  	}
@@@ -1040,7 -1040,7 +1040,7 @@@ show_hist (GList *history, int widget_x
      if (query_dlg->ret_value != B_CANCEL) {
  	listbox_get_current (query_list, &q, NULL);
  	if (q)
- 	    r = g_strdup (q);
+ 	    r = mhl_str_dup (q);
      }
      destroy_dlg (query_dlg);
      return r;
@@@ -1129,7 -1129,7 +1129,7 @@@ push_history (WInput *in, const char *t
  	    return 1;
      }
  
-     t = g_strdup (text);
+     t = mhl_str_dup (text);
  
      if (in->history_name) {
  	p = in->history_name + 3;
@@@ -1382,7 -1382,7 +1382,7 @@@ static voi
  kill_line (WInput *in)
  {
      g_free (kill_buffer);
-     kill_buffer = g_strdup (&in->buffer [in->point]);
+     kill_buffer = mhl_str_dup (&in->buffer [in->point]);
      in->buffer [in->point] = 0;
  }
  
@@@ -1391,7 -1391,7 +1391,7 @@@ assign_text (WInput *in, const char *te
  {
      free_completions (in);
      g_free (in->buffer);
-     in->buffer = g_strdup (text);	/* was in->buffer->text */
+     in->buffer = mhl_str_dup (text);	/* was in->buffer->text */
      in->current_max_len = strlen (in->buffer) + 1;
      in->point = strlen (in->buffer);
      in->mark = 0;
@@@ -1660,7 -1660,7 +1660,7 @@@ input_event (Gpm_Event * event, void *d
  
  WInput *
  input_new (int y, int x, int color, int len, const char *def_text,
 -	   const char *histname)
 +	   const char *histname, INPUT_COMPLETE_FLAGS completion_flags)
  {
      WInput *in = g_new (WInput, 1);
      int initial_buffer_len;
@@@ -1672,7 -1672,7 +1672,7 @@@
      in->history_name = 0;
      if (histname) {
  	if (*histname) {
- 	    in->history_name = g_strdup (histname);
+ 	    in->history_name = mhl_str_dup (histname);
  	    in->history = history_get (histname);
  	}
      }
@@@ -1689,7 -1689,9 +1689,7 @@@
      initial_buffer_len = 1 + max ((size_t) len, strlen (def_text));
      in->widget.options |= W_IS_INPUT;
      in->completions = NULL;
 -    in->completion_flags =
 -	INPUT_COMPLETE_FILENAMES | INPUT_COMPLETE_HOSTNAMES |
 -	INPUT_COMPLETE_VARIABLES | INPUT_COMPLETE_USERNAMES;
 +    in->completion_flags = completion_flags;
      in->current_max_len = initial_buffer_len;
      in->buffer = g_malloc (initial_buffer_len);
      in->color = color;
@@@ -2234,7 -2236,7 +2234,7 @@@ listbox_add_item (WListbox *l, enum app
  	    return NULL;
  	    
      entry = g_new (WLEntry, 1);
-     entry->text = g_strdup (text);
+     entry->text = mhl_str_dup (text);
      entry->data = data;
      entry->hotkey = hotkey;
  
@@@ -2283,7 -2285,7 +2283,7 @@@ listbox_get_current (WListbox *l, char 
  }
  
  /* returns TRUE if a function has been called, FALSE otherwise. */
 -static gboolean
 +static bool
  buttonbar_call (WButtonBar *bb, int i)
  {
      switch (bb->labels[i].tag) {
@@@ -2386,7 -2388,7 +2386,7 @@@ set_label_text (WButtonBar * bb, int in
  {
      g_free (bb->labels[index - 1].text);
  
-     bb->labels[index - 1].text = g_strdup (text);
+     bb->labels[index - 1].text = mhl_str_dup (text);
  }
  
  /* Find ButtonBar widget in the dialog */
@@@ -2442,7 -2444,7 +2442,7 @@@ buttonbar_set_label (Dlg_head *h, int i
  }
  
  void
 -buttonbar_set_visible (WButtonBar *bb, gboolean visible)
 +buttonbar_set_visible (WButtonBar *bb, bool visible)
  {
      bb->visible = visible;
  }
@@@ -2504,7 -2506,7 +2504,7 @@@ groupbox_new (int x, int y, int width, 
      /* Strip existing spaces, add one space before and after the title */
      if (title) {
  	char *t;
- 	t = g_strstrip (g_strdup (title));
+ 	t = g_strstrip (mhl_str_dup (title));
  	g->title = g_strconcat (" ", t, " ", (char *) NULL);
  	g_free (t);
      }
diff --combined src/wtools.c
index ba317e9,5fa1233..cfc25aa
--- a/src/wtools.c
+++ b/src/wtools.c
@@@ -29,6 -29,8 +29,8 @@@
  #include <stdio.h>
  #include <string.h>
  
+ #include <mhl/string.h>
+ 
  #include "global.h"
  #include "tty.h"
  #include "color.h"		/* dialog_colors */
@@@ -36,6 -38,7 +38,6 @@@
  #include "widget.h"
  #include "wtools.h"
  #include "key.h"		/* mi_getch() */
 -#include "complete.h"		/* INPUT_COMPLETE_CD */
  #include "background.h"		/* parent_call */
  
  
@@@ -360,7 -363,7 +362,7 @@@ quick_dialog_skip (QuickDialog *qd, in
  	case quick_input:
  	    input =
  		input_new (ypos, xpos, INPUT_COLOR, qw->hotkey_pos,
 -			   qw->text, qw->histname);
 +			   qw->text, qw->histname, INPUT_COMPLETE_DEFAULT);
  	    input->is_password = qw->value == 1;
  	    input->point = 0;
  	    if (qw->value & 2)
@@@ -405,7 -408,7 +407,7 @@@
  		    *qw->str_result =
  			tilde_expand (((WInput *) w)->buffer);
  		else
- 		    *qw->str_result = g_strdup (((WInput *) w)->buffer);
+ 		    *qw->str_result = mhl_str_dup (((WInput *) w)->buffer);
  		break;
  	    }
  	}
@@@ -498,7 -501,7 +500,7 @@@ fg_input_dialog_help (const char *heade
      Quick_input.title = header;
      Quick_input.help = help;
      Quick_input.i18n = 1; /* The dialog is already translated. */
-     p_text = g_strstrip (g_strdup (text));
+     p_text = g_strstrip (mhl_str_dup (text));
      quick_widgets[INPUT_INDEX + 1].text = p_text;
      quick_widgets[INPUT_INDEX].text = def_text;
  
diff --combined vfs/extfs.c
index b46057d,4641dd4..e4aef78
--- a/vfs/extfs.c
+++ b/vfs/extfs.c
@@@ -137,7 -137,7 +137,7 @@@ static void extfs_make_dots (struct ent
      struct inode *inode = ent->inode, *parent;
      
      parent = (parentry != NULL) ? parentry->inode : NULL;
-     entry->name = g_strdup (".");
+     entry->name = mhl_str_dup (".");
      entry->inode = inode;
      entry->dir = ent;
      inode->local_filename = NULL;
@@@ -145,7 -145,7 +145,7 @@@
      inode->nlink++;
      entry->next_in_dir = g_new (struct entry, 1);
      entry = entry->next_in_dir;
-     entry->name = g_strdup ("..");
+     entry->name = mhl_str_dup ("..");
      inode->last_in_subdir = entry;
      entry->next_in_dir = NULL;
      if (parent != NULL) {
@@@ -169,7 -169,7 +169,7 @@@ static struct entry *extfs_generate_ent
      parent = (parentry != NULL) ? parentry->inode : NULL;
      entry = g_new (struct entry, 1);
      
-     entry->name = g_strdup (name);
+     entry->name = mhl_str_dup (name);
      entry->next_in_dir = NULL;
      entry->dir = parentry;
      if (parent != NULL) {
@@@ -249,7 -249,7 +249,7 @@@ extfs_open_archive (int fstype, const c
  	tmp = name_quote (name, 0);
      }
  
 -    mc_extfsdir = concat_dir_and_file (mc_home, "extfs" PATH_SEP_STR);
 +    mc_extfsdir = mhl_str_dir_plus_file (mc_home, "extfs" PATH_SEP_STR);
      cmd =
  	g_strconcat (mc_extfsdir, extfs_prefixes[fstype], " list ",
  		     local_name ? local_name : tmp, (char *) NULL);
@@@ -272,7 -272,7 +272,7 @@@
  
      current_archive = g_new (struct archive, 1);
      current_archive->fstype = fstype;
-     current_archive->name = name ? g_strdup (name) : NULL;
+     current_archive->name = name ? mhl_str_dup (name) : NULL;
      current_archive->local_name = local_name;
  
      if (local_name != NULL)
@@@ -361,7 -361,7 +361,7 @@@ extfs_read_archive (int fstype, const c
  		    return -1;
  		}
  		entry = g_new (struct entry, 1);
- 		entry->name = g_strdup (p);
+ 		entry->name = mhl_str_dup (p);
  		entry->next_in_dir = NULL;
  		entry->dir = pent;
  		if (pent->inode->last_in_subdir) {
@@@ -493,11 -493,11 +493,11 @@@ static char 
  extfs_get_path (struct vfs_class *me, const char *inname, struct archive **archive,
  		int do_not_open)
  {
-     char *buf = g_strdup (inname);
+     char *buf = mhl_str_dup (inname);
      char *res = extfs_get_path_mangle (me, buf, archive, do_not_open);
      char *res2 = NULL;
      if (res)
- 	res2 = g_strdup (res);
+ 	res2 = mhl_str_dup (res);
      g_free (buf);
      return res2;
  }
@@@ -522,7 -522,7 +522,7 @@@ static char *extfs_get_path_from_entry 
      }
  
      if (len == 0)
- 	return g_strdup ("");
+ 	return mhl_str_dup ("");
      
      localpath = g_malloc (len);
      *localpath = '\0';
@@@ -624,7 -624,7 +624,7 @@@ extfs_cmd (const char *extfs_cmd, struc
      archive_name = name_quote (extfs_get_archive_name (archive), 0);
      quoted_localname = name_quote (localname, 0);
  
 -    mc_extfsdir = concat_dir_and_file (mc_home, "extfs" PATH_SEP_STR);
 +    mc_extfsdir = mhl_str_dir_plus_file (mc_home, "extfs" PATH_SEP_STR);
      cmd = g_strconcat (mc_extfsdir, extfs_prefixes[archive->fstype],
  		       extfs_cmd, archive_name, " ", quoted_file, " ",
  		       quoted_localname, (char *) NULL);
@@@ -653,7 -653,7 +653,7 @@@ extfs_run (struct vfs_class *me, const 
      g_free (p);
  
      archive_name = name_quote (extfs_get_archive_name (archive), 0);
 -    mc_extfsdir = concat_dir_and_file (mc_home, "extfs" PATH_SEP_STR);
 +    mc_extfsdir = mhl_str_dir_plus_file (mc_home, "extfs" PATH_SEP_STR);
      cmd = g_strconcat (mc_extfsdir, extfs_prefixes[archive->fstype],
  		       " run ", archive_name, " ", q, (char *) NULL);
      g_free (mc_extfsdir);
@@@ -947,7 -947,7 +947,7 @@@ extfs_internal_stat (struct vfs_class *
      struct archive *archive;
      char *q;
      struct entry *entry;
-     char *path2 = g_strdup (path);
+     char *path2 = mhl_str_dup (path);
      int result = -1;
  
      if ((q = extfs_get_path_mangle (me, path2, &archive, 0)) == NULL)
@@@ -989,7 -989,7 +989,7 @@@ extfs_readlink (struct vfs_class *me, c
      char *q;
      size_t len;
      struct entry *entry;
-     char *mpath = g_strdup (path);
+     char *mpath = mhl_str_dup (path);
      int result = -1;
  
      if ((q = extfs_get_path_mangle (me, mpath, &archive, 0)) == NULL)
@@@ -1030,7 -1030,7 +1030,7 @@@ static ssize_t extfs_write (void *data
  static int extfs_unlink (struct vfs_class *me, const char *file)
  {
      struct archive *archive;
-     char *q, *mpath = g_strdup (file);
+     char *q, *mpath = mhl_str_dup (file);
      struct entry *entry;
      int result = -1;
  
@@@ -1059,7 -1059,7 +1059,7 @@@ cleanup
  static int extfs_mkdir (struct vfs_class *me, const char *path, mode_t mode)
  {
      struct archive *archive;
-     char *q, *mpath = g_strdup(path);
+     char *q, *mpath = mhl_str_dup(path);
      struct entry *entry;
      int result = -1;
  
@@@ -1096,7 -1096,7 +1096,7 @@@ cleanup
  static int extfs_rmdir (struct vfs_class *me, const char *path)
  {
      struct archive *archive;
-     char *q, *mpath = g_strdup(path);
+     char *q, *mpath = mhl_str_dup(path);
      struct entry *entry;
      int result = -1;
  
@@@ -1262,7 -1262,7 +1262,7 @@@ extfs_getlocalcopy (struct vfs_class *m
  	extfs_close ((void *) fp);
  	return NULL;
      }
-     p = g_strdup (fp->entry->inode->local_filename);
+     p = mhl_str_dup (fp->entry->inode->local_filename);
      fp->archive->fd_usage++;
      extfs_close ((void *) fp);
      return p;
@@@ -1298,7 -1298,7 +1298,7 @@@ static int extfs_init (struct vfs_clas
  
      (void) me;
  
 -    mc_extfsini = concat_dir_and_file (mc_home, "extfs" PATH_SEP_STR "extfs.ini");
 +    mc_extfsini = mhl_str_dir_plus_file (mc_home, "extfs" PATH_SEP_STR "extfs.ini");
      cfg = fopen (mc_extfsini, "r");
  
      /* We may not use vfs_die() message or message or similar,
@@@ -1339,7 -1339,7 +1339,7 @@@
  	if (!(*key))
  	    continue;
  
- 	extfs_prefixes [extfs_no++] = g_strdup (key);
+ 	extfs_prefixes [extfs_no++] = mhl_str_dup (key);
      }
      fclose(cfg);
      g_free (mc_extfsini);
diff --combined vfs/fish.c
index d01e6cd,e94cb5a..1d53230
--- a/vfs/fish.c
+++ b/vfs/fish.c
@@@ -36,8 -36,11 +36,11 @@@
  /* Define this if your ssh can take -I option */
  
  #include <config.h>
+ 
  #include <errno.h>
  
+ #include <mhl/string.h>
+ 
  #include "../src/global.h"
  #include "../src/tty.h"		/* enable/disable interrupt key */
  #include "../src/wtools.h"	/* message() */
@@@ -144,7 -147,7 +147,7 @@@ fish_command (struct vfs_class *me, str
      enable_interrupt_key ();
  
      status = write (SUP.sockw, str, strlen (str));
 -    g_free (str);
 +    mhl_mem_free (str);
  
      disable_interrupt_key ();
      if (status < 0)
@@@ -168,10 -171,10 +171,10 @@@ fish_free_archive (struct vfs_class *me
  	close (SUP.sockr);
  	SUP.sockw = SUP.sockr = -1;
      }
 -    g_free (SUP.host);
 -    g_free (SUP.user);
 -    g_free (SUP.cwdir);
 -    g_free (SUP.password);
 +    mhl_mem_free (SUP.host);
 +    mhl_mem_free (SUP.user);
 +    mhl_mem_free (SUP.cwdir);
 +    mhl_mem_free (SUP.password);
  }
  
  static void
@@@ -216,22 -219,13 +219,22 @@@ static in
  fish_open_archive_int (struct vfs_class *me, struct vfs_s_super *super)
  {
      {
 -	const char *argv[10];
 +	char gbuf[10];
 +	const char *argv[10];	/* All of 10 is used now */
  	const char *xsh = (SUP.flags == FISH_FLAG_RSH ? "rsh" : "ssh");
  	int i = 0;
  
  	argv[i++] = xsh;
  	if (SUP.flags == FISH_FLAG_COMPRESSED)
  	    argv[i++] = "-C";
 +
 +	if (SUP.flags > FISH_FLAG_RSH)
 +	{
 +	    argv[i++] = "-p";
 +	    snprintf (gbuf, sizeof (gbuf), "%d", SUP.flags);
 +	    argv[i++] = gbuf;
 +	}
 +
  	argv[i++] = "-l";
  	argv[i++] = SUP.user;
  	argv[i++] = SUP.host;
@@@ -260,7 -254,7 +263,7 @@@
  		p = g_strconcat (_(" fish: Password required for "),
  				 SUP.user, " ", (char *) NULL);
  		op = vfs_get_password (p);
 -		g_free (p);
 +		mhl_mem_free (p);
  		if (op == NULL)
  		    ERRNOR (EPERM, -1);
  		SUP.password = op;
@@@ -303,7 -297,7 +306,7 @@@
      super->name =
  	g_strconcat ("/#sh:", SUP.user, "@", SUP.host, "/", (char *) NULL);
  #endif
-     super->name = g_strdup (PATH_SEP_STR);
+     super->name = mhl_str_dup (PATH_SEP_STR);
  
      super->root =
  	vfs_s_new_inode (me, super,
@@@ -323,13 -317,13 +326,13 @@@ fish_open_archive (struct vfs_class *me
      p = vfs_split_url (strchr (op, ':') + 1, &host, &user, &flags,
  		       &password, 0, URL_NOSLASH);
  
 -    g_free (p);
 +    mhl_mem_free (p);
  
      SUP.host = host;
      SUP.user = user;
      SUP.flags = flags;
      if (!strncmp (op, "rsh:", 4))
 -	SUP.flags |= FISH_FLAG_RSH;
 +	SUP.flags = FISH_FLAG_RSH;
      SUP.cwdir = NULL;
      if (password)
  	SUP.password = password;
@@@ -350,12 -344,12 +353,12 @@@ fish_archive_same (struct vfs_class *me
      op = vfs_split_url (strchr (op, ':') + 1, &host, &user, &flags, 0, 0,
  			URL_NOSLASH);
  
 -    g_free (op);
 +    mhl_mem_free (op);
  
      flags = ((strcmp (host, SUP.host) == 0)
  	     && (strcmp (user, SUP.user) == 0) && (flags == SUP.flags));
 -    g_free (host);
 -    g_free (user);
 +    mhl_mem_free (host);
 +    mhl_mem_free (user);
  
      return flags;
  }
@@@ -367,7 -361,7 +370,7 @@@ fish_dir_load(struct vfs_class *me, str
      char buffer[8192];
      struct vfs_s_entry *ent = NULL;
      FILE *logfile;
 -    char *quoted_path;
 +    SHELL_ESCAPED_STR quoted_path;
      int reply_code;
  
  #if 0
@@@ -462,8 -456,8 +465,8 @@@
  	"else\n"
  		  "echo '### 500'\n"
  	"fi\n",
 -	    quoted_path, quoted_path, quoted_path, quoted_path, quoted_path, quoted_path);
 -    mhl_mem_free (quoted_path);
 +	    quoted_path.s, quoted_path.s, quoted_path.s, quoted_path.s, quoted_path.s, quoted_path.s);
 +    mhl_mem_free (quoted_path.s);
      ent = vfs_s_generate_entry(me, NULL, dir, 0);
      while (1) {
  	int res = vfs_s_get_line_interruptible (me, buffer, sizeof (buffer), SUP.sockr); 
@@@ -594,8 -588,8 +597,8 @@@
      vfs_s_free_entry (me, ent);
      reply_code = fish_decode_reply(buffer + 4, 0);
      if (reply_code == COMPLETE) {
 -	g_free (SUP.cwdir);
 +	mhl_mem_free (SUP.cwdir);
- 	SUP.cwdir = g_strdup (remote_path);
+ 	SUP.cwdir = mhl_str_dup (remote_path);
  	print_vfs_message (_("%s: done."), me->name);
  	return 0;
      } else if (reply_code == ERROR) {
@@@ -618,7 -612,7 +621,7 @@@ fish_file_store(struct vfs_class *me, s
      struct stat s;
      int was_error = 0;
      int h;
 -    char *quoted_name;
 +    SHELL_ESCAPED_STR quoted_name;
  
      h = open (localname, O_RDONLY);
  
@@@ -659,7 -653,7 +662,7 @@@
       */
  
      quoted_name = mhl_shell_escape_dup(name);
 -    print_vfs_message(_("fish: store %s: sending command..."), quoted_name );
 +    print_vfs_message(_("fish: store %s: sending command..."), quoted_name.s );
  
      /* FIXME: File size is limited to ULONG_MAX */
      if (!fh->u.fish.append)
@@@ -683,8 -677,8 +686,8 @@@
  			"    rest=`expr $rest - $n`\n"
  			"done\n"
  		 "}; echo '### 200'\n",
 -		 (unsigned long) s.st_size, quoted_name,
 -		 quoted_name, (unsigned long) s.st_size,
 +		 (unsigned long) s.st_size, quoted_name.s,
 +		 quoted_name.s, (unsigned long) s.st_size,
  		 (unsigned long) s.st_size);
      else
  	n = fish_command (me, super, WAIT_REPLY,
@@@ -700,8 -694,8 +703,8 @@@
  			"    rest=`expr $rest - $n`\n"
  			"done\n"
  		 "}; echo '### 200'\n",
 -		 (unsigned long) s.st_size, quoted_name,
 -		 quoted_name, (unsigned long) s.st_size);
 +		 (unsigned long) s.st_size, quoted_name.s,
 +		 quoted_name.s, (unsigned long) s.st_size);
  
      if (n != PRELIM) {
  	close (h);
@@@ -735,14 -729,14 +738,14 @@@
  			  (unsigned long) s.st_size);
      }
      close(h);
 -    mhl_mem_free(quoted_name);
 +    mhl_mem_free(quoted_name.s);
      if ((fish_get_reply (me, SUP.sockr, NULL, 0) != COMPLETE) || was_error)
          ERRNOR (E_REMOTE, -1);
      return 0;
  error_return:
      close(h);
      fish_get_reply(me, SUP.sockr, NULL, 0);
 -    mhl_mem_free(quoted_name);
 +    mhl_mem_free(quoted_name.s);
      return -1;
  }
  
@@@ -750,7 -744,7 +753,7 @@@ static in
  fish_linear_start (struct vfs_class *me, struct vfs_s_fh *fh, off_t offset)
  {
      char *name;
 -    char *quoted_name;
 +    SHELL_ESCAPED_STR quoted_name;
      if (offset)
          ERRNOR (E_NOTSUPP, 0);
      name = vfs_s_fullpath (me, fh->ino);
@@@ -779,8 -773,8 +782,8 @@@
  		"else\n"
  		"echo '### 500'\n"
  		"fi\n",
 -		quoted_name, quoted_name, quoted_name, quoted_name );
 -    g_free (quoted_name);
 +		quoted_name.s, quoted_name.s, quoted_name.s, quoted_name.s );
 +    mhl_mem_free (quoted_name.s);
      if (offset != PRELIM) ERRNOR (E_REMOTE, 0);
      fh->linear = LS_LINEAR_OPEN;
      fh->u.fish.got = 0;
@@@ -889,29 -883,28 +892,29 @@@ fish_send_command(struct vfs_class *me
  #define PREFIX \
      char buf[BUF_LARGE]; \
      const char *crpath; \
 -    char *rpath, *mpath = mhl_str_dup (path); \
 +    char *mpath = mhl_str_dup (path); \
 +    SHELL_ESCAPED_STR rpath; \
      struct vfs_s_super *super; \
      if (!(crpath = vfs_s_get_path_mangle (me, mpath, &super, 0))) { \
 -	g_free (mpath); \
 +	mhl_mem_free (mpath); \
  	return -1; \
      } \
      rpath = mhl_shell_escape_dup(crpath); \
 -    g_free (mpath);
 +    mhl_mem_free (mpath);
  
  #define POSTFIX(flags) \
 -    g_free (rpath); \
 +    mhl_mem_free (rpath.s); \
      return fish_send_command(me, super, buf, flags);
  
  static int
  fish_chmod (struct vfs_class *me, const char *path, int mode)
  {
      PREFIX
 -    g_snprintf(buf, sizeof(buf), "#CHMOD %4.4o /%s\n"
 +    snprintf(buf, sizeof(buf), "#CHMOD %4.4o /%s\n"
  				 "chmod %4.4o /%s 2>/dev/null\n"
  				 "echo '### 000'\n", 
 -	    mode & 07777, rpath,
 -	    mode & 07777, rpath);
 +	    mode & 07777, rpath.s,
 +	    mode & 07777, rpath.s);
      POSTFIX(OPT_FLUSH);
  }
  
@@@ -920,24 -913,24 +923,23 @@@ static int fish_##name (struct vfs_clas
  { \
      char buf[BUF_LARGE]; \
      const char *crpath1, *crpath2; \
 -    char *rpath1, *rpath2, *mpath1, *mpath2; \
 +    char *mpath1, *mpath2; \
      struct vfs_s_super *super1, *super2; \
-     if (!(crpath1 = vfs_s_get_path_mangle (me, mpath1 = g_strdup(path1), &super1, 0))) { \
+     if (!(crpath1 = vfs_s_get_path_mangle (me, mpath1 = mhl_str_dup(path1), &super1, 0))) { \
 -	g_free (mpath1); \
 +	mhl_mem_free (mpath1); \
  	return -1; \
      } \
-     if (!(crpath2 = vfs_s_get_path_mangle (me, mpath2 = g_strdup(path2), &super2, 0))) { \
+     if (!(crpath2 = vfs_s_get_path_mangle (me, mpath2 = mhl_str_dup(path2), &super2, 0))) { \
 -	g_free (mpath1); \
 -	g_free (mpath2); \
 -	return -1; \
 +	mhl_mem_free (mpath1); \
 +	mhl_mem_free (mpath2); \
- 	return -1; \
      } \
 -    rpath1 = mhl_shell_escape_dup (crpath1); \
 -    g_free (mpath1); \
 -    rpath2 = mhl_shell_escape_dup (crpath2); \
 -    g_free (mpath2); \
 -    g_snprintf(buf, sizeof(buf), string "\n", rpath1, rpath2, rpath1, rpath2); \
 -    mhl_mem_free (rpath1); \
 -    mhl_mem_free (rpath2); \
 +    SHELL_ESCAPED_STR rpath1 = mhl_shell_escape_dup (crpath1); \
 +    mhl_mem_free (mpath1); \
 +    SHELL_ESCAPED_STR rpath2 = mhl_shell_escape_dup (crpath2); \
 +    mhl_mem_free (mpath2); \
-     g_snprintf(buf, sizeof(buf), string "\n", rpath1.s, rpath2.s, rpath1.s, rpath2.s); \
++    snprintf(buf, sizeof(buf), string "\n", rpath1.s, rpath2.s, rpath1.s, rpath2.s); \
 +    mhl_mem_free (rpath1.s); \
 +    mhl_mem_free (rpath2.s); \
      return fish_send_command(me, super2, buf, OPT_FLUSH); \
  }
  
@@@ -950,15 -943,15 +952,15 @@@ FISH_OP(link,   "#LINK /%s /%s\n
  
  static int fish_symlink (struct vfs_class *me, const char *setto, const char *path)
  {
 -    char *qsetto;
 +    SHELL_ESCAPED_STR qsetto;
      PREFIX
      qsetto = mhl_shell_escape_dup (setto);
 -    g_snprintf(buf, sizeof(buf),
 +    snprintf(buf, sizeof(buf),
              "#SYMLINK %s /%s\n"
  	    "ln -s %s /%s 2>/dev/null\n"
  	    "echo '### 000'\n",
 -	    qsetto, rpath, qsetto, rpath);
 -    mhl_mem_free (qsetto);
 +	    qsetto.s, rpath.s, qsetto.s, rpath.s);
 +    mhl_mem_free (qsetto.s);
      POSTFIX(OPT_FLUSH);
  }
  
@@@ -979,20 -972,20 +981,20 @@@ fish_chown (struct vfs_class *me, cons
      sgroup = gr->gr_name;
      {
  	PREFIX
 -	g_snprintf (buf, sizeof(buf),
 +	snprintf (buf, sizeof(buf),
      	    "#CHOWN %s /%s\n"
  	    "chown %s /%s 2>/dev/null\n"
  	    "echo '### 000'\n", 
 -	    sowner, rpath,
 -	    sowner, rpath);
 +	    sowner, rpath.s,
 +	    sowner, rpath.s);
  	fish_send_command (me, super, buf, OPT_FLUSH); 
  	/* FIXME: what should we report if chgrp succeeds but chown fails? */
 -	g_snprintf (buf, sizeof(buf),
 +	snprintf (buf, sizeof(buf),
              "#CHGRP /%s \"/%s\"\n"
  	    "chgrp %s \"/%s\" 2>/dev/null\n"
  	    "echo '### 000'\n", 
 -	    sgroup, rpath,
 -	    sgroup, rpath);
 +	    sgroup, rpath.s,
 +	    sgroup, rpath.s);
  	/* fish_send_command(me, super, buf, OPT_FLUSH); */
  	POSTFIX (OPT_FLUSH)
      }
@@@ -1001,11 -994,11 +1003,11 @@@
  static int fish_unlink (struct vfs_class *me, const char *path)
  {
      PREFIX
 -    g_snprintf(buf, sizeof(buf),
 +    snprintf(buf, sizeof(buf),
              "#DELE /%s\n"
  	    "rm -f /%s 2>/dev/null\n"
  	    "echo '### 000'\n",
 -	    rpath, rpath);
 +	    rpath.s, rpath.s);
      POSTFIX(OPT_FLUSH);
  }
  
@@@ -1015,22 -1008,22 +1017,22 @@@ static int fish_mkdir (struct vfs_clas
  
      (void) mode;
  
 -    g_snprintf(buf, sizeof(buf),
 +    snprintf(buf, sizeof(buf),
              "#MKD /%s\n"
  	    "mkdir /%s 2>/dev/null\n"
  	    "echo '### 000'\n",
 -	    rpath, rpath);
 +	    rpath.s, rpath.s);
      POSTFIX(OPT_FLUSH);
  }
  
  static int fish_rmdir (struct vfs_class *me, const char *path)
  {
      PREFIX
 -    g_snprintf(buf, sizeof(buf),
 +    snprintf(buf, sizeof(buf),
              "#RMD /%s\n"
  	    "rmdir /%s 2>/dev/null\n"
  	    "echo '### 000'\n",
 -	    rpath, rpath);
 +	    rpath.s, rpath.s);
      POSTFIX(OPT_FLUSH);
  }
  
@@@ -1066,35 -1059,29 +1068,35 @@@ static voi
  fish_fill_names (struct vfs_class *me, fill_names_f func)
  {
      struct vfs_s_super *super = MEDATA->supers;
 -    const char *flags;
      char *name;
 -    
 -    while (super){
 -	switch (SUP.flags & (FISH_FLAG_RSH | FISH_FLAG_COMPRESSED)) {
 -	case FISH_FLAG_RSH:
 +
 +    char gbuf[10];
 +
 +    while (super)
 +    {
 +	const char *flags = "";
 +	switch (SUP.flags)
 +	{
 +	    case FISH_FLAG_RSH:
  		flags = ":r";
  		break;
 -	case FISH_FLAG_COMPRESSED:
 +	    case FISH_FLAG_COMPRESSED:
  		flags = ":C";
  		break;
 -	case FISH_FLAG_RSH | FISH_FLAG_COMPRESSED:
 -		flags = "";
 -		break;
 -	default:
 -		flags = "";
 +	    default:
 +		if (SUP.flags > FISH_FLAG_RSH)
 +		{
 +		    break;
 +		    snprintf (gbuf, sizeof (gbuf), ":%d", SUP.flags);
 +		    flags = gbuf;
 +		}
  		break;
  	}
  
  	name = g_strconcat ("/#sh:", SUP.user, "@", SUP.host, flags,
  			    "/", SUP.cwdir, (char *) NULL);
  	(*func)(name);
 -	g_free (name);
 +	mhl_mem_free (name);
  	super = super->next;
      }
  }
diff --combined vfs/ftpfs.c
index 852b305,8c48bc7..d221395
--- a/vfs/ftpfs.c
+++ b/vfs/ftpfs.c
@@@ -44,7 -44,7 +44,7 @@@ What to do with this
          int f = !strcmp( remote_path, "/~" );
  	if (f || !strncmp( remote_path, "/~/", 3 )) {
  	    char *s;
 -	    s = concat_dir_and_file( qhome (*bucket), remote_path +3-f );
 +	    s = mhl_str_dir_plus_file( qhome (*bucket), remote_path +3-f );
  	    g_free (remote_path);
  	    remote_path = s;
  	}
@@@ -174,7 -174,7 +174,7 @@@ static char 
  ftpfs_translate_path (struct vfs_class *me, struct vfs_s_super *super, const char *remote_path)
  {
      if (!SUP.remote_is_amiga)
- 	return g_strdup (remote_path);
+ 	return mhl_str_dup (remote_path);
      else {
  	char *ret, *p;
  
@@@ -192,9 -192,9 +192,9 @@@
  	 * invalid.
  	 */
          if (*remote_path == '\0')
- 	    return g_strdup ("."); 
+ 	    return mhl_str_dup ("."); 
  
- 	ret = g_strdup (remote_path);
+ 	ret = mhl_str_dup (remote_path);
  
  	/* replace first occurance of ":/" with ":" */
  	if ((p = strchr (ret, ':')) && *(p + 1) == '/')
@@@ -235,7 -235,7 +235,7 @@@ ftpfs_split_url(char *path, char **host
  	if (use_netrc)
  	    ftpfs_netrc_lookup (*host, user, pass);
  	if (!*user)
- 	    *user = g_strdup ("anonymous");
+ 	    *user = mhl_str_dup ("anonymous");
      }
  
      /* Look up password in netrc for known user */
@@@ -443,13 -443,13 +443,13 @@@ ftpfs_login_server (struct vfs_class *m
      SUP.isbinary = TYPE_UNKNOWN;
  
      if (SUP.password)		/* explicit password */
- 	op = g_strdup (SUP.password);
+ 	op = mhl_str_dup (SUP.password);
      else if (netrcpass)		/* password from netrc */
- 	op = g_strdup (netrcpass);
+ 	op = mhl_str_dup (netrcpass);
      else if (!strcmp (SUP.user, "anonymous") || !strcmp (SUP.user, "ftp")) {
  	if (!ftpfs_anonymous_passwd)	/* default anonymous password */
  	    ftpfs_init_passwd ();
- 	op = g_strdup (ftpfs_anonymous_passwd);
+ 	op = mhl_str_dup (ftpfs_anonymous_passwd);
  	anon = 1;
      } else {			/* ask user */
  	char *p;
@@@ -460,7 -460,7 +460,7 @@@
  	g_free (p);
  	if (op == NULL)
  	    ERRNOR (EPERM, 0);
- 	SUP.password = g_strdup (op);
+ 	SUP.password = mhl_str_dup (op);
      }
  
      if (!anon || MEDATA->logfile)
@@@ -477,7 -477,7 +477,7 @@@
  			 SUP.host[0] == '!' ? SUP.host + 1 : SUP.host,
  			 NULL);
      } else
- 	name = g_strdup (SUP.user);
+ 	name = mhl_str_dup (SUP.user);
  
      if (ftpfs_get_reply
  	(me, SUP.sock, reply_string,
@@@ -557,7 -557,7 +557,7 @@@ ftpfs_load_no_proxy_list (void
      if (mc_file)
  	return;
  
 -    mc_file = concat_dir_and_file (mc_home, "mc.no_proxy");
 +    mc_file = mhl_str_dir_plus_file (mc_home, "mc.no_proxy");
      if (exist_file (mc_file) &&
  	(npf = fopen (mc_file, "r"))) {
  	while (fgets (s, sizeof (s), npf)) {
@@@ -573,7 -573,7 +573,7 @@@
  	    *p = '\0';
  	    
  	    np = g_new (struct no_proxy_entry, 1);
- 	    np->domain = g_strdup (s);
+ 	    np->domain = mhl_str_dup (s);
  	    np->next   = NULL;
  	    if (no_proxy)
  		current->next = np;
@@@ -766,7 -766,7 +766,7 @@@ ftpfs_open_archive_int (struct vfs_clas
      
      SUP.cwdir = ftpfs_get_current_directory (me, super);
      if (!SUP.cwdir)
-         SUP.cwdir = g_strdup (PATH_SEP_STR);
+         SUP.cwdir = mhl_str_dup (PATH_SEP_STR);
      return 0;
  }
  
@@@ -793,7 -793,7 +793,7 @@@ ftpfs_open_archive (struct vfs_class *m
      SUP.strict = ftpfs_use_unix_list_options ? RFC_AUTODETECT : RFC_STRICT;
      SUP.isbinary = TYPE_UNKNOWN;
      SUP.remote_is_amiga = 0;
-     super->name = g_strdup ("/");
+     super->name = mhl_str_dup ("/");
      super->root =
  	vfs_s_new_inode (me, super,
  			 vfs_s_default_stat (me, S_IFDIR | 0755));
@@@ -844,7 -844,7 +844,7 @@@ ftpfs_get_current_directory (struct vfs
  		            *bufq = 0;
  		        }
  			if (*bufp == '/')
- 			    return g_strdup (bufp);
+ 			    return mhl_str_dup (bufp);
  			else {
  			    /* If the remote server is an Amiga a leading slash
  			       might be missing. MC needs it because it is used
@@@ -1232,7 -1232,7 +1232,7 @@@ ftpfs_dir_load (struct vfs_class *me, s
  	    ftpfs_open_data_connection (me, super, "LIST -la", 0, TYPE_ASCII, 0);
      else {
  	/* Trailing "/." is necessary if remote_path is a symlink */
 -	char *path = concat_dir_and_file (remote_path, ".");
 +	char *path = mhl_str_dir_plus_file (remote_path, ".");
  	sock =
  	    ftpfs_open_data_connection (me, super, "LIST -la", path, TYPE_ASCII,
  				  0);
@@@ -1479,7 -1479,7 +1479,7 @@@ static in
  ftpfs_send_command(struct vfs_class *me, const char *filename, const char *cmd, int flags)
  {
      const char *rpath;
-     char *p, *mpath = g_strdup(filename);
+     char *p, *mpath = mhl_str_dup(filename);
      struct vfs_s_super *super;
      int r;
      int flush_directory_cache = (flags & OPT_FLUSH);
@@@ -1521,14 -1521,14 +1521,14 @@@ ftpfs_init_passwd(void
       * - We don't want to let ftp sites to discriminate by the user,
       *   host or country.
       */
-     ftpfs_anonymous_passwd = g_strdup ("anonymous@");
+     ftpfs_anonymous_passwd = mhl_str_dup ("anonymous@");
  }
  
  static int ftpfs_chmod (struct vfs_class *me, const char *path, int mode)
  {
      char buf[BUF_SMALL];
  
 -    g_snprintf(buf, sizeof(buf), "SITE CHMOD %4.4o /%%s", mode & 07777);
 +    snprintf(buf, sizeof(buf), "SITE CHMOD %4.4o /%%s", mode & 07777);
      return ftpfs_send_command(me, path, buf, OPT_FLUSH);
  }
  
@@@ -1583,7 -1583,7 +1583,7 @@@ ftpfs_chdir_internal (struct vfs_class 
  	ftpfs_errno = EIO;
      } else {
  	g_free(SUP.cwdir);
- 	SUP.cwdir = g_strdup (remote_path);
+ 	SUP.cwdir = mhl_str_dup (remote_path);
  	SUP.cwd_deferred = 0;
      }
      return r;
@@@ -1880,15 -1880,15 +1880,15 @@@ static int ftpfs_netrc_lookup (const ch
      for (rupp = rup_cache; rupp != NULL; rupp = rupp->next) {
  	if (!strcmp (host, rupp->host)) {
  	    if (rupp->login)
- 		*login = g_strdup (rupp->login);
+ 		*login = mhl_str_dup (rupp->login);
  	    if (pass && rupp->pass)
- 		*pass = g_strdup (rupp->pass);
+ 		*pass = mhl_str_dup (rupp->pass);
  	    return 0;
  	}
      }
  
      /* Load current .netrc */
 -    netrcname = concat_dir_and_file (home_dir, ".netrc");
 +    netrcname = mhl_str_dir_plus_file (home_dir, ".netrc");
      netrcp = netrc = load_file (netrcname);
      if (netrc == NULL) {
  	g_free (netrcname);
@@@ -1923,7 -1923,7 +1923,7 @@@
  	    }
  
  	    /* We have login name now */
- 	    *login = g_strdup (buffer);
+ 	    *login = mhl_str_dup (buffer);
  	    break;
  
  	case NETRC_PASSWORD:
@@@ -1942,7 -1942,7 +1942,7 @@@
  
  	    /* Remember password.  pass may be NULL, so use tmp_pass */
  	    if (tmp_pass == NULL)
- 		tmp_pass = g_strdup (buffer);
+ 		tmp_pass = mhl_str_dup (buffer);
  	    break;
  
  	case NETRC_ACCOUNT:
@@@ -1970,14 -1970,14 +1970,14 @@@
      g_free (netrcname);
  
      rupp = g_new (struct rupcache, 1);
-     rupp->host = g_strdup (host);
+     rupp->host = mhl_str_dup (host);
      rupp->login = rupp->pass = 0;
  
      if (*login != NULL) {
- 	rupp->login = g_strdup (*login);
+ 	rupp->login = mhl_str_dup (*login);
      }
      if (tmp_pass != NULL)
- 	rupp->pass = g_strdup (tmp_pass);
+ 	rupp->pass = mhl_str_dup (tmp_pass);
      rupp->next = rup_cache;
      rup_cache = rupp;
  
diff --combined vfs/mcfs.c
index 27a0cfb,29c1c6b..dde1b45
--- a/vfs/mcfs.c
+++ b/vfs/mcfs.c
@@@ -49,6 -49,8 +49,8 @@@
  #endif
  #endif
  
+ #include <mhl/string.h>
+ 
  #include "../src/global.h"
  #include "../src/tty.h"		/* enable/disable interrupt key */
  #include "../src/wtools.h"	/* message() */
@@@ -159,7 -161,7 +161,7 @@@ mcfs_login_server (int my_socket, char 
  	    }
  	}
  	if (netrcpass != NULL)
- 	    pass = g_strdup (netrcpass);
+ 	    pass = mhl_str_dup (netrcpass);
  	else
  	    pass = vfs_get_password (_(" MCFS Password required "));
  	if (!pass) {
@@@ -341,8 -343,8 +343,8 @@@ mcfs_open_link (char *host, char *user
  
      bucket = mcfs_get_free_bucket ();
      mcfs_open_connections++;
-     bucket->host = g_strdup (host);
-     bucket->user = g_strdup (user);
+     bucket->host = mhl_str_dup (host);
+     bucket->user = mhl_str_dup (user);
      bucket->home = 0;
      bucket->port = *port;
      bucket->sock = sock;
@@@ -406,7 -408,7 +408,7 @@@ mcfs_get_path (mcfs_connection **mc, co
  	int f = !strcmp (remote_path, "/~");
  	if (f || !strncmp (remote_path, "/~/", 3)) {
  	    char *s;
 -	    s = concat_dir_and_file (mcfs_gethome (*mc),
 +	    s = mhl_str_dir_plus_file (mcfs_gethome (*mc),
  				     remote_path + 3 - f);
  	    g_free (remote_path);
  	    remote_path = s;
@@@ -509,13 -511,13 +511,13 @@@ mcfs_gethome (mcfs_connection *mc
      char *buffer;
  
      if (mc->home)
- 	return g_strdup (mc->home);
+ 	return mhl_str_dup (mc->home);
      else {
  	rpc_send (mc->sock, RPC_INT, MC_GETHOME, RPC_END);
  	if (0 == rpc_get (mc->sock, RPC_STRING, &buffer, RPC_END))
- 	    return g_strdup (PATH_SEP_STR);
+ 	    return mhl_str_dup (PATH_SEP_STR);
  	mc->home = buffer;
- 	return g_strdup (buffer);
+ 	return mhl_str_dup (buffer);
      }
  }
  
@@@ -975,8 -977,8 +977,8 @@@ mcfs_utime (struct vfs_class *me, cons
  	atime = (long) times->actime;
  	mtime = (long) times->modtime;
  
 -	g_snprintf (abuf, sizeof (abuf), "%lx", atime);
 -	g_snprintf (mbuf, sizeof (mbuf), "%lx", mtime);
 +	snprintf (abuf, sizeof (abuf), "%lx", atime);
 +	snprintf (mbuf, sizeof (mbuf), "%lx", mtime);
  
  	rpc_send (mc->sock, RPC_INT, MC_UTIME,
  		  RPC_STRING, file,
diff --combined vfs/sfs.c
index 34fee61,72492e7..a8ae3ba
--- a/vfs/sfs.c
+++ b/vfs/sfs.c
@@@ -76,7 -76,7 +76,7 @@@ sfs_vfmake (struct vfs_class *me, cons
      char *pname;	/* name of parent archive */
      char *pqname;	/* name of parent archive, quoted */
  
-     pname = g_strdup (name);
+     pname = mhl_str_dup (name);
      vfs_split (pname, &inpath, &op);
      if ((w = (*me->which) (me, op)) == -1)
  	vfs_die ("This cannot happen... Hopefully.\n");
@@@ -182,7 -182,7 +182,7 @@@ sfs_redirect (struct vfs_class *me, con
  
      if (!sfs_vfmake (me, name, cache)) {
  	cur = g_new (struct cachedfile, 1);
- 	cur->name = g_strdup (name);
+ 	cur->name = mhl_str_dup (name);
  	cur->cache = cache;
  	cur->next = head;
  	head = cur;
@@@ -316,7 -316,7 +316,7 @@@ static char 
  sfs_getlocalcopy (struct vfs_class *me, const char *path)
  {
      path = sfs_redirect (me, path);
-     return g_strdup (path);
+     return mhl_str_dup (path);
  }
  
  static int
@@@ -338,7 -338,7 +338,7 @@@ static int sfs_init (struct vfs_class *
  
      (void) me;
  
 -    mc_sfsini = concat_dir_and_file (mc_home, "extfs" PATH_SEP_STR "sfs.ini");
 +    mc_sfsini = mhl_str_dir_plus_file (mc_home, "extfs" PATH_SEP_STR "sfs.ini");
      cfg = fopen (mc_sfsini, "r");
  
      if (!cfg){
@@@ -391,8 -391,8 +391,8 @@@
  	if ((semi = strchr (c, '\n')))
  	    *semi = 0;
  
- 	sfs_prefix [sfs_no] = g_strdup (key);
- 	sfs_command [sfs_no] = g_strdup (c);
+ 	sfs_prefix [sfs_no] = mhl_str_dup (key);
+ 	sfs_command [sfs_no] = mhl_str_dup (c);
  	sfs_flags [sfs_no] = flags;
  	sfs_no++;
      }
diff --combined vfs/smbfs.c
index 9eb4a3d,2bd7137..a4e5050
--- a/vfs/smbfs.c
+++ b/vfs/smbfs.c
@@@ -22,10 -22,11 +22,12 @@@
  
  /* Namespace: exports init_smbfs, smbfs_set_debug(), smbfs_set_debugf() */
  #include <config.h>
+ 
  #include <stdio.h>
  #include <sys/types.h>
  
 +#include <mhl/types.h>
+ #include <mhl/string.h>
  
  #undef	USE_NCURSES	/* Don't include *curses.h */
  #include "../src/global.h"
@@@ -51,8 -52,6 +53,8 @@@
  
  #include <string.h>
  
 +#include <mhl/string.h>
 +
  #include "vfs.h"
  #include "vfs-impl.h"
  #include "smbfs.h"
@@@ -72,8 -71,8 +74,8 @@@ extern struct in_addr ipzero
  static mode_t myumask = 0755;
  extern pstring global_myname;
  static int smbfs_open_connections = 0;
 -static gboolean got_user = FALSE;
 -static gboolean got_pass = FALSE;
 +static bool got_user = FALSE;
 +static bool got_pass = FALSE;
  static pstring password;
  static pstring username;
  static struct vfs_class vfs_smbfs_ops;
@@@ -110,7 -109,7 +112,7 @@@ typedef struct 
  static GSList *auth_list;
  
  /* this function allows you to write:
-  * char *s = g_strdup("hello, world");
+  * char *s = mhl_str_dup("hello, world");
   * s = free_after(g_strconcat(s, s, (char *)0), s);
   */
  static inline char *
@@@ -180,12 -179,12 +182,12 @@@ smbfs_auth_add (const char *host, cons
      if (!auth)
          return;
  
-     /* Don't check for NULL, g_strdup already does. */
-     auth->host = g_strdup (host);
-     auth->share = g_strdup (share);
-     auth->domain = g_strdup (domain);
-     auth->user = g_strdup (user);
-     auth->password = g_strdup (password);
+     /* Don't check for NULL, mhl_str_dup already does. */
+     auth->host = mhl_str_dup (host);
+     auth->share = mhl_str_dup (share);
+     auth->domain = mhl_str_dup (domain);
+     auth->user = mhl_str_dup (user);
+     auth->password = mhl_str_dup (password);
      auth_list = g_slist_prepend (auth_list, auth);
  }
  
@@@ -196,8 -195,8 +198,8 @@@ smbfs_auth_remove (const char *host, co
      struct smb_authinfo *auth;
      GSList *list;
  
-     data.host = g_strdup (host);
-     data.share = g_strdup (share);
+     data.host = mhl_str_dup (host);
+     data.share = mhl_str_dup (share);
      list = g_slist_find_custom (auth_list, 
                                  &data, 
                                  smbfs_auth_cmp_host_and_share);
@@@ -226,9 -225,9 +228,9 @@@ smbfs_bucket_set_authinfo (smbfs_connec
          g_free (bucket->domain);
          g_free (bucket->user);
          g_free (bucket->password);
-         bucket->domain = g_strdup (domain);
-         bucket->user = g_strdup (user);
-         bucket->password = g_strdup (pass);
+         bucket->domain = mhl_str_dup (domain);
+         bucket->user = mhl_str_dup (user);
+         bucket->password = mhl_str_dup (pass);
          smbfs_auth_remove (bucket->host, bucket->service);
          smbfs_auth_add (bucket->host, bucket->service,
                    domain, user, pass);
@@@ -242,16 -241,16 +244,16 @@@
          list = g_slist_find_custom (auth_list, &data, smbfs_auth_cmp_host);
      if (list) {
          auth = list->data;
-         bucket->domain = g_strdup (auth->domain);
-         bucket->user = g_strdup (auth->user);
-         bucket->password = g_strdup (auth->password);
+         bucket->domain = mhl_str_dup (auth->domain);
+         bucket->user = mhl_str_dup (auth->user);
+         bucket->password = mhl_str_dup (auth->password);
          return 1;
      }
  
      if (got_pass) {
-         bucket->domain = g_strdup (lp_workgroup ());
-         bucket->user = g_strdup (got_user ? username : user);
-         bucket->password = g_strdup (password);
+         bucket->domain = mhl_str_dup (lp_workgroup ());
+         bucket->user = mhl_str_dup (got_user ? username : user);
+         bucket->password = mhl_str_dup (password);
          return 1;
      }
  
@@@ -263,9 -262,9 +265,9 @@@
          g_free (bucket->domain);
          g_free (bucket->user);
          g_free (bucket->password);
-         bucket->domain = g_strdup (auth->domain);
-         bucket->user = g_strdup (auth->user);
-         bucket->password = g_strdup (auth->password);
+         bucket->domain = mhl_str_dup (auth->domain);
+         bucket->user = mhl_str_dup (auth->user);
+         bucket->password = mhl_str_dup (auth->password);
          smbfs_auth_remove (bucket->host, bucket->service);
          auth_list = g_slist_prepend (auth_list, auth);
          return 1;
@@@ -437,7 -436,7 +439,7 @@@ typedef struct dir_entry 
  } dir_entry;
  
  typedef struct {
 -    gboolean server_list;
 +    bool server_list;
      char *dirname;
      char *path;			/* the dir originally passed to smbfs_opendir */
      smbfs_connection *conn;
@@@ -451,7 -450,7 +453,7 @@@ static opendir_inf
  	*current_share_info,
  	*current_server_info;
  
 -static gboolean first_direntry;
 +static bool first_direntry;
  
  static dir_entry *
  smbfs_new_dir_entry (const char *name)
@@@ -459,7 -458,7 +461,7 @@@
      static int inode_counter;
      dir_entry *new_entry;
      new_entry = g_new0 (dir_entry, 1);
-     new_entry->text = dos_to_unix (g_strdup (name), 1);
+     new_entry->text = dos_to_unix (mhl_str_dup (name), 1);
  
      if (first_direntry) {
  	current_info->entries = new_entry;
@@@ -550,7 -549,7 +552,7 @@@ smbfs_loaddir_helper (file_info * finfo
  
  /* takes "/foo/bar/file" and gives malloced "\\foo\\bar\\file" */
  static char *
 -smbfs_convert_path (const char *remote_file, gboolean trailing_asterik)
 +smbfs_convert_path (const char *remote_file, bool trailing_asterik)
  {
      const char *p, *my_remote;
      char *result;
@@@ -601,9 -600,9 +603,9 @@@ smbfs_reconnect(smbfs_connection *conn
  	DEBUG(3, ("RECONNECT\n"));
  
  	if (*(conn->host) == 0)
- 		host = g_strdup(conn->cli->desthost);		/* server browsing */
+ 		host = mhl_str_dup(conn->cli->desthost);		/* server browsing */
  	else
- 		host = g_strdup(conn->host);
+ 		host = mhl_str_dup(conn->host);
  
  	cli_shutdown(conn->cli);
  
@@@ -763,7 -762,7 +765,7 @@@ smbfs_loaddir (opendir_info *smbfs_info
      /* do regular directory listing */
      if (strncmp (smbfs_info->conn->service, info_dirname + 1, servlen) == 0) {
  	/* strip share name from dir */
- 	my_dirname = g_strdup (info_dirname + servlen);
+ 	my_dirname = mhl_str_dup (info_dirname + servlen);
  	*my_dirname = '/';
  	my_dirname = free_after(smbfs_convert_path (my_dirname, TRUE), my_dirname);
      } else
@@@ -1032,7 -1031,7 +1034,7 @@@ smbfs_get_master_browser(char **host
  		if (!count)
  			return 0;
  		/* just return first master browser */
- 		*host = g_strdup(inet_ntoa(ip_list[0]));
+ 		*host = mhl_str_dup(inet_ntoa(ip_list[0]));
  		return 1;
  	}
  	return 0;
@@@ -1146,16 -1145,16 +1148,16 @@@ smbfs_open_link (char *host, char *path
      }
      current_bucket = bucket;
  
-     bucket->user = g_strdup (user);
-     bucket->service = g_strdup (service);
+     bucket->user = mhl_str_dup (user);
+     bucket->service = mhl_str_dup (service);
  
      if (!(*host)) {		/* if blank host name, browse for servers */
  	if (!smbfs_get_master_browser (&host))	/* set host to ip of master browser */
  	    return 0;		/* could not find master browser? */
  	g_free (host);
- 	bucket->host = g_strdup ("");	/* blank host means master browser */
+ 	bucket->host = mhl_str_dup ("");	/* blank host means master browser */
      } else
- 	bucket->host = g_strdup (host);
+ 	bucket->host = mhl_str_dup (host);
  
      if (!smbfs_bucket_set_authinfo (bucket, 0,	/* domain currently not used */
  			      user, this_pass, 1))
@@@ -1215,7 -1214,7 +1217,7 @@@ smbfs_get_path (smbfs_connection ** sc
  	int f = !strcmp (remote_path, "/~");
  	if (f || !strncmp (remote_path, "/~/", 3)) {
  	    char *s;
 -	    s = concat_dir_and_file ((*sc)->home, remote_path + 3 - f);
 +	    s = mhl_str_dir_plus_file ((*sc)->home, remote_path + 3 - f);
  	    g_free (remote_path);
  	    return s;
  	}
@@@ -1252,7 -1251,7 +1254,7 @@@ smbfs_opendir (struct vfs_class *me, co
      /* FIXME: where freed? */
      smbfs_info = g_new (opendir_info, 1);
  	smbfs_info->server_list = FALSE;
-     smbfs_info->path = g_strdup(dirname);		/* keep original */
+     smbfs_info->path = mhl_str_dup(dirname);		/* keep original */
  	smbfs_info->dirname = remote_dir;
      smbfs_info->conn = sc;
      smbfs_info->entries = 0;
@@@ -1360,7 -1359,7 +1362,7 @@@ smbfs_get_remote_stat (smbfs_connectio
  #if 0	/* single_entry is never free()d now.  And only my_stat is used */
      single_entry = g_new (dir_entry, 1);
  
-     single_entry->text = dos_to_unix (g_strdup (finfo->name), 1);
+     single_entry->text = dos_to_unix (mhl_str_dup (finfo->name), 1);
  
      single_entry->next = 0;
  #endif
@@@ -1428,7 -1427,7 +1430,7 @@@ smbfs_get_stat_info (smbfs_connection 
      {
  	char *mdp;
  	char *mydir;
- 	mdp = mydir = g_strdup (current_info->dirname);
+ 	mdp = mydir = mhl_str_dup (current_info->dirname);
  	if ((p = strrchr (mydir, '/')))
  	    *p = 0;		/* advance util last '/' */
  	if ((p = strrchr (mydir, '/')))
@@@ -1510,7 -1509,7 +1512,7 @@@ smbfs_loaddir_by_name (struct vfs_clas
  	void *info;
  	char *mypath, *p;
  
- 	mypath = g_strdup(path);
+ 	mypath = mhl_str_dup(path);
  	p = strrchr(mypath, '/');
  
  	if (p > mypath)
diff --combined vfs/undelfs.c
index 496c800,1af5cbb..00afcaf
--- a/vfs/undelfs.c
+++ b/vfs/undelfs.c
@@@ -35,8 -35,8 +35,8 @@@
   */
   
  #include <config.h>
- #include <errno.h>
  
+ #include <errno.h>
  #include <stdio.h>
  #include <stdlib.h>
  
@@@ -51,6 -51,8 +51,8 @@@
  #include <ext2fs/ext2fs.h>
  #include <ctype.h>
  
+ #include <mhl/string.h>
+ 
  #include "../src/global.h"
  #include "../src/tty.h"		/* enable/disable interrupt key */
  #include "../src/wtools.h"	/* message() */
@@@ -140,7 -142,7 +142,7 @@@ undelfs_get_path (const char *dirname, 
  	if (*p == '/'){
  	    char *tmp;
  
- 	    *file = g_strdup (p+1);
+ 	    *file = mhl_str_dup (p+1);
  	    tmp = g_strndup (dirname, p - dirname);
  	    *fsname = g_strconcat ("/dev/", tmp, (char *) NULL);
  	    g_free (tmp);
@@@ -148,7 -150,7 +150,7 @@@
  	}
  	p--;
      }
-     *file = g_strdup ("");
+     *file = mhl_str_dup ("");
      *fsname = g_strconcat ("/dev/", dirname, (char *) NULL);
      return;
  }
@@@ -367,7 -369,7 +369,7 @@@ undelfs_readdir(void *vfs_info
      if (readdir_ptr < 0)
  	strcpy (dirent_dest, readdir_ptr == -2 ? "." : "..");
      else
 -	g_snprintf(dirent_dest, MC_MAXPATHLEN, "%ld:%d",
 +	snprintf(dirent_dest, MC_MAXPATHLEN, "%ld:%d",
  		   (long) delarray[readdir_ptr].ino,
  		   delarray[readdir_ptr].num_blocks);
      readdir_ptr++;
diff --combined vfs/utilvfs.c
index 384f5a4,c1f4e1d..944d6e1
--- a/vfs/utilvfs.c
+++ b/vfs/utilvfs.c
@@@ -19,9 -19,10 +19,11 @@@
     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
  
  #include <config.h>
+ 
  #include <ctype.h>
  
 +#include <mhl/types.h>
+ #include <mhl/string.h>
  
  #include "../src/global.h"
  #include "../src/tty.h"		/* enable/disable interrupt key */
@@@ -57,7 -58,7 +59,7 @@@ vfs_split_url (const char *path, char *
      struct passwd *passwd_info;
      char *dir, *colon, *inner_colon, *at, *rest;
      char *retval;
-     char * const pcopy = g_strdup (path);
+     char * const pcopy = mhl_str_dup (path);
      const char *pend = pcopy + strlen (pcopy);
  
      if (pass)
@@@ -72,10 -73,10 +74,10 @@@
  	while (*dir != PATH_SEP && *dir)
  	    dir++;
  	if (*dir) {
- 	    retval = g_strdup (dir);
+ 	    retval = mhl_str_dup (dir);
  	    *dir = 0;
  	} else
- 	    retval = g_strdup (PATH_SEP_STR);
+ 	    retval = mhl_str_dup (PATH_SEP_STR);
      }
  
      /* search for any possible user */
@@@ -89,10 -90,10 +91,10 @@@
  	    *inner_colon = 0;
  	    inner_colon++;
  	    if (pass)
- 		*pass = g_strdup (inner_colon);
+ 		*pass = mhl_str_dup (inner_colon);
  	}
  	if (*pcopy != 0)
- 	    *user = g_strdup (pcopy);
+ 	    *user = mhl_str_dup (pcopy);
  
  	if (pend == at + 1)
  	    rest = at;
@@@ -104,10 -105,10 +106,10 @@@
      if (!*user && !(flags & URL_ALLOW_ANON)) {
  	passwd_info = getpwuid (geteuid ());
  	if (passwd_info && passwd_info->pw_name)
- 	    *user = g_strdup (passwd_info->pw_name);
+ 	    *user = mhl_str_dup (passwd_info->pw_name);
  	else {
  	    /* This is very unlikely to happen */
- 	    *user = g_strdup ("anonymous");
+ 	    *user = mhl_str_dup ("anonymous");
  	}
  	endpwent ();
      }
@@@ -133,7 -134,7 +135,7 @@@
  	}
      }
      if (host)
- 	*host = g_strdup (rest);
+ 	*host = mhl_str_dup (rest);
  
      g_free (pcopy);
      return retval;
@@@ -411,7 -412,7 +413,7 @@@ is_year (char *str, struct tm *tim
      return 1;
  }
  
 -gboolean
 +bool
  vfs_parse_filetype (const char *s, size_t *ret_skipped, mode_t *ret_type)
  {
      mode_t type;
@@@ -448,7 -449,7 +450,7 @@@
      return TRUE;
  }
  
 -gboolean
 +bool
  vfs_parse_fileperms (const char *s, size_t *ret_skipped, mode_t *ret_perms)
  {
      const char *p;
@@@ -518,7 -519,7 +520,7 @@@
      return TRUE;
  }
  
 -gboolean
 +bool
  vfs_parse_filemode (const char *s, size_t *ret_skipped,
  		    mode_t *ret_mode)
  {
@@@ -541,7 -542,7 +543,7 @@@
      return TRUE;
  }
  
 -gboolean
 +bool
  vfs_parse_raw_filemode (const char *s, size_t *ret_skipped,
  		    mode_t *ret_mode)
  {
@@@ -745,7 -746,7 +747,7 @@@ vfs_parse_ls_lga (const char *p, struc
  	s->st_mode |= perms;
      }
  
-     p_copy = g_strdup (p);
+     p_copy = mhl_str_dup (p);
      num_cols = vfs_split_text (p_copy);
  
      s->st_nlink = atol (columns[0]);
@@@ -844,7 -845,7 +846,7 @@@
  			   column_ptr[idx2] - column_ptr[idx] - 1);
  	}
  	if (linkname) {
- 	    t = g_strdup (p + column_ptr[idx2 + 1]);
+ 	    t = mhl_str_dup (p + column_ptr[idx2 + 1]);
  	    *linkname = t;
  	}
      } else {
@@@ -853,10 -854,10 +855,10 @@@
  	 */
  	if (filename) {
  	    /*
- 	     * filename = g_strdup (columns [idx++]);
+ 	     * filename = mhl_str_dup (columns [idx++]);
  	     */
  
- 	    t = g_strdup (p + column_ptr[idx]);
+ 	    t = mhl_str_dup (p + column_ptr[idx]);
  	    *filename = t;
  	}
  	if (linkname)
diff --combined vfs/vfs.c
index f13d217,1c6bb56..dba0619
--- a/vfs/vfs.c
+++ b/vfs/vfs.c
@@@ -21,7 -21,7 +21,7 @@@
     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
  
  /* Warning: funtions like extfs_lstat() have right to destroy any
-  * strings you pass to them. This is acutally ok as you g_strdup what
+  * strings you pass to them. This is acutally ok as you mhl_str_dup what
   * you are passing to them, anyway; still, beware.  */
  
  /* Namespace: exports *many* functions with vfs_ prefix; exports
@@@ -188,7 -188,7 +188,7 @@@ vfs_strip_suffix_from_filename (const c
      if (!filename)
  	vfs_die ("vfs_strip_suffix_from_path got NULL: impossible");
  
-     p = g_strdup (filename);
+     p = mhl_str_dup (filename);
      if (!(semi = strrchr (p, '#')))
  	return p;
  
@@@ -300,7 -300,7 +300,7 @@@ struct vfs_class 
  vfs_get_class (const char *pathname)
  {
      struct vfs_class *vfs;
-     char *path = g_strdup (pathname);
+     char *path = mhl_str_dup (pathname);
  
      vfs = _vfs_get_class (path);
      g_free (path);
@@@ -566,7 -566,7 +566,7 @@@ int mc_fstat (int handle, struct stat *
  
  /*
   * Return current directory.  If it's local, reread the current directory
-  * from the OS.  You must g_strdup() whatever this function returns.
+  * from the OS.  You must mhl_str_dup() whatever this function returns.
   */
  static const char *
  _vfs_get_cwd (void)
@@@ -596,7 -596,7 +596,7 @@@
  static void
  vfs_setup_wd (void)
  {
-     current_dir = g_strdup (PATH_SEP_STR);
+     current_dir = mhl_str_dup (PATH_SEP_STR);
      _vfs_get_cwd ();
  
      if (strlen (current_dir) > MC_MAXPATHLEN - 2)
@@@ -658,7 -658,7 +658,7 @@@ vfs_canon (const char *path
      if (*path != PATH_SEP){ 
      	char *local, *result;
  
 -	local = concat_dir_and_file (current_dir, path);
 +	local = mhl_str_dir_plus_file (current_dir, path);
  
  	result = vfs_canon (local);
  	g_free (local);
@@@ -670,7 -670,7 +670,7 @@@
       * /p1/p2#op/.././././p3#op/p4. Good luck.
       */
      {
- 	char *result = g_strdup (path);
+ 	char *result = mhl_str_dup (path);
  	canonicalize_pathname (result);
          return result;
      }
@@@ -931,7 -931,7 +931,7 @@@ vfs_fill_names (fill_names_f func
  
  /*
   * Returns vfs path corresponding to given url. If passed string is
-  * not recognized as url, g_strdup(url) is returned.
+  * not recognized as url, mhl_str_dup(url) is returned.
   */
  
  static const struct {
@@@ -955,7 -955,7 +955,7 @@@ vfs_translate_url (const char *url
         if (strncmp (url, url_table[i].name, url_table[i].name_len) == 0)
             return g_strconcat (url_table[i].substitute, url + url_table[i].name_len, (char*) NULL);
  
-     return g_strdup (url);
+     return mhl_str_dup (url);
  }
  
  int vfs_file_is_local (const char *filename)

-- 
Midnight Commander Development


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]