vi: reject change command when motion fails
If the motion command used to define the range of a change, yank or delete fails the whole command should be rejected. BusyBox vi already handled failed searches in these circumstances. Add some more cases: - non-existent mark: d'x - movement beyond end of file: c99999+ or 99999<< This is implemented using a global variable which is set when a command error is detected. Unlike the case of motion within a line it's insufficient to check that the motion command doesn't move the cursor: this fails to process 'LyL' correctly, for example, as the second 'L' doesn't move the cursor. function old new delta indicate_error 75 82 +7 find_range 686 692 +6 do_cmd 4851 4852 +1 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 3/0 up/down: 14/0) Total: 14 bytes Signed-off-by: Ron Yorston <rmy@pobox.com> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
		
				
					committed by
					
						
						Denys Vlasenko
					
				
			
			
				
	
			
			
			
						parent
						
							ac04eb3657
						
					
				
				
					commit
					038d400709
				
			
							
								
								
									
										13
									
								
								editors/vi.c
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								editors/vi.c
									
									
									
									
									
								
							@@ -378,6 +378,7 @@ struct globals {
 | 
			
		||||
#if ENABLE_FEATURE_VI_SETOPTS
 | 
			
		||||
	int indentcol;		// column of recently autoindent, 0 or -1
 | 
			
		||||
#endif
 | 
			
		||||
	smallint cmd_error;
 | 
			
		||||
 | 
			
		||||
	// former statics
 | 
			
		||||
#if ENABLE_FEATURE_VI_YANKMARK
 | 
			
		||||
@@ -502,6 +503,7 @@ struct globals {
 | 
			
		||||
#define dotcnt                  (G.dotcnt             )
 | 
			
		||||
#define last_search_pattern     (G.last_search_pattern)
 | 
			
		||||
#define indentcol               (G.indentcol          )
 | 
			
		||||
#define cmd_error               (G.cmd_error          )
 | 
			
		||||
 | 
			
		||||
#define edit_file__cur_line     (G.edit_file__cur_line)
 | 
			
		||||
#define refresh__old_offset     (G.refresh__old_offset)
 | 
			
		||||
@@ -1099,6 +1101,7 @@ static void indicate_error(void)
 | 
			
		||||
	if (crashme > 0)
 | 
			
		||||
		return;
 | 
			
		||||
#endif
 | 
			
		||||
	cmd_error = TRUE;
 | 
			
		||||
	if (!err_method) {
 | 
			
		||||
		write1(ESC_BELL);
 | 
			
		||||
	} else {
 | 
			
		||||
@@ -3399,8 +3402,11 @@ static int find_range(char **start, char **stop, int cmd)
 | 
			
		||||
#endif
 | 
			
		||||
		// these cmds operate on whole lines
 | 
			
		||||
		buftype = WHOLE;
 | 
			
		||||
		if (--cmdcnt > 0)
 | 
			
		||||
		if (--cmdcnt > 0) {
 | 
			
		||||
			do_cmd('j');
 | 
			
		||||
			if (cmd_error)
 | 
			
		||||
				buftype = -1;
 | 
			
		||||
		}
 | 
			
		||||
	} else if (strchr("^%$0bBeEfFtThnN/?|{}\b\177", c)) {
 | 
			
		||||
		// Most operate on char positions within a line.  Of those that
 | 
			
		||||
		// don't '%' needs no special treatment, search commands are
 | 
			
		||||
@@ -3430,6 +3436,8 @@ static int find_range(char **start, char **stop, int cmd)
 | 
			
		||||
		// these operate on whole lines
 | 
			
		||||
		buftype = WHOLE;
 | 
			
		||||
		do_cmd(c);		// execute movement cmd
 | 
			
		||||
		if (cmd_error)
 | 
			
		||||
			buftype = -1;
 | 
			
		||||
	} else if (c == ' ' || c == 'l') {
 | 
			
		||||
		// forward motion by character
 | 
			
		||||
		int tmpcnt = (cmdcnt ?: 1);
 | 
			
		||||
@@ -3515,6 +3523,7 @@ static void do_cmd(int c)
 | 
			
		||||
//	p = q = save_dot = buf; // quiet the compiler
 | 
			
		||||
	memset(buf, '\0', sizeof(buf));
 | 
			
		||||
	keep_index = FALSE;
 | 
			
		||||
	cmd_error = FALSE;
 | 
			
		||||
 | 
			
		||||
	show_status_line();
 | 
			
		||||
 | 
			
		||||
@@ -3699,6 +3708,8 @@ static void do_cmd(int c)
 | 
			
		||||
				dot = q;
 | 
			
		||||
				dot_begin();	// go to B-o-l
 | 
			
		||||
				dot_skip_over_ws();
 | 
			
		||||
			} else {
 | 
			
		||||
				indicate_error();
 | 
			
		||||
			}
 | 
			
		||||
		} else if (c1 == '\'') {	// goto previous context
 | 
			
		||||
			dot = swap_context(dot);	// swap current and previous context
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user