📄 exbuffer.cpp
字号:
// ExBuffer.cpp: implementation of the CExBuffer class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "ExBuffer.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CExBuffer::CExBuffer()
{
m_nStartLine = 0;
m_byCurrentFontSize = 0;
m_byCurrentFontType = 0;
m_dwMaxLineWidth = 176;
m_FullScreen = FALSE;
}
CExBuffer::~CExBuffer()
{
}
BOOL CExBuffer::FillLine(BYTE *szSource,DWORD &nLen)
{
DWORD dwPrevRead = nLen;
BYTE dwTheLineWidth = 0;
DWORD dwPtr = 0;
short dwLine = 0;
// DWORD dwPrevSpacePos = 0;
BYTE pcLineBuf[50];
BYTE pcTmp[50];
memset(pcLineBuf,0,sizeof(pcLineBuf));
short byMaxTmpLine = 0;//NUMS OF CHAR FOR MAX WIDTH LINE
DWORD dwTmpPtr = 0; //Only a long word exists in a line
while(dwPtr <dwPrevRead)
{
BYTE c = szSource[dwPtr++];
if(c == 0x0D || c == 0x0A)
{
if((c == 0x0D)&&(szSource[dwPtr] == 0x0A))
dwPtr ++;
if(dwLine == 0) //EMPTY LINE
m_pcLine.Add(CString("\r\n"));
else
{ //END OF A LINE
pcLineBuf[dwLine] = '\0';
m_pcLine.Add(CString(pcLineBuf));
dwLine = 0;
dwTheLineWidth = 0;
}
memset(pcLineBuf,0,sizeof(pcLineBuf));
}
else
{
dwTheLineWidth += byFontWidth[m_byCurrentFontType * 3 + m_byCurrentFontSize][c];
if(dwTheLineWidth <= m_dwMaxLineWidth)
{
if(c == VK_TAB) c = VK_SPACE;//TAB = 1 SPACE, SHOULD BE 8
// else if(c == VK_SPACE) dwPrevSpacePos = dwLine;
pcLineBuf[dwLine ++] = c;
}
else
{
// dwPtr -= dwLine - dwPrevSpacePos;
// pcLineBuf[dwPrevSpacePos + 1] = '\0';
byMaxTmpLine = dwLine - 1;
dwTmpPtr = dwPtr - 2;
memset(pcTmp,0,sizeof(pcTmp));
memcpy(pcTmp,pcLineBuf,byMaxTmpLine);
while((--dwLine>=0)&&((pcLineBuf[dwLine] >= '0' && pcLineBuf[dwLine] <= '9') ||
(pcLineBuf[dwLine] >= 'a' && pcLineBuf[dwLine] <= 'z') ||
(pcLineBuf[dwLine] >= 'A' && pcLineBuf[dwLine] <= 'Z') ||
pcLineBuf[dwLine] == '_' || pcLineBuf[dwLine] == '*' ||
pcLineBuf[dwLine] == '^' || pcLineBuf[dwLine] == '~' ))
--dwPtr;
if(dwLine<0)
{
memset(pcLineBuf,0,sizeof(pcLineBuf));
memcpy(pcLineBuf,pcTmp,byMaxTmpLine);
dwPtr = dwTmpPtr;
dwLine = byMaxTmpLine;
}
else
--dwPtr;
pcLineBuf[dwLine + 1] = '\0';
m_pcLine.Add(CString(pcLineBuf));
memset(pcLineBuf,0,sizeof(pcLineBuf));
dwTheLineWidth = 0;
dwLine = 0;
}
}
}
pcLineBuf[dwLine] = '\0';
memset(szSource,0,sizeof(szSource));
memcpy((LPVOID)szSource,pcLineBuf,dwLine+1);
nLen = dwLine+1;
return TRUE;
}
BOOL CExBuffer::LoadTxtFile(LPCTSTR szTxtFileName)
{
HANDLE m_pTargetFile = CreateFile(szTxtFileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0);
if(m_pTargetFile == INVALID_HANDLE_VALUE)
return FALSE;
DWORD dwNumBytesToGet = 32768;
BYTE *szFileContent = new BYTE [dwNumBytesToGet + 1];
ATLASSERT(szFileContent != NULL);
memset(szFileContent ,0,sizeof(szFileContent ));
DWORD dwNumBytesRead = 0;
do
{
if (!ReadFile(m_pTargetFile, szFileContent+dwNumBytesRead, dwNumBytesToGet, &dwNumBytesRead, 0))
return FALSE;
if (dwNumBytesRead > 0)
{
// szFileContent[dwNumBytesRead] = '\0';
FillLine(szFileContent,dwNumBytesRead);
dwNumBytesToGet = 32768 - dwNumBytesRead;
}
}while(dwNumBytesRead >0);
m_pcLine.Add(CString(szFileContent));
delete [] szFileContent;
if(m_pTargetFile != INVALID_HANDLE_VALUE)
CloseHandle(m_pTargetFile);
return TRUE;
}
BOOL CExBuffer::LoadHtmlFile(LPCTSTR szHtmlFileName)
{
if(szHtmlFileName == NULL) return FALSE;
CString szTxtFile("\\WINDOWS\\MYPRC.TMP");
Html2Txt(szHtmlFileName,szTxtFile);
m_pcLine.RemoveAll();
BOOL bSuccess = LoadTxtFile(szTxtFile);
DeleteFile(szTxtFile);
return bSuccess;
}
BOOL CExBuffer::LoadPrcFile(LPCTSTR szFileName)
{
BOOL bSuccess = FALSE;
const DWORD dwNumBytesToGet = 6000;
BYTE szFileContent[dwNumBytesToGet + 1];
DWORD dwNumBytesRead;
PRC_FILE_HEADER PRCHeader;
memset(&PRCHeader,0,sizeof(PRC_FILE_HEADER));
CString szTmpFile("\\WINDOWS\\MYPRC.TMP");
HANDLE hTmpFile = CreateFile(szTmpFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
if(hTmpFile == INVALID_HANDLE_VALUE)
return FALSE;
HANDLE m_pTargetFile = CreateFile(szFileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0);
if(m_pTargetFile == INVALID_HANDLE_VALUE)
{
CloseHandle(hTmpFile);
return FALSE;
}
//Read FILE header INFORMATION
if(!ReadFile(m_pTargetFile, &PRCHeader, PRC_FILE_HEADER_LEN, &dwNumBytesRead, 0))
return FALSE;
DWORD dwOffSet;
if(!ReadFile(m_pTargetFile, &dwOffSet, 4, &dwNumBytesRead, 0))
return FALSE;
dwOffSet = SwapLong(dwOffSet);
SetFilePointer(m_pTargetFile,dwOffSet,NULL,FILE_BEGIN);
if(!ReadFile(m_pTargetFile, &dwOffSet, 2, &dwNumBytesRead, 0))
return FALSE;
WORD bCompressed;
bCompressed = SwapWord((WORD)dwOffSet);
ATLASSERT((bCompressed == 1)||(bCompressed == 2)); //1: PLAIN TEXT 2: COMPRESSED
bCompressed--;
DWORD dwLen;
dwLen = GetFileSize(m_pTargetFile,NULL);
WORD nRecs;
nRecs = SwapWord(PRCHeader.wRecords) - 1;
DWORD dwRecLen;
int i;
for (i=0; i<nRecs; i++)
{
// read the record offset
SetFilePointer(m_pTargetFile,0x56 + 8*i,NULL,FILE_BEGIN);
if(!ReadFile(m_pTargetFile, &dwOffSet, 4, &dwNumBytesRead, 0))
return FALSE;
dwOffSet = SwapLong(dwOffSet);
// read start of next record
SetFilePointer(m_pTargetFile,0x5E + 8*i,NULL,FILE_BEGIN);
if(!ReadFile(m_pTargetFile, &dwRecLen, 4, &dwNumBytesRead, 0))
return FALSE;
dwRecLen = SwapLong(dwRecLen);
// for the last, use the file len
if (i==nRecs-1) dwRecLen = dwLen;
dwRecLen -= dwOffSet;
SetFilePointer(m_pTargetFile,dwOffSet,NULL,FILE_BEGIN);
if(!ReadFile(m_pTargetFile, szFileContent, dwRecLen, &dwNumBytesRead, 0))
return FALSE;
if(dwNumBytesRead>0)
{
szFileContent[dwNumBytesRead] = '\0';
if(bCompressed)
DeCode(szFileContent,dwNumBytesRead);
DWORD dwRealSize;
WriteFile(hTmpFile,szFileContent,dwNumBytesRead,&dwRealSize,NULL);
// FillLine(szFileContent,dwNumBytesRead);
}
}
if(m_pTargetFile != INVALID_HANDLE_VALUE)
CloseHandle(m_pTargetFile);
if(hTmpFile != INVALID_HANDLE_VALUE)
{
CloseHandle(hTmpFile);
m_pcLine.RemoveAll();
BOOL bSuccess = LoadTxtFile(szTmpFile);
DeleteFile(szTmpFile);
return bSuccess;
}
return FALSE;
}
BOOL CExBuffer::LoadFile(UINT nType, LPCTSTR szFileName)
{
BOOL bLoadSuccess = FALSE;
ASSERT((nType == FORMAT_TEXT)||
(nType == FORMAT_HTML)||
(nType == FORMAT_PRC));
if((nType != FORMAT_TEXT)&&
(nType != FORMAT_HTML)&&
(nType != FORMAT_PRC ))
return bLoadSuccess;
::SystemParametersInfo(SPI_GETWORKAREA, 0, &m_rectWnd, 0);
m_dwMaxLineWidth = m_rectWnd.right - 10;
HDC hDC = GetDC(NULL);
TEXTMETRIC tm;
memset(&tm,0,sizeof(tm));
GetTextMetrics(hDC,&tm);
ReleaseDC(NULL,hDC);
// m_nMaxLinePerPage = (m_rectWnd.bottom - m_rectWnd.top)/(tm.tmHeight + tm.tmExternalLeading) ;
if (!m_FullScreen)
m_nMaxLinePerPage = 10 - m_byCurrentFontSize;
else
m_nMaxLinePerPage = 12 - m_byCurrentFontSize;
m_pcLine.RemoveAll();
if(nType == FORMAT_TEXT)
bLoadSuccess = LoadTxtFile(szFileName);
else if( nType == FORMAT_HTML)
bLoadSuccess = LoadHtmlFile(szFileName);
else
bLoadSuccess = LoadPrcFile(szFileName);
return bLoadSuccess;
}
BOOL CExBuffer::Html2Txt(CHAR *szBuffer)
{
static int iStart=0;
int iPos,iPointer;
int iLen=strlen( szBuffer );
int nStartPos = 0;
iPos=iPointer=0;
while( iLen-->0 )
{
iPointer++;
//Convert Specific Char in "<>"
// BlockQuote
if( ConvertChar( iLen, szBuffer, iPointer, "<BLOCKQUOTE>", 12 ) )
{
szBuffer[iPos++]='"';
iPointer+=11;
continue;
}
if( ConvertChar( iLen, szBuffer, iPointer, "</BLOCKQUOTE>", 13 ) )
{
szBuffer[iPos++]='"';
iPointer+=12;
continue;
}
// LineBreak
if( ConvertChar( iLen, szBuffer, iPointer, "<BR>", 4 ) )
{
szBuffer[iPos++]=0x0d;
iPointer+=3;
continue;
}
// Citation
if( ConvertChar( iLen, szBuffer, iPointer, "<CITE>", 6 ) )
{
szBuffer[iPos++]='"';
iPointer+=5;
continue;
}
if( ConvertChar( iLen, szBuffer, iPointer, "</CITE>", 7 ) )
{
szBuffer[iPos++]='"';
iPointer+=6;
continue;
}
// Tab
if( ConvertChar( iLen, szBuffer, iPointer, "</TD>", 5 ) )
{
szBuffer[iPos++]=9;
iPointer+=4;
continue;
}
// HTML Command Skipper
if( szBuffer[iPointer-1]=='<' )
{
nStartPos = iPointer-1;
if( szBuffer[iPointer]!='\0' )
{
if( szBuffer[iPointer]>='a' && szBuffer[iPointer]<='z' )
iStart=1;
if( szBuffer[iPointer]>='A' && szBuffer[iPointer]<='Z' )
iStart=1;
if( szBuffer[iPointer]=='!')
iStart=1;
if( szBuffer[iPointer]=='/')
iStart=1;
}
}
if( szBuffer[iPointer-1]=='>')
{
if (iStart == 1 )
{
iStart=0;
continue;
}
}
if( iStart==0 )
{
if( szBuffer[iPointer-1]=='&' )
{
if( ConvertChar( iLen, szBuffer, iPointer, "<" , 4 ) ){ szBuffer[iPos++]='<'; iPointer+=3; continue; } //4
if( ConvertChar( iLen, szBuffer, iPointer, ">" , 4 ) ){ szBuffer[iPos++]='>'; iPointer+=3; continue; } //4
if( ConvertChar( iLen, szBuffer, iPointer, "&" , 5 ) ){ szBuffer[iPos++]='&'; iPointer+=4; continue; } //5
if( ConvertChar( iLen, szBuffer, iPointer, """ , 6 ) ){ szBuffer[iPos++]='"'; iPointer+=5; continue; } //6
if( ConvertChar( iLen, szBuffer, iPointer, "©" , 6 ) ){ szBuffer[iPos++]='('; szBuffer[iPos++]='c'; szBuffer[iPos++]=')'; iPointer+=5; continue; } //6
if( ConvertChar( iLen, szBuffer, iPointer, "™" , 7 ) ){ szBuffer[iPos++]='t';
szBuffer[iPos++]='m'; iPointer+=6; continue; } //7
if( ConvertChar( iLen, szBuffer, iPointer, " " , 6 ) ){ szBuffer[iPos++]=' '; iPointer+=5; continue; } //6
// &#number
if( szBuffer[iPointer]=='#' )
{
// May be a Number
int nCount = 0;
while( iLen-(nCount+1)>0 && // I have char?
szBuffer[iPointer+1+nCount]>='0' && // Are number ?
szBuffer[iPointer+1+nCount]<='9' )
{
nCount++;
}
// If I have number .. try to cenvert it
if( nCount>0 )
{
int nDmm = 0;
int nChar = 0;
int nMul = 1;
while( nDmm < nCount )
{
nChar += (szBuffer[iPointer+nCount-nDmm]-48)*nMul;
printf( "%d\n", szBuffer[iPointer+nCount-nDmm]-48 );
printf( "%d\n", nMul );
nMul *= 10;
nDmm++;
}
if( nChar > 0 )
{
szBuffer[iPos++]=nChar;
iPointer+=nDmm+1;
continue;
}
}
}
}
if( szBuffer[iPointer-1]==0x0d && szBuffer[iPointer]==0x0d )
{
iPointer++;
continue;
}
szBuffer[iPos++]=szBuffer[iPointer-1];
}
}
szBuffer[iPos++]='\0';
return TRUE;
}
BOOL CExBuffer::DeCode(BYTE *szSource, DWORD &nLen)
{
ATLASSERT(szSource != NULL);
BYTE *szTarget = NULL;
szTarget = new BYTE[6000];
if(szTarget == NULL)
return FALSE;
int i,j;
for (j=i=0; j<(INT)nLen; )
{
unsigned int nChar;
nChar = szSource[j++];
if (nChar>0 && nChar<9)
while(nChar--) szTarget[i++] = szSource[j++];
else if (nChar<0x80)
szTarget[i++] = nChar;
else if (nChar>=0xC0)
szTarget[i++] = ' ', szTarget[i++] = nChar ^ 0x80;
else
{
int m,n;
nChar <<= 8;
nChar += szSource[j++];
m = (nChar & 0x3FFF) >> 3;
n = nChar & ((1<<3) - 1);
n += 3;
while (n--)
{
szTarget[i] = szTarget[i-m];
i++;
}
}
}
nLen = i;
memcpy((void*)szSource,(void*)szTarget,nLen);
szSource[nLen] = '\0';
delete[] szTarget;
szTarget = NULL;
return TRUE;
}
WORD CExBuffer::SwapWord(WORD wNumber)
{
return (wNumber>>8) + (wNumber<<8);
}
DWORD CExBuffer::SwapLong(DWORD dwNumber)
{
return ((dwNumber>>24) & 0xFF) + (dwNumber<<24) + ((dwNumber>>8) & 0xFF00) + ((dwNumber<<8) & 0xFF0000);
}
BOOL CExBuffer::Html2Txt(LPCTSTR szHtmlFile, LPCTSTR szTxtFile)
{
int BUFFER_LEN = 32768;
CHAR szfrw[MAX_PATH];
memset(szfrw, 0 , sizeof(szfrw));
wcstombs(szfrw, szHtmlFile, sizeof(szfrw));
FILE *fr = fopen(szfrw , "r");
memset(szfrw, 0 , sizeof(szfrw));
wcstombs(szfrw, szTxtFile, sizeof(szfrw));
FILE *fw = fopen(szfrw , "w");
if ((fw == NULL ) || (fr == NULL))
return FALSE;
char *RBuffer;
RBuffer = (char *)malloc( BUFFER_LEN );
while( fgets( RBuffer, BUFFER_LEN, fr ) != NULL )
{
Html2Txt( RBuffer );
fputs( RBuffer, fw );
}
free( RBuffer );
fclose(fr);
fclose(fw);
return TRUE;
}
VOID CExBuffer::SetFontCtrl(BYTE byFontType, BYTE byFontSize)
{
m_byCurrentFontSize = byFontSize;
m_byCurrentFontType = byFontType;
}
int CExBuffer::ConvertChar(int iLen, char *Buffer, int iPointer, char *Check, int iCheckLen)
{
int iRet=0;
if( iLen+1 >= iCheckLen ){
iPointer--;
while( *Check!='\0' ){
if( Buffer[iPointer] ==*Check ||
(Buffer[iPointer]|32)==*Check ){
iPointer++;
Check++;
} else break;
}
iRet = (*Check==0 || *Check==13 || *Check==';' || *Check==' ');
}
return iRet;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -