ReactOS 0.4.16-dev-2498-g8632030
pager.c File Reference

Console/terminal paging functionality. More...

#include <windef.h>
#include <winbase.h>
#include <wincon.h>
#include <winnls.h>
#include <strsafe.h>
#include "conutils.h"
#include "stream.h"
#include "screen.h"
#include "pager.h"
Include dependency graph for pager.c:

Go to the source code of this file.

Macros

#define UNICODE
 
#define _UNICODE
 
#define CON_STREAM_WRITE   ConStreamWrite
 
#define CP_SHIFTJIS   932
 
#define CP_HANGUL   949
 
#define CP_JOHAB   1361
 
#define CP_GB2312   936
 
#define CP_BIG5   950
 
#define IsCJKCodePage(CodePage)
 

Functions

static INT GetWidthOfCharCJK (IN UINT nCodePage, IN WCHAR ch)
 
static BOOL GetNextLine (IN OUT PCON_PAGER Pager, IN PCTCH TextBuff, IN SIZE_T cch)
 Retrieves a new text line, or continue fetching the current one.
 
static BOOL ConPagerWorker (IN PCON_PAGER Pager, IN PCTCH TextBuff, IN SIZE_T cch)
 Does the main paging work: fetching text lines and displaying them.
 
ConWritePaging

Pages the contents of a user-specified character buffer on the screen.

Parameters
[in]PagerPager object that describes where the paged output is issued.
[in]PagePromptA user-specific callback, called when a page has been displayed.
[in]StartPagingSet to TRUE for initializing the paging operation; FALSE during paging.
[in]szStrPointer to the character buffer whose contents are to be paged.
[in]lenLength of the character buffer pointed by szStr, specified in number of characters.
Returns
TRUE when all the contents of the character buffer has been displayed; FALSE if the paging operation has been stopped (controlled via PagePrompt).
BOOL ConWritePaging (IN PCON_PAGER Pager, IN PAGE_PROMPT PagePrompt, IN BOOL StartPaging, IN PCTCH szStr, IN SIZE_T len)
 
BOOL ConPutsPaging (IN PCON_PAGER Pager, IN PAGE_PROMPT PagePrompt, IN BOOL StartPaging, IN PCTSTR szStr)
 
BOOL ConResPagingEx (IN PCON_PAGER Pager, IN PAGE_PROMPT PagePrompt, IN BOOL StartPaging, IN HINSTANCE hInstance OPTIONAL, IN UINT uID)
 
BOOL ConResPaging (IN PCON_PAGER Pager, IN PAGE_PROMPT PagePrompt, IN BOOL StartPaging, IN UINT uID)
 

Detailed Description

Console/terminal paging functionality.

Definition in file pager.c.

Macro Definition Documentation

◆ _UNICODE

#define _UNICODE

Definition at line 18 of file pager.c.

◆ CON_STREAM_WRITE

#define CON_STREAM_WRITE   ConStreamWrite

Definition at line 32 of file pager.c.

◆ CP_BIG5

#define CP_BIG5   950

Definition at line 38 of file pager.c.

◆ CP_GB2312

#define CP_GB2312   936

Definition at line 37 of file pager.c.

◆ CP_HANGUL

#define CP_HANGUL   949

Definition at line 35 of file pager.c.

◆ CP_JOHAB

#define CP_JOHAB   1361

Definition at line 36 of file pager.c.

◆ CP_SHIFTJIS

#define CP_SHIFTJIS   932

Definition at line 34 of file pager.c.

◆ IsCJKCodePage

#define IsCJKCodePage (   CodePage)
Value:
((CodePage) == CP_SHIFTJIS || (CodePage) == CP_HANGUL || \
/* (CodePage) == CP_JOHAB || */ \
(CodePage) == CP_BIG5 || (CodePage) == CP_GB2312)
#define CP_GB2312
Definition: pager.c:37
#define CP_BIG5
Definition: pager.c:38
#define CP_HANGUL
Definition: pager.c:35
#define CP_SHIFTJIS
Definition: pager.c:34

Definition at line 41 of file pager.c.

◆ UNICODE

Definition at line 17 of file pager.c.

Function Documentation

◆ ConPagerWorker()

static BOOL ConPagerWorker ( IN PCON_PAGER  Pager,
IN PCTCH  TextBuff,
IN SIZE_T  cch 
)
static

Does the main paging work: fetching text lines and displaying them.

Definition at line 218 of file pager.c.

222{
223 const DWORD PageColumns = Pager->PageColumns;
224 const DWORD ScrollRows = Pager->ScrollRows;
225
226 BOOL bFinitePaging = ((PageColumns > 0) && (Pager->PageRows > 0));
227 LONG nTabWidth = Pager->nTabWidth;
228
229 PCTCH Line;
230 SIZE_T ich;
231 SIZE_T ichStart;
232 SIZE_T iEndLine;
233 DWORD iColumn = Pager->iColumn;
234
235 UINT nCodePage = GetConsoleOutputCP();
236 BOOL IsCJK = IsCJKCodePage(nCodePage);
237 UINT nWidthOfChar = 1;
238 BOOL IsDoubleWidthCharTrailing = FALSE;
239
240 /* Normalize the tab width: if negative or too large,
241 * cap it to the number of columns. */
242 if (PageColumns > 0) // if (bFinitePaging)
243 {
244 if (nTabWidth < 0)
245 nTabWidth = PageColumns - 1;
246 else
247 nTabWidth = min(nTabWidth, PageColumns - 1);
248 }
249 else
250 {
251 /* If no column width is known, default to 8 spaces if the
252 * original value is negative; otherwise keep the current one. */
253 if (nTabWidth < 0)
254 nTabWidth = 8;
255 }
256
257
258 /* Continue displaying the previous line, if any, or start a new one */
259 Line = Pager->CurrentLine;
260 ichStart = Pager->ichCurr;
261 iEndLine = Pager->iEndLine;
262
263ProcessLine:
264
265 /* Stop now if we have displayed more page lines than requested */
266 if (bFinitePaging && (Pager->iLine >= ScrollRows))
267 goto End;
268
269 if (!Line || (ichStart >= iEndLine))
270 {
271 /* Start a new line */
272 if (!GetNextLine(Pager, TextBuff, cch))
273 goto End;
274
275 Line = Pager->CurrentLine;
276 ichStart = Pager->ichCurr;
277 iEndLine = Pager->iEndLine;
278 }
279 else
280 {
281 /* Continue displaying the current line */
282 }
283
284 // ASSERT(Line && ((ichStart < iEndLine) || (ichStart == iEndLine && iEndLine == 0)));
285
286 /* Determine whether this line segment (from the current position till the end) should be displayed */
287 Pager->iColumn = iColumn;
288 if (Pager->PagerLine && Pager->PagerLine(Pager, &Line[ichStart], iEndLine - ichStart))
289 {
290 iColumn = Pager->iColumn;
291
292 /* Done with this line; start a new one */
293 Pager->nSpacePending = 0; // And reset any pending space.
294 ichStart = iEndLine;
295 goto ProcessLine;
296 }
297 // else: Continue displaying the line.
298
299
300 /* Print out any pending TAB expansion */
301 if (Pager->nSpacePending > 0)
302 {
304 while (Pager->nSpacePending > 0)
305 {
306 /* Print filling spaces */
307 CON_STREAM_WRITE(Pager->Screen->Stream, TEXT(" "), 1);
308 --(Pager->nSpacePending);
309 ++iColumn;
310
311 /* Check whether we are going across the column */
312 if ((PageColumns > 0) && (iColumn % PageColumns == 0))
313 {
314 // Pager->nSpacePending = 0; // <-- This is the mode of most text editors...
315
316 /* Reposition the cursor to the next line, first column */
317 if (!bFinitePaging || (PageColumns < Pager->Screen->csbi.dwSize.X))
318 CON_STREAM_WRITE(Pager->Screen->Stream, TEXT("\n"), 1);
319
320 Pager->iLine++;
321
322 /* Restart at the character */
323 // ASSERT(ichStart == ich);
324 goto ProcessLine;
325 }
326 }
327 }
328
329
330 /* Find, within this line segment (starting from its
331 * beginning), until where we can print to the page. */
332 for (ich = ichStart; ich < iEndLine; ++ich)
333 {
334 /* NEWLINE character */
335 if (Line[ich] == TEXT('\n'))
336 {
337 /* We should stop now */
338 // ASSERT(ich == iEndLine - 1);
339 break;
340 }
341
342 /* TAB character */
343 if (Line[ich] == TEXT('\t') &&
344 (Pager->dwFlags & CON_PAGER_EXPAND_TABS))
345 {
346 /* We should stop now */
347 break;
348 }
349
350 /* FORM-FEED character */
351 if (Line[ich] == TEXT('\f') &&
352 (Pager->dwFlags & CON_PAGER_EXPAND_FF))
353 {
354 /* We should stop now */
355 break;
356 }
357
358 /* Other character - Handle double-width for CJK */
359
360 if (IsCJK)
361 nWidthOfChar = GetWidthOfCharCJK(nCodePage, Line[ich]);
362
363 /* Care about CJK character presentation only when outputting
364 * to a device where the number of columns is known. */
365 if ((PageColumns > 0) && IsCJK)
366 {
367 IsDoubleWidthCharTrailing = (nWidthOfChar == 2) &&
368 ((iColumn + 1) % PageColumns == 0);
369 if (IsDoubleWidthCharTrailing)
370 {
371 /* Reserve this character for the next line */
372 ++iColumn; // Count a blank instead.
373 /* We should stop now */
374 break;
375 }
376 }
377
378 iColumn += nWidthOfChar;
379
380 /* Check whether we are going across the column */
381 if ((PageColumns > 0) && (iColumn % PageColumns == 0))
382 {
383 ++ich;
384 break;
385 }
386 }
387
388 /* Output the pending line segment */
389 if (ich - ichStart > 0)
390 CON_STREAM_WRITE(Pager->Screen->Stream, &Line[ichStart], ich - ichStart);
391
392 /* Have we finished the line segment? */
393 if (ich >= iEndLine)
394 {
395 /* Restart at the character */
396 ichStart = ich;
397 goto ProcessLine;
398 }
399
400 /* Handle special characters */
401
402 /* NEWLINE character */
403 if (Line[ich] == TEXT('\n'))
404 {
405 // ASSERT(ich == iEndLine - 1);
406
407 /* Reposition the cursor to the next line, first column */
408 CON_STREAM_WRITE(Pager->Screen->Stream, TEXT("\n"), 1);
409
410 Pager->iLine++;
411 iColumn = 0;
412
413 /* Done with this line; start a new one */
414 Pager->nSpacePending = 0; // And reset any pending space.
415 ichStart = iEndLine;
416 goto ProcessLine;
417 }
418
419 /* TAB character */
420 if (Line[ich] == TEXT('\t') &&
421 (Pager->dwFlags & CON_PAGER_EXPAND_TABS))
422 {
423 /* Perform TAB expansion, unless the tab width is zero */
424 if (nTabWidth == 0)
425 {
426 ichStart = ++ich;
427 goto ProcessLine;
428 }
429
430 ichStart = ++ich;
431 /* Reset the number of spaces needed to develop this TAB character */
432 Pager->nSpacePending = nTabWidth - (iColumn % nTabWidth);
433 goto ExpandTab;
434 }
435
436 /* FORM-FEED character */
437 if (Line[ich] == TEXT('\f') &&
438 (Pager->dwFlags & CON_PAGER_EXPAND_FF))
439 {
440 if (bFinitePaging)
441 {
442 /* Clear until the end of the page */
443 while (Pager->iLine < ScrollRows)
444 {
445 /* Call the user paging function in order to know
446 * whether we need to output the blank lines. */
447 Pager->iColumn = iColumn;
448 if (Pager->PagerLine && Pager->PagerLine(Pager, TEXT("\n"), 1))
449 {
450 /* Only one blank line displayed, that counts in the line count */
451 Pager->iLine++;
452 break;
453 }
454 else
455 {
456 CON_STREAM_WRITE(Pager->Screen->Stream, TEXT("\n"), 1);
457 Pager->iLine++;
458 }
459 }
460 }
461 else
462 {
463 /* Just output a FORM-FEED and a NEWLINE */
464 CON_STREAM_WRITE(Pager->Screen->Stream, TEXT("\f\n"), 2);
465 Pager->iLine++;
466 }
467
468 iColumn = 0;
469 Pager->nSpacePending = 0; // And reset any pending space.
470
471 /* Skip and restart past the character */
472 ichStart = ++ich;
473 goto ProcessLine;
474 }
475
476 /* If we output a double-width character that goes across the column,
477 * fill with blank and display the character on the next line. */
478 if (IsDoubleWidthCharTrailing)
479 {
480 IsDoubleWidthCharTrailing = FALSE; // Reset the flag.
481 CON_STREAM_WRITE(Pager->Screen->Stream, TEXT(" "), 1);
482 /* Fall back below */
483 }
484
485 /* Are we wrapping the line? */
486 if ((PageColumns > 0) && (iColumn % PageColumns == 0))
487 {
488 /* Reposition the cursor to the next line, first column */
489 if (!bFinitePaging || (PageColumns < Pager->Screen->csbi.dwSize.X))
490 CON_STREAM_WRITE(Pager->Screen->Stream, TEXT("\n"), 1);
491
492 Pager->iLine++;
493 }
494
495 /* Restart at the character */
496 ichStart = ich;
497 goto ProcessLine;
498
499
500End:
501 /*
502 * We are exiting, either because we displayed all the required lines
503 * (iLine >= ScrollRows), or, because we don't have more data to display.
504 */
505
506 Pager->ichCurr = ichStart;
507 Pager->iColumn = iColumn;
508 // INVESTIGATE: Can we get rid of CurrentLine here? // if (ichStart >= iEndLine) ...
509
510 /* Return TRUE if we displayed all the required lines; FALSE otherwise */
511 if (bFinitePaging && (Pager->iLine >= ScrollRows))
512 {
513 Pager->iLine = 0; /* Reset the count of lines being printed */
514 return TRUE;
515 }
516 else
517 {
518 return FALSE;
519 }
520}
static LPTSTR ExpandTab(LPCTSTR line)
Definition: text.h:141
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
@ Screen
Definition: console.h:34
UINT WINAPI DECLSPEC_HOTPATCH GetConsoleOutputCP(void)
Definition: console.c:957
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
#define TEXT(s)
Definition: k32.h:28
#define min(a, b)
Definition: monoChain.cc:55
unsigned int UINT
Definition: ndis.h:50
LPCCH PCTCH
Definition: ntbasedef.h:498
#define CON_PAGER_EXPAND_TABS
Definition: pager.h:40
#define CON_PAGER_EXPAND_FF
Definition: pager.h:41
long LONG
Definition: pedump.c:60
static BOOL GetNextLine(IN OUT PCON_PAGER Pager, IN PCTCH TextBuff, IN SIZE_T cch)
Retrieves a new text line, or continue fetching the current one.
Definition: pager.c:67
#define IsCJKCodePage(CodePage)
Definition: pager.c:41
static INT GetWidthOfCharCJK(IN UINT nCodePage, IN WCHAR ch)
Definition: pager.c:47
#define CON_STREAM_WRITE
Definition: pager.c:32
_In_ UINT _In_ UINT cch
Definition: shellapi.h:432
Definition: ncftp.h:79
ULONG_PTR SIZE_T
Definition: typedefs.h:80

Referenced by ConWritePaging().

◆ ConPutsPaging()

BOOL ConPutsPaging ( IN PCON_PAGER  Pager,
IN PAGE_PROMPT  PagePrompt,
IN BOOL  StartPaging,
IN PCTSTR  szStr 
)

Definition at line 645 of file pager.c.

650{
651 SIZE_T len;
652
653 /* Return if no string has been given */
654 if (szStr == NULL)
655 return TRUE;
656
657 len = wcslen(szStr);
658 return ConWritePaging(Pager, PagePrompt, StartPaging, szStr, len);
659}
#define NULL
Definition: types.h:112
_ACRTIMP size_t __cdecl wcslen(const wchar_t *)
Definition: wcs.c:2983
GLenum GLsizei len
Definition: glext.h:6722
static BOOL __stdcall PagePrompt(PCON_PAGER Pager, DWORD Done, DWORD Total)
Definition: more.c:159
BOOL ConWritePaging(IN PCON_PAGER Pager, IN PAGE_PROMPT PagePrompt, IN BOOL StartPaging, IN PCTCH szStr, IN SIZE_T len)
Definition: pager.c:548

◆ ConResPaging()

BOOL ConResPaging ( IN PCON_PAGER  Pager,
IN PAGE_PROMPT  PagePrompt,
IN BOOL  StartPaging,
IN UINT  uID 
)

Definition at line 679 of file pager.c.

684{
685 return ConResPagingEx(Pager, PagePrompt, StartPaging, NULL, uID);
686}
_In_ UINT uID
Definition: shlwapi.h:156
BOOL ConResPagingEx(IN PCON_PAGER Pager, IN PAGE_PROMPT PagePrompt, IN BOOL StartPaging, IN HINSTANCE hInstance OPTIONAL, IN UINT uID)
Definition: pager.c:662

Referenced by ConOutResPaging().

◆ ConResPagingEx()

BOOL ConResPagingEx ( IN PCON_PAGER  Pager,
IN PAGE_PROMPT  PagePrompt,
IN BOOL  StartPaging,
IN HINSTANCE hInstance  OPTIONAL,
IN UINT  uID 
)

Definition at line 662 of file pager.c.

668{
669 INT Len;
670 PCWSTR szStr = NULL;
671
672 Len = K32LoadStringW(hInstance, uID, (PWSTR)&szStr, 0);
673 if (szStr && Len)
674 return ConWritePaging(Pager, PagePrompt, StartPaging, szStr, Len);
675 return TRUE;
676}
HINSTANCE hInstance
Definition: charmap.c:19
#define Len
Definition: deflate.h:82
INT WINAPI K32LoadStringW(IN HINSTANCE hInstance OPTIONAL, IN UINT uID, OUT LPWSTR lpBuffer, IN INT nBufferMax)
Definition: utils.c:183
uint16_t * PWSTR
Definition: typedefs.h:56
const uint16_t * PCWSTR
Definition: typedefs.h:57
int32_t INT
Definition: typedefs.h:58

Referenced by ConResPaging().

◆ ConWritePaging()

BOOL ConWritePaging ( IN PCON_PAGER  Pager,
IN PAGE_PROMPT  PagePrompt,
IN BOOL  StartPaging,
IN PCTCH  szStr,
IN SIZE_T  len 
)

Definition at line 548 of file pager.c.

554{
556 BOOL bIsConsole;
557
558 /* Parameters validation */
559 if (!Pager)
560 return FALSE;
561
562 /* Get the size of the visual screen that can be printed to */
563 bIsConsole = ConGetScreenInfo(Pager->Screen, &csbi);
564 if (bIsConsole)
565 {
566 /* Calculate the console screen extent */
567 Pager->PageColumns = csbi.dwSize.X;
568 Pager->PageRows = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
569 }
570 else
571 {
572 /* We assume it's a file handle */
573 Pager->PageColumns = 0;
574 Pager->PageRows = 0;
575 }
576
577 if (StartPaging)
578 {
579 if (bIsConsole && (Pager->PageRows >= 2))
580 {
581 /* Reset to display one page by default */
582 Pager->ScrollRows = Pager->PageRows - 1;
583 }
584 else
585 {
586 /* File output, or single line: all lines are displayed at once; reset to a default value */
587 Pager->ScrollRows = 0;
588 }
589
590 /* Reset the internal data buffer */
591 Pager->CachedLine = NULL;
592 Pager->cchCachedLine = 0;
593
594 /* Reset the paging state */
595 Pager->CurrentLine = NULL;
596 Pager->ichCurr = 0;
597 Pager->iEndLine = 0;
598 Pager->nSpacePending = 0;
599 Pager->iColumn = 0;
600 Pager->iLine = 0;
601 Pager->lineno = 0;
602 }
603
604 /* Reset the reading index in the user-provided source buffer */
605 Pager->ich = 0;
606
607 /* Run the pager even when the user-provided source buffer is
608 * empty, in case we need to flush any remaining cached line. */
609 if (!Pager->CachedLine)
610 {
611 /* No cached line, bail out now */
612 if (len == 0 || szStr == NULL)
613 return TRUE;
614 }
615
616 while (ConPagerWorker(Pager, szStr, len))
617 {
618 /* Prompt the user only when we display to a console and the screen
619 * is not too small: at least one line for the actual paged text and
620 * one line for the prompt. */
621 if (bIsConsole && (Pager->PageRows >= 2))
622 {
623 /* Reset to display one page by default */
624 Pager->ScrollRows = Pager->PageRows - 1;
625
626 /* Prompt the user; give him some values for statistics */
627 // FIXME: Doesn't reflect what's currently being displayed.
628 if (!PagePrompt(Pager, Pager->ich, len))
629 return FALSE;
630 }
631
632 /* If we display to a console, recalculate its screen extent
633 * in case the user has redimensioned it during the prompt. */
634 if (bIsConsole && ConGetScreenInfo(Pager->Screen, &csbi))
635 {
636 Pager->PageColumns = csbi.dwSize.X;
637 Pager->PageRows = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
638 }
639 }
640
641 return TRUE;
642}
static BOOL ConPagerWorker(IN PCON_PAGER Pager, IN PCTCH TextBuff, IN SIZE_T cch)
Does the main paging work: fetching text lines and displaying them.
Definition: pager.c:218
BOOL ConGetScreenInfo(IN PCON_SCREEN Screen, OUT PCONSOLE_SCREEN_BUFFER_INFO pcsbi)
Definition: screen.c:72
SHORT X
Definition: blue.h:26
SHORT Top
Definition: blue.h:33
SHORT Bottom
Definition: blue.h:35

Referenced by ConPrintfVPaging(), ConPutsPaging(), ConResPagingEx(), and wmain().

◆ GetNextLine()

static BOOL GetNextLine ( IN OUT PCON_PAGER  Pager,
IN PCTCH  TextBuff,
IN SIZE_T  cch 
)
static

Retrieves a new text line, or continue fetching the current one.

Remarks
Manages setting Pager's CurrentLine, ichCurr, iEndLine, and the line cache (CachedLine, cchCachedLine). Other functions must not modify these values.

Definition at line 67 of file pager.c.

71{
72 SIZE_T ich = Pager->ich;
73 SIZE_T ichStart;
74 SIZE_T cchLine;
75 BOOL bCacheLine;
76
77 Pager->ichCurr = 0;
78 Pager->iEndLine = 0;
79
80 /*
81 * If we already had an existing line, then we can safely start a new one
82 * and getting rid of any current cached line. Otherwise, we don't have
83 * a current line and we may be caching a new one, in which case, continue
84 * caching it until it becomes complete.
85 */
86 // INVESTIGATE: Do that only if (ichStart >= iEndLine) ??
87 if (Pager->CurrentLine)
88 {
89 // ASSERT(Pager->CurrentLine == Pager->CachedLine);
90 if (Pager->CachedLine)
91 {
92 HeapFree(GetProcessHeap(), 0, (PVOID)Pager->CachedLine);
93 Pager->CachedLine = NULL;
94 Pager->cchCachedLine = 0;
95 }
96
97 Pager->CurrentLine = NULL;
98 }
99
100 /* Nothing else to read if we are past the end of the buffer */
101 if (ich >= cch)
102 {
103 /* If we have a pending cached line, terminate it now */
104 if (Pager->CachedLine)
105 goto TerminateLine;
106
107 /* Otherwise, bail out */
108 return FALSE;
109 }
110
111 /* Start a new line, or continue an existing one */
112 ichStart = ich;
113
114 /* Find where this line ends, looking for a NEWLINE character.
115 * (NOTE: We cannot use strchr because the buffer is not NULL-terminated) */
116 for (; ich < cch; ++ich)
117 {
118 if (TextBuff[ich] == TEXT('\n'))
119 {
120 ++ich;
121 break;
122 }
123 }
124 Pager->ich = ich;
125
126 cchLine = (ich - ichStart);
127
128 //
129 // FIXME: Impose a maximum string limit when the line is cached, in order
130 // not to potentially grow memory indefinitely. When the limit is reached,
131 // terminate the line.
132 //
133
134 /*
135 * If we have stopped because we have exhausted the text buffer
136 * and we have not found an end-of-line character, this may mean
137 * that the text line spans across different text buffers. If we
138 * have been told so, cache this line: we will complete it during
139 * the next call(s) and only then, display it.
140 * Otherwise, consider the line to be terminated now.
141 */
142 bCacheLine = ((Pager->dwFlags & CON_PAGER_CACHE_INCOMPLETE_LINE) &&
143 (ich >= cch) && (TextBuff[ich - 1] != TEXT('\n')));
144
145 /* Allocate, or re-allocate, the cached line buffer */
146 if (bCacheLine && !Pager->CachedLine)
147 {
148 /* We start caching, allocate the cached line buffer */
149 Pager->CachedLine = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
150 cchLine * sizeof(TCHAR));
151 Pager->cchCachedLine = 0;
152
153 if (!Pager->CachedLine)
154 {
156 return FALSE;
157 }
158 }
159 else if (Pager->CachedLine)
160 {
161 /* We continue caching, re-allocate the cached line buffer */
163 (PVOID)Pager->CachedLine,
164 (Pager->cchCachedLine + cchLine) * sizeof(TCHAR));
165 if (!ptr)
166 {
167 HeapFree(GetProcessHeap(), 0, (PVOID)Pager->CachedLine);
168 Pager->CachedLine = NULL;
169 Pager->cchCachedLine = 0;
170
172 return FALSE;
173 }
174 Pager->CachedLine = ptr;
175 }
176 if (Pager->CachedLine)
177 {
178 /* Copy/append the text to the cached line buffer */
179 RtlCopyMemory((PVOID)&Pager->CachedLine[Pager->cchCachedLine],
180 &TextBuff[ichStart],
181 cchLine * sizeof(TCHAR));
182 Pager->cchCachedLine += cchLine;
183 }
184 if (bCacheLine)
185 {
186 /* The line is currently incomplete, don't proceed further for now */
187 return FALSE;
188 }
189
190TerminateLine:
191 /* The line should be complete now. If we have an existing cached line,
192 * it has been completed by appending the remaining text to it. */
193
194 /* We are starting a new line */
195 Pager->ichCurr = 0;
196 if (Pager->CachedLine)
197 {
198 Pager->iEndLine = Pager->cchCachedLine;
199 Pager->CurrentLine = Pager->CachedLine;
200 }
201 else
202 {
203 Pager->iEndLine = cchLine;
204 Pager->CurrentLine = &TextBuff[ichStart];
205 }
206
207 /* Increase only when we have got a NEWLINE */
208 if ((Pager->iEndLine > 0) && (Pager->CurrentLine[Pager->iEndLine - 1] == TEXT('\n')))
209 Pager->lineno++;
210
211 return TRUE;
212}
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define GetProcessHeap()
Definition: compat.h:736
#define SetLastError(x)
Definition: compat.h:752
#define HeapAlloc
Definition: compat.h:733
#define HeapReAlloc
Definition: compat.h:734
#define HeapFree(x, y, z)
Definition: compat.h:735
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
static PVOID ptr
Definition: dispmode.c:27
#define CON_PAGER_CACHE_INCOMPLETE_LINE
Definition: pager.h:43
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
char TCHAR
Definition: xmlstorage.h:189

Referenced by ConPagerWorker().

◆ GetWidthOfCharCJK()

static INT GetWidthOfCharCJK ( IN UINT  nCodePage,
IN WCHAR  ch 
)
inlinestatic

Definition at line 47 of file pager.c.

50{
51 INT ret = WideCharToMultiByte(nCodePage, 0, &ch, 1, NULL, 0, NULL, NULL);
52 if (ret == 0)
53 ret = 1;
54 else if (ret > 2)
55 ret = 2;
56 return ret;
57}
#define WideCharToMultiByte
Definition: compat.h:111
unsigned char ch[4][2]
Definition: console.c:118
return ret
Definition: mutex.c:146

Referenced by ConPagerWorker().