xref: /reactos/sdk/lib/conutils/pager.c (revision 8c2e9189)
1 /*
2  * PROJECT:     ReactOS Console Utilities Library
3  * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4  * PURPOSE:     Console/terminal paging functionality.
5  * COPYRIGHT:   Copyright 2017-2018 ReactOS Team
6  *              Copyright 2017-2018 Hermes Belusca-Maito
7  */
8 
9 /**
10  * @file    pager.c
11  * @ingroup ConUtils
12  *
13  * @brief   Console/terminal paging functionality.
14  **/
15 
16 /* FIXME: Temporary HACK before we cleanly support UNICODE functions */
17 #define UNICODE
18 #define _UNICODE
19 
20 #include <windef.h>
21 #include <winbase.h>
22 // #include <winnls.h>
23 #include <wincon.h>  // Console APIs (only if kernel32 support included)
24 #include <strsafe.h>
25 
26 #include "conutils.h"
27 #include "stream.h"
28 #include "screen.h"
29 #include "pager.h"
30 
31 // Temporary HACK
32 #define CON_STREAM_WRITE    ConStreamWrite
33 
34 
35 
36 /* Returns TRUE when all the text is displayed, and FALSE if display is stopped */
37 BOOL
38 ConWritePaging(
39     IN PCON_PAGER Pager,
40     IN PAGE_PROMPT PagePrompt,
41     IN BOOL StartPaging,
42     IN PTCHAR szStr,
43     IN DWORD len)
44 {
45     CONSOLE_SCREEN_BUFFER_INFO csbi;
46 
47     /* Used to see how big the screen is */
48     DWORD ScreenLines = 0;
49 
50     /* Chars since start of line */
51     DWORD CharSL;
52 
53     DWORD from = 0, i = 0;
54 
55     /* Parameters validation */
56     if (!Pager)
57         return FALSE;
58 
59     /* Reset LineCount and return if no string has been given */
60     if (StartPaging == TRUE)
61         Pager->LineCount = 0;
62     if (szStr == NULL)
63         return TRUE;
64 
65     /* Get the size of the visual screen that can be printed to */
66     if (!ConGetScreenInfo(Pager->Screen, &csbi))
67     {
68         /* We assume it's a file handle */
69         CON_STREAM_WRITE(Pager->Screen->Stream, szStr, len);
70         return TRUE;
71     }
72 
73     /*
74      * Get the number of lines currently displayed on screen, minus 1
75      * to account for the "press any key..." prompt from PagePrompt().
76      */
77     ScreenLines = (csbi.srWindow.Bottom - csbi.srWindow.Top);
78     CharSL = csbi.dwCursorPosition.X;
79 
80     /* Make sure the user doesn't have the screen too small */
81     if (ScreenLines < 4)
82     {
83         CON_STREAM_WRITE(Pager->Screen->Stream, szStr, len);
84         return TRUE;
85     }
86 
87     while (i < len)
88     {
89         /* Search until the end of a line is reached */
90         if (szStr[i++] != TEXT('\n') && ++CharSL < csbi.dwSize.X)
91             continue;
92 
93         Pager->LineCount++;
94         CharSL = 0;
95 
96         if (Pager->LineCount >= ScreenLines)
97         {
98             CON_STREAM_WRITE(Pager->Screen->Stream, &szStr[from], i-from);
99             from = i;
100 
101             /* Prompt the user; give him some values for statistics */
102             // FIXME TODO: The prompt proc can also take ScreenLines ??
103             if (!PagePrompt(Pager, from, len))
104                 return FALSE;
105 
106             // TODO: Recalculate 'ScreenLines' in case the user redimensions
107             // the window during the prompt.
108 
109             /* Reset the number of lines being printed */
110             Pager->LineCount = 0;
111         }
112     }
113     if (i > from)
114         CON_STREAM_WRITE(Pager->Screen->Stream, &szStr[from], i-from);
115 
116     return TRUE;
117 }
118 
119 BOOL
120 ConPutsPaging(
121     IN PCON_PAGER Pager,
122     IN PAGE_PROMPT PagePrompt,
123     IN BOOL StartPaging,
124     IN LPTSTR szStr)
125 {
126     DWORD len;
127 
128     /* Return if no string has been given */
129     if (szStr == NULL)
130         return TRUE;
131 
132     len = wcslen(szStr);
133     return ConWritePaging(Pager, PagePrompt, StartPaging, szStr, len);
134 }
135 
136 BOOL
137 ConResPagingEx(
138     IN PCON_PAGER Pager,
139     IN PAGE_PROMPT PagePrompt,
140     IN BOOL StartPaging,
141     IN HINSTANCE hInstance OPTIONAL,
142     IN UINT uID)
143 {
144     INT Len;
145     PWCHAR szStr = NULL;
146 
147     Len = K32LoadStringW(hInstance, uID, (PWSTR)&szStr, 0);
148     if (szStr && Len)
149         return ConWritePaging(Pager, PagePrompt, StartPaging, szStr, Len);
150     else
151         return TRUE;
152 }
153 
154 BOOL
155 ConResPaging(
156     IN PCON_PAGER Pager,
157     IN PAGE_PROMPT PagePrompt,
158     IN BOOL StartPaging,
159     IN UINT uID)
160 {
161     return ConResPagingEx(Pager, PagePrompt, StartPaging,
162                           NULL /*GetModuleHandleW(NULL)*/, uID);
163 }
164 
165 /* EOF */
166