A tiny contribution to an Haiku Debugger rebirth: a Running Teams window designed similar to old' bdb one.

The skeleton 'hdb' application does nothing usefull beside, as I was trying to get fluent in team_debugger 
messages.

That's pretty much all what I came with during a pathetic attempt to secure some free time to work on 
a (indeed) most wanted native graphical debugger for Haiku. Building libdwarf was pending when I've realized
I wont have time ever. 

Ingo, I hope you don't mind. Fee free to do whatever you want with it, remove included.



git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31066 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Philippe Houdoin 2009-06-15 23:11:19 +00:00
parent 774e234b75
commit f06173c765
10 changed files with 1285 additions and 0 deletions

View File

@ -21,3 +21,5 @@ Application Debugger :
: $(TARGET_LIBSUPC++)
;
HaikuSubInclude gui running_teams_window ;

View File

@ -0,0 +1,16 @@
SubDir HAIKU_TOP src apps debugger gui running_teams_window ;
CCFLAGS += -Werror ;
C++FLAGS += -Werror ;
UsePrivateHeaders debug ;
UsePrivateSystemHeaders ;
Application hdb :
hdb.cpp
RunningTeamsWindow.cpp
TeamsListView.cpp
TeamWindow.cpp
: be tracker translation libdebug.so
;

View File

@ -0,0 +1,138 @@
/*
* Copyright 2009, Philippe Houdoin, phoudoin@haiku-os.org. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include "hdb.h"
#include "RunningTeamsWindow.h"
#include "TeamsListView.h"
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <Application.h>
#include <ListView.h>
#include <ScrollView.h>
#include <File.h>
#include <FindDirectory.h>
#include <Path.h>
RunningTeamsWindow::RunningTeamsWindow()
: BWindow(BRect(100, 100, 500, 250), "Running Teams", B_DOCUMENT_WINDOW,
B_ASYNCHRONOUS_CONTROLS)
{
BMessage settings;
_LoadSettings(settings);
BRect frame;
if (settings.FindRect("running teams window frame", &frame) == B_OK) {
MoveTo(frame.LeftTop());
ResizeTo(frame.Width(), frame.Height());
}
// Add a teams list view
BRect rect = Bounds();
rect.right -= B_V_SCROLL_BAR_WIDTH;
fTeamsListView = new TeamsListView(rect, "RunningTeamsList", B_FOLLOW_ALL);
// Set the message sent on team list item invocation
fTeamsListView->SetInvocationMessage(new BMessage(kMsgDebugThisTeam));
BScrollView * scroller = new BScrollView("RunningTeamsListScroller",
fTeamsListView, B_FOLLOW_ALL_SIDES, B_WILL_DRAW | B_FRAME_EVENTS,
false, true); // Vertical scrollbar only
AddChild(scroller);
}
RunningTeamsWindow::~RunningTeamsWindow()
{
}
void
RunningTeamsWindow::MessageReceived(BMessage* message)
{
switch (message->what) {
case kMsgDebugThisTeam:
{
TeamListItem* item = dynamic_cast<TeamListItem*>(fTeamsListView->ItemAt(
fTeamsListView->CurrentSelection()));
if (item != NULL) {
BMessage message(kMsgOpenTeamWindow);
message.AddInt32("team_id", item->TeamID());
be_app_messenger.SendMessage(&message);
}
break;
}
default:
BWindow::MessageReceived(message);
break;
}
}
bool
RunningTeamsWindow::QuitRequested()
{
_SaveSettings();
be_app_messenger.SendMessage(kMsgRunningTeamsWindowClosed);
return true;
}
// #pragma mark --
status_t
RunningTeamsWindow::_OpenSettings(BFile& file, uint32 mode)
{
BPath path;
if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK)
return B_ERROR;
path.Append("Debugger settings");
return file.SetTo(path.Path(), mode);
}
status_t
RunningTeamsWindow::_LoadSettings(BMessage& settings)
{
BFile file;
status_t status = _OpenSettings(file, B_READ_ONLY);
if (status < B_OK)
return status;
return settings.Unflatten(&file);
}
status_t
RunningTeamsWindow::_SaveSettings()
{
BFile file;
status_t status = _OpenSettings(file,
B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE);
if (status < B_OK)
return status;
BMessage settings('hdbg');
status = settings.AddRect("running teams window frame", Frame());
if (status != B_OK)
return status;
if (status == B_OK)
status = settings.Flatten(&file);
return status;
}

View File

@ -0,0 +1,36 @@
/*
* Copyright 2009, Philippe Houdoin, phoudoin@haiku-os.org. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef RUNNING_TEAMS_WINDOW_H
#define RUNNING_TEAMS_WINDOW_H
#include <Window.h>
class BListView;
class BFile;
class BMessage;
class RunningTeamsWindow : public BWindow {
public:
RunningTeamsWindow();
virtual ~RunningTeamsWindow();
virtual void MessageReceived(BMessage* message);
virtual bool QuitRequested();
private:
status_t _OpenSettings(BFile& file, uint32 mode);
status_t _LoadSettings(BMessage& settings);
status_t _SaveSettings();
BListView* fTeamsListView;
};
static const uint32 kMsgDebugThisTeam = 'dbtm';
#endif // RUNNING_TEAMS_WINDOW_H

View File

@ -0,0 +1,373 @@
/*
* Copyright 2008, Philippe Houdoin, phoudoin@haiku-os.org. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include "hdb.h"
#include "TeamWindow.h"
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <String.h>
#include <Application.h>
#include <File.h>
#include <FindDirectory.h>
#include <Path.h>
#include <debugger.h>
TeamWindow::TeamWindow(team_id team)
: BWindow(BRect(100, 100, 500, 250), "Running Teams", B_DOCUMENT_WINDOW,
B_ASYNCHRONOUS_CONTROLS),
fTeam(team),
fNubThread(-1),
fNubPort(-1),
fListenerThread(-1),
fListenerPort(-1)
{
BMessage settings;
_LoadSettings(settings);
BRect frame;
if (settings.FindRect("team window frame", &frame) == B_OK) {
MoveTo(frame.LeftTop());
ResizeTo(frame.Width(), frame.Height());
}
team_info info;
get_team_info(team, &info);
BString title;
title << "Team " << fTeam << ": " << info.args;
SetTitle(title.String());
_InstallDebugger();
}
TeamWindow::~TeamWindow()
{
_RemoveDebugger();
}
void
TeamWindow::MessageReceived(BMessage* message)
{
switch (message->what) {
default:
BWindow::MessageReceived(message);
break;
}
}
bool
TeamWindow::QuitRequested()
{
/* _SaveSettings();
BMessage update(kMsgSettingsChanged);
update.AddRect("window_frame", Frame());
be_app_messenger.SendMessage(&update);
*/
be_app_messenger.SendMessage(kMsgWindowClosed);
return true;
}
// #pragma mark --
status_t
TeamWindow::_InstallDebugger()
{
char name[32];
status_t result;
snprintf(name, sizeof(name), "team %ld nub listener", fTeam);
printf("Starting %s...\n", name);
// create listener port
fListenerPort = create_port(10, name);
if (fListenerPort < 0)
return fListenerPort;
// spawn the listener thread
fListenerThread = spawn_thread(_ListenerEntry, name,
B_NORMAL_PRIORITY, this);
if (fListenerThread < 0)
return fListenerThread;
// register as this team debugger
printf("Installing team %ld debugger on port 0x%lx...\n",
fTeam, fListenerPort);
fNubPort = install_team_debugger(fTeam, fListenerPort);
if (fNubPort < 0)
return fNubPort;
// init the debug context
result = init_debug_context(&fDebugContext, fTeam, fNubPort);
if (result != B_OK) {
fprintf(stderr, "Failed to init debug context for team %ld: %s\n",
fTeam, strerror(result));
}
// get team nub thread
team_info teamInfo;
result = get_team_info(fTeam, &teamInfo);
if (result != B_OK) {
fprintf(stderr, "Failed to get info for team %ld: %s\n",
fTeam, strerror(result));
}
fNubThread = teamInfo.debugger_nub_thread;
// set the team debug flags
debug_nub_set_team_flags message;
message.flags =
B_TEAM_DEBUG_SIGNALS |
// B_TEAM_DEBUG_PRE_SYSCALL |
// B_TEAM_DEBUG_POST_SYSCALL |
B_TEAM_DEBUG_TEAM_CREATION |
B_TEAM_DEBUG_THREADS |
B_TEAM_DEBUG_IMAGES |
// B_TEAM_DEBUG_STOP_NEW_THREADS |
0;
send_debug_message(&fDebugContext,
B_DEBUG_MESSAGE_SET_TEAM_FLAGS, &message, sizeof(message), NULL, 0);
// resume the listener
resume_thread(fListenerThread);
return B_OK;
}
status_t
TeamWindow::_RemoveDebugger()
{
if (fListenerPort < 0)
// No debugger installed (yet?)
return B_OK;
printf("Stopping team %ld nub listener...\n", fTeam);
printf("Removing team %ld debugger installed on port 0x%lx...\n",
fTeam, fListenerPort);
status_t status = remove_team_debugger(fTeam);
delete_port(fListenerPort);
if (fListenerThread >= 0 && find_thread(NULL) != fListenerThread) {
status_t result;
wait_for_thread(fListenerThread, &result);
fListenerThread = -1;
}
destroy_debug_context(&fDebugContext);
fListenerPort = -1;
return status;
}
status_t
TeamWindow::_ListenerEntry(void *data)
{
return ((TeamWindow*) data)->_Listener();
}
// _Listener
status_t
TeamWindow::_Listener()
{
printf("Team %ld nub listener on port 0x%lx started...\n", fTeam, fListenerPort);
while (true) {
// receive the next debug message
debug_debugger_message code;
debug_debugger_message_data data;
ssize_t bytesRead;
do {
bytesRead = read_port(fListenerPort, (int32 *) &code, &data,
sizeof(debug_debugger_message_data));
} while (bytesRead == B_INTERRUPTED);
if (bytesRead == B_BAD_PORT_ID)
break;
if (bytesRead < 0) {
fprintf(stderr, "Team %ld nub listener: failed to read from "
"listener port: %s. Terminating!\n",
fTeam, strerror(bytesRead));
break;
}
_HandleDebugMessage(code, data);
}
printf("Team %ld nub listener on port 0x%lx stopped.\n", fTeam, fListenerPort);
return B_OK;
}
status_t
TeamWindow::_HandleDebugMessage(debug_debugger_message code,
debug_debugger_message_data & data)
{
char dump[512];
get_debug_message_string(code, dump, sizeof(dump));
printf("Team %ld nub listener: code %d from team %ld received: %s\n",
fTeam, code, data.origin.team, dump);
switch (code) {
case B_DEBUGGER_MESSAGE_DEBUGGER_CALL:
{
// print the debugger message
char debuggerMessage[1024];
ssize_t bytesRead = debug_read_string(&fDebugContext,
data.debugger_call.message, debuggerMessage,
sizeof(debuggerMessage));
if (bytesRead > 0) {
printf(" Thread %ld called debugger(): %s\n",
data.origin.thread, debuggerMessage);
} else {
fprintf(stderr, " Thread %ld called debugger(), but failed"
"to get the debugger message.\n",
data.origin.thread);
}
// fall through...
}
case B_DEBUGGER_MESSAGE_THREAD_DEBUGGED:
case B_DEBUGGER_MESSAGE_BREAKPOINT_HIT:
case B_DEBUGGER_MESSAGE_WATCHPOINT_HIT:
case B_DEBUGGER_MESSAGE_SINGLE_STEP: {
// ATM, just continue
debug_nub_continue_thread message;
message.thread = data.origin.thread;
message.handle_event = B_THREAD_DEBUG_HANDLE_EVENT;
message.single_step = false; // run full speed
status_t result= send_debug_message(&fDebugContext,
B_DEBUG_MESSAGE_CONTINUE_THREAD, &message, sizeof(message),
NULL, 0);
if (result != B_OK) {
fprintf(stderr, "Failed to resume thread %ld: %s\n",
message.thread, strerror(result));
}
break;
}
case B_DEBUGGER_MESSAGE_PRE_SYSCALL:
printf(" pre_syscall.syscall = %ld\n", data.pre_syscall.syscall);
break;
case B_DEBUGGER_MESSAGE_POST_SYSCALL:
printf(" post_syscall.syscall = %ld\n", data.post_syscall.syscall);
break;
case B_DEBUGGER_MESSAGE_SIGNAL_RECEIVED:
printf(" signal_received.signal = %d\n",
data.signal_received.signal);
break;
case B_DEBUGGER_MESSAGE_EXCEPTION_OCCURRED:
{
// print the exception message
char exception[1024];
get_debug_exception_string(data.exception_occurred.exception,
exception, sizeof(exception));
printf(" Thread %ld caused an exception: signal %d, %s\n",
data.origin.thread, data.exception_occurred.signal, exception);
break;
}
case B_DEBUGGER_MESSAGE_TEAM_CREATED:
case B_DEBUGGER_MESSAGE_TEAM_DELETED:
break;
case B_DEBUGGER_MESSAGE_THREAD_CREATED:
printf(" thread_created.new_thread = %ld\n",
data.thread_created.new_thread);
break;
case B_DEBUGGER_MESSAGE_THREAD_DELETED:
printf(" thread_deleted.origin.thread = %ld\n",
data.thread_deleted.origin.thread);
break;
case B_DEBUGGER_MESSAGE_IMAGE_CREATED:
printf(" id = %ld, type = %d, name = %s\n",
data.image_created.info.id,
data.image_created.info.type,
data.image_created.info.name);
break;
case B_DEBUGGER_MESSAGE_IMAGE_DELETED:
printf(" id = %ld, type = %d, name = %s\n",
data.image_deleted.info.id,
data.image_deleted.info.type,
data.image_deleted.info.name);
break;
default:
// unknown message, ignore
break;
}
return B_OK;
}
// ----
status_t
TeamWindow::_OpenSettings(BFile& file, uint32 mode)
{
BPath path;
if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK)
return B_ERROR;
path.Append("Debugger settings");
return file.SetTo(path.Path(), mode);
}
status_t
TeamWindow::_LoadSettings(BMessage& settings)
{
BFile file;
status_t status = _OpenSettings(file, B_READ_ONLY);
if (status < B_OK)
return status;
return settings.Unflatten(&file);
}
status_t
TeamWindow::_SaveSettings()
{
BFile file;
status_t status = _OpenSettings(file,
B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE);
if (status < B_OK)
return status;
BMessage settings('hdbg');
status = settings.AddRect("team window frame", Frame());
if (status != B_OK)
return status;
if (status == B_OK)
status = settings.Flatten(&file);
return status;
}

View File

@ -0,0 +1,51 @@
/*
* Copyright 2008, Philippe Houdoin, phoudoin@haiku-os.org. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef TEAM_WINDOW_H
#define TEAM_WINDOW_H
#include <Window.h>
#include <debug_support.h>
class BFile;
class BMessage;
class TeamWindow : public BWindow {
public:
TeamWindow(team_id team);
virtual ~TeamWindow();
virtual void MessageReceived(BMessage* message);
virtual bool QuitRequested();
team_id Team() { return fTeam; };
private:
status_t _InstallDebugger();
status_t _RemoveDebugger();
static status_t _ListenerEntry(void *data);
status_t _Listener();
status_t _HandleDebugMessage(debug_debugger_message message,
debug_debugger_message_data & data);
status_t _OpenSettings(BFile& file, uint32 mode);
status_t _LoadSettings(BMessage& settings);
status_t _SaveSettings();
// ----
team_id fTeam;
thread_id fNubThread;
port_id fNubPort;
debug_context fDebugContext;
thread_id fListenerThread;
port_id fListenerPort;
};
#endif // TEAM_WINDOW_H

View File

@ -0,0 +1,339 @@
/*
* Copyright 2009, Philippe Houdoin, phoudoin@haiku-os.org. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include "TeamsListView.h"
#include <stdio.h>
#include <string.h>
#include <ListView.h>
#include <Bitmap.h>
#include <FindDirectory.h>
#include <NodeInfo.h>
#include <Path.h>
#include <Roster.h>
#include <MimeType.h>
#include <MessageRunner.h>
#include <String.h>
TeamListItem::TeamListItem(team_info & info)
: BStringItem("", false),
fIcon(NULL)
{
_SetTo(info);
}
TeamListItem::TeamListItem(team_id team)
: BStringItem("", false),
fIcon(NULL)
{
team_info info;
get_team_info(team, &info);
_SetTo(info);
}
TeamListItem::~TeamListItem()
{
delete fIcon;
}
void
TeamListItem::DrawItem(BView *owner, BRect frame, bool complete)
{
BRect rect = frame;
if (fIcon) {
rgb_color highColor = owner->HighColor();
rgb_color lowColor = owner->LowColor();
if (IsSelected() || complete) {
// Draw the background...
if (IsSelected())
owner->SetLowColor(tint_color(lowColor, B_DARKEN_2_TINT));
owner->FillRect(rect, B_SOLID_LOW);
}
BPoint point(rect.left + 2.0f,
rect.top + (rect.Height() - B_MINI_ICON) / 2.0f);
// Draw icon
owner->SetDrawingMode(B_OP_ALPHA);
owner->DrawBitmap(fIcon, point);
owner->SetDrawingMode(B_OP_COPY);
owner->MovePenTo(rect.left + B_MINI_ICON + 8.0f, frame.top + fBaselineOffset);
if (!IsEnabled())
owner->SetHighColor(tint_color(owner->HighColor(), B_LIGHTEN_2_TINT));
else
owner->SetHighColor(0, 0, 0);
owner->DrawString(Text());
owner->SetHighColor(highColor);
owner->SetLowColor(lowColor);
} else
// No icon, fallback on plain StringItem...
BStringItem::DrawItem(owner, rect, complete);
}
void
TeamListItem::Update(BView *owner, const BFont *font)
{
BStringItem::Update(owner, font);
if (Height() < B_MINI_ICON + 4.0f)
SetHeight(B_MINI_ICON + 4.0f);
font_height fontHeight;
font->GetHeight(&fontHeight);
fBaselineOffset = fontHeight.ascent +
+ (Height() - ceilf(fontHeight.ascent + fontHeight.descent)) / 2.0f;
}
/* static */
int
TeamListItem::Compare(const void* a, const void* b)
{
const BListItem *itemA = *static_cast<const BListItem * const *>(a);
const BListItem *itemB = *static_cast<const BListItem * const *>(b);
const TeamListItem *teamItemA = dynamic_cast<const TeamListItem *>(itemA);
const TeamListItem *teamItemB = dynamic_cast<const TeamListItem *>(itemB);
if (teamItemA != NULL && teamItemB != NULL) {
return teamItemA->fTeamInfo.team - teamItemB->fTeamInfo.team;
}
return 0;
}
status_t
TeamListItem::_SetTo(team_info & info)
{
BPath systemPath;
team_info teamInfo = fTeamInfo = info;
find_directory(B_BEOS_SYSTEM_DIRECTORY, &systemPath);
// strip any trailing space(s)...
for (int len = strlen(teamInfo.args) - 1;
len >= 0 && teamInfo.args[len] == ' '; len--) {
teamInfo.args[len] = 0;
}
app_info appInfo;
status_t status = be_roster->GetRunningAppInfo(teamInfo.team, &appInfo);
if (status == B_OK || teamInfo.team == B_SYSTEM_TEAM) {
if (teamInfo.team == B_SYSTEM_TEAM) {
// Get icon and name from kernel
system_info systemInfo;
get_system_info(&systemInfo);
BPath kernelPath(systemPath);
kernelPath.Append(systemInfo.kernel_name);
get_ref_for_path(kernelPath.Path(), &appInfo.ref);
}
} else {
BEntry entry(teamInfo.args, true);
entry.GetRef(&appInfo.ref);
}
SetText(teamInfo.args);
fIcon = new BBitmap(BRect(0, 0, B_MINI_ICON - 1, B_MINI_ICON - 1), B_RGBA32);
status = BNodeInfo::GetTrackerIcon(&appInfo.ref, fIcon, B_MINI_ICON);
if (status != B_OK) {
BMimeType genericAppType(B_APP_MIME_TYPE);
status = genericAppType.GetIcon(fIcon, B_MINI_ICON);
}
if (status != B_OK) {
delete fIcon;
fIcon = NULL;
}
return status;
}
// #pragma mark -
TeamsListView::TeamsListView(BRect rect, const char* name, uint32 resizingMode)
: BListView(rect, name, B_SINGLE_SELECTION_LIST, resizingMode),
fUpdateRunner(NULL)
{
team_info tmi;
get_team_info(B_CURRENT_TEAM, &tmi);
fThisTeam = tmi.team;
}
TeamsListView::~TeamsListView()
{
delete fUpdateRunner;
}
void
TeamsListView::AttachedToWindow()
{
BListView::AttachedToWindow();
_InitList();
be_roster->StartWatching(this, B_REQUEST_LAUNCHED | B_REQUEST_QUIT);
BMessage msg(kMsgUpdateTeamsList);
fUpdateRunner = new BMessageRunner(this, &msg, 100000L); // 10Hz
}
void
TeamsListView::DetachedFromWindow()
{
BListView::DetachedFromWindow();
be_roster->StopWatching(this);
delete fUpdateRunner;
fUpdateRunner = NULL;
// free all items, they will be retrieved again in AttachedToWindow()
for (int32 i = CountItems(); i-- > 0;) {
delete ItemAt(i);
}
MakeEmpty();
}
void
TeamsListView::MessageReceived(BMessage* message)
{
switch (message->what) {
case kMsgUpdateTeamsList:
_UpdateList();
break;
case B_SOME_APP_LAUNCHED:
{
team_id team;
if (message->FindInt32("be:team", &team) != B_OK)
break;
AddItem(new TeamListItem(team));
SortItems(&TeamListItem::Compare);
break;
}
case B_SOME_APP_QUIT:
{
team_id team;
if (message->FindInt32("be:team", &team) != B_OK)
break;
TeamListItem *item = FindItem(team);
if (item != NULL) {
RemoveItem(item);
delete item;
}
break;
}
default:
BListView::MessageReceived(message);
}
}
TeamListItem *
TeamsListView::FindItem(team_id teamId)
{
for (int32 i = CountItems(); i-- > 0;) {
TeamListItem* item = dynamic_cast<TeamListItem*>(ItemAt(i));
if (item == NULL)
continue;
if (item->TeamID() == teamId)
return item;
}
return NULL;
}
void
TeamsListView::_InitList()
{
int32 tmi_cookie = 0;
team_info tmi;
while (get_next_team_info(&tmi_cookie, &tmi) == B_OK) {
TeamListItem * item = new TeamListItem(tmi);
if (tmi.team == B_SYSTEM_TEAM ||
tmi.team == fThisTeam)
// We don't support debugging kernel and... ourself!
// Don't show these two teams
continue;
AddItem(item);
}
// SortItems(&TeamListItem::Compare);
}
void
TeamsListView::_UpdateList()
{
int32 tmi_cookie = 0;
team_info tmi;
TeamListItem *item;
int32 index = 0;
// NOTA: assuming get_next_team_info() returns team ordered by team ID...
while (get_next_team_info(&tmi_cookie, &tmi) == B_OK) {
if (tmi.team == B_SYSTEM_TEAM ||
tmi.team == fThisTeam)
continue; // Ignore kernel and ourself teams
item = (TeamListItem *) ItemAt(index);
while (item && tmi.team > item->TeamID()) {
RemoveItem(item);
delete item;
item = (TeamListItem *) ItemAt(index);
}
if (!item || tmi.team != item->TeamID()) {
// Team not found in known teams list: insert an new item
TeamListItem * item = new TeamListItem(tmi);
if (!item)
index++; // No item with team id bigger found: insert at list end
AddItem(item, index);
}
index++; // Move list sync head.
}
// Remove tail list items, if we don't walk list thru the end
while ((item = (TeamListItem *) ItemAt(index)) != NULL) {
RemoveItem(item);
delete item;
item = (TeamListItem *) ItemAt(++index);
}
}

View File

@ -0,0 +1,66 @@
/*
* Copyright 2009, Philippe Houdoin, phoudoin@haiku-os.org. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef TEAMS_LIST_ITEM_H
#define TEAMS_LIST_ITEM_H
#include <ListView.h>
#include <StringItem.h>
#include <OS.h>
class BBitmap;
class BMessageRunner;
class TeamListItem : public BStringItem {
public:
TeamListItem(team_info & teamInfo);
TeamListItem(team_id teamId);
virtual ~TeamListItem();
public:
virtual void DrawItem(BView *owner, BRect itemRect,
bool drawEverything = false);
virtual void Update(BView *owner, const BFont *font);
team_id TeamID() { return fTeamInfo.team; };
static int Compare(const void* a, const void* b);
private:
status_t _SetTo(team_info & info);
team_info fTeamInfo;
BBitmap * fIcon;
float fBaselineOffset;
};
class TeamsListView : public BListView {
public:
TeamsListView(BRect rect, const char* name,
uint32 resizingMode = B_FOLLOW_LEFT | B_FOLLOW_TOP);
virtual ~TeamsListView();
TeamListItem* FindItem(team_id teamId);
protected:
virtual void AttachedToWindow();
virtual void DetachedFromWindow();
virtual void MessageReceived(BMessage* message);
private:
void _InitList();
void _UpdateList();
BMessageRunner* fUpdateRunner;
team_id fThisTeam;
};
static const uint32 kMsgUpdateTeamsList = 'uptl';
#endif // TEAMS_LIST_VIEW_H

View File

@ -0,0 +1,247 @@
/*
* Copyright 2009, Philippe Houdoin, phoudoin@haiku-os.org. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include "hdb.h"
#include "RunningTeamsWindow.h"
#include "TeamWindow.h"
#include <Application.h>
#include <Alert.h>
#include <TextView.h>
#include <FindDirectory.h>
#include <Directory.h>
#include <Entry.h>
#include <Path.h>
#include <stdio.h>
#include <string.h>
const char* kSignature = "application/x-vnd.Haiku-Debugger";
class Debugger : public BApplication {
public:
Debugger();
virtual ~Debugger();
virtual void ReadyToRun();
virtual void RefsReceived(BMessage *message);
virtual void ArgvReceived(int32 argc, char **argv);
virtual void MessageReceived(BMessage *message);
virtual void AboutRequested();
static void ShowAbout();
private:
status_t Debug(team_id team);
status_t Debug(BEntry &entry);
RunningTeamsWindow * fRunningTeamsWindow;
};
Debugger::Debugger()
: BApplication(kSignature),
fRunningTeamsWindow(NULL)
{
}
Debugger::~Debugger()
{
}
status_t
Debugger::Debug(BEntry &entry)
{
// Does the file really exist?
if (!entry.Exists())
return B_ENTRY_NOT_FOUND;
// TODO
BWindow *window = new TeamWindow(0); // team);
window->Show();
return B_OK;
}
status_t
Debugger::Debug(team_id team)
{
// int32 teamWindows = 0;
// Do we already have that window open?
for (int32 i = CountWindows(); i-- > 0; ) {
TeamWindow *window = dynamic_cast<TeamWindow *>(WindowAt(i));
if (window == NULL)
continue;
if (window->Team() == team) {
window->Activate(true);
return B_OK;
}
// teamWindows++;
}
BWindow *window = new TeamWindow(team);
window->Show();
return B_OK;
}
void
Debugger::ReadyToRun()
{
// are there already windows open?
if (CountWindows() != 0)
return;
// if not, open the running teams window
PostMessage(kMsgOpenRunningTeamsWindow);
}
void
Debugger::RefsReceived(BMessage *message)
{
int32 index = 0;
entry_ref ref;
while (message->FindRef("refs", index++, &ref) == B_OK) {
BEntry entry;
status_t status = entry.SetTo(&ref);
if (status == B_OK)
status = Debug(entry);
if (status != B_OK) {
char buffer[1024];
snprintf(buffer, sizeof(buffer),
"Could not debug \"%s\":\n"
"%s",
ref.name, strerror(status));
(new BAlert("Debugger request",
buffer, "Ok", NULL, NULL,
B_WIDTH_AS_USUAL, B_STOP_ALERT))->Go();
}
}
}
void
Debugger::ArgvReceived(int32 argc, char **argv)
{
BMessage *message = CurrentMessage();
BDirectory currentDirectory;
if (message)
currentDirectory.SetTo(message->FindString("cwd"));
BMessage refs;
for (int i = 1 ; i < argc ; i++) {
BPath path;
if (argv[i][0] == '/')
path.SetTo(argv[i]);
else
path.SetTo(&currentDirectory, argv[i]);
status_t status;
entry_ref ref;
BEntry entry;
if ((status = entry.SetTo(path.Path(), false)) != B_OK
|| (status = entry.GetRef(&ref)) != B_OK) {
fprintf(stderr, "Could not open file \"%s\": %s\n", path.Path(), strerror(status));
continue;
}
refs.AddRef("refs", &ref);
}
RefsReceived(&refs);
}
void
Debugger::MessageReceived(BMessage *message)
{
switch (message->what) {
case kMsgOpenRunningTeamsWindow:
if (fRunningTeamsWindow == NULL) {
fRunningTeamsWindow = new RunningTeamsWindow();
fRunningTeamsWindow->Show();
} else
fRunningTeamsWindow->Activate(true);
break;
case kMsgRunningTeamsWindowClosed:
fRunningTeamsWindow = NULL;
// supposed to fall through
case kMsgWindowClosed:
if (CountWindows() == 1)
// Last window is being closed: quit application
PostMessage(B_QUIT_REQUESTED);
break;
case kMsgOpenTeamWindow:
{
team_id team;
if (message->FindInt32("team_id", &team) == B_OK)
Debug(team);
break;
}
default:
BApplication::MessageReceived(message);
break;
}
}
void
Debugger::AboutRequested()
{
ShowAbout();
}
/*static*/ void
Debugger::ShowAbout()
{
BAlert *alert = new BAlert("about", "Debugger\n"
"\twritten by Philippe Houdoin\n"
"\tCopyright 2009, Haiku Inc.\n", "Ok");
BTextView *view = alert->TextView();
BFont font;
view->SetStylable(true);
view->GetFont(&font);
font.SetSize(18);
font.SetFace(B_BOLD_FACE);
view->SetFontAndColor(0, 15, &font);
alert->Go();
}
// #pragma mark -
int
main(int /* argc */, char ** /* argv */)
{
Debugger app;
app.Run();
return 0;
}

View File

@ -0,0 +1,17 @@
/*
* Copyright 2009, Philippe Houdoin, phoudoin@haiku-os.org. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef HDB_H
#define HDB_H
#include <SupportDefs.h>
static const uint32 kMsgOpenRunningTeamsWindow = 'OpRt';
static const uint32 kMsgRunningTeamsWindowClosed = 'ClRt';
static const uint32 kMsgWindowClosed = 'WiCl';
static const uint32 kMsgOpenTeamWindow = 'OpTw';
#endif /* HDB_H */