// <Changelog:
// * Language switching,
// March 2007:
// Initial public release, Gilles Casse <gcasse@oralux.org>
//
// >
// <includes
#include "langswitch.h"
#include <stdlib.h>
#include <string.h>
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
// >
// <decls and function prototypes

struct langInfo {
  enum ECILanguageDialect lang;
  const char *code;
  const char *encoding;
  const char *id;
  const char *label;
};

enum { LANGUAGE_MAX_LABEL = 30 };  // max size of the label field

static struct langInfo TheLanguages[] = {
    {NODEFINEDCODESET, NULL, NULL, NULL, NULL},
    {eciGeneralAmericanEnglish, "en_US", "iso8859-1", "1.0", "American"},
    {eciBritishEnglish, "en_GB", "iso8859-1", "1.1", "British"},
    {eciCastilianSpanish, "es_ES", "iso8859-1", "2.0", "Español"},
    {eciMexicanSpanish, "es_MX", "iso8859-1", "2.1", "Mexicano"},
    {eciStandardFrench, "fr_FR", "iso8859-1", "3.0", "Français"},
    {eciCanadianFrench, "fr_CA", "iso8859-1", "3.1", "Français Canadien"},
    {eciStandardGerman, "de_DE", "iso8859-1", "4.0", "Deutsch"},
    {eciStandardItalian, "it_IT", "iso8859-1", "5.0", "Italiano"},
    {eciMandarinChineseGB, "zh_CN", "gb2312", "6.0", "Chinese Simplified"},
    {eciMandarinChinesePinYin, "zh_CN", "gb2312", "6.0.1",
     "Chinese Simplified"},
    {eciMandarinChineseUCS, "zh_CN", "UCS2", "6.0.8", "Chinese Simplified"},
    {eciTaiwaneseMandarinBig5, "zh_HK", "big5", "6.1", "Chinese Traditional"},
    {eciTaiwaneseMandarinZhuYin, "zh_HK", "big5", "6.1.1",
     "Chinese Traditional"},
    {eciTaiwaneseMandarinPinYin, "zh_HK", "big5", "6.1.2",
     "Chinese Traditional"},
    {eciTaiwaneseMandarinUCS, "zh_HK", "UCS2", "6.1.8", "Chinese Traditional"},
    {eciBrazilianPortuguese, "pt_BR", "iso8859-1", "7.0",
     "Brazilian Portuguese"},
    {eciStandardJapaneseSJIS, "ja_JP", "shiftjis", "8.0", "Japanese"},
    {eciStandardJapaneseUCS, "ja_JP", "UCS2", "8.0.8", "Japanese"},
    {eciStandardFinnish, "fi_FI", "iso8859-1", "9.0", "Finnish"},
    {eciStandardKoreanUHC, NULL, NULL, NULL, NULL},
    {eciStandardKoreanUCS, NULL, NULL, NULL, NULL},
    {eciStandardCantoneseGB, NULL, NULL, NULL, NULL},
    {eciStandardCantoneseUCS, NULL, NULL, NULL, NULL},
    {eciHongKongCantoneseBig5, NULL, NULL, NULL, NULL},
    {eciHongKongCantoneseUCS, NULL, NULL, NULL, NULL},
    {eciStandardDutch, NULL, NULL, NULL, NULL},
    {eciStandardNorwegian, NULL, NULL, NULL, NULL},
    {eciStandardSwedish, NULL, NULL, NULL, NULL},
    {eciStandardDanish, NULL, NULL, NULL, NULL},
    {eciStandardReserved, NULL, NULL, NULL, NULL},
    {eciStandardThai, NULL, NULL, NULL, NULL},
    {eciStandardThaiTIS, NULL, NULL, NULL, NULL},
};

// >
// <initLanguage

enum ECILanguageDialect initLanguage(Tcl_Interp *interp,
                                     enum ECILanguageDialect *aLanguages,
                                     int nLanguages) {
  // List the available languages
  int i = 0;
  int j = 0;
  enum ECILanguageDialect aCurrentLanguage, aEnglishLanguage, aFirstLanguage;
  aCurrentLanguage = aEnglishLanguage = aFirstLanguage = NODEFINEDCODESET;
  const char *aDefaultLang = getenv("LANGUAGE");

  if (aDefaultLang == NULL) {
    aDefaultLang = getenv("LANG");
    if (aDefaultLang == NULL) {
      aDefaultLang = "en";
    }
  }
  if (strlen(aDefaultLang) < 2) {
    aDefaultLang = "en";
  }

  Tcl_SetVar2(interp, "langsynth", "current", "0", 0);

  for (i = 0; i < LANG_INFO_MAX; i++) {
    if ((TheLanguages[i].code) != NULL) {
      char buffer_i[3];
      snprintf(buffer_i, 3, "%d", i);
      char command[40];
      sprintf(command, "set langalias(%s)  %s\n",
              const_cast<char *>(TheLanguages[i].code), buffer_i);
      Tcl_Eval(interp, command);
    }
  }

  int aCurrentLangIndex = 0;
  int aEnglishLangIndex = 0;
  int aFirstLangIndex = 0;

  for (i = 0; i < nLanguages; i++) {
    int aLang = 0;
    char buffer_i[3];
    char buffer_j[3];
    for (aLang = 0; aLang < LANG_INFO_MAX; aLang++) {
      if (TheLanguages[aLang].lang == aLanguages[i]) break;
    }

    if ((aLang == LANG_INFO_MAX) || (TheLanguages[aLang].code == NULL)) {
      continue;
    }

    snprintf(buffer_i, 3, "%d", MIN(aLang, LANG_INFO_MAX));
    snprintf(buffer_j, 3, "%d", MIN(j, LANG_INFO_MAX));
    j++;
    Tcl_SetVar2(interp, "langsynth", buffer_j, buffer_i, 0);

    if (aCurrentLanguage == NODEFINEDCODESET) {
      if (strncmp(aDefaultLang, TheLanguages[aLang].code, 2) == 0) {
        aCurrentLanguage = TheLanguages[aLang].lang;
        aCurrentLangIndex = aLang;
      } else if (strncmp("en", TheLanguages[aLang].code, 2) == 0) {
        aEnglishLanguage = TheLanguages[aLang].lang;
        aEnglishLangIndex = aLang;
      } else if (j == 1) {
        aFirstLanguage = TheLanguages[aLang].lang;
        aFirstLangIndex = aLang;
      }
    }
    Tcl_SetVar2(interp, "langlabel", buffer_j,
                const_cast<char *>(TheLanguages[aLang].label), 0);
    Tcl_SetVar2(interp, "langsynth", "top", buffer_j, 0);
  }

  if (aCurrentLanguage == NODEFINEDCODESET) {
    if (aEnglishLanguage != NODEFINEDCODESET) {
      aCurrentLangIndex = aEnglishLangIndex;
      aCurrentLanguage = aEnglishLanguage;
    } else if (aFirstLanguage != NODEFINEDCODESET) {
      aCurrentLangIndex = aFirstLangIndex;
      aCurrentLanguage = aFirstLanguage;
    }
  }

  if (aCurrentLanguage != NODEFINEDCODESET) {
    char buffer_i[3];
    snprintf(buffer_i, 3, "%d", MIN(aCurrentLangIndex, LANG_INFO_MAX));
    Tcl_SetVar2(interp, "langsynth", "current", buffer_i, 0);
  }

  return aCurrentLanguage;
}
// >
// <getAnnotation

const char *getAnnotation(Tcl_Interp *interp, int *theIndex) {
  const char *code = NULL;
  const char *aInfo = Tcl_GetVar2(interp, "langsynth", "current", 0);

  if (aInfo) {
    *theIndex = atoi(aInfo);
    if ((*theIndex > 0) && (*theIndex < LANG_INFO_MAX)) {
      code = TheLanguages[*theIndex].id;
    }
  }
  return code;
}

// >
// <convertFromUTF8

char *convertFromUTF8(Tcl_Interp *interp, const char *src) {
  char *dest = NULL;

  if (interp && src) {
    int srcLen = -1;
    int aLength = 2 * strlen(src) + 1;
    dest = new char[aLength];
    int srcReadPtr = 0;
    int destWrotePtr = 0;
    int destCharsPtr = 0;
    int aIndex = 0;

    const char *aEncoding = "iso8859-1";
    if (getAnnotation(interp, &aIndex)) {
      aEncoding = TheLanguages[aIndex].encoding;
    }

    // Characters are converted from utf-8 to the expected encoding
    Tcl_Encoding encoding = Tcl_GetEncoding(interp, aEncoding);
    Tcl_UtfToExternal(interp, encoding, src, srcLen, 0, NULL, dest, aLength,
                      &srcReadPtr, &destWrotePtr, &destCharsPtr);
  }
  return dest;
}

// >
// <end of file
// local variables:
// folded-file: t
// end:
// >
