Index: src/documentprivate.h
===================================================================
--- src/documentprivate.h	(revision 3195)
+++ src/documentprivate.h	(working copy)
@@ -26,6 +26,8 @@
 #ifndef GEANY_DOCUMENT_PRIVATE_H
 #define GEANY_DOCUMENT_PRIVATE_H
 
+#include "filetypes.h"
+
 /* available UNDO actions, UNDO_SCINTILLA is a pseudo action to trigger Scintilla's
  * undo management */
 enum
@@ -66,6 +68,7 @@
 	FileEncoding	 saved_encoding;
 	gboolean		colourise_needed;	/* use document.c:queue_colourise() instead */
 	gint			line_count;			/* Number of lines in the document. */
+	struct GeanyFiletypeVariant *variant;      /* Pointer to variant of filetype eg c/c++ headers vs source */
 }
 GeanyDocumentPrivate;
 
Index: src/filetypes.c
===================================================================
--- src/filetypes.c	(revision 3195)
+++ src/filetypes.c	(working copy)
@@ -55,8 +55,10 @@
 /* Private GeanyFiletype fields */
 typedef struct GeanyFiletypePrivate
 {
-	GtkWidget	*menu_item;			/* holds a pointer to the menu item for this filetype */
+	GtkWidget	*menu_item;			 /* holds a pointer to the menu item for this filetype */
 	gboolean	keyfile_loaded;
+	struct GeanyFiletypeVariant *variants;  /* array of variants NULL=none */
+	gint        num_variants;        /* size of above */
 #ifdef HAVE_REGCOMP
 	regex_t		error_regex;
 	gboolean	error_regex_compiled;
@@ -762,7 +764,7 @@
 }
 
 
-/* Detect the filetype checking for a shebang, then filename extension. */
+/* Detect the filetype checking for a shebang, then filename extension */
 static GeanyFiletype *filetypes_detect_from_file_internal(const gchar *utf8_filename,
 														  const gchar *line)
 {
@@ -796,7 +798,42 @@
 	return ft;
 }
 
+/* Detect a filetype variant from extensions */
+struct GeanyFiletypeVariant *filetype_get_variant(GeanyFiletype *ft, gchar *fname )
+{
+	gchar *base_filename = fname;
+	gint i,j;
+	gboolean ret = FALSE;
 
+	if (ft->priv->variants == NULL) return NULL; /* no variants */
+
+	/* to match against the basename of the file (because of Makefile*) */
+	base_filename = g_path_get_basename(fname);
+#ifdef G_OS_WIN32
+	/* use lower case basename */
+	setptr(base_filename, g_utf8_strdown(base_filename, -1));
+#endif
+	for (i=0; i<ft->priv->num_variants; i++)
+	{
+		ret = FALSE;
+		for (j = 0; ft->priv->variants[i].extensions[j] != NULL; j++)
+		{
+			GPatternSpec *pattern = g_pattern_spec_new(ft->priv->variants[i].extensions[j]);
+
+			if (g_pattern_match_string(pattern, base_filename))
+			{
+				ret = TRUE;
+				g_pattern_spec_free(pattern);
+				break;
+			}
+			g_pattern_spec_free(pattern);
+		}
+		if (ret) break;
+	}
+	if (i>=ft->priv->num_variants) return NULL;
+	return &(ft->priv->variants[i]);
+};
+
 #ifdef HAVE_PLUGINS
 /* Currently only used by external plugins (e.g. geanyprj). */
 /** Detect filetype based on a shebang line in the file, or the filename extension. */
@@ -907,7 +944,7 @@
 	g_free(ft->programs);
 	g_free(ft->actions);
 	set_error_regex(ft, NULL);
-
+/* TODO clean up variants */
 	g_strfreev(ft->pattern);
 	g_free(ft);
 }
@@ -924,13 +961,52 @@
 	g_hash_table_destroy(filetypes_hash);
 }
 
+static void load_build_settings( struct build_programs *prog, struct build_actions *act, GKeyFile *config, GKeyFile *configh, const gchar *sectname)
+{
+	gchar *result;
 
+	result = g_key_file_get_string(configh, sectname, "compiler", NULL);
+	if (result == NULL) result = g_key_file_get_string(config, sectname, "compiler", NULL);
+	if (result != NULL)
+	{
+		prog->compiler = result;
+		act->can_compile = TRUE;
+	}
+
+	result = g_key_file_get_string(configh, sectname, "linker", NULL);
+	if (result == NULL) result = g_key_file_get_string(config, sectname, "linker", NULL);
+	if (result != NULL)
+	{
+		prog->linker = result;
+		act->can_link = TRUE;
+	}
+
+	result = g_key_file_get_string(configh, sectname, "run_cmd", NULL);
+	if (result == NULL) result = g_key_file_get_string(config, sectname, "run_cmd", NULL);
+	if (result != NULL)
+	{
+		prog->run_cmd = result;
+		act->can_exec = TRUE;
+	}
+
+	result = g_key_file_get_string(configh, sectname, "run_cmd2", NULL);
+	if (result == NULL) result = g_key_file_get_string(config, sectname, "run_cmd2", NULL);
+	if (result != NULL)
+	{
+		prog->run_cmd2 = result;
+		act->can_exec = TRUE;
+	}
+	
+};
+
 static void load_settings(gint ft_id, GKeyFile *config, GKeyFile *configh)
 {
 	GeanyFiletype *ft = filetypes[ft_id];
 	gchar *result;
 	GError *error = NULL;
 	gboolean tmp;
+	gsize len=0;
+	gchar **list;
 
 	/* default extension */
 	result = g_key_file_get_string(configh, "settings", "extension", NULL);
@@ -977,44 +1053,38 @@
 	}
 
 	/* read build settings */
-	result = g_key_file_get_string(configh, "build_settings", "compiler", NULL);
-	if (result == NULL) result = g_key_file_get_string(config, "build_settings", "compiler", NULL);
-	if (result != NULL)
-	{
-		filetypes[ft_id]->programs->compiler = result;
-		filetypes[ft_id]->actions->can_compile = TRUE;
-	}
 
-	result = g_key_file_get_string(configh, "build_settings", "linker", NULL);
-	if (result == NULL) result = g_key_file_get_string(config, "build_settings", "linker", NULL);
-	if (result != NULL)
-	{
-		filetypes[ft_id]->programs->linker = result;
-		filetypes[ft_id]->actions->can_link = TRUE;
-	}
+	load_build_settings( ft->programs, ft->actions, config, configh, "build_settings" ); /* defaults */
 
-	result = g_key_file_get_string(configh, "build_settings", "run_cmd", NULL);
-	if (result == NULL) result = g_key_file_get_string(config, "build_settings", "run_cmd", NULL);
-	if (result != NULL)
-	{
-		filetypes[ft_id]->programs->run_cmd = result;
-		filetypes[ft_id]->actions->can_exec = TRUE;
-	}
-
-	result = g_key_file_get_string(configh, "build_settings", "run_cmd2", NULL);
-	if (result == NULL) result = g_key_file_get_string(config, "build_settings", "run_cmd2", NULL);
-	if (result != NULL)
-	{
-		filetypes[ft_id]->programs->run_cmd2 = result;
-		filetypes[ft_id]->actions->can_exec = TRUE;
-	}
-
 	result = g_key_file_get_string(configh, "build_settings", "error_regex", NULL);
 	if (result == NULL) result = g_key_file_get_string(config, "build_settings", "error_regex", NULL);
 	if (result != NULL)
 	{
 		set_error_regex(ft, result);
 	}
+		
+	list = g_key_file_get_string_list(configh, "settings", "variants", &len, NULL);
+	if (list == NULL) list = g_key_file_get_string_list(config, "settings", "variants", &len, NULL);
+	if (list != NULL && len>0)
+	{
+		int     i;
+		gchar **list1;
+		gsize   len1;
+		gchar  *buildvar;
+		gchar **index;
+		
+		ft->priv->variants = g_new0(struct GeanyFiletypeVariant, len);
+		for (index = list, i=0; index; i++, index++)
+		{
+			list1 = g_key_file_get_string_list( configh, "variants", *index, &len1, NULL );
+			if (list1 == NULL) list1 = g_key_file_get_string_list(config, "variants", *index, &len1, NULL);
+			if (list1 != NULL && len1>0)
+				ft->priv->variants[i].extensions = list1;
+			buildvar = g_strdup_printf("build_settings_%s", *index );
+			load_build_settings( ft->priv->variants[i].programs, ft->priv->variants[i].actions, config, configh, buildvar );
+			g_free(buildvar);
+		}
+	}
 }
 
 
Index: src/filetypes.h
===================================================================
--- src/filetypes.h	(revision 3195)
+++ src/filetypes.h	(working copy)
@@ -139,6 +139,14 @@
 	struct GeanyFiletypePrivate	*priv;	/* must be last, append fields before this item */
 };
 
+struct GeanyFiletypeVariant
+{
+	gchar   *name;
+	gchar  **extensions;			/* list of extensions for this variant */
+	struct build_programs *programs;
+	struct build_actions  *actions;
+};
+
 extern GPtrArray *filetypes_array;
 
 /* Wrap filetypes_array so it can be used with C array syntax.
@@ -178,4 +186,6 @@
 gboolean filetypes_parse_error_message(GeanyFiletype *ft, const gchar *message,
 		gchar **filename, gint *line);
 
+struct GeanyFiletypeVariant *filetype_get_variant(GeanyFiletype *ft, gchar *fname);
+
 #endif
Index: src/document.c
===================================================================
--- src/document.c	(revision 3195)
+++ src/document.c	(working copy)
@@ -330,6 +330,7 @@
 	priv->undo_actions = NULL;
 	priv->redo_actions = NULL;
 	priv->line_count = 0;
+	priv->variant = NULL;
 }
 
 
@@ -2124,6 +2125,7 @@
 	if (ft_changed)	/* filetype has changed */
 	{
 		doc->file_type = type;
+		doc->priv->variant = filetype_get_variant( type, doc->file_name );
 
 		/* delete tm file object to force creation of a new one */
 		if (doc->tm_file != NULL)
