[MORE]: Rewrite almost completely the MORE command, taking advantage of the console...
authorHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Sat, 22 Oct 2016 22:07:28 +0000 (22:07 +0000)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Sat, 22 Oct 2016 22:07:28 +0000 (22:07 +0000)
- When displaying files, display the percentage of file read so far in the "Continue" prompt. Otherwise (when being piped or feeded from StdIn), just display the "Continue" prompt without percentage.
- Try to detect the text file encoding (ANSI, UTF16-BE/BE w/ or w/o BOM; UTF-8 to do!!) before displaying it. See the code for more details.

NOTE that the other functionalities of more (being able to scroll one line at a time, other command-line switches, etc...) are still not implemented yet.

svn path=/trunk/; revision=73025

25 files changed:
reactos/base/applications/cmdutils/more/CMakeLists.txt
reactos/base/applications/cmdutils/more/lang/bg-BG.rc
reactos/base/applications/cmdutils/more/lang/ca-ES.rc
reactos/base/applications/cmdutils/more/lang/cs-CZ.rc
reactos/base/applications/cmdutils/more/lang/de-DE.rc
reactos/base/applications/cmdutils/more/lang/el-GR.rc
reactos/base/applications/cmdutils/more/lang/en-US.rc
reactos/base/applications/cmdutils/more/lang/es-ES.rc
reactos/base/applications/cmdutils/more/lang/fr-FR.rc
reactos/base/applications/cmdutils/more/lang/it-IT.rc
reactos/base/applications/cmdutils/more/lang/lt-LT.rc
reactos/base/applications/cmdutils/more/lang/no-NO.rc
reactos/base/applications/cmdutils/more/lang/pl-PL.rc
reactos/base/applications/cmdutils/more/lang/ro-RO.rc
reactos/base/applications/cmdutils/more/lang/ru-RU.rc
reactos/base/applications/cmdutils/more/lang/sk-SK.rc
reactos/base/applications/cmdutils/more/lang/sq-AL.rc
reactos/base/applications/cmdutils/more/lang/sv-SE.rc
reactos/base/applications/cmdutils/more/lang/tr-TR.rc
reactos/base/applications/cmdutils/more/lang/uk-UA.rc
reactos/base/applications/cmdutils/more/lang/zh-CN.rc
reactos/base/applications/cmdutils/more/lang/zh-TW.rc
reactos/base/applications/cmdutils/more/more.c
reactos/base/applications/cmdutils/more/more.rc
reactos/base/applications/cmdutils/more/resource.h

index 9abb016..f84cedb 100644 (file)
@@ -1,6 +1,11 @@
 
+PROJECT(more)
+
+include_directories(${REACTOS_SOURCE_DIR}/sdk/lib/conutils)
+
 add_executable(more more.c more.rc)
-set_module_type(more win32cui)
+set_module_type(more win32cui UNICODE)
+target_link_libraries(more conutils_pager ${PSEH_LIB})
+add_importlibs(more advapi32 user32 msvcrt kernel32)
 set_target_properties(more PROPERTIES SUFFIX ".com")
-add_importlibs(more user32 msvcrt kernel32)
 add_cd_file(TARGET more DESTINATION reactos/system32 FOR all)
index 528b870..9d4c43d 100644 (file)
@@ -9,6 +9,7 @@ BEGIN
   [Устройство:][Път]Файлово име    Файл, чието съдържание да бъде показано.\n\
   Команда\t\t     Команда, чийто изход да бъде показан.\n\n\
   При въпроса ""-- Продължаване --"" натиснете произволен клавиш, за показаване на следващата страница.\n"
-    IDS_CONTINUE " -- Продължаване (100%) -- "
-    IDS_FILE_ACCESS "Няма достъп до файл %s."
+    IDS_CONTINUE "-- Продължаване --"
+    IDS_CONTINUE_PROGRESS "-- Продължаване (%d%%) --"
+    IDS_FILE_ACCESS "Няма достъп до файл %s.\n"
 END
index aa96d61..4948964 100644 (file)
@@ -9,6 +9,7 @@ BEGIN
   [Unitat:][Ruta]Nom del fitxer    Un fitxer, el contingut del qual serà mostrat.\n\
   Instrucció\t\t     Una instrucció, el resultat de la qual serà mostrada.\n\n\
   Al visualitzar ""-- Continua --"" heu de premer qualsevol tecla per visualitzar la següent pàgina.\n"
-    IDS_CONTINUE " -- Continua (100%) -- "
-    IDS_FILE_ACCESS "No puc accedir al fitxer %s."
+    IDS_CONTINUE "-- Continua --"
+    IDS_CONTINUE_PROGRESS "-- Continua (%d%%) --"
+    IDS_FILE_ACCESS "No puc accedir al fitxer %s.\n"
 END
index 294d491..4c1863e 100644 (file)
@@ -16,6 +16,7 @@ BEGIN
   Příkaz\t\t     Příkaz, jehož výstup bude zobrazen.\n\n\
   Při výzvě ""-- Pokračovat --"" lze stisknout libovolnou klávesu\n\
   pro zobrazení další stránky.\n"
-    IDS_CONTINUE " -- Pokračovat (100%) -- "
-    IDS_FILE_ACCESS "Nelze získat přístup k souboru %s."
+    IDS_CONTINUE "-- Pokračovat --"
+    IDS_CONTINUE_PROGRESS "-- Pokračovat (%d%%) --"
+    IDS_FILE_ACCESS "Nelze získat přístup k souboru %s.\n"
 END
index 506e4ce..cc4112f 100644 (file)
@@ -10,6 +10,7 @@ BEGIN
   Befehl\t\t     Ein Befehl, dessen Ausgabe angezeigt werden soll.\n\n\
   An der Eingabeaufforderung ""-- Fortsetzung --"" kann eine beliebige\n\
   Taste gedrückt werden, um die nächste Seite anzuzeigen.\n"
-    IDS_CONTINUE " -- Fortsetzung (100%) -- "
-    IDS_FILE_ACCESS "Auf die Datei %s kann nicht zugegriffen werden."
+    IDS_CONTINUE "-- Fortsetzung --"
+    IDS_CONTINUE_PROGRESS "-- Fortsetzung (%d%%) --"
+    IDS_FILE_ACCESS "Auf die Datei %s kann nicht zugegriffen werden.\n"
 END
index a34b697..e2d8bfc 100644 (file)
@@ -9,6 +9,7 @@ BEGIN
   [Δίσκος:][Μονοπάτι]Όνομα αρχείου    Το αρχείο, τα δεδομένα του οποίου θα εμφανιστούν.\n\
   Εντολή\t\t     Η εντολή, της οποίας η έξοδος θα εμφανιστεί.\n\n\
   Στη γραμμή εντολών ""-- Συνέχεια --"" μπορείτε να πατήσετε οποιοδήποτε κουμπί για να δείτε την επόμενη σελίδα.\n"
-    IDS_CONTINUE " -- Συνέχεια (100%) -- "
-    IDS_FILE_ACCESS "Δεν ήταν δυνατή η προσπέλαση του αρχείου %s."
+    IDS_CONTINUE "-- Συνέχεια --"
+    IDS_CONTINUE_PROGRESS "-- Συνέχεια (%d%%) --"
+    IDS_FILE_ACCESS "Δεν ήταν δυνατή η προσπέλαση του αρχείου %s.\n"
 END
index 486ef83..8632592 100644 (file)
@@ -9,6 +9,7 @@ BEGIN
   [Drive:][Path]File name    A file, whose content shall be displayed.\n\
   Command\t\t     A command, whose output shall be displayed.\n\n\
   At the prompt ""-- Continue --"" you can press any key to show the next page.\n"
-    IDS_CONTINUE " -- Continue (100%) -- "
-    IDS_FILE_ACCESS "Cannot access the file %s."
+    IDS_CONTINUE "-- Continue --"
+    IDS_CONTINUE_PROGRESS "-- Continue (%d%%) --"
+    IDS_FILE_ACCESS "Cannot access the file %s.\n"
 END
index 4f21874..596326e 100644 (file)
@@ -9,6 +9,7 @@ BEGIN
   [Unidad:][Ruta]Nombre del archivo    Un archivo, cuyo contenido pueda ser mostrado.\n\
   Comando\t\t     Un comando, cuya salida pueda ser mostrada.\n\n\
   Al visualizar ""-- Continuar --"" presione cualquier tecla para mostrar la siguiente página.\n"
-    IDS_CONTINUE " -- Continuar (100%) -- "
-    IDS_FILE_ACCESS "No se puede acceder al fichero %s."
+    IDS_CONTINUE "-- Continuar --"
+    IDS_CONTINUE_PROGRESS "-- Continuar (%d%%) --"
+    IDS_FILE_ACCESS "No se puede acceder al fichero %s.\n"
 END
index 242617d..2db50c8 100644 (file)
@@ -9,6 +9,7 @@ BEGIN
   [Lecteur:][Chemin]Nom du fichier    Un fichier, dont le contenu sera affiché.\n\
   Commande\t\t     Une commande, dont la sortie sera affichée.\n\n\
   À l'invite ""-- Continuer --"" Vous pouvez appuyer sur n'importe quelle touche pour afficher la page suivante.\n"
-    IDS_CONTINUE " -- Continuer (100%) -- "
-    IDS_FILE_ACCESS "Impossible d'accéder au fichier %s."
+    IDS_CONTINUE "-- Continuer --"
+    IDS_CONTINUE_PROGRESS "-- Continuer (%d %%) --"
+    IDS_FILE_ACCESS "Impossible d'accéder au fichier %s.\n"
 END
index 54b15a7..5f99f2b 100644 (file)
@@ -9,6 +9,7 @@ BEGIN
   [Drive:][Path]File    Il file da visualizzare.\n\
   Comando\t\t     Il comando di cui l'output dev'essere visualizzato.\n\n\
   Alla richiesta ""-- Continua --"" premere un tasto qualsiasi per visualizzare la pagina successiva.\n"
-    IDS_CONTINUE " -- Continua (100%) -- "
-    IDS_FILE_ACCESS "Impossibile accedere al file %s."
+    IDS_CONTINUE "-- Continua --"
+    IDS_CONTINUE_PROGRESS "-- Continua (%d%%) --"
+    IDS_FILE_ACCESS "Impossibile accedere al file %s.\n"
 END
index ef34058..4644b0e 100644 (file)
@@ -21,6 +21,7 @@ BEGIN
                                              būti atvaizduotas.\n\n\
   Pasirodžius raginimui ""-- Toliau --"" spauskite bet kurį klavišą, kad\n\
   pamatytumėte sekantį puslapį.\n"
-    IDS_CONTINUE " -- Toliau (100%) -- "
-    IDS_FILE_ACCESS "Nepavyko atverti bylos %s."
+    IDS_CONTINUE "-- Toliau --"
+    IDS_CONTINUE_PROGRESS "-- Toliau (%d%%) --"
+    IDS_FILE_ACCESS "Nepavyko atverti bylos %s.\n"
 END
index 40f16fa..cd77804 100644 (file)
@@ -9,6 +9,7 @@ BEGIN
   [Stasjon:][Mappe]Filnavn    En fil, Velg innhold som skal vises.\n\
   Command\t\t     En kommando, Velg output som skal vises.\n\n\
   At the prompt ""-- Fortsett --"" du kan trykke en tast for å vise neste side.\n"
-    IDS_CONTINUE " -- Fortsett (100%) -- "
-    IDS_FILE_ACCESS "Får ikke tilgang til filen %s."
+    IDS_CONTINUE "-- Fortsett --"
+    IDS_CONTINUE_PROGRESS "-- Fortsett (%d%%) --"
+    IDS_FILE_ACCESS "Får ikke tilgang til filen %s.\n"
 END
index 659325d..145c39d 100644 (file)
@@ -17,6 +17,7 @@ BEGIN
   [Napęd:][Ścieżka]Nazwa pliku    Plik, którego zawartość ma być wyświetlona.\n\
   Polecenie\t\t     Polecenie, którego wynik ma być wyświetlony.\n\n\
   Po wyświetleniu ""-- Kontynuuj --"" możesz nacisnąć dowolny klawisz, aby przejść do następnej strony.\n"
-    IDS_CONTINUE " -- Kontynuuj (100%) -- "
-    IDS_FILE_ACCESS "Brak dostępu do pliku: %s."
+    IDS_CONTINUE "-- Kontynuuj --"
+    IDS_CONTINUE_PROGRESS "-- Kontynuuj (%d%%) --"
+    IDS_FILE_ACCESS "Brak dostępu do pliku: %s.\n"
 END
index 6a1b677..00e22d9 100644 (file)
@@ -18,6 +18,7 @@ BEGIN
   Comandă                        Comanda a cărei ieșire va fi afișată.\n\n\
   La vederea sugestiei ""-- Continuă --"" veți apăsa o tastă pentru afișarea\n\
   următoarei pagini.\n"
-    IDS_CONTINUE " -- Continuă (100%) -- "
-    IDS_FILE_ACCESS "Fișierul «%s» nu poate fi accesat!"
+    IDS_CONTINUE "-- Continuă --"
+    IDS_CONTINUE_PROGRESS "-- Continuă (%d%%) --"
+    IDS_FILE_ACCESS "Fișierul «%s» nu poate fi accesat!\n"
 END
index a7772fd..1980e3e 100644 (file)
@@ -17,6 +17,7 @@ BEGIN
   [диск:][путь]имя_файла    Файл, отображаемый по фрагментам.\n\
   имя_команды             Команда, вывод которой отображается на экране.\n\n\
   При запросе  ""-- Продолжить --"" вы можете нажать любую клавишу для отображения следующего экрана.\n"
-    IDS_CONTINUE " -- Продолжить (100%) -- "
-    IDS_FILE_ACCESS "Нет доступа к файлу %s."
+    IDS_CONTINUE "-- Продолжить --"
+    IDS_CONTINUE_PROGRESS "-- Продолжить (%d%%) --"
+    IDS_FILE_ACCESS "Нет доступа к файлу %s.\n"
 END
index b1d1143..bb13c76 100644 (file)
@@ -14,6 +14,7 @@ BEGIN
   Príkaz\t\t     Príkaz, ktorého výstup má byť zobrazený.\n\n\
   Pri výzve ""-- Pokračujte --"" môžete stlačiť ľubovoľný kláves\n\
   k zobrazeniu nasledujúcej stránky.\n"
-    IDS_CONTINUE " -- Pokračujte (100%) -- "
-    IDS_FILE_ACCESS "Neviem získať prístup k súboru %s."
+    IDS_CONTINUE "-- Pokračujte --"
+    IDS_CONTINUE_PROGRESS "-- Pokračujte (%d%%) --"
+    IDS_FILE_ACCESS "Neviem získať prístup k súboru %s.\n"
 END
index 882b3fb..18281bb 100644 (file)
@@ -13,6 +13,7 @@ BEGIN
   [Drive:][Path]File name    Nje dokument, përmbajtja e të cilit do të shfaqet.\n\
   Komandë\t\t     Nje komande, nxjerrja e te cilit do të shfaqet.\n\n\
   At the prompt ""-- Vazhdo --"" ju mund të shtypni çfarëdo butoni për të vazhduar në faqen tjetër.\n"
-    IDS_CONTINUE " -- Vazhdo (100%) -- "
-    IDS_FILE_ACCESS "Nuk mund të aksesoj dokumentin %s."
+    IDS_CONTINUE "-- Vazhdo --"
+    IDS_CONTINUE_PROGRESS "-- Vazhdo (%d%%) --"
+    IDS_FILE_ACCESS "Nuk mund të aksesoj dokumentin %s.\n"
 END
index c11c608..7ba17a9 100644 (file)
@@ -16,6 +16,7 @@ BEGIN
   [Enhet:][Mapp]Filnamn    En fil, Välj innehåll som skall visas.\n\
   Kommando\t\t     Ett kommando, Välj vad som skall visas.\n\n\
   vid prompten ""-- Fortsätt --"" du kan trycka valfri knapp för att visa nästa sida.\n"
-    IDS_CONTINUE " -- Fortsätt (100%) -- "
-    IDS_FILE_ACCESS "Får inte tillgång till filen %s."
+    IDS_CONTINUE "-- Fortsätt --"
+    IDS_CONTINUE_PROGRESS "-- Fortsätt (%d%%) --"
+    IDS_FILE_ACCESS "Får inte tillgång till filen %s.\n"
 END
index a512a9c..cf28dd6 100644 (file)
@@ -11,6 +11,7 @@ BEGIN
   [Sürücü:][Yol]Kütük adı    İçeriği görüntülenecek bir kütük.\n\
   Komut\t\t     Çıkışı görüntülenecek bir komut.\n\n\
   İstemde ""-- Sürdür --"" ile bir sonraki sayfayı göstermek için rastgele bir düğmeye basabilirsiniz.\n"
-    IDS_CONTINUE " -- Sürdür (%100) -- "
-    IDS_FILE_ACCESS "%s kütüğüne erişilemiyor."
+    IDS_CONTINUE "-- Sürdür --"
+    IDS_CONTINUE_PROGRESS "-- Sürdür (%%%d) --"
+    IDS_FILE_ACCESS "%s kütüğüne erişilemiyor.\n"
 END
index f5fc69b..0c61a55 100644 (file)
@@ -17,6 +17,7 @@ BEGIN
   [Диск:][Шлях]Ім'я_файлу    Файл, вмiст якого треба вивести на екран.\n\
   Command\t\t     Команда, результат роботи якої треба вивести на екран.\n\n\
   На запрошення ""-- Далi --"" Ви можете натиснути будь-яку клавiшу щоб побачити наступну сторiнку.\n"
-    IDS_CONTINUE " -- Далi (100%) -- "
-    IDS_FILE_ACCESS "Не можу отримати доступ до файла %s."
+    IDS_CONTINUE "-- Далi --"
+    IDS_CONTINUE_PROGRESS "-- Далi (%d%%) --"
+    IDS_FILE_ACCESS "Не можу отримати доступ до файла %s.\n"
 END
index 333e628..93c60c6 100644 (file)
@@ -11,6 +11,7 @@ BEGIN
   [驱动器:][路径]文件名    一个将要被如此显示内容的文件。\n\
   命令\t\t     一个输出将要被如此显示的命令。\n\n\
   在 ""-- 继续 --"" 的提示出现时你可以按任意键来显示下一页。\n"
-    IDS_CONTINUE " -- 继续 (100%) -- "
-    IDS_FILE_ACCESS "无法访问文件 %s。"
+    IDS_CONTINUE "-- 继续 --"
+    IDS_CONTINUE_PROGRESS "-- 继续 (%d%%) --"
+    IDS_FILE_ACCESS "无法访问文件 %s。\n"
 END
index 3137dbf..21fcf41 100644 (file)
@@ -11,6 +11,7 @@ BEGIN
   [磁碟機:][路徑]檔案名    一個將要被如此顯示內容的檔案。\n\
   命令\t\t     一個輸出將要被如此顯示的命令。\n\n\
   在 ""-- 繼續 --"" 的提示出現時你可以按任意鍵來顯示下一頁。\n"
-    IDS_CONTINUE " -- 繼續 (100%) -- "
-    IDS_FILE_ACCESS "無法訪問檔案 %s。"
+    IDS_CONTINUE "-- 繼續 --"
+    IDS_CONTINUE_PROGRESS "-- 繼續 (%d%%) --"
+    IDS_FILE_ACCESS "無法訪問檔案 %s。\n"
 END
index 46ecdc5..161818a 100644 (file)
@@ -1,3 +1,14 @@
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS More Command
+ * FILE:            base/applications/cmdutils/more/more.c
+ * PURPOSE:         Displays text stream from STDIN or from an arbitrary number
+ *                  of files to STDOUT, with screen capabilities (more than CAT,
+ *                  but less than LESS ^^).
+ * PROGRAMMERS:     Paolo Pantaleo
+ *                  Timothy Schepens
+ *                  Hermes Belusca-Maito (hermes.belusca@sfr.fr)
+ */
 /*
  * MORE.C - external command.
  *
  *
  * 26 Sep 1999 - Paolo Pantaleo <paolopan@freemail.it>
  *     started
+ *
  * Oct 2003 - Timothy Schepens <tischepe at fastmail dot fm>
  *     use window size instead of buffer size.
  */
 
 #include <stdio.h>
-#include <malloc.h>
-#include <tchar.h>
 
 #include <windef.h>
 #include <winbase.h>
+#include <winnls.h>
 #include <winuser.h>
-#include <wincon.h>
 
-#include "resource.h"
+#include <conutils.h>
 
-static TCHAR szCont[128];
-static DWORD szContLength;
-static HINSTANCE hApp;
+#include "resource.h"
 
-/*handle for file and console*/
-HANDLE hStdIn;
-HANDLE hStdOut;
-HANDLE hStdErr;
+/* PagePrompt statistics for the current file */
+DWORD dwFileSize; // In bytes
+DWORD dwSumReadBytes, dwSumReadChars;
+// The average number of bytes per character is equal to
+// dwSumReadBytes / dwSumReadChars. Note that dwSumReadChars
+// will never be == 0 when ConWritePaging (and possibly PagePrompt)
+// is called.
+
+/* Handles for file and console */
+HANDLE hFile = INVALID_HANDLE_VALUE;
+HANDLE hStdIn, hStdOut;
 HANDLE hKeyboard;
 
 
-static VOID
-GetScreenSize (PSHORT maxx, PSHORT maxy)
+static BOOL
+__stdcall
+PagePrompt(PCON_PAGER Pager, DWORD Done, DWORD Total)
 {
-   CONSOLE_SCREEN_BUFFER_INFO csbi;
+    HANDLE hInput = ConStreamGetOSHandle(StdIn);
+    DWORD dwMode;
+    KEY_EVENT_RECORD KeyEvent;
+
+    /*
+     * Just use the simple prompt if the file being displayed is the STDIN,
+     * otherwise use the prompt with progress percentage.
+     *
+     * The progress percentage is evaluated as follows.
+     * So far we have read a total of 'dwSumReadBytes' bytes from the file.
+     * Amongst those is the latest read chunk of 'dwReadBytes' bytes, to which
+     * correspond a number of 'dwReadChars' characters with which we have called
+     * ConWritePaging who called PagePrompt. We then have: Total == dwReadChars.
+     * During this ConWritePaging call the PagePrompt was called after 'Done'
+     * number of characters over 'Total'.
+     * It should be noted that for 'dwSumReadBytes' number of bytes read it
+     * *roughly* corresponds 'dwSumReadChars' number of characters. This is
+     * because there may be some failures happening during the conversion of
+     * the bytes read to the character string for a given encoding.
+     * Therefore the number of characters displayed on screen is equal to:
+     *   dwSumReadChars - Total + Done ,
+     * but the best corresponding approximed number of bytes would be:
+     *   dwSumReadBytes - (Total - Done) * (dwSumReadBytes / dwSumReadChars) ,
+     * where the ratio is the average number of bytes per character.
+     * The percentage is then computed relative to the total file size.
+     */
+    if (hFile == hStdIn)
+    {
+        ConResPuts(Pager->Screen->Stream, IDS_CONTINUE);
+    }
+    else
+    {
+        ConResPrintf(Pager->Screen->Stream, IDS_CONTINUE_PROGRESS,
+                     // (dwSumReadChars - Total + Done) * 100 / dwFileSize
+                     (dwSumReadBytes - (Total - Done) *
+                        (dwSumReadBytes / dwSumReadChars)) * 100 / dwFileSize
+                     );
+    }
 
-   GetConsoleScreenBufferInfo (hStdOut, &csbi);
-      *maxx = (csbi.srWindow.Right - csbi.srWindow.Left) + 1;
-      *maxy = (csbi.srWindow.Bottom  - csbi.srWindow.Top) - 4;
+    // TODO: Implement prompt read line!
 
-}
+    // FIXME: Does not support TTY yet!
 
+    /* RemoveBreakHandler */
+    SetConsoleCtrlHandler(NULL, TRUE);
+    /* ConInDisable */
+    GetConsoleMode(hInput, &dwMode);
+    dwMode &= ~ENABLE_PROCESSED_INPUT;
+    SetConsoleMode(hInput, dwMode);
 
-static
-VOID ConOutPuts (LPTSTR szText)
-{
-   DWORD dwWritten;
-   
-   WriteFile (GetStdHandle (STD_OUTPUT_HANDLE), szText, _tcslen(szText), &dwWritten, NULL);
-   WriteFile (GetStdHandle (STD_OUTPUT_HANDLE), "\n", 1, &dwWritten, NULL);
-}
+    do
+    {
+        // FIXME: Does not support TTY yet!
+
+        // ConInKey(&KeyEvent);
+        INPUT_RECORD ir;
+        DWORD dwRead;
+        do
+        {
+            ReadConsoleInput(hInput, &ir, 1, &dwRead);
+        }
+        while ((ir.EventType != KEY_EVENT) || (!ir.Event.KeyEvent.bKeyDown));
+
+        /* Got our key, return to caller */
+        KeyEvent = ir.Event.KeyEvent;
+    }
+    while ((KeyEvent.wVirtualKeyCode == VK_SHIFT) ||
+           (KeyEvent.wVirtualKeyCode == VK_MENU) ||
+           (KeyEvent.wVirtualKeyCode == VK_CONTROL));
+
+    /* AddBreakHandler */
+    SetConsoleCtrlHandler(NULL, FALSE);
+    /* ConInEnable */
+    GetConsoleMode(hInput, &dwMode);
+    dwMode |= ENABLE_PROCESSED_INPUT;
+    SetConsoleMode(hInput, dwMode);
+
+    /*
+     * Erase the full line where the cursor is, and move
+     * the cursor back to the beginning of the line.
+     */
+    ConClearLine(Pager->Screen->Stream);
+
+    if ((KeyEvent.wVirtualKeyCode == VK_ESCAPE) ||
+        ((KeyEvent.wVirtualKeyCode == L'C') &&
+         (KeyEvent.dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))))
+    {
+        /* We break, output a newline */
+        WCHAR ch = L'\n';
+        ConStreamWrite(Pager->Screen->Stream, &ch, 1);
+        return FALSE;
+    }
 
+    return TRUE;
+}
 
-static VOID
-ConInKey (VOID)
+/*
+ * See base/applications/cmdutils/clip/clip.c!IsDataUnicode()
+ * and base/applications/notepad/text.c!ReadText() for more details.
+ * Also some good code example can be found at:
+ * https://github.com/AutoIt/text-encoding-detect
+ */
+typedef enum
 {
-   INPUT_RECORD ir;
-   DWORD dwRead;
-
-   do
-   {
-      ReadConsoleInput (hKeyboard, &ir, 1, &dwRead);
-      if ((ir.EventType == KEY_EVENT) &&
-         (ir.Event.KeyEvent.bKeyDown == TRUE))
-         return;
-   }
-   while (TRUE);
-}
+    ENCODING_ANSI    =  0,
+    ENCODING_UTF16LE =  1,
+    ENCODING_UTF16BE =  2,
+    ENCODING_UTF8    =  3
+} ENCODING;
+
+static BOOL
+IsDataUnicode(
+    IN PVOID Buffer,
+    IN DWORD BufferSize,
+    OUT ENCODING* Encoding OPTIONAL,
+    OUT PDWORD SkipBytes OPTIONAL)
+{
+    PBYTE pBytes = Buffer;
+    ENCODING encFile = ENCODING_ANSI;
+    DWORD dwPos = 0;
+
+    /*
+     * See http://archives.miloush.net/michkap/archive/2007/04/22/2239345.html
+     * for more details about the algorithm and the pitfalls behind it.
+     * Of course it would be actually great to make a nice function that
+     * would work, once and for all, and put it into a library.
+     */
+
+    /* Look for Byte Order Marks */
+    if ((BufferSize >= 2) && (pBytes[0] == 0xFF) && (pBytes[1] == 0xFE))
+    {
+        encFile = ENCODING_UTF16LE;
+        dwPos = 2;
+    }
+    else if ((BufferSize >= 2) && (pBytes[0] == 0xFE) && (pBytes[1] == 0xFF))
+    {
+        encFile = ENCODING_UTF16BE;
+        dwPos = 2;
+    }
+    else if ((BufferSize >= 3) && (pBytes[0] == 0xEF) && (pBytes[1] == 0xBB) && (pBytes[2] == 0xBF))
+    {
+        encFile = ENCODING_UTF8;
+        dwPos = 3;
+    }
+    else
+    {
+        /*
+         * Try using statistical analysis. Do not rely on the return value of
+         * IsTextUnicode as we can get FALSE even if the text is in UTF-16 BE
+         * (i.e. we have some of the IS_TEXT_UNICODE_REVERSE_MASK bits set).
+         * Instead, set all the tests we want to perform, then just check
+         * the passed tests and try to deduce the string properties.
+         */
+
+/*
+ * This mask contains the 3 highest bits from IS_TEXT_UNICODE_NOT_ASCII_MASK
+ * and the 1st highest bit from IS_TEXT_UNICODE_NOT_UNICODE_MASK.
+ */
+#define IS_TEXT_UNKNOWN_FLAGS_MASK  ((7 << 13) | (1 << 11))
+
+        /* Flag out the unknown flags here, the passed tests will not have them either */
+        INT Tests = (IS_TEXT_UNICODE_NOT_ASCII_MASK   |
+                     IS_TEXT_UNICODE_NOT_UNICODE_MASK |
+                     IS_TEXT_UNICODE_REVERSE_MASK | IS_TEXT_UNICODE_UNICODE_MASK)
+                        & ~IS_TEXT_UNKNOWN_FLAGS_MASK;
+        INT Results;
+    
+        IsTextUnicode(Buffer, BufferSize, &Tests);
+        Results = Tests;
+
+        /*
+         * As the IS_TEXT_UNICODE_NULL_BYTES or IS_TEXT_UNICODE_ILLEGAL_CHARS
+         * flags are expected to be potentially present in the result without
+         * modifying our expectations, filter them out now.
+         */
+        Results &= ~(IS_TEXT_UNICODE_NULL_BYTES | IS_TEXT_UNICODE_ILLEGAL_CHARS);
+
+        /*
+         * NOTE: The flags IS_TEXT_UNICODE_ASCII16 and
+         * IS_TEXT_UNICODE_REVERSE_ASCII16 are not reliable.
+         *
+         * NOTE2: Check for potential "bush hid the facts" effect by also
+         * checking the original results (in 'Tests') for the absence of
+         * the IS_TEXT_UNICODE_NULL_BYTES flag, as we may presumably expect
+         * that in UTF-16 text there will be at some point some NULL bytes.
+         * If not, fall back to ANSI. This shows the limitations of using the
+         * IsTextUnicode API to perform such tests, and the usage of a more
+         * improved encoding detection algorithm would be really welcome.
+         */
+        if (!(Results & IS_TEXT_UNICODE_NOT_UNICODE_MASK) &&
+            !(Results & IS_TEXT_UNICODE_REVERSE_MASK)     &&
+             (Results & IS_TEXT_UNICODE_UNICODE_MASK)     &&
+             (Tests   & IS_TEXT_UNICODE_NULL_BYTES))
+        {
+            encFile = ENCODING_UTF16LE;
+            dwPos = (Results & IS_TEXT_UNICODE_SIGNATURE) ? 2 : 0;
+        }
+        else
+        if (!(Results & IS_TEXT_UNICODE_NOT_UNICODE_MASK) &&
+            !(Results & IS_TEXT_UNICODE_UNICODE_MASK)     &&
+             (Results & IS_TEXT_UNICODE_REVERSE_MASK)     &&
+             (Tests   & IS_TEXT_UNICODE_NULL_BYTES))
+        {
+            encFile = ENCODING_UTF16BE;
+            dwPos = (Results & IS_TEXT_UNICODE_REVERSE_SIGNATURE) ? 2 : 0;
+        }
+        else
+        {
+            /*
+             * Either 'Results' has neither of those masks set, as it can be
+             * the case for UTF-8 text (or ANSI), or it has both as can be the
+             * case when analysing pure binary data chunk. This is therefore
+             * invalid and we fall back to ANSI encoding.
+             * FIXME: In case of failure, assume ANSI (as long as we do not have
+             * correct tests for UTF8, otherwise we should do them, and at the
+             * very end, assume ANSI).
+             */
+            encFile = ENCODING_ANSI; // ENCODING_UTF8;
+            dwPos = 0;
+        }
+    }
 
+    if (Encoding)
+        *Encoding = encFile;
+    if (SkipBytes)
+        *SkipBytes = dwPos;
 
-static VOID
-WaitForKey (VOID)
+    return (encFile != ENCODING_ANSI);
+}
+
+/*
+ * Adapted from base/shell/cmd/misc.c!FileGetString(), but with correct
+ * text encoding support. Also please note that similar code should be
+ * also used in the CMD.EXE 'TYPE' command.
+ * Contrary to CMD's FileGetString() we do not stop at new-lines.
+ *
+ * Read text data from a file and convert it from a given encoding to UTF-16.
+ *
+ *   IN OUT PVOID pCacheBuffer and IN DWORD CacheBufferLength :
+ *     Implementation detail so that the function uses an external user-provided
+ *     buffer to store the data temporarily read from the file. The function
+ *     could have used an internal buffer instead. The length is in number of bytes.
+ *
+ *   IN OUT PWSTR* pBuffer and IN OUT PDWORD pnBufferLength :
+ *     Reallocated buffer containing the string data converted to UTF-16.
+ *     In input, contains a pointer to the original buffer and its length.
+ *     In output, contains a pointer to the reallocated buffer and its length.
+ *     The length is in number of characters.
+ *
+ *     At first call to this function, pBuffer can be set to NULL, in which case
+ *     when the function returns the pointer will point to a valid buffer.
+ *     After the last call to this function, free the pBuffer pointer with:
+ *     HeapFree(GetProcessHeap(), 0, *pBuffer);
+ *
+ *     If Encoding is set to ENCODING_UTF16LE or ENCODING_UTF16BE, since we are
+ *     compiled in UNICODE, no extra conversion is performed and therefore
+ *     pBuffer is unused (remains unallocated) and one can directly use the
+ *     contents of pCacheBuffer as it is expected to contain valid UTF-16 text.
+ *
+ *   OUT PDWORD pdwReadBytes : Number of bytes read from the file (optional).
+ *   OUT PDWORD pdwReadChars : Corresponding number of characters read (optional).
+ */
+static BOOL
+FileGetString(
+    IN HANDLE hFile,
+    IN ENCODING Encoding,
+    IN OUT PVOID pCacheBuffer,
+    IN DWORD CacheBufferLength,
+    IN OUT PWCHAR* pBuffer,
+    IN OUT PDWORD pnBufferLength,
+    OUT PDWORD pdwReadBytes OPTIONAL,
+    OUT PDWORD pdwReadChars OPTIONAL)
 {
-   DWORD dwWritten;
+    BOOL Success;
+    UINT CodePage = (UINT)-1;
+    DWORD dwReadBytes;
+    INT len;
 
-    WriteFile (hStdErr, szCont , szContLength, &dwWritten, NULL);
+    // ASSERT(pCacheBuffer && (CacheBufferLength > 0));
+    // ASSERT(CacheBufferLength % 2 == 0); // Cache buffer length MUST BE even!
+    // ASSERT(pBuffer && pnBufferLength);
 
-   ConInKey();
+    /* Always reset the retrieved number of bytes/characters */
+    if (pdwReadBytes) *pdwReadBytes = 0;
+    if (pdwReadChars) *pdwReadChars = 0;
 
-   WriteFile (hStdErr, _T("\n"), 1, &dwWritten, NULL);
+    Success = ReadFile(hFile, pCacheBuffer, CacheBufferLength, &dwReadBytes, NULL);
+    if (!Success || dwReadBytes == 0)
+        return FALSE;
 
-//     FlushConsoleInputBuffer (hConsoleIn);
-}
+    if (pdwReadBytes) *pdwReadBytes = dwReadBytes;
 
+    if ((Encoding == ENCODING_ANSI) || (Encoding == ENCODING_UTF8))
+    {
+        /* Conversion is needed */
+
+        if (Encoding == ENCODING_ANSI)
+            CodePage = GetConsoleCP(); // CP_ACP; // FIXME: Cache GetConsoleCP() value.
+        else // if (Encoding == ENCODING_UTF8)
+            CodePage = CP_UTF8;
+
+        /* Retrieve the needed buffer size */
+        len = MultiByteToWideChar(CodePage, 0, pCacheBuffer, dwReadBytes,
+                                  NULL, 0);
+        if (len == 0)
+        {
+            /* Failure, bail out */
+            return FALSE;
+        }
+
+        /* Initialize the conversion buffer if needed... */
+        if (*pBuffer == NULL)
+        {
+            *pnBufferLength = len;
+            *pBuffer = HeapAlloc(GetProcessHeap(), 0, *pnBufferLength * sizeof(WCHAR));
+            if (*pBuffer == NULL)
+            {
+                // *pBuffer = NULL;
+                *pnBufferLength = 0;
+                // WARN("DEBUG: Cannot allocate memory for *pBuffer!\n");
+                // ConErrFormatMessage(GetLastError());
+                return FALSE;
+            }
+        }
+        /* ... or reallocate only if the new length is greater than the old one */
+        else if (len > *pnBufferLength)
+        {
+            PWSTR OldBuffer = *pBuffer;
+
+            *pnBufferLength = len;
+            *pBuffer = HeapReAlloc(GetProcessHeap(), 0, *pBuffer, *pnBufferLength * sizeof(WCHAR));
+            if (*pBuffer == NULL)
+            {
+                /* Do not leak old buffer */
+                HeapFree(GetProcessHeap(), 0, OldBuffer);
+                // *pBuffer = NULL;
+                *pnBufferLength = 0;
+                // WARN("DEBUG: Cannot reallocate memory for *pBuffer!\n");
+                // ConErrFormatMessage(GetLastError());
+                return FALSE;
+            }
+        }
 
-//INT CommandMore (LPTSTR cmd, LPTSTR param)
-int main (int argc, char **argv)
-{
-   SHORT maxx,maxy;
-   SHORT line_count=0,ch_count=0;
-   DWORD i, last;
-   HANDLE hFile = INVALID_HANDLE_VALUE;
-   TCHAR szFullPath[MAX_PATH];
-    TCHAR szMsg[1024];
-   /*reading/writing buffer*/
-   TCHAR *buff;
+        /* Now perform the conversion proper */
+        len = MultiByteToWideChar(CodePage, 0, pCacheBuffer, dwReadBytes,
+                                  *pBuffer, len);
+        dwReadBytes = len;
+    }
+    else
+    {
+        /*
+         * No conversion needed, just convert from big to little endian if needed.
+         * pBuffer and pnBufferLength are left untouched and pCacheBuffer can be
+         * directly used.
+         */
+        PWCHAR pWChars = pCacheBuffer;
+        DWORD i;
+
+        dwReadBytes /= sizeof(WCHAR);
+
+        if (Encoding == ENCODING_UTF16BE)
+        {
+            for (i = 0; i < dwReadBytes; i++)
+            {
+                /* Equivalent to RtlUshortByteSwap: reverse high/low bytes */
+                pWChars[i] = MAKEWORD(HIBYTE(pWChars[i]), LOBYTE(pWChars[i]));
+            }
+        }
+        // else if (Encoding == ENCODING_UTF16LE), we are good, nothing to do.
+    }
 
-   /*bytes written by WriteFile and ReadFile*/
-   DWORD dwRead,dwWritten;
+    /* Return the number of characters (dwReadBytes is converted) */
+    if (pdwReadChars) *pdwReadChars = dwReadBytes;
 
-   /*ReadFile() return value*/
-   BOOL bRet;
+    return TRUE;
+}
 
+// INT CommandMore(LPTSTR cmd, LPTSTR param)
+int wmain(int argc, WCHAR* argv[])
+{
+    // FIXME this stuff!
+    CON_SCREEN Screen = {StdOut};
+    CON_PAGER Pager = {&Screen, 0};
 
-   hStdIn = GetStdHandle(STD_INPUT_HANDLE);
-   hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
-   hStdErr = GetStdHandle(STD_ERROR_HANDLE);
-    hApp = GetModuleHandle(NULL);
+    int i;
 
-   buff=malloc(4096);
-   if (!buff)
-   {
-      ConOutPuts(_T("Error: no memory"));
-      return 1;
-   }
+    BOOL bRet, bContinue;
 
-   if (argc > 1 && _tcsncmp (argv[1], _T("/?"), 2) == 0)
-   {
-      if (LoadString(hApp, IDS_USAGE, buff, 4096 / sizeof(TCHAR)) < (int)(4096 / sizeof(TCHAR)))
-      {
-         CharToOem(buff, buff);
-         ConOutPuts(buff);
-      }
+    ENCODING Encoding;
+    DWORD SkipBytes = 0;
 
-      free(buff);
-      return 0;
-   }
+#define FileCacheBufferSize 4096
+    PVOID FileCacheBuffer = NULL;
+    PWCHAR StringBuffer = NULL;
+    DWORD StringBufferLength = 0;
+    DWORD dwReadBytes, dwReadChars;
 
-   hKeyboard = CreateFile (_T("CONIN$"), GENERIC_READ|GENERIC_WRITE,
-                           0,NULL,OPEN_ALWAYS,0,0);
+    TCHAR szFullPath[MAX_PATH];
 
-   GetScreenSize(&maxx,&maxy);
+    hStdIn = GetStdHandle(STD_INPUT_HANDLE);
+    hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
 
+    /* Initialize the Console Standard Streams */
+    ConStreamInit(StdIn , GetStdHandle(STD_INPUT_HANDLE) , UTF8Text, INVALID_CP);
+    ConStreamInit(StdOut, GetStdHandle(STD_OUTPUT_HANDLE), UTF8Text, INVALID_CP);
+    ConStreamInit(StdErr, GetStdHandle(STD_ERROR_HANDLE) , UTF8Text, INVALID_CP);
 
+    /*
+     * Bad usage (too much options) or we use the /? switch.
+     * Display help for the MORE command.
+     */
+    if (argc > 1 && wcscmp(argv[1], L"/?") == 0)
+    {
+        ConResPuts(StdOut, IDS_USAGE);
+        return 0;
+    }
 
-   FlushConsoleInputBuffer (hKeyboard);
+    // FIXME: Parse all the remaining parameters.
+    // Then the file list can be found at the very end.
+    // FIXME2: Use the PARSER api that can be found in EVENTCREATE.
 
-   if(argc > 1)
-   {
-      GetFullPathNameA(argv[1], MAX_PATH, szFullPath, NULL);
-      hFile = CreateFile (szFullPath, 
-                            GENERIC_READ,
-                           0,
-                            NULL,
-                            OPEN_EXISTING,
-                            0,
-                            0);
-      if (hFile == INVALID_HANDLE_VALUE)
-      {
-         if (LoadString(hApp, IDS_FILE_ACCESS, szMsg, sizeof(szMsg) / sizeof(TCHAR)) < (int)(sizeof(szMsg) / sizeof(TCHAR)))
-         {
-            _stprintf(buff, szMsg, szFullPath);
-            CharToOem(buff, buff);
-            ConOutPuts(buff);
-         }
-
-         free(buff);
-         return 0;
-      }
-   }
-   else
-   {
-      hFile = hStdIn;
-   }
-
-    if (!LoadString(hApp, IDS_CONTINUE, szCont, sizeof(szCont) / sizeof(TCHAR)))
+    // NOTE: We might try to duplicate the ConOut for read access... ?
+    hKeyboard = CreateFileW(L"CONIN$", GENERIC_READ|GENERIC_WRITE,
+                            FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
+                            OPEN_EXISTING, 0, NULL);
+    FlushConsoleInputBuffer(hKeyboard);
+    ConStreamSetOSHandle(StdIn, hKeyboard);
+
+
+    FileCacheBuffer = HeapAlloc(GetProcessHeap(), 0, FileCacheBufferSize);
+    if (!FileCacheBuffer)
     {
-        /* Shouldn't happen, so exit */
-        free(buff);
+        ConPuts(StdErr, L"Error: no memory\n");
+        CloseHandle(hKeyboard);
         return 1;
     }
-    szContLength = _tcslen(szCont);
-
 
+    /* Special case where we run 'MORE' without any argument: we use STDIN */
+    if (argc <= 1)
+    {
+        /*
+         * Assign STDIN handle to hFile so that the page prompt function will
+         * know the data comes from STDIN, and will take different actions.
+         */
+        hFile = hStdIn;
+
+        /* Update the statistics for PagePrompt */
+        dwFileSize = 0;
+        dwSumReadBytes = dwSumReadChars = 0;
+
+        /* We suppose we read text from the file */
+
+        /* For STDIN we always suppose we are in ANSI mode */
+        // SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
+        Encoding = ENCODING_ANSI; // ENCODING_UTF8;
+
+        bContinue = ConPutsPaging(&Pager, PagePrompt, TRUE, L"");
+        if (!bContinue)
+            goto Quit;
+
+        do
+        {
+            bRet = FileGetString(hFile, Encoding,
+                                 FileCacheBuffer, FileCacheBufferSize,
+                                 &StringBuffer, &StringBufferLength,
+                                 &dwReadBytes, &dwReadChars);
+            if (!bRet || dwReadBytes == 0 || dwReadChars == 0)
+            {
+                /* We failed at reading the file, bail out */
+                break;
+            }
 
-   do
-   {
-      bRet = ReadFile(hFile,buff,4096,&dwRead,NULL);
+            /* Update the statistics for PagePrompt */
+            dwSumReadBytes += dwReadBytes;
+            dwSumReadChars += dwReadChars;
+
+            bContinue = ConWritePaging(&Pager, PagePrompt, FALSE,
+                                       StringBuffer, dwReadChars);
+            /* If we Ctrl-C/Ctrl-Break, stop everything */
+            if (!bContinue)
+                goto Quit;
+        }
+        while (bRet && dwReadBytes > 0);
+        goto Quit;
+    }
 
-      for(last=i=0;i<dwRead && bRet;i++)
-      {
-         ch_count++;
-         if(buff[i] == _T('\n') || ch_count == maxx)
-         {
-            ch_count=0;
-            line_count++;
-            if (line_count == maxy)
+    /* We have files: read them and output them to STDOUT */
+    for (i = 1; i < argc; i++)
+    {
+        GetFullPathNameW(argv[i], ARRAYSIZE(szFullPath), szFullPath, NULL);
+        hFile = CreateFileW(szFullPath, 
+                            GENERIC_READ,
+                            FILE_SHARE_READ,
+                            NULL,
+                            OPEN_EXISTING,
+                            0, // FILE_ATTRIBUTE_NORMAL,
+                            NULL);
+        if (hFile == INVALID_HANDLE_VALUE)
+        {
+            ConResPrintf(StdErr, IDS_FILE_ACCESS, szFullPath);
+            continue;
+        }
+
+        /* We currently do not support files too big */
+        dwFileSize = GetFileSize(hFile, NULL);
+        if (dwFileSize == INVALID_FILE_SIZE)
+        {
+            ConPuts(StdErr, L"ERROR: Invalid file size!\n");
+            CloseHandle(hFile);
+            continue;
+        }
+
+        /* We suppose we read text from the file */
+
+        /* Check whether the file is UNICODE and retrieve its encoding */
+        SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
+        bRet = ReadFile(hFile, FileCacheBuffer, FileCacheBufferSize, &dwReadBytes, NULL);
+        IsDataUnicode(FileCacheBuffer, dwReadBytes, &Encoding, &SkipBytes);
+        SetFilePointer(hFile, SkipBytes, NULL, FILE_BEGIN);
+
+        /* Update the statistics for PagePrompt */
+        dwSumReadBytes = dwSumReadChars = 0;
+
+        bContinue = ConPutsPaging(&Pager, PagePrompt, TRUE, L"");
+        if (!bContinue)
+        {
+            CloseHandle(hFile);
+            goto Quit;
+        }
+
+        do
+        {
+            bRet = FileGetString(hFile, Encoding,
+                                 FileCacheBuffer, FileCacheBufferSize,
+                                 &StringBuffer, &StringBufferLength,
+                                 &dwReadBytes, &dwReadChars);
+            if (!bRet || dwReadBytes == 0 || dwReadChars == 0)
             {
-               line_count = 0;
-               WriteFile(hStdOut,&buff[last], i-last+1, &dwWritten, NULL);
-               last=i+1;
-               FlushFileBuffers (hStdOut);
-               WaitForKey ();
+                /*
+                 * We failed at reading the file, bail out and
+                 * continue with the other files.
+                 */
+                break;
             }
-         }
-      }
-      if (last<dwRead && bRet)
-         WriteFile(hStdOut,&buff[last], dwRead-last, &dwWritten, NULL);
 
-   }
-   while(dwRead>0 && bRet);
+            /* Update the statistics for PagePrompt */
+            dwSumReadBytes += dwReadBytes;
+            dwSumReadChars += dwReadChars;
+
+            if ((Encoding == ENCODING_UTF16LE) || (Encoding == ENCODING_UTF16BE))
+            {
+                bContinue = ConWritePaging(&Pager, PagePrompt, FALSE,
+                                           FileCacheBuffer, dwReadChars);
+            }
+            else
+            {
+                bContinue = ConWritePaging(&Pager, PagePrompt, FALSE,
+                                           StringBuffer, dwReadChars);
+            }
+            /* If we Ctrl-C/Ctrl-Break, stop everything */
+            if (!bContinue)
+            {
+                CloseHandle(hFile);
+                goto Quit;
+            }
+        }
+        while (bRet && dwReadBytes > 0);
 
-   free (buff);
-   CloseHandle (hKeyboard);
-   if (hFile != hStdIn)
-      CloseHandle (hFile);
+        CloseHandle(hFile);
+    }
 
-   return 0;
+Quit:
+    if (StringBuffer) HeapFree(GetProcessHeap(), 0, StringBuffer);
+    HeapFree(GetProcessHeap(), 0, FileCacheBuffer);
+    CloseHandle(hKeyboard);
+    return 0;
 }
 
 /* EOF */
index c772bb9..b9339d8 100644 (file)
@@ -2,13 +2,16 @@
 
 #include "resource.h"
 
-#define REACTOS_STR_FILE_DESCRIPTION  "ReactOS More Command"
-#define REACTOS_STR_INTERNAL_NAME     "more"
-#define REACTOS_STR_ORIGINAL_FILENAME "more.com"
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
+
+#define REACTOS_STR_FILE_DESCRIPTION    "ReactOS More Command"
+#define REACTOS_STR_INTERNAL_NAME       "more"
+#define REACTOS_STR_ORIGINAL_FILENAME   "more.com"
 #include <reactos/version.rc>
 
 /* UTF-8 */
 #pragma code_page(65001)
+
 #ifdef LANGUAGE_BG_BG
     #include "lang/bg-BG.rc"
 #endif
@@ -71,4 +74,4 @@
 #endif
 #ifdef LANGUAGE_ZH_TW
     #include "lang/zh-TW.rc"
-#endif
\ No newline at end of file
+#endif
index 756c41a..dc077bb 100644 (file)
@@ -2,4 +2,5 @@
 
 #define IDS_USAGE       100
 #define IDS_CONTINUE    101
-#define IDS_FILE_ACCESS 102
+#define IDS_CONTINUE_PROGRESS   102
+#define IDS_FILE_ACCESS 103