Enable the line editor in read() for CP/M.
This changes the BDOS call from CPM_BDOS_CONSOLE_INPUT to CPN_BDOS_READ_CONSOLE_BUFFER. This allows commands like ^H to delete characters and ^C to exit to CCP. This is more like how Unix read(2) uses canonical mode of termios to read a line. This change has a disadvantage: the user buffer to read(2) must now be large enough for an entire line. This is because CP/M, unlike Unix, lacks a kernel buffer to hold the rest of the line. If you use a buffered input library like stdio to call read(2), then it works; but if you try to read part of a line or a single character, then it doesn't work.
This commit is contained in:
parent
b4be612832
commit
154509038d
|
@ -10,29 +10,44 @@
|
||||||
|
|
||||||
int read(int fd, void* buffer, size_t count)
|
int read(int fd, void* buffer, size_t count)
|
||||||
{
|
{
|
||||||
char i;
|
short save;
|
||||||
|
unsigned char before_n;
|
||||||
|
|
||||||
/* We're only allowed to read from fd 0, 1 or 2. */
|
/* We're only allowed to read from fd 0, 1 or 2. */
|
||||||
|
|
||||||
if ((fd < 0) || (fd > 2))
|
if ((fd < 0) || (fd > 2))
|
||||||
{
|
{
|
||||||
errno = EBADF;
|
errno = EBADF;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Empty buffer? */
|
/* We need room for at least 1 char plus '\n'. */
|
||||||
|
if (count < 2)
|
||||||
if (count == 0)
|
{
|
||||||
return 0;
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
/* Read one byte. */
|
}
|
||||||
|
|
||||||
cpm_bc_register = CPM_BDOS_CONSOLE_INPUT;
|
/* Make room to append '\n' later. */
|
||||||
|
before_n = count > 255 ? 255 : count - 1;
|
||||||
|
|
||||||
|
/* Borrow 2 bytes of RAM before the buffer. */
|
||||||
|
/* This might overwrite count!!! */
|
||||||
|
save = ((short*)buffer)[-1];
|
||||||
|
|
||||||
|
/* Read one line from the console. */
|
||||||
|
((unsigned char*)buffer)[-2] = before_n;
|
||||||
|
cpm_bc_register = CPM_BDOS_READ_CONSOLE_BUFFER;
|
||||||
|
cpm_de_register = (char*)buffer - 2;
|
||||||
|
cpm_bdos();
|
||||||
|
before_n = ((unsigned char*)buffer)[-1];
|
||||||
|
|
||||||
|
((char*)buffer)[before_n] = '\n'; /* Append '\n'. */
|
||||||
|
((short*)buffer)[-1] = save; /* Give back borrowed bytes. */
|
||||||
|
|
||||||
|
/* Echo '\n' to console. */
|
||||||
|
cpm_bc_register = CPM_BDOS_PRINT_STRING;
|
||||||
|
cpm_de_register = "\r\n$";
|
||||||
cpm_bdos();
|
cpm_bdos();
|
||||||
|
|
||||||
if (cpm_a_register == '\r')
|
return (int)before_n + 1;
|
||||||
cpm_a_register = '\n';
|
|
||||||
*(char*)buffer = cpm_a_register;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue