/****************************************************************************
** $Id: quickdebugger.cpp  beta1   edited Dec 10 14:22 $
**
** Copyright (C) 2001-2002 Trolltech AS.  All rights reserved.
**
** This file is part of the Qt Script for Applications framework (QSA).
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.
**
** Licensees holding a valid QSA Beta Evaluation Version license may use
** this file in accordance with the QSA Beta Evaluation Version License
** Agreement provided with the Software.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
**   information about QSA Commercial License Agreements.
** See http://www.trolltech.com/gpl/ for GPL licensing information.
**
** Contact info@trolltech.com if any conditions of this licensing are
** not clear to you.
**
*****************************************************************************/

#include "quickdebugger.h"

#include <qregexp.h>

QuickDebugger::QuickDebugger( QSEngine *e )
    : Debugger( e )
{
}

int QuickDebugger::freeSourceId()
{
    return Debugger::freeSourceId();
}

/*!
 * Returns TRUE if \a var could be found in the current context, FALSE
 * otherwise. On success \a value and \a type are set to the respective
 * values.
 */

bool QuickDebugger::watch( const QString &var,
				 QString &type, QString &value )
{
    QString simple = var;
    simple.replace( QRegExp( "\\[" ), "." );
    simple.replace( QRegExp( "\\]" ), "" );
    QString info = varInfo(simple);
    if ( info.isNull() ) {
	value = type = QString::null;
	return FALSE;
    }
    int eq = info.find( '=' );
    int sep = info.findRev( ':' );
    value = info.mid( eq+1, sep-eq-1 );
    type = info.mid( sep+1 );
    return TRUE;
}

/*!
 * Set \a var to \val. Returns TRUE on success, FALSE if \var couldn't
 * be found in the current context, isn't writable or couldn't be
 * parse as s simple data type. Those types are null, undefined, a boolean,
 * a string or number.
 */

bool QuickDebugger::setVariable( const QString &var, const QString &val )
{
    QString simple = var;
    simple.replace( QRegExp( "\\[" ), "." );
    simple.replace( QRegExp( "\\]" ), "" );
    QString v = val.lower();
    QSObject value;
    bool ok;
    double d;
    if ( v == "null" )
	value = QSNull();
    else if ( v == "undefined" )
	value = QSUndefined();
    else if ( v == "true" )
	value = QSBoolean( TRUE );
    else if ( v == "false" )
	value = QSBoolean( FALSE );
    else if ( d = val.toDouble( &ok ), ok )
	value = QSNumber( d );
    else {
	v = val.stripWhiteSpace();
	QChar c0 = v[ 0 ];
	if ( ( c0 == '"' || c0 == '\'' ) && v[ (int)v.length()-1 ] == c0 )
	    value = QSString( v.mid( 1, v.length()-2 ) );
	else
	    return FALSE;

    }

    return setVar( simple, value );
}

bool QuickDebugger::validBreakpoint( const QString &code, int line )
{
    return Debugger::validBreakpoint( code, line );
}

void QuickDebugger::clearAllBreakpoints( int i )
{
    Debugger::clearAllBreakpoints( i );
}

bool QuickDebugger::stopEvent()
{
    bool ret = TRUE;
    emit stopped( ret );
    return ret;
}

void QuickDebugger::callEvent( const QString &fn, const QString &s )
{
    if ( cStack.count() > 0 ) {
	if ( cStack[ 0 ].line == -1 ) {
	    cStack[ 0 ].line = lineNumber();
	    cStack[ 0 ].sourceId = sourceId();
	}
    }
    if ( fn == "(internal)" ) {
	tmpCStack.push( FALSE );
	return;
    }
    tmpCStack.push( TRUE );
    QuickDebuggerStackFrame sf( QString().sprintf( "#%03d: %s(%s)",
						   cStack.count()+1,
						   fn.latin1(),
						   s.latin1() ),
						   -1,
						   -1
				);
    cStack.prepend( sf );
    emit stackChanged( cStack.count() );
}

void QuickDebugger::returnEvent()
{
    if ( tmpCStack.pop() ) {
	cStack.remove( cStack.begin() );
	emit stackChanged( cStack.count() );
    }
}

QValueList<QuickDebuggerStackFrame> QuickDebugger::backtrace()
{
    if ( cStack.count() > 1 ) {
	QuickDebuggerStackFrame &sf = cStack.first();
	sf.line = lineNumber();
	sf.sourceId = sourceId();
    }
    return cStack;
}
