2016-10-22 21:54:29 +00:00
|
|
|
/*
|
2017-10-16 21:58:23 +00:00
|
|
|
* PROJECT: ReactOS Console Utilities Library
|
|
|
|
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
|
|
|
|
* PURPOSE: Console/terminal paging functionality.
|
2021-06-09 14:30:30 +00:00
|
|
|
* COPYRIGHT: Copyright 2017-2021 Hermes Belusca-Maito
|
|
|
|
* Copyright 2021 Katayama Hirofumi MZ
|
2016-10-22 21:54:29 +00:00
|
|
|
*/
|
|
|
|
|
2018-02-01 23:35:08 +00:00
|
|
|
/**
|
|
|
|
* @file pager.h
|
|
|
|
* @ingroup ConUtils
|
|
|
|
*
|
|
|
|
* @brief Console/terminal paging functionality.
|
|
|
|
**/
|
|
|
|
|
2016-10-22 21:54:29 +00:00
|
|
|
#ifndef __PAGER_H__
|
|
|
|
#define __PAGER_H__
|
|
|
|
|
2017-10-16 21:58:23 +00:00
|
|
|
#pragma once
|
|
|
|
|
2016-10-22 21:54:29 +00:00
|
|
|
#ifndef _UNICODE
|
|
|
|
#error The ConUtils library at the moment only supports compilation with _UNICODE defined!
|
|
|
|
#endif
|
|
|
|
|
2018-01-27 14:48:59 +00:00
|
|
|
#ifdef __cplusplus
|
|
|
|
extern "C" {
|
|
|
|
#endif
|
|
|
|
|
2016-10-22 21:54:29 +00:00
|
|
|
// #include <wincon.h>
|
|
|
|
|
2021-06-09 14:30:30 +00:00
|
|
|
struct _CON_PAGER;
|
2021-06-27 00:23:12 +00:00
|
|
|
|
|
|
|
typedef BOOL
|
|
|
|
(__stdcall *CON_PAGER_LINE_FN)(
|
2021-06-09 14:30:30 +00:00
|
|
|
IN OUT struct _CON_PAGER *Pager,
|
|
|
|
IN PCTCH line,
|
|
|
|
IN DWORD cch);
|
|
|
|
|
|
|
|
/* Flags for CON_PAGER */
|
[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.
2021-06-28 18:08:38 +00:00
|
|
|
#define CON_PAGER_EXPAND_TABS (1 << 0)
|
|
|
|
#define CON_PAGER_EXPAND_FF (1 << 1)
|
|
|
|
// Whether or not the pager will cache the line if it's incomplete (not NEWLINE-terminated).
|
|
|
|
#define CON_PAGER_CACHE_INCOMPLETE_LINE (1 << 2)
|
2016-10-22 21:54:29 +00:00
|
|
|
|
|
|
|
typedef struct _CON_PAGER
|
|
|
|
{
|
2021-06-09 14:30:30 +00:00
|
|
|
/* Console screen properties */
|
2016-10-22 21:54:29 +00:00
|
|
|
PCON_SCREEN Screen;
|
2021-06-27 00:23:12 +00:00
|
|
|
DWORD PageColumns;
|
|
|
|
DWORD PageRows;
|
2021-06-09 14:30:30 +00:00
|
|
|
|
|
|
|
/* Paging parameters */
|
|
|
|
CON_PAGER_LINE_FN PagerLine; /* The line function */
|
2021-06-27 00:23:12 +00:00
|
|
|
DWORD dwFlags; /* The CON_PAGER_... flags */
|
2021-06-09 14:30:30 +00:00
|
|
|
LONG nTabWidth;
|
|
|
|
DWORD ScrollRows;
|
|
|
|
|
|
|
|
/* Data buffer */
|
[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.
2021-06-28 18:08:38 +00:00
|
|
|
PCTCH CachedLine; /* Cached line, HeapAlloc'ated */
|
|
|
|
SIZE_T cchCachedLine; /* Its length (number of characters) */
|
|
|
|
SIZE_T ich; /* The current index of character in TextBuff (a user-provided source buffer) */
|
2021-06-09 14:30:30 +00:00
|
|
|
|
|
|
|
/* Paging state */
|
[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.
2021-06-28 18:08:38 +00:00
|
|
|
PCTCH CurrentLine; /* Pointer to the current line (either within a user-provided source buffer, or to CachedLine) */
|
|
|
|
SIZE_T ichCurr; /* The current index of character in CurrentLine */
|
|
|
|
SIZE_T iEndLine; /* End (length) of CurrentLine */
|
|
|
|
DWORD nSpacePending; /* Pending spaces for TAB expansion */
|
2021-06-09 14:30:30 +00:00
|
|
|
DWORD iColumn; /* The current index of column */
|
|
|
|
DWORD iLine; /* The physical output line count of screen */
|
|
|
|
DWORD lineno; /* The logical line number */
|
2016-10-22 21:54:29 +00:00
|
|
|
} CON_PAGER, *PCON_PAGER;
|
|
|
|
|
2017-10-01 16:03:44 +00:00
|
|
|
#define INIT_CON_PAGER(pScreen) {(pScreen), 0}
|
|
|
|
|
2021-06-09 14:30:30 +00:00
|
|
|
#define InitializeConPager(pPager, pScreen) \
|
2017-10-01 16:03:44 +00:00
|
|
|
do { \
|
2021-06-09 14:30:30 +00:00
|
|
|
ZeroMemory((pPager), sizeof(*(pPager))); \
|
|
|
|
(pPager)->Screen = (pScreen); \
|
2017-10-01 16:03:44 +00:00
|
|
|
} while (0)
|
|
|
|
|
2017-10-16 21:58:23 +00:00
|
|
|
|
2021-06-27 00:23:12 +00:00
|
|
|
typedef BOOL
|
|
|
|
(__stdcall *PAGE_PROMPT)(
|
2020-08-23 17:10:11 +00:00
|
|
|
IN PCON_PAGER Pager,
|
|
|
|
IN DWORD Done,
|
|
|
|
IN DWORD Total);
|
2016-10-22 21:54:29 +00:00
|
|
|
|
|
|
|
BOOL
|
|
|
|
ConWritePaging(
|
|
|
|
IN PCON_PAGER Pager,
|
|
|
|
IN PAGE_PROMPT PagePrompt,
|
|
|
|
IN BOOL StartPaging,
|
2020-08-23 17:10:11 +00:00
|
|
|
IN PCTCH szStr,
|
2016-10-22 21:54:29 +00:00
|
|
|
IN DWORD len);
|
|
|
|
|
|
|
|
BOOL
|
|
|
|
ConPutsPaging(
|
|
|
|
IN PCON_PAGER Pager,
|
|
|
|
IN PAGE_PROMPT PagePrompt,
|
|
|
|
IN BOOL StartPaging,
|
2020-08-23 17:10:11 +00:00
|
|
|
IN PCTSTR szStr);
|
2016-10-22 21:54:29 +00:00
|
|
|
|
2017-10-01 16:03:44 +00:00
|
|
|
BOOL
|
|
|
|
ConResPagingEx(
|
|
|
|
IN PCON_PAGER Pager,
|
|
|
|
IN PAGE_PROMPT PagePrompt,
|
|
|
|
IN BOOL StartPaging,
|
|
|
|
IN HINSTANCE hInstance OPTIONAL,
|
|
|
|
IN UINT uID);
|
|
|
|
|
2016-10-22 21:54:29 +00:00
|
|
|
BOOL
|
|
|
|
ConResPaging(
|
|
|
|
IN PCON_PAGER Pager,
|
|
|
|
IN PAGE_PROMPT PagePrompt,
|
|
|
|
IN BOOL StartPaging,
|
|
|
|
IN UINT uID);
|
|
|
|
|
2018-01-27 14:48:59 +00:00
|
|
|
#ifdef __cplusplus
|
|
|
|
}
|
|
|
|
#endif
|
2017-10-16 21:58:23 +00:00
|
|
|
|
2016-10-22 21:54:29 +00:00
|
|
|
#endif /* __PAGER_H__ */
|
2017-10-16 21:58:23 +00:00
|
|
|
|
|
|
|
/* EOF */
|