class o_CyrillicEncodeUtilities extends object;

// source: http://killingfloor.ru/xforum/threads/ispravlenie-russkix-imen.4023/#post-121031 @Flame
// Пусть для определённости SpecialOpen="([{", а SpecialClose="}])"

// Функция конвертирует строку. Символы кириллицы заменяются на символы латиницы, а так же спец символы
// Например слово проверка конвертируется в строку ([{proverka}]), теsт->([{te}])s([{t}])
// То есть все блоки символов кириллицы выделяются с помощью набора спец символов. Спец символы можно задавать в настройках
final static function string EnCodeString(string Source, string SpecialOpen, string SpecialClose)
{
  local int i;
  local int code;
  local int sLength;
  local bool bOpened;
  local string result;

  sLength = Len(Source);

  for (i = 0; i < sLength; i++)
  {
    // Получаем код первого символа строки
    code = Asc(Source);
    // Если кодировка за 1000 - вычитаем 848. Подробнее в теме про кириллицу в линуксе и винде
    if (code > 848)
      code -= 848;

    // Параметр bOpened отвечает за индикацию, того что сейчас идут символы кириллицы.
    // Если code <= 160, значит встретился символ латиницы и надо закрывать блок отвечающий за русский язык
    // То есть ранее был прописан спец набор символов SpecialOpen и надо закрывать этот набор символов с помощью SpecialClose
    if (bOpened && code <= 160)
    {
      bOpened = false;
      result $= SpecialClose;
    }

    // Если кириллица и не добавлен спец символы открытия блока русского языка SpecialOpen - добавляем
    // Если же либо символ латиницы, либо уже были символы открытия - пытаемся конвертировать символ с помощью EnCodeSymbol
    // EnCodeSymbol конвертирует только кириллицу, остальные символы он не трогает
    if(code > 160 && !bOpened)
    {
      bOpened = true;
      result $= SpecialOpen $ Chr(EnCodeSymbol(code));
    }
    else
      result $= Chr(EnCodeSymbol(code));

    // "Отрезаем" первый символ от входной строки - мы его уже обработали. Теперь новый первый символ и цикл повторяется
    Source = Mid(Source, 1);
    // Если исходная строка заканчивается кириллицей, то надо закрыть строку символами SpecialClose
    if (i >= sLength-1 && bOpened)
      result $= SpecialClose;
  }
  return result;
}


// our version without any open / close symbols
final static function string EnCodeStringHide(string Source)
{
  local int i;
  local int code;
  local int sLength;
  local string result;

  sLength = Len(Source);

  for (i = 0; i < sLength; i++)
  {
    // Получаем код первого символа строки
    code = Asc(Source);
    // Если кодировка за 1000 - вычитаем 848. Подробнее в теме про кириллицу в линуксе и винде
    if (code > 848)
      code -= 848;

    result $= Chr(EnCodeSymbol(code));

    // "Отрезаем" первый символ от входной строки - мы его уже обработали. Теперь новый первый символ и цикл повторяется
    Source = Mid(Source, 1);
  }
  return result;
}


// Получаем исходную строку на кириллице из преобразованной
// ([{proverka}])->проверка, ([{te}])s([{t}])->теsт
final static function string DeCodeString(string Source, string SpecialOpen, string SpecialClose)
{
  local string result;
  local int i;
  local array<string> Parts, InnerParts;
  local string Part;

  // Разбиваем строку на подстроки. Строка по которой разбиваем - SpecialClose набор символов
  // "([{te}])s([{t}])" разбивается на "([{te" и "s([{t"
  Split(Source, SpecialClose, Parts);

  for (i = 0; i < Parts.Length; i++)
  {
    Part = Parts[i];
    // Для каждой подстроки проверяем содержит ли она спец символы открытия SpecialOpen
    // Если содержут, то разбивам на 2 подстроки по ([{
    // Например. ([{te-> "пустая строка" и "te", s([{t-> "s" и "t"
    // Левая из двух подстрок - чистая латиница, правая - кириллица и её надо конвертировать
    // DeCodePart конвертирует строку на латинице в строку на кириллице, согласно правилам определённых выше
    if (InStr(Part, SpecialOpen) >= 0)
    {
      Split(Part, SpecialOpen, InnerParts);
      result $= InnerParts[0] $ DeCodePart(InnerParts[1]);
    }
    else
      result $= Part;
  }
  return result;
}


// Конвертация символов из латиницы в кириллицу
final static function string DeCodePart(string Source)
{
  local int sLength;
  local int i;
  local int code;
  local string result;

  sLength = Len(Source);
  for (i = 0; i < sLength; i++)
  {
    code = Asc(Source);
    result $= Chr(DeCodeSymbol(code) + 848); // Для Windows надо добавить. Для Linux надо проверять
    Source = Mid(Source,1);
  }
  return result;
}


// Конвертация символа из кириллицы в латиницу. Передаётся и возвращается код символа
final static function int EnCodeSymbol(int code)
{
  switch(code)
  {
    case 224:
      return 97;
    case 225:
      return 98;
    case 226:
      return 118;
    case 227:
      return 103;
    case 228:
      return 100;
    case 229:
      return 101;
    case 184:
      return 42;
    case 230:
      return 106;
    case 231:
      return 122;
    case 232:
      return 105;
    case 233:
      return 94;
    case 234:
      return 107;
    case 235:
      return 108;
    case 236:
      return 109;
    case 237:
      return 110;
    case 238:
      return 111;
    case 239:
      return 112;
    case 240:
      return 114;
    case 241:
      return 115;
    case 242:
      return 116;
    case 243:
      return 117;
    case 244:
      return 102;
    case 245:
      return 104;
    case 246:
      return 99;
    case 247:
      return 121;
    case 248:
      return 119;
    case 249:
      return 36;
    case 250:
      return 33;
    case 251:
      return 37;
    case 252:
      return 63;
    case 253:
      return 41;
    case 254:
      return 124;
    case 255:
      return 47;
    case 192:
      return 65;
    case 193:
      return 66;
    case 194:
      return 86;
    case 195:
      return 71;
    case 196:
      return 68;
    case 197:
      return 69;
    case 168:
      return 64;
    case 198:
      return 74;
    case 199:
      return 90;
    case 200:
      return 73;
    case 201:
      return 38;
    case 202:
      return 75;
    case 203:
      return 76;
    case 204:
      return 77;
    case 205:
      return 78;
    case 206:
      return 79;
    case 207:
      return 80;
    case 208:
      return 82;
    case 209:
      return 83;
    case 210:
      return 84;
    case 211:
      return 85;
    case 212:
      return 70;
    case 213:
      return 72;
    case 214:
      return 67;
    case 215:
      return 89;
    case 216:
      return 87;
    case 217:
      return 55;
    case 218:
      return 56;
    case 219:
      return 57;
    case 220:
      return 48;
    case 221:
      return 49;
    case 222:
      return 50;
    case 223:
      return 51;
  }
  return code;
}


// Конвертация символа из латиницы в кириллицу. Передаётся и возвращается код символа
final static function int DeCodeSymbol(int code)
{
  switch(code)
  {
    case 97:
      return 224;
    case 98:
      return 225;
    case 118:
      return 226;
    case 103:
      return 227;
    case 100:
      return 228;
    case 101:
      return 229;
    case 42:
      return 184;
    case 106:
      return 230;
    case 122:
      return 231;
    case 105:
      return 232;
    case 94:
      return 233;
    case 107:
      return 234;
    case 108:
      return 235;
    case 109:
      return 236;
    case 110:
      return 237;
    case 111:
      return 238;
    case 112:
      return 239;
    case 114:
      return 240;
    case 115:
      return 241;
    case 116:
      return 242;
    case 117:
      return 243;
    case 102:
      return 244;
    case 104:
      return 245;
    case 99:
      return 246;
    case 121:
      return 247;
    case 119:
      return 248;
    case 36:
      return 249;
    case 33:
      return 250;
    case 37:
      return 251;
    case 63:
      return 252;
    case 41:
      return 253;
    case 124:
      return 254;
    case 47:
      return 255;
    case 65:
      return 192;
    case 66:
      return 193;
    case 86:
      return 194;
    case 71:
      return 195;
    case 68:
      return 196;
    case 69:
      return 197;
    case 64:
      return 168;
    case 74:
      return 198;
    case 90:
      return 199;
    case 73:
      return 200;
    case 38:
      return 201;
    case 75:
      return 202;
    case 76:
      return 203;
    case 77:
      return 204;
    case 78:
      return 205;
    case 79:
      return 206;
    case 80:
      return 207;
    case 82:
      return 208;
    case 83:
      return 209;
    case 84:
      return 210;
    case 85:
      return 211;
    case 70:
      return 212;
    case 72:
      return 213;
    case 67:
      return 214;
    case 89:
      return 215;
    case 87:
      return 216;
    case 55:
      return 217;
    case 56:
      return 218;
    case 57:
      return 219;
    case 48:
      return 220;
    case 49:
      return 221;
    case 50:
      return 222;
    case 51:
      return 223;
  }
  return code;
}

defaultproperties
{
}
