Juergen Spitzmueller wrote:
>> I've written a little test program (attached) that I think achieves
>> this. Could you have a look?
> 
> Neat. AFAICS it does just what we want.

Here's the patch against cvs. Committing now...

-- 
Angus
Index: src/frontends/controllers/ChangeLog
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/frontends/controllers/ChangeLog,v
retrieving revision 1.442
diff -u -p -r1.442 ChangeLog
--- src/frontends/controllers/ChangeLog	14 May 2004 13:13:19 -0000	1.442
+++ src/frontends/controllers/ChangeLog	14 May 2004 15:24:40 -0000
@@ -1,5 +1,11 @@
 2004-05-14  Angus Leeming  <[EMAIL PROTECTED]>
 
+	* biblio.[Ch] (asValidLatexCommand): new function which examines
+	the input string to return a latex citation command that is
+	valid for the current citation engine.
+
+2004-05-14  Angus Leeming  <[EMAIL PROTECTED]>
+
 	* ControlCitation.[Ch]: small changes to use the CiteEngine_enum
 	wrapper class.
 
Index: src/frontends/controllers/biblio.C
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/frontends/controllers/biblio.C,v
retrieving revision 1.65
diff -u -p -r1.65 biblio.C
--- src/frontends/controllers/biblio.C	14 May 2004 13:13:19 -0000	1.65
+++ src/frontends/controllers/biblio.C	14 May 2004 15:24:41 -0000
@@ -30,6 +30,7 @@ using lyx::support::compare_ascii_no_cas
 using lyx::support::contains;
 using lyx::support::getVectorFromString;
 using lyx::support::ltrim;
+using lyx::support::prefixIs;
 using lyx::support::rtrim;
 using lyx::support::split;
 using lyx::support::subst;
@@ -42,6 +43,113 @@ using std::vector;
 
 
 namespace biblio {
+
+namespace {
+
+vector<string> const init_possible_cite_commands()
+{
+	char const * const pos[] = {
+		"cite",
+		"citet", "citep", "citealt", "citealp",
+		"citeauthor", "citeyear", "citeyearpar",
+		"citet*", "citep*", "citealt*", "citealp*", "citeauthor*",
+		"Citet",  "Citep",  "Citealt",  "Citealp",  "Citeauthor",
+		"Citet*", "Citep*", "Citealt*", "Citealp*", "Citeauthor*",
+		"fullcite",
+		"footcite", "footcitet", "footcitep", "footcitealt",
+		"footcitealp", "footciteauthor", "footciteyear",
+		"footciteyearpar",
+		"citefield",
+		"citetitle",
+		"cite*"
+	};
+	size_t const size_pos = sizeof(pos) / sizeof(pos[0]);
+
+	return vector<string>(pos, pos + size_pos);
+}
+
+
+vector<string> const & possible_cite_commands()
+{
+	static vector<string> const pos = init_possible_cite_commands();
+	return pos;
+}
+
+
+bool is_possible_cite_command(string const & input)
+{
+	vector<string> const & possibles = possible_cite_commands();
+	vector<string>::const_iterator const end = possibles.end();
+	return std::find(possibles.begin(), end, input) != end;
+}
+
+
+string const default_cite_command(CiteEngine engine)
+{
+	string str;
+	switch (engine) {
+	case ENGINE_BASIC:
+		str = "cite";
+		break;
+	case ENGINE_NATBIB_AUTHORYEAR:
+		str = "citet";
+		break;
+	case ENGINE_NATBIB_NUMERICAL:
+		str = "citep";
+		break;
+	case ENGINE_JURABIB:
+		str = "cite";
+		break;
+	}
+	return str;
+}
+
+} // namespace anon
+
+
+string const asValidLatexCommand(string const & input,
+				 CiteEngine_enum const & engine)
+{
+	string const default_str = default_cite_command(engine);
+	if (!is_possible_cite_command(input))
+		return default_str;
+
+	string output;
+	switch (engine) {
+	case ENGINE_BASIC:
+		output = default_str;
+		break;
+
+	case ENGINE_NATBIB_AUTHORYEAR:
+	case ENGINE_NATBIB_NUMERICAL:
+		if (input == "cite" || input == "citefield" ||
+		    input == "citetitle" || input == "cite*")
+			output = default_str;
+		else if (prefixIs(input, "foot"))
+			output = input.substr(4);
+		else
+			output = input;
+		break;
+
+	case ENGINE_JURABIB: {
+		// Jurabib does not support the 'uppercase' natbib style.
+		if (input[0] == 'C')
+			output = string(1, 'c') + input.substr(1);
+		else
+			output = input;
+
+		// Jurabib does not support the 'full' natbib style.
+                string::size_type const n = output.size() - 1;
+                if (output != "cite*" && output[n] == '*')
+                        output = output.substr(0, n);
+
+		break;
+	}
+	}
+
+	return output;
+}
+
 
 string const familyName(string const & name)
 {
Index: src/frontends/controllers/biblio.h
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/frontends/controllers/biblio.h,v
retrieving revision 1.20
diff -u -p -r1.20 biblio.h
--- src/frontends/controllers/biblio.h	14 May 2004 13:13:19 -0000	1.20
+++ src/frontends/controllers/biblio.h	14 May 2004 15:24:41 -0000
@@ -49,6 +49,14 @@ enum Direction {
 	BACKWARD
 };
 
+
+/** Each citation engine recognizes only a subset of all possible
+ *  citation commands. Given a latex command \c input, this function
+ *  returns an appropriate command, valid for \c engine.
+ */
+std::string const asValidLatexCommand(std::string const & input,
+				      CiteEngine_enum const & engine);
+
 /// First entry is the bibliography key, second the data
 typedef std::map<std::string, std::string> InfoMap;
 
Index: src/insets/ChangeLog
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/insets/ChangeLog,v
retrieving revision 1.1015
diff -u -p -r1.1015 ChangeLog
--- src/insets/ChangeLog	13 May 2004 20:44:35 -0000	1.1015
+++ src/insets/ChangeLog	14 May 2004 15:24:48 -0000
@@ -1,3 +1,8 @@
+2004-05-14  Angus Leeming  <[EMAIL PROTECTED]>
+
+	* insetcite.C (getNatbibLabel, generateLabel, latex): use the
+	new biblio::asValidLatexString function.
+
 2004-05-12  Angus Leeming  <[EMAIL PROTECTED]>
 
 	* insetcite.C: use BufferParams::cite_engine rather than the three
Index: src/insets/insetcite.C
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/insets/insetcite.C,v
retrieving revision 1.82
diff -u -p -r1.82 insetcite.C
--- src/insets/insetcite.C	14 May 2004 13:13:20 -0000	1.82
+++ src/insets/insetcite.C	14 May 2004 15:24:48 -0000
@@ -80,12 +80,11 @@ string const getNatbibLabel(Buffer const
 	// CITE:	author/<before field>
 
 	// We don't currently use the full or forceUCase fields.
-	// bool const forceUCase = citeType[0] == 'C';
-	bool const full = citeType[citeType.size() - 1] == '*';
-
-	string const cite_type = full ?
-		ascii_lowercase(citeType.substr(0, citeType.size() - 1)) :
-		ascii_lowercase(citeType);
+	string cite_type = biblio::asValidLatexCommand(citeType, engine);
+	if (cite_type[0] == 'C')
+		cite_type = string(1, 'c') + cite_type.substr(1);
+	if (cite_type[cite_type.size() - 1] == '*')
+		cite_type = cite_type.substr(0, cite_type.size() - 1);
 
 	string before_str;
 	if (!before.empty()) {
@@ -270,19 +269,7 @@ string const InsetCitation::generateLabe
 	string label;
 	biblio::CiteEngine const engine = buffer.params().cite_engine;
 	if (engine != biblio::ENGINE_BASIC) {
-		string cmd = getCmdName();
-		if (cmd == "cite") {
-			// We may be "upgrading" from an older LyX version.
-			// If, however, we use "cite" because the necessary
-			// author/year info is not present in the biblio
-			// database, then getNatbibLabel will exit gracefully
-			// and we'll call getBasicLabel.
-			if (engine == biblio::ENGINE_NATBIB_NUMERICAL)
-				cmd = "citep";
-			else if (engine == biblio::ENGINE_NATBIB_AUTHORYEAR)
-				cmd = "citet";
-		}
-		label = getNatbibLabel(buffer, cmd, getContents(),
+		label = getNatbibLabel(buffer, getCmdName(), getContents(),
 				       before, after, engine);
 	}
 
@@ -343,30 +330,10 @@ int InsetCitation::latex(Buffer const & 
 			 OutputParams const &) const
 {
 	biblio::CiteEngine const cite_engine = buffer.params().cite_engine;
+	string const cite_str =
+		biblio::asValidLatexCommand(getCmdName(), cite_engine);
 	
-	os << "\\";
-	switch (cite_engine) {
-	case biblio::ENGINE_BASIC:
-		os << "cite";
-		break;
-	case biblio::ENGINE_NATBIB_AUTHORYEAR:
-	case biblio::ENGINE_NATBIB_NUMERICAL:
-		os << getCmdName();
-		break;
-	case biblio::ENGINE_JURABIB: 
-	{
-		// jurabib does not (yet) support "force upper case"
-		// and "full author name". Fallback.
-		string cmd = getCmdName();
-		if (cmd[0] == 'C')
-			cmd[0] = 'c';
-		size_t n = cmd.size() - 1;
-		if (cmd[n] == '*')
-			cmd = cmd.substr(0,n);
-		os << cmd;
-		break;
-	}
-	}
+	os << "\\" << cite_str;
 	
 	string const before = getSecOptions();
 	string const after  = getOptions();

Reply via email to