Had to change ctrl-c/ctrl-break handling again...

Seems to be more consistent now. read_char_sft_dev handles ^C at a fairly
high level. So raw_get_char doesn't need to worry about sft's anymore.


git-svn-id: https://svn.code.sf.net/p/freedos/svn/kernel/trunk@885 6ac86273-5f31-0410-b378-82cca8765d1b
This commit is contained in:
Bart Oldeman 2004-04-14 15:40:51 +00:00
parent 6c4fd1228c
commit cf2ed6752b
4 changed files with 100 additions and 77 deletions

View File

@ -42,37 +42,52 @@ static BYTE *RcsId =
/* Check for ^Break/^C. /* Check for ^Break/^C.
* Three sources are available: * Three 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) syscon stream (usually CON:)
* 3) input stream (most likely STDIN) * 3) i/o stream (if unequal to syscon, e.g. AUX)
* Actions:
* 1) echo ^C
* 2) clear the STDIN stream
* 3) decrease the InDOS flag as the kernel drops back to user space
* 4) invoke INT-23 and never come back
*/ */
unsigned char check_handle_break(struct dhdr FAR **pdev, int sft_out)
unsigned char ctrl_break_pressed(void)
{
return CB_FLG & CB_MSK;
}
unsigned char check_handle_break(struct dhdr FAR **pdev)
{ {
unsigned char c = CTL_C; unsigned char c = CTL_C;
if (CB_FLG & CB_MSK) if (!ctrl_break_pressed())
CB_FLG &= ~CB_MSK; /* reset the ^Break flag */
else
c = (unsigned char)ndread(&syscon); c = (unsigned char)ndread(&syscon);
if (c == CTL_C) if (c != CTL_C && *pdev != syscon)
{
sft_out = -1;
pdev = &syscon;
}
else if (*pdev != syscon)
c = (unsigned char)ndread(pdev); c = (unsigned char)ndread(pdev);
if (c == CTL_C) if (c == CTL_C)
{ handle_break(pdev, -1);
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 */
}
return c; return c;
} }
/*
* Handles a ^Break state
*
* Actions:
* 1) clear the ^Break flag
* 2) clear the STDIN stream
* 3) echo ^C to sft_out or pdev if sft_out==-1
* 4) decrease the InDOS flag as the kernel drops back to user space
* 5) invoke INT-23 and never come back
*/
void handle_break(struct dhdr FAR **pdev, int sft_out)
{
char *buf = "^C\r\n";
CB_FLG &= ~CB_MSK; /* reset the ^Break flag */
con_flush(pdev);
if (sft_out == -1)
cooked_write(pdev, 4, buf);
else
DosRWSft(sft_out, 4, buf, XFR_FORCE_WRITE);
if (!ErrorMode) /* within int21_handler, InDOS is not incremented */
if (InDOS)
--InDOS; /* fail-safe */
spawn_int23(); /* invoke user INT-23 and never come back */
}

View File

@ -89,7 +89,7 @@ STATIC int CharIO(struct dhdr FAR **pdev, unsigned char ch, unsigned command)
/* STATE FUNCTIONS */ /* STATE FUNCTIONS */
void CharCmd(struct dhdr FAR **pdev, unsigned command) STATIC void CharCmd(struct dhdr FAR **pdev, unsigned command)
{ {
while (CharRequest(pdev, command) == 1); while (CharRequest(pdev, command) == 1);
} }
@ -126,14 +126,6 @@ int StdinBusy(void)
return s->sft_posit >= s->sft_size; return s->sft_posit >= s->sft_size;
} }
STATIC void Do_DosIdle_loop(struct dhdr FAR **pdev)
{
/* the idle int is only safe if we're using the character stack */
while (Busy(pdev) && (*pdev == syscon || Busy(&syscon)))
if (user_r->AH < 0xd)
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 */
int ndread(struct dhdr FAR **pdev) int ndread(struct dhdr FAR **pdev)
@ -144,19 +136,6 @@ int ndread(struct dhdr FAR **pdev)
return CharReqHdr.r_ndbyte; return CharReqHdr.r_ndbyte;
} }
STATIC void con_hold(struct dhdr FAR **pdev, int sft_out)
{
unsigned char c = check_handle_break(pdev, sft_out);
if (c == CTL_S)
{
CharIO(pdev, 0, C_INPUT);
Do_DosIdle_loop(pdev);
/* just wait and then skip a character */
check_handle_break(pdev, sft_out);
CharIO(pdev, 0, C_INPUT);
}
}
/* OUTPUT FUNCTIONS */ /* OUTPUT FUNCTIONS */
#ifdef __WATCOMC__ #ifdef __WATCOMC__
@ -213,9 +192,9 @@ STATIC int cooked_write_char(struct dhdr FAR **pdev,
/* if not fast then < 0x80; always check /* if not fast then < 0x80; always check
otherwise check every 32 characters */ otherwise check every 32 characters */
if (*fast_counter <= 0x80) if (*fast_counter <= 0x80 && check_handle_break(pdev) == CTL_S)
/* Test for hold char and ctl_c */ /* Test for hold char and ctl_c */
con_hold(pdev, -1); raw_get_char(pdev, TRUE);
*fast_counter += 1; *fast_counter += 1;
*fast_counter &= 0x9f; *fast_counter &= 0x9f;
@ -302,16 +281,6 @@ STATIC 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);
@ -321,15 +290,13 @@ STATIC void destr_bs(int sft_idx)
/* READ FUNCTIONS */ /* READ FUNCTIONS */
STATIC int raw_get_char(struct dhdr FAR **pdev, int sft_out, BOOL check_break) STATIC unsigned char read_char_sft_dev(int sft_in, int sft_out,
struct dhdr FAR **pdev,
BOOL check_break);
STATIC int raw_get_char(struct dhdr FAR **pdev, BOOL check_break)
{ {
Do_DosIdle_loop(pdev); return read_char_sft_dev(-1, -1, pdev, check_break);
if (check_break)
{
con_hold(pdev, sft_out);
Do_DosIdle_loop(pdev);
}
return CharIO(pdev, 0, C_INPUT);
} }
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)
@ -338,7 +305,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, -1, TRUE); c = raw_get_char(pdev, TRUE);
if (c < 0) if (c < 0)
return c; return c;
if (c == 256) if (c == 256)
@ -351,18 +318,55 @@ long cooked_read(struct dhdr FAR **pdev, size_t n, char FAR *bp)
return xfer; return xfer;
} }
unsigned char read_char(int sft_in, int sft_out, BOOL check_break) STATIC unsigned char read_char_sft_dev(int sft_in, int sft_out,
struct dhdr FAR **pdev,
BOOL check_break)
{ {
unsigned char c; unsigned char c;
struct dhdr FAR *dev = sft_to_dev(idx_to_sft(sft_in));
if (dev) if (pdev)
return (unsigned char)raw_get_char(&dev, sft_out, check_break); {
FOREVER
{
if (ctrl_break_pressed())
{
c = CTL_C;
break;
}
if (!Busy(pdev))
{
c = CharIO(pdev, 0, C_INPUT);
break;
}
if (check_break && *pdev != syscon)
check_handle_break(&syscon);
/* the idle int is only safe if we're using the character stack */
if (user_r->AH < 0xd)
DosIdle_int();
}
}
else
DosRWSft(sft_in, 1, &c, XFR_READ);
DosRWSft(sft_in, 1, &c, XFR_READ); /* check for break or stop on sft_in, echo to sft_out */
if (check_break && (c == CTL_C || c == CTL_S))
{
if (c == CTL_S)
c = read_char_sft_dev(sft_in, sft_out, pdev, FALSE);
if (c == CTL_C)
handle_break(pdev, sft_out);
/* DOS oddity: if you press ^S somekey ^C then ^C does not break */
c = read_char(sft_in, sft_out, FALSE);
}
return c; return c;
} }
unsigned char read_char(int sft_in, int sft_out, BOOL check_break)
{
struct dhdr FAR *dev = sft_to_dev(idx_to_sft(sft_in));
return read_char_sft_dev(sft_in, sft_out, &dev, check_break);
}
STATIC unsigned char read_char_check_break(int sft_in, int sft_out) STATIC unsigned char read_char_check_break(int sft_in, int sft_out)
{ {
return read_char(sft_in, sft_out, TRUE); return read_char(sft_in, sft_out, TRUE);

View File

@ -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(&syscon, -1); check_handle_break(&syscon);
/* The dispatch handler */ /* The dispatch handler */
switch (lr.AH) switch (lr.AH)

View File

@ -49,14 +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 */
unsigned char check_handle_break(struct dhdr FAR **pdev, int sft_out); unsigned char ctrl_break_pressed(void);
unsigned char check_handle_break(struct dhdr FAR **pdev);
void handle_break(struct dhdr FAR **pdev, int sft_out);
#ifdef __WATCOMC__
#pragma aux handle_break aborts;
#endif
/* 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);
void echo_ctl_c(struct dhdr FAR **pdev, int sft_idx);
int ndread(struct dhdr FAR **pdev); 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);