Index: cpp/frams/genetics/geno.cpp
===================================================================
--- cpp/frams/genetics/geno.cpp	(revision 146)
+++ cpp/frams/genetics/geno.cpp	(revision 150)
@@ -8,257 +8,265 @@
 
 SListTempl<GenoValidator*> Geno::validators;
-GenoConvManager *Geno::converters=NULL;
-
-void Geno::init(const SString& genstring,char genformat,const SString& genname,const SString& comment)
-{
-refcount=1;
-owner=0;
-f0gen=0;
-mapinshift=0;
-mapoutshift=0;
-isvalid=-1;
-SString gencopy(genstring);
-if (genformat==-1)
+GenoConvManager *Geno::converters = NULL;
+
+void Geno::init(const SString& genstring, char genformat, const SString& genname, const SString& comment)
+{
+	refcount = 1;
+	owner = 0;
+	f0gen = 0;
+	mapinshift = 0;
+	mapoutshift = 0;
+	isvalid = -1;
+	SString gencopy(genstring);
+	if (genformat == -1)
 	{ // unknown format
-	genformat='1';
-	if (genstring.charAt(0)=='/')
+		genformat = '1';
+		if (genstring.charAt(0) == '/')
 		{
-		int end;
-		SString newcomment;
-		switch(genstring.charAt(1))
+			int end;
+			SString newcomment;
+			switch (genstring.charAt(1))
 			{
 			case '/':
-				genformat=genstring.charAt(2);
-				if ((end=genstring.indexOf('\n'))>=0)
-					{
-					newcomment=genstring.substr(2,end-2);
-					gencopy=genstring.substr(end+1);
-					mapinshift=end+1;
-					}
+				genformat = genstring.charAt(2);
+				if ((end = genstring.indexOf('\n')) >= 0)
+				{
+					newcomment = genstring.substr(2, end - 2);
+					gencopy = genstring.substr(end + 1);
+					mapinshift = end + 1;
+				}
 				else
-					{
-					gencopy=0;
-					mapinshift=genstring.len();
-					}
+				{
+					gencopy = 0;
+					mapinshift = genstring.len();
+				}
 				break;
 			case '*':
-				genformat=genstring.charAt(2);
-				if ((end=genstring.indexOf("*/"))>=0)
-					{
-					newcomment=genstring.substr(2,end-2);
-					gencopy=genstring.substr(end+2);
-					mapinshift=end+2;
-					}
+				genformat = genstring.charAt(2);
+				if ((end = genstring.indexOf("*/")) >= 0)
+				{
+					newcomment = genstring.substr(2, end - 2);
+					gencopy = genstring.substr(end + 2);
+					mapinshift = end + 2;
+				}
 				else
-					{
-					gencopy=0;
-					mapinshift=genstring.len();
-					}
+				{
+					gencopy = 0;
+					mapinshift = genstring.len();
+				}
 				break;
 			}
-		if (newcomment.len()>0)
+			if (newcomment.len() > 0)
 			{
-			SString token; int pos=0;
-			if (newcomment.getNextToken(pos,token,';'))
-			if (newcomment.getNextToken(pos,token,';'))
-				{
-				if (token.len()) txt=token;
-			if (newcomment.getNextToken(pos,token,';'))
-				if (token.len()) name=token;
-				}
+				SString token; int pos = 0;
+				if (newcomment.getNextToken(pos, token, ';'))
+					if (newcomment.getNextToken(pos, token, ';'))
+					{
+						if (token.len()) txt = token;
+						if (newcomment.getNextToken(pos, token, ';'))
+							if (token.len()) name = token;
+					}
 			}
 		}
 	}
 
-gen=gencopy;
-format=genformat;
-if (!name.len()) name=genname;
-if (!txt.len()) txt=comment;
-multiline=(strchr((const char*)gen,'\n')!=0);
-// mapoutshift...?
+	gen = gencopy;
+	format = genformat;
+	if (!name.len()) name = genname;
+	if (!txt.len()) txt = comment;
+	multiline = (strchr((const char*)gen, '\n') != 0);
+	// mapoutshift...?
 }
 
 void Geno::freeF0()
 {
-if (f0gen) {delete f0gen; f0gen=0;}
-}
-
-Geno::Geno(const char *genstring,char genformat,const char *genname,const char *comment)
-{
-init(SString(genstring),genformat,SString(genname),SString(comment));
-}
-
-Geno::Geno(const SString& genstring,char genformat,const SString& genname,const SString& comment)
-{
-init(genstring,genformat,genname,comment);
+	if (f0gen) { delete f0gen; f0gen = 0; }
+}
+
+Geno::Geno(const char *genstring, char genformat, const char *genname, const char *comment)
+{
+	init(SString(genstring), genformat, SString(genname), SString(comment));
+}
+
+Geno::Geno(const SString& genstring, char genformat, const SString& genname, const SString& comment)
+{
+	init(genstring, genformat, genname, comment);
 }
 
 Geno::Geno(const Geno& src)
-	:gen(src.gen),name(src.name),format(src.format),txt(src.txt),isvalid(src.isvalid),
-	 f0gen(0),mapinshift(src.mapinshift),mapoutshift(src.mapinshift),
-	 multiline(src.multiline),owner(0)
-{f0gen=src.f0gen?new Geno(*src.f0gen):0; refcount=1;}
+:gen(src.gen), name(src.name), format(src.format), txt(src.txt), isvalid(src.isvalid),
+f0gen(0), mapinshift(src.mapinshift), mapoutshift(src.mapinshift),
+multiline(src.multiline), owner(0)
+{
+	f0gen = src.f0gen ? new Geno(*src.f0gen) : 0; refcount = 1;
+}
 
 void Geno::operator=(const Geno& src)
 {
-freeF0();
-gen=src.gen;
-name=src.name;
-format=src.format;
-txt=src.txt;
-isvalid=src.isvalid;
-mapinshift=src.mapinshift;
-mapoutshift=src.mapinshift;
-multiline=src.multiline;
-f0gen=src.f0gen?new Geno(*src.f0gen):0;
-owner=0;
+	freeF0();
+	gen = src.gen;
+	name = src.name;
+	format = src.format;
+	txt = src.txt;
+	isvalid = src.isvalid;
+	mapinshift = src.mapinshift;
+	mapoutshift = src.mapinshift;
+	multiline = src.multiline;
+	f0gen = src.f0gen ? new Geno(*src.f0gen) : 0;
+	owner = 0;
 }
 
 Geno::Geno(const SString& src)
 {
-init(src,-1,SString::empty(),SString::empty());
-}
-
-void Geno::setGene(const SString& g,char newformat)
-{
-gen=g;
-isvalid=-1;
-freeF0();
-if (newformat>=0) format=newformat;
+	init(src, -1, SString::empty(), SString::empty());
+}
+
+void Geno::setGene(const SString& g, char newformat)
+{
+	gen = g;
+	isvalid = -1;
+	freeF0();
+	if (newformat >= 0) format = newformat;
 }
 
 void Geno::setString(const SString& g)
 {
-freeF0();
-init(g,-1,SString::empty(),SString::empty());
+	freeF0();
+	init(g, -1, SString::empty(), SString::empty());
 }
 
 void Geno::setName(const SString& n)
 {
-name=n;
+	name = n;
 }
 
 void Geno::setComment(const SString& c)
 {
-txt=c;
+	txt = c;
 }
 
 SString Geno::toString(void) const
 {
-SString out;
-int comment=0;
-if ((format!='1')||(comment=(txt.len()||name.len())))
-	{
-	if (multiline)
-		out+="//";
+	SString out;
+	int comment = 0;
+	if ((format != '1') || (comment = (txt.len() || name.len())))
+	{
+		if (multiline)
+			out += "//";
+		else
+			out += "/*";
+		out += format;
+		if (comment)
+		{
+			if (txt.len()) { out += ";"; out += txt; }
+			if (name.len()){ out += ";"; out += name; }
+		}
+		if (multiline)
+			out += "\n";
+		else
+			out += "*/";
+	}
+	out += gen;
+	return out;
+}
+
+SString Geno::shortString(void) const
+{
+	SString out;
+	if (format != '1')
+	{
+		if (multiline)
+			out += "//";
+		else
+			out += "/*";
+		if (format == 0)
+			out += "invalid";
+		else
+			out += format;
+		if (multiline)
+			out += "\n";
+		else
+			out += "*/";
+	}
+	out += gen;
+	return out;
+}
+
+int Geno::mapGenToString(int genpos) const
+{
+	if (genpos > gen.len()) return -2;
+	if (genpos<0) return -1;
+	return mapinshift + genpos;
+}
+
+int Geno::mapStringToGen(int stringpos) const
+{
+	stringpos -= mapinshift;
+	if (stringpos>gen.len()) return -2;
+	if (stringpos < 0) return -1;
+	return stringpos;
+}
+
+SString Geno::getGene(void) const { return gen; }
+SString Geno::getName(void) const { return name; }
+char Geno::getFormat(void) const { return format; }
+SString Geno::getComment(void) const { return txt; }
+
+int ModelGenoValidator::testGenoValidity(Geno& g)
+{
+	if (g.getFormat() == '0')
+	{
+		Model mod(g);
+		return mod.isValid();
+	}
 	else
-		out+="/*";
-	out+=format;
-	if (comment)
+	{
+		bool converter_missing;
+		Geno f0geno = g.getConverted('0', NULL, &converter_missing);
+		if (converter_missing)
+			return -1;//no result
+		return f0geno.isValid();
+	}
+}
+
+void Geno::validate()
+{
+	if (isvalid >= 0) return;
+	if (gen.len() == 0) { isvalid = 0; return; }
+	FOREACH(GenoValidator*, v, validators)
+		if ((isvalid = v->testGenoValidity(*this)) >= 0)
+			return;
+	isvalid = 0;
+	FMprintf("Geno", "validate", FMLV_WARN, "Wrong configuration? No genotype validators defined for genetic format f%c.", format);
+}
+
+bool Geno::isValid(void)
+{
+	if (isvalid<0) validate();
+	return isvalid>0;
+}
+
+Geno Geno::getConverted(char otherformat, MultiMap *m, bool *converter_missing)
+{
+	if (otherformat == getFormat()) { if (converter_missing) *converter_missing = false; return *this; }
+#ifndef NO_GENOCONVMANAGER
+	if (converters)
+	{
+		if ((otherformat == '0') && (!m))
 		{
-		if (txt.len()) {out+=";";out+=txt;}
-		if (name.len()){out+=";";out+=name;}
+			if (!f0gen)
+				f0gen = new Geno(converters->convert(*this, otherformat, NULL, converter_missing));
+			return *f0gen;
 		}
-	if (multiline)
-		out+="\n";
-	else
-		out+="*/";
-	}
-out+=gen;
-return out;
-}
-
-SString Geno::shortString(void) const
-{
-SString out;
-if (format!='1')
-	{
-	if (multiline)
-		out+="//";
-	else
-		out+="/*";
-	if (format==0)
-		out+="invalid";
-	else
-		out+=format;
-	if (multiline)
-		out+="\n";
-	else
-		out+="*/";
-	}
-out+=gen;
-return out;
-}
-
-int Geno::mapGenToString(int genpos) const
-{
-if (genpos>gen.len()) return -2;
-if (genpos<0) return -1;
-return mapinshift+genpos;
-}
-
-int Geno::mapStringToGen(int stringpos) const
-{
-stringpos-=mapinshift;
-if (stringpos>gen.len()) return -2;
-if (stringpos<0) return -1;
-return stringpos;
-}
-
-SString Geno::getGene(void) const {return gen;}
-SString Geno::getName(void) const {return name;}
-char Geno::getFormat(void) const {return format;}
-SString Geno::getComment(void) const {return txt;}
-
-int ModelGenoValidator::testGenoValidity(Geno& g)
-{
-if (g.getFormat()=='0')
-	{
-	Model mod(g);
-	return mod.isValid();
-	}
-else
-	{
-	Geno f0geno=g.getConverted('0');
-	return f0geno.isValid();
-	}
-}
-
-void Geno::validate()
-{
-if (isvalid>=0) return;
-if (gen.len()==0) { isvalid=0; return; }
-FOREACH(GenoValidator*,v,validators)
-	if ((isvalid=v->testGenoValidity(*this))>=0)
-		break;
-}
-
-bool Geno::isValid(void)
-{
-if (isvalid<0) validate();
-return isvalid>0;
-}
-
-Geno Geno::getConverted(char otherformat,MultiMap *m)
-{
-if (otherformat==getFormat()) return *this;
-#ifndef NO_GENOCONVMANAGER
-if (converters)
-	{
-	if ((otherformat=='0')&&(!m))
-		{
-		if (!f0gen)
-			f0gen=new Geno(converters->convert(*this,otherformat));
-		return *f0gen;
-	}
-	else
-		return converters->convert(*this,otherformat,m);
+		else
+			return converters->convert(*this, otherformat, m, converter_missing);
 	}
 #endif
-return (otherformat==getFormat())?*this:Geno(0,0,0,"GenConvManager not available");
+	if (converter_missing) *converter_missing = true;
+	return (otherformat == getFormat()) ? *this : Geno(0, 0, 0, "GenConvManager not available");
 }
 
 Geno::~Geno()
 {
-if (f0gen) delete f0gen;
-}
+	if (f0gen) delete f0gen;
+}
Index: cpp/frams/genetics/geno.h
===================================================================
--- cpp/frams/genetics/geno.h	(revision 146)
+++ cpp/frams/genetics/geno.h	(revision 150)
@@ -15,11 +15,11 @@
 class GenoValidator
 {
-  public:
-virtual int testGenoValidity(Geno& g)=0;/// -1=no information  0=invalid  1=valid
+public:
+	virtual int testGenoValidity(Geno& g) = 0;/// -1=no information  0=invalid  1=valid
 };
 
-/// basic GenoValidator that works by building a Model from any Geno (by converting to f0)
-/// validation fails when the model can't be built or the genotype can't be converted
-class ModelGenoValidator: public GenoValidator
+/// Basic GenoValidator that works by building a Model from any Geno (by converting to f0).
+/// Validation fails when the model can't be built or the genotype can't be converted.
+class ModelGenoValidator : public GenoValidator
 {
 public:
@@ -28,98 +28,99 @@
 
 /// basic information about a single genotype.
-class Geno: public DestrBase
+class Geno : public DestrBase
 {
-friend class Simulator;//needs to access validators directly
-SString gen;
-SString name;
-char format;
-SString txt;
-int isvalid; ///< <0 -> unknown   >=0 -> value for "isValid"
+	friend class Simulator;//needs to access validators directly
+	SString gen;
+	SString name;
+	char format;
+	SString txt;
+	int isvalid; ///< <0 -> unknown   >=0 -> value for "isValid"
 
-Geno *f0gen;
+	Geno *f0gen;
 
-int mapinshift; /// # of characters in the initial comment
-int mapoutshift; /// # of characters in the output comment
-int multiline;
+	int mapinshift; /// number of characters in the initial comment
+	int mapoutshift; /// number of characters in the output comment
+	int multiline;
 
-void init(const SString& genstring,char genformat,const SString& genname,const SString& comment);
-void validate(void);
+	void init(const SString& genstring, char genformat, const SString& genname, const SString& comment);
+	void validate(void);
 
-void freeF0();
+	void freeF0();
 
-bool isInvalid() {return isvalid==0;}
+	bool isInvalid() { return isvalid == 0; }
 
-friend class Model;
-friend class GenoConvManager;
-	
+	friend class Model;
+	friend class GenoConvManager;
+
 public:
-/// create a genotype object from primitives
-/// @param genstring pure genotype, without any comments
-/// @param genformat genotype format
-/// @param comment information about genotype (for genetic operators and "history")
-Geno(const char *genstring=0,char genformat=-1,const char *genname=0,const char *comment=0);
+	/// create a genotype object from primitives
+	/// @param genstring pure genotype, without any comments
+	/// @param genformat genotype format
+	/// @param comment information about genotype (for genetic operators and "history")
+	Geno(const char *genstring = 0, char genformat = -1, const char *genname = 0, const char *comment = 0);
 
-/// create a genotype object from primitives
-/// @param genstring pure genotype, wihtout any comments
-/// @param genformat genotype format
-/// @param name genotype name, new name will generated if needed
-/// @param comment information about genotype (for genetic operators and "history")
-Geno(const SString& genstring,char genformat,const SString& genname,const SString& comment);
+	/// create a genotype object from primitives
+	/// @param genstring pure genotype, wihtout any comments
+	/// @param genformat genotype format
+	/// @param name genotype name, new name will generated if needed
+	/// @param comment information about genotype (for genetic operators and "history")
+	Geno(const SString& genstring, char genformat, const SString& genname, const SString& comment);
 
-/// create object from full string, containing optional format and comment information
-Geno(const SString & fullstring);
+	/// create object from full string, containing optional format and comment information
+	Geno(const SString & fullstring);
 
-/// clone
-Geno(const Geno& src);
+	/// clone
+	Geno(const Geno& src);
 
-void operator=(const Geno& src);
+	void operator=(const Geno& src);
 
-~Geno();
+	~Geno();
 
-void setValid(int v) {isvalid=v;}
-int getValid() {return isvalid;}
+	void setValid(int v) { isvalid = v; }
+	int getValid() { return isvalid; }
 
-/// return string representation, with format comment at the beginning
-SString toString(void) const;
-SString shortString(void) const;
+	/// return string representation, with format comment at the beginning
+	SString toString(void) const;
+	SString shortString(void) const;
 
-void setString(const SString& genewithcomments);
+	void setString(const SString& genewithcomments);
 
-/** @param newformat=-1 -> don't change */
-void setGene(const SString& g, char newformat=-1);
-SString getGene(void) const;
+	/** @param newformat=-1 -> don't change */
+	void setGene(const SString& g, char newformat = -1);
+	SString getGene(void) const;
 
-SString getName(void) const;
-void setName(const SString&);
-char getFormat(void) const;
+	SString getName(void) const;
+	void setName(const SString&);
+	char getFormat(void) const;
 
-SString getComment(void) const;
-void setComment(const SString&);
+	SString getComment(void) const;
+	void setComment(const SString&);
 
-/// invalid genotype cannot be used to build a creature
-bool isValid(void);
+	/// invalid genotype cannot be used to build a creature
+	bool isValid(void);
 
-/// make converted version of the genotype.
-Geno getConverted(char otherformat,MultiMap *m=0);
+	/// make converted version of the genotype.
+	/// @param converter_missing optional output parameter (ignored when NULL). Receives true if the conversion fails because of the lack of appropriate converter(s) (the returned Geno is always invalid in this case). Receives false if the genotype was converted by a converter or a converter chain (the returned Geno can be valid or invalid, depending on the converter's decision).
+	Geno getConverted(char otherformat, MultiMap *m = 0, bool *converter_missing = NULL);
 
-/// @return -1 = before first char in the string
-/// @return -2 = after last char in the string
-int mapGenToString(int genpos) const;
-/// @return -1 = before first char in the genotype
-/// @return -2 = after last char in the genotype
-int mapStringToGen(int stringpos) const;
+	/// @return -1 = before first char in the string
+	/// @return -2 = after last char in the string
+	int mapGenToString(int genpos) const;
+	/// @return -1 = before first char in the genotype
+	/// @return -2 = after last char in the genotype
+	int mapStringToGen(int stringpos) const;
 
-int operator==(const Geno &g) {return (format==g.format)&&(gen==g.gen);}
+	int operator==(const Geno &g) { return (format == g.format) && (gen == g.gen); }
 
-void* owner;
+	void* owner;
 
-// managing global Geno-related objects (used for validation and conversion)
-static void addValidator(GenoValidator* gv) {validators+=gv;}
-static void removeValidator(GenoValidator* gv) {validators-=gv;}
-static void useConverters(GenoConvManager& gcm) {converters=&gcm;}
-static GenoConvManager &getConverters() {return *converters;}
-  protected:
-static GenoConvManager *converters;
-static SListTempl<GenoValidator*> validators;
+	// managing global Geno-related objects (used for validation and conversion)
+	static void addValidator(GenoValidator* gv) { validators += gv; }
+	static void removeValidator(GenoValidator* gv) { validators -= gv; }
+	static void useConverters(GenoConvManager& gcm) { converters = &gcm; }
+	static GenoConvManager &getConverters() { return *converters; }
+protected:
+	static GenoConvManager *converters;
+	static SListTempl<GenoValidator*> validators;
 };
 
Index: cpp/frams/genetics/genoconv.cpp
===================================================================
--- cpp/frams/genetics/genoconv.cpp	(revision 146)
+++ cpp/frams/genetics/genoconv.cpp	(revision 150)
@@ -18,67 +18,67 @@
 ///////////////////////////////////////////////////////////////////////////
 
-GenoConvParam::GenoConvParam(GenoConvManager *g):Param(0),gcm(g)
-{
-updatetab();
+GenoConvParam::GenoConvParam(GenoConvManager *g) :Param(0), gcm(g)
+{
+	updatetab();
 }
 
 void GenoConvParam::freetab()
 {
-if (tab) free(tab);
-tab=0;
+	if (tab) free(tab);
+	tab = 0;
 }
 
 const char *GenoConvParam::id(int i)
 {
-if (i>=gcm->converters.size()) return 0;
-sprintf(tmp_id,"genkonw%d",i);
-return tmp_id;
+	if (i >= gcm->converters.size()) return 0;
+	sprintf(tmp_id, "genkonw%d", i);
+	return tmp_id;
 }
 
 void GenoConvParam::updatetab()
 {
-int i;
-GenoConverter *gk;
-ParamEntry *pe;
-int ile=gcm->converters.size();
-freetab();
-tab=(ParamEntry*)calloc(2+ile,sizeof(ParamEntry));
-tab[0].id="Genetics: Conversions";
-tab[0].group=1;
-tab[0].flags=(short)ile;
-tab[0].name="gkparam:";
-gcnames.clear();
-for (i=0,pe=tab+1;gk=(GenoConverter *)gcm->converters(i);pe++,i++)
-	{
-	pe->id="?";
-	pe->group=0;
-	pe->flags=0;
-	std::string descr="f";
-	descr+=gk->in_format;
-	descr+=" -> f";
-	descr+=gk->out_format;
-	descr+=" : ";
-	descr+=gk->name;
-	gcnames.push_back(descr);
-	pe->name=descr.c_str();
-	pe->type="d 0 1";
-	pe->help=gk->info;
-	}
-pe->id=0;
+	int i;
+	GenoConverter *gk;
+	ParamEntry *pe;
+	int ile = gcm->converters.size();
+	freetab();
+	tab = (ParamEntry*)calloc(2 + ile, sizeof(ParamEntry));
+	tab[0].id = "Genetics: Conversions";
+	tab[0].group = 1;
+	tab[0].flags = (short)ile;
+	tab[0].name = "gkparam:";
+	gcnames.clear();
+	for (i = 0, pe = tab + 1; gk = (GenoConverter *)gcm->converters(i); pe++, i++)
+	{
+		pe->id = "?";
+		pe->group = 0;
+		pe->flags = 0;
+		std::string descr = "f";
+		descr += gk->in_format;
+		descr += " -> f";
+		descr += gk->out_format;
+		descr += " : ";
+		descr += gk->name;
+		gcnames.push_back(descr);
+		pe->name = descr.c_str();
+		pe->type = "d 0 1";
+		pe->help = gk->info;
+	}
+	pe->id = 0;
 }
 
 GenoConvParam::~GenoConvParam()
 {
-freetab();
+	freetab();
 }
 
 void *GenoConvParam::getTarget(int i)
 {
-GenoConverter *gk=(GenoConverter *)gcm->converters(i);
-return &gk->enabled;
+	GenoConverter *gk = (GenoConverter *)gcm->converters(i);
+	return &gk->enabled;
 }
 
 GenoConvManager::GenoConvManager()
-	:param(this)
+:param(this)
 {
 }
@@ -86,36 +86,35 @@
 GenoConvManager::~GenoConvManager()
 {
-GenoConverter *gc;
-for (converters.start();gc=(GenoConverter*)converters();) delete gc;
+	FOREACH(GenoConverter*, gc, converters) delete gc;
 }
 
 void GenoConvManager::addConverter(GenoConverter *gc)
 {
-converters+=gc;
-param.updatetab();
+	converters += gc;
+	param.updatetab();
 }
 void GenoConvManager::removeConverter(GenoConverter *gc)
 {
-converters-=gc;
-param.updatetab();
-}
-
-GenoConverter *GenoConvManager::findConverters(SListTempl<GenoConverter*>* result,char in,char out,int enabled,char* name)
-{
-GenoConverter *gk,*retval=0;
-int i=0;
-for (;gk=(GenoConverter*)converters(i);i++)
-	{
-	if ((in!=-1)&&(in!=gk->in_format)) continue;
-	if ((out!=-1)&&(out!=gk->out_format)) continue;
-	if ((enabled!=-1)&&(enabled!=gk->enabled)) continue;
-	if ((name)&&(strcmp(name,gk->name))) continue;
-	if (!retval) {retval=gk; if (!result) break;}
-	if (result) result->append(gk);
-	}
-return retval;
-}
-
-/// write path into 'path'
+	converters -= gc;
+	param.updatetab();
+}
+
+GenoConverter *GenoConvManager::findConverters(SListTempl<GenoConverter*>* result, char in, char out, int enabled, char* name)
+{
+	GenoConverter *gk, *retval = 0;
+	int i = 0;
+	for (; gk = (GenoConverter*)converters(i); i++)
+	{
+		if ((in != -1) && (in != gk->in_format)) continue;
+		if ((out != -1) && (out != gk->out_format)) continue;
+		if ((enabled != -1) && (enabled != gk->enabled)) continue;
+		if ((name) && (strcmp(name, gk->name))) continue;
+		if (!retval) { retval = gk; if (!result) break; }
+		if (result) result->append(gk);
+	}
+	return retval;
+}
+
+/// Writes path into 'path'.
 /// return the last path element (return >= path)
 /// null -> path not found
@@ -123,92 +122,93 @@
 /// (can be NULL if you don't need this information)
 
-char *GenoConvManager::getPath(char in,char out,char *path,int maxlen,int *mapavailable)
-{
-if (!maxlen) return 0;
-GenoConverter *gk;
-int i=0;
-for (;gk=(GenoConverter*)converters(i);i++)
-	{
-	if ((gk->enabled)&&(gk->in_format == in))
+char *GenoConvManager::getPath(char in, char out, char *path, int maxlen, int *mapavailable)
+{
+	if (!maxlen) return 0;
+	GenoConverter *gk;
+	int i = 0;
+	for (; gk = (GenoConverter*)converters(i); i++)
+	{
+		if ((gk->enabled) && (gk->in_format == in))
 		{
-		*path=(char)i;
-		if (gk->out_format == out)
-			{
-			if (mapavailable)
-				*mapavailable=gk->mapsupport;
-			return path;
-			}
-		else
-			{
-			int mapavail;
-			char *ret=getPath(gk->out_format,out,path+1,maxlen-1,&mapavail);
-			if (ret)
+			*path = (char)i;
+			if (gk->out_format == out)
+			{
+				if (mapavailable)
+					*mapavailable = gk->mapsupport;
+				return path;
+			}
+			else
+			{
+				int mapavail;
+				char *ret = getPath(gk->out_format, out, path + 1, maxlen - 1, &mapavail);
+				if (ret)
 				{
-				if (mapavailable)
-					*mapavailable=gk->mapsupport && mapavail;
-				return ret;
+					if (mapavailable)
+						*mapavailable = gk->mapsupport && mapavail;
+					return ret;
 				}
 			}
 		}
 	}
-return 0;
-}
-
-char *GenoConvManager::getFormatPath(char in,char out,char *path,int maxlen,int *mapavailable)
-{
-char *ret=getPath(in,out,path,maxlen,mapavailable);
-if (ret)
-	{
-	for (char*t=path;t<=ret;t++)
-		*t=((GenoConverter*)converters(*t))->out_format;
-	}
-return ret;
-}
-
-Geno GenoConvManager::convert(Geno &in,char format,MultiMap *map)
-{
-if (in.getFormat()==format) return in;
-char path[10];
-int dep;
-char *ret;
-if (in.isInvalid()) { return Geno("",0,"","invalid genotype cannot be converted"); }
-int mapavail;
-for (dep=1;dep<(int)sizeof(path);dep++) // sogenannte iteracyjne poglebianie...
-	if (ret=getPath(in.getFormat(),format,path,dep,&mapavail)) break;
-if (!ret) { return Geno("",0,"","converter not found"); }
-if (!map) mapavail=0;
-char *t=path;
-SString tmp;
-tmp=in.getGene();
-MultiMap lastmap,tmpmap;
-int firstmap=1;
-for (;t<=ret;t++)
-	{
-	GenoConverter *gk=(GenoConverter*)converters(*t);
-	tmp=gk->convert(tmp,mapavail?&tmpmap:0);
-	if (!tmp.len())
+	return 0;
+}
+
+char *GenoConvManager::getFormatPath(char in, char out, char *path, int maxlen, int *mapavailable)
+{
+	char *ret = getPath(in, out, path, maxlen, mapavailable);
+	if (ret)
+	{
+		for (char*t = path; t <= ret; t++)
+			*t = ((GenoConverter*)converters(*t))->out_format;
+	}
+	return ret;
+}
+
+Geno GenoConvManager::convert(Geno &in, char format, MultiMap *map, bool *converter_missing)
+{
+	if (in.getFormat() == format) { if (converter_missing) *converter_missing = false; return in; }
+	char path[10];
+	int dep;
+	char *ret;
+	if (in.isInvalid()) { if (converter_missing) *converter_missing = false; return Geno("", 0, "", "invalid genotype cannot be converted"); }
+	int mapavail;
+	for (dep = 1; dep < (int)sizeof(path); dep++) //iterative deepening
+		if (ret = getPath(in.getFormat(), format, path, dep, &mapavail)) break;
+	if (!ret) { if (converter_missing) *converter_missing = true; return Geno("", 0, "", "converter not found"); }
+	if (converter_missing) *converter_missing = false;
+	if (!map) mapavail = 0;
+	char *t = path;
+	SString tmp;
+	tmp = in.getGene();
+	MultiMap lastmap, tmpmap;
+	int firstmap = 1;
+	for (; t <= ret; t++)
+	{
+		GenoConverter *gk = (GenoConverter*)converters(*t);
+		tmp = gk->convert(tmp, mapavail ? &tmpmap : 0);
+		if (!tmp.len())
 		{
-		char t[100];
-		sprintf(t,"f%c->f%c conversion failed (%s)",gk->in_format,gk->out_format,gk->name);
-		return Geno(0,0,0,t);
+			char t[100];
+			sprintf(t, "f%c->f%c conversion failed (%s)", gk->in_format, gk->out_format, gk->name);
+			return Geno(0, 0, 0, t);
 		}
-	if (mapavail)
+		if (mapavail)
 		{
-		if (firstmap)
-			{
-			lastmap=tmpmap;
-			firstmap=0;
-			}
-		else
-			{
-			MultiMap m;
-			m.addCombined(lastmap,tmpmap);
-			lastmap=m;
-			}
-		tmpmap.clear();
+			if (firstmap)
+			{
+				lastmap = tmpmap;
+				firstmap = 0;
+			}
+			else
+			{
+				MultiMap m;
+				m.addCombined(lastmap, tmpmap);
+				lastmap = m;
+			}
+			tmpmap.clear();
 		}
 	}
-if (map)
-	*map=lastmap;
-return Geno(tmp, format, in.getName(), in.getComment());
-}
+	if (map)
+		*map = lastmap;
+	return Geno(tmp, format, in.getName(), in.getComment());
+}
Index: cpp/frams/genetics/genoconv.h
===================================================================
--- cpp/frams/genetics/genoconv.h	(revision 146)
+++ cpp/frams/genetics/genoconv.h	(revision 150)
@@ -17,16 +17,16 @@
 class GenoConvManager;
 
-class GenoConvParam: public Param
+class GenoConvParam : public Param
 {
-GenoConvManager *gcm;
-std::vector<std::string> gcnames;
-char tmp_id[20];
-void freetab();
+	GenoConvManager *gcm;
+	std::vector<std::string> gcnames;
+	char tmp_id[20];
+	void freetab();
 public:
-GenoConvParam(GenoConvManager *g);
-~GenoConvParam();
-void *getTarget(int);
-const char* id(int i);
-void updatetab();
+	GenoConvParam(GenoConvManager *g);
+	~GenoConvParam();
+	void *getTarget(int);
+	const char* id(int i);
+	void updatetab();
 };
 
@@ -42,21 +42,21 @@
 {
 public:
-const char *name;	//< converter name (short)
-char in_format,		//< input format, eg. '1'
-	out_format;	//< output format, eg. '0'
-const char *info;	//< detailed info about converter, format or copyright
-long enabled;	//< don't touch this! (used by configuration module)
-long mapsupport; //< set to 1 if your converter supports genotype mapping
+	const char *name;	//< converter name (short)
+	char in_format,		//< input format, eg. '1'
+		out_format;	//< output format, eg. '0'
+	const char *info;	//< detailed info about converter, format or copyright
+	long enabled;	//< don't touch this! (used by configuration module)
+	long mapsupport; //< set to 1 if your converter supports genotype mapping
 
-/// You have to reimplement this method.
-/// If your converter cannot do its job, return empty string
-/// (return SString();), any other return value is assumed
-/// to be output genotype.
-/// @param map if not null, mapping informaton is requested, converter should add conversion map to this object
-virtual SString convert(SString &i,MultiMap *map) {return SString();}
+	/// You have to reimplement this method.
+	/// If your converter cannot do its job, return empty string
+	/// (return SString();), any other return value is assumed
+	/// to be output genotype.
+	/// @param map if not null, mapping informaton is requested, converter should add conversion map to this object
+	virtual SString convert(SString &i, MultiMap *map) { return SString(); }
 
-virtual ~GenoConverter() {}
-/// Don't forget to set public fields in your constructor
-GenoConverter():name(""),in_format(-1),out_format('0'),info(""),enabled(1),mapsupport(0) {}
+	virtual ~GenoConverter() {}
+	/// Don't forget to set public fields in your constructor
+	GenoConverter() :name(""), in_format(-1), out_format('0'), info(""), enabled(1), mapsupport(0) {}
 };
 
@@ -71,27 +71,25 @@
 class GenoConvManager
 {
-friend class GenoConvParam;
-SList converters;
+	friend class GenoConvParam;
+	SList converters;
 public:
-GenoConvManager();
-~GenoConvManager();
-class GenoConvParam param;
-/// make a genotype in other format. genotype will be invalid
-/// if GenoConvManager cannot convert it.
-Geno convert(Geno &in,char format,MultiMap *map=0);
-/// register GenoConverter, the added object will be automatically deleted when GenoConvManager is destructed (call removeConverter() if this is not desirable)
-void addConverter(GenoConverter *conv);
-/// unregister GenoConverter
-void removeConverter(GenoConverter *conv);
+	GenoConvManager();
+	~GenoConvManager();
+	class GenoConvParam param;
+	/// make a genotype in other format. genotype will be invalid
+	/// if GenoConvManager cannot convert it.
+	Geno convert(Geno &in, char format, MultiMap *map = 0, bool *converter_missing = NULL);
+	/// register GenoConverter, the added object will be automatically deleted when GenoConvManager is destructed (call removeConverter() if this is not desirable)
+	void addConverter(GenoConverter *conv);
+	/// unregister GenoConverter
+	void removeConverter(GenoConverter *conv);
 
-char *getPath(char in,char out,char *path,int maxlen,int *mapavailable=0);
-char *getFormatPath(char in,char out,char *path,int maxlen,int *mapavailable=0);
-/// returns the list of converters meeting the specified criteria
-/// pass result=0 if you only need one result (by return value)
-/// default criteria values mean "don't care", pass anything else to narrow your search
-GenoConverter *findConverters(SListTempl<GenoConverter*>* result=0,char in=-1,char out=-1,int enabled=-1,char* name=0);
+	char *getPath(char in, char out, char *path, int maxlen, int *mapavailable = 0);
+	char *getFormatPath(char in, char out, char *path, int maxlen, int *mapavailable = 0);
+	/// returns the list of converters meeting the specified criteria
+	/// pass result=0 if you only need one result (by return value)
+	/// default criteria values mean "don't care", pass anything else to narrow your search
+	GenoConverter *findConverters(SListTempl<GenoConverter*>* result = 0, char in = -1, char out = -1, int enabled = -1, char* name = 0);
 };
 
 #endif
-
-
