Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version

CHM Reader for Pocket PC 2003

, 29 Feb 2004 CPOL
Allows the reading of CHM files on a Pocket PC2003.
chmreaderexe.zip
CHMReader.exe
chmreadersource.zip
PocketPC
CHM Reader
CHMLib
AUTHORS
ChmLib.dsp
ChmLib.dsw
COPYING
enumdir_chmLib.dsp
enum_chmLib.dsp
extract_chmLib.dsp
INSTALL
Makefile
NEWS
README
test_chmLib.dsp
res
CHM Reader.ico
Cmdbar.bmp
icon1.ico
CHM Reader.vcl
CHM Reader.ico
CHM Reader.vcp
CHM Reader.vcw
CHM Reader.vcb
CHM Reader.vcc
CHM Reader.vco
chm_readerexe-pc2002.zip
ARMRel
CHM Reader.exe
//-------------------------------------------------------------------
// VOString implementation file
//-------------------------------------------------------------------
// 
// Copyright �2000- 02 Virtual Office Systems Incorporated
// All Rights Reserved                      
//
// This code may be used in compiled form in any way you desire. This
// file may be redistributed unmodified by any means PROVIDING it is 
// not sold for profit without the authors written consent, and 
// providing that this notice and the authors name is included.
//
// This code can be compiled, modified and distributed freely, providing
// that this copyright information remains intact in the distribution.
//
// This code may be compiled in original or modified form in any private 
// or commercial application.
//
// This file is provided "as is" with no expressed or implied warranty.
// The author accepts no liability for any damage, in any form, caused
// by this code. Use it at your own risk.
//-------------------------------------------------------------------

#include "stdafx.h"
#include <atlbase.h>
#include <tchar.h>
#include "VOString.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CVOString::CVOString(LPCTSTR pcszValue)
{
	m_pBuffer = NULL;
	m_dwBufferSize = 0;

	*this = pcszValue;
}

// Copy Constructor
CVOString::CVOString(const CVOString &rSrc)
{
	m_pBuffer = NULL;
	m_dwBufferSize = 0;

	*this = rSrc.m_pBuffer;
}

CVOString::~CVOString()
{
	if(m_pBuffer)
		delete m_pBuffer;
}

void CVOString::operator = (const CVOString& rSrc)
{
	*this = rSrc.m_pBuffer;
}

void CVOString::operator = (LPCTSTR pcszValue)
{
	if(pcszValue == NULL)
	{
		m_dwLength = 0;
		m_pBuffer = NULL;
	}
	else
	{
		m_dwLength = _tcslen(pcszValue);
		SetMinBufferSize(m_dwLength);
		_tcscpy(m_pBuffer, pcszValue);
	}
}

#ifndef _UNICODE
void CVOString::operator =(LPCWSTR pcwszValue)
{
	if(!pcwszValue)
	{
		m_dwLength = 0;
		m_pBuffer = NULL;
		return;
	}

	if(sizeof(TCHAR) == sizeof(WCHAR))
	{
		m_dwLength = wcslen(pcwszValue);
		SetMinBufferSize(m_dwLength);
		wcscpy((LPWSTR)m_pBuffer, pcwszValue);
	}
	else
	{
		int		nChars = wcslen(pcwszValue) + 1;
		LPTSTR	pszBuffer = new TCHAR[nChars];

		for(int n = 0; n < nChars; n++)
			pszBuffer[n] = (TCHAR) pcwszValue[n];

		m_dwLength = _tcslen(pszBuffer);
		SetMinBufferSize(m_dwLength);
		_tcscpy(m_pBuffer, pszBuffer);

		delete pszBuffer;
	}
}
#endif

BOOL CVOString::operator == (LPCTSTR pcszValue) const
{
	if(!m_pBuffer)
	{
		if(!pcszValue)
			return TRUE;

		return (_tcsicmp(pcszValue, TEXT("")) == 0);
	}

	return(_tcsicmp(pcszValue, m_pBuffer) == 0);
}

BOOL CVOString::operator == (const CVOString& rCompare) const
{
	if(!m_pBuffer)
	{
		if(rCompare.GetLength() == 0)
			return TRUE;
		else
			return FALSE;
	}

	if(!rCompare.m_pBuffer)
		return FALSE;

	return(_tcsicmp(rCompare.m_pBuffer, m_pBuffer) == 0);
}

LPCTSTR CVOString::operator += (LPCTSTR pcszAppend)
{
	if(m_pBuffer)
	{
		SetMinBufferSize(GetLength() + _tcslen(pcszAppend));
		_tcscat(m_pBuffer, pcszAppend);
		m_dwLength = _tcslen(m_pBuffer);
	}
	else
		*this = pcszAppend;

	return *this;
}

LPCTSTR CVOString::operator += (TCHAR chAppend)
{
	SetMinBufferSize(m_dwLength + 2);
	m_dwLength++;
	m_pBuffer[m_dwLength] = 0;
	m_pBuffer[m_dwLength - 1] = chAppend;

	return *this;
}

CVOString CVOString::operator + (LPCTSTR pcszAppend)
{
	CVOString strReturn(*this);
	
	strReturn += pcszAppend;

	return strReturn;
}

BOOL CVOString::SetMinBufferSize(DWORD dwChars)
{
#ifdef _DEBUG
	if(dwChars > 65536)
		DebugBreak();	// This is just a precaution to protect against memory leaks.  Large strings are fine.
#endif
	if(m_dwBufferSize < dwChars + 1)
	{
		TCHAR*	pNewBuffer;
		DWORD	dwNewBufferSize = dwChars + 16;

		pNewBuffer = new TCHAR[dwNewBufferSize];

		memset(pNewBuffer, 0, sizeof(TCHAR) * dwNewBufferSize);

		if(m_pBuffer)
		{
			memmove(pNewBuffer, m_pBuffer, m_dwBufferSize * sizeof(TCHAR) );
			delete m_pBuffer;
		}

		m_pBuffer = pNewBuffer;
		m_dwBufferSize = dwNewBufferSize;
	}

	return TRUE;
}

TCHAR CVOString::GetAt(DWORD dwOffset) const
{
	if(dwOffset > m_dwLength - 1)
		return (TCHAR) 0;

	return m_pBuffer[dwOffset];
}

CVOString CVOString::Left(DWORD dwCount) const
{
	if(dwCount >= m_dwLength)
		return CVOString(*this);

	LPTSTR	pszTemp = new TCHAR[dwCount + 1];

	memset(pszTemp, 0, sizeof(TCHAR) * (dwCount + 1));
	memmove(pszTemp, m_pBuffer, sizeof(TCHAR) * dwCount);

	CVOString strValue(pszTemp);

	delete pszTemp;

	return strValue;
}

CVOString CVOString::Mid(DWORD dwOffset, int nLength) const
{
	if(dwOffset < 0 || dwOffset > m_dwLength)
		return CVOString(TEXT(""));

	if(nLength == -1)
		nLength = m_dwLength - dwOffset;
	else if(dwOffset + nLength > m_dwLength)
		nLength = m_dwLength - dwOffset;

	LPTSTR	pszTemp = new TCHAR[nLength + 1];

	memset(pszTemp, 0, sizeof(TCHAR) * (nLength + 1));
	memmove(pszTemp, m_pBuffer + dwOffset, sizeof(TCHAR) * nLength);

	CVOString strValue(pszTemp);

	delete pszTemp;

	return strValue;
}

LPTSTR CVOString::GetBuffer(DWORD dwMinSize)
{
	SetMinBufferSize(dwMinSize + 1);

	return m_pBuffer;
}

int CVOString::Format(LPCTSTR pcszFormat, ...)
{
    va_list vl;

    va_start( vl, pcszFormat);

	wvsprintf(GetBuffer(2048), pcszFormat, vl);
	ReleaseBuffer();

	va_end(vl);

	return GetLength();
}

int CVOString::Find(LPCTSTR pcszValue, int nStartingOffset) const
{
	LPTSTR pszSubstring;
	
	if(nStartingOffset < 0)
		nStartingOffset = 0;

	pszSubstring = _tcsstr(m_pBuffer + nStartingOffset, pcszValue);

	if(!pszSubstring)
		return -1;

	return (pszSubstring - m_pBuffer);
}

int CVOString::Find(TCHAR chValue, int nStartingOffset) const
{
	TCHAR pcszValue[2];

	pcszValue[0] = chValue;
	pcszValue[1] = 0;

	return Find(pcszValue, nStartingOffset);
}

int CVOString::ReverseFind(LPCTSTR pcszSubstring) const
{
	int nOffset = -1, nNextOffset = 0;

	while((nNextOffset = Find(pcszSubstring, nNextOffset)) != -1)
		nOffset = nNextOffset++;

	return nOffset;
}

DWORD CVOString::ReleaseBuffer(int nChars)
{
	if((m_pBuffer == NULL) || (m_dwBufferSize == 0))
		return 0;

	if(nChars == -1)
		m_dwLength = _tcslen(m_pBuffer);
	else
	{
		m_dwLength = (DWORD) nChars;

		if(m_dwLength > m_dwBufferSize)
			m_dwLength = m_dwBufferSize;

		m_pBuffer[m_dwLength] = 0;
	}

	return m_dwLength;
}

const CVOString& CVOString::TrimRight()
{
	while(GetLength() && GetAt(GetLength() - 1) == TCHAR(' '))
		*this = Left(GetLength() - 1);

	return *this;
}

const CVOString& CVOString::TrimLeft()
{
	while(GetLength() && GetAt(0) == TCHAR(' '))
		*this = Mid(1);

	return *this;
}

CVOString CVOString::Right(int nChars)
{
	if((int)GetLength() < nChars)
		return *this;

	return Mid(GetLength() - nChars);
}

void CVOString::MakeUpper()
{
	for(int i = 0; i < (int)GetLength(); i++)
	{
		if(m_pBuffer[i] >= TCHAR('a') && m_pBuffer[i] <= TCHAR('z'))
			m_pBuffer[i] = m_pBuffer[i] - (TCHAR('a') - TCHAR('A'));
	}
}

int CVOString::CompareNoCase(LPCTSTR pcszValue)
{
	if(!m_pBuffer && !pcszValue)
		return 0;

	if(!pcszValue)
		return 1;

	if(!m_pBuffer)
		return -1;

	return _tcsicmp(m_pBuffer, pcszValue);
}

int CVOString::FindOneOf(LPCTSTR pcszDelims)
{
	if(m_pBuffer == NULL || m_dwBufferSize == 0)
		return -1;

	if(!pcszDelims)
		return -1;

	int nDelim = _tcscspn((LPCTSTR)m_pBuffer, pcszDelims);

	if(nDelim == (int)GetLength())
		return -1;

	return nDelim;
}

DWORD CVOString::Replace(LPCTSTR pcszSearchFor, LPCTSTR pcszReplaceWith)
{
	CVOString	strSearchFor(pcszSearchFor);
	CVOString	strReplaceWith(pcszReplaceWith);
	CVOString	strRemain;

	if(strReplaceWith.Find(strSearchFor) != -1)
		return 0;	// Would be infinite loop

	DWORD	dwCount = 0;
	int		nMatch = -1;

	while((nMatch = Find(strSearchFor, nMatch + 1)) != -1)
	{
		strRemain = Mid(nMatch + strSearchFor.GetLength());
		*this = Left(nMatch);
		*this += strReplaceWith;
		*this += strRemain;
		dwCount++;
	}

	return dwCount;
}

#define CH_QUOTE			TCHAR('\"')
#define SZ_QUOTE			TEXT("\"")
#define SZ_QUOTE_ENCODED	TEXT("%22")

CVOString CVOString::AddQuotes(LPCTSTR pcszValue)
{
	CVOString strValue(pcszValue);

	strValue.Replace(SZ_QUOTE, SZ_QUOTE_ENCODED);

	CVOString strNewValue;
	
	strNewValue += CH_QUOTE;
	strNewValue += strValue;
	strNewValue += CH_QUOTE;

	return strNewValue;
}

CVOString CVOString::RemoveQuotes(LPCTSTR pcszValue)
{
	CVOString strValue(pcszValue);

	if(strValue.GetLength() < 2)
		return strValue;

	if(	(strValue.GetAt(0) == CH_QUOTE) && 
		(strValue.GetAt(strValue.GetLength() - 1) == CH_QUOTE) )
		strValue = strValue.Mid(1, strValue.GetLength() - 2);

	strValue.Replace(SZ_QUOTE_ENCODED, SZ_QUOTE);

	return strValue;
}

CVOString CVOString::DescribeErrorMessage(DWORD dwError)
{
    LPVOID lpMsgBuf;
    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,    
                  NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 
                  (LPTSTR) &lpMsgBuf, 0, NULL);
	CVOString strDescription = (LPCTSTR) lpMsgBuf;
    LocalFree(lpMsgBuf);

	return strDescription;
}

BOOL CVOString::ToSystemTime(SYSTEMTIME &st, DWORD dwFlags)
{
	USES_CONVERSION;

	DATE	dt;
	SCODE	sc;

	if (FAILED(sc = VarDateFromStr((LPOLESTR)T2COLE(m_pBuffer), LANG_USER_DEFAULT, dwFlags, &dt)))
	{
		if (sc == DISP_E_TYPEMISMATCH)
		{
			OutputDebugString(TEXT("CVOString::ToSystemTime() Failed - Type Mismatch\n"));
			
			return FALSE;
		}
		else if (sc == DISP_E_OVERFLOW)
		{
			OutputDebugString(TEXT("CVOString::ToSystemTime() Failed - Overflow\n"));

			return FALSE;
		}
		else
		{
			OutputDebugString(TEXT("CVOString::ToSystemTime() Failed\n"));

			return FALSE;
		}
	}

	VariantTimeToSystemTime(dt, &st);

	return TRUE;
}

BOOL CVOString::ParseSystemTime(SYSTEMTIME &st, DWORD dwFlags)
{
	USES_CONVERSION;

	DATE dt;

	SystemTimeToVariantTime(&st, &dt);

	CComBSTR bstrDate;

	if(VarBstrFromDate(dt, LANG_USER_DEFAULT, dwFlags, &bstrDate) != S_OK)
		return FALSE;

	*this = bstrDate;

	return TRUE;
}

CVOString CVOString::EncodeHex(LPCTSTR pcszValue)
{
	if(!pcszValue)
		return CVOString(TEXT(""));

	static TCHAR hexChar[] = {	TCHAR('0'), TCHAR('1'), TCHAR('2'), TCHAR('3'),
								TCHAR('4'), TCHAR('5'), TCHAR('6'), TCHAR('7'),
								TCHAR('8'), TCHAR('9'), TCHAR('A'), TCHAR('B'),
								TCHAR('C'), TCHAR('D'), TCHAR('E'), TCHAR('F') };
	CVOString strValue;

	LPCTSTR pcszCur = pcszValue;

	unsigned char chCur;

	while(*pcszCur)
	{
		chCur = (unsigned char)(*pcszCur);
		strValue += hexChar[chCur >> 4];
		strValue += hexChar[chCur & 0xF];
		pcszCur++;
	}

	return strValue;
}

CVOString CVOString::DecodeHex(LPCTSTR pcszValue)
{
	CVOString strValue(pcszValue);
	CVOString strDecoded;

	strValue.MakeUpper();

	if(strValue.GetLength() % 2)	// Uneven hex pairs
		return CVOString(TEXT(""));

	unsigned char	ch;
	TCHAR			nibHigh, nibLow;

	for(int nChar = 0; nChar < (int)strValue.GetLength() / 2; nChar++)
	{
		ch = 0;

		nibHigh = strValue.GetAt(nChar * 2);
		nibLow = strValue.GetAt(nChar * 2 + 1);

		switch(nibHigh)
		{
		case TCHAR('0'):
		case TCHAR('1'):
		case TCHAR('2'):
		case TCHAR('3'):
		case TCHAR('4'):
		case TCHAR('5'):
		case TCHAR('6'):
		case TCHAR('7'):
		case TCHAR('8'):
		case TCHAR('9'):
			ch += (unsigned char)(nibHigh - TCHAR('0'));
			break;

		case TCHAR('A'):
		case TCHAR('B'):
		case TCHAR('C'):
		case TCHAR('D'):
		case TCHAR('E'):
		case TCHAR('F'):
			ch += (unsigned char)(nibHigh - TCHAR('A') + 10);
			break;
		}

		ch = ch << 4;

		switch(nibLow)
		{
		case TCHAR('0'):
		case TCHAR('1'):
		case TCHAR('2'):
		case TCHAR('3'):
		case TCHAR('4'):
		case TCHAR('5'):
		case TCHAR('6'):
		case TCHAR('7'):
		case TCHAR('8'):
		case TCHAR('9'):
			ch += (unsigned char)(nibLow - TCHAR('0'));
			break;

		case TCHAR('A'):
		case TCHAR('B'):
		case TCHAR('C'):
		case TCHAR('D'):
		case TCHAR('E'):
		case TCHAR('F'):
			ch += (unsigned char)(nibLow - TCHAR('A') + 10);
			break;
		}

		strDecoded += (TCHAR)ch;
	}

	return strDecoded;
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Peter Tewkesbury
Software Developer (Senior)
United Kingdom United Kingdom
Hi, I am a developer working in Cheshire, England. I started programming on a Vic-20 back in the 80's with only 5K of ram), and I have not looked back since. I have developed software using Visual C/C++, C#/.NET, MFC, ATL & ASP.NET, SQL Server, Crystal Reports, DevExpress .NET Components, WinForms, SQL Server client side reporting.
 
My favourite language is C# on .NET V3.5 and I am always trying to learn new stuff like LINQ.

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.141223.1 | Last Updated 1 Mar 2004
Article Copyright 2004 by Peter Tewkesbury
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid