diff --git a/edit/ChangeLog b/edit/ChangeLog
index 3ddc90398..28c657367 100644
--- a/edit/ChangeLog
+++ b/edit/ChangeLog
@@ -1,7 +1,15 @@
+2003-03-03  Andrew V. Samoilov  <sav@bcs.zp.ua>
+
+	* syntax.c (subst_defines): New function to substitute defines.
+	(this_try_alloc_color_pair): Move color substitution ...
+	(edit_read_syntax_rules): ... here.  Use subst_defines() to
+	substitute colors for contexts and keywords.  Allow multiword
+	defines.
+
 2003-02-26  Andrew V. Samoilov  <sav@bcs.zp.ua>
 
-	* syntax.c (edit_read_syntax_rules): Add args argument and it
-	use instead of own auto args array to share this area with ...
+	* syntax.c (edit_read_syntax_rules): Add args argument and use
+	it instead of own auto args array to share this area with ...
 	(edit_read_syntax_file): ... this.  Adjust for the above.
 	Use strncpy() instead of unsafe strcpy().
 
diff --git a/edit/syntax.c b/edit/syntax.c
index 9b5bdc651..3ac353d6e 100644
--- a/edit/syntax.c
+++ b/edit/syntax.c
@@ -89,14 +89,18 @@ static GTree *defines;
 static gint
 mc_defines_destroy (gpointer key, gpointer value, gpointer data)
 {
+    char **values = value;
+
     g_free (key);
+    while (*values)
+	g_free (*values++);
     g_free (value);
 
     return FALSE;
 }
 
 /* Completely destroys the defines tree */
-static void
+static inline void
 destroy_defines (void)
 {
     g_tree_traverse (defines, mc_defines_destroy, G_POST_ORDER, NULL);
@@ -104,7 +108,39 @@ destroy_defines (void)
     defines = 0;
 }
 
-static long compare_word_to_right (WEdit * edit, long i, char *text, char *whole_left, char *whole_right, int line_start)
+static void
+subst_defines (GTree *defines, char **argv, char **argv_end)
+{
+    char **t, **p;
+    int argc;
+    while (*argv && argv < argv_end) {
+	if ((t = g_tree_lookup (defines, *argv))) {
+	    int count = 0;
+	    /* Count argv array members */
+	    argc = 0;
+	    for (p = &argv[1]; *p; p++)
+		argc++;
+	    /* Count members of definition array */
+	    for (p = t; *p; p++)
+		count++;
+	    p = &argv[count + argc];
+	    /* Buffer overflow or infinitive loop in define */
+	    if (p >= argv_end)
+		break;
+	    /* Move rest of argv after definition members */
+	    while (argc >= 0)
+		*p-- = argv[argc-- + 1];
+	    /* Copy definition members to argv */
+	    for (p = argv; *t; *p++ = *t++);
+	}
+	argv++;
+    }
+}
+
+static long
+compare_word_to_right (WEdit *edit, long i, const char *text,
+		       const char *whole_left, const char *whole_right,
+		       int line_start)
 {
     unsigned char *p, *q;
     int c, d, j;
@@ -555,9 +591,6 @@ this_try_alloc_color_pair (char *fg, char *bg)
 	if (!*fg)
 	    fg = 0;
     if (fg) {
-	p = g_tree_lookup (defines, fg);
-	if (p)
-	    fg = p;
 	strncpy (f, fg, sizeof (f) - 1);
 	f[sizeof (f) - 1] = 0;
 	p = strchr (f, '/');
@@ -566,9 +599,6 @@ this_try_alloc_color_pair (char *fg, char *bg)
 	fg = f;
     }
     if (bg) {
-	p = g_tree_lookup (defines, bg);
-	if (p)
-	    bg = p;
 	strncpy (b, bg, sizeof (b) - 1);
 	b[sizeof (b) - 1] = 0;
 	p = strchr (b, '/');
@@ -735,6 +765,7 @@ edit_read_syntax_rules (WEdit *edit, FILE *f, char **args)
 #endif
 	    num_words = 1;
 	    c->keyword[0] = g_malloc0 (sizeof (struct key_word));
+	    subst_defines (defines, a, &args[1024]);
 	    fg = *a;
 	    if (*a)
 		a++;
@@ -783,6 +814,7 @@ edit_read_syntax_rules (WEdit *edit, FILE *f, char **args)
 	    }
 	    k->keyword = g_strdup (*a++);
 	    k->first = *k->keyword;
+	    subst_defines (defines, a, &args[1024]);
 	    fg = *a;
 	    if (*a)
 		a++;
@@ -801,17 +833,22 @@ edit_read_syntax_rules (WEdit *edit, FILE *f, char **args)
 	} else if (!strcmp (args[0], "file")) {
 	    break;
 	} else if (!strcmp (args[0], "define")) {
-	    gpointer t;
 	    char *key = *a++;
-	    char *value = *a;
-	    if (!key || !value)
+	    char **argv;
+
+	    if (argc < 3)
 		break_a;
-	    if ((t = g_tree_lookup (defines, key))){
-		g_free (t);
+	    if ((argv = g_tree_lookup (defines, key))) {
+		mc_defines_destroy (NULL, argv, NULL);
 	    } else {
 		key = g_strdup (key);
 	    }
-	    g_tree_insert (defines, key, g_strdup (value));
+	    argv = g_new (char *, argc - 1);
+	    g_tree_insert (defines, key, argv);
+	    while (*a) {
+		*argv++ = g_strdup (*a++);
+	    };
+	    *argv = NULL;
 	} else {		/* anything else is an error */
 	    break_a;
 	}