ReactOS 0.4.15-dev-7924-g5949c20
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 DWORD 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 DWORD 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 33 of file pager.c.

◆ CP_BIG5

#define CP_BIG5   950

Definition at line 39 of file pager.c.

◆ CP_GB2312

#define CP_GB2312   936

Definition at line 38 of file pager.c.

◆ CP_HANGUL

#define CP_HANGUL   949

Definition at line 36 of file pager.c.

◆ CP_JOHAB

#define CP_JOHAB   1361

Definition at line 37 of file pager.c.

◆ CP_SHIFTJIS

#define CP_SHIFTJIS   932

Definition at line 35 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:38
#define CP_BIG5
Definition: pager.c:39
#define CP_HANGUL
Definition: pager.c:36
#define CP_SHIFTJIS
Definition: pager.c:35

Definition at line 42 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 DWORD  cch 
)
static

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

Definition at line 219 of file pager.c.

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

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

◆ ConResPaging()

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

Definition at line 681 of file pager.c.

686{
687 return ConResPagingEx(Pager, PagePrompt, StartPaging,
688 NULL /*GetModuleHandleW(NULL)*/, uID);
689}
BOOL ConResPagingEx(IN PCON_PAGER Pager, IN PAGE_PROMPT PagePrompt, IN BOOL StartPaging, IN HINSTANCE hInstance OPTIONAL, IN UINT uID)
Definition: pager.c:663

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 663 of file pager.c.

669{
670 INT Len;
671 PCWSTR szStr = NULL;
672
673 Len = K32LoadStringW(hInstance, uID, (PWSTR)&szStr, 0);
674 if (szStr && Len)
675 return ConWritePaging(Pager, PagePrompt, StartPaging, szStr, Len);
676 else
677 return TRUE;
678}
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:173
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 DWORD  len 
)

Definition at line 549 of file pager.c.

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

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

51{
52 INT ret = WideCharToMultiByte(nCodePage, 0, &ch, 1, NULL, 0, NULL, NULL);
53 if (ret == 0)
54 ret = 1;
55 else if (ret > 2)
56 ret = 2;
57 return ret;
58}
#define WideCharToMultiByte
Definition: compat.h:111
int ret

Referenced by ConPagerWorker().