Notepad3/grepWinNP3/sktoolslib_mod/ResourceTextFile.cpp
2020-04-17 14:19:38 +02:00

284 lines
7.4 KiB
C++

// sktoolslib - common files for SK tools
// Copyright (C) 2012 - Stefan Kueng
// 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,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
#include "stdafx.h"
#include <stdio.h>
#include <string.h>
#include <tchar.h>
#include <malloc.h>
#include <crtdbg.h>
#include "ResourceTextFile.h"
CResourceTextFile::CResourceTextFile()
: m_pszText(NULL)
, m_eBomAction(NoBomAction)
, m_eConvertAction(NoConvertAction)
{
}
CResourceTextFile::CResourceTextFile(const CResourceTextFile& rf)
{
if (rf.m_bDoNotDeleteBuffer)
{
// buffer is allocated externally or has been detached
m_pszText = rf.m_pszText;
}
else
{
m_pszText = new TCHAR [rf.m_nBufLen + 2];
memset(m_pszText, 0, (rf.m_nBufLen+2)*sizeof(TCHAR));
_tcsncpy_s(m_pszText, rf.m_nBufLen + 2, rf.m_pszText, rf.m_nBufLen);
}
m_nBufLen = rf.m_nBufLen;
m_nPosition = 0;
m_bIsOpen = rf.m_bIsOpen;
m_bText = rf.m_bText;
m_bDoNotDeleteBuffer = rf.m_bDoNotDeleteBuffer;
m_eConvertAction = rf.m_eConvertAction;
m_eBomAction = rf.m_eBomAction;
}
CResourceTextFile::~CResourceTextFile()
{
Close();
}
BOOL CResourceTextFile::Open(HINSTANCE hInstance,
LPCTSTR lpszResId,
LPCTSTR lpszResType /*= _T("TEXT")*/,
ConvertAction eConvertAction /*= NoConvertAction*/,
BomAction eBomAction /*= NoBomAction*/)
{
BOOL rc = FALSE;
Close();
_ASSERTE(lpszResId);
_ASSERTE(lpszResType);
m_eConvertAction = eConvertAction;
m_eBomAction = eBomAction;
if (lpszResId && lpszResType)
{
rc = CResourceFile::Open(hInstance, lpszResId, lpszResType);
if (rc)
{
TCHAR *cp = (TCHAR *) GetByteBuffer();
DWORD dwSize = (DWORD) GetLength();
rc = SetTextBuffer(cp, dwSize,
eConvertAction, eBomAction);
if (rc)
{
m_bText = TRUE;
}
else
{
Close();
}
}
}
return rc;
}
void CResourceTextFile::Close()
{
CResourceFile::Close();
if (m_pszText && !m_bDoNotDeleteBuffer)
delete [] m_pszText;
m_pszText = NULL;
}
TCHAR * CResourceTextFile::DetachTextBuffer()
{
TCHAR *cp = NULL;
if (m_bIsOpen && m_bText)
{
m_bDoNotDeleteBuffer = TRUE;
cp = m_pszText;
}
return cp;
}
TCHAR * CResourceTextFile::DuplicateTextBuffer()
{
TCHAR *dup = NULL;
if (IsOpen() && m_bText)
dup = _tcsdup(m_pszText);
return dup;
}
BOOL CResourceTextFile::SetTextBuffer(TCHAR * inbuf,
DWORD len,
ConvertAction eConvertAction /*= NoConvertAction*/,
BomAction eBomAction /*= NoBomAction*/)
{
BOOL rc = FALSE;
_ASSERTE(inbuf);
_ASSERTE(len != 0);
_ASSERTE(m_pszText == NULL);
if (inbuf && (len != 0))
{
m_bText = TRUE;
m_eConvertAction = eConvertAction;
m_eBomAction = eBomAction;
DWORD dwSize = len; // bytes
// copy buffer to ensure it's null terminated
BYTE * buf = new BYTE [dwSize+16];
memset(buf, 0, dwSize+16);
memcpy(buf, inbuf, dwSize);
BOOL bFoundBom = (buf[0] == 0xFF) && (buf[1] == 0xFE);
if (m_eConvertAction == ConvertToUnicode)
{
int wlen = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)buf, -1, NULL, 0);
#ifndef _UNICODE
wlen = wlen * sizeof(WCHAR);
#endif
m_pszText = new TCHAR [wlen+16];
memset(m_pszText, 0, (wlen+16)*sizeof(TCHAR));
LPWSTR wp = (LPWSTR) m_pszText;
if ((m_eBomAction == AddBom) && !bFoundBom)
{
// caller wants a BOM
BYTE * p = (BYTE *)m_pszText;
p[0] = 0xFF;
p[1] = 0xFE;
wp += 1;
}
MultiByteToWideChar(CP_ACP, 0, (LPCSTR)buf, -1, wp, wlen+2);
m_nBufLen = wcslen((WCHAR*)m_pszText);
}
else if (m_eConvertAction == ConvertToAnsi)
{
LPCWSTR wp = (LPCWSTR) buf;
if (bFoundBom && (m_eBomAction == RemoveBom))
wp++; // skip over BOM
int alen = WideCharToMultiByte(CP_ACP, 0, wp, -1,
NULL, 0, NULL, NULL);
m_pszText = new TCHAR [alen+4];
memset(m_pszText, 0, (alen+4)*sizeof(TCHAR));
WideCharToMultiByte(CP_ACP, 0, wp, -1,
(LPSTR)m_pszText, alen+1, NULL, NULL);
m_nBufLen = strlen((LPCSTR)m_pszText);
}
else
{
// no conversion
m_pszText = new TCHAR [(dwSize + 16)/sizeof(TCHAR)];
TCHAR *cp = m_pszText;
memset(m_pszText, 0, dwSize+8);
int index = 0;
if ((m_eBomAction == AddBom) && !bFoundBom)
{
BYTE bom[2] = { 0xFF, 0xFE };
memcpy(cp, bom, 2);
cp += 2;
}
else if ((m_eBomAction == RemoveBom) && bFoundBom)
{
index = 2;
}
memcpy(cp, &buf[index], dwSize);
m_nBufLen = _tcslen(m_pszText);
}
m_nPosition = 0;
m_bIsOpen = TRUE;
m_bDoNotDeleteBuffer = FALSE; // ok to delete the buffer
delete [] buf;
rc = TRUE;
}
return rc;
}
size_t CResourceTextFile::ReadLine(TCHAR *buf, size_t nBufLen)
{
size_t nOldPosition = m_nPosition;
size_t nIndex = 0;
if (buf)
*buf = _T('\0');
if (m_bIsOpen && m_pszText && m_bText)
{
while (!IsAtEOF())
{
TCHAR c = m_pszText[m_nPosition++];
if ((c == _T('\r')) || (c == _T('\n')))
{
if (!IsAtEOF())
{
// check for \r\n pair
TCHAR prevc = c;
c = m_pszText[m_nPosition];
if (((prevc == _T('\r')) && (c == _T('\n'))) ||
((prevc == _T('\n')) && (c == _T('\r'))))
{
m_nPosition++;
}
}
break; // end of line
}
if (buf && (nIndex < nBufLen))
buf[nIndex] = c;
nIndex++;
}
}
// add terminating nul always
if (buf)
{
if (nIndex >= nBufLen)
{
// there is not enough room, so replace last char
nIndex = nBufLen - 1;
if (nBufLen == 0)
nIndex = 0;
}
buf[nIndex] = _T('\0');
}
// if we were just getting buffer size, restore position
if (!buf)
{
m_nPosition = nOldPosition;
}
return nIndex;
}