ReactOS  0.4.15-dev-3294-ge98684e
pager.c File Reference
#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. More...
 
static BOOL ConPagerWorker (IN PCON_PAGER Pager, IN PCTCH TextBuff, IN DWORD cch)
 Does the main paging work: fetching text lines and displaying them. More...
 
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)
 

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

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 
264 ProcessLine:
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  {
304 ExpandTab:
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 
501 End:
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 }
#define CON_STREAM_WRITE
Definition: pager.c:33
#define TRUE
Definition: types.h:120
#define CON_PAGER_EXPAND_TABS
Definition: pager.h:40
LPCCH PCTCH
Definition: ntbasedef.h:486
static INT GetWidthOfCharCJK(IN UINT nCodePage, IN WCHAR ch)
Definition: pager.c:48
struct Line Line
Definition: wdfdevice.h:4081
#define FALSE
Definition: types.h:117
unsigned int BOOL
Definition: ntddk_ex.h:94
long LONG
Definition: pedump.c:60
UINT WINAPI DECLSPEC_HOTPATCH GetConsoleOutputCP(VOID)
Definition: console.c:2453
static LPTSTR ExpandTab(LPCTSTR line)
Definition: text.h:141
#define CON_PAGER_EXPAND_FF
Definition: pager.h:41
unsigned long DWORD
Definition: ntddk_ex.h:95
Definition: ncftp.h:79
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define TEXT(s)
Definition: k32.h:26
#define IsCJKCodePage(CodePage)
Definition: pager.c:42
#define min(a, b)
Definition: monoChain.cc:55
unsigned int UINT
Definition: ndis.h:50
Definition: console.h:34
IN PCTCH IN DWORD cch
Definition: pager.h:36
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

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 }
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
#define TRUE
Definition: types.h:120
unsigned long DWORD
Definition: ntddk_ex.h:95
GLenum GLsizei len
Definition: glext.h:6722
#define NULL
Definition: types.h:112
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)

◆ 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 }
static BOOL __stdcall PagePrompt(PCON_PAGER Pager, DWORD Done, DWORD Total)
Definition: more.c:160
BOOL ConResPagingEx(IN PCON_PAGER Pager, IN PAGE_PROMPT PagePrompt, IN BOOL StartPaging, IN HINSTANCE hInstance OPTIONAL, IN UINT uID)
Definition: pager.c:663
#define NULL
Definition: types.h:112

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 }
const uint16_t * PCWSTR
Definition: typedefs.h:57
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
#define TRUE
Definition: types.h:120
uint16_t * PWSTR
Definition: typedefs.h:56
INT WINAPI K32LoadStringW(IN HINSTANCE hInstance OPTIONAL, IN UINT uID, OUT LPWSTR lpBuffer, IN INT nBufferMax)
Definition: utils.c:173
int32_t INT
Definition: typedefs.h:58
HINSTANCE hInstance
Definition: charmap.c:20
#define Len
Definition: deflate.h:82
#define NULL
Definition: types.h:112

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 __stdcall PagePrompt(PCON_PAGER Pager, DWORD Done, DWORD Total)
Definition: more.c:160
BOOL ConGetScreenInfo(IN PCON_SCREEN Screen, OUT PCONSOLE_SCREEN_BUFFER_INFO pcsbi)
Definition: screen.c:73
#define TRUE
Definition: types.h:120
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
#define FALSE
Definition: types.h:117
unsigned int BOOL
Definition: ntddk_ex.h:94
ULONG X
Definition: bl.h:1340
SHORT Bottom
Definition: blue.h:35
SHORT Top
Definition: blue.h:33
GLenum GLsizei len
Definition: glext.h:6722
#define NULL
Definition: types.h:112

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 
191 TerminateLine:
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 TRUE
Definition: types.h:120
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define FALSE
Definition: types.h:117
unsigned int BOOL
Definition: ntddk_ex.h:94
static PVOID ptr
Definition: dispmode.c:27
char TCHAR
Definition: xmlstorage.h:189
#define GetProcessHeap()
Definition: compat.h:595
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
#define SetLastError(x)
Definition: compat.h:611
#define CON_PAGER_CACHE_INCOMPLETE_LINE
Definition: pager.h:43
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define TEXT(s)
Definition: k32.h:26
#define HeapReAlloc
Definition: compat.h:593
#define NULL
Definition: types.h:112
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
IN PCTCH IN DWORD cch
Definition: pager.h:36
#define HeapFree(x, y, z)
Definition: compat.h:594

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
int32_t INT
Definition: typedefs.h:58
int ret
#define NULL
Definition: types.h:112

Referenced by ConPagerWorker().