From 156686ef42c3f6940045f33fc350b806bcbc7f52 Mon Sep 17 00:00:00 2001 From: simon Date: Fri, 13 Apr 2001 10:52:36 +0000 Subject: [PATCH] New improved bell handling. Choice between visual and audible bell; configurable bell overload handling. Thanks to Robert de Bath for galvanising me into doing this, but I've had to rip most of his code out and redo it myself... git-svn-id: svn://svn.tartarus.org/sgt/putty@1039 cda61777-01e9-0310-a592-d414129be87e --- putty.h | 9 ++++- settings.c | 8 ++++ terminal.c | 121 +++++++++++++++++++++++++++++++++++++++++++++++++++++-------- windlg.c | 92 ++++++++++++++++++++++++++++++++++++++++++---- window.c | 27 ++++---------- 5 files changed, 215 insertions(+), 42 deletions(-) diff --git a/putty.h b/putty.h index 061074b4..b5606880 100644 --- a/putty.h +++ b/putty.h @@ -72,6 +72,9 @@ GLOBAL int outbuf_head, outbuf_reap; GLOBAL int has_focus; +GLOBAL int in_vbell; +GLOBAL long vbell_timeout; + GLOBAL int app_cursor_keys, app_keypad_keys, vt52_mode; GLOBAL int repeat_off, cr_lf_return; @@ -214,7 +217,11 @@ typedef struct { int lfhascr; int cursor_type; /* 0=block 1=underline 2=vertical */ int blink_cur; - int beep; + int beep; /* 0=none 1=defaultsound 2=visual */ + int bellovl; /* bell overload protection active? */ + int bellovl_n; /* number of bells to cause overload */ + int bellovl_t; /* time interval for overload (seconds) */ + int bellovl_s; /* period of silence to re-enable bell (s) */ int scrollbar; int locksize; int bce; diff --git a/settings.c b/settings.c index 559d4813..e1bfbc3a 100644 --- a/settings.c +++ b/settings.c @@ -104,6 +104,10 @@ void save_settings (char *section, int do_host, Config *cfg) { write_setting_i (sesskey, "CurType", cfg->cursor_type); write_setting_i (sesskey, "BlinkCur", cfg->blink_cur); write_setting_i (sesskey, "Beep", cfg->beep); + write_setting_i (sesskey, "BellOverload", cfg->bellovl); + write_setting_i (sesskey, "BellOverloadN", cfg->bellovl_n); + write_setting_i (sesskey, "BellOverloadT", cfg->bellovl_t); + write_setting_i (sesskey, "BellOverloadS", cfg->bellovl_s); write_setting_i (sesskey, "ScrollbackLines", cfg->savelines); write_setting_i (sesskey, "DECOriginMode", cfg->dec_om); write_setting_i (sesskey, "AutoWrapMode", cfg->wrap_mode); @@ -256,6 +260,10 @@ void load_settings (char *section, int do_host, Config *cfg) { gppi (sesskey, "CurType", 0, &cfg->cursor_type); gppi (sesskey, "BlinkCur", 0, &cfg->blink_cur); gppi (sesskey, "Beep", 1, &cfg->beep); + gppi (sesskey, "BellOverload", 1, &cfg->bellovl); + gppi (sesskey, "BellOverloadN", 5, &cfg->bellovl_n); + gppi (sesskey, "BellOverloadT", 2, &cfg->bellovl_t); + gppi (sesskey, "BellOverloadS", 5, &cfg->bellovl_s); gppi (sesskey, "ScrollbackLines", 200, &cfg->savelines); gppi (sesskey, "DECOriginMode", 0, &cfg->dec_om); gppi (sesskey, "AutoWrapMode", 1, &cfg->wrap_mode); diff --git a/terminal.c b/terminal.c index 9ef0c5cf..e6c15048 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]; @@ -829,9 +842,77 @@ static int beep_overload = 0; } break; case '\007': - beep_count++; - if(beep_count>6) beep_overload=1; - disptop = scrtop; + { + struct beeptime *newbeep; + long ticks; + + ticks = GetTickCount(); +debug(("beep received at %ld, last was %ld, nbeeps=%d\n", ticks, lastbeep, nbeeps)); + + 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; +debug(("throwing out beep received at %ld\n", tmp->ticks)); + 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. + */ +debug(("silence reigns, leaving overload mode\n")); + 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. + */ +debug(("%d beeps between times %ld and %ld, overload!\n", + nbeeps, beephead->ticks, ticks)); + beep_overloaded = TRUE; + } + lastbeep = ticks; + + /* + * Perform an actual beep if we're not overloaded. + */ + if ((!cfg.bellovl || !beep_overloaded) && cfg.beep != 0) { +debug(("not overloaded; performing a beep\n")); + 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) @@ -1753,13 +1834,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); } /* @@ -1783,7 +1857,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) @@ -1796,8 +1886,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 && beep_diff<50) - return; - - if(errorbeep) - MessageBeep(MB_ICONHAND); - else - MessageBeep(MB_OK); - - last_beep = GetTickCount(); +void beep(int mode) { + if (mode == 1) + MessageBeep(MB_OK); } -- 2.11.0