status_t
DebugReportGenerator::_DumpRunningThreads(BFile& _output)
{
	AutoLocker< ::Team> locker(fTeam);

	BString data("\nActive Threads:\n");
	WRITE_AND_CHECK(_output, data);
	BObjectList< ::Thread> threads;
	::Thread* thread;
	for (ThreadList::ConstIterator it = fTeam->Threads().GetIterator();
		  (thread = it.Next());) {
		 threads.AddItem(thread);
	}

	threads.SortItems(&_CompareThreads);
	for (int32 i = 0; (thread = threads.ItemAt(i)) != NULL; i++) {
		try {
			data.SetToFormat("\tthread %" B_PRId32 ": %s %s\n", thread->ID(),
					thread->Name(), thread->IsMainThread()
						? "(main)" : "");
			WRITE_AND_CHECK(_output, data);

			if (thread->State() == THREAD_STATE_STOPPED) {
				data.SetToFormat("\t\tstate: %s",
					UiUtils::ThreadStateToString(thread->State(),
							thread->StoppedReason()));
				const BString& stoppedInfo = thread->StoppedReasonInfo();
				if (stoppedInfo.Length() != 0)
					data << " (" << stoppedInfo << ")";
				data << "\n\n";
				WRITE_AND_CHECK(_output, data);

				// we need to release our lock on the team here
				// since we might need to block and wait
				// on the stack trace.
				BReference< ::Thread> threadRef(thread);
				locker.Unlock();
				status_t error = _DumpDebuggedThreadInfo(_output, thread);
				if (error != B_OK)
					return error;
				locker.Lock();
			}
		} catch (...) {
			return B_NO_MEMORY;
		}
	}

	return B_OK;
}
status_t
DebugReportGenerator::_DumpLoadedImages(BFile& _output)
{
	AutoLocker< ::Team> locker(fTeam);

	BString data("\nLoaded Images:\n");
	WRITE_AND_CHECK(_output, data);
	BObjectList<Image> images;
	for (ImageList::ConstIterator it = fTeam->Images().GetIterator();
		 Image* image = it.Next();) {
		 images.AddItem(image);
	}

	images.SortItems(&_CompareImages);

	Image* image = NULL;
	data.SetToFormat("\tID\t\tText Base\tText End\tData Base\tData"
		" End\tType\tName\n\t");
	WRITE_AND_CHECK(_output, data);
	data.Truncate(0L);
	data.Append('-', 80);
	data.Append("\n");
	WRITE_AND_CHECK(_output, data);
	for (int32 i = 0; (image = images.ItemAt(i)) != NULL; i++) {
		const ImageInfo& info = image->Info();
		char buffer[32];
		try {
			target_addr_t textBase = info.TextBase();
			target_addr_t dataBase = info.DataBase();

			data.SetToFormat("\t%" B_PRId32 "\t0x%08" B_PRIx64 "\t"
				"0x%08" B_PRIx64 "\t0x%08" B_PRIx64 "\t0x%08" B_PRIx64 "\t"
				"%-7s\t%s\n", info.ImageID(), textBase, textBase + info.TextSize(),
				dataBase, dataBase + info.DataSize(),
				UiUtils::ImageTypeToString(info.Type(), buffer,
					sizeof(buffer)), info.Name().String());

			WRITE_AND_CHECK(_output, data);
		} catch (...) {
			return B_NO_MEMORY;
		}
	}

	return B_OK;
}
// ---------------------------------------------------------------
// AddTranslationItems
//
// Envious of that "Save As" menu in ShowImage? Well, you can have your own!
// AddTranslationItems will add menu items for all translations from the
// basic format you specify (B_TRANSLATOR_BITMAP, B_TRANSLATOR_TEXT etc).
// The translator ID and format constant chosen will be added to the message
// that is sent to you when the menu item is selected.
//
// The following code is a modified version of code
// written by Jon Watte from
// http://www.b500.com/bepage/TranslationKit2.html
//
// Preconditions:
//
// Parameters: intoMenu, the menu where the entries are created
//             fromType, the type of translators to put on
//                       intoMenu
//             kModel, the BMessage model for creating the menu
//                     if NULL, B_TRANSLATION_MENU is used
//             kTranslationIdName, the name used for
//                                 translator_id in the menuitem,
//                                 if NULL, be:translator is used
//             kTranslatorTypeName, the name used for
//                                  output format id in the menuitem
//             roster, BTranslatorRoster used to find translators
//                     if NULL, the default translators are used
//             
//
// Postconditions:
//
// Returns: B_BAD_VALUE, if intoMenu is NULL
//          B_OK, if successful
//          error value if not successful
// ---------------------------------------------------------------
status_t
BTranslationUtils::AddTranslationItems(BMenu *intoMenu, uint32 fromType,
	const BMessage *kModel, const char *kTranslatorIdName,
	const char *kTranslatorTypeName, BTranslatorRoster *roster)
{
	if (!intoMenu)
		return B_BAD_VALUE;
		
	if (!roster)
		roster = BTranslatorRoster::Default();

	if (!kTranslatorIdName)
		kTranslatorIdName = "be:translator";

	if (!kTranslatorTypeName)
		kTranslatorTypeName = "be:type";

	translator_id * ids = NULL;
	int32 count = 0;
	status_t err = roster->GetAllTranslators(&ids, &count);
	if (err < B_OK)
		return err;

	BObjectList<translator_info> infoList;

	for (int tix = 0; tix < count; tix++) {
		const translation_format *formats = NULL;
		int32 numFormats = 0;
		bool ok = false;
		err = roster->GetInputFormats(ids[tix], &formats, &numFormats);
		if (err == B_OK) {
			for (int iix = 0; iix < numFormats; iix++) {
				if (formats[iix].type == fromType) {
					ok = true;
					break;
				}
			}
		}
		if (!ok)
			continue;

		// Get supported output formats
		err = roster->GetOutputFormats(ids[tix], &formats, &numFormats); 
		if (err == B_OK) {
			for (int oix = 0; oix < numFormats; oix++) {
				if (formats[oix].type != fromType) {
					infoList.AddItem(_BuildTranslatorInfo(ids[tix],
						const_cast<translation_format*>(&formats[oix])));
				}
			}
		}
	}

	// Sort alphabetically by name
	infoList.SortItems(&_CompareTranslatorInfoByName);

	// Now add the menu items
	for (int i = 0; i < infoList.CountItems(); i++) {
		translator_info* info = infoList.ItemAt(i);

		BMessage *itemmsg;
		if (kModel)
			itemmsg = new BMessage(*kModel);
		else
			itemmsg = new BMessage(B_TRANSLATION_MENU);
		itemmsg->AddInt32(kTranslatorIdName, info->translator);
		itemmsg->AddInt32(kTranslatorTypeName, info->type);
		intoMenu->AddItem(new BMenuItem(info->name, itemmsg));

		// Delete object created in _BuildTranslatorInfo
		delete info;
	}

	delete[] ids;
	return B_OK;
}
status_t
ThreadModelLoader::_Load()
{
	// create a model
	fThreadModel = new(std::nothrow) ThreadModel(fModel, fThread);
	if (fThreadModel == NULL)
		return B_NO_MEMORY;

	// collect all wait objects
	BObjectList<Model::ThreadWaitObject> waitObjects;

	int32 groupCount = fThread->CountThreadWaitObjectGroups();
	for (int32 i = 0; i < groupCount; i++) {
		Model::ThreadWaitObjectGroup* group
			= fThread->ThreadWaitObjectGroupAt(i);

		if (!group->GetThreadWaitObjects(waitObjects))
			return B_NO_MEMORY;
	}

	// sort them by type and name
	waitObjects.SortItems(&compare_by_type_and_name);

	// create the groups
	int32 waitObjectCount = waitObjects.CountItems();
	printf("%" B_PRId32 " wait objects\n", waitObjectCount);
	for (int32 i = 0; i < waitObjectCount;) {
		printf("new wait object group at %" B_PRId32 "\n", i);
		// collect the objects for this group
		Model::ThreadWaitObject* firstObject = waitObjects.ItemAt(i);
		int32 k = i + 1;
		for (; k < waitObjectCount; k++) {
			if (compare_by_type_and_name(firstObject, waitObjects.ItemAt(k))
					!= 0) {
				break;
			}
		}

		if (fThreadModel->AddWaitObjectGroup(waitObjects, i, k) == NULL)
			return B_NO_MEMORY;

		i = k;
	}

	// filter the events
	thread_id threadID = fThread->ID();
	bool done = false;
	uint32 count = 0;

	system_profiler_event_header** events = fModel->Events();
	size_t eventCount = fModel->CountEvents();
	for (size_t i = 0; i < eventCount; i++) {
		system_profiler_event_header* header = events[i];
		void* buffer = header + 1;

		// process the event
		bool keepEvent = false;

		switch (header->event) {
			case B_SYSTEM_PROFILER_THREAD_REMOVED:
			{
				system_profiler_thread_removed* event
					= (system_profiler_thread_removed*)buffer;
				if (event->thread == threadID)
					done = true;
				break;
			}

			case B_SYSTEM_PROFILER_THREAD_SCHEDULED:
			{
				system_profiler_thread_scheduled* event
					= (system_profiler_thread_scheduled*)buffer;
				keepEvent = event->thread == threadID
					|| event->previous_thread == threadID ;
				break;
			}

			case B_SYSTEM_PROFILER_THREAD_ENQUEUED_IN_RUN_QUEUE:
			{
				thread_enqueued_in_run_queue* event
					= (thread_enqueued_in_run_queue*)buffer;
				keepEvent = event->thread == threadID;
				break;
			}

			case B_SYSTEM_PROFILER_THREAD_REMOVED_FROM_RUN_QUEUE:
			{
				thread_removed_from_run_queue* event
					= (thread_removed_from_run_queue*)buffer;
				keepEvent = event->thread == threadID;
				break;
			}

			default:
				break;
		}

		if (keepEvent)
			fThreadModel->AddSchedulingEvent(header);

		// periodically check whether we're supposed to abort
		if (++count % 32 == 0) {
			AutoLocker<BLocker> locker(fLock);
			if (fAborted)
				return B_ERROR;
		}
	}

	return B_OK;
}