mirror of https://github.com/FDOS/kernel.git
Improve ^C handling:
- ^C didn't work for int21/ah=3f. Corrected -- Do_DosIdle_loop still needs to wait even if it doesn't call the idle int - ^C needs to be echoed to STDOUT for low character functions (ah<0xd) but to the device that is read from for handle functions. So we need to pass either the STDOUT sft or that device on to the ^C echoer. - The ^C echo really should print ^C\r\n. - misc cleanups in break.c. git-svn-id: https://svn.code.sf.net/p/freedos/svn/kernel/trunk@883 6ac86273-5f31-0410-b378-82cca8765d1b
This commit is contained in:
parent
9c41d97021
commit
f94ba5ebe1
|
@ -31,49 +31,48 @@
|
||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
#include "proto.h"
|
#include "proto.h"
|
||||||
|
|
||||||
extern void ASMCFUNC spawn_int23(void);
|
|
||||||
|
|
||||||
#ifdef VERSION_STRINGS
|
#ifdef VERSION_STRINGS
|
||||||
static BYTE *RcsId =
|
static BYTE *RcsId =
|
||||||
"$Id$";
|
"$Id$";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define CB_FLG *(UBYTE FAR*)MK_FP(0x40, 0x71)
|
#define CB_FLG *(UBYTE FAR*)MK_FP(0x0, 0x471)
|
||||||
#define CB_MSK 0x80
|
#define CB_MSK 0x80
|
||||||
|
|
||||||
/* Check for ^Break.
|
/* Check for ^Break/^C.
|
||||||
|
* Three sources are available:
|
||||||
* Two sources are available:
|
* 1) flag at 40:71 bit 7
|
||||||
* 1) flag at 40:71 bit 7
|
* 2) CON stream (if STDIN is redirected somewhere else)
|
||||||
* 2) STDIN stream via con_break()
|
* 3) input stream (most likely STDIN)
|
||||||
*/
|
|
||||||
int check_handle_break(void)
|
|
||||||
{
|
|
||||||
if (CB_FLG & CB_MSK) {
|
|
||||||
CB_FLG &= ~CB_MSK; /* reset the ^Break flag */
|
|
||||||
handle_break(&syscon);
|
|
||||||
}
|
|
||||||
/* con_break will call handle_break() for CTL_C */
|
|
||||||
return con_break();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Handles a ^Break state
|
|
||||||
*
|
|
||||||
* Actions:
|
* Actions:
|
||||||
* 1) clear the ^Break flag
|
* 1) echo ^C
|
||||||
* 2) clear the STDIN stream
|
* 2) clear the STDIN stream
|
||||||
* 3) decrease the InDOS flag as the kernel drops back to user space
|
* 3) decrease the InDOS flag as the kernel drops back to user space
|
||||||
* 4) invoke INT-23 and never come back
|
* 4) invoke INT-23 and never come back
|
||||||
*/
|
*/
|
||||||
void handle_break(struct dhdr FAR **pdev)
|
unsigned char check_handle_break(struct dhdr FAR **pdev, int sft_out)
|
||||||
{
|
{
|
||||||
echo_char(CTL_C, get_sft_idx(STDOUT));
|
unsigned char c = CTL_C;
|
||||||
con_flush(pdev);
|
if (CB_FLG & CB_MSK)
|
||||||
if (!ErrorMode) /* within int21_handler, InDOS is not incremented */
|
CB_FLG &= ~CB_MSK; /* reset the ^Break flag */
|
||||||
if (InDOS)
|
else
|
||||||
--InDOS; /* fail-safe */
|
c = (unsigned char)ndread(&syscon);
|
||||||
|
if (c == CTL_C)
|
||||||
|
{
|
||||||
|
sft_out = -1;
|
||||||
|
pdev = &syscon;
|
||||||
|
}
|
||||||
|
else if (*pdev != syscon)
|
||||||
|
c = (unsigned char)ndread(pdev);
|
||||||
|
if (c == CTL_C)
|
||||||
|
{
|
||||||
|
con_flush(pdev);
|
||||||
|
echo_ctl_c(pdev, sft_out);
|
||||||
|
if (!ErrorMode) /* within int21_handler, InDOS is not incremented */
|
||||||
|
if (InDOS)
|
||||||
|
--InDOS; /* fail-safe */
|
||||||
|
|
||||||
spawn_int23(); /* invoke user INT-23 and never come back */
|
spawn_int23(); /* invoke user INT-23 and never come back */
|
||||||
|
}
|
||||||
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -128,15 +128,15 @@ int StdinBusy(void)
|
||||||
|
|
||||||
STATIC void Do_DosIdle_loop(struct dhdr FAR **pdev)
|
STATIC void Do_DosIdle_loop(struct dhdr FAR **pdev)
|
||||||
{
|
{
|
||||||
/* the idle loop is only safe if we're using the character stack */
|
/* the idle int is only safe if we're using the character stack */
|
||||||
if (user_r->AH < 0xd)
|
while (Busy(pdev) && (*pdev == syscon || Busy(&syscon)))
|
||||||
while (Busy(pdev) && Busy(&syscon))
|
if (user_r->AH < 0xd)
|
||||||
DosIdle_int();
|
DosIdle_int();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get character from the console - this is how DOS gets
|
/* get character from the console - this is how DOS gets
|
||||||
CTL_C/CTL_S/CTL_P when outputting */
|
CTL_C/CTL_S/CTL_P when outputting */
|
||||||
STATIC int ndread(struct dhdr FAR **pdev)
|
int ndread(struct dhdr FAR **pdev)
|
||||||
{
|
{
|
||||||
CharCmd(pdev, C_NDREAD);
|
CharCmd(pdev, C_NDREAD);
|
||||||
if (CharReqHdr.r_status & S_BUSY)
|
if (CharReqHdr.r_status & S_BUSY)
|
||||||
|
@ -144,35 +144,19 @@ STATIC int ndread(struct dhdr FAR **pdev)
|
||||||
return CharReqHdr.r_ndbyte;
|
return CharReqHdr.r_ndbyte;
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC void con_skip_char(struct dhdr FAR **pdev)
|
STATIC void con_hold(struct dhdr FAR **pdev, int sft_out)
|
||||||
{
|
{
|
||||||
if (CharIO(pdev, 0, C_INPUT) == CTL_C)
|
unsigned char c = check_handle_break(pdev, sft_out);
|
||||||
handle_break(pdev);
|
if (c == CTL_S)
|
||||||
}
|
|
||||||
|
|
||||||
STATIC void con_hold(struct dhdr FAR **pdev)
|
|
||||||
{
|
|
||||||
int c = check_handle_break();
|
|
||||||
if (*pdev != syscon)
|
|
||||||
c = ndread(pdev);
|
|
||||||
if (c == CTL_S || c == CTL_C)
|
|
||||||
{
|
{
|
||||||
con_skip_char(pdev);
|
CharIO(pdev, 0, C_INPUT);
|
||||||
Do_DosIdle_loop(pdev);
|
Do_DosIdle_loop(pdev);
|
||||||
/* just wait */
|
/* just wait and then skip a character */
|
||||||
check_handle_break();
|
check_handle_break(pdev, sft_out);
|
||||||
con_skip_char(pdev);
|
CharIO(pdev, 0, C_INPUT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int con_break(void)
|
|
||||||
{
|
|
||||||
int c = ndread(&syscon);
|
|
||||||
if (c == CTL_C)
|
|
||||||
con_skip_char(&syscon);
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* OUTPUT FUNCTIONS */
|
/* OUTPUT FUNCTIONS */
|
||||||
|
|
||||||
#ifdef __WATCOMC__
|
#ifdef __WATCOMC__
|
||||||
|
@ -231,7 +215,7 @@ STATIC int cooked_write_char(struct dhdr FAR **pdev,
|
||||||
otherwise check every 32 characters */
|
otherwise check every 32 characters */
|
||||||
if (*fast_counter <= 0x80)
|
if (*fast_counter <= 0x80)
|
||||||
/* Test for hold char and ctl_c */
|
/* Test for hold char and ctl_c */
|
||||||
con_hold(pdev);
|
con_hold(pdev, -1);
|
||||||
*fast_counter += 1;
|
*fast_counter += 1;
|
||||||
*fast_counter &= 0x9f;
|
*fast_counter &= 0x9f;
|
||||||
|
|
||||||
|
@ -306,7 +290,7 @@ void write_char_stdout(int c)
|
||||||
#define iscntrl(c) ((unsigned char)(c) < ' ')
|
#define iscntrl(c) ((unsigned char)(c) < ' ')
|
||||||
|
|
||||||
/* this is for handling things like ^C, mostly used in echoed input */
|
/* this is for handling things like ^C, mostly used in echoed input */
|
||||||
int echo_char(int c, int sft_idx)
|
STATIC int echo_char(int c, int sft_idx)
|
||||||
{
|
{
|
||||||
int out = c;
|
int out = c;
|
||||||
if (iscntrl(c) && c != HT && c != LF && c != CR)
|
if (iscntrl(c) && c != HT && c != LF && c != CR)
|
||||||
|
@ -318,6 +302,16 @@ int echo_char(int c, int sft_idx)
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void echo_ctl_c(struct dhdr FAR **pdev, int sft_idx)
|
||||||
|
{
|
||||||
|
char *buf = "^C\r\n";
|
||||||
|
|
||||||
|
if (sft_idx == -1)
|
||||||
|
cooked_write(pdev, 4, buf);
|
||||||
|
else
|
||||||
|
DosRWSft(sft_idx, 4, buf, XFR_FORCE_WRITE);
|
||||||
|
}
|
||||||
|
|
||||||
STATIC void destr_bs(int sft_idx)
|
STATIC void destr_bs(int sft_idx)
|
||||||
{
|
{
|
||||||
write_char(BS, sft_idx);
|
write_char(BS, sft_idx);
|
||||||
|
@ -327,12 +321,12 @@ STATIC void destr_bs(int sft_idx)
|
||||||
|
|
||||||
/* READ FUNCTIONS */
|
/* READ FUNCTIONS */
|
||||||
|
|
||||||
STATIC int raw_get_char(struct dhdr FAR **pdev, BOOL check_break)
|
STATIC int raw_get_char(struct dhdr FAR **pdev, int sft_out, BOOL check_break)
|
||||||
{
|
{
|
||||||
Do_DosIdle_loop(pdev);
|
Do_DosIdle_loop(pdev);
|
||||||
if (check_break)
|
if (check_break)
|
||||||
{
|
{
|
||||||
con_hold(pdev);
|
con_hold(pdev, sft_out);
|
||||||
Do_DosIdle_loop(pdev);
|
Do_DosIdle_loop(pdev);
|
||||||
}
|
}
|
||||||
return CharIO(pdev, 0, C_INPUT);
|
return CharIO(pdev, 0, C_INPUT);
|
||||||
|
@ -344,7 +338,7 @@ long cooked_read(struct dhdr FAR **pdev, size_t n, char FAR *bp)
|
||||||
int c;
|
int c;
|
||||||
while(n--)
|
while(n--)
|
||||||
{
|
{
|
||||||
c = raw_get_char(pdev, TRUE);
|
c = raw_get_char(pdev, -1, TRUE);
|
||||||
if (c < 0)
|
if (c < 0)
|
||||||
return c;
|
return c;
|
||||||
if (c == 256)
|
if (c == 256)
|
||||||
|
@ -357,26 +351,26 @@ long cooked_read(struct dhdr FAR **pdev, size_t n, char FAR *bp)
|
||||||
return xfer;
|
return xfer;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char read_char(int sft_idx, BOOL check_break)
|
unsigned char read_char(int sft_in, int sft_out, BOOL check_break)
|
||||||
{
|
{
|
||||||
unsigned char c;
|
unsigned char c;
|
||||||
struct dhdr FAR *dev = sft_to_dev(idx_to_sft(sft_idx));
|
struct dhdr FAR *dev = sft_to_dev(idx_to_sft(sft_in));
|
||||||
|
|
||||||
if (dev)
|
if (dev)
|
||||||
return (unsigned char)raw_get_char(&dev, check_break);
|
return (unsigned char)raw_get_char(&dev, sft_out, check_break);
|
||||||
|
|
||||||
DosRWSft(sft_idx, 1, &c, XFR_READ);
|
DosRWSft(sft_in, 1, &c, XFR_READ);
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC unsigned char read_char_check_break(int sft_idx)
|
STATIC unsigned char read_char_check_break(int sft_in, int sft_out)
|
||||||
{
|
{
|
||||||
return read_char(sft_idx, TRUE);
|
return read_char(sft_in, sft_out, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char read_char_stdin(BOOL check_break)
|
unsigned char read_char_stdin(BOOL check_break)
|
||||||
{
|
{
|
||||||
return read_char(get_sft_idx(STDIN), check_break);
|
return read_char(get_sft_idx(STDIN), get_sft_idx(STDOUT), check_break);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* reads a line (buffered, called by int21/ah=0ah, 3fh) */
|
/* reads a line (buffered, called by int21/ah=0ah, 3fh) */
|
||||||
|
@ -399,9 +393,9 @@ void read_line(int sft_in, int sft_out, keyboard FAR * kp)
|
||||||
{
|
{
|
||||||
unsigned new_pos = stored_size;
|
unsigned new_pos = stored_size;
|
||||||
|
|
||||||
c = read_char_check_break(sft_in);
|
c = read_char_check_break(sft_in, sft_out);
|
||||||
if (c == 0)
|
if (c == 0)
|
||||||
c = (unsigned)read_char_check_break(sft_in) << 8;
|
c = (unsigned)read_char_check_break(sft_in, sft_out) << 8;
|
||||||
switch (c)
|
switch (c)
|
||||||
{
|
{
|
||||||
case LF:
|
case LF:
|
||||||
|
@ -426,11 +420,11 @@ void read_line(int sft_in, int sft_out, keyboard FAR * kp)
|
||||||
case F4:
|
case F4:
|
||||||
/* insert/delete up to character c */
|
/* insert/delete up to character c */
|
||||||
{
|
{
|
||||||
unsigned char c2 = read_char_check_break(sft_in);
|
unsigned char c2 = read_char_check_break(sft_in, sft_out);
|
||||||
new_pos = stored_pos;
|
new_pos = stored_pos;
|
||||||
if (c2 == 0)
|
if (c2 == 0)
|
||||||
{
|
{
|
||||||
read_char_check_break(sft_in);
|
read_char_check_break(sft_in, sft_out);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -408,7 +408,7 @@ dispatch:
|
||||||
|
|
||||||
/* Check for Ctrl-Break */
|
/* Check for Ctrl-Break */
|
||||||
if (break_ena || (lr.AH >= 1 && lr.AH <= 5) || (lr.AH >= 8 && lr.AH <= 0x0b))
|
if (break_ena || (lr.AH >= 1 && lr.AH <= 5) || (lr.AH >= 8 && lr.AH <= 0x0b))
|
||||||
check_handle_break();
|
check_handle_break(&syscon, -1);
|
||||||
|
|
||||||
/* The dispatch handler */
|
/* The dispatch handler */
|
||||||
switch (lr.AH)
|
switch (lr.AH)
|
||||||
|
@ -435,8 +435,11 @@ dispatch:
|
||||||
|
|
||||||
/* Auxiliary Input */
|
/* Auxiliary Input */
|
||||||
case 0x03:
|
case 0x03:
|
||||||
lr.AL = read_char(get_sft_idx(STDAUX), TRUE);
|
{
|
||||||
|
int sft_idx = get_sft_idx(STDAUX);
|
||||||
|
lr.AL = read_char(sft_idx, sft_idx, TRUE);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* Auxiliary Output */
|
/* Auxiliary Output */
|
||||||
case 0x04:
|
case 0x04:
|
||||||
|
|
|
@ -49,21 +49,18 @@ UWORD dskxfer(COUNT dsk, ULONG blkno, VOID FAR * buf, UWORD numblocks,
|
||||||
void AllocateHMASpace (size_t lowbuffer, size_t highbuffer);
|
void AllocateHMASpace (size_t lowbuffer, size_t highbuffer);
|
||||||
|
|
||||||
/* break.c */
|
/* break.c */
|
||||||
#ifdef __WATCOMC__
|
unsigned char check_handle_break(struct dhdr FAR **pdev, int sft_out);
|
||||||
#pragma aux handle_break aborts;
|
|
||||||
#endif
|
|
||||||
int check_handle_break(void);
|
|
||||||
void handle_break(struct dhdr FAR **pdev);
|
|
||||||
|
|
||||||
/* chario.c */
|
/* chario.c */
|
||||||
struct dhdr FAR *sft_to_dev(sft FAR *sft);
|
struct dhdr FAR *sft_to_dev(sft FAR *sft);
|
||||||
long BinaryCharIO(struct dhdr FAR **pdev, size_t n, void FAR * bp,
|
long BinaryCharIO(struct dhdr FAR **pdev, size_t n, void FAR * bp,
|
||||||
unsigned command);
|
unsigned command);
|
||||||
int echo_char(int c, int sft_idx);
|
int echo_char(int c, int sft_idx);
|
||||||
int con_break(void);
|
void echo_ctl_c(struct dhdr FAR **pdev, int sft_idx);
|
||||||
|
int ndread(struct dhdr FAR **pdev);
|
||||||
int StdinBusy(void);
|
int StdinBusy(void);
|
||||||
void con_flush(struct dhdr FAR **pdev);
|
void con_flush(struct dhdr FAR **pdev);
|
||||||
unsigned char read_char(int sft_idx, BOOL check_break);
|
unsigned char read_char(int sft_in, int sft_out, BOOL check_break);
|
||||||
unsigned char read_char_stdin(BOOL check_break);
|
unsigned char read_char_stdin(BOOL check_break);
|
||||||
long cooked_read(struct dhdr FAR **pdev, size_t n, char FAR *bp);
|
long cooked_read(struct dhdr FAR **pdev, size_t n, char FAR *bp);
|
||||||
void read_line(int sft_in, int sft_out, keyboard FAR * kp);
|
void read_line(int sft_in, int sft_out, keyboard FAR * kp);
|
||||||
|
|
Loading…
Reference in New Issue