--- erts/emulator/drivers/unix/ttsl_drv.c.orig 2007-12-18 04:57:58.000000000 -0700 +++ erts/emulator/drivers/unix/ttsl_drv.c 2007-12-31 12:13:30.000000000 -0700 @@ -58,6 +58,7 @@ static char *capbuf; static char *up, *down, *left, *right; static int cols, xn; +static int cols_needs_update = FALSE; /* The various opcodes. */ #define OP_PUTC 0 @@ -114,6 +115,7 @@ static int move_right(int); static int move_up(int); static int move_down(int); +static void update_cols(void); /* Terminal setting functions. */ static int tty_init(int,int,int,int); @@ -122,6 +124,7 @@ static int ttysl_control(ErlDrvData, unsigned int, char *, int, char **, int); static RETSIGTYPE suspend(int); static RETSIGTYPE cont(int); +static RETSIGTYPE winch(int); /* Define the driver table entry. */ struct erl_drv_entry ttsl_driver_entry = { @@ -200,6 +203,7 @@ setlocale(LC_CTYPE, ""); /* Set international environment */ sys_sigset(SIGCONT, cont); + sys_sigset(SIGWINCH, winch); driver_select(port, (ErlDrvEvent)(Uint)ttysl_fd, DO_READ, 1); ttysl_port = port; @@ -262,6 +266,7 @@ close(ttysl_fd); driver_select(ttysl_port, (ErlDrvEvent)(Uint)ttysl_fd, DO_READ, 0); sys_sigset(SIGCONT, SIG_DFL); + sys_sigset(SIGWINCH, SIG_DFL); } ttysl_port = (ErlDrvPort)-1; ttysl_fd = -1; @@ -432,6 +437,8 @@ int i, l, r; byte *c; + update_cols(); + /* Step forward or backwards over n logical characters. */ c = step_over_chars(n); @@ -553,6 +560,8 @@ */ static int write_buf(byte *s, int n) { + update_cols(); + while (n > 0) { if (isprint(*s)) { outc(*s); @@ -598,6 +607,8 @@ { int dc, dl; + update_cols(); + dc = COL(to) - COL(from); dl = LINE(to) - LINE(from); if (dl > 0) @@ -704,6 +715,27 @@ tputs(down, 1, outc); return TRUE; } + +/* + * Updates cols if terminal has resized (SIGWINCH). Should be called + * at the start of any function that uses the COL or LINE macros. If + * the terminal is resized after calling this function but before use + * of the macros, then we may write to the wrong screen location. + * + * We cannot call this from the SIGWINCH handler because it uses + * ioctl() which is not a safe function as listed in the signal(7) + * man page. + */ +static void update_cols(void) +{ + Uint32 width, height; + + if (cols_needs_update) { + cols_needs_update = FALSE; + ttysl_get_window_size(&width, &height); + cols = width; + } +} /* @@ -830,3 +862,7 @@ } } +static RETSIGTYPE winch(int sig) +{ + cols_needs_update = TRUE; +}