📄 curses.c
字号:
/** Refresh curses interface windows. */
static void refresh_windows(void)
{
refresh();
f_nLeft = application_windows.pMainWin->_begx;
f_nTop = application_windows.pMainWin->_begy;
f_nWidth = application_windows.pMainWin->_maxx;
f_nHeight = application_windows.pMainWin->_maxy;
refresh_title_window();
refresh_progress_window();
refresh_run_summary_window();
refresh_summary_window();
refresh_details_window();
refresh_options_window();
}
/*------------------------------------------------------------------------*/
/** Refresh the title window. */
static void refresh_title_window(void)
{
const char* const szPackageTitle = "CUnit - A Unit Testing Framework for \'C\' (v" CU_VERSION ")";
const char* const szSite = "http:\\\\cunit.sourceforge.net\\";
static bool bFirstTime = true;
if (!bFirstTime) {
return;
}
wattrset(application_windows.pTitleWin, A_BOLD | COLOR_PAIR(TITLE_COLOR));
mvwprintw(application_windows.pTitleWin,
0, f_nLeft + (f_nWidth - strlen(szPackageTitle))/2,
"%s", szPackageTitle);
wattrset(application_windows.pTitleWin, A_BOLD | A_UNDERLINE | COLOR_PAIR(TITLE_COLOR));
mvwprintw(application_windows.pTitleWin, 1, f_nLeft + (f_nWidth - strlen(szSite))/2,
"%s", szSite);
wattrset(application_windows.pTitleWin, A_NORMAL);
wrefresh(application_windows.pTitleWin);
}
/*------------------------------------------------------------------------*/
/** Refresh the progress bar window. */
static void refresh_progress_window(void)
{
wattrset(application_windows.pProgressWin, A_BOLD);
mvwprintw(application_windows.pProgressWin, 0, 1, (char *)f_szProgress);
show_progress_bar();
wrefresh(application_windows.pProgressWin);
}
/*------------------------------------------------------------------------*/
/** Refresh the summary window. */
static void refresh_summary_window(void)
{
const char* szSummary = "Run : %6u Tests Success : %6u Failed : %6u";
char szTemp[STRING_LENGTH];
memset(szTemp, 0, sizeof(szTemp));
snprintf(szTemp, STRING_LENGTH, szSummary, f_uiTestsRun, f_uiTestsRunSuccessful,
f_uiTestsRun - f_uiTestsRunSuccessful);
werase(application_windows.pSummaryWin);
mvwprintw(application_windows.pSummaryWin, 0, 1, "%s", szTemp);
wrefresh(application_windows.pSummaryWin);
}
/*------------------------------------------------------------------------*/
/** Refresh the run summary window. */
static void refresh_run_summary_window(void)
{
const char* szRunSummary = "Running test \'%s\' of Suite \'%s\'";
char szTemp[STRING_LENGTH];
if (f_pCurrentTest && f_pCurrentSuite) {
snprintf(szTemp, STRING_LENGTH, szRunSummary, f_pCurrentTest->pName, f_pCurrentSuite->pName);
}
else {
snprintf(szTemp, STRING_LENGTH, "%s", "");
}
werase(application_windows.pRunSummaryWin);
mvwprintw(application_windows.pRunSummaryWin, 0, 1, "%s", szTemp);
wrefresh(application_windows.pRunSummaryWin);
}
/*------------------------------------------------------------------------*/
/** Refresh the details window. */
static void refresh_details_window(void)
{
const char* szDetailsTitle = " Details Window";
box(application_windows.pDetailsWin, ACS_VLINE, ACS_HLINE);
mvwprintw(application_windows.pDetailsWin, 0,
f_nLeft + (f_nWidth - strlen(szDetailsTitle))/2, "%s", szDetailsTitle);
scrollok(application_windows.pDetailsWin, CU_TRUE);
wrefresh(application_windows.pDetailsWin);
if (details_pad.pPad) {
prefresh(details_pad.pPad, details_pad.uiPadRow, details_pad.uiPadCol,
details_pad.uiWinTop, details_pad.uiWinLeft,
details_pad.uiWinTop + details_pad.uiWinRows,
details_pad.uiWinLeft + details_pad.uiWinColumns);
}
}
/*------------------------------------------------------------------------*/
/** Refresh the options window. */
static void refresh_options_window(void)
{
int nPos = 0;
const char* szHotKey = NULL;
wclear(application_windows.pOptionsWin);
mvwprintw(application_windows.pOptionsWin, 0, 1, "%s", f_szOptions);
get_hotkey(f_szOptions, NULL);
wattron(application_windows.pOptionsWin, A_BOLD);
while (NULL != (szHotKey = get_hotkey((const char*)NULL, &nPos))) {
mvwaddstr(application_windows.pOptionsWin, 0, nPos + 1, szHotKey);
}
wattroff(application_windows.pOptionsWin, A_BOLD);
wrefresh(application_windows.pOptionsWin);
}
/*------------------------------------------------------------------------*/
/** Show the progress bar window. */
static void show_progress_bar(void)
{
int nLength = 0;
int nIndex = 0;
int nStart = strlen(f_szProgress);
int nColorID = 0;
if (0 == (f_uiTestsRun + f_uiTestsSkipped)) {
nLength = f_nWidth - f_nLeft - nStart - 6;
nColorID = PROGRESS_BACKGROUND_COLOR;
}
else {
nLength = (f_nWidth - f_nLeft - nStart - 6) * ((double)(f_uiTestsRun + f_uiTestsSkipped) / f_uiTotalTests);
nColorID = (!f_uiTestsSkipped && f_uiTestsRun == f_uiTestsRunSuccessful)
? PROGRESS_SUCCESS_COLOR
: PROGRESS_FAILURE_COLOR;
}
wattron(application_windows.pProgressWin, A_BOLD | COLOR_PAIR(nColorID));
for (nIndex = 0; nIndex < nLength; nIndex++) {
mvwprintw(application_windows.pProgressWin, 0, nStart + nIndex, " ");
}
wattroff(application_windows.pProgressWin, COLOR_PAIR(nColorID));
}
/*------------------------------------------------------------------------*/
/** Initialize the message handlers in preparation for running tests. */
static bool test_initialize(void)
{
CU_set_test_start_handler(curses_test_start_message_handler);
CU_set_test_complete_handler(curses_test_complete_message_handler);
CU_set_all_test_complete_handler(curses_all_tests_complete_message_handler);
CU_set_suite_init_failure_handler(curses_suite_init_failure_message_handler);
return true;
}
/*------------------------------------------------------------------------*/
/** Parse a string and return the coded hotkeys.
* If called with szStr non-NULL, the string is simply stored.
* Subsequent calls with szStr NULL will cause the
* hotkeys in the string (chars between parentheses) to
* be returned sequentially in the order in which they
* appear in the original string.
* @param szStr String to parse (non-NULL to set, NULL to parse).
* @param pPos Used to store position of the next '('.
* @return If szStr is non-NULL, it is returned. If szStr is NULL,
* the next hotkey character is returned, or NULL if there
* are no more hotkey characters in the original string.
*/
static const char* get_hotkey(const char* szStr, int* pPos)
{
static char szTemp[128] = "";
static char szString[128] = "";
static int nPos = 0;
int nTempIndex;
char* pS = NULL;
if (szStr) {
nPos = 0;
strcpy(szString, szStr);
return szString;
}
memset(szTemp, 0, sizeof(szTemp));
for (nTempIndex = 0, pS = szString + nPos; *pS; nPos++, pS++) {
if (!nTempIndex && '(' == *pS) {
szTemp[nTempIndex++] = *pS;
*pPos = nPos;
}
else if (nTempIndex && ')' == *pS) {
szTemp[nTempIndex++] = *pS;
szTemp[nTempIndex++] = '\0';
return szTemp;
}
else if (nTempIndex) {
szTemp[nTempIndex++] = *pS;
}
}
return NULL;
}
/*------------------------------------------------------------------------*/
/** Main loop for curses interface.
* Displays actions and responds based on user imput.
* @param pRegistry The CU_pTestRegistry to use for testing (non-NULL).
*/
static STATUS curses_registry_level_run(CU_pTestRegistry pRegistry)
{
char szSuiteName[STRING_LENGTH];
CU_pSuite pSuite = NULL;
bool bContinue = true;
while (bContinue) {
int option = toupper(getch());
switch (option) {
case 'R':
curses_run_all_tests(pRegistry);
break;
case 'S':
read_input_string("Enter Suite Name : ", szSuiteName, STRING_LENGTH);
refresh_details_window();
if (NULL != (pSuite = CU_get_suite_by_name(szSuiteName, (NULL == pRegistry) ? pRegistry : CU_get_registry()))) {
if (STOP == curses_suite_level_run(pSuite)) {
bContinue = false;
}
f_szOptions = MAIN_OPTIONS;
refresh_options_window();
}
break;
case 'L':
list_suites(pRegistry);
break;
case 'F':
show_failures();
break;
case 'Q':
return bContinue = false;
case KEY_UP:
case KEY_DOWN:
case KEY_RIGHT:
case KEY_LEFT:
scroll_window(option, &details_pad, refresh_details_window);
break;
default:
break;
}
}
return STOP;
}
/*------------------------------------------------------------------------*/
/** Run a selected suite within the curses interface.
* Displays actions and responds based on user imput.
* @param pSuite The suite to use for testing (non-NULL).
*/
static STATUS curses_suite_level_run(CU_pSuite pSuite)
{
char szTestName[STRING_LENGTH];
CU_pTest pTest = NULL;
f_szOptions = SUITE_OPTIONS;
refresh_options_window();
while (true) {
int option = toupper(getch());
switch (option) {
case 'R':
curses_run_suite_tests(pSuite);
break;
case 'S':
read_input_string("Enter Test Name : ", szTestName, STRING_LENGTH);
if (NULL != (pTest = CU_get_test_by_name(szTestName, pSuite))) {
curses_run_single_test(pSuite, pTest);
}
refresh_details_window();
break;
case 'L':
list_tests(pSuite);
break;
case 'F':
show_failures();
break;
case 'U':
return CONTINUE;
case 'Q':
return STOP;
case KEY_UP:
case KEY_DOWN:
case KEY_RIGHT:
case KEY_LEFT:
scroll_window(option, &details_pad, refresh_details_window);
break;
default:
break;
}
}
return CONTINUE;
}
/*------------------------------------------------------------------------*/
/** Display a prompt, then read a string from the keyboard.
* @param szPrompt The prompt to display.
* @param szValue The string in which to store the response.
* @param nBytes The length of the szValue buffer.
*/
static void read_input_string(const char szPrompt[], char szValue[], int nBytes)
{
echo();
curs_set(1);
nocbreak();
wclear(application_windows.pOptionsWin);
mvwprintw(application_windows.pOptionsWin, 0, 1, "%s", szPrompt);
wgetnstr(application_windows.pOptionsWin, szValue, nBytes - 1);
refresh_options_window();
cbreak();
curs_set(0);
noecho();
}
/*------------------------------------------------------------------------*/
/** Scroll a window.
* @param nCommand Code for the direction to scroll.
* @param pPad The window to scroll.
* @param parent_refresh Function to call to refresh the parent window.
*/
static void scroll_window(int nCommand, APPPAD* pPad, void (*parent_refresh)(void))
{
if (NULL == pPad->pPad) {
return;
}
switch (nCommand) {
case KEY_UP:
if (pPad->uiPadRow) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -