Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/dosbox-staging/dosbox-staging.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFeralChild64 <>2022-10-12 01:19:18 +0300
committerFeralChild64 <>2022-10-12 10:50:01 +0300
commit89fa10b8270f7e99f71b78c3cc38655ddfa97752 (patch)
tree0e3c951a14892946066974681d2d1b36963243ed
parent83a2ab3ec59a4dffc8a78dad554aecf64422b001 (diff)
Implement MORE.COM commandfc/command-more-1
-rw-r--r--src/dos/dos_programs.cpp2
-rw-r--r--src/dos/meson.build1
-rw-r--r--src/dos/program_more.cpp173
-rw-r--r--src/dos/program_more.h42
-rw-r--r--vs/dosbox.vcxproj1
-rw-r--r--vs/dosbox.vcxproj.filters3
6 files changed, 222 insertions, 0 deletions
diff --git a/src/dos/dos_programs.cpp b/src/dos/dos_programs.cpp
index 48ed523d6..2bf99f99e 100644
--- a/src/dos/dos_programs.cpp
+++ b/src/dos/dos_programs.cpp
@@ -32,6 +32,7 @@
#include "program_loadrom.h"
#include "program_ls.h"
#include "program_mem.h"
+#include "program_more.h"
#include "program_mount.h"
#include "program_placeholder.h"
#include "program_rescan.h"
@@ -74,6 +75,7 @@ void Add_VFiles(const bool add_autoexec)
PROGRAMS_MakeFile("LOADROM.COM", ProgramCreate<LOADROM>);
PROGRAMS_MakeFile("LS.COM", ProgramCreate<LS>);
PROGRAMS_MakeFile("MEM.COM", ProgramCreate<MEM>);
+ PROGRAMS_MakeFile("MORE.COM", ProgramCreate<MORE>);
PROGRAMS_MakeFile("MOUNT.COM", ProgramCreate<MOUNT>);
PROGRAMS_MakeFile("RESCAN.COM", ProgramCreate<RESCAN>);
PROGRAMS_MakeFile("MIXER.COM", MIXER_ProgramCreate);
diff --git a/src/dos/meson.build b/src/dos/meson.build
index 4a31a1bf1..d9021ef34 100644
--- a/src/dos/meson.build
+++ b/src/dos/meson.build
@@ -34,6 +34,7 @@ libdos_sources = files(
'program_loadrom.cpp',
'program_ls.cpp',
'program_mem.cpp',
+ 'program_more.cpp',
'program_mount.cpp',
'program_mount_common.cpp',
'program_placeholder.cpp',
diff --git a/src/dos/program_more.cpp b/src/dos/program_more.cpp
new file mode 100644
index 000000000..cb23e6223
--- /dev/null
+++ b/src/dos/program_more.cpp
@@ -0,0 +1,173 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * Copyright (C) 2022 The DOSBox Staging Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "program_more.h"
+
+#include "../ints/int10.h"
+#include "checks.h"
+
+CHECK_NARROWING();
+
+
+// ASCII control characters
+static constexpr char char_break = 0x03;
+static constexpr char char_line_feed = 0x0a;
+static constexpr char char_carriage_return = 0x0d;
+
+
+void MORE::Run()
+{
+ // Check command line
+
+ if (HelpRequested()) {
+ WriteOut(MSG_Get("SHELL_CMD_MORE_HELP_LONG"));
+ return;
+ }
+
+ if (cmd->GetCount()) {
+ WriteOut(MSG_Get("SHELL_CMD_MORE_SYNTAX"));
+ return;
+ }
+
+ // Prepare screen parameters information
+
+ const auto adapt_dimension = [](const uint16_t d) {
+ const uint16_t min = 10;
+ if (d < min)
+ return min;
+ else
+ return static_cast<uint16_t>(d - 1);
+ };
+
+ const uint16_t screen_max_x = adapt_dimension(INT10_GetTextColumns());
+ const uint16_t screen_max_y = adapt_dimension(INT10_GetTextRows());
+
+ auto get_column = []() {
+ const auto page = real_readb(BIOSMEM_SEG, BIOSMEM_CURRENT_PAGE);
+ return CURSOR_POS_COL(page);
+ };
+
+ // We need to be able to read STDIN for key presses, but it is most
+ // likely redirected - so clone the handle, and reconstruct real STDIN
+ // from STDERR (idea from FreeDOS implementation,
+ // https://github.com/FDOS/more/blob/master/src/more.c)
+
+ uint16_t in_handle = 0;
+ if (!DOS_DuplicateEntry(STDIN, &in_handle) ||
+ !DOS_ForceDuplicateEntry(STDERR, STDIN)) {
+ LOG_ERR("DOS: Unable to prepare handles in MORE.COM");
+ return;
+ }
+
+ // Main loop
+
+ char character = '\0';
+ uint16_t amount = 1;
+ uint16_t counter = 0;
+
+ auto previous_column = get_column();
+ bool previous_was_cr = false; // if last character was 'carriage return'
+ bool previous_was_lf = false; // if last character was 'line feed'
+
+ while (true) {
+ if (!counter)
+ counter = screen_max_y;
+
+ // Read character and duplicate it on the output
+
+ amount = 1;
+ DOS_ReadFile(in_handle, reinterpret_cast<uint8_t *>(&character), &amount);
+ if (!amount)
+ break; // end of stream
+ WriteOut("%c", character);
+
+ // Detect new line; we can't just simply the characters,
+ // as some might be ANSI escape codes
+
+ const auto column = get_column();
+
+ if ((!previous_was_cr && character == char_line_feed) ||
+ (!previous_was_lf && character == char_carriage_return))
+ --counter; // new line in the input stream
+ else if (character != char_line_feed &&
+ character != char_carriage_return &&
+ (!column && (previous_column == screen_max_x)))
+ --counter; // line longer than screen size
+
+ previous_column = column;
+ previous_was_cr = (character == char_carriage_return);
+ previous_was_lf = (character == char_line_feed);
+
+ if (counter)
+ continue;
+
+ // Scrolling occured several times, pause until key press
+
+ if (!column)
+ WriteOut("\n");
+ WriteOut(MSG_Get("SHELL_CMD_PAUSE"));
+ WriteOut("\n");
+
+ amount = 0;
+ while (!amount) {
+ amount = 1;
+ DOS_ReadFile(STDIN,
+ reinterpret_cast<uint8_t *>(&character),
+ &amount);
+ }
+
+ // Check for termination by user (CTRL+C)
+
+ if (character == char_break) {
+ WriteOut("^C\n");
+ break;
+ }
+ }
+
+ // End of processing
+
+ WriteOut("\n");
+}
+
+void MORE::AddMessages()
+{
+ MSG_Add("SHELL_CMD_MORE_HELP",
+ "Display command output or text file one screen at a time.\n");
+ MSG_Add("SHELL_CMD_MORE_HELP_LONG",
+ "Display command output or text file one screen at a time.\n"
+ "\n"
+ "Usage:\n"
+ " [color=cyan]COMMAND[reset] | [color=green]more[reset]\n"
+ " [color=green]more[reset] < [color=cyan]FILE[reset]\n"
+ "\n"
+ "Where:\n"
+ " [color=cyan]COMMAND[reset] is the command to diplay output one screen at a time.\n"
+ " [color=cyan]FILE[reset] is the name of the file to display.\n"
+ "\n"
+ "Notes:\n"
+ " The file must be an exact file name, optionally with a path.\n"
+ " This command is only for viewing text files, not binary files.\n"
+ "\n"
+ "Examples:\n"
+ " [color=cyan]dir /on[reset] | [color=green]more[reset] ; shows sorted directory content one screen at a time\n"
+ " [color=green]more[reset] < [color=cyan]A:\\MANUAL.TXT[reset] ; displays the file content one screen at a time");
+
+ MSG_Add("SHELL_CMD_MORE_SYNTAX", "Wrong command syntax.");
+}
diff --git a/src/dos/program_more.h b/src/dos/program_more.h
new file mode 100644
index 000000000..536c5df9e
--- /dev/null
+++ b/src/dos/program_more.h
@@ -0,0 +1,42 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * Copyright (C) 2022 The DOSBox Staging Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef DOSBOX_PROGRAM_MORE_H
+#define DOSBOX_PROGRAM_MORE_H
+
+#include "programs.h"
+
+class MORE final : public Program {
+public:
+ MORE()
+ {
+ AddMessages();
+ help_detail = {HELP_Filter::All,
+ HELP_Category::Dosbox,
+ HELP_CmdType::Program,
+ "MORE"};
+ }
+ void Run();
+
+private:
+ void AddMessages();
+};
+
+#endif
diff --git a/vs/dosbox.vcxproj b/vs/dosbox.vcxproj
index 36269342e..384b99920 100644
--- a/vs/dosbox.vcxproj
+++ b/vs/dosbox.vcxproj
@@ -553,6 +553,7 @@ IF %ERRORLEVEL% LSS 8 SET ERRORLEVEL = 0</Command>
<ClCompile Include="..\src\dos\program_loadrom.cpp" />
<ClCompile Include="..\src\dos\program_ls.cpp" />
<ClCompile Include="..\src\dos\program_mem.cpp" />
+ <ClCompile Include="..\src\dos\program_more.cpp" />
<ClCompile Include="..\src\dos\program_mount_common.cpp" />
<ClCompile Include="..\src\dos\program_mount.cpp" />
<ClCompile Include="..\src\dos\program_placeholder.cpp" />
diff --git a/vs/dosbox.vcxproj.filters b/vs/dosbox.vcxproj.filters
index 3823a9f06..a4627ead5 100644
--- a/vs/dosbox.vcxproj.filters
+++ b/vs/dosbox.vcxproj.filters
@@ -559,6 +559,9 @@
<ClCompile Include="..\src\dos\program_mem.cpp">
<Filter>src\dos</Filter>
</ClCompile>
+ <ClCompile Include="..\src\dos\program_more.cpp">
+ <Filter>src\dos</Filter>
+ </ClCompile>
<ClCompile Include="..\src\dos\program_mount.cpp">
<Filter>src\dos</Filter>
</ClCompile>