Files correlati : librerie Ricompilazione Demo : [ ] Commento : diction.cpp: aggiunto logging delle frasi non tradotte isam.cpp: aggiunti commenti e migliorati prompt delle importazioni reprint.cpp: aggiunti commenti git-svn-id: svn://10.65.10.50/trunk@14325 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			361 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			361 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
/*
 | 
						|
<dictionary>
 | 
						|
  <entry>
 | 
						|
     <ita>Attezione: premere OK per cancellare</ita>
 | 
						|
     <eng>Atension: pres ochei to dilit</eng>
 | 
						|
     <src>ba1.exe</src>
 | 
						|
     <max>40</max>
 | 
						|
  </entry>
 | 
						|
</dictionary>
 | 
						|
*/
 | 
						|
#include <xvt.h>
 | 
						|
 | 
						|
#include <config.h>
 | 
						|
#include <diction.h>
 | 
						|
#include <netsock.h>
 | 
						|
#include <scanner.h>
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// Utility di conversione
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
TString& txt2xml(const TString& str)
 | 
						|
{
 | 
						|
  TString& tmp = get_tmp_string();
 | 
						|
  for (int i = 0; str[i]; i++)
 | 
						|
  {
 | 
						|
    if (str[i] < ' ' || str[i] > 'z' || strchr("&<>/", str[i]) != NULL)
 | 
						|
    {
 | 
						|
      TString8 code;
 | 
						|
      code.format("&#%X;", (int)(unsigned char)(str[i]));
 | 
						|
      tmp << code;
 | 
						|
    }
 | 
						|
    else
 | 
						|
      tmp << str[i];
 | 
						|
  }
 | 
						|
  return tmp;
 | 
						|
}
 | 
						|
 | 
						|
TString& xml2txt(const TString& str)
 | 
						|
{
 | 
						|
  TString& tmp = get_tmp_string();
 | 
						|
  for (int i = 0; str[i]; i++)
 | 
						|
  {
 | 
						|
    if (str[i] == '&' && str[i+1] == '#')
 | 
						|
    {
 | 
						|
      i += 2;
 | 
						|
      const int semicolon = str.find(';', i);
 | 
						|
      if (semicolon > 0)
 | 
						|
      {
 | 
						|
        int n;
 | 
						|
        sscanf(str.sub(i, semicolon), "%X", &n);
 | 
						|
        tmp << char(n & 0xFF);
 | 
						|
        i = semicolon;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    else
 | 
						|
      tmp << str[i];
 | 
						|
  }
 | 
						|
  return tmp;
 | 
						|
}
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// TTraduttore
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
class TTraduttore : public TCache
 | 
						|
{
 | 
						|
	TString _str;
 | 
						|
  TSocketClient _client;
 | 
						|
	CONNID _connection;
 | 
						|
   
 | 
						|
protected:
 | 
						|
	virtual TObject* key2obj(const char* key);
 | 
						|
 | 
						|
public:
 | 
						|
	bool active() const { return _connection != 0; }
 | 
						|
	const char* translate(const char* sentence);
 | 
						|
	TTraduttore();
 | 
						|
	virtual ~TTraduttore();
 | 
						|
};
 | 
						|
 | 
						|
TObject* TTraduttore::key2obj(const char* key)
 | 
						|
{
 | 
						|
  const char* const prefix = "<sentence>";
 | 
						|
  const char* const posfix = "</sentence>";
 | 
						|
 | 
						|
	_str.cut(0);
 | 
						|
	_str << "<m:Translate>\n"
 | 
						|
			 << prefix << txt2xml(key) << posfix << '\n'
 | 
						|
	     << "</m:Translate>\n";
 | 
						|
 | 
						|
	if (_client.HttpSoap(_connection, _str))
 | 
						|
	{
 | 
						|
		_str.cut(0);
 | 
						|
		size_t size;
 | 
						|
		const TFixed_string buf((const char*)_client.GetBuffer(size));
 | 
						|
		int start = buf.find("<sentence");
 | 
						|
		if (start > 0)
 | 
						|
			start = buf.find('>', start+1)+1;
 | 
						|
		if (start > 0)
 | 
						|
		{
 | 
						|
			const int stop = buf.find('<', start);
 | 
						|
			if (stop > 0)
 | 
						|
				_str = xml2txt(buf.sub(start, stop));
 | 
						|
		}
 | 
						|
    // _client.ReleaseBuffer();  // Non perdiamo tempo in 'ste cose
 | 
						|
	}
 | 
						|
	else
 | 
						|
		return NULL;
 | 
						|
 | 
						|
	return _str.dup();
 | 
						|
}
 | 
						|
 | 
						|
const char* TTraduttore::translate(const char* sentence)
 | 
						|
{
 | 
						|
	if (sentence && *sentence && active())
 | 
						|
	{
 | 
						|
		for (int i = 0; sentence[i]; i++)  
 | 
						|
		{
 | 
						|
			if (isalpha(sentence[i]))
 | 
						|
			{
 | 
						|
				TString* trans = (TString*)objptr(sentence);
 | 
						|
				if (trans != NULL && trans->not_empty())
 | 
						|
					return (const char*) *trans;
 | 
						|
				break;
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return sentence;
 | 
						|
}
 | 
						|
 | 
						|
TTraduttore::TTraduttore() : _connection(0)
 | 
						|
{
 | 
						|
  TConfig ini(CONFIG_INSTALL, "Server");
 | 
						|
  const TString& server = ini.get("Dictionary");
 | 
						|
  if (server.not_empty())
 | 
						|
	  _connection = _client.QueryConnection("3883", server);
 | 
						|
}
 | 
						|
 | 
						|
TTraduttore::~TTraduttore()
 | 
						|
{
 | 
						|
	// Autoclose connection
 | 
						|
}
 | 
						|
 | 
						|
static TTraduttore* _DevotoOli = NULL;
 | 
						|
 | 
						|
const char* dictionary_translate(const char* sentence)
 | 
						|
{
 | 
						|
 if (_DevotoOli == NULL)
 | 
						|
    _DevotoOli = new TTraduttore;
 | 
						|
  return _DevotoOli->translate(sentence);
 | 
						|
}
 | 
						|
 | 
						|
const char* dictionary_translate_macro(const char* sentence)
 | 
						|
{
 | 
						|
#ifdef WIN32
 | 
						|
	if (memcmp(sentence, TO_BE_TRANSLATED, 4) == 0)
 | 
						|
    sentence = dictionary_translate(sentence+4);
 | 
						|
#else
 | 
						|
  sentence = dictionary_translate(sentence);
 | 
						|
#endif
 | 
						|
	return sentence;
 | 
						|
}
 | 
						|
 | 
						|
char strip_accelerator(TString& str)
 | 
						|
{
 | 
						|
	char tilde= '\0';
 | 
						|
	for (int i = 0; str[i]; i++)
 | 
						|
	{
 | 
						|
		if (str[i] == '~' || str[i] == '&')
 | 
						|
		{
 | 
						|
			tilde = str[i+1];
 | 
						|
			str.strip("~&");
 | 
						|
		  break;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return tilde;
 | 
						|
}
 | 
						|
 | 
						|
void restore_accelerator(TString& str, char acc, char tilde)
 | 
						|
{
 | 
						|
	if (acc > ' ')
 | 
						|
	{
 | 
						|
		int newtilde = 0;
 | 
						|
		for (int m = 0; str[m]; m++)
 | 
						|
		{
 | 
						|
			if (toupper(str[m]) == acc)
 | 
						|
			{
 | 
						|
				newtilde = m;
 | 
						|
				break;
 | 
						|
			}
 | 
						|
		}
 | 
						|
		const char s[2] = { tilde, '\0' };
 | 
						|
		str.insert(s, newtilde);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// len - Effect
 | 
						|
//  -1 - No length limit
 | 
						|
//   0 - Exactly same lenght as original
 | 
						|
//  >0 - Maximum specified length
 | 
						|
const char* dictionary_translate_prompt(const char* prompt, int maxlen)
 | 
						|
{
 | 
						|
	if (prompt && *prompt && dictionary_active())
 | 
						|
	{
 | 
						|
		TString& str = get_tmp_string();
 | 
						|
		str = prompt;
 | 
						|
 | 
						|
    int prefixlen = 0;
 | 
						|
		if (str[0] == '@')
 | 
						|
      prefixlen = 2; else
 | 
						|
		if (str[0] == '$')
 | 
						|
      prefixlen = 6;
 | 
						|
		TString8 prefix;
 | 
						|
    if (prefixlen > 0)
 | 
						|
    {
 | 
						|
      prefix = str.left(prefixlen);
 | 
						|
      str = str.mid(prefixlen);    
 | 
						|
    }
 | 
						|
		
 | 
						|
		const char matilde = strip_accelerator(str);  // Ricorda tasto rapido
 | 
						|
    
 | 
						|
		const int oldlen = str.len(); // Memorizza vecchia lunghezza
 | 
						|
		str = dictionary_translate(str);
 | 
						|
		if (maxlen >= 0)
 | 
						|
		{
 | 
						|
			const int limit = maxlen == 0 ? oldlen : maxlen;
 | 
						|
			if (str.len() > limit)
 | 
						|
			{
 | 
						|
				// Abbrevio all'ultima consonante
 | 
						|
				int i;
 | 
						|
				
 | 
						|
				for (i = limit-2; i > 0; i--)
 | 
						|
				{
 | 
						|
					if (strchr("aeiou", str[i]) == NULL)
 | 
						|
					{
 | 
						|
						str.cut(i+1);
 | 
						|
						str << '.';
 | 
						|
						break;
 | 
						|
					}
 | 
						|
				}
 | 
						|
				if (i <= 0)
 | 
						|
					str.cut(limit);
 | 
						|
			}
 | 
						|
			if (maxlen == 0 && str.len() < limit)
 | 
						|
				str.left_just(limit);
 | 
						|
		}
 | 
						|
		restore_accelerator(str, matilde, '~');
 | 
						|
		str.insert(prefix);
 | 
						|
 | 
						|
		return str;
 | 
						|
	}
 | 
						|
	return prompt;
 | 
						|
}
 | 
						|
 | 
						|
const char* dictionary_translate_macro_prompt(const char* sentence, int maxlen)
 | 
						|
{
 | 
						|
#ifdef WIN32
 | 
						|
	if (memcmp(sentence, TO_BE_TRANSLATED, 4) == 0)
 | 
						|
    sentence = dictionary_translate_prompt(sentence+4, maxlen);
 | 
						|
#else
 | 
						|
  sentence = dictionary_translate_prompt(sentence, maxlen);
 | 
						|
#endif
 | 
						|
	return sentence;
 | 
						|
}
 | 
						|
 | 
						|
const char* dictionary_translate_header(const char* head)
 | 
						|
{
 | 
						|
	if (head && *head && dictionary_active())
 | 
						|
	{
 | 
						|
		const TFixed_string str(head);
 | 
						|
		const int at = str.rfind('@');
 | 
						|
		if (at >= 0)
 | 
						|
		{
 | 
						|
			TString& tmp = get_tmp_string();
 | 
						|
  		tmp = dictionary_translate(str.left(at));
 | 
						|
			tmp << str.mid(at);
 | 
						|
			return tmp;
 | 
						|
		}
 | 
						|
		
 | 
						|
		if (str.ends_with(" "))
 | 
						|
			return dictionary_translate_prompt(head);
 | 
						|
		
 | 
						|
		return dictionary_translate(head);
 | 
						|
	}
 | 
						|
	return head;
 | 
						|
}
 | 
						|
 | 
						|
const char* dictionary_translate_macro_header(const char* head)
 | 
						|
{
 | 
						|
#ifdef WIN32
 | 
						|
	if (memcmp(head, TO_BE_TRANSLATED, 4) == 0)
 | 
						|
    head = dictionary_translate_header(head+4);
 | 
						|
#else    
 | 
						|
  head = dictionary_translate_header(head);
 | 
						|
#endif
 | 
						|
	return head;
 | 
						|
}
 | 
						|
 | 
						|
const char* dictionary_translate_menu_item(const char* text)
 | 
						|
{
 | 
						|
	TString& str = get_tmp_string();
 | 
						|
	str = text;
 | 
						|
	const char matilde = strip_accelerator(str);
 | 
						|
 | 
						|
	TString16 posfix;
 | 
						|
  int start = str.find('\t');
 | 
						|
	if (start < 0)
 | 
						|
		start = str.find("...");
 | 
						|
	if (start > 0)
 | 
						|
	{
 | 
						|
		posfix = str.mid(start);
 | 
						|
	  str.cut(start);
 | 
						|
	}
 | 
						|
 | 
						|
	const char* newtext = dictionary_translate(str);
 | 
						|
	if (str != newtext)
 | 
						|
	{
 | 
						|
    str = newtext;
 | 
						|
		restore_accelerator(str, matilde, '&');
 | 
						|
		if (posfix.not_empty())
 | 
						|
			str << posfix;
 | 
						|
  	return str;
 | 
						|
	}
 | 
						|
	return text;
 | 
						|
}
 | 
						|
 | 
						|
void dictionary_translate_menu(MENU_ITEM* menu)
 | 
						|
{
 | 
						|
  if (menu && dictionary_active()) for (int m = 0; menu[m].tag != 0; m++)
 | 
						|
	{
 | 
						|
		MENU_ITEM& mi = menu[m];
 | 
						|
		if (!mi.separator)
 | 
						|
		{
 | 
						|
			const char* newtext = dictionary_translate_menu_item(mi.text);
 | 
						|
  		if (strlen(newtext) > strlen(mi.text))  // Posso sovrascrivere?
 | 
						|
 			  mi.text = xvt_mem_realloc(mi.text, strlen(newtext)+1);
 | 
						|
  	  strcpy(mi.text, newtext);
 | 
						|
			if (mi.child)
 | 
						|
				dictionary_translate_menu(mi.child);
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
bool dictionary_active()
 | 
						|
{
 | 
						|
  return _DevotoOli != NULL && _DevotoOli->active(); 
 | 
						|
}
 | 
						|
 | 
						|
void dictionary_close()
 | 
						|
{
 | 
						|
  if (_DevotoOli != NULL)
 | 
						|
	{
 | 
						|
		delete _DevotoOli;
 | 
						|
		_DevotoOli = NULL;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 |