Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tw/stringtable.h"
Toshihiro Shimizu 890ddd
// #include "tw/message.h"
Toshihiro Shimizu 890ddd
//#include "tfilepath.h"
Toshihiro Shimizu 890ddd
#include "tfilepath_io.h"
Toshihiro Shimizu 890ddd
#include "tenv.h"
Toshihiro Shimizu 890ddd
//#include "texception.h"
Toshihiro Shimizu 890ddd
#include "tsystem.h"
Toshihiro Shimizu 890ddd
#include "tstream.h"
Toshihiro Shimizu 890ddd
#include "tconvert.h"
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
class TStringTableImp final : public TStringTable {
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  bool m_initialized;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  std::map<std::string, item=""> m_table;</std::string,>
Shinya Kitaoka 120a6e
  std::pair<std::string, int=""> m_defaultFontNameAndSize;</std::string,>
Shinya Kitaoka 120a6e
  std::string m_defaultMacFontName;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TStringTableImp();
Shinya Kitaoka 120a6e
  ~TStringTableImp();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  void init();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  void load(const TFilePath &);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  void loadCoded(const TFilePath &);
Shinya Kitaoka 120a6e
  void saveCoded(const TFilePath &);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 473e70
  const Item *getItem(std::string name) const override;
Shinya Kitaoka 473e70
  std::pair<std::string, int=""> getDefaultFontNameAndSize() const override {</std::string,>
Shinya Kitaoka 120a6e
    return m_defaultFontNameAndSize;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 473e70
  std::string getDefaultMacFontName() const override;
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TStringTableImp::TStringTableImp()
Shinya Kitaoka 120a6e
    : m_initialized(false)
Shinya Kitaoka 120a6e
    , m_defaultFontNameAndSize("", 0)
Shinya Kitaoka 120a6e
    , m_defaultMacFontName("") {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TStringTableImp::~TStringTableImp() {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TStringTableImp::init() {
Shinya Kitaoka 120a6e
  if (m_initialized) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_initialized = true;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TFilePath plainFp = TEnv::getConfigDir() + "current.txt";
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  try {
Shinya Kitaoka 120a6e
    load(plainFp);
Shinya Kitaoka 120a6e
  } catch (...) {
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
std::string TStringTableImp::getDefaultMacFontName() const {
Shinya Kitaoka 120a6e
  return m_defaultMacFontName;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void writeShort(Tofstream &os, int x) {
Shinya Kitaoka 120a6e
  os.put(x & 0xff);
Shinya Kitaoka 120a6e
  os.put((x >> 8) & 0xff);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int readShort(Tifstream &is) {
Shinya Kitaoka 120a6e
  char hi = 0, lo = 0;
Shinya Kitaoka 120a6e
  is.get(lo);
Shinya Kitaoka 120a6e
  is.get(hi);
Shinya Kitaoka 120a6e
  return (unsigned char)hi << 8 | (unsigned char)lo;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void writeString(Tofstream &os, std::string s) {
Shinya Kitaoka 120a6e
  int len = s.length();
Shinya Kitaoka 120a6e
  writeShort(os, len);
Shinya Kitaoka 120a6e
  os.write(s.c_str(), len);
Shinya Kitaoka 120a6e
  if (len & 0x3) {
Shinya Kitaoka 120a6e
    os.write("____", 4 - (len & 0x3));
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
std::string readString(Tifstream &is) {
Shinya Kitaoka 120a6e
  int len  = readShort(is);
Shinya Kitaoka 120a6e
  int len2 = len;
Shinya Kitaoka 120a6e
  if (len2 & 0x3) len2 += 4 - (len2 & 0x3);
Shinya Kitaoka 120a6e
  char buffer[1204];
Shinya Kitaoka 120a6e
  assert(len2 <= (int)(sizeof(buffer)));
Shinya Kitaoka 120a6e
  is.read(buffer, len2);
Shinya Kitaoka 120a6e
  return std::string(buffer, len);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void writeStringW(Tofstream &os, std::wstring s) {
Shinya Kitaoka 120a6e
  int len = s.length();
Shinya Kitaoka 120a6e
  writeShort(os, len);
Shinya Kitaoka 120a6e
  os.write(reinterpret_cast<const *="" char="">(s.c_str()), sizeof(wchar_t) * len);</const>
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
std::wstring readStringW(Tifstream &is) {
Shinya Kitaoka 120a6e
  int len = readShort(is);
Shinya Kitaoka 120a6e
  wchar_t buffer[1204];
Shinya Kitaoka 120a6e
  assert(len <= (int)(sizeof(buffer)));
Shinya Kitaoka 120a6e
  is.read(reinterpret_cast<char *="">(buffer), sizeof(wchar_t) * len);</char>
Shinya Kitaoka 120a6e
  return std::wstring(buffer, len);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
#ifdef MACOSX
Shinya Kitaoka 120a6e
class TMagic  // singleton
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  std::string m_magic;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Shinya Kitaoka 120a6e
  TMagic() : m_magic("stab.001") {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  static TMagic *instance() {
Shinya Kitaoka 120a6e
    static TMagic inst;
Shinya Kitaoka 120a6e
    ;
Shinya Kitaoka 120a6e
    return &inst;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#else
Shinya Kitaoka 3bfa54
const std::string magic = "stab.001";
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TStringTableImp::loadCoded(const TFilePath &fp) {
Shinya Kitaoka 120a6e
  try {
Shinya Kitaoka 120a6e
    Tifstream is(fp);
Shinya Kitaoka 120a6e
    char buffer[1024];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef MACOSX
Shinya Kitaoka 120a6e
    is.read(buffer, TMagic::instance()->m_magic.length());
Toshihiro Shimizu 890ddd
#else
Shinya Kitaoka 120a6e
    is.read(buffer, magic.length());
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    m_defaultFontNameAndSize.first  = readString(is);
Shinya Kitaoka 120a6e
    m_defaultFontNameAndSize.second = readShort(is);
Shinya Kitaoka 120a6e
    int count                       = readShort(is);
Shinya Kitaoka 120a6e
    for (int i = 0; i < count; i++) {
Shinya Kitaoka 120a6e
      int m = readShort(is);
Shinya Kitaoka 120a6e
      assert(1 <= m && m <= 3);
Shinya Kitaoka 120a6e
      std::string id = readString(is);
Shinya Kitaoka 120a6e
      Item &item     = m_table[id];
Shinya Kitaoka 120a6e
      item.m_name    = readStringW(is);
Shinya Kitaoka 120a6e
      if (m >= 2) {
Shinya Kitaoka 120a6e
        item.m_help            = readStringW(is);
Shinya Kitaoka 120a6e
        if (m == 3) item.m_tip = readStringW(is);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    int check = readShort(is);
Shinya Kitaoka 120a6e
    assert(check == 12345);
Shinya Kitaoka 120a6e
    // if(check != 12345)
Shinya Kitaoka 120a6e
    //  throw;
Shinya Kitaoka 120a6e
  } catch (...) {
Shinya Kitaoka 120a6e
    // TMessage::error("Error reading StringTable file: ", fp);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*
Toshihiro Shimizu 890ddd
void TStringTableImp::saveCoded(const TFilePath &fp)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
  try {
Toshihiro Shimizu 890ddd
    Tofstream os(fp);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
#ifdef MACOSX
Shinya Kitaoka 120a6e
    os.write(TMagic::instance()->m_magic.c_str(),
Shinya Kitaoka 120a6e
TMagic::instance()->m_magic.length());
Toshihiro Shimizu 890ddd
 #else
Toshihiro Shimizu 890ddd
    os.write(magic.c_str(), magic.length());
Toshihiro Shimizu 890ddd
 #endif
Toshihiro Shimizu 890ddd
    writeString(os, m_defaultFontNameAndSize.first);
Toshihiro Shimizu 890ddd
    writeShort(os, m_defaultFontNameAndSize.second);
Toshihiro Shimizu 890ddd
    writeShort(os, m_table.size());
Shinya Kitaoka 3bfa54
    for(std::map<std::string, item="">::iterator it = m_table.begin();</std::string,>
Toshihiro Shimizu 890ddd
        it != m_table.end(); ++it)
Toshihiro Shimizu 890ddd
      {
Toshihiro Shimizu 890ddd
       Item &item = it->second;
Toshihiro Shimizu 890ddd
       int m = 1;
Toshihiro Shimizu 890ddd
       if(item.m_tip != L"") m = 3;
Toshihiro Shimizu 890ddd
       else if(item.m_help != L"") m = 2;
Toshihiro Shimizu 890ddd
       writeShort(os, m);
Toshihiro Shimizu 890ddd
       writeString(os, it->first);
Toshihiro Shimizu 890ddd
       writeStringW(os, item.m_name);
Toshihiro Shimizu 890ddd
       if(m>=2)
Toshihiro Shimizu 890ddd
         {
Toshihiro Shimizu 890ddd
          writeStringW(os, item.m_help);
Shinya Kitaoka 120a6e
          if(m==3)
Shinya Kitaoka 120a6e
            writeStringW(os, item.m_tip);
Toshihiro Shimizu 890ddd
         }
Toshihiro Shimizu 890ddd
      }
Toshihiro Shimizu 890ddd
    writeShort(os, 12345);
Toshihiro Shimizu 890ddd
  } catch(...) {
Toshihiro Shimizu 890ddd
    TMessage::error("Unable to save StringTable file: ", fp);
Toshihiro Shimizu 890ddd
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TStringTableImp::load(const TFilePath &fp) {
Shinya Kitaoka 120a6e
  if (!TFileStatus(fp).doesExist()) throw TException("file not found");
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TIStream is(fp);
Shinya Kitaoka 120a6e
  if (!is) throw TException("can't read string table ");
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  std::string tagName;
Shinya Kitaoka 120a6e
  if (!is.matchTag(tagName) || tagName != "stringtable")
Shinya Kitaoka 120a6e
    throw TException("not a string table file");
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  while (!is.matchEndTag()) {
Shinya Kitaoka 120a6e
    if (!is.matchTag(tagName)) throw TException("expected tag");
Shinya Kitaoka 120a6e
    if (tagName == "item") {
Shinya Kitaoka 120a6e
      std::string id, name, help, tip;
Shinya Kitaoka 120a6e
      is >> id >> name;
Shinya Kitaoka 120a6e
      if (!is.matchEndTag()) {
Shinya Kitaoka 120a6e
        is >> help;
Shinya Kitaoka 120a6e
        if (!is.matchEndTag()) {
Shinya Kitaoka 120a6e
          is >> tip;
Shinya Kitaoka 120a6e
          if (!is.matchEndTag()) throw TException("Expected end tag");
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      Item &item  = m_table[id];
Shinya Kitaoka 120a6e
      item.m_name = ::to_wstring(name);
Shinya Kitaoka 120a6e
      item.m_help = ::to_wstring(help);
Shinya Kitaoka 120a6e
      item.m_tip  = ::to_wstring(tip);
Shinya Kitaoka 120a6e
    } else if (tagName == "defaultFont") {
Shinya Kitaoka 120a6e
      std::string fontName;
Shinya Kitaoka 120a6e
      int fontSize = 0;
Shinya Kitaoka 120a6e
      is >> fontName >> fontSize;
Shinya Kitaoka 120a6e
      if (!is.matchEndTag()) throw TException("Expected end tag");
Shinya Kitaoka 120a6e
      m_defaultFontNameAndSize = std::make_pair(fontName, fontSize);
Shinya Kitaoka 120a6e
    } else if (tagName == "defaultMacFont") {
Shinya Kitaoka 120a6e
      std::string macFontName;
Shinya Kitaoka 120a6e
      is >> macFontName;
Shinya Kitaoka 120a6e
      if (!is.matchEndTag()) throw TException("Expected end tag");
Shinya Kitaoka 120a6e
      m_defaultMacFontName = macFontName;
Shinya Kitaoka 120a6e
    } else
Shinya Kitaoka 120a6e
      throw TException("unexpected tag /" + tagName + "/");
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  // m_valid =true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
const TStringTable::Item *TStringTableImp::getItem(std::string name) const {
Shinya Kitaoka 120a6e
  std::map<std::string, item="">::const_iterator it;</std::string,>
Shinya Kitaoka 120a6e
  it = m_table.find(name);
Shinya Kitaoka 120a6e
  if (it == m_table.end())
Shinya Kitaoka 120a6e
    return 0;
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    return &(it->second);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
}  // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TStringTable::TStringTable() {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TStringTable::~TStringTable() {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
std::wstring TStringTable::translate(std::string name) {
Shinya Kitaoka 120a6e
  const TStringTable::Item *item = instance()->getItem(name);
Shinya Kitaoka 120a6e
  if (item)
Shinya Kitaoka 120a6e
    return item->m_name;
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    return ::to_wstring(name);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
const TStringTable *TStringTable::instance() {
Shinya Kitaoka 120a6e
  // may hurt MacOsX
Shinya Kitaoka 120a6e
  static TStringTableImp *instance = 0;
Shinya Kitaoka 120a6e
  if (!instance) instance          = new TStringTableImp;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  instance->init();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return instance;
Toshihiro Shimizu 890ddd
}