// TextfileDemoDlg.cpp : implementation file
//
#include "stdafx.h"
#include "TextfileDemo.h"
#include "TextfileDemoDlg.h"
#include "textfile.h"
#include <vector>
#include <algorithm>
using namespace std;
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About
#if PEK_TX_TECHLEVEL < 2
#ifdef _UNICODE
typedef wstring TextString;
#else
typedef string TextString;
#endif
void TtoC(CString& a, const TextString& b)
{
a = b.c_str();
}
#else
typedef CString TextString;
void TtoC(CString& a, const TextString& b)
{
a = b;
}
#endif
#ifndef _WIN32_WCE
#define TIMERSTART(TIMEVAR) clock_t TIMEVAR = clock();
#define TIMEREND(TIMEVAR, MESS) TRACE(MESS, (double)(clock() - TIMEVAR) / CLOCKS_PER_SEC);
#else
#define TIMERSTART(TIMEVAR) 0;
#define TIMEREND(TIMEVAR, MESS) 0;
#endif
class defcodepage
{
public:
defcodepage(CString a, UINT b)
{
text=a;
value=b;
}
CString text;
UINT value;
};
/*
CP_ACP ANSI code page
CP_MACCP Macintosh code page
CP_OEMCP OEM code page
CP_SYMBOL Symbol code page (42)
CP_THREAD_ACP The current thread's ANSI code page
CP_UTF7 Translate using UTF-7
CP_UTF8
*/
defcodepage DefaultCodePages[] =
{
defcodepage("CP_ACP (system default)", CP_ACP),
defcodepage("CP_MACCP", CP_MACCP),
defcodepage("CP_OEMCP", CP_OEMCP),
defcodepage("CP_SYMBOL", CP_SYMBOL),
defcodepage("CP_THREAD_ACP", CP_THREAD_ACP),
defcodepage("CP_UTF7", CP_UTF7),
defcodepage("CP_UTF8", CP_UTF8),
};
vector<int> SystemCodepages;
BOOL CALLBACK EnumCodePagesProc(LPTSTR lpCodePageString)
{
SystemCodepages.push_back( _ttoi(lpCodePageString) );
return TRUE;
}
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
//{{AFX_DATA(CAboutDlg)
enum { IDD = IDD_ABOUTBOX };
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
//{{AFX_MSG(CAboutDlg)
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
// No message handlers
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CTextfileDemoDlg dialog
CTextfileDemoDlg::CTextfileDemoDlg(CWnd* pParent /*=NULL*/)
: CDialog(CTextfileDemoDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CTextfileDemoDlg)
m_filename = _T("");
m_text = _T("");
m_first = 0;
m_last = 0;
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CTextfileDemoDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CTextfileDemoDlg)
DDX_Control(pDX, IDC_COMBO_CODEPAGE, m_codepage);
DDX_Control(pDX, IDC_COMBO_FORMAT, m_format);
DDX_Text(pDX, IDC_EDIT_FILENAME, m_filename);
DDX_Text(pDX, IDC_EDIT_TEXT, m_text);
DDX_Text(pDX, IDC_EDIT_FIRSTCHAR, m_first);
DDX_Text(pDX, IDC_EDIT_LASTCHAR, m_last);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CTextfileDemoDlg, CDialog)
//{{AFX_MSG_MAP(CTextfileDemoDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BUTTON_SAVE, OnButtonSave)
ON_BN_CLICKED(IDC_BUTTON_LOAD, OnButtonLoad)
ON_BN_CLICKED(IDC_BUTTON_BROWSE, OnButtonBrowse)
ON_BN_CLICKED(IDC_BUTTON_SELFTEST, OnButtonSelftest)
ON_BN_CLICKED(IDC_BUTTON_FULLTEXT, OnButtonFulltext)
ON_CBN_SELCHANGE(IDC_COMBO_FORMAT, OnSelchangeComboFormat)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CTextfileDemoDlg message handlers
BOOL CTextfileDemoDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
#ifndef _WIN32_WCE
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
#endif
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
CString encodings[] = { _T("ASCII"), _T("UNI16_BE"), _T("UNI16_LE"), _T("UTF-8") };
for(int k=0; k<sizeof(encodings)/sizeof(CString); k++)
m_format.AddString( encodings[k] );
// TODO: Add extra initialization here
m_text = _T("Hello world!");
m_filename = _T("testfile.txt");
m_first = 32;
m_last = 0xffff;
UpdateData(FALSE);
m_format.SetCurSel(1);
EnumSystemCodePages(&EnumCodePagesProc, CP_SUPPORTED);
for(int i=0; i<sizeof(DefaultCodePages)/sizeof(defcodepage); i++)
m_codepage.AddString( DefaultCodePages[i].text );
sort(SystemCodepages.begin(), SystemCodepages.end());
for(int j=0; j<(int)SystemCodepages.size(); j++)
{
if(IsValidCodePage( SystemCodepages[j] ) )
{
CString a;
a.Format(_T("%d"), SystemCodepages[j]);
m_codepage.AddString(a);
}
}
m_codepage.SetCurSel(0);
CString s;
s.Format(_T("System codepage: %d"), GetACP());
GetDlgItem(IDC_STATIC_SYSTEMCP)->SetWindowText(s);
return TRUE; // return TRUE unless you set the focus to a control
}
UINT CTextfileDemoDlg::GetSelectedCodepage()
{
CString selected;
m_codepage.GetLBText(m_codepage.GetCurSel(), selected);
for(int i=0; i<sizeof(DefaultCodePages)/sizeof(defcodepage); i++)
{
if(DefaultCodePages[i].text == selected)
return DefaultCodePages[i].value;
}
return _ttoi(selected);
}
void CTextfileDemoDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CTextfileDemoDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
#ifndef _WIN32_WCE
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
#endif
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
// The system calls this to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CTextfileDemoDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
void CTextfileDemoDlg::OnButtonSave()
{
CWaitCursor wc;
UpdateData();
TRACE(_T("Start writing...\n"));
TIMERSTART(writetime);
CTextFileWrite file(m_filename, (CTextFileBase::TEXTENCODING) m_format.GetCurSel());
#if PEK_TX_TECHLEVEL > 0
file.SetCodePage( GetSelectedCodepage() );
#endif
if(!file.IsOpen())
{
MessageBox(_T("Couldn't open file!"), NULL, MB_ICONWARNING|MB_OK);
return;
}
#ifdef _UNICODE
file << m_text;
#else
int cp = GetSelectedCodepage();
if(cp != CP_ACP && file.GetEncoding() == CTextFileBase::ASCII)
{
CString s;
s.Format("You are writing n ASCII-file. Sense you are running a none-Unicode version"
" of this program the code-page you have selected will not be used when"
" the file is written.\r\n\r\nInstead you could convert the string that be written"
" to a a wstring with the system code page (%d). The will this Unicode-string"
" be converted with codepage you selected (%d) when the file is written."
" Do you want to do this? Otherwise will"
" file be written without any conversion.", GetACP(), cp);
int res = MessageBox(s, NULL, MB_YESNO|MB_ICONQUESTION);
if(res == IDYES)
{
wstring temp;
CTextFileBase::ConvertCharToWstring(m_text, temp);
file << temp.c_str();
}
else
//Write without converting
file << m_text;
}
else
file << m_text;
#endif
if( file.IsDataLost() )
MessageBox( _T("Data was lost when the file was written. This means that some Unicode-characters couldn't be converted to multi-byte characters"),
NULL,
MB_ICONWARNING|MB_OK);
TIMEREND(writetime, _T("Time to write: %f.\n"));
}
void CTextfileDemoDlg::OnButtonLoad()
{
/* //The follow code converts file to UTF_8
{
wstring tot;
{
CTextFileRead file(m_filename);
ASSERT(file.IsOpen());
file.Read(tot);
}
{
CTextFileWrite file(m_filename, CTextFileWrite::UTF_8);
ASSERT(file.IsOpen());
file.Write(tot.c_str());
}
}
*/
CWaitCursor wc;
UpdateData();
TRACE(_T("Start reading...\n"));
TIMERSTART(readtime);
CTextFileRead file(m_filename);
#if PEK_TX_TECHLEVEL > 0
file.SetCodePage( GetSelectedCodepage() );
#endif
if(!file.IsOpen())
{
MessageBox(_T("Couldn't open file!"), NULL, MB_ICONWARNING|MB_OK);
return;
}
TextString tot;
#ifdef _UNICODE
file.Read(tot);
#else
int cp = GetSelectedCodepage();
if(cp != CP_ACP && file.GetEncoding() == CTextFileBase::ASCII)
{
CString s;
s.Format("This is an ASCII-file. Sense you are running a none-Unicode version"
" of this program the code-page you have selected will not be used when"
" the file is read.\r\n\r\nInstead you could read the file to a wstring"
" (Unicode) with the codepage you selected (%d), and then convert the Unicode"
" string to an multibyte string with the system code page (%d). Do you want to do this? Otherwise will"
" file be read without any conversion.", cp, GetACP());
int res = MessageBox(s, NULL, MB_YESNO|MB_ICONQUESTION);
if(res == IDYES)
{
//Read the file to a Unicode-string.
wstring temp;
file.Read(temp);
//Convert the Unicode-string to an ordinary string
string simple;
CTextFileBase::ConvertWcharToString(temp.c_str(), simple);
tot = simple.c_str();
}
else
//Read without converting
file.Read(tot);
}
else
file.Read(tot);
#endif
TIMEREND(readtime, _T("Time to read: %f.\n"));
m_format.SetCurSel( file.GetEncoding() );
TtoC(m_text, tot);
//Note! If file is large, the edit box may not change data in Win9x
UpdateData(FALSE);
OnSelchangeComboFormat();
if( file.IsDataLost() )
MessageBox( _T("Data was lost when reading file. This means that some Unicode-characters couldn't be converted to multi-byte characters."),
NULL,
MB_ICONWARNING|MB_OK);
}
void CTextfileDemoDlg::OnButtonBrowse()
{
UpdateData();
CFileDialog dlg(TRUE, NULL, m_filename, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
_T("Text Files (*.txt)|*.txt|All Files (*.*)|*.*||"));
if(dlg.DoModal())
{
m_filename = dlg.m_ofn.lpstrFile;
UpdateData(FALSE);
}
}
void CTextfileDemoDlg::OnButtonSelftest()
{
UpdateData();
wchar_t first = (wchar_t)m_first,
last = (wchar_t)m_last;
int count =last-first+1;
if(count < 1)
return;
CString mess;
mess.Format(_T("A string with %d characters will be constructed, and writed to the current file with the current encoding. Then the file will be read an be compared with the constructed string. Current filename will be used. Continue?"), count);
if(AfxMessageBox(mess, MB_ICONQUESTION|MB_YESNO) != IDYES)
return;
CWaitCursor wc;
wstring out, in;
for(wchar_t x=first; x<=last; x++)
//Ignore wrapping
if(x != 13 && x != 10)
{
out += x;
if(x==last)
break;
}
TRACE(_T("Start writing...\n"));
TIMERSTART(writetime);
{
CTextFileWrite outfile(m_filename, (CTextFileWrite::TEXTENCODING) m_format.GetCurSel());
ASSERT(outfile.IsOpen());
outfile << out.c_str();
}
TIMEREND(writetime, _T("Time to write: %f.\n"));
TRACE(_T("Start reading...\n"));
TIMERSTART(readtime);
{
CTextFileRead infile(m_filename);
ASSERT(infile.IsOpen());
infile.Read(in);
}
TIMEREND(readtime, _T("Time to read: %f.\n"));
if(in == out)
MessageBox(_T("Match."));
else
{
CString mess;
mess.Format(_T("Strings doesn't match!\r\n\r\nCharacters written: ")
_T("%d\nCharacters read: %d"),
out.size(),
in.size());
MessageBox(mess);
}
}
void CTextfileDemoDlg::OnButtonFulltext()
{
CString mess;
mess.Format(_T("This test will create, write and read strings and test if any data is lost. All encodings will be used, and all possible strings (string, wstring and CString). Continue?"));
if(AfxMessageBox(mess, MB_ICONQUESTION|MB_YESNO) != IDYES)
return;
CWaitCursor wc;
CString enc[] = { _T("ASCII"), _T("UNI16_BE"), _T("UNI16_LE"), _T("UTF_8") };
//Test string...
for(int test=0; test<4; test++)
{
string out, in;
unsigned char first = 32, last = 255;
for(unsigned char x=first; x<=last; x++)
//Ignore wrapping
if(x != 13 && x != 10)
{
out += x;
if(x%10 == 0)
{
out += "\r\n";
}
if(x==last)
break;
}
TRACE(_T("Testing: string in %s...\n"), enc[test]);
TIMERSTART(writetime);
{
CTextFileWrite outfile(m_filename, (CTextFileWrite::TEXTENCODING) test); //m_format.GetCurSel());
ASSERT(outfile.IsOpen());
outfile << out.c_str();
}
TIMEREND(writetime, _T("Time to write: %f.\n"));
TIMERSTART(readtime);
{
CTextFileRead infile(m_filename);
ASSERT(infile.IsOpen());
infile.Read(in);
}
TIMEREND(readtime, _T("Time to read: %f.\n"));
if(in != out)
{
CString mess;
mess.Format(_T("Strings doesn't match!\r\n\r\nCharacters written: ")
_T("%d\nCharacters read: %d"),
out.size(),
in.size());
MessageBox(mess);
}
else
TRACE(_T("Test OK!\n\n"));
}
//Test wstring...
{
wstring out, in;
for(test=0; test<4; test++)
{
if(test == 0 || test == 1)
{
out = L"";
wchar_t first = 32, last = 127; //255;
if(test != 0)
last = 0xFFFF;
for(wchar_t x=first; x<=last; x++)
//Ignore wrapping
if(x != 13 && x != 10)
{
out += x;
if(x%10 == 0)
{
out += L"\r\n";
}
if(x==last)
break;
}
}
TRACE(_T("Testing: wstring in %s...\n"), enc[test]);
TIMERSTART(writetime);
{
CTextFileWrite outfile(m_filename, (CTextFileWrite::TEXTENCODING) test); //m_format.GetCurSel());
ASSERT(outfile.IsOpen());
outfile << out.c_str();
}
TIMEREND(writetime, _T("Time to write: %f.\n"));
TIMERSTART(readtime);
{
CTextFileRead infile(m_filename);
ASSERT(infile.IsOpen());
infile.Read(in);
}
TIMEREND(readtime, _T("Time to read: %f.\n"));
if(in != out)
{
for(int i=0; i<(int)out.size(); i++)
{
if(in[i] != out[i])
{
wchar_t xi = in[i]; //, xo = out[i];
xi++;
}
}
CString mess;
mess.Format(_T("Wstrings doesn't match!\r\n\r\nCharacters written: ")
_T("%d\nCharacters read: %d"),
out.size(),
in.size());
MessageBox(mess);
}
else
TRACE(_T("Test OK!\n\n"));
}
}
//Test Cstring...
for(test=0; test<4; test++)
{
#ifdef _UNICODE
static CString out, in;
if(test == 0 || test == 1)
{
wchar_t first = 32, last = 127; //255;
if(test != 0)
last = 0xFFFF;
out = _T("");
for(wchar_t x=first; x<=last; x++)
//Ignore wrapping
if(x != 13 && x != 10)
{
out += x;
if(x%10 == 0)
{
out += L"\r\n";
}
if(x==last)
break;
}
}
#else
CString out, in;
unsigned char first = 32, last = 255;
for(unsigned char x=first; x<=last; x++)
//Ignore wrapping
if(x != 13 && x != 10)
{
out += x;
if(x%10 == 0)
{
out += "\r\n";
}
if(x==last)
break;
}
#endif
TRACE(_T("Testing: CString in %s...\n"), enc[test]);
TIMERSTART(writetime);
{
CTextFileWrite outfile(m_filename, (CTextFileWrite::TEXTENCODING) test); //m_format.GetCurSel());
ASSERT(outfile.IsOpen());
outfile << out;
}
TIMEREND(writetime, _T("Time to write: %f.\n"));
TIMERSTART(readtime);
{
CTextFileRead infile(m_filename);
ASSERT(infile.IsOpen());
TextString temp;
infile.Read(temp);
TtoC(in, temp);
}
TIMEREND(readtime, _T("Time to read: %f.\n"));
if(in != out)
{
CString mess;
mess.Format(_T("CStrings doesn't match!\r\n\r\nCharacters written: ")
_T("%d\nCharacters read: %d"),
out.GetLength(),
in.GetLength());
MessageBox(mess);
}
else
TRACE(_T("Test OK!\n\n"));
}
}
void CTextfileDemoDlg::OnSelchangeComboFormat()
{
m_codepage.EnableWindow( m_format.GetCurSel() == 0 ? TRUE : FALSE );
}