X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/0965bee0865fd8ea129b2de62a3c50e09c59a184..c404e5b3bdd2c7e16cdab6c3bc722425085bb83f:/terminal.c diff --git a/terminal.c b/terminal.c index 0f4504ac..70010bd4 100644 --- a/terminal.c +++ b/terminal.c @@ -55,6 +55,17 @@ static unsigned long *disptext; /* buffer of text on real screen */ static unsigned long *wanttext; /* buffer of text we want on screen */ static unsigned long *alttext; /* buffer of text on alt. screen */ +#define VBELL_TIMEOUT 100 /* millisecond duration of visual bell */ + +struct beeptime { + struct beeptime *next; + long ticks; +}; +static struct beeptime *beephead, *beeptail; +int nbeeps; +int beep_overloaded; +long lastbeep; + static unsigned char *selspace; /* buffer for building selections in */ #define TSIZE (sizeof(*text)) @@ -183,6 +194,7 @@ static void power_on(void) { alt_cset = cset = 0; cset_attr[0] = cset_attr[1] = ATTR_ASCII; rvideo = 0; + in_vbell = FALSE; cursor_on = 1; save_attr = curr_attr = ATTR_DEFAULT; term_editing = term_echoing = FALSE; @@ -255,6 +267,10 @@ void term_init(void) { deselect(); rows = cols = -1; power_on(); + beephead = beeptail = NULL; + nbeeps = 0; + lastbeep = FALSE; + beep_overloaded = FALSE; } /* @@ -773,9 +789,6 @@ static void do_osc(void) { void term_out(void) { int c, inbuf_reap; -static int beep_overload = 0; - int beep_count = 0; - for(inbuf_reap = 0; inbuf_reap < inbuf_head; inbuf_reap++) { c = inbuf[inbuf_reap]; @@ -803,13 +816,97 @@ static int beep_overload = 0; * * An xterm returns "xterm" (5 characters) */ - compatibility(OTHER); - ldisc_send ("PuTTY", 5); + compatibility(ANSIMIN); + { + char abuf[256], *s, *d; + int state=0; + for(s=cfg.answerback, d=abuf; *s; s++) { + if (state) + { + if (*s >= 'a' && *s <= 'z') + *d++ = (*s - ('a'-1)); + else if ((*s >='@' && *s<='_') || + *s == '?' || (*s&0x80)) + *d++ = ('@'^*s); + else if (*s == '~') + *d++ = '^'; + state = 0; + } + else if (*s == '^') { + state = 1; + } + else + *d++ = xlat_kbd2tty((unsigned char)*s); + } + ldisc_send (abuf, d-abuf); + } break; case '\007': - beep_count++; - if(beep_count>6) beep_overload=1; - disptop = scrtop; + { + struct beeptime *newbeep; + long ticks; + + ticks = GetTickCount(); + + if (!beep_overloaded) { + newbeep = smalloc(sizeof(struct beeptime)); + newbeep->ticks = ticks; + newbeep->next = NULL; + if (!beephead) + beephead = newbeep; + else + beeptail->next = newbeep; + beeptail = newbeep; + nbeeps++; + } + + /* + * Throw out any beeps that happened more than + * t seconds ago. + */ + while (beephead && + beephead->ticks < ticks - cfg.bellovl_t*1000) { + struct beeptime *tmp = beephead; + beephead = tmp->next; + sfree(tmp); + if (!beephead) + beeptail = NULL; + nbeeps--; + } + + if (cfg.bellovl && beep_overloaded && + ticks-lastbeep >= cfg.bellovl_s * 1000) { + /* + * If we're currently overloaded and the + * last beep was more than s seconds ago, + * leave overload mode. + */ + beep_overloaded = FALSE; + } else if (cfg.bellovl && !beep_overloaded && + nbeeps >= cfg.bellovl_n) { + /* + * Now, if we have n or more beeps + * remaining in the queue, go into overload + * mode. + */ + beep_overloaded = TRUE; + } + lastbeep = ticks; + + /* + * Perform an actual beep if we're not overloaded. + */ + if ((!cfg.bellovl || !beep_overloaded) && cfg.beep != 0) { + if (cfg.beep != 2) + beep(cfg.beep); + else if(cfg.beep == 2) { + in_vbell = TRUE; + vbell_timeout = ticks + VBELL_TIMEOUT; + term_update(); + } + } + disptop = scrtop; + } break; case '\b': if (curs_x == 0 && curs_y == 0) @@ -1731,13 +1828,6 @@ static int beep_overload = 0; check_selection (cpos, cpos+1); } inbuf_head = 0; - - if (beep_overload) - { - if(!beep_count) beep_overload=0; - } - else if(beep_count && beep_count<5 && cfg.beep) - beep(beep_count/3); } /* @@ -1761,7 +1851,23 @@ static void do_paint (Context ctx, int may_optimise){ int i, j, start, our_curs_y; unsigned long attr, rv, cursor; char ch[1024]; + long ticks; + /* + * Check the visual bell state. + */ + if (in_vbell) { + ticks = GetTickCount(); + if (ticks - vbell_timeout >= 0) + in_vbell = FALSE; + } + + /* Depends on: + * screen array, disptop, scrtop, + * selection, rv, + * cfg.blinkpc, blink_is_real, tblinker, + * curs_y, curs_x, blinker, cfg.blink_cur, cursor_on, has_focus + */ if (cursor_on) { if (has_focus) { if (blinker || !cfg.blink_cur) @@ -1774,8 +1880,9 @@ static void do_paint (Context ctx, int may_optimise){ if (wrapnext) cursor |= ATTR_RIGHTCURS; } - else cursor = 0; - rv = (rvideo ? ATTR_REVERSE : 0); + else + cursor = 0; + rv = (!rvideo ^ !in_vbell ? ATTR_REVERSE : 0); our_curs_y = curs_y + (scrtop - disptop) / (cols+1); for (i=0; i=0 && blink_diff<450) + /* Make sure the cursor blinks no faster than GetCaretBlinkTime() */ + if (blink_diff>=0 && blink_diff<(long)GetCaretBlinkTime()) return; last_blink = now; @@ -1948,34 +2055,34 @@ static void clipme(unsigned long *top, unsigned long *bottom, char *workbuf) { } while (top < nlpos && top < bottom) { -#if 0 - /* VT Specials -> ISO8859-1 */ - static const char poorman2[] = + int ch = (*top & CHAR_MASK); + int set = (*top & CSET_MASK); + + /* VT Specials -> ISO8859-1 for Cut&Paste */ + static const unsigned char poorman2[] = "* # HTFFCRLF\xB0 \xB1 NLVT+ + + + + - - - - - + + + + | <=>=PI!=\xA3 \xB7 "; -#endif - int ch = (*top & CHAR_MASK); + if (set && !cfg.rawcnp) { + if (set == ATTR_LINEDRW && ch >= 0x60 && ch < 0x7F) { + int x; + if ((x = poorman2[2*(ch-0x60)+1]) == ' ') + x = 0; + ch = (x<<8) + poorman2[2*(ch-0x60)]; + } + } -#if 0 - if ((*top & ATTR_LINEDRW) && ch >= 0x60 && ch < 0x7F) { - int x; - *wbptr++ = poorman2[2*(ch-0x60)]; - if ( (x = poorman2[2*(ch-0x60)+1]) != ' ') - *wbptr++ = x; - } else -#endif -#if 0 - if ((*top & ATTR_GBCHR) && ch == '#') - *wbptr++ = (unsigned char) 0xA3; - else -#endif - if ( wblen == buflen ) - { - workbuf = srealloc(workbuf, buflen += 100); - wbptr = workbuf + wblen; + while(ch != 0) { + if (cfg.rawcnp || !!(ch&0xE0)) { + if ( wblen == buflen ) + { + workbuf = srealloc(workbuf, buflen += 100); + wbptr = workbuf + wblen; + } + wblen++; + *wbptr++ = (unsigned char) ch; + } + ch>>=8; } - wblen++; - *wbptr++ = (unsigned char) ch; top++; } if (nl) {