diff --git a/dict/src/conf.h b/dict/src/conf.h
index 953be86..fdd37b6 100644
--- a/dict/src/conf.h
+++ b/dict/src/conf.h
@@ -290,7 +290,7 @@ private:
 };
 
 
-extern std::unique_ptr<AppConf> conf;//global exemplar of AppConf class
+extern std::unique_ptr<AppConf> conf; //global exemplar of AppConf class
 extern std::unique_ptr<AppDirs> conf_dirs;
 
 #endif
diff --git a/dict/src/lib/plugin.h b/dict/src/lib/plugin.h
index 5b75b9b..a8199bd 100644
--- a/dict/src/lib/plugin.h
+++ b/dict/src/lib/plugin.h
@@ -53,6 +53,10 @@ struct StarDictPluginSystemService {
 	terminal2pango_func_t terminal2pango;
 	typedef void(*terminal2pango_2_func_t)(const char *t, std::string &pango);
 	terminal2pango_func_t terminal2pango_2;
+	typedef const std::list<std::string>&(*conf_get_strlist_at_func_t)(const char *path);
+	conf_get_strlist_at_func_t conf_get_strlist_at;
+	typedef void(*conf_set_strlist_at_func_t)(const char *path, std::list<std::string> &Command_List);
+	conf_set_strlist_at_func_t conf_set_strlist_at;
 	typedef char *(*build_dictdata_func_t)(char type, const char *definition);
 	build_dictdata_func_t build_dictdata;
 	typedef void (*netdict_save_cache_resp_func_t)(const char *dict, const char *key, NetDictResponse *resp);
diff --git a/dict/src/lib/pluginmanager.h b/dict/src/lib/pluginmanager.h
index b25f7cc..e06fcf5 100644
--- a/dict/src/lib/pluginmanager.h
+++ b/dict/src/lib/pluginmanager.h
@@ -57,6 +57,7 @@ public:
 	StarDictVirtualDictPlugin(StarDictPluginBaseObject *baseobj, StarDictVirtualDictPlugInObject *virtualdict_plugin_obj);
 	~StarDictVirtualDictPlugin();
 	void lookup(const char *word, char ***pppWord, char ****ppppWordData);
+	void multi_lookup(const char *word, char **dict_name, char ****pppWord, char *****ppppWordData);
 	const char *dict_name();
 	const char *dict_id();
 private:
diff --git a/dict/src/lib/virtualdictplugin.cpp b/dict/src/lib/virtualdictplugin.cpp
index 9b448b2..ba5f172 100644
--- a/dict/src/lib/virtualdictplugin.cpp
+++ b/dict/src/lib/virtualdictplugin.cpp
@@ -23,6 +23,7 @@
 StarDictVirtualDictPlugInObject::StarDictVirtualDictPlugInObject()
 :
 lookup_func(NULL),
+multi_lookup_func(NULL),
 dict_name(NULL)
 {
 }
diff --git a/dict/src/lib/virtualdictplugin.h b/dict/src/lib/virtualdictplugin.h
index 4faa799..a596426 100644
--- a/dict/src/lib/virtualdictplugin.h
+++ b/dict/src/lib/virtualdictplugin.h
@@ -25,6 +25,8 @@ struct StarDictVirtualDictPlugInObject{
 
 	typedef void (*lookup_func_t)(const char *text, char ***pppWord, char ****ppppWordData);
 	lookup_func_t lookup_func;
+	typedef void (*multi_lookup_func_t)(const char *text, char **dict_name, char ****pppWord, char *****ppppWordData);
+	multi_lookup_func_t multi_lookup_func;
 	const char *dict_name;
 };
 
diff --git a/dict/src/stardict.cpp b/dict/src/stardict.cpp
index 1c62d56..99b0d6e 100644
--- a/dict/src/stardict.cpp
+++ b/dict/src/stardict.cpp
@@ -249,6 +249,17 @@ void AppCore::ShowPangoTips(const char *word, const char *text)
 	gpAppFrame->oFloatWin.ShowPangoTips(word, text);
 }
 
+static const std::list<std::string> &common_conf_get_strlist_at(const char *path)
+{
+	const std::list<std::string> &strlist = conf->get_strlist_at(path);
+	return strlist;
+}
+
+static void common_conf_set_strlist_at(const char *path, std::list<std::string> &Command_List)
+{
+	conf->set_strlist_at(path, Command_List);
+}
+
 void AppCore::Create(const gchar *queryword)
 {
 	if (conf->get_bool_at("dictionary/use_custom_font")) {
@@ -297,6 +308,8 @@ void AppCore::Create(const gchar *queryword)
 	oStarDictPluginSystemService.encode_uri_string = common_encode_uri_string;
 	oStarDictPluginSystemService.terminal2pango = common_terminal2pango;
 	oStarDictPluginSystemService.terminal2pango_2 = common_terminal2pango_2;
+	oStarDictPluginSystemService.conf_get_strlist_at = common_conf_get_strlist_at;
+	oStarDictPluginSystemService.conf_set_strlist_at = common_conf_set_strlist_at;
 	oStarDictPluginSystemService.build_dictdata = common_build_dictdata;
 	oStarDictPluginSystemService.netdict_save_cache_resp = netdict_save_cache_resp;
 	oStarDictPluginSystemService.show_netdict_resp = show_netdict_resp;
diff --git a/dict/stardict-plugins/stardict-multi-cmd-plugin/stardict_multi_cmd.cpp b/dict/stardict-plugins/stardict-multi-cmd-plugin/stardict_multi_cmd.cpp
index 5433c09..c660577 100644
--- a/dict/stardict-plugins/stardict-multi-cmd-plugin/stardict_multi_cmd.cpp
+++ b/dict/stardict-plugins/stardict-multi-cmd-plugin/stardict_multi_cmd.cpp
@@ -22,6 +22,8 @@
 #include <gtk/gtk.h>
 #include <stdlib.h>
 #include <cstring>
+#include <memory>
+#include <list>
 #include <string>
 
 static const StarDictPluginSystemInfo *plugin_info = NULL;
@@ -29,50 +31,65 @@ static const StarDictPluginSystemService *plugin_service;
 static IAppDirs* gpAppDirs = NULL;
 
 
-static void lookup(const char *text, char ***pppWord, char ****ppppWordData)
+static std::list<std::string> Command_List;
+
+static void multi_lookup(const char *text, char **dict_name, char ****pppWord, char *****ppppWordData)
 {
-	std::string definition;
-	bool found = true;
-	FILE *pf = popen("cal", "r");
-	if (!pf) {
-		found = false;
-	} else {
-		char buffer[2048];
-		size_t len;
-		while (true) {
-			len = fread(buffer, 1, sizeof(buffer), pf);
-			if (len <= 0)
-				break;
-			definition.append(buffer, len);
+	for(std::list<std::string>::const_iterator it = Command_List.begin(); it != Command_List.end(); ++it) {
+		if (it->empty()) {
+			continue;
 		}
-		pclose(pf);
-		if (definition.empty()) {
+		std::string definition;
+		bool found = true;
+		FILE *pf = popen(it->c_str(), "r");
+		if (!pf) {
 			found = false;
 		} else {
-			size_t length1;
+			char buffer[2048];
+			size_t len;
 			while (true) {
-				length1 = definition.length() -1;
-				if ((definition[length1] == '\n') || (definition[length1] == ' ')) {
-					definition.resize(length1, '\0');
-				} else {
+				len = fread(buffer, 1, sizeof(buffer), pf);
+				if (len <= 0)
 					break;
+				definition.append(buffer, len);
+			}
+			pclose(pf);
+			if (definition.empty()) {
+				found = false;
+			} else {
+				size_t length1;
+				while (true) {
+					length1 = definition.length() -1;
+					if ((definition[length1] == '\n') || (definition[length1] == ' ')) {
+						definition.resize(length1, '\0');
+					} else {
+						break;
+					}
 				}
 			}
 		}
+		std::string pango;
+		if (found) {
+			plugin_service->terminal2pango(definition.c_str(), pango);
+		} else {
+			pango = _("<b><span foreground=\"red\">");
+			pango += *it;
+			pango += _("</span> program is not found! Please install it!</b>");
+		}
+		*dict_name = (gchar **)g_malloc(sizeof(gchar *)*2);
+		*pppWord = (gchar **)g_malloc(sizeof(gchar *)*2);
+		(*pppWord)[0] = g_strdup(it->c_str());
+		(*pppWord)[1] = NULL;
+		*ppppWordData = (gchar ***)g_malloc(sizeof(gchar **)*(1));
+		(*ppppWordData)[0] = (gchar **)g_malloc(sizeof(gchar *)*2);
+		(*ppppWordData)[0][0] =  plugin_service->build_dictdata('g', pango.c_str());
+		(*ppppWordData)[0][1] = NULL;
 	}
-	std::string pango;
-	if (found) {
-		plugin_service->terminal2pango(definition.c_str(), pango);
-	} else {
-		pango = _("<b><span foreground=\"red\">cal</span> program is not found! Please install it!</b>");
-	}
-	*pppWord = (gchar **)g_malloc(sizeof(gchar *)*2);
-	(*pppWord)[0] = g_strdup(text);
-	(*pppWord)[1] = NULL;
-	*ppppWordData = (gchar ***)g_malloc(sizeof(gchar **)*(1));
-	(*ppppWordData)[0] = (gchar **)g_malloc(sizeof(gchar *)*2);
-	(*ppppWordData)[0][0] =  plugin_service->build_dictdata('g', pango.c_str());
-	(*ppppWordData)[0][1] = NULL;
+}
+
+void on_cmd_path_defaultbutton_clicked(GtkWidget *widget, GtkTextBuffer *buffer)
+{
+	gtk_text_buffer_set_text(buffer, "toilet\nbanner\ncowsay\nrig\nsl\ncmarix\naafire\n", -1);
 }
 
 static void configure()
@@ -83,19 +100,73 @@ static void configure()
 #else
 	GtkWidget *vbox = gtk_vbox_new(false, 5);
 #endif
-	GtkWidget *label;
-	label = gtk_label_new(NULL);
-	int have_cal;
-	have_cal = system("which cal");
-	if (have_cal == 0) {
-		gtk_label_set_markup(GTK_LABEL (label), _("<b><span foreground=\"yellow\">cal</span> program is found!</b>"));
-	} else {
-		gtk_label_set_markup(GTK_LABEL (label), _("<b><span foreground=\"red\">cal</span> program is not found!</b>"));
-	}
+	GtkWidget *label = gtk_label_new(_("Multi command path:"));
+	gtk_misc_set_alignment(GTK_MISC(label), 0, .5);
 	gtk_box_pack_start(GTK_BOX(vbox), label, false, false, 0);
+
+	GtkWidget *hbox2;
+#if GTK_MAJOR_VERSION >= 3
+	hbox2 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6);
+#else
+	hbox2 = gtk_hbox_new(FALSE, 6);
+#endif
+	gtk_box_pack_start(GTK_BOX(vbox), hbox2, FALSE, FALSE, 0);
+
+	GtkWidget *cmd_textview = gtk_text_view_new();
+	gtk_widget_set_size_request(cmd_textview, -1, 70);
+	gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(cmd_textview), GTK_WRAP_CHAR);
+	GtkWidget *scrolled_window = gtk_scrolled_window_new(NULL, NULL);
+	gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window), GTK_SHADOW_ETCHED_IN);
+	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+	gtk_box_pack_start(GTK_BOX(hbox2), scrolled_window, false, false, 0);
+	gtk_container_add(GTK_CONTAINER(scrolled_window), cmd_textview);
+	Command_List = plugin_service->conf_get_strlist_at("dictionary/multi_cmd_path");
+	if (Command_List.empty()) {
+		Command_List.push_back("toilet");
+		Command_List.push_back("banner");
+		Command_List.push_back("cowsay");
+		Command_List.push_back("rig");
+		Command_List.push_back("sl");
+		Command_List.push_back("cmarix");
+		Command_List.push_back("aafire");
+	}
+	std::string cmd_path;
+	for(std::list<std::string>::const_iterator it = Command_List.begin(); it != Command_List.end(); ++it) {
+		cmd_path += *it;
+		cmd_path += "\n";
+	}
+	GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(cmd_textview));
+	gtk_text_buffer_set_text(buffer, cmd_path.c_str(), -1);
+
+	GtkWidget *button = gtk_button_new_with_mnemonic(_("_Default"));
+	g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (on_cmd_path_defaultbutton_clicked), buffer);
+	gtk_box_pack_start(GTK_BOX(hbox2), button, FALSE, FALSE, 0);
+
 	gtk_widget_show_all(vbox);
 	gtk_container_add (GTK_CONTAINER (gtk_dialog_get_content_area(GTK_DIALOG(window))), vbox);
 	gtk_dialog_run(GTK_DIALOG(window));
+	GtkTextIter start_iter, end_iter;
+	gtk_text_buffer_get_start_iter(buffer, &start_iter);
+	gtk_text_buffer_get_end_iter(buffer, &end_iter);
+	gchar *text = gtk_text_buffer_get_text(buffer, &start_iter, &end_iter, FALSE);
+	gchar *p1, *p2;
+	p2 = text;
+	Command_List.clear();
+	while (true) {
+		p1 = strchr(p2, '\n');
+		if (!p1) {
+			break;
+		}
+		if (*p1 == '\n') {
+			p2 = p1 + 1;
+			continue;
+		}
+		std::string cmd_path(p2, p1-p2-1);
+		Command_List.push_back(cmd_path);
+		p2 = p1 +1;
+	}
+	g_free(text);
+	plugin_service->conf_set_strlist_at("dictionary/multi_cmd_path", Command_List);
 	gtk_widget_destroy (window);
 }
 
@@ -123,8 +194,7 @@ void stardict_plugin_exit(void)
 
 bool stardict_virtualdict_plugin_init(StarDictVirtualDictPlugInObject *obj)
 {
-	obj->lookup_func = lookup;
-	obj->dict_name = _("Multi Command");
+	obj->multi_lookup_func = multi_lookup;
 	g_print(_("Multi Command plug-in \033[31m[loaded]\033[0m.\n"));
 	return false;
 }
diff --git a/dict/tests/Makefile.am b/dict/tests/Makefile.am
index 45fed45..1f3a93b 100644
--- a/dict/tests/Makefile.am
+++ b/dict/tests/Makefile.am
@@ -4,9 +4,11 @@ AUTOMAKE_OPTIONS = subdir-objects
 COMMONLIB_CPPFLAGS = -I$(top_srcdir)/$(COMMONLIB_INCLUDE_DIR)
 COMMONLIB_LIB = $(top_builddir)/$(COMMONLIB_LIBRARY)
 
-noinst_PROGRAMS = t_config_file t_dict t_fuzzy t_query t_lookupdata \
+noinst_PROGRAMS = t_config_file \
+	t_dict t_fuzzy t_query t_lookupdata \
 	t_convert_old_ini t_articleview t_xml t_res_database
 
+# Disable: t_dict_client.cpp
 EXTRA_DIST = sample1.ifo sample1.idx sample1.dict t_dict_client.cpp t_str.cpp
 
 if USE_SYSTEM_SIGCPP
@@ -64,7 +66,7 @@ AM_CPPFLAGS = @STARDICT_CFLAGS@ $(LOCAL_SIGCPP_INCLUDE) -I$(top_builddir) \
 	-I$(top_srcdir) -I$(top_srcdir)/src -I$(top_srcdir)/src/lib $(COMMONLIB_CPPFLAGS)
 
 TESTS = \
-	t_config_file t_convert_old_ini t_dict t_query t_xml
+	t_config_file t_convert_old_ini t_articleview t_xml t_dict t_fuzzy t_query t_lookupdata
 
 # need fix up:
 # t_articleview t_lookupdata
