// get the localized version of the string. if none exists, return the original string
// valid input to this function includes :
// "this is some text"
// XSTR("wheeee", -1)
// XSTR("whee", 20)
// and these should cover all the externalized string cases
// fills in id if non-NULL. a value of -2 indicates it is not an external string
void lcl_ext_localize_sub(const char *in, char *out, size_t max_len, int *id)
{
	char text_str[PARSE_BUF_SIZE]="";
	int str_id;
	size_t str_len;

	Assert(in);
	Assert(out);

	// default (non-external string) value
	if (id != NULL) {
		*id = -2;
	}

	str_len = strlen(in);

	// if the string is < 9 chars, it can't be an XSTR("",) tag, so just copy it
	if (str_len < 9) {
		if (str_len > max_len)
			error_display(0, "Token too long: [%s].  Length = %i.  Max is %i.\n", in, str_len, max_len);

		strncpy(out, in, max_len);

		if (id != NULL)
			*id = -2;

		return;
	}

	// otherwise, check to see if it's an XSTR() tag
	if (strnicmp(in, "XSTR", 4)) {
		// NOT an XSTR() tag
		if (str_len > max_len)
			error_display(0, "Token too long: [%s].  Length = %i.  Max is %i.\n", in, str_len, max_len);

		strncpy(out, in, max_len);

		if (id != NULL)
			*id = -2;

		return;
	}

	// at this point we _know_ its an XSTR() tag, so split off the strings and id sections
	if (!lcl_ext_get_text(in, text_str)) {
		if (str_len > max_len)
			error_display(0, "Token too long: [%s].  Length = %i.  Max is %i.\n", in, str_len, max_len);

		strncpy(out, in, max_len);

		if (id != NULL)
			*id = -1;

		return;
	}
	if (!lcl_ext_get_id(in, &str_id)) {
		if (str_len > max_len)
			error_display(0, "Token too long: [%s].  Length = %i.  Max is %i.\n", in, str_len, max_len);

		strncpy(out, in, max_len);

		if (id != NULL)
			*id = -1;

		return;
	}
	
	// if the localization file is not open, or we're running in the default language, return the original string
	if ( !Xstr_inited || (str_id < 0) || (Lcl_current_lang == FS2_OPEN_DEFAULT_LANGUAGE) ) {
		if ( strlen(text_str) > max_len )
			error_display(0, "Token too long: [%s].  Length = %i.  Max is %i.\n", text_str, strlen(text_str), max_len);

		strncpy(out, text_str, max_len);

		if (id != NULL)
			*id = str_id;

		return;
	}

	// get the string if it exists
	if ((str_id < LCL_MAX_STRINGS) && (Lcl_ext_str[str_id] != NULL)) {
		// copy to the outgoing string
		if ( strlen(Lcl_ext_str[str_id]) > max_len )
			error_display(0, "Token too long: [%s].  Length = %i.  Max is %i.\n", Lcl_ext_str[str_id], strlen(Lcl_ext_str[str_id]), max_len);

		strncpy(out, Lcl_ext_str[str_id], max_len);
	}
	// otherwise use what we have - probably should Int3() or assert here
	else {
		if ( strlen(text_str) > max_len )
			error_display(0, "Token too long: [%s].  Length = %i.  Max is %i.\n", text_str, strlen(text_str), max_len);

		if (str_id >= LCL_MAX_STRINGS)
			error_display(0, "Invalid XSTR ID: [%d]. (Must be less than %d.)\n", str_id, LCL_MAX_STRINGS);

		strncpy(out, text_str, max_len);
	}

	// set the id #
	if (id != NULL) {
		*id = str_id;
	}
}
// ditto for SCP_string
void lcl_ext_localize_sub(const SCP_string &in, SCP_string &out, int *id)
{
	SCP_string text_str = "";
	int str_id;

	// default (non-external string) value
	if (id != NULL) {
		*id = -2;
	}	

	// if the string is < 9 chars, it can't be an XSTR("",) tag, so just copy it
	if (in.length() < 9) {
		out = in;

		if (id != NULL)
			*id = -2;

		return;
	}

	// otherwise, check to see if it's an XSTR() tag
	if (in.compare(0, 4, "XSTR")) {
		// NOT an XSTR() tag
		out = in;

		if (id != NULL)
			*id = -2;

		return;
	}

	// at this point we _know_ its an XSTR() tag, so split off the strings and id sections		
	if (!lcl_ext_get_text(in, text_str)) {
		out = in;

		if (id != NULL)
			*id = -1;

		return;
	}
	if (!lcl_ext_get_id(in, &str_id)) {
		out = in;

		if (id != NULL)
			*id = -1;

		return;
	}
	
	// if the localization file is not open, or we're running in the default language, return the original string
	if ( !Xstr_inited || (str_id < 0) || (Lcl_current_lang == FS2_OPEN_DEFAULT_LANGUAGE) ) {
		out = text_str;

		if (id != NULL)
			*id = str_id;

		return;
	}

	// get the string if it exists
	if ((str_id < LCL_MAX_STRINGS) && (Lcl_ext_str[str_id] != NULL)) {
		// copy to the outgoing string
		out = Lcl_ext_str[str_id];
	}
	// otherwise use what we have - probably should Int3() or assert here
	else {
		if (str_id >= LCL_MAX_STRINGS)
			error_display(0, "Invalid XSTR ID: [%d]. (Must be less than %d.)\n", str_id, LCL_MAX_STRINGS);

		out = text_str;
	}

	// set the id #
	if (id != NULL){
		*id = str_id;
	}
}
// get the localized version of the string. if none exists, return the original string
// valid input to this function includes :
// "this is some text"
// XSTR("wheeee", -1)
// XSTR("whee", 20)
// and these should cover all the externalized string cases
// fills in id if non-NULL. a value of -2 indicates it is not an external string
void lcl_ext_localize_sub(char *in, char *out, int max_len, int *id)
{			
	char first_four[5];
	char text_str[PARSE_BUF_SIZE]="";
	char lookup_str[PARSE_BUF_SIZE]="";
	int str_id;	
	int str_len;	

	Assert(in);
	Assert(out);

	// default (non-external string) value
	if(id != NULL){
		*id = -2;
	}	

	str_len = strlen(in);

	// if the string is < 9 chars, it can't be an XSTR("",) tag, so just copy it
	if(str_len < 9){
		if(str_len > max_len){
			error_display(0, "Token too long: [%s].  Length = %i.  Max is %i.\n", in, str_len, max_len);
			return;
		}		
		strcpy(out, in);
		if(id != NULL){
			*id = -2;
		}
		return;
	}

	// otherwise, check to see if it's an XSTR() tag
	memset(first_four, 0, 5);
	strncpy(first_four, in, 4);
	if(stricmp(first_four, "XSTR")){
		// NOT an XSTR() tag
		if(str_len > max_len){
			error_display(0, "Token too long: [%s].  Length = %i.  Max is %i.\n", in, str_len, max_len);
			return;
		}		
		strcpy(out, in);
		if(id != NULL){
			*id = -2;
		}
		return;
	}

	// at this point we _know_ its an XSTR() tag, so split off the strings and id sections		
	if(!lcl_ext_get_text(in, text_str)){
		Int3();
		strcpy(out, in);
		if(id != NULL){
			*id = -1;
		}
		return;
	}
	if(!lcl_ext_get_id(in, &str_id)){
		strcpy(out, in);
		if(id != NULL){
			*id = -1;
		}
		return;
	}
	
	// if the localization file is not open, or we're running in the default language, return the original string
	if((Lcl_ext_file == NULL) || (str_id < 0) || (Lcl_current_lang == LCL_DEFAULT_LANGUAGE)){
		strcpy(out, text_str);
		if(id != NULL){
			*id = str_id;
		}
		return;
	}		

	// attempt to find the string
	if(lcl_ext_lookup(lookup_str, str_id)){
		// copy to the outgoing string
		Assert(strlen(lookup_str) <= (unsigned int)(max_len - 1));

		if (strlen(lookup_str) > (unsigned int)(max_len-1)) {
			// be safe and truncate string to fit
			strncpy(out, lookup_str, (size_t) (max_len-1));
			out[max_len-1] = '\0';		// ensure null terminator, since strncpy(...) doesnt.
		} else {
			strcpy(out, lookup_str);
		}

	}
	// otherwise use what we have - probably should Int3() or assert here
	else {
		strcpy(out, text_str);
	}	

	// set the id #
	if(id != NULL){
		*id = str_id;
	}
}