VBoxDbgConsole.cpp revision a8ba1b7dc1d8bae7f95f4030cbc1a3c6920585b7
/* $Id$ */
/** @file
* VBox Debugger GUI - Console.
*/
/*
* Copyright (C) 2006-2007 Sun Microsystems, Inc.
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
* Clara, CA 95054 USA or visit http://www.sun.com if you need
* additional information or have any questions.
*/
/*******************************************************************************
* Header Files *
*******************************************************************************/
#include "VBoxDbgConsole.h"
#ifdef VBOXDBG_USE_QT4
# include <QLabel>
# include <QApplication>
# include <QFont>
# include <QLineEdit>
# include <QHBoxLayout>
#else
# include <qlabel.h>
# include <qapplication.h>
# include <qfont.h>
# include <qtextview.h>
# include <qlineedit.h>
#endif
/*
*
* V B o x D b g C o n s o l e O u t p u t
* V B o x D b g C o n s o l e O u t p u t
* V B o x D b g C o n s o l e O u t p u t
*
*
*/
VBoxDbgConsoleOutput::VBoxDbgConsoleOutput(QWidget *pParent/* = NULL*/, const char *pszName/* = NULL*/)
#ifdef VBOXDBG_USE_QT4
#else
#endif
{
setReadOnly(true);
setUndoRedoEnabled(false);
setOverwriteMode(true);
#ifdef VBOXDBG_USE_QT4
setPlainText("");
#else
#endif
#ifdef Q_WS_MAC
#else
#endif
/* green on black */
#ifdef VBOXDBG_USE_QT4
#else
#endif
}
{
}
{
return;
/*
* Insert line by line.
*/
unsigned iPos = 0;
{
#ifdef VBOXDBG_USE_QT4
#else
#endif
{
if (m_uCurPos == 0)
else
#ifdef VBOXDBG_USE_QT4
#else
#endif
if (iPosNL >= 0)
{
m_uCurLine++;
m_uCurPos = 0;
}
else
}
else
{
m_uCurLine++;
m_uCurPos = 0;
}
/* next */
}
}
/*
*
* V B o x D b g C o n s o l e I n p u t
* V B o x D b g C o n s o l e I n p u t
* V B o x D b g C o n s o l e I n p u t
*
*
*/
VBoxDbgConsoleInput::VBoxDbgConsoleInput(QWidget *pParent/* = NULL*/, const char *pszName/* = NULL*/)
#ifdef VBOXDBG_USE_QT4
#else
#endif
{
#ifdef VBOXDBG_USE_QT4
setEditable(true);
setAutoCompletion(false);
#else
#endif
setMaxCount(50);
if (pEdit)
}
{
}
{
}
void VBoxDbgConsoleInput::returnPressed()
{
/* deal with the current command. */
/* update the history and clear the entry field */
#ifdef VBOXDBG_USE_QT4
{
}
#else
{
}
clearEdit();
#endif
}
/*
*
* V B o x D b g C o n s o l e
* V B o x D b g C o n s o l e
* V B o x D b g C o n s o l e
*
*
*/
VBoxDbgConsole::VBoxDbgConsole(PVM pVM, QWidget *pParent/* = NULL*/, const char *pszName/* = NULL*/)
m_pTimer(NULL), m_fUpdatePending(false), m_Thread(NIL_RTTHREAD), m_EventSem(NIL_RTSEMEVENT), m_fTerminate(false)
{
#ifdef VBOXDBG_USE_QT4
setWindowTitle("VBoxDbg - Console");
#else
setCaption("VBoxDbg - Console");
#endif
/*
* Create the output text box.
*/
m_pOutput = new VBoxDbgConsoleOutput(this);
/* try figure a suitable size */
#ifdef VBOXDBG_USE_QT4
QLabel *pLabel = new QLabel( "11111111111111111111111111111111111111111111111111111111111111111111111111111112222222222", this);
#else
QLabel *pLabel = new QLabel(NULL, "11111111111111111111111111111111111111111111111111111111111111111111111111111112222222222", this); /// @todo
#endif
delete pLabel;
/*
* Create the input combo box (with a label).
*/
#ifdef VBOXDBG_USE_QT4
//pLayout->setSizeConstraint(QLayout::SetMaximumSize);
m_pInput->setDuplicatesEnabled(false);
connect(m_pInput, SIGNAL(commandSubmitted(const QString &)), this, SLOT(commandSubmitted(const QString &)));
# if 0//def Q_WS_MAC
# endif
#else /* QT3 */
m_pInput->setDuplicatesEnabled(false);
connect(m_pInput, SIGNAL(commandSubmitted(const QString &)), this, SLOT(commandSubmitted(const QString &)));
# ifdef Q_WS_MAC
# endif
#endif /* QT3 */
#ifdef VBOXDBG_USE_QT4
/*
* Vertical layout box on the whole widget.
*/
pVLayout->setContentsMargins(0, 0, 0, 0);
#endif
/*
* The tab order is from input to output, not the otherway around as it is by default.
*/
/*
* Setup the timer.
*/
/*
* Init the backend structure.
*/
/*
* Create the critical section, the event semaphore and the debug console thread.
*/
rc = RTThreadCreate(&m_Thread, backThread, this, 0, RTTHREADTYPE_DEBUGGER, RTTHREADFLAGS_WAITABLE, "VBoxDbgC");
if (VBOX_FAILURE(rc))
}
{
Assert(isGUIThread());
/*
* Wait for the thread.
*/
ASMAtomicXchgSize(&m_fTerminate, true);
if (m_Thread != NIL_RTTHREAD)
{
}
/*
* Free resources.
*/
delete m_pTimer;
m_EventSem = 0;
if (m_pszInputBuf)
{
}
m_cbInputBuf = 0;
m_cbInputBufAlloc = 0;
}
{
Assert(isGUIThread());
lock();
#ifdef VBOXDBG_USE_QT4
#else
#endif
/*
* Make sure we've got space for the input.
*/
{
if (!pv)
{
unlock();
return;
}
m_pszInputBuf = (char *)pv;
}
/*
* Add the input and output it.
*/
m_cbInputBuf += cb;
#ifdef VBOXDBG_USE_QT4
#else
#endif
m_pInput->setEnabled(false);
unlock();
}
void VBoxDbgConsole::updateOutput()
{
Assert(isGUIThread());
lock();
m_fUpdatePending = false;
if (m_cbOutputBuf)
{
m_cbOutputBuf = 0;
}
unlock();
}
/**
* Lock the object.
*/
void VBoxDbgConsole::lock()
{
}
/**
* Unlocks the object.
*/
void VBoxDbgConsole::unlock()
{
}
/**
* Checks if there is input.
*
* @returns true if there is input ready.
* @returns false if there not input ready.
* @param pBack Pointer to VBoxDbgConsole::m_Back.
* @param cMillies Number of milliseconds to wait on input data.
*/
{
/* questing for input means it's done processing. */
/* dirty focus hack: */
if (pThis->m_fInputRestoreFocus)
bool fRc = true;
if (!pThis->m_cbInputBuf)
{
}
return fRc;
}
/**
* Read input.
*
* @returns VBox status code.
* @param pBack Pointer to VBoxDbgConsole::m_Back.
* @param pvBuf Where to put the bytes we read.
* @param cbBuf Maximum nymber of bytes to read.
* @param pcbRead Where to store the number of bytes actually read.
* If NULL the entire buffer must be filled for a
* successful return.
*/
/*static*/ DECLCALLBACK(int) VBoxDbgConsole::backRead(PDBGCBACK pBack, void *pvBuf, size_t cbBuf, size_t *pcbRead)
{
if (pcbRead)
*pcbRead = 0;
int rc = VINF_SUCCESS;
if (!pThis->m_fTerminate)
{
if (pThis->m_cbInputBuf)
{
if (*psz)
}
}
else
return rc;
}
/**
* Write (output).
*
* @returns VBox status code.
* @param pBack Pointer to VBoxDbgConsole::m_Back.
* @param pvBuf What to write.
* @param cbBuf Number of bytes to write.
* @param pcbWritten Where to store the number of bytes actually written.
* If NULL the entire buffer must be successfully written.
*/
/*static*/ DECLCALLBACK(int) VBoxDbgConsole::backWrite(PDBGCBACK pBack, const void *pvBuf, size_t cbBuf, size_t *pcbWritten)
{
int rc = VINF_SUCCESS;
{
if (!pv)
{
if (pcbWritten)
*pcbWritten = 0;
return VERR_NO_MEMORY;
}
}
/*
* Add the output.
*/
if (pcbWritten)
*pcbWritten = cbBuf;
if (pThis->m_fTerminate)
/*
* Tell the GUI thread to draw this text.
* We cannot do it from here without frequent crashes.
*/
if (!pThis->m_fUpdatePending)
return rc;
}
/**
* The Debugger Console Thread
*
* @returns VBox status code (ignored).
* @param Thread The thread handle.
* @param pvUser Pointer to the VBoxDbgConsole object.s
*/
{
/*
* Create and execute the console.
*/
if (!pThis->m_fTerminate)
return rc;
}
{
Assert(isGUIThread());
{
{
/* make update pending. */
case VBoxDbgConsoleEvent::kUpdate:
if (!m_fUpdatePending)
{
m_fUpdatePending = true;
#ifdef VBOXDBG_USE_QT4
m_pTimer->setSingleShot(true);
#else
#endif
}
break;
/* dirty hack: restores the focus */
if (m_fInputRestoreFocus)
{
m_fInputRestoreFocus = false;
}
break;
/* the thread terminated */
case VBoxDbgConsoleEvent::kTerminated:
m_pInput->setEnabled(false);
break;
/* paranoia */
default:
break;
}
return true;
}
#ifdef VBOXDBG_USE_QT4
#else
#endif
}