Logo Search packages:      
Sourcecode: bayonne version File versions  Download package

french.cpp

// Copyright (C) 2000 Open Source Telecom Corporation.
//  
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software 
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

#include <bayonne.h>
#include <cc++/strchar.h>
#ifdef      HAVE_SSTREAM
#include <sstream>
#else
#include <strstream>
#endif

#ifdef      HAVE_SSTREAM
#define     strstream   ostringstream
#endif

#ifdef      CCXX_NAMESPACES
namespace ost {
using namespace std;
#endif

class FrenchTranslator : public Translator
{
private:
      char *getName(void)
            {return "french";};
public:
      FrenchTranslator();
      char *speak(Trunk *trunk);
} french;

FrenchTranslator::FrenchTranslator() :
Translator("/bayonne/french")
{
      slog(Slog::levelDebug) << "TTS: loading french phrasebooks..." << endl;
}

static void spell(strstream *s, const char *text);

static int lownumber(strstream *s, int num, bool andfix)
{
      int last = num;
      bool andrule = false;

      if(num >= 100)
      {
            *s << ',' << num / 100 << ",hundred";
            num %= 100;
            andfix = false;
            if(!num)
                  return 100;
      }
      if(num >= 80)
      {
            andrule = andfix;
            *s << ",80";
            num -= 80;
            last = 80;
      }
      if(num >= 60)
      {
            andrule = andfix;
            *s << ",60";
            num -= 60;
            last = 60;
      }
      if(num >= 20)
      {
            andrule = andfix;
            *s << ',' << (num / 10) * 10;
            last = (num / 10) * 10;
            num -= last;
      }
      if(num > 16)
      {
            *s << ",10";
            num -= 10;
            last = 10;
      }
      if(num)
      {
            if(num == 1 && andrule)
                  *s << ",and";
            last = num;
            *s << "," << num;
      }
      return last;
}

static void order(strstream *s, int num)
{
      int last;

      if(!num)
            return;

      if(num == 1)
      {
            *s << ",1st";
            return;
      }
      last = lownumber(s, num, false);    
      switch(last)
      {
      case 1:     // last spoke 1 as in 21, 31, etc...
            *s << ",uniemi";
            break;
      case 7:
      case 8:
      case 20:
      case 30:
      case 40:
      case 50:
      case 60:
      case 80:
      case 100:
            *s << ",tiemi";
            break;
      case 4:
      case 5:
      case 9:
      case 1000:
            *s << ",iemi";
            break;
      default:
            *s << ",ziemi";
            break;
      }
}

static bool number(strstream *s, const char *text)
{
      unsigned long num;
      bool zero = false;

      if(!text)
            return true;

      if(!*text)
            return true;

      if(*text == '-')
      {
            *s << ",negative";
            ++text; 
      }
      num = atol(text);
      if(num > 999999999)
      {
            zero = true;
            lownumber(s, num / 1000000000, false);
            *s << ",billion";
            num %= 1000000000;
      }
      if(num > 999999)
      {
            zero = true;
            lownumber(s, num / 1000000, false);
            *s << ",million";
            num %= 1000000;
      }
      if(num > 999)
      {
            zero = true;
            lownumber(s, num / 1000, false);
            *s << ",thousand";
            num %= 1000;
      }
      if(num || zero)
            lownumber(s, num, true);

      if(num)
            zero = false;

      text = strchr(text, '.');
      if(!text)
            return zero;
      *s << ",point";
      spell(s, ++text);
      return false;
}

static void spell(strstream *s, const char *text)
{
      char ch;
      if(!text)
            return;


      while((ch = *(text++)))
      {
            if(ch >= 'A' && ch <= 'Z')
                  ch += 32;

            if(ch >= '0' && ch <= '9')
                  *s << ',' << ch;
            else if(ch >= 'a' && ch <= 'z')
                  *s << ',' << ch;
            else if(ch == '.')
                  *s << ",point";
      }
}

static void sayweekday(strstream *s, const char *text)
{
      static char *days[] = {
            "sunday", "monday", "tuesday", "wednesday", "thursday",
            "friday", "saturday"};

        time_t cl;
        struct tm *ti;
      int month, day, year;

        time(&cl);
        ti = localtime (&cl);

      if(text[2] == '/')
            sscanf(text, "%02d/%02d/%04d", &month, &day, &year);
      else if(text[2] == '.')
            sscanf(text, "%02d.%02d.%04d", &day, &month, &year);
      else if(text[4] == '-')
            sscanf(text, "%04d-%02d-%02d", &year, &month, &day);
      else
            sscanf(text, "%04d%02d%02d", &year, &month, &day);

      ti->tm_year = year;
      ti->tm_mon = month - 1;
      ti->tm_mday = day;

        if(ti->tm_year > 1000) 
            ti->tm_year -= 1900;

        mktime(ti);
      *s << ',' << days[ti->tm_wday];
}

static void saydate(strstream *s, const char *text)
{
      static char *months[] = {
            "january", "februrary", "march", "april",
            "may", "june", "july", "august",
            "september", "october", "november", "december"};

      time_t now;
      struct tm *dt;
      time(&now);
      dt = localtime(&now);
      int month, day, year;
      char buf[5];

      if(text[2] == '/')
            sscanf(text, "%02d/%02d/%04d", &month, &day, &year);
      else if(text[2] == '.')
            sscanf(text, "%02d.%02d.%04d", &day, &month, &year);
      else if(text[4] == '-')
            sscanf(text, "%04d-%02d-%02d", &year, &month, &day);
      else
            sscanf(text, "%04d%02d%02d", &year, &month, &day);

      --month;
      if(dt->tm_year < 1000)
            dt->tm_year += 1900;
      if(month == dt->tm_mon && day == dt->tm_mday && year == dt->tm_year)
      {
            *s << ",today";
            return;
      }     

      lownumber(s, day, true);
      *s << ',' << months[month];
      if(dt->tm_year == year)
            return;

      sprintf(buf, "%d", year);
      number(s, buf);
}

static char *getchange(const char *text, int dec, char *ch)
{
      int len;
      text = strchr(text, '.');
      if(!text)
            return NULL;

      ++text;
      memset(ch, '0', dec);
      ch[dec] = 0;
      len = strlen(text);
      if(len > dec)
            len = dec;
      strncpy(ch, text, len);
      return ch;
}
      
static void sayvalue(strstream *s, const char *cu, const char *ch, int dec, const char *text)
{
      char chbuf[dec + 1];
      int currency = atoi(text);
      char cbuf[11];
      char *change = getchange(text, dec, chbuf);

      if(!currency && !change)
      {
            *s << ",0," << cu << ",s";
      }

      if(currency)
      {
            sprintf(cbuf, "%d", currency);
            number(s, cbuf);
            if(currency > 1)
                  *s << ',' << cu << ",s";
            else
                  *s << ',' << cu;
      }
      if(change)
      {
            number(s, change);
            if(atoi(change) > 1)
                  *s << ',' << ch << ",s";
            else
                  *s << ',' << ch;
      }
}                 

static bool sayprimary(strstream *s, const char *text)
{
      const char *cu = keylocal.getLast("primarycurrency");
      const char *ch = keylocal.getLast("primarychange");
      const char *d = keylocal.getLast("primarydecimal");
      if(!d)
            d = "2";

      if(!cu)
            return false;

      sayvalue(s, cu, ch, atoi(d), text);
      return true;
}

static bool saylocal(strstream *s, double v, bool orflag)
{
      char tbuf[33];
      const char *cu = keylocal.getLast("localcurrency");
      const char *ch = keylocal.getLast("localchange");
      const char *d = keylocal.getLast("localdecimal");
      const char *cvt = keylocal.getLast("convertcurrency");

      if(!d)
            d = "2";

      if(!cu)
            return true;

      if(cvt)
      {
            v *= atof(cvt);
            sprintf(tbuf, "%f", v);
      }
      else
            sprintf(tbuf, "%f", v); 
      if(!v)
            return false;

      *s << ",or";
      sayvalue(s, cu, ch, atoi(d), tbuf);
      return true;
}

static void saycurrency(strstream *s, const char *text)
{
      saylocal(s, atof(text), sayprimary(s, text));
}
      
static bool sayduration(strstream *s, const char *text)
{
      int hour = 0, minute = 0, second = 0;

      if(text[2] == '.')
      {
            if(strchr(text + 3, '.'))
                  sscanf(text, "%02d.%02d.%02d",
                        &hour, &minute, &second);
            else
                  sscanf(text, "%02d.%02d",
                        &hour, &minute);
      }
      else
      {
            if(strlen(text) > 4)
                  sscanf(text, "%02d%02d%02d",
                        &hour, &minute, &second);
            else
                  sscanf(text, "%02d%02d",
                        &hour, &minute);
      }
      if(hour)
      {
            lownumber(s, hour, true);
            if(hour == 1)
                  *s << ",hour";
            else
                  *s << ",hour,s";
            if(minute || second)
                  *s << ",and";
      }
      if(minute)
      {
            lownumber(s, minute, true);
            if(minute == 1)
                  *s << ",minute";
            else
                  *s << ",minute,s";
            if(second)
                  *s << ",and";
      }
      if(second)
      {
            lownumber(s, second, true);
            if(second == 1)
                  *s << ",second";
            else
                  *s << ",second,s";
      }
      if(hour || minute || second)
            return false;
      return true;
}
            
static void saytime(strstream *s, const char *text)
{
      int hour, minute;

      if(text[2] == '%')
            sscanf(text, "%02d:%02d", &hour, &minute);
      else
            sscanf(text, "%02d%02d", &hour, &minute);

      if(hour)
            lownumber(s, hour, false);
      else
            *s << ",0";
      
      if(minute)
            lownumber(s, minute, false);
      else
            *s << ",0";
}

char *FrenchTranslator::speak(Trunk *trunk)
{
      char *pbuf = getPlayBuffer(trunk);
#ifdef      HAVE_SSTREAM
      ostringstream str;
#else
      strstream str(pbuf, 254);
#endif
      char rules[256];
      const char *rule = NULL;
      const char *phrase;
      bool skip = false;
      long lastnum = 0;
      char *text;
      ScriptImage *cmd = trunk->getImage();

      while(NULL != (rule = trunk->getValue(NULL)))
      {
            if(*rule != '&')
            {
                  str << ',' << rule;
                  continue;
            }
            phrase = getLast(rule + 1);
            if(!phrase)
            {
                  snprintf(rules, 256, "_french_%s", rule + 1);
                  phrase = cmd->getLast(rules);
            }
            if(!phrase)
            {
                  snprintf(rules, 256, "_all_%s", rule + 1);
                  phrase = cmd->getLast(rules);
            }
            if(!phrase)
                  phrase = rule;

            strncpy(rules, phrase, 254);
            rules[255] = 0;
            rule = strtok(rules, " ;,\t\n");
            while(rule)
            {
                  if(!stricmp(rule, "&exit"))
                  {
                        if(skip)
                              return NULL;
                  }
                  else if(!stricmp(rule, "&ignore") || !stricmp(rule, "&several"))
                  {
                        trunk->getValue(NULL);
                  }
                  else if(!stricmp(rule, "&use"))
                  {
                        text = trunk->getValue(NULL);
                        if(text)
                              str << ',' << text;
                  }
                  else if(!stricmp(rule, "&skip"))
                  {
                        if(skip)
                              trunk->getValue(NULL);
                  }
                  else if(!stricmp(rule, "&single") || !stricmp(rule, "&singular"))
                  {
                        text = trunk->getValue(NULL);
                        if(lastnum == 1 && !skip && text)
                              str << ',' << text;
                  }
                  else if(!stricmp(rule, "&plural"))
                  {
                        text = trunk->getValue(NULL);
                        if(lastnum != 1 && !skip && text)
                              str << ',' << text;
                  }
                  else if(!stricmp(rule, "&spell"))
                  {
                        skip = false;
                        spell(&str, trunk->getValue(""));
                  }
                  else if(!stricmp(rule, "&number"))
                  {
                        text = trunk->getValue(NULL);
                        if(text)
                        {
                              lastnum = atol(text);   
                              skip = number(&str, text);
                        }
                  }
                  else if(!stricmp(rule, "&order"))
                  {
                        skip = false;
                        text = trunk->getValue(NULL);
                        if(text)
                              order(&str, atoi(text));
                  }
                  else if(!stricmp(rule, "&time"))
                  {
                        skip = false;
                        text = trunk->getValue(NULL);
                        if(text)
                              saytime(&str, text);
                  }
                  else if(!stricmp(rule, "&duration"))
                  {
                        skip = false;
                        text = trunk->getValue(NULL);
                        if(text)
                              skip = sayduration(&str, text);
                  }
                  else if(!stricmp(rule, "&date"))
                  {
                        skip = false;
                        text = trunk->getValue(NULL);
                        if(text)
                              saydate(&str, text);
                  }
                  else if(!stricmp(rule, "&weekday"))
                  {
                        skip = false;
                        text = trunk->getValue(NULL);
                        if(text)
                              sayweekday(&str, text);
                  }
                  else if(!stricmp(rule, "&unit"))
                  {
                        skip = false;
                        text = trunk->getValue(NULL);
                        if(text)
                        {
                              lastnum = atol(text);
                              if(number(&str, text))
                                    str << ",0";
                        }
                  }
                  else if(!stricmp(rule, "&zero"))
                  {
                        skip = false;
                        text = trunk->getValue(NULL);
                        if(!lastnum && text)
                              str << ',' << text;
                  }
                  else if(!stricmp(rule, "&currency"))
                  {
                        skip = false;
                        lastnum = 1;
                        text = trunk->getValue(NULL);
                        if(text)
                        {
                              if(atof(text))
                                    saycurrency(&str, text);
                              else
                                    lastnum = 0;
                        }
                  }
                  else if(!stricmp(rule, "&primary"))
                  {
                        skip = false;
                        lastnum = 1;
                        text = trunk->getValue(NULL);
                        if(text)
                        {
                              if(atof(text))
                                    sayprimary(&str, text);
                              else
                                    lastnum = 0;
                        }
                  }
                  else if(!stricmp(rule, "&local"))
                  {
                        skip = false;
                        lastnum = 1;
                        text = trunk->getValue(NULL);
                        if(text)
                        {
                              if(!saylocal(&str, atof(text), false))
                                    lastnum = 0;
                        }
                  }
                  else 
                  {
                        skip = false;
                        str << ',' << rule;
                  }
                  rule = strtok(NULL, " ;,\t\n");
            }     
      }

#ifdef      HAVE_SSTREAM
      snprintf(pbuf, 256, "%s", str.str().c_str());
#else
      str << ends;
      pbuf[255] = 0;
#endif
      while(*pbuf)
      {
            *pbuf = tolower(*pbuf);
            ++pbuf;
      }
      return NULL;
}
      
#ifdef      CCXX_NAMESPACES
};
#endif
      
      


Generated by  Doxygen 1.6.0   Back to index