From: Dan Crevier, dan@rhino.harvard.edu
Subject: Mastering TCL errata

ERRATA FOR MASTERING THE THINK CLASS LIBRARY BOOK (2/24/96)

This file contains code that is missing or in error in the book. If you find
other errors in the book (other than typos), please EMAIL me what needs 
to be corrected to one of the following adresses:

CompuServe: 76556, 1132
Internet:   rparker@s2.sonnet.com (Rich Parker)

Several of the code examples in the book are missing #include statements 
or have other errors that this document addresses. Please make the following
corrections or additions to your code.


=======================================================================

CHAPTER 3: Managing the Document's Data

On page-69, the CApp::DoNewDialog function includes the statement:

    filetype = CMainFType;
    
This should be changed to read:

    *filetype = CMainFType;

-----

Add the following #include statements at the top of the CApp.cp file,
beginning on page-74:

#include "CNewFile.h"
#include "CMain.h"
#include "CNewView.h"

Also, in the CApp.h file, change the declaration of the 
GetDocTypeFromDialog function to read as follows:

    virtual OSType GetDocTypeFromDialog(CNewFile *dialog);

The additions to the CNewView.h header file are not shown in the book.
These are as follows:

public:

    virtual void OpenFile(SFReply *macSFReply);
    
protected:

    virtual void MakeNewWindow (void);
    
    
-----
    
Also, the code for the OpenFile member function of the CNewView class
wasn't shown in the section dealing with source code additions to the
CNewView.cp source file. This function should be added, as follows:

void CNewView::OpenFile (SFReply *macSFReply)
{
    // override the immediate base class version of this
    // function in order to open a file using the version
    // implemented in the CTextData class.
    
    CTextData::OpenFile (macSFReply);
}

=======================================================================

CHAPTER 4: Creating a Business Account View

When creating the NewAccount dialog, the following identifiers were
assigned to the various controls in the VA (see pp. 114):

    Checking button:    CheckingRadio
    Savings button:     SavingsRadio
    Cash button:        CashRadio
    Credit Card button: CreditRadio
    Asset button:       AssetRadio
    Liability button:   LiabilityRadio

    Account name field: AcctName
    Info field:         InfoText

The foregoing are used to generate the names that appear in the 
enumeration listed on page 133.

-----

The code for the CMain::GetAcctSettings and CMain::UpdateMenus functions
is not provided in the book. It is as follows:

void CMain::GetAcctSettings (Boolean fromDocument, CNewAccountData *data)
{
    if (fromDocument)
    {
        *data = itsAcctData;
    }
    else
    {
        itsAcctData = *data;
    }
}

void CMain::UpdateMenus()
{
    Cell curCell = {0, 0};
    long nextAccount = ((CApp *)gApplication)->theNextAccount;
    
    x_CMain::UpdateMenus();
    if (itsMainPane != NULL)
    {
        if (!((CArrayPane *)itsMainPane)->GetSelect (TRUE, &curCell))
        {
            gBartender->DisableCmd (cmdEditAcct);
            gBartender->DisableCmd (cmdDeleteAcct);
        }
    }
    else
    {
        gBartender->DisableCmd (cmdNewAcct);
        gBartender->DisableCmd (cmdEditAcct);
        gBartender->DisableCmd (cmdDeleteAcct);
    }
    for (long cmd = kFirstAcctCmdID; cmd < nextAccount; cmd++)
    {
        gBartender->EnableCmd (cmd);
    }
}

-----

Missing #include statements for CMain.cp file (pp. 126)

Add the following #include statements at the top of the CMain.cp file:

#include <CArray.h>
#include <CTLpstring.h>
#include <CBartender.h>
#include <CArrayIterator.h>
#include <TCLpstrcmp.h>

#include "CAccount.h"
#include "CNewAccount.h"
#include "CTransaction.h"
#include "CAcctList.h"
#include "CApp.h"
#include "CMainList.h"

also these statements:

extern CBartender   *gBartender;
extern CDesktop     *gDesktop
extern CBureaucrat  *gGopher;
extern CApplication *gApplication;

-----

Missing code from DoCmdDeleteAcct function on page 132

Add the following statement right after the "break;" statement, toward
the top of the page:

    TCLForgetObject (anAccount); // delete the matching CAccount object

-----

Missing code from functions in the CNewAccount class not documented:

void CNewAccount::BeginData(CNewAccountData *initial)
{
	// use data supplied by CMain's GetAcctSettings function
	
	((CMain *)itsSupervisor)->GetAcctSettings (TRUE, initial);
}

void CNewAccount::EndData(CNewAccountData *final)
{
	// return final settings to the CMain class
		
	((CMain *)itsSupervisor)->GetAcctSettings (FALSE, final);
}

=======================================================================

Chapter 5: Examining the CFontList and CSizeList Code (page 208)

The following declaration should be added to the CFontList.h
header file that was generated by the VA:

public:

	// overrides
	void GetCellText(Cell aCell, short availableWidth, StringPtr itsText);

The corresponding definition of the GetCellText function to be added to
the CFontList.cp file is as follows:

/******************************************************************************
 GetCellText (override)

        Get the contents of the indicated cell
 ******************************************************************************/
 
void CFontList::GetCellText (Cell aCell, short availableWidth, StringPtr itsText)
{
	StringPtr pString;
	CArray *itsArray = GetArray();
	itsArray->GetArrayItem (&pString, aCell.v+1);
	TCLpstrcpy(itsText, pString);
}

-----

The following declaration should be added to the CSizeList.h
header file that was generated by the VA:

public:

	// overrides
	void GetCellText (Cell aCell, short availableWidth, StringPtr itsText);

Then add the following global "fontSizes" definitions to the beginning
of the CSizeList.cp file, as follows:

unsigned char *fontSizes[] =
{
	"\p 8", "\p 9", "\p10", "\p12", "\p14", "\p16",
	"\p18", "\p20", "\p24", "\p28", "\p32", "\p36",
	"\p40", "\p48", "\p60", "\p64", "\p72", NULL
};

Finally, add the following definition of the GetCellText function to
the CSizeList.cp file, as follows:

/******************************************************************************
 GetCellText (override)

        Get the contents of the indicated cell
 ******************************************************************************/
 
void CSizeList::GetCellText (Cell aCell, short availableWidth, StringPtr itsText)
{
	StringPtr pString;
	CArray *itsArray = GetArray();
	itsArray->GetArrayItem (&pString, aCell.v+1);
	TCLpstrcpy(itsText, pString);	
}

=======================================================================

Chapter 9: When you don't want to use Object I/O (page 406)

At the top of page 406, right after the declaration of the
WriteContents function, add the following inline function call
and private variable declaration:

virtual void OpenFile (SFReply *macSFReply)
{
	CSimpleSaver::OpenFile(macSFReply);
}

private:

	Handle	h;	// text handle

We have to override the OpenFile function because the x_CMain.h
header file contains an empty version of this function.

-----

Then on the same page (406) modify the ReadContents function to
look like the following:

void CMain::ReadContents (CFileStream *aStream)
{
	h = aStream->GetHandle(); // read the file's data into the handle
}

-----

And then finally, put the remainder of the code that appeared in the
original version of ReadContents into the ContentsToWindow function
in the CMain.cp file, as follows:

void CMain::ContentsToWindow()
{
	HLock(h);
	try_
	{
		fMain_TextPane->SetTextPtr(*h, GetHandleSize(h));
		DisposeHandle(h);
	}
	catch_all_()
	{
		DisposeHandle(h);
	}
	end_try_

}

=======================================================================