From fad63735be828f27b77e74782ecae92d04685b54 Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Tue, 29 Dec 2009 19:07:19 +0100 Subject: [PATCH] text input: fix problem with autoindenting and ^^D The following sequence would lead to an abort: :se ai^Mi^I^M^^Da^D The problem appears to be that the carat state is overloaded to track both the current state and something that happened before ("C_NOCHANGE"). Keep track of "nochange" in a separate variable. Problem reported and analyzed by Peter Bex --- common/common.h | 2 +- ex/ex_txt.c | 9 ++++++--- vi/v_txt.c | 8 ++++++-- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/common/common.h b/common/common.h index 624a53f9..45ac7686 100644 --- a/common/common.h +++ b/common/common.h @@ -57,7 +57,7 @@ typedef struct _text TEXT; typedef struct _win WIN; /* Autoindent state. */ -typedef enum { C_NOTSET, C_CARATSET, C_NOCHANGE, C_ZEROSET } carat_t; +typedef enum { C_NOTSET, C_CARATSET, C_ZEROSET } carat_t; /* Busy message types. */ typedef enum { BUSY_ON = 1, BUSY_OFF, BUSY_UPDATE } busy_t; diff --git a/ex/ex_txt.c b/ex/ex_txt.c index 410d984f..f551ee54 100644 --- a/ex/ex_txt.c +++ b/ex/ex_txt.c @@ -62,6 +62,7 @@ ex_txt(SCR *sp, TEXTH *tiqh, ARG_CHAR_T prompt, u_int32_t flags) carat_t carat_st; size_t cnt; int rval; + int nochange; rval = 0; @@ -110,7 +111,7 @@ newtp: if ((tp = text_init(sp, NULL, 0, 32)) == NULL) txt_prompt(sp, tp, prompt, flags); } - for (carat_st = C_NOTSET;;) { + for (carat_st = C_NOTSET, nochange = 0;;) { if (v_event_get(sp, &ev, 0, 0)) goto err; @@ -206,7 +207,8 @@ notlast: CIRCLEQ_REMOVE(tiqh, tp, q); * erased. */ if (LF_ISSET(TXT_AUTOINDENT)) { - if (carat_st == C_NOCHANGE) { + if (nochange) { + nochange = 0; if (v_txt_auto(sp, OOBLNO, &ait, ait.ai, ntp)) goto err; @@ -293,7 +295,8 @@ notlast: CIRCLEQ_REMOVE(tiqh, tp, q); MEMCPYW(ait.lb, tp->lb, tp->ai); ait.ai = ait.len = tp->ai; - carat_st = C_NOCHANGE; + carat_st = C_NOTSET; + nochange = 1; goto leftmargin; case C_ZEROSET: /* 0^D */ if (tp->len > tp->ai + 1) diff --git a/vi/v_txt.c b/vi/v_txt.c index 76b56b81..65e33e1b 100644 --- a/vi/v_txt.c +++ b/vi/v_txt.c @@ -275,6 +275,7 @@ v_txt(SCR *sp, VICMD *vp, MARK *tm, const CHAR_T *lp, size_t len, ARG_CHAR_T pro int showmatch; /* Showmatch set on this character. */ int wm_set, wm_skip; /* Wrapmargin happened, blank skip flags. */ int max, tmp; + int nochange; CHAR_T *p; gp = sp->gp; @@ -458,6 +459,7 @@ newtp: if ((tp = text_init(sp, lp, len, len + 32)) == NULL) /* Other text input mode setup. */ quote = Q_NOTSET; carat = C_NOTSET; + nochange = 0; FL_INIT(is_flags, LF_ISSET(TXT_SEARCHINCR) ? IS_RESTART | IS_RUNNING : 0); filec_redraw = hexcnt = showmatch = 0; @@ -785,7 +787,8 @@ k_cr: if (LF_ISSET(TXT_CR)) { * characters may have been erased. */ if (LF_ISSET(TXT_AUTOINDENT)) { - if (carat == C_NOCHANGE) { + if (nochange) { + nochange = 0; if (v_txt_auto(sp, OOBLNO, &ait, ait.ai, ntp)) goto err; FREE_SPACEW(sp, ait.lb, ait.lb_len); @@ -958,7 +961,8 @@ k_escape: LINE_RESOLVE; MEMMOVEW(ait.lb, tp->lb, tp->ai); ait.ai = ait.len = tp->ai; - carat = C_NOCHANGE; + carat = C_NOTSET; + nochange = 1; goto leftmargin; case C_ZEROSET: /* 0^D */ if (tp->ai == 0 || tp->cno > tp->ai + tp->offset + 1) -- 2.11.4.GIT