Click here to Skip to main content
15,892,480 members
Articles / Mobile Apps / Windows Mobile

CHM Reader for Pocket PC 2003

Rate me:
Please Sign up or sign in to vote.
4.91/5 (65 votes)
29 Feb 2004CPOL3 min read 477.2K   960   87  
Allows the reading of CHM files on a Pocket PC2003.
//-------------------------------------------------------------------
// 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)


Written By
Software Developer (Senior)
United Kingdom United Kingdom
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions