-
-
Notifications
You must be signed in to change notification settings - Fork 152
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
FeralChild64
committed
Oct 12, 2022
1 parent
c437482
commit c660d66
Showing
4 changed files
with
209 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
/* | ||
* 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 "checks.h" | ||
|
||
#include "../ints/int10.h" | ||
|
||
CHECK_NARROWING(); | ||
|
||
// ASCII control characters | ||
static constexpr char char_break = 0x03; | ||
static constexpr char char_backspace = 0x08; | ||
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 uint16_t screen_max_x = INT10_GetTextColumns() - 1; | ||
const uint16_t screen_max_y = INT10_GetTextRows() - 1; | ||
|
||
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")); | ||
|
||
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."); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |