Skip to content

Commit

Permalink
Fixed bug with garbled text in the notepad window
Browse files Browse the repository at this point in the history
  • Loading branch information
nickgammon committed Sep 27, 2010
1 parent 7b35548 commit c038158
Show file tree
Hide file tree
Showing 2 changed files with 140 additions and 57 deletions.
192 changes: 135 additions & 57 deletions TextView.cpp
Expand Up @@ -14,14 +14,15 @@ Copyright (C) 2000 Nick Gammon.
#include "sendvw.h"
#include "mainfrm.h"
#include "doc.h"
#include <../src/afximpl.h>

#include "dialogs\GoToLineDlg.h"
#include "dialogs\LuaGsubDlg.h"

#pragma warning( disable : 4100) // unreferenced formal parameter

#ifdef _DEBUG
//#define new DEBUG_NEW
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
Expand Down Expand Up @@ -225,62 +226,6 @@ void CTextView::OnEscape()
}


void CTextView::SerializeRaw(CArchive& ar)
// Read/Write object as stand-alone file.
{
ASSERT_VALID(this);

if (ar.IsStoring())
{
CString strContents;
GetEditCtrl().GetWindowText (strContents);
ar.Write(strContents, strContents.GetLength ());
}
else
{
CFile* pFile = ar.GetFile();
ASSERT(pFile->GetPosition() == 0);
DWORD nLen = pFile->GetLength();
// ReadFromArchive takes the number of characters as argument

// REPLACING: ReadFromArchive(ar, (UINT)nFileSize/sizeof(TCHAR));

// with this (we got garbage at times):

LPVOID hText = LocalAlloc(LMEM_MOVEABLE, (nLen+1)*sizeof(TCHAR));
if (hText == NULL)
AfxThrowMemoryException();

LPTSTR lpszText = (LPTSTR)LocalLock(hText);
ASSERT(lpszText != NULL);
if (ar.Read(lpszText, nLen*sizeof(TCHAR)) != nLen*sizeof(TCHAR))
{
LocalUnlock(hText);
LocalFree(hText);
AfxThrowArchiveException(CArchiveException::endOfFile);
}
// Replace the editing edit buffer with the newly loaded data
lpszText[nLen] = '\0';

// set the text with SetWindowText, then free
BOOL bResult = ::SetWindowText(m_hWnd, lpszText);
LocalUnlock(hText);
LocalFree(hText);

// make sure that SetWindowText was successful
if (!bResult || ::GetWindowTextLength(m_hWnd) < (int)nLen)
AfxThrowMemoryException();

// remove old shadow buffer
delete[] m_pShadowBuffer;
m_pShadowBuffer = NULL;
m_nShadowSize = 0;

}
ASSERT_VALID(this);
} /* end of CTextView::SerializeRaw */


void CTextView::OnViewMaximize()
{
WINDOWPLACEMENT wp;
Expand Down Expand Up @@ -1760,3 +1705,136 @@ void CTextView::OnUpdateCompleteFunction(CCmdUI* pCmdUI)
{
pCmdUI->Enable ();
}


#define VERSION_6 MAKELONG(0, 6)

// from Worstje

void CTextView::Serialize(CArchive& ar)
// Read and write CTextView object to archive, with length prefix.
{
ASSERT_VALID(this);
ASSERT(m_hWnd != NULL);
if (ar.IsStoring())
{
UINT nLen = GetBufferLength();
ar << (DWORD)nLen;
WriteToArchive(ar);
}
else
{
DWORD dwLen;
ar >> dwLen;
if (dwLen > GetEditCtrl().GetLimitText())
// Larger than edit control limit. Call SetLimitText() to set your own max size.
// Refer to documentation for EM_LIMITTEXT for max sizes for your target OS.
AfxThrowArchiveException(CArchiveException::badIndex);
UINT nLen = (UINT)dwLen;
ReadFromArchive(ar, nLen);
}
ASSERT_VALID(this);
}

void CTextView::ReadFromArchive(CArchive& ar, UINT nLen)
// Read certain amount of text from the file, assume at least nLen
// characters (not bytes) are in the file.
{
ASSERT_VALID(this);

LPVOID hText = LocalAlloc(LMEM_MOVEABLE, (nLen+1)*sizeof(TCHAR));

//LPVOID hText = LocalAlloc(LMEM_MOVEABLE, static_cast<UINT>(::ATL::AtlMultiplyThrow(static_cast<UINT>(nLen+1),static_cast<UINT>(sizeof(TCHAR)))));
if (hText == NULL)
AfxThrowMemoryException();

LPTSTR lpszText = (LPTSTR)LocalLock(hText);
ASSERT(lpszText != NULL);
if (ar.Read(lpszText, nLen*sizeof(TCHAR)) != nLen*sizeof(TCHAR))
{
LocalUnlock(hText);
LocalFree(hText);
AfxThrowArchiveException(CArchiveException::endOfFile);
}
// Replace the editing edit buffer with the newly loaded data
lpszText[nLen] = '\0';


#ifndef _UNICODE
if (_AfxGetComCtlVersion() >= VERSION_6)
{
// set the text with SetWindowText, then free
BOOL bResult = ::SetWindowText(m_hWnd, lpszText);
LocalUnlock(hText);
LocalFree(hText);

// make sure that SetWindowText was successful
if (!bResult || ::GetWindowTextLength(m_hWnd) < (int)nLen)
AfxThrowMemoryException();

// remove old shadow buffer
delete[] m_pShadowBuffer;
m_pShadowBuffer = NULL;
m_nShadowSize = 0;

ASSERT_VALID(this);
return;
}
#endif

LocalUnlock(hText);
HLOCAL hOldText = GetEditCtrl().GetHandle();
ASSERT(hOldText != NULL);
LocalFree(hOldText);
GetEditCtrl().SetHandle((HLOCAL)hText);
Invalidate();
ASSERT_VALID(this);
}

void CTextView::WriteToArchive(CArchive& ar)
// Write just the text to an archive, no length prefix.
{
ASSERT_VALID(this);
LPCTSTR lpszText = LockBuffer();
ASSERT(lpszText != NULL);
UINT nLen = GetBufferLength();
TRY
{
ar.Write(lpszText, nLen*sizeof(TCHAR));
}
CATCH_ALL(e)
{
UnlockBuffer();
THROW_LAST();
}
END_CATCH_ALL
UnlockBuffer();
ASSERT_VALID(this);
}

void CTextView::SerializeRaw(CArchive& ar)
// Read/Write object as stand-alone file.
{
ASSERT_VALID(this);
if (ar.IsStoring())
{
WriteToArchive(ar);
}
else
{
CFile* pFile = ar.GetFile();
ASSERT(pFile->GetPosition() == 0);
ULONGLONG nFileSize = pFile->GetLength();
if (nFileSize/sizeof(TCHAR) > GetEditCtrl().GetLimitText())
{
// Larger than edit control limit. Call SetLimitText() to set your own max size.
// Refer to documentation for EM_LIMITTEXT for max sizes for your target OS.
AfxMessageBox(AFX_IDP_FILE_TOO_LARGE);
AfxThrowUserException();
}
// ReadFromArchive takes the number of characters as argument
ReadFromArchive(ar, (UINT)nFileSize/sizeof(TCHAR));
}
ASSERT_VALID(this);
}

5 changes: 5 additions & 0 deletions TextView.h
Expand Up @@ -52,6 +52,11 @@ class CTextView : public CEditView
CString & result,
int & count);


virtual void Serialize(CArchive& ar);
virtual void ReadFromArchive(CArchive& ar, UINT nLen);
virtual void WriteToArchive(CArchive& ar);

// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CTextView)
public:
Expand Down

0 comments on commit c038158

Please sign in to comment.