Improvements to cmd ConPrintfPaging:

- Even if there is a console, don't do paging when output is redirected to a file; it would just confuse users with prompts they can't see.
- Instead of WriteFile, use WriteConsole (which has a convenient Unicode version).
- Rework the paging algorithm: don't treat end of string the same way as end-of-line (was causing nul bytes to be output after strings that didn't end with \n), and output multiple lines at once when possible.
- Use the screen buffer width, not the window width, to determine when wrapping will happen.
- Take the initial cursor position into account.

svn path=/trunk/; revision=34847
This commit is contained in:
Jeffrey Morlan 2008-07-27 14:03:44 +00:00
parent 12a1603c6e
commit f3fa3ee47e

View file

@ -236,10 +236,10 @@ VOID ConPrintf(LPTSTR szFormat, va_list arg_ptr, DWORD nStdHandle)
INT ConPrintfPaging(BOOL NewPage, LPTSTR szFormat, va_list arg_ptr, DWORD nStdHandle) INT ConPrintfPaging(BOOL NewPage, LPTSTR szFormat, va_list arg_ptr, DWORD nStdHandle)
{ {
INT len; INT len;
PCHAR pBuf;
CONSOLE_SCREEN_BUFFER_INFO csbi; CONSOLE_SCREEN_BUFFER_INFO csbi;
TCHAR szOut[OUTPUT_BUFFER_SIZE]; TCHAR szOut[OUTPUT_BUFFER_SIZE];
DWORD dwWritten; DWORD dwWritten;
HANDLE hOutput = GetStdHandle(nStdHandle);
/* used to count number of lines since last pause */ /* used to count number of lines since last pause */
static int LineCount = 0; static int LineCount = 0;
@ -247,13 +247,10 @@ INT ConPrintfPaging(BOOL NewPage, LPTSTR szFormat, va_list arg_ptr, DWORD nStdHa
/* used to see how big the screen is */ /* used to see how big the screen is */
int ScreenLines = 0; int ScreenLines = 0;
/* the number of chars in a roow */
int ScreenCol = 0;
/* chars since start of line */ /* chars since start of line */
int CharSL = 0; int CharSL;
int i = 0; int from = 0, i = 0;
if(NewPage == TRUE) if(NewPage == TRUE)
LineCount = 0; LineCount = 0;
@ -264,7 +261,7 @@ INT ConPrintfPaging(BOOL NewPage, LPTSTR szFormat, va_list arg_ptr, DWORD nStdHa
//get the size of the visual screen that can be printed too //get the size of the visual screen that can be printed too
if (!GetConsoleScreenBufferInfo(hConsole, &csbi)) if (!GetConsoleScreenBufferInfo(hOutput, &csbi))
{ {
// we assuming its a file handle // we assuming its a file handle
ConPrintf(szFormat, arg_ptr, nStdHandle); ConPrintf(szFormat, arg_ptr, nStdHandle);
@ -272,7 +269,7 @@ INT ConPrintfPaging(BOOL NewPage, LPTSTR szFormat, va_list arg_ptr, DWORD nStdHa
} }
//subtract 2 to account for "press any key..." and for the blank line at the end of PagePrompt() //subtract 2 to account for "press any key..." and for the blank line at the end of PagePrompt()
ScreenLines = (csbi.srWindow.Bottom - csbi.srWindow.Top) - 4; ScreenLines = (csbi.srWindow.Bottom - csbi.srWindow.Top) - 4;
ScreenCol = (csbi.srWindow.Right - csbi.srWindow.Left) + 1; CharSL = csbi.dwCursorPosition.X;
//make sure they didnt make the screen to small //make sure they didnt make the screen to small
if(ScreenLines<4) if(ScreenLines<4)
@ -282,45 +279,32 @@ INT ConPrintfPaging(BOOL NewPage, LPTSTR szFormat, va_list arg_ptr, DWORD nStdHa
} }
len = _vstprintf (szOut, szFormat, arg_ptr); len = _vstprintf (szOut, szFormat, arg_ptr);
#ifdef _UNICODE
pBuf = cmd_alloc(len + 1);
len = WideCharToMultiByte( OutputCodePage, 0, szOut, len + 1, pBuf, len + 1, NULL, NULL) - 1;
#else
pBuf = szOut;
#endif
for(i = 0; i < len; i++) while (i < len)
{ {
// search 'end of string' '\n' or 'end of screen line' // Search until the end of a line is reached
for(; (i < len) && (pBuf[i] != _T('\n') && (CharSL<ScreenCol)) ; i++) if (szOut[i++] != _T('\n') && ++CharSL < csbi.dwSize.X)
CharSL++; continue;
WriteFile (GetStdHandle (nStdHandle),&pBuf[i-CharSL],sizeof(CHAR)*(CharSL+1),&dwWritten,NULL);
LineCount++; LineCount++;
CharSL=0; CharSL=0;
if(LineCount >= ScreenLines) if(LineCount >= ScreenLines)
{ {
if(_strnicmp(&pBuf[i], "\n", 2)!=0) WriteConsole(hOutput, &szOut[from], i-from, &dwWritten, NULL);
WriteFile (GetStdHandle (nStdHandle),_T("\n"),sizeof(CHAR),&dwWritten,NULL); from = i;
if(PagePrompt() != PROMPT_YES) if(PagePrompt() != PROMPT_YES)
{ {
#ifdef _UNICODE
cmd_free(pBuf);
#endif
return 1; return 1;
} }
//reset the number of lines being printed //reset the number of lines being printed
LineCount = 0; LineCount = 0;
CharSL=0; }
} }
} WriteConsole(hOutput, &szOut[from], i-from, &dwWritten, NULL);
#ifdef _UNICODE
cmd_free(pBuf);
#endif
return 0; return 0;
} }