// ----------------------------------------
// Перекодировка текстового файла
// из OEM в ANSI с использованием
// дополнительной таблицы перекодировки
// ----------------------------------------

#define STRICT
#include <windows.h>
#include <commdlg.h>
#include <mem.h>

// Прототипы функций
HFILE GetSrcFile(void);
HFILE GetDstFile(void);
void  Oem3Ansi(HFILE, HFILE);

// Указатель на таблицу перекодировки,
// которая будет загружена из ресурсов
char far * lpXlatTable;

// -------------------------------
// Функция WinMain
// -------------------------------

#pragma argsused
int PASCAL
WinMain(HINSTANCE hInstance,
	HINSTANCE hPrevInstance,
	LPSTR     lpszCmdLine,
	int       nCmdShow)
{
  HFILE hfSrc, hfDst;

  // Положение ресурса в файле
  HRSRC   hResource;

  // Идентификатор таблицы перекодировки
  HGLOBAL hXlatTable;

  // Определяем расположение ресурса
  hResource   = FindResource(hInstance, "XlatTable", "XLAT");

  // получаем идентификатор ресурса
  hXlatTable  = LoadResource(hInstance, hResource);

  // Фиксируем ресурс в памяти, получая его адрес
  lpXlatTable = (char far *)LockResource(hXlatTable);

  // Если адрес равен NULL, при загружке или
  // фиксации ресурса произошла ошибка
  if(lpXlatTable == NULL)
  {
    MessageBox(NULL, "Error", "Resource loading error", MB_OK);
    return(-1);
  }

  // Открываем входной файл.
  hfSrc = GetSrcFile();
  if(!hfSrc) return 0;

  // Открываем выходной файл
  hfDst = GetDstFile();
  if(!hfDst) return 0;

  // Выполняем перекодировку файла
  Oem3Ansi(hfSrc, hfDst);

  // Закрываем входной и выходной файлы
  _lclose(hfSrc);
  _lclose(hfDst);

  UnlockResource(hXlatTable);
  FreeResource(hXlatTable);

  return 0;
}

// -------------------------------
// Функция GetSrcFile
// Выбор файла для перекодировки
// -------------------------------

HFILE GetSrcFile(void)
{
  OPENFILENAME ofn;

  char szFile[256];
  char szFileTitle[256];
  char szFilter[256] =
	 "Text Files\0*.txt;*.doc\0Any Files\0*.*\0";
  HFILE hf;

  szFile[0] = '\0';
  memset(&ofn, 0, sizeof(OPENFILENAME));

  // Инициализируем нужные нам поля
  ofn.lStructSize       = sizeof(OPENFILENAME);
  ofn.hwndOwner         = NULL;
  ofn.lpstrFilter       = szFilter;
  ofn.nFilterIndex      = 1;
  ofn.lpstrFile         = szFile;
  ofn.nMaxFile          = sizeof(szFile);
  ofn.lpstrFileTitle    = szFileTitle;
  ofn.nMaxFileTitle     = sizeof(szFileTitle);
  ofn.lpstrInitialDir   = NULL;
  ofn.Flags =   OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST
				  | OFN_HIDEREADONLY;
  // Выбираем входной файл
  if (GetOpenFileName(&ofn)) {
    hf = _lopen(ofn.lpstrFile, OF_READ);
    return hf;
  }
  else return 0;
}

// -------------------------------
// Функция GetDstFile
// Выбор файла для записи
// результата перекодировки
// -------------------------------

HFILE GetDstFile(void)
{
  OPENFILENAME ofn;

  char szFile[256];
  char szFileTitle[256];
  char szFilter[256] =
	 "Text Files\0*.txt;*.doc\0Any Files\0*.*\0";

  HFILE hf;

  szFile[0] = '\0';

  memset(&ofn, 0, sizeof(OPENFILENAME));

  ofn.lStructSize       = sizeof(OPENFILENAME);
  ofn.hwndOwner         = NULL;
  ofn.lpstrFilter       = szFilter;
  ofn.nFilterIndex      = 1;
  ofn.lpstrFile         = szFile;
  ofn.nMaxFile          = sizeof(szFile);
  ofn.lpstrFileTitle    = szFileTitle;
  ofn.nMaxFileTitle     = sizeof(szFileTitle);
  ofn.lpstrInitialDir   = NULL;
  ofn.Flags             = OFN_HIDEREADONLY;

  // Выбираем выходной файл
  if (GetSaveFileName(&ofn)) {

    // При необходимости создаем файл
    hf = _lcreat(ofn.lpstrFile, 0);
    return hf;
  }
  else return 0;
}

// -------------------------------
// Функция Oem3Ansi
// Перекодировка файла
// -------------------------------

void Oem3Ansi(HFILE hfSrcFile, HFILE hfDstFile)
{
  // Счетчик прочитанных байт
  int cbRead;

  // Буфер для считанных данных
  BYTE bBuf[2048];

  // Читаем в цикле файл и перекодируем его,
  // записывая результат в другой файл
  do {
    // Читаем в буфер 2048 байт из входного файла
    cbRead = _lread(hfSrcFile, bBuf, 2048);

    // Выполняем дополнительную перекодировку
    // по таблице, загруженной из ресурсов
    for(int i=0;i < cbRead; i++)
    {
      bBuf[i] = lpXlatTable[bBuf[i]];
    }

    // Перекодируем содержимое буфера
    // из OEM в ANSI
    OemToAnsiBuff(bBuf, bBuf, cbRead);

    // Сохраняем содержимое буфера в
    // выходном файле
    _lwrite(hfDstFile, bBuf, cbRead);

  // Завершаем цикл по концу входного файла
  } while (cbRead != 0);
}

