mirror of
https://github.com/reactos/reactos.git
synced 2025-08-01 19:53:22 +00:00
[CONUTILS:PAGER][MORE] Implement text line caching + fix some bugs.
- Implement caching of individual (newline-separated) text lines; this behaviour can be enabled with a flag (enabled by MORE): CON_PAGER_CACHE_INCOMPLETE_LINE. This feature is necessary when reading a text file, whose text lines may span across two or more successive temporary read buffers, and is required for correctly determining whether the lines being read are blank and may be squeezed. - When squeezing blank lines, the blank-line check must be done for each line segment corresponding to the screen line (and following) that need to be displayed. This matches the behaviour of MS MORE.COM. - Fix the IsBlankLine() check to not consider FORM-FEEDs as being blank characters: This is necessary for correctly handling FORM-FEED expansion. Also note that MS MORE.COM only checks for spaces and TABs, so we are slightly overdoing these checks (considering other types of whitespace). - Get rid of ConCallPagerLine() and the intermediate CON_PAGER_DONT_OUTPUT state flag that were used repeatedly for each and every small line chunks. Instead, call directly the user-specified 'PagerLine' callback when we are about to start treating the next line segment to be displayed (see comment above). - Fix the exit return condition of ConPagerWorker(): it should return TRUE whenever we displayed all the required lines, and FALSE otherwise. Otherwise, the previous (buggy) condition on the data being read from the text file, may lead to the prompt not showing when a screenful of text has been displayed, if it happened that the current text buffer becomes empty at the same time (even if, overall, the text file hasn't been fully displayed). - In MorePagerLine(), when we encounter for the first time a blank line that will be squeezed with other successive ones, display a single blank line. But for that, just display one space and a newline: this single space is especially needed in order to force line wrapping when the ENABLE_VIRTUAL_TERMINAL_PROCESSING or DISABLE_NEWLINE_AUTO_RETURN console modes are enabled. Otherwise the cursor remains at the previous line (without wrapping), and just outputting one newline will not make it move past 2 lines as one would naively expect.
This commit is contained in:
parent
aff90f530c
commit
31322f5df9
3 changed files with 363 additions and 109 deletions
|
@ -80,6 +80,19 @@ static BOOL IsBlankLine(IN PCWCH line, IN DWORD cch)
|
|||
WORD wType;
|
||||
for (ich = 0; ich < cch; ++ich)
|
||||
{
|
||||
/*
|
||||
* Explicitly exclude FORM-FEED from the check,
|
||||
* so that the pager can handle it.
|
||||
*/
|
||||
if (line[ich] == L'\f')
|
||||
return FALSE;
|
||||
|
||||
/*
|
||||
* Otherwise do the extended blanks check.
|
||||
* Note that MS MORE.COM only checks for spaces (\x20) and TABs (\x09).
|
||||
* See http://archives.miloush.net/michkap/archive/2007/06/11/3230072.html
|
||||
* for more information.
|
||||
*/
|
||||
wType = 0;
|
||||
GetStringTypeW(CT_CTYPE1, &line[ich], 1, &wType);
|
||||
if (!(wType & (C1_BLANK | C1_SPACE)))
|
||||
|
@ -95,15 +108,12 @@ MorePagerLine(
|
|||
IN PCWCH line,
|
||||
IN DWORD cch)
|
||||
{
|
||||
DWORD ich;
|
||||
|
||||
if (s_dwFlags & FLAG_PLUSn) /* Skip lines */
|
||||
{
|
||||
if (Pager->lineno < s_nNextLineNo)
|
||||
{
|
||||
Pager->dwFlags |= CON_PAGER_DONT_OUTPUT;
|
||||
s_bPrevLineIsBlank = FALSE;
|
||||
return TRUE; /* Don't output */
|
||||
return TRUE; /* Handled */
|
||||
}
|
||||
s_dwFlags &= ~FLAG_PLUSn;
|
||||
}
|
||||
|
@ -113,19 +123,26 @@ MorePagerLine(
|
|||
if (IsBlankLine(line, cch))
|
||||
{
|
||||
if (s_bPrevLineIsBlank)
|
||||
{
|
||||
Pager->dwFlags |= CON_PAGER_DONT_OUTPUT;
|
||||
return TRUE; /* Don't output */
|
||||
}
|
||||
return TRUE; /* Handled */
|
||||
|
||||
for (ich = 0; ich < cch; ++ich)
|
||||
{
|
||||
if (line[ich] == L'\n')
|
||||
{
|
||||
s_bPrevLineIsBlank = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Display a single blank line, independently of the actual size
|
||||
* of the current line, by displaying just one space: this is
|
||||
* especially needed in order to force line wrapping when the
|
||||
* ENABLE_VIRTUAL_TERMINAL_PROCESSING or DISABLE_NEWLINE_AUTO_RETURN
|
||||
* console modes are enabled.
|
||||
* Then, reposition the cursor to the next line, first column.
|
||||
*/
|
||||
if (Pager->PageColumns > 0)
|
||||
ConStreamWrite(Pager->Screen->Stream, TEXT(" "), 1);
|
||||
ConStreamWrite(Pager->Screen->Stream, TEXT("\n"), 1);
|
||||
Pager->iLine++;
|
||||
Pager->iColumn = 0;
|
||||
|
||||
s_bPrevLineIsBlank = TRUE;
|
||||
s_nNextLineNo = 0;
|
||||
|
||||
return TRUE; /* Handled */
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -134,7 +151,8 @@ MorePagerLine(
|
|||
}
|
||||
|
||||
s_nNextLineNo = 0;
|
||||
return FALSE; /* Do output */
|
||||
/* Not handled, let the pager do the default action */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static BOOL
|
||||
|
@ -998,7 +1016,7 @@ int wmain(int argc, WCHAR* argv[])
|
|||
}
|
||||
|
||||
Pager.PagerLine = MorePagerLine;
|
||||
Pager.dwFlags |= CON_PAGER_EXPAND_TABS;
|
||||
Pager.dwFlags |= CON_PAGER_EXPAND_TABS | CON_PAGER_CACHE_INCOMPLETE_LINE;
|
||||
if (s_dwFlags & FLAG_P)
|
||||
Pager.dwFlags |= CON_PAGER_EXPAND_FF;
|
||||
Pager.nTabWidth = s_nTabWidth;
|
||||
|
@ -1023,7 +1041,7 @@ int wmain(int argc, WCHAR* argv[])
|
|||
Encoding = ENCODING_ANSI; // ENCODING_UTF8;
|
||||
|
||||
/* Start paging */
|
||||
bContinue = ConPutsPaging(&Pager, PagePrompt, TRUE, L"");
|
||||
bContinue = ConWritePaging(&Pager, PagePrompt, TRUE, NULL, 0);
|
||||
if (!bContinue)
|
||||
goto Quit;
|
||||
|
||||
|
@ -1050,6 +1068,11 @@ int wmain(int argc, WCHAR* argv[])
|
|||
break;
|
||||
}
|
||||
while (bRet && dwReadBytes > 0);
|
||||
|
||||
/* Flush any cached pager buffers */
|
||||
if (bContinue)
|
||||
bContinue = ConWritePaging(&Pager, PagePrompt, FALSE, NULL, 0);
|
||||
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
|
@ -1100,7 +1123,7 @@ int wmain(int argc, WCHAR* argv[])
|
|||
dwSumReadBytes = dwSumReadChars = 0;
|
||||
|
||||
/* Start paging */
|
||||
bContinue = ConPutsPaging(&Pager, PagePrompt, TRUE, L"");
|
||||
bContinue = ConWritePaging(&Pager, PagePrompt, TRUE, NULL, 0);
|
||||
if (!bContinue)
|
||||
{
|
||||
/* We stop displaying this file */
|
||||
|
@ -1152,6 +1175,10 @@ int wmain(int argc, WCHAR* argv[])
|
|||
}
|
||||
while (bRet && dwReadBytes > 0);
|
||||
|
||||
/* Flush any cached pager buffers */
|
||||
if (bContinue)
|
||||
bContinue = ConWritePaging(&Pager, PagePrompt, FALSE, NULL, 0);
|
||||
|
||||
CloseHandle(hFile);
|
||||
|
||||
/* Check whether we should stop displaying this file */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue