BOOL CDynamoRIOView::Refresh()
{
    if (m_selected_pid <= 0) {
        ZeroStrings();
        return TRUE;
    }
    // We have to grab new stats every refresh
    dr_statistics_t *new_stats = get_dynamorio_stats(m_selected_pid);
    if (new_stats == NULL) {
        if (m_stats != NULL) {
            // Leave the stats for an exited process in place, for viewing
            // and copying
        } else
            return TRUE;
    } else {
        if (m_stats != NULL)
            free_dynamorio_stats(m_stats);
        m_stats = new_stats;
    }

    uint i;
#define MAX_VISIBLE_STATS 75
#define STATS_BUFSZ (MAX_VISIBLE_STATS*(sizeof(single_stat_t)*2/*cover %10u, etc.*/))
    TCHAR buf[STATS_BUFSZ];
    TCHAR *c = buf;
    buf[0] = _T('\0');

    // If I just use a CString hooked up via DDX, re-setting the
    // text causes the top of the visible box to show the top of
    // the stats string; plus the scrollbar goes to the top,
    // unless held in place; probably any reset of the string
    // does an auto-reset of the display and scrollbar position.
    // To have all the text in there do this:
    //      int scroll_pos = m_StatsCtl.GetScrollPos(SB_VERT);
    //      m_StatsCtl.SetWindowText(buf);
    //      m_StatsCtl.LineScroll(scroll_pos);
    // But then there's a lot of flickering: too much.
    // We only put visible text lines in the CEdit box, to reduce the
    // flicker.  It's too hard to do it w/ the CEdit's own scrollbar,
    // which sets itself based on the actual text, so we have a
    // separate one.

    // HACK: I don't know how to find out how many lines will
    // fit w/o putting actual text in there
    if (m_StatsViewLines == 0) {
        for (i = 0; i < m_stats->num_stats &&
                 i < MAX_VISIBLE_STATS /* can't be more than this */; i++) {
            if (c >= &buf[STATS_BUFSZ-STAT_NAME_MAX_LEN*2])
                break;
            c += PrintStat(c, i, FALSE/*no filter*/);
            assert(c < &buf[STATS_BUFSZ-1]);
        }
        m_StatsCtl.SetWindowText(buf);
        UpdateData(FALSE);  // write to screen
        // I tried having only one screenful of string there, and
        // setting the scrollbar range to be larger, but it doesn't
        // seem to support that.
        RECT rect;
        m_StatsCtl.GetRect(&rect);
        CPoint pos(rect.right, rect.bottom);
        m_StatsViewLines = HIWORD(m_StatsCtl.CharFromPos(pos));
        assert(m_StatsViewLines > 0);
        m_StatsSB.SetScrollRange(0, m_stats->num_stats-1, TRUE/*redraw*/);
        c = buf;

        SCROLLINFO info;
        info.cbSize = sizeof(SCROLLINFO);
        info.fMask = SIF_PAGE;
        info.nPage = m_StatsViewLines;
        m_StatsSB.SetScrollInfo(&info);
    }

    int scroll_pos = m_StatsSB.GetScrollPos();
    DWORD shown = 0;
    uint printed;
    for (i = scroll_pos;
         i < m_stats->num_stats && shown < m_StatsViewLines; i++) {
        if (c >= &buf[STATS_BUFSZ-STAT_NAME_MAX_LEN*2])
            break;
        printed = PrintStat(c, i, TRUE/*filter*/);
        c += printed;
        assert(c < &buf[STATS_BUFSZ-1]);
        if (printed > 0)
            shown++;
    }
    m_StatsCtl.SetWindowText(buf);
    // num_stats could have changed so update
    m_StatsSB.SetScrollRange(0, m_stats->num_stats-1, TRUE/*redraw*/);

    if (new_stats == NULL)
        m_Exited = _T("  Exited"); // line right end up with Running
    else
        m_Exited = _T("Running");
#ifndef DRSTATS_DEMO
    m_LogLevel.Format(_T("%d"), m_stats->loglevel);
    m_LogMask.Format(_T("0x%05X"), m_stats->logmask);
    m_LogDir.Format(_T("%") ASCII_PRINTF, m_stats->logdir);
#endif

    if (m_clientStats != NULL) {
#define CLIENTSTATS_BUFSZ USHRT_MAX
        TCHAR buf[CLIENTSTATS_BUFSZ];
        PrintClientStats(buf, &buf[CLIENTSTATS_BUFSZ-1]);
        m_ClientStats.Format(_T("%s"), buf);
    } else
        m_ClientStats.Format(_T(""));

    UpdateData(FALSE);  // write to screen
    return TRUE;
}
void CDynamoRIOView::OnEditCopystats()
{
    if (m_ProcessList.GetCurSel() == 0) {
        MessageBox(_T("No instance selected"), _T("Error"), MB_OK | MYMBFLAGS);
        return;
    }
    if (!OpenClipboard()) {
        MessageBox(_T("Error opening clipboard"), _T("Error"),
                   MB_OK | MYMBFLAGS);
        return;
    }
    EmptyClipboard();

#define CLIPBOARD_BUFSZ USHRT_MAX
    TCHAR buf[CLIPBOARD_BUFSZ];
    TCHAR *pos = buf;

    if (m_selected_pid > 0) {
        if (m_stats != NULL) {
            pos += _stprintf(pos, _T("Process id                  = %d\r\n"),
                             m_stats->process_id);
            pos += _stprintf(pos, _T("Process name                = %") ASCII_PRINTF
                             _T("\r\n"), m_stats->process_name);
            pos += _stprintf(pos, _T("Status                      = %s\r\n"),
                             m_Exited.GetBuffer(0));
#ifndef DRSTATS_DEMO
            pos += _stprintf(pos, _T("Log mask                    = %s\r\n"),
                             m_LogMask.GetBuffer(0));
            pos += _stprintf(pos, _T("Log level                   = %s\r\n"),
                             m_LogLevel.GetBuffer(0));
            pos += _stprintf(pos, _T("Log file                    = %s\r\n"),
                             m_LogDir.GetBuffer(0));
#endif
            pos += _stprintf(pos, _T("\r\nSTATS\r\n"));
            uint i;
            for (i = 0; i < m_stats->num_stats; i++) {
                if (pos >= &buf[STATS_BUFSZ-STAT_NAME_MAX_LEN*2])
                    break;
                // FIXME: Filter here too
                pos += PrintStat(pos, i, TRUE/*filter*/);
                assert(pos < &buf[STATS_BUFSZ-1]);
            }
        } else {
            CString pname;
            m_ProcessList.GetLBText(m_ProcessList.GetCurSel(), pname);
            _stprintf(pos, _T("%s"), pname);
            pos += _tcslen(pos);
        }
    }
    if (m_clientStats != NULL) {
        pos += PrintClientStats(pos, &buf[STATS_BUFSZ-1]);
    }

    size_t len = _tcslen(buf);

    // Allocate a global memory object for the text.
    HGLOBAL hglbCopy = GlobalAlloc(GMEM_DDESHARE,
                                   (len + 1) * sizeof(TCHAR));
    if (hglbCopy == NULL) {
        CloseClipboard();
        return;
    }

    // Lock the handle and copy the text to the buffer.
    LPTSTR lptstrCopy = (LPTSTR) GlobalLock(hglbCopy);
    memcpy(lptstrCopy, buf, (len + 1) * sizeof(TCHAR));
    lptstrCopy[len] = (TCHAR) 0;    // null TCHARacter
    GlobalUnlock(hglbCopy);

    // Place the handle on the clipboard.
    SetClipboardData(
#ifdef UNICODE
                     CF_UNICODETEXT,
#else
                     CF_TEXT,
#endif
                     hglbCopy);

    CloseClipboard();
}
Exemple #3
0
void G_PrintStats(void) {
	const playerStat_t	*columns;
	gclient_t			*cl;
	int					stats[STAT_MAX];
	int					bestStats[STAT_MAX];
	qboolean			reallyBest[STAT_MAX] = { qfalse };
	int					i, j;

	if (level.numPlayingClients == 0) {
		return;
	}

	cl = &level.clients[level.sortedClients[0]];
	GetStats(bestStats, cl);

	for (i = 1; i < level.numPlayingClients; i++) {
		cl = &level.clients[level.sortedClients[i]];
		GetStats(stats, cl);

		for (j = 0; j <= STAT_MAX_ASC; j++) {
			if (stats[j] != bestStats[j]) {
				reallyBest[j] = qtrue;
			}
			if (stats[j] > bestStats[j]) {
				bestStats[j] = stats[j];
			}
		}
		for (; j < STAT_MAX; j++) {
			if (stats[j] != bestStats[j]) {
				reallyBest[j] = qtrue;
			}
			if (stats[j] < bestStats[j]) {
				bestStats[j] = stats[j];
			}
		}
	}

	// Don't highlight the stat if it's the same for all players
	for (j = 0; j < STAT_MAX; j++) {
		if (!reallyBest[j]) {
			bestStats[j] = INT_MAX;
		}
	}

	// disable stats irrelevant in current gametype. column arrays can
	// be removed at this point, but i'd rather keep line length under
	// firm control
	statCol[STAT_ACC].disabled = HasSetSaberOnly();
	statCol[STAT_IMPRESSIVE].disabled = (g_spawnWeapons.integer & WP_DISRUPTOR);

	trap_SendServerCommand(-1, "print \"\n\"");

	if (GT_Team(g_gametype.integer) && g_gametype.integer != GT_REDROVER) {
		if (g_gametype.integer == GT_CTF) {
			if (g_instagib.integer)
				columns = ictfColumns;
			else
				columns = ctfColumns;
		} else {
			if (g_instagib.integer)
				columns = iffaColumns;
			else
				columns = tffaColumns;
		}

		PrintStatsHeader(columns);

		PrintStatsSeparator(columns, teamColorString[TEAM_RED]);
		for (i = 0; i < level.numPlayingClients; i++) {
			cl = level.clients + level.sortedClients[i];
			if (cl->sess.sessionTeam == TEAM_RED)
				PrintClientStats(cl, columns, bestStats);
		}

		PrintStatsSeparator(columns, teamColorString[TEAM_BLUE]);
		for (i = 0; i < level.numPlayingClients; i++) {
			cl = level.clients + level.sortedClients[i];
			if (cl->sess.sessionTeam == TEAM_BLUE) {
				PrintClientStats(cl, columns, bestStats);
			}
		}
	} else {
		if (g_instagib.integer) {
			columns = iffaColumns;
		} else if (g_gametype.integer == GT_REDROVER) {
			columns = tffaColumns;
		} else {
			columns = ffaColumns;
		}

		PrintStatsHeader(columns);

		PrintStatsSeparator(columns, teamColorString[TEAM_FREE]);
		for (i = 0; i < level.numPlayingClients; i++) {
			cl = level.clients + level.sortedClients[i];
			PrintClientStats(cl, columns, bestStats);
		}
	}

	trap_SendServerCommand(-1, "print \"\n\"");

}