/*-------------------------------------------------------*/
/*                                                       */
/*   Turbo Vision 1.0                                    */
/*   Turbo Vision Forms Demo                             */
/*   Copyright (c) 1991 by Borland International         */
/*                                                       */
/*   Forms.cpp: Support source file for TVFORMS demo     */
/*-------------------------------------------------------*/

#define Uses_TKeys
#define Uses_TEvent
#define Uses_TRect
#define Uses_TDialog
#define Uses_TStreamableClass
#define Uses_MsgBox
#include <tv.h>
__link( RDialog )
__link( RView )

#if !defined( __FORMS_H )
#include "Forms.h"
#endif  // __FORMS_H

#if !defined( __LISTDLG_H )
#include "Listdlg.h"
#endif  // __LISTDLG_H

#if !defined( __FORMCMDS_H )
#include "Formcmds.h"
#endif  // __FORMCMDS_H

#if !defined( __STRING_H )
#include <string.h>
#endif  // __STRING_H

// Compares two buffers and returns True if contents are equal

Boolean compBlocks( void *buf1, void *buf2, ushort bufSize )
{
    return Boolean(memcmp( buf1, buf2, bufSize ) == 0);
}

const char * const TForm::name = "TForm";

void TForm::write( opstream& os )
{

    TDialog::write( os );
    os << keyWidth;
    
}

void *TForm::read( ipstream& is )
{

    TDialog::read( is );
    is >> keyWidth;
    return this;
}

TStreamable *TForm::build()
{
    return new TForm( streamableInit );
}


TStreamableClass RForm( TForm::name,
                        TForm::build,
                        __DELTA(TForm)
                      );

TForm::TForm( const TRect& bounds, const char *aTitle) :
       TDialog( bounds, aTitle),
       TWindowInit(&TForm::initFrame)
{
}

Boolean TForm::changed()
{
    void *curData;
    ushort compSize;
    Boolean newForm, result;

    compSize = dataSize();
    curData = new char[compSize];
    getData(curData);
    if (prevData == NULL)
	newForm = True;
    else
	newForm = False;

    if (newForm)
	{
	// Dummy up empty record for comparison
	prevData = new char[compSize];
	memset(prevData, 0, compSize);
	}
    if (compBlocks(prevData, curData, compSize))
        result = False;
    else
        result = True;

    delete (curData);
    if (newForm)
	{
	delete(prevData);
	prevData = NULL;
	}
    if (result)
	return True;
    else
	return False;
}

void TForm::handleEvent( TEvent& event)
{
    // Respond to CANCEL button and ESC
    if ( ( (event.what == evKeyDown) && (event.keyDown.keyCode == kbEsc) ) ||
       ( (event.what == evCommand) && (event.message.command == cmCancel) ) )
	{
	clearEvent(event);
	destroy(this);
	return;
	}

    // Respond to SAVE button
    if ( (event.what == evCommand) && (event.message.command == cmFormSave) )
	{
	clearEvent(event);
	if (changed() == True)
	    {
	    if (((TListDialog *)listDialog)->saveForm(this))
		{
		destroy(this);
		return;
		}
            }
	else
	    {
	    destroy(this);                        // not changed
	    return;
	    }
	}

    TDialog::handleEvent(event);

    // Respond to TopForm messages
    if (event.what == evBroadcast)
	if (event.message.command == cmEditingForm)
	    {
	    // Already editing broadcast form?
	    if ( (prevData != NULL) && (event.message.infoPtr == prevData) )
		clearEvent(event);
	    }
	else
	    // Belong to sending ListDialog?
	    if (listDialog == event.message.infoPtr)
	    {
		if (event.message.command == cmTopForm)
		    clearEvent(event);
		else if (event.message.command == cmCanCloseForm)
		    {
		    if (!valid(cmClose))
			clearEvent(event);
		    }
		else if (event.message.command == cmCloseForm)
		    destroy(this);
	   }
}

Boolean TForm::valid(ushort command)
{
    ushort action;

    action = cmYes;                    // assume calling inherited
    if (command == cmClose)
	if (changed())
	    {
	    select();
	    action = messageBox("Form data has been modified. Save? ",
				mfYesNoCancel);
	    switch (action)
		{
		case cmYes:
		// Try to save changes. Cancel if save fails
		    if (!((TListDialog *)listDialog)->saveForm(this))
			action = cmCancel;
		    break;
		case cmNo:
		    break;                // abandon changes
		default :
		    action = cmCancel;            // cancel close request
		}
	    }
	else
	    action = cmNo;                        // no changes
  if (action == cmYes)
      return TDialog::valid(command);
  else
      {
      if (action != cmCancel)
	  return True;
      else
	  return False;

      }
}
