xref: /titanic_53/usr/src/cmd/vi/port/ex_voper.c (revision 6a634c9dca3093f3922e4b7ab826d7bdf17bf78e)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5d67944fbSScott Rotondo  * Common Development and Distribution License (the "License").
6d67944fbSScott Rotondo  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
21*23a1cceaSRoger A. Faulkner 
22f6db9f27Scf46844 /*
23*23a1cceaSRoger A. Faulkner  * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
24f6db9f27Scf46844  */
25f6db9f27Scf46844 
267c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
277c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate /*
317c478bd9Sstevel@tonic-gate  * Copyright (c) 1981 Regents of the University of California
327c478bd9Sstevel@tonic-gate  */
337c478bd9Sstevel@tonic-gate 
347c478bd9Sstevel@tonic-gate #include "ex.h"
357c478bd9Sstevel@tonic-gate #include "ex_tty.h"
367c478bd9Sstevel@tonic-gate #include "ex_vis.h"
377c478bd9Sstevel@tonic-gate #include <regexpr.h>
387c478bd9Sstevel@tonic-gate #ifndef PRESUNEUC
397c478bd9Sstevel@tonic-gate #include <wctype.h>
407c478bd9Sstevel@tonic-gate /* Undef putchar/getchar if they're defined. */
417c478bd9Sstevel@tonic-gate #ifdef putchar
427c478bd9Sstevel@tonic-gate #undef putchar
437c478bd9Sstevel@tonic-gate #endif
447c478bd9Sstevel@tonic-gate #ifdef getchar
457c478bd9Sstevel@tonic-gate #undef getchar
467c478bd9Sstevel@tonic-gate #endif
477c478bd9Sstevel@tonic-gate #endif /* PRESUNEUC */
487c478bd9Sstevel@tonic-gate 
497c478bd9Sstevel@tonic-gate #ifdef PRESUNEUC
507c478bd9Sstevel@tonic-gate #define	blank()		isspace(wcursor[0])
517c478bd9Sstevel@tonic-gate #endif /* PRESUNEUC */
527c478bd9Sstevel@tonic-gate #define	forbid(a)	if (a) goto errlab;
537c478bd9Sstevel@tonic-gate 
547c478bd9Sstevel@tonic-gate unsigned char	vscandir[2] =	{ '/', 0 };
557c478bd9Sstevel@tonic-gate 
56d67944fbSScott Rotondo static int get_addr();
57d67944fbSScott Rotondo 
587c478bd9Sstevel@tonic-gate /*
597c478bd9Sstevel@tonic-gate  * Decode an operator/operand type command.
607c478bd9Sstevel@tonic-gate  * Eventually we switch to an operator subroutine in ex_vops.c.
617c478bd9Sstevel@tonic-gate  * The work here is setting up a function variable to point
627c478bd9Sstevel@tonic-gate  * to the routine we want, and manipulation of the variables
637c478bd9Sstevel@tonic-gate  * wcursor and wdot, which mark the other end of the affected
647c478bd9Sstevel@tonic-gate  * area.  If wdot is zero, then the current line is the other end,
657c478bd9Sstevel@tonic-gate  * and if wcursor is zero, then the first non-blank location of the
667c478bd9Sstevel@tonic-gate  * other line is implied.
677c478bd9Sstevel@tonic-gate  */
68f6db9f27Scf46844 void
operate(int c,int cnt)69f6db9f27Scf46844 operate(int c, int cnt)
707c478bd9Sstevel@tonic-gate {
71f6db9f27Scf46844 	wchar_t i;
727c478bd9Sstevel@tonic-gate 	int (*moveop)(), (*deleteop)();
73f6db9f27Scf46844 	int (*opf)();
747c478bd9Sstevel@tonic-gate 	bool subop = 0;
757c478bd9Sstevel@tonic-gate 	unsigned char *oglobp, *ocurs;
76f6db9f27Scf46844 	line *addr;
777c478bd9Sstevel@tonic-gate 	line *odot;
787c478bd9Sstevel@tonic-gate 	int oc;
797c478bd9Sstevel@tonic-gate 	static unsigned char lastFKND;
807c478bd9Sstevel@tonic-gate 	static wchar_t lastFCHR;
817c478bd9Sstevel@tonic-gate 	short d;
827c478bd9Sstevel@tonic-gate /* #ifdef PTR_ADDRESSES */
837c478bd9Sstevel@tonic-gate 	int mouse_x;
847c478bd9Sstevel@tonic-gate 	int mouse_y;
857c478bd9Sstevel@tonic-gate 	int oline;
867c478bd9Sstevel@tonic-gate /* #endif PTR_ADDRESSES */
877c478bd9Sstevel@tonic-gate 
88f6db9f27Scf46844 	moveop = vmove, deleteop = (int (*)())vdelete;
897c478bd9Sstevel@tonic-gate 	wcursor = cursor;
907c478bd9Sstevel@tonic-gate 	wdot = NOLINE;
917c478bd9Sstevel@tonic-gate 	notecnt = 0;
927c478bd9Sstevel@tonic-gate 	dir = 1;
937c478bd9Sstevel@tonic-gate 	switch (c) {
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate 	/*
967c478bd9Sstevel@tonic-gate 	 * d		delete operator.
977c478bd9Sstevel@tonic-gate 	 */
987c478bd9Sstevel@tonic-gate 	case 'd':
99f6db9f27Scf46844 		moveop = (int (*)())vdelete;
1007c478bd9Sstevel@tonic-gate 		deleteop = beep;
1017c478bd9Sstevel@tonic-gate 		break;
1027c478bd9Sstevel@tonic-gate 
1037c478bd9Sstevel@tonic-gate 	/*
1047c478bd9Sstevel@tonic-gate 	 * s		substitute characters, like c\040, i.e. change space.
1057c478bd9Sstevel@tonic-gate 	 */
1067c478bd9Sstevel@tonic-gate 	case 's':
1077c478bd9Sstevel@tonic-gate 		ungetkey(' ');
1087c478bd9Sstevel@tonic-gate 		subop++;
1097c478bd9Sstevel@tonic-gate 		/* fall into ... */
1107c478bd9Sstevel@tonic-gate 
1117c478bd9Sstevel@tonic-gate 	/*
1127c478bd9Sstevel@tonic-gate 	 * c		Change operator.
1137c478bd9Sstevel@tonic-gate 	 */
1147c478bd9Sstevel@tonic-gate 	case 'c':
1157c478bd9Sstevel@tonic-gate 		if (c == 'c' && workcmd[0] == 'C' || workcmd[0] == 'S')
1167c478bd9Sstevel@tonic-gate 			subop++;
117f6db9f27Scf46844 		moveop = (int (*)())vchange;
1187c478bd9Sstevel@tonic-gate 		deleteop = beep;
1197c478bd9Sstevel@tonic-gate 		break;
1207c478bd9Sstevel@tonic-gate 
1217c478bd9Sstevel@tonic-gate 	/*
1227c478bd9Sstevel@tonic-gate 	 * !		Filter through a UNIX command.
1237c478bd9Sstevel@tonic-gate 	 */
1247c478bd9Sstevel@tonic-gate 	case '!':
1257c478bd9Sstevel@tonic-gate 		moveop = vfilter;
1267c478bd9Sstevel@tonic-gate 		deleteop = beep;
1277c478bd9Sstevel@tonic-gate 		break;
1287c478bd9Sstevel@tonic-gate 
1297c478bd9Sstevel@tonic-gate 	/*
1307c478bd9Sstevel@tonic-gate 	 * y		Yank operator.  Place specified text so that it
1317c478bd9Sstevel@tonic-gate 	 *		can be put back with p/P.  Also yanks to named buffers.
1327c478bd9Sstevel@tonic-gate 	 */
1337c478bd9Sstevel@tonic-gate 	case 'y':
1347c478bd9Sstevel@tonic-gate 		moveop = vyankit;
1357c478bd9Sstevel@tonic-gate 		deleteop = beep;
1367c478bd9Sstevel@tonic-gate 		break;
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate 	/*
1397c478bd9Sstevel@tonic-gate 	 * =		Reformat operator (for LISP).
1407c478bd9Sstevel@tonic-gate 	 */
1417c478bd9Sstevel@tonic-gate 	case '=':
1427c478bd9Sstevel@tonic-gate 		forbid(!value(vi_LISP));
1437c478bd9Sstevel@tonic-gate 		/* fall into ... */
1447c478bd9Sstevel@tonic-gate 
1457c478bd9Sstevel@tonic-gate 	/*
1467c478bd9Sstevel@tonic-gate 	 * >		Right shift operator.
1477c478bd9Sstevel@tonic-gate 	 * <		Left shift operator.
1487c478bd9Sstevel@tonic-gate 	 */
1497c478bd9Sstevel@tonic-gate 	case '<':
1507c478bd9Sstevel@tonic-gate 	case '>':
1517c478bd9Sstevel@tonic-gate 		moveop = vshftop;
1527c478bd9Sstevel@tonic-gate 		deleteop = beep;
1537c478bd9Sstevel@tonic-gate 		break;
1547c478bd9Sstevel@tonic-gate 
1557c478bd9Sstevel@tonic-gate 	/*
1567c478bd9Sstevel@tonic-gate 	 * r		Replace character under cursor with single following
1577c478bd9Sstevel@tonic-gate 	 *		character.
1587c478bd9Sstevel@tonic-gate 	 */
1597c478bd9Sstevel@tonic-gate 	case 'r':
1607c478bd9Sstevel@tonic-gate 		vmacchng(1);
1617c478bd9Sstevel@tonic-gate 		vrep(cnt);
1627c478bd9Sstevel@tonic-gate 		return;
1637c478bd9Sstevel@tonic-gate 
1647c478bd9Sstevel@tonic-gate 	default:
1657c478bd9Sstevel@tonic-gate 		goto nocount;
1667c478bd9Sstevel@tonic-gate 	}
1677c478bd9Sstevel@tonic-gate 	vmacchng(1);
1687c478bd9Sstevel@tonic-gate 	/*
1697c478bd9Sstevel@tonic-gate 	 * Had an operator, so accept another count.
1707c478bd9Sstevel@tonic-gate 	 * Multiply counts together.
1717c478bd9Sstevel@tonic-gate 	 */
1727c478bd9Sstevel@tonic-gate 	if (isdigit(peekkey()) && peekkey() != '0') {
1737c478bd9Sstevel@tonic-gate 		cnt *= vgetcnt();
1747c478bd9Sstevel@tonic-gate 		Xcnt = cnt;
1757c478bd9Sstevel@tonic-gate 		forbid(cnt <= 0);
1767c478bd9Sstevel@tonic-gate 	}
1777c478bd9Sstevel@tonic-gate 
1787c478bd9Sstevel@tonic-gate 	/*
1797c478bd9Sstevel@tonic-gate 	 * Get next character, mapping it and saving as
1807c478bd9Sstevel@tonic-gate 	 * part of command for repeat.
1817c478bd9Sstevel@tonic-gate 	 */
1827c478bd9Sstevel@tonic-gate 	c = map(getesc(), arrows, 0);
1837c478bd9Sstevel@tonic-gate 	if (c == 0)
1847c478bd9Sstevel@tonic-gate 		return;
1857c478bd9Sstevel@tonic-gate 	if (!subop)
1867c478bd9Sstevel@tonic-gate 		*lastcp++ = c;
1877c478bd9Sstevel@tonic-gate nocount:
1887c478bd9Sstevel@tonic-gate 	opf = moveop;
1897c478bd9Sstevel@tonic-gate 	switch (c) {
1907c478bd9Sstevel@tonic-gate 
1917c478bd9Sstevel@tonic-gate /* #ifdef PTR_ADDRESSES */
1927c478bd9Sstevel@tonic-gate 	/*
1937c478bd9Sstevel@tonic-gate 	 * ^X^_		Netty Mouse positioning hack
1947c478bd9Sstevel@tonic-gate 	 * ^X^]
1957c478bd9Sstevel@tonic-gate 	 */
1967c478bd9Sstevel@tonic-gate 	case CTRL('X'):
1977c478bd9Sstevel@tonic-gate /*
1987c478bd9Sstevel@tonic-gate  *	Read in mouse stuff
1997c478bd9Sstevel@tonic-gate  */
2007c478bd9Sstevel@tonic-gate 		c = getkey();			/* ^_ or ^] */
2017c478bd9Sstevel@tonic-gate 		if ((c != CTRL('_')) && (c != (CTRL(']'))))
2027c478bd9Sstevel@tonic-gate 			break;
2037c478bd9Sstevel@tonic-gate 		getkey();			/* mouse button */
2047c478bd9Sstevel@tonic-gate 		mouse_x = get_addr() + 1;
2057c478bd9Sstevel@tonic-gate 		mouse_y = get_addr() + 1;
2067c478bd9Sstevel@tonic-gate 		if (mouse_y < WTOP)
2077c478bd9Sstevel@tonic-gate 			break;
2087c478bd9Sstevel@tonic-gate 		if (Pline == numbline)
2097c478bd9Sstevel@tonic-gate 			mouse_x -= 8;
2107c478bd9Sstevel@tonic-gate 		if (mouse_x < 0)
2117c478bd9Sstevel@tonic-gate 			mouse_x = 0;
2127c478bd9Sstevel@tonic-gate 		if (mouse_x > WCOLS)
2137c478bd9Sstevel@tonic-gate 			break;
2147c478bd9Sstevel@tonic-gate /*
2157c478bd9Sstevel@tonic-gate  *	Find the line on the screen
2167c478bd9Sstevel@tonic-gate  */
217dd3f38fbScf46844 		for (i = 0; i <= WECHO; i++) {
2187c478bd9Sstevel@tonic-gate 			if (vlinfo[i].vliny >= mouse_y)
2197c478bd9Sstevel@tonic-gate 				break;
2207c478bd9Sstevel@tonic-gate 		}
2217c478bd9Sstevel@tonic-gate 		if (i > WECHO)
2227c478bd9Sstevel@tonic-gate 			break;
2237c478bd9Sstevel@tonic-gate /*
2247c478bd9Sstevel@tonic-gate  *	Look for lines longer than one line - note  odd case at zero
2257c478bd9Sstevel@tonic-gate  */
226dd3f38fbScf46844 		if (i) {
227dd3f38fbScf46844 			if (vlinfo[i - 1].vdepth > 1) {
2287c478bd9Sstevel@tonic-gate 				mouse_x += WCOLS * (mouse_y -
2297c478bd9Sstevel@tonic-gate 				    (vlinfo[i].vliny -
2307c478bd9Sstevel@tonic-gate 				    (vlinfo[i - 1].vdepth - 1)));
2317c478bd9Sstevel@tonic-gate 			}
2327c478bd9Sstevel@tonic-gate 		}
2337c478bd9Sstevel@tonic-gate 		else
2347c478bd9Sstevel@tonic-gate 		{
2357c478bd9Sstevel@tonic-gate 			mouse_x += WCOLS * (mouse_y - 1);
2367c478bd9Sstevel@tonic-gate 		}
2377c478bd9Sstevel@tonic-gate /*
2387c478bd9Sstevel@tonic-gate  *	Set the line
2397c478bd9Sstevel@tonic-gate  */
2407c478bd9Sstevel@tonic-gate 		vsave();
2417c478bd9Sstevel@tonic-gate 		ocurs = cursor;
2427c478bd9Sstevel@tonic-gate 		odot = dot;
2437c478bd9Sstevel@tonic-gate 		oline = vcline;
2447c478bd9Sstevel@tonic-gate 		operate('H', i);
2457c478bd9Sstevel@tonic-gate /*
2467c478bd9Sstevel@tonic-gate  *	Set the column
2477c478bd9Sstevel@tonic-gate  */
2487c478bd9Sstevel@tonic-gate 		getDOT();
2497c478bd9Sstevel@tonic-gate 		if (Pline == numbline)
2507c478bd9Sstevel@tonic-gate 			mouse_x += 8;
2517c478bd9Sstevel@tonic-gate 		vmovcol = mouse_x;
2527c478bd9Sstevel@tonic-gate 		vmoving = 1;
2537c478bd9Sstevel@tonic-gate 		wcursor = vfindcol(mouse_x);
2547c478bd9Sstevel@tonic-gate /*
2557c478bd9Sstevel@tonic-gate  *	Reset everything so that stuff like delete and change work
2567c478bd9Sstevel@tonic-gate  */
2577c478bd9Sstevel@tonic-gate 		wdot = (odot - oline) + i - 1;
2587c478bd9Sstevel@tonic-gate 		cursor = ocurs;
2597c478bd9Sstevel@tonic-gate 		vcline = oline;
2607c478bd9Sstevel@tonic-gate 		dot = odot;
2617c478bd9Sstevel@tonic-gate 		getDOT();
2627c478bd9Sstevel@tonic-gate 		break;
2637c478bd9Sstevel@tonic-gate /* #endif PTR_ADDRESSES */
2647c478bd9Sstevel@tonic-gate 
2657c478bd9Sstevel@tonic-gate 	/*
2667c478bd9Sstevel@tonic-gate 	 * b		Back up a word.
2677c478bd9Sstevel@tonic-gate 	 * B		Back up a word, liberal definition.
2687c478bd9Sstevel@tonic-gate 	 */
2697c478bd9Sstevel@tonic-gate 	case 'b':
2707c478bd9Sstevel@tonic-gate 	case 'B':
2717c478bd9Sstevel@tonic-gate 		dir = -1;
2727c478bd9Sstevel@tonic-gate 		/* fall into ... */
2737c478bd9Sstevel@tonic-gate 
2747c478bd9Sstevel@tonic-gate 	/*
2757c478bd9Sstevel@tonic-gate 	 * w		Forward a word.
2767c478bd9Sstevel@tonic-gate 	 * W		Forward a word, liberal definition.
2777c478bd9Sstevel@tonic-gate 	 */
2787c478bd9Sstevel@tonic-gate 	case 'W':
2797c478bd9Sstevel@tonic-gate 	case 'w':
2807c478bd9Sstevel@tonic-gate 		wdkind = c & ' ';
2817c478bd9Sstevel@tonic-gate 		forbid(lfind(2, cnt, opf, (line *)0) < 0);
2827c478bd9Sstevel@tonic-gate 		vmoving = 0;
2837c478bd9Sstevel@tonic-gate 		break;
2847c478bd9Sstevel@tonic-gate 
2857c478bd9Sstevel@tonic-gate 	/*
2867c478bd9Sstevel@tonic-gate 	 * E		to end of following blank/nonblank word
2877c478bd9Sstevel@tonic-gate 	 */
2887c478bd9Sstevel@tonic-gate 	case 'E':
2897c478bd9Sstevel@tonic-gate 		wdkind = 0;
2907c478bd9Sstevel@tonic-gate 		goto ein;
2917c478bd9Sstevel@tonic-gate 
2927c478bd9Sstevel@tonic-gate 	/*
2937c478bd9Sstevel@tonic-gate 	 * e		To end of following word.
2947c478bd9Sstevel@tonic-gate 	 */
2957c478bd9Sstevel@tonic-gate 	case 'e':
2967c478bd9Sstevel@tonic-gate 		wdkind = 1;
2977c478bd9Sstevel@tonic-gate ein:
2987c478bd9Sstevel@tonic-gate 		forbid(lfind(3, cnt - 1, opf, (line *)0) < 0);
2997c478bd9Sstevel@tonic-gate 		vmoving = 0;
3007c478bd9Sstevel@tonic-gate 		break;
3017c478bd9Sstevel@tonic-gate 
3027c478bd9Sstevel@tonic-gate 	/*
3037c478bd9Sstevel@tonic-gate 	 * (		Back an s-expression.
3047c478bd9Sstevel@tonic-gate 	 */
3057c478bd9Sstevel@tonic-gate 	case '(':
3067c478bd9Sstevel@tonic-gate 		dir = -1;
3077c478bd9Sstevel@tonic-gate 		/* fall into... */
3087c478bd9Sstevel@tonic-gate 
3097c478bd9Sstevel@tonic-gate 	/*
3107c478bd9Sstevel@tonic-gate 	 * )		Forward an s-expression.
3117c478bd9Sstevel@tonic-gate 	 */
3127c478bd9Sstevel@tonic-gate 	case ')':
3137c478bd9Sstevel@tonic-gate 		forbid(lfind(0, cnt, opf, (line *) 0) < 0);
3147c478bd9Sstevel@tonic-gate 		markDOT();
3157c478bd9Sstevel@tonic-gate 		break;
3167c478bd9Sstevel@tonic-gate 
3177c478bd9Sstevel@tonic-gate 	/*
3187c478bd9Sstevel@tonic-gate 	 * {		Back an s-expression, but don't stop on atoms.
3197c478bd9Sstevel@tonic-gate 	 *		In text mode, a paragraph.  For C, a balanced set
3207c478bd9Sstevel@tonic-gate 	 *		of {}'s.
3217c478bd9Sstevel@tonic-gate 	 */
3227c478bd9Sstevel@tonic-gate 	case '{':
3237c478bd9Sstevel@tonic-gate 		dir = -1;
3247c478bd9Sstevel@tonic-gate 		/* fall into... */
3257c478bd9Sstevel@tonic-gate 
3267c478bd9Sstevel@tonic-gate 	/*
3277c478bd9Sstevel@tonic-gate 	 * }		Forward an s-expression, but don't stop on atoms.
3287c478bd9Sstevel@tonic-gate 	 *		In text mode, back paragraph.  For C, back a balanced
3297c478bd9Sstevel@tonic-gate 	 *		set of {}'s.
3307c478bd9Sstevel@tonic-gate 	 */
3317c478bd9Sstevel@tonic-gate 	case '}':
3327c478bd9Sstevel@tonic-gate 		forbid(lfind(1, cnt, opf, (line *) 0) < 0);
3337c478bd9Sstevel@tonic-gate 		markDOT();
3347c478bd9Sstevel@tonic-gate 		break;
3357c478bd9Sstevel@tonic-gate 
3367c478bd9Sstevel@tonic-gate 	/*
3377c478bd9Sstevel@tonic-gate 	 * %		To matching () or {}.  If not at ( or { scan for
3387c478bd9Sstevel@tonic-gate 	 *		first such after cursor on this line.
3397c478bd9Sstevel@tonic-gate 	 */
3407c478bd9Sstevel@tonic-gate 	case '%':
3417c478bd9Sstevel@tonic-gate 		vsave();
3427c478bd9Sstevel@tonic-gate 		ocurs = cursor;
3437c478bd9Sstevel@tonic-gate 		odot = wdot = dot;
3447c478bd9Sstevel@tonic-gate 		oglobp = globp;
3457c478bd9Sstevel@tonic-gate 		CATCH
3467c478bd9Sstevel@tonic-gate 			i = lmatchp((line *) 0);
3477c478bd9Sstevel@tonic-gate 		ONERR
3487c478bd9Sstevel@tonic-gate 			globp = oglobp;
3497c478bd9Sstevel@tonic-gate 			dot = wdot = odot;
3507c478bd9Sstevel@tonic-gate 			cursor = ocurs;
3517c478bd9Sstevel@tonic-gate 			splitw = 0;
3527c478bd9Sstevel@tonic-gate 			vclean();
3537c478bd9Sstevel@tonic-gate 			vjumpto(dot, ocurs, 0);
3547c478bd9Sstevel@tonic-gate 			return;
3557c478bd9Sstevel@tonic-gate 		ENDCATCH
3567c478bd9Sstevel@tonic-gate #ifdef TRACE
3577c478bd9Sstevel@tonic-gate 		if (trace)
3587c478bd9Sstevel@tonic-gate 			fprintf(trace, "after lmatchp in %, dot=%d, wdot=%d, "
3597c478bd9Sstevel@tonic-gate 			    "dol=%d\n", lineno(dot), lineno(wdot), lineno(dol));
3607c478bd9Sstevel@tonic-gate #endif
3617c478bd9Sstevel@tonic-gate 		getDOT();
3627c478bd9Sstevel@tonic-gate 		forbid(!i);
3637c478bd9Sstevel@tonic-gate 		if (opf != vmove)
3647c478bd9Sstevel@tonic-gate 			if (dir > 0)
3657c478bd9Sstevel@tonic-gate 				wcursor++;
3667c478bd9Sstevel@tonic-gate 			else
3677c478bd9Sstevel@tonic-gate 				cursor++;
3687c478bd9Sstevel@tonic-gate 		else
3697c478bd9Sstevel@tonic-gate 			markDOT();
3707c478bd9Sstevel@tonic-gate 		vmoving = 0;
3717c478bd9Sstevel@tonic-gate 		break;
3727c478bd9Sstevel@tonic-gate 
3737c478bd9Sstevel@tonic-gate 	/*
3747c478bd9Sstevel@tonic-gate 	 * [		Back to beginning of defun, i.e. an ( in column 1.
3757c478bd9Sstevel@tonic-gate 	 *		For text, back to a section macro.
3767c478bd9Sstevel@tonic-gate 	 *		For C, back to a { in column 1 (~~ beg of function.)
3777c478bd9Sstevel@tonic-gate 	 */
3787c478bd9Sstevel@tonic-gate 	case '[':
3797c478bd9Sstevel@tonic-gate 		dir = -1;
3807c478bd9Sstevel@tonic-gate 		/* fall into ... */
3817c478bd9Sstevel@tonic-gate 
3827c478bd9Sstevel@tonic-gate 	/*
3837c478bd9Sstevel@tonic-gate 	 * ]		Forward to next defun, i.e. a ( in column 1.
3847c478bd9Sstevel@tonic-gate 	 *		For text, forward section.
3857c478bd9Sstevel@tonic-gate 	 *		For C, forward to a } in column 1 (if delete or such)
3867c478bd9Sstevel@tonic-gate 	 *		or if a move to a { in column 1.
3877c478bd9Sstevel@tonic-gate 	 */
3887c478bd9Sstevel@tonic-gate 	case ']':
3897c478bd9Sstevel@tonic-gate 		if (!vglobp)
3907c478bd9Sstevel@tonic-gate 			forbid(getkey() != c);
3917c478bd9Sstevel@tonic-gate #ifndef XPG4
3927c478bd9Sstevel@tonic-gate 		forbid(Xhadcnt);
3937c478bd9Sstevel@tonic-gate #endif
3947c478bd9Sstevel@tonic-gate 		vsave();
3957c478bd9Sstevel@tonic-gate #ifdef XPG4
3967c478bd9Sstevel@tonic-gate 		if (cnt > 1) {
3977c478bd9Sstevel@tonic-gate 			while (cnt-- > 1) {
3987c478bd9Sstevel@tonic-gate 				i = lbrack(c, opf);
3997c478bd9Sstevel@tonic-gate 				getDOT();
4007c478bd9Sstevel@tonic-gate 				forbid(!i);
4017c478bd9Sstevel@tonic-gate 				markDOT();
4027c478bd9Sstevel@tonic-gate 				if (ospeed > B300)
4037c478bd9Sstevel@tonic-gate 					hold |= HOLDWIG;
4047c478bd9Sstevel@tonic-gate 				(*opf)(c);
4057c478bd9Sstevel@tonic-gate 			}
4067c478bd9Sstevel@tonic-gate 		}
4077c478bd9Sstevel@tonic-gate #endif /* XPG4 */
4087c478bd9Sstevel@tonic-gate 		i = lbrack(c, opf);
4097c478bd9Sstevel@tonic-gate 		getDOT();
4107c478bd9Sstevel@tonic-gate 		forbid(!i);
4117c478bd9Sstevel@tonic-gate 		markDOT();
4127c478bd9Sstevel@tonic-gate 		if (ospeed > B300)
4137c478bd9Sstevel@tonic-gate 			hold |= HOLDWIG;
4147c478bd9Sstevel@tonic-gate 		break;
4157c478bd9Sstevel@tonic-gate 
4167c478bd9Sstevel@tonic-gate 	/*
4177c478bd9Sstevel@tonic-gate 	 * ,		Invert last find with f F t or T, like inverse
4187c478bd9Sstevel@tonic-gate 	 *		of ;.
4197c478bd9Sstevel@tonic-gate 	 */
4207c478bd9Sstevel@tonic-gate 	case ',':
4217c478bd9Sstevel@tonic-gate 		forbid(lastFKND == 0);
4227c478bd9Sstevel@tonic-gate 		c = isupper(lastFKND) ? tolower(lastFKND) : toupper(lastFKND);
4237c478bd9Sstevel@tonic-gate 		i = lastFCHR;
4247c478bd9Sstevel@tonic-gate 		if (vglobp == 0)
4257c478bd9Sstevel@tonic-gate 			vglobp = (unsigned char *)"";
4267c478bd9Sstevel@tonic-gate 		subop++;
4277c478bd9Sstevel@tonic-gate 		goto nocount;
4287c478bd9Sstevel@tonic-gate 
4297c478bd9Sstevel@tonic-gate 	/*
4307c478bd9Sstevel@tonic-gate 	 * 0		To beginning of real line.
4317c478bd9Sstevel@tonic-gate 	 */
4327c478bd9Sstevel@tonic-gate 	case '0':
4337c478bd9Sstevel@tonic-gate 		wcursor = linebuf;
4347c478bd9Sstevel@tonic-gate 		vmoving = 0;
4357c478bd9Sstevel@tonic-gate 		break;
4367c478bd9Sstevel@tonic-gate 
4377c478bd9Sstevel@tonic-gate 	/*
4387c478bd9Sstevel@tonic-gate 	 * ;		Repeat last find with f F t or T.
4397c478bd9Sstevel@tonic-gate 	 */
4407c478bd9Sstevel@tonic-gate 	case ';':
4417c478bd9Sstevel@tonic-gate 		forbid(lastFKND == 0);
4427c478bd9Sstevel@tonic-gate 		c = lastFKND;
4437c478bd9Sstevel@tonic-gate 		i = lastFCHR;
4447c478bd9Sstevel@tonic-gate 		subop++;
4457c478bd9Sstevel@tonic-gate 		goto nocount;
4467c478bd9Sstevel@tonic-gate 
4477c478bd9Sstevel@tonic-gate 	/*
4487c478bd9Sstevel@tonic-gate 	 * F		Find single character before cursor in current line.
4497c478bd9Sstevel@tonic-gate 	 * T		Like F, but stops before character.
4507c478bd9Sstevel@tonic-gate 	 */
4517c478bd9Sstevel@tonic-gate 	case 'F':	/* inverted find */
4527c478bd9Sstevel@tonic-gate 	case 'T':
4537c478bd9Sstevel@tonic-gate 		dir = -1;
4547c478bd9Sstevel@tonic-gate 		/* fall into ... */
4557c478bd9Sstevel@tonic-gate 
4567c478bd9Sstevel@tonic-gate 	/*
4577c478bd9Sstevel@tonic-gate 	 * f		Find single character following cursor in current line.
4587c478bd9Sstevel@tonic-gate 	 * t		Like f, but stope before character.
4597c478bd9Sstevel@tonic-gate 	 */
4607c478bd9Sstevel@tonic-gate 	case 'f':	/* find */
4617c478bd9Sstevel@tonic-gate 	case 't':
4627c478bd9Sstevel@tonic-gate 		if (!subop) {
4637c478bd9Sstevel@tonic-gate 			int length;
4647c478bd9Sstevel@tonic-gate 			wchar_t wchar;
4657c478bd9Sstevel@tonic-gate 			length = _mbftowc(lastcp, &wchar, getesc, &Peekkey);
4667c478bd9Sstevel@tonic-gate 			if (length <= 0 || wchar == 0) {
467f6db9f27Scf46844 				(void) beep();
4687c478bd9Sstevel@tonic-gate 				return;
4697c478bd9Sstevel@tonic-gate 			}
4707c478bd9Sstevel@tonic-gate 			i = wchar;
4717c478bd9Sstevel@tonic-gate 			lastcp += length;
4727c478bd9Sstevel@tonic-gate 		}
4737c478bd9Sstevel@tonic-gate 		if (vglobp == 0)
4747c478bd9Sstevel@tonic-gate 			lastFKND = c, lastFCHR = i;
4757c478bd9Sstevel@tonic-gate 		for (; cnt > 0; cnt--)
4767c478bd9Sstevel@tonic-gate 			forbid(find(i) == 0);
4777c478bd9Sstevel@tonic-gate 		vmoving = 0;
4787c478bd9Sstevel@tonic-gate 		switch (c) {
4797c478bd9Sstevel@tonic-gate 
4807c478bd9Sstevel@tonic-gate 		case 'T':
4817c478bd9Sstevel@tonic-gate 			wcursor = nextchr(wcursor);
4827c478bd9Sstevel@tonic-gate 			break;
4837c478bd9Sstevel@tonic-gate 
4847c478bd9Sstevel@tonic-gate 		case 't':
4857c478bd9Sstevel@tonic-gate 			wcursor = lastchr(linebuf, wcursor);
4867c478bd9Sstevel@tonic-gate 		case 'f':
4877c478bd9Sstevel@tonic-gate fixup:
4887c478bd9Sstevel@tonic-gate 			if (moveop != vmove)
4897c478bd9Sstevel@tonic-gate 				wcursor = nextchr(wcursor);
4907c478bd9Sstevel@tonic-gate 			break;
4917c478bd9Sstevel@tonic-gate 		}
4927c478bd9Sstevel@tonic-gate 		break;
4937c478bd9Sstevel@tonic-gate 
4947c478bd9Sstevel@tonic-gate 	/*
4957c478bd9Sstevel@tonic-gate 	 * |		Find specified print column in current line.
4967c478bd9Sstevel@tonic-gate 	 */
4977c478bd9Sstevel@tonic-gate 	case '|':
4987c478bd9Sstevel@tonic-gate 		if (Pline == numbline)
4997c478bd9Sstevel@tonic-gate 			cnt += 8;
5007c478bd9Sstevel@tonic-gate 		vmovcol = cnt;
5017c478bd9Sstevel@tonic-gate 		vmoving = 1;
5027c478bd9Sstevel@tonic-gate 		wcursor = vfindcol(cnt);
5037c478bd9Sstevel@tonic-gate 		break;
5047c478bd9Sstevel@tonic-gate 
5057c478bd9Sstevel@tonic-gate 	/*
5067c478bd9Sstevel@tonic-gate 	 * ^		To beginning of non-white space on line.
5077c478bd9Sstevel@tonic-gate 	 */
5087c478bd9Sstevel@tonic-gate 	case '^':
5097c478bd9Sstevel@tonic-gate 		wcursor = vskipwh(linebuf);
5107c478bd9Sstevel@tonic-gate 		vmoving = 0;
5117c478bd9Sstevel@tonic-gate 		break;
5127c478bd9Sstevel@tonic-gate 
5137c478bd9Sstevel@tonic-gate 	/*
5147c478bd9Sstevel@tonic-gate 	 * $		To end of line.
5157c478bd9Sstevel@tonic-gate 	 */
5167c478bd9Sstevel@tonic-gate 	case '$':
5177c478bd9Sstevel@tonic-gate 		if (opf == vmove) {
5187c478bd9Sstevel@tonic-gate 			vmoving = 1;
5197c478bd9Sstevel@tonic-gate 			vmovcol = 20000;
5207c478bd9Sstevel@tonic-gate 		} else
5217c478bd9Sstevel@tonic-gate 			vmoving = 0;
5227c478bd9Sstevel@tonic-gate 		if (cnt > 1) {
5237c478bd9Sstevel@tonic-gate 			if (opf == vmove) {
5247c478bd9Sstevel@tonic-gate 				wcursor = 0;
5257c478bd9Sstevel@tonic-gate 				cnt--;
5267c478bd9Sstevel@tonic-gate 			} else
5277c478bd9Sstevel@tonic-gate 				wcursor = linebuf;
5287c478bd9Sstevel@tonic-gate 			/* This is wrong at EOF */
5297c478bd9Sstevel@tonic-gate 			wdot = dot + cnt;
5307c478bd9Sstevel@tonic-gate 			break;
5317c478bd9Sstevel@tonic-gate 		}
5327c478bd9Sstevel@tonic-gate 		if (linebuf[0]) {
5337c478bd9Sstevel@tonic-gate 			wcursor = strend(linebuf);
5347c478bd9Sstevel@tonic-gate 			wcursor = lastchr(linebuf, wcursor);
5357c478bd9Sstevel@tonic-gate 			goto fixup;
5367c478bd9Sstevel@tonic-gate 		}
5377c478bd9Sstevel@tonic-gate 		wcursor = linebuf;
5387c478bd9Sstevel@tonic-gate 		break;
5397c478bd9Sstevel@tonic-gate 
5407c478bd9Sstevel@tonic-gate 	/*
5417c478bd9Sstevel@tonic-gate 	 * h		Back a character.
5427c478bd9Sstevel@tonic-gate 	 * ^H		Back a character.
5437c478bd9Sstevel@tonic-gate 	 */
5447c478bd9Sstevel@tonic-gate 	case 'h':
5457c478bd9Sstevel@tonic-gate 	case CTRL('h'):
5467c478bd9Sstevel@tonic-gate 		dir = -1;
5477c478bd9Sstevel@tonic-gate 		/* fall into ... */
5487c478bd9Sstevel@tonic-gate 
5497c478bd9Sstevel@tonic-gate 	/*
5507c478bd9Sstevel@tonic-gate 	 * space	Forward a character.
5517c478bd9Sstevel@tonic-gate 	 */
5527c478bd9Sstevel@tonic-gate 	case 'l':
5537c478bd9Sstevel@tonic-gate 	case ' ':
5547c478bd9Sstevel@tonic-gate 		forbid(margin() || opf == vmove && edge());
5557c478bd9Sstevel@tonic-gate 		while (cnt > 0 && !margin()) {
5567c478bd9Sstevel@tonic-gate 			if (dir == 1)
5577c478bd9Sstevel@tonic-gate 				wcursor = nextchr(wcursor);
5587c478bd9Sstevel@tonic-gate 			else
5597c478bd9Sstevel@tonic-gate 				wcursor = lastchr(linebuf, wcursor);
5607c478bd9Sstevel@tonic-gate 			cnt--;
5617c478bd9Sstevel@tonic-gate 		}
5627c478bd9Sstevel@tonic-gate 		if (margin() && opf == vmove || wcursor < linebuf) {
5637c478bd9Sstevel@tonic-gate 			if (dir == 1)
5647c478bd9Sstevel@tonic-gate 				wcursor = lastchr(linebuf, wcursor);
5657c478bd9Sstevel@tonic-gate 			else
5667c478bd9Sstevel@tonic-gate 				wcursor = linebuf;
5677c478bd9Sstevel@tonic-gate 		}
5687c478bd9Sstevel@tonic-gate 		vmoving = 0;
5697c478bd9Sstevel@tonic-gate 		break;
5707c478bd9Sstevel@tonic-gate 
5717c478bd9Sstevel@tonic-gate 	/*
5727c478bd9Sstevel@tonic-gate 	 * D		Delete to end of line, short for d$.
5737c478bd9Sstevel@tonic-gate 	 */
5747c478bd9Sstevel@tonic-gate 	case 'D':
5757c478bd9Sstevel@tonic-gate 		cnt = INF;
5767c478bd9Sstevel@tonic-gate 		goto deleteit;
5777c478bd9Sstevel@tonic-gate 
5787c478bd9Sstevel@tonic-gate 	/*
5797c478bd9Sstevel@tonic-gate 	 * X		Delete character before cursor.
5807c478bd9Sstevel@tonic-gate 	 */
5817c478bd9Sstevel@tonic-gate 	case 'X':
5827c478bd9Sstevel@tonic-gate 		dir = -1;
5837c478bd9Sstevel@tonic-gate 		/* fall into ... */
5847c478bd9Sstevel@tonic-gate deleteit:
5857c478bd9Sstevel@tonic-gate 	/*
5867c478bd9Sstevel@tonic-gate 	 * x		Delete character at cursor, leaving cursor where it is.
5877c478bd9Sstevel@tonic-gate 	 */
5887c478bd9Sstevel@tonic-gate 	case 'x':
5897c478bd9Sstevel@tonic-gate 		if (margin())
5907c478bd9Sstevel@tonic-gate 			goto errlab;
5917c478bd9Sstevel@tonic-gate 		vmacchng(1);
5927c478bd9Sstevel@tonic-gate 		while (cnt > 0 && !margin()) {
5937c478bd9Sstevel@tonic-gate 			if (dir == 1)
5947c478bd9Sstevel@tonic-gate 				wcursor = nextchr(wcursor);
5957c478bd9Sstevel@tonic-gate 			else
5967c478bd9Sstevel@tonic-gate 				wcursor = lastchr(linebuf, wcursor);
5977c478bd9Sstevel@tonic-gate 			cnt--;
5987c478bd9Sstevel@tonic-gate 		}
5997c478bd9Sstevel@tonic-gate 		opf = deleteop;
6007c478bd9Sstevel@tonic-gate 		vmoving = 0;
6017c478bd9Sstevel@tonic-gate 		break;
6027c478bd9Sstevel@tonic-gate 
6037c478bd9Sstevel@tonic-gate 	default:
6047c478bd9Sstevel@tonic-gate 		/*
6057c478bd9Sstevel@tonic-gate 		 * Stuttered operators are equivalent to the operator on
6067c478bd9Sstevel@tonic-gate 		 * a line, thus turn dd into d_.
6077c478bd9Sstevel@tonic-gate 		 */
6087c478bd9Sstevel@tonic-gate 		if (opf == vmove || c != workcmd[0]) {
6097c478bd9Sstevel@tonic-gate errlab:
610f6db9f27Scf46844 			(void) beep();
6117c478bd9Sstevel@tonic-gate 			vmacp = 0;
6127c478bd9Sstevel@tonic-gate 			return;
6137c478bd9Sstevel@tonic-gate 		}
6147c478bd9Sstevel@tonic-gate 		/* fall into ... */
6157c478bd9Sstevel@tonic-gate 
6167c478bd9Sstevel@tonic-gate 	/*
6177c478bd9Sstevel@tonic-gate 	 * _		Target for a line or group of lines.
6187c478bd9Sstevel@tonic-gate 	 *		Stuttering is more convenient; this is mostly
6197c478bd9Sstevel@tonic-gate 	 *		for aesthetics.
6207c478bd9Sstevel@tonic-gate 	 */
6217c478bd9Sstevel@tonic-gate 	case '_':
6227c478bd9Sstevel@tonic-gate 		wdot = dot + cnt - 1;
6237c478bd9Sstevel@tonic-gate 		vmoving = 0;
6247c478bd9Sstevel@tonic-gate 		wcursor = 0;
6257c478bd9Sstevel@tonic-gate 		break;
6267c478bd9Sstevel@tonic-gate 
6277c478bd9Sstevel@tonic-gate 	/*
6287c478bd9Sstevel@tonic-gate 	 * H		To first, home line on screen.
6297c478bd9Sstevel@tonic-gate 	 *		Count is for count'th line rather than first.
6307c478bd9Sstevel@tonic-gate 	 */
6317c478bd9Sstevel@tonic-gate 	case 'H':
6327c478bd9Sstevel@tonic-gate 		wdot = (dot - vcline) + cnt - 1;
6337c478bd9Sstevel@tonic-gate 		if (opf == vmove)
6347c478bd9Sstevel@tonic-gate 			markit(wdot);
6357c478bd9Sstevel@tonic-gate 		vmoving = 0;
6367c478bd9Sstevel@tonic-gate 		wcursor = 0;
6377c478bd9Sstevel@tonic-gate 		break;
6387c478bd9Sstevel@tonic-gate 
6397c478bd9Sstevel@tonic-gate 	/*
6407c478bd9Sstevel@tonic-gate 	 * -		Backwards lines, to first non-white character.
6417c478bd9Sstevel@tonic-gate 	 */
6427c478bd9Sstevel@tonic-gate 	case '-':
6437c478bd9Sstevel@tonic-gate 		wdot = dot - cnt;
6447c478bd9Sstevel@tonic-gate 		vmoving = 0;
6457c478bd9Sstevel@tonic-gate 		wcursor = 0;
6467c478bd9Sstevel@tonic-gate 		break;
6477c478bd9Sstevel@tonic-gate 
6487c478bd9Sstevel@tonic-gate 	/*
6497c478bd9Sstevel@tonic-gate 	 * ^P		To previous line same column.  Ridiculous on the
6507c478bd9Sstevel@tonic-gate 	 *		console of the VAX since it puts console in LSI mode.
6517c478bd9Sstevel@tonic-gate 	 */
6527c478bd9Sstevel@tonic-gate 	case 'k':
6537c478bd9Sstevel@tonic-gate 	case CTRL('p'):
6547c478bd9Sstevel@tonic-gate 		wdot = dot - cnt;
6557c478bd9Sstevel@tonic-gate 		if (vmoving == 0)
6567c478bd9Sstevel@tonic-gate 			vmoving = 1, vmovcol = column(cursor);
6577c478bd9Sstevel@tonic-gate 		wcursor = 0;
6587c478bd9Sstevel@tonic-gate 		break;
6597c478bd9Sstevel@tonic-gate 
6607c478bd9Sstevel@tonic-gate 	/*
6617c478bd9Sstevel@tonic-gate 	 * L		To last line on screen, or count'th line from the
6627c478bd9Sstevel@tonic-gate 	 *		bottom.
6637c478bd9Sstevel@tonic-gate 	 */
6647c478bd9Sstevel@tonic-gate 	case 'L':
6657c478bd9Sstevel@tonic-gate 		wdot = dot + vcnt - vcline - cnt;
6667c478bd9Sstevel@tonic-gate 		if (opf == vmove)
6677c478bd9Sstevel@tonic-gate 			markit(wdot);
6687c478bd9Sstevel@tonic-gate 		vmoving = 0;
6697c478bd9Sstevel@tonic-gate 		wcursor = 0;
6707c478bd9Sstevel@tonic-gate 		break;
6717c478bd9Sstevel@tonic-gate 
6727c478bd9Sstevel@tonic-gate 	/*
6737c478bd9Sstevel@tonic-gate 	 * M		To the middle of the screen.
6747c478bd9Sstevel@tonic-gate 	 */
6757c478bd9Sstevel@tonic-gate 	case 'M':
6767c478bd9Sstevel@tonic-gate 		wdot = dot + ((vcnt + 1) / 2) - vcline - 1;
6777c478bd9Sstevel@tonic-gate 		if (opf == vmove)
6787c478bd9Sstevel@tonic-gate 			markit(wdot);
6797c478bd9Sstevel@tonic-gate 		vmoving = 0;
6807c478bd9Sstevel@tonic-gate 		wcursor = 0;
6817c478bd9Sstevel@tonic-gate 		break;
6827c478bd9Sstevel@tonic-gate 
6837c478bd9Sstevel@tonic-gate 	/*
6847c478bd9Sstevel@tonic-gate 	 * +		Forward line, to first non-white.
6857c478bd9Sstevel@tonic-gate 	 *
6867c478bd9Sstevel@tonic-gate 	 * CR		Convenient synonym for +.
6877c478bd9Sstevel@tonic-gate 	 */
6887c478bd9Sstevel@tonic-gate 	case '+':
6897c478bd9Sstevel@tonic-gate 	case CR:
6907c478bd9Sstevel@tonic-gate 		wdot = dot + cnt;
6917c478bd9Sstevel@tonic-gate 		vmoving = 0;
6927c478bd9Sstevel@tonic-gate 		wcursor = 0;
6937c478bd9Sstevel@tonic-gate 		break;
6947c478bd9Sstevel@tonic-gate 
6957c478bd9Sstevel@tonic-gate 	/*
6967c478bd9Sstevel@tonic-gate 	 * ^N		To next line, same column if possible.
6977c478bd9Sstevel@tonic-gate 	 *
6987c478bd9Sstevel@tonic-gate 	 * LF		Linefeed is a convenient synonym for ^N.
6997c478bd9Sstevel@tonic-gate 	 */
7007c478bd9Sstevel@tonic-gate 	case CTRL('n'):
7017c478bd9Sstevel@tonic-gate 	case 'j':
7027c478bd9Sstevel@tonic-gate 	case NL:
7037c478bd9Sstevel@tonic-gate 		wdot = dot + cnt;
7047c478bd9Sstevel@tonic-gate 		if (vmoving == 0)
7057c478bd9Sstevel@tonic-gate 			vmoving = 1, vmovcol = column(cursor);
7067c478bd9Sstevel@tonic-gate 		wcursor = 0;
7077c478bd9Sstevel@tonic-gate 		break;
7087c478bd9Sstevel@tonic-gate 
7097c478bd9Sstevel@tonic-gate 	/*
7107c478bd9Sstevel@tonic-gate 	 * n		Search to next match of current pattern.
7117c478bd9Sstevel@tonic-gate 	 */
7127c478bd9Sstevel@tonic-gate 	case 'n':
7137c478bd9Sstevel@tonic-gate 		vglobp = vscandir;
7147c478bd9Sstevel@tonic-gate 		c = *vglobp++;
7157c478bd9Sstevel@tonic-gate 		goto nocount;
7167c478bd9Sstevel@tonic-gate 
7177c478bd9Sstevel@tonic-gate 	/*
7187c478bd9Sstevel@tonic-gate 	 * N		Like n but in reverse direction.
7197c478bd9Sstevel@tonic-gate 	 */
7207c478bd9Sstevel@tonic-gate 	case 'N':
7217c478bd9Sstevel@tonic-gate 		vglobp = vscandir[0] == '/' ? (unsigned char *)"?" :
7227c478bd9Sstevel@tonic-gate 		    (unsigned char *)"/";
7237c478bd9Sstevel@tonic-gate 		c = *vglobp++;
7247c478bd9Sstevel@tonic-gate 		goto nocount;
7257c478bd9Sstevel@tonic-gate 
7267c478bd9Sstevel@tonic-gate 	/*
7277c478bd9Sstevel@tonic-gate 	 * '		Return to line specified by following mark,
7287c478bd9Sstevel@tonic-gate 	 *		first white position on line.
7297c478bd9Sstevel@tonic-gate 	 *
7307c478bd9Sstevel@tonic-gate 	 * `		Return to marked line at remembered column.
7317c478bd9Sstevel@tonic-gate 	 */
7327c478bd9Sstevel@tonic-gate 	case '\'':
7337c478bd9Sstevel@tonic-gate 	case '`':
7347c478bd9Sstevel@tonic-gate 		d = c;
7357c478bd9Sstevel@tonic-gate 		c = getesc();
7367c478bd9Sstevel@tonic-gate 		if (c == 0)
7377c478bd9Sstevel@tonic-gate 			return;
7387c478bd9Sstevel@tonic-gate 		c = markreg(c);
7397c478bd9Sstevel@tonic-gate 		forbid(c == 0);
7407c478bd9Sstevel@tonic-gate 		wdot = getmark(c);
7417c478bd9Sstevel@tonic-gate 		forbid(wdot == NOLINE);
7427c478bd9Sstevel@tonic-gate 		forbid(Xhadcnt);
7437c478bd9Sstevel@tonic-gate 		vmoving = 0;
7447c478bd9Sstevel@tonic-gate 		wcursor = d == '`' ? ncols[c - 'a'] : 0;
7457c478bd9Sstevel@tonic-gate 		if (opf == vmove && (wdot != dot ||
7467c478bd9Sstevel@tonic-gate 		    (d == '`' && wcursor != cursor)))
7477c478bd9Sstevel@tonic-gate 			markDOT();
7487c478bd9Sstevel@tonic-gate 		if (wcursor) {
7497c478bd9Sstevel@tonic-gate 			vsave();
750*23a1cceaSRoger A. Faulkner 			getaline(*wdot);
7517c478bd9Sstevel@tonic-gate 			if (wcursor > strend(linebuf))
7527c478bd9Sstevel@tonic-gate 				wcursor = 0;
7537c478bd9Sstevel@tonic-gate 			else {
7547c478bd9Sstevel@tonic-gate 				cnt = wcursor - linebuf;
7557c478bd9Sstevel@tonic-gate 				/*CSTYLED*/
7567c478bd9Sstevel@tonic-gate 				for (wcursor = linebuf; wcursor - linebuf < cnt; )
7577c478bd9Sstevel@tonic-gate 					wcursor = nextchr(wcursor);
7587c478bd9Sstevel@tonic-gate 				if (wcursor - linebuf > cnt)
7597c478bd9Sstevel@tonic-gate 					wcursor = lastchr(linebuf, wcursor);
7607c478bd9Sstevel@tonic-gate 			}
7617c478bd9Sstevel@tonic-gate 			getDOT();
7627c478bd9Sstevel@tonic-gate 		}
7637c478bd9Sstevel@tonic-gate 		if (ospeed > B300)
7647c478bd9Sstevel@tonic-gate 			hold |= HOLDWIG;
7657c478bd9Sstevel@tonic-gate 		break;
7667c478bd9Sstevel@tonic-gate 
7677c478bd9Sstevel@tonic-gate 	/*
7687c478bd9Sstevel@tonic-gate 	 * G		Goto count'th line, or last line if no count
7697c478bd9Sstevel@tonic-gate 	 *		given.
7707c478bd9Sstevel@tonic-gate 	 */
7717c478bd9Sstevel@tonic-gate 	case 'G':
7727c478bd9Sstevel@tonic-gate 		if (!Xhadcnt)
7737c478bd9Sstevel@tonic-gate 			cnt = lineDOL();
7747c478bd9Sstevel@tonic-gate 		wdot = zero + cnt;
7757c478bd9Sstevel@tonic-gate 		forbid(wdot < one || wdot > dol);
7767c478bd9Sstevel@tonic-gate 		if (opf == vmove)
7777c478bd9Sstevel@tonic-gate 			markit(wdot);
7787c478bd9Sstevel@tonic-gate 		vmoving = 0;
7797c478bd9Sstevel@tonic-gate 		wcursor = 0;
7807c478bd9Sstevel@tonic-gate 		break;
7817c478bd9Sstevel@tonic-gate 
7827c478bd9Sstevel@tonic-gate 	/*
7837c478bd9Sstevel@tonic-gate 	 * /		Scan forward for following re.
7847c478bd9Sstevel@tonic-gate 	 * ?		Scan backward for following re.
7857c478bd9Sstevel@tonic-gate 	 */
7867c478bd9Sstevel@tonic-gate 	case '/':
7877c478bd9Sstevel@tonic-gate 	case '?':
7887c478bd9Sstevel@tonic-gate 		forbid(Xhadcnt);
7897c478bd9Sstevel@tonic-gate 		vsave();
7907c478bd9Sstevel@tonic-gate 		oc = c;
7917c478bd9Sstevel@tonic-gate 		ocurs = cursor;
7927c478bd9Sstevel@tonic-gate 		odot = dot;
7937c478bd9Sstevel@tonic-gate 		wcursor = 0;
7947c478bd9Sstevel@tonic-gate 		if (readecho(c))
7957c478bd9Sstevel@tonic-gate 			return;
7967c478bd9Sstevel@tonic-gate 		if (!vglobp)
7977c478bd9Sstevel@tonic-gate 			vscandir[0] = genbuf[0];
7987c478bd9Sstevel@tonic-gate 		oglobp = globp; CP(vutmp, genbuf); globp = vutmp;
7997c478bd9Sstevel@tonic-gate 		d = peekc;
8007c478bd9Sstevel@tonic-gate fromsemi:
8017c478bd9Sstevel@tonic-gate 		ungetchar(0);
8027c478bd9Sstevel@tonic-gate 		fixech();
8037c478bd9Sstevel@tonic-gate 		CATCH
8047c478bd9Sstevel@tonic-gate #ifndef CBREAK
8057c478bd9Sstevel@tonic-gate 			/*
8067c478bd9Sstevel@tonic-gate 			 * Lose typeahead (ick).
8077c478bd9Sstevel@tonic-gate 			 */
8087c478bd9Sstevel@tonic-gate 			vcook();
8097c478bd9Sstevel@tonic-gate #endif
8107c478bd9Sstevel@tonic-gate 			addr = address(cursor);
8117c478bd9Sstevel@tonic-gate #ifndef CBREAK
8127c478bd9Sstevel@tonic-gate 			vraw();
8137c478bd9Sstevel@tonic-gate #endif
8147c478bd9Sstevel@tonic-gate 		ONERR
8157c478bd9Sstevel@tonic-gate #ifndef CBREAK
8167c478bd9Sstevel@tonic-gate 			vraw();
8177c478bd9Sstevel@tonic-gate #endif
8187c478bd9Sstevel@tonic-gate slerr:
8197c478bd9Sstevel@tonic-gate 			globp = oglobp;
8207c478bd9Sstevel@tonic-gate 			dot = odot;
8217c478bd9Sstevel@tonic-gate 			cursor = ocurs;
8227c478bd9Sstevel@tonic-gate 			ungetchar(d);
8237c478bd9Sstevel@tonic-gate 			splitw = 0;
8247c478bd9Sstevel@tonic-gate 			vclean();
8257c478bd9Sstevel@tonic-gate 			vjumpto(dot, ocurs, 0);
8267c478bd9Sstevel@tonic-gate 			return;
8277c478bd9Sstevel@tonic-gate 		ENDCATCH
8287c478bd9Sstevel@tonic-gate 		if (globp == 0)
8297c478bd9Sstevel@tonic-gate 			globp = (unsigned char *)"";
8307c478bd9Sstevel@tonic-gate 		else if (peekc)
8317c478bd9Sstevel@tonic-gate 			--globp;
8327c478bd9Sstevel@tonic-gate 		if (*globp == ';') {
8337c478bd9Sstevel@tonic-gate 			/* /foo/;/bar/ */
8347c478bd9Sstevel@tonic-gate 			globp++;
8357c478bd9Sstevel@tonic-gate 			dot = addr;
8367c478bd9Sstevel@tonic-gate 			cursor = (unsigned char *)loc1;
8377c478bd9Sstevel@tonic-gate 			goto fromsemi;
8387c478bd9Sstevel@tonic-gate 		}
8397c478bd9Sstevel@tonic-gate 		dot = odot;
8407c478bd9Sstevel@tonic-gate 		ungetchar(d);
8417c478bd9Sstevel@tonic-gate 		c = 0;
8427c478bd9Sstevel@tonic-gate 		if (*globp == 'z')
8437c478bd9Sstevel@tonic-gate 			globp++, c = '\n';
8447c478bd9Sstevel@tonic-gate 		if (any(*globp, "^+-."))
8457c478bd9Sstevel@tonic-gate 			c = *globp++;
8467c478bd9Sstevel@tonic-gate 		i = 0;
8477c478bd9Sstevel@tonic-gate 		while (isdigit(*globp))
8487c478bd9Sstevel@tonic-gate 			i = i * 10 + *globp++ - '0';
8497c478bd9Sstevel@tonic-gate 		if (any(*globp, "^+-."))
8507c478bd9Sstevel@tonic-gate 			c = *globp++;
8517c478bd9Sstevel@tonic-gate 		if (*globp) {
8527c478bd9Sstevel@tonic-gate 			/* random junk after the pattern */
853f6db9f27Scf46844 			(void) beep();
8547c478bd9Sstevel@tonic-gate 			goto slerr;
8557c478bd9Sstevel@tonic-gate 		}
8567c478bd9Sstevel@tonic-gate 		globp = oglobp;
8577c478bd9Sstevel@tonic-gate 		splitw = 0;
8587c478bd9Sstevel@tonic-gate 		vmoving = 0;
8597c478bd9Sstevel@tonic-gate 		wcursor = (unsigned char *)loc1;
8607c478bd9Sstevel@tonic-gate 		if (i != 0)
8617c478bd9Sstevel@tonic-gate 			vsetsiz(i);
8627c478bd9Sstevel@tonic-gate 		if (opf == vmove) {
8637c478bd9Sstevel@tonic-gate 			if (state == ONEOPEN || state == HARDOPEN)
8647c478bd9Sstevel@tonic-gate 				outline = destline = WBOT;
8657c478bd9Sstevel@tonic-gate 			if (addr != dot || (unsigned char *)loc1 != cursor)
8667c478bd9Sstevel@tonic-gate 				markDOT();
8677c478bd9Sstevel@tonic-gate 			if (loc1 > (char *)linebuf && *loc1 == 0)
8687c478bd9Sstevel@tonic-gate 				loc1 = (char *)lastchr(linebuf, loc1);
8697c478bd9Sstevel@tonic-gate 			if (c)
870f6db9f27Scf46844 				vjumpto(addr, (unsigned char *)loc1, c);
8717c478bd9Sstevel@tonic-gate 			else {
8727c478bd9Sstevel@tonic-gate 				vmoving = 0;
8737c478bd9Sstevel@tonic-gate 				if (loc1) {
8747c478bd9Sstevel@tonic-gate 					vmoving++;
8757c478bd9Sstevel@tonic-gate 					vmovcol = column(loc1);
8767c478bd9Sstevel@tonic-gate 				}
8777c478bd9Sstevel@tonic-gate 				getDOT();
8787c478bd9Sstevel@tonic-gate 				if (state == CRTOPEN && addr != dot)
8797c478bd9Sstevel@tonic-gate 					vup1();
8807c478bd9Sstevel@tonic-gate 				vupdown(addr - dot, NOSTR);
8817c478bd9Sstevel@tonic-gate 			}
8827c478bd9Sstevel@tonic-gate 			if (oc == '/') {	/* forward search */
8837c478bd9Sstevel@tonic-gate 				if (dot < odot ||
8847c478bd9Sstevel@tonic-gate 				    (dot == odot && cursor <= ocurs))
8857c478bd9Sstevel@tonic-gate 					warnf(value(vi_TERSE) ?
8867c478bd9Sstevel@tonic-gate 			gettext("Search wrapped BOTTOM") :
8877c478bd9Sstevel@tonic-gate 			gettext("Search wrapped around BOTTOM of buffer"));
8887c478bd9Sstevel@tonic-gate 			} else {		/* backward search */
8897c478bd9Sstevel@tonic-gate 				if (dot > odot ||
8907c478bd9Sstevel@tonic-gate 				    (dot == odot && cursor >= ocurs))
8917c478bd9Sstevel@tonic-gate 					warnf(value(vi_TERSE) ?
8927c478bd9Sstevel@tonic-gate 			gettext("Search wrapped TOP") :
8937c478bd9Sstevel@tonic-gate 			gettext("Search wrapped around TOP of buffer"));
8947c478bd9Sstevel@tonic-gate 			}
8957c478bd9Sstevel@tonic-gate 			return;
8967c478bd9Sstevel@tonic-gate 		}
8977c478bd9Sstevel@tonic-gate 		lastcp[-1] = 'n';
8987c478bd9Sstevel@tonic-gate 		getDOT();
8997c478bd9Sstevel@tonic-gate 		wdot = addr;
9007c478bd9Sstevel@tonic-gate 		break;
9017c478bd9Sstevel@tonic-gate 	}
9027c478bd9Sstevel@tonic-gate 	/*
9037c478bd9Sstevel@tonic-gate 	 * Apply.
9047c478bd9Sstevel@tonic-gate 	 */
9057c478bd9Sstevel@tonic-gate 	if (vreg && wdot == 0)
9067c478bd9Sstevel@tonic-gate 		wdot = dot;
9077c478bd9Sstevel@tonic-gate 	(*opf)(c);
9087c478bd9Sstevel@tonic-gate 	wdot = NOLINE;
9097c478bd9Sstevel@tonic-gate }
9107c478bd9Sstevel@tonic-gate 
9117c478bd9Sstevel@tonic-gate static void
lfixol()9127c478bd9Sstevel@tonic-gate lfixol()
9137c478bd9Sstevel@tonic-gate {
9147c478bd9Sstevel@tonic-gate 	unsigned char *savevglobp;
9157c478bd9Sstevel@tonic-gate 	int savesplit;
9167c478bd9Sstevel@tonic-gate 
9177c478bd9Sstevel@tonic-gate 	if (Outchar == vputchar)
9187c478bd9Sstevel@tonic-gate 		return;
9197c478bd9Sstevel@tonic-gate 
9207c478bd9Sstevel@tonic-gate 	/* Show messages */
9217c478bd9Sstevel@tonic-gate 	putnl();
9227c478bd9Sstevel@tonic-gate 	if (inopen > 0 && clr_eol)
9237c478bd9Sstevel@tonic-gate 		vclreol();
9247c478bd9Sstevel@tonic-gate 	if (enter_standout_mode && exit_bold)
925f6db9f27Scf46844 		putpad((unsigned char *)enter_standout_mode);
9267c478bd9Sstevel@tonic-gate 	lprintf(gettext("[Hit return to continue] "), 0);
9277c478bd9Sstevel@tonic-gate 	if (enter_standout_mode && exit_bold)
928f6db9f27Scf46844 		putpad((unsigned char *)exit_bold);
9297c478bd9Sstevel@tonic-gate 
9307c478bd9Sstevel@tonic-gate 	/* Get key input for confirmation */
9317c478bd9Sstevel@tonic-gate 	savevglobp = vglobp;
9327c478bd9Sstevel@tonic-gate 	vglobp = 0; /* force typed input */
9337c478bd9Sstevel@tonic-gate 	getkey();
9347c478bd9Sstevel@tonic-gate 	vglobp = savevglobp;
9357c478bd9Sstevel@tonic-gate 
9367c478bd9Sstevel@tonic-gate 	/* reset output function */
9377c478bd9Sstevel@tonic-gate 	Outchar = vputchar;
9387c478bd9Sstevel@tonic-gate 
9397c478bd9Sstevel@tonic-gate 	/* Clean up screen */
9407c478bd9Sstevel@tonic-gate 	savesplit = splitw;
9417c478bd9Sstevel@tonic-gate 	splitw = 0;
9427c478bd9Sstevel@tonic-gate 	vclear();
9437c478bd9Sstevel@tonic-gate 	vdirty(0, WLINES);
9447c478bd9Sstevel@tonic-gate 	vredraw(WTOP);
9457c478bd9Sstevel@tonic-gate 	splitw = savesplit;
9467c478bd9Sstevel@tonic-gate }
9477c478bd9Sstevel@tonic-gate 
948f6db9f27Scf46844 void
warnf(char * str,char * cp)949f6db9f27Scf46844 warnf(char *str, char *cp)
9507c478bd9Sstevel@tonic-gate {
9517c478bd9Sstevel@tonic-gate 	int saveline, savecol, savesplit;
9527c478bd9Sstevel@tonic-gate 
9537c478bd9Sstevel@tonic-gate 	saveline = outline;
9547c478bd9Sstevel@tonic-gate 	savecol = outcol;
9557c478bd9Sstevel@tonic-gate 	savesplit = splitw;
9567c478bd9Sstevel@tonic-gate 	splitw = 1;
9577c478bd9Sstevel@tonic-gate 	vgoto(WECHO, 0);
9587c478bd9Sstevel@tonic-gate 	if (!enter_standout_mode || !exit_bold)
9597c478bd9Sstevel@tonic-gate 		dingdong();
9607c478bd9Sstevel@tonic-gate 	if (clr_eol)
9617c478bd9Sstevel@tonic-gate 		vclreol();
9627c478bd9Sstevel@tonic-gate 	if (enter_standout_mode && exit_bold)
963f6db9f27Scf46844 		putpad((unsigned char *)enter_standout_mode);
9647c478bd9Sstevel@tonic-gate 	lprintf(str, cp);
9657c478bd9Sstevel@tonic-gate 	if (enter_standout_mode && exit_bold)
966f6db9f27Scf46844 		putpad((unsigned char *)exit_bold);
9677c478bd9Sstevel@tonic-gate 	lfixol();
9687c478bd9Sstevel@tonic-gate 	vgoto(saveline, savecol);
9697c478bd9Sstevel@tonic-gate 	splitw = savesplit;
9707c478bd9Sstevel@tonic-gate }
9717c478bd9Sstevel@tonic-gate 
9727c478bd9Sstevel@tonic-gate /* #ifdef PTR_ADDRESSES */
9737c478bd9Sstevel@tonic-gate /*
9747c478bd9Sstevel@tonic-gate  *	read in a row or column address
9757c478bd9Sstevel@tonic-gate  *
9767c478bd9Sstevel@tonic-gate  */
9777c478bd9Sstevel@tonic-gate static int
get_addr()9787c478bd9Sstevel@tonic-gate get_addr()
9797c478bd9Sstevel@tonic-gate {
980f6db9f27Scf46844 	short  c;
981f6db9f27Scf46844 	short  next;
9827c478bd9Sstevel@tonic-gate 
9837c478bd9Sstevel@tonic-gate 	c = getkey();
9847c478bd9Sstevel@tonic-gate 	next = 0;
9857c478bd9Sstevel@tonic-gate 	switch (c) {
9867c478bd9Sstevel@tonic-gate 	case CTRL('A'):
9877c478bd9Sstevel@tonic-gate 		next = 96;
9887c478bd9Sstevel@tonic-gate 		c = getkey();
9897c478bd9Sstevel@tonic-gate 		break;
9907c478bd9Sstevel@tonic-gate 
9917c478bd9Sstevel@tonic-gate 	case CTRL('B'):
9927c478bd9Sstevel@tonic-gate 		next = 192;
9937c478bd9Sstevel@tonic-gate 		c = getkey();
9947c478bd9Sstevel@tonic-gate 		break;
9957c478bd9Sstevel@tonic-gate 	}
9967c478bd9Sstevel@tonic-gate 	if (c < ' ')
9977c478bd9Sstevel@tonic-gate 		return (-1);
9987c478bd9Sstevel@tonic-gate 	return (next + c - ' ');
9997c478bd9Sstevel@tonic-gate }
10007c478bd9Sstevel@tonic-gate /* #endif PTR_ADDRESSES */
10017c478bd9Sstevel@tonic-gate 
10027c478bd9Sstevel@tonic-gate /*
10037c478bd9Sstevel@tonic-gate  * Find single character c, in direction dir from cursor.
10047c478bd9Sstevel@tonic-gate  */
1005f6db9f27Scf46844 int
find(wchar_t c)1006f6db9f27Scf46844 find(wchar_t c)
10077c478bd9Sstevel@tonic-gate {
10087c478bd9Sstevel@tonic-gate 
10097c478bd9Sstevel@tonic-gate 	wchar_t wchar;
10107c478bd9Sstevel@tonic-gate 	int length;
10117c478bd9Sstevel@tonic-gate 	for (;;) {
10127c478bd9Sstevel@tonic-gate 		if (edge())
10137c478bd9Sstevel@tonic-gate 			return (0);
10147c478bd9Sstevel@tonic-gate 		if (dir == 1)
10157c478bd9Sstevel@tonic-gate 			wcursor = nextchr(wcursor);
10167c478bd9Sstevel@tonic-gate 		else
10177c478bd9Sstevel@tonic-gate 			wcursor = lastchr(linebuf, wcursor);
10187c478bd9Sstevel@tonic-gate 		if ((length = mbtowc(&wchar, (char *)wcursor,
10197c478bd9Sstevel@tonic-gate 		    MULTI_BYTE_MAX)) > 0 && wchar == c)
10207c478bd9Sstevel@tonic-gate 			return (1);
10217c478bd9Sstevel@tonic-gate 	}
10227c478bd9Sstevel@tonic-gate }
10237c478bd9Sstevel@tonic-gate 
10247c478bd9Sstevel@tonic-gate /*
10257c478bd9Sstevel@tonic-gate  * Do a word motion with operator op, and cnt more words
10267c478bd9Sstevel@tonic-gate  * to go after this.
10277c478bd9Sstevel@tonic-gate  */
1028f6db9f27Scf46844 int
word(int (* op)(),int cnt)1029f6db9f27Scf46844 word(int (*op)(), int cnt)
10307c478bd9Sstevel@tonic-gate {
1031f6db9f27Scf46844 	int which;
1032f6db9f27Scf46844 	unsigned char *iwc;
1033f6db9f27Scf46844 	line *iwdot = wdot;
10347c478bd9Sstevel@tonic-gate 	wchar_t wchar;
10357c478bd9Sstevel@tonic-gate 	int length;
10367c478bd9Sstevel@tonic-gate 
10377c478bd9Sstevel@tonic-gate 	if (dir == 1) {
10387c478bd9Sstevel@tonic-gate 		iwc = wcursor;
10397c478bd9Sstevel@tonic-gate 		which = wordch(wcursor);
10407c478bd9Sstevel@tonic-gate 		while (wordof(which, wcursor)) {
10417c478bd9Sstevel@tonic-gate 			length = mbtowc(&wchar, (char *)wcursor,
10427c478bd9Sstevel@tonic-gate 			    MULTI_BYTE_MAX);
10437c478bd9Sstevel@tonic-gate 			if (length <= 0)
10447c478bd9Sstevel@tonic-gate 				length = 1;
10457c478bd9Sstevel@tonic-gate 			if (cnt == 1 && op != vmove && wcursor[length] == 0) {
10467c478bd9Sstevel@tonic-gate 				wcursor += length;
10477c478bd9Sstevel@tonic-gate 				break;
10487c478bd9Sstevel@tonic-gate 			}
10497c478bd9Sstevel@tonic-gate 			if (!lnext())
10507c478bd9Sstevel@tonic-gate 				return (0);
10517c478bd9Sstevel@tonic-gate 			if (wcursor == linebuf)
10527c478bd9Sstevel@tonic-gate 				break;
10537c478bd9Sstevel@tonic-gate 		}
10547c478bd9Sstevel@tonic-gate 		/* Unless last segment of a change skip blanks */
1055f6db9f27Scf46844 		if (op != (int (*)())vchange || cnt > 1)
10567c478bd9Sstevel@tonic-gate 			while (!margin() && blank()) {
10577c478bd9Sstevel@tonic-gate 				if (!lnext())
10587c478bd9Sstevel@tonic-gate 					return (0);
10597c478bd9Sstevel@tonic-gate 			}
10607c478bd9Sstevel@tonic-gate 		else
10617c478bd9Sstevel@tonic-gate 			if (wcursor == iwc && iwdot == wdot && *iwc)
10627c478bd9Sstevel@tonic-gate 				wcursor = nextchr(wcursor);
10637c478bd9Sstevel@tonic-gate 		if (op == vmove && margin()) {
10647c478bd9Sstevel@tonic-gate 			wcursor = lastchr(linebuf, wcursor);
10657c478bd9Sstevel@tonic-gate #ifdef XPG4
10667c478bd9Sstevel@tonic-gate 			if (wcursor < linebuf) {
10677c478bd9Sstevel@tonic-gate 				wcursor = linebuf;
10687c478bd9Sstevel@tonic-gate 			}
10697c478bd9Sstevel@tonic-gate #endif /* XPG4 */
10707c478bd9Sstevel@tonic-gate 		}
10717c478bd9Sstevel@tonic-gate 	} else {
10727c478bd9Sstevel@tonic-gate 		if (!lnext())
10737c478bd9Sstevel@tonic-gate 			return (0);
10747c478bd9Sstevel@tonic-gate 		while (blank())
10757c478bd9Sstevel@tonic-gate 			if (!lnext())
10767c478bd9Sstevel@tonic-gate 				return (0);
10777c478bd9Sstevel@tonic-gate 		if (!margin()) {
10787c478bd9Sstevel@tonic-gate 			which = wordch(wcursor);
10797c478bd9Sstevel@tonic-gate 			while (!margin() && wordof(which, wcursor))
10807c478bd9Sstevel@tonic-gate 				wcursor = lastchr(linebuf, wcursor);
10817c478bd9Sstevel@tonic-gate 		}
10827c478bd9Sstevel@tonic-gate #ifdef PRESUNEUC
10837c478bd9Sstevel@tonic-gate 		if (wcursor < linebuf || !wordof(which, wcursor))
10847c478bd9Sstevel@tonic-gate 			wcursor = nextchr(wcursor);
10857c478bd9Sstevel@tonic-gate #else
10867c478bd9Sstevel@tonic-gate 		if (wcursor < linebuf)
10877c478bd9Sstevel@tonic-gate 			wcursor++;
10887c478bd9Sstevel@tonic-gate 		else if (!wordof(which, wcursor))
10897c478bd9Sstevel@tonic-gate 			wcursor = nextchr(wcursor);
10907c478bd9Sstevel@tonic-gate #endif /* PRESUNEUC */
10917c478bd9Sstevel@tonic-gate 	}
10927c478bd9Sstevel@tonic-gate 	return (1);
10937c478bd9Sstevel@tonic-gate }
10947c478bd9Sstevel@tonic-gate 
10957c478bd9Sstevel@tonic-gate /*
10967c478bd9Sstevel@tonic-gate  * To end of word, with operator op and cnt more motions
10977c478bd9Sstevel@tonic-gate  * remaining after this.
10987c478bd9Sstevel@tonic-gate  */
1099f6db9f27Scf46844 int
eend(int (* op)())1100f6db9f27Scf46844 eend(int (*op)())
11017c478bd9Sstevel@tonic-gate {
1102f6db9f27Scf46844 	int which;
11037c478bd9Sstevel@tonic-gate 
11047c478bd9Sstevel@tonic-gate 	if (!lnext())
11057c478bd9Sstevel@tonic-gate 		return (0);
11067c478bd9Sstevel@tonic-gate 	while (blank())
11077c478bd9Sstevel@tonic-gate 		if (!lnext())
11087c478bd9Sstevel@tonic-gate 			return (0);
11097c478bd9Sstevel@tonic-gate 	which = wordch(wcursor);
11107c478bd9Sstevel@tonic-gate 	while (wordof(which, wcursor)) {
11117c478bd9Sstevel@tonic-gate 		if (wcursor[1] == 0) {
11127c478bd9Sstevel@tonic-gate 			wcursor = nextchr(wcursor);
11137c478bd9Sstevel@tonic-gate 			break;
11147c478bd9Sstevel@tonic-gate 		}
11157c478bd9Sstevel@tonic-gate 		if (!lnext())
11167c478bd9Sstevel@tonic-gate 			return (0);
11177c478bd9Sstevel@tonic-gate 	}
11187c478bd9Sstevel@tonic-gate 	if (op == vyankit)
11197c478bd9Sstevel@tonic-gate 		wcursor = lastchr(linebuf, wcursor) + 1;
1120f6db9f27Scf46844 	else if (op != (int (*)())vchange && op != (int (*)())vdelete &&
1121f6db9f27Scf46844 	    wcursor > linebuf)
11227c478bd9Sstevel@tonic-gate 		wcursor = lastchr(linebuf, wcursor);
11237c478bd9Sstevel@tonic-gate 	return (1);
11247c478bd9Sstevel@tonic-gate }
11257c478bd9Sstevel@tonic-gate 
11267c478bd9Sstevel@tonic-gate /*
11277c478bd9Sstevel@tonic-gate  * Wordof tells whether the character at *wc is in a word of
11287c478bd9Sstevel@tonic-gate  * kind which (blank/nonblank words are 0, conservative words 1).
11297c478bd9Sstevel@tonic-gate  */
1130f6db9f27Scf46844 int
wordof(unsigned char which,unsigned char * wc)1131f6db9f27Scf46844 wordof(unsigned char which, unsigned char *wc)
11327c478bd9Sstevel@tonic-gate {
11337c478bd9Sstevel@tonic-gate #ifdef PRESUNEUC
11347c478bd9Sstevel@tonic-gate 
11357c478bd9Sstevel@tonic-gate 	if (isspace(*wc))
11367c478bd9Sstevel@tonic-gate #else
11377c478bd9Sstevel@tonic-gate 	wchar_t z;
11387c478bd9Sstevel@tonic-gate 
11397c478bd9Sstevel@tonic-gate 	(void) mbtowc(&z, (char *)wc, MB_LEN_MAX);
11407c478bd9Sstevel@tonic-gate 	if (iswspace(z))
11417c478bd9Sstevel@tonic-gate #endif /* PRESUNEUC */
11427c478bd9Sstevel@tonic-gate 		return (0);
11437c478bd9Sstevel@tonic-gate 	return (!wdkind || wordch(wc) == which);
11447c478bd9Sstevel@tonic-gate }
11457c478bd9Sstevel@tonic-gate 
11467c478bd9Sstevel@tonic-gate /*
11477c478bd9Sstevel@tonic-gate  * Wordch tells whether character at *wc is a word character
11487c478bd9Sstevel@tonic-gate  * i.e. an alfa, digit, or underscore.
11497c478bd9Sstevel@tonic-gate  */
11507c478bd9Sstevel@tonic-gate #ifdef PRESUNEUC
11517c478bd9Sstevel@tonic-gate #define	SS2 0216
11527c478bd9Sstevel@tonic-gate #define	SS3 0217
11537c478bd9Sstevel@tonic-gate #endif /* PRESUNEUC */
11547c478bd9Sstevel@tonic-gate 
1155f6db9f27Scf46844 int
wordch(unsigned char * wc)1156f6db9f27Scf46844 wordch(unsigned char *wc)
11577c478bd9Sstevel@tonic-gate {
1158f6db9f27Scf46844 	int length;
11597c478bd9Sstevel@tonic-gate 	wchar_t c;
11607c478bd9Sstevel@tonic-gate 
11617c478bd9Sstevel@tonic-gate 	length = mbtowc(&c, (char *)wc, MULTI_BYTE_MAX);
11627c478bd9Sstevel@tonic-gate 	if (length <= 0)
11637c478bd9Sstevel@tonic-gate 		return (0);
11647c478bd9Sstevel@tonic-gate 	if (length > 1)
11657c478bd9Sstevel@tonic-gate #ifndef PRESUNEUC
11667c478bd9Sstevel@tonic-gate 		if (wdwc)
11677c478bd9Sstevel@tonic-gate 			return (*wdwc)(c);
11687c478bd9Sstevel@tonic-gate 		else
11697c478bd9Sstevel@tonic-gate #endif /* PRESUNEUC */
11707c478bd9Sstevel@tonic-gate 		return (length);
11717c478bd9Sstevel@tonic-gate #ifndef PRESUNEUC
11727c478bd9Sstevel@tonic-gate 	return (isalpha(*wc) || isdigit(*wc) || *wc == '_');
11737c478bd9Sstevel@tonic-gate #else
11747c478bd9Sstevel@tonic-gate 	return (isalpha(c) || isdigit(c) || c == '_');
11757c478bd9Sstevel@tonic-gate #endif /* PRESUNEUC */
11767c478bd9Sstevel@tonic-gate }
11777c478bd9Sstevel@tonic-gate 
11787c478bd9Sstevel@tonic-gate /*
11797c478bd9Sstevel@tonic-gate  * Edge tells when we hit the last character in the current line.
11807c478bd9Sstevel@tonic-gate  */
1181f6db9f27Scf46844 int
edge(void)1182f6db9f27Scf46844 edge(void)
11837c478bd9Sstevel@tonic-gate {
11847c478bd9Sstevel@tonic-gate 
11857c478bd9Sstevel@tonic-gate 	if (linebuf[0] == 0)
11867c478bd9Sstevel@tonic-gate 		return (1);
11877c478bd9Sstevel@tonic-gate 	if (dir == 1)
11887c478bd9Sstevel@tonic-gate 		return (*(nextchr(wcursor)) == 0);
11897c478bd9Sstevel@tonic-gate 	else
11907c478bd9Sstevel@tonic-gate 		return (wcursor == linebuf);
11917c478bd9Sstevel@tonic-gate }
11927c478bd9Sstevel@tonic-gate 
11937c478bd9Sstevel@tonic-gate /*
11947c478bd9Sstevel@tonic-gate  * Margin tells us when we have fallen off the end of the line.
11957c478bd9Sstevel@tonic-gate  */
1196f6db9f27Scf46844 int
margin(void)1197f6db9f27Scf46844 margin(void)
11987c478bd9Sstevel@tonic-gate {
11997c478bd9Sstevel@tonic-gate 
12007c478bd9Sstevel@tonic-gate 	return (wcursor < linebuf || wcursor[0] == 0);
12017c478bd9Sstevel@tonic-gate }
12027c478bd9Sstevel@tonic-gate #ifndef PRESUNEUC
12037c478bd9Sstevel@tonic-gate 
12047c478bd9Sstevel@tonic-gate /*
12057c478bd9Sstevel@tonic-gate  * Blank tells if the cursor is currently on a TAB, RETURN,
12067c478bd9Sstevel@tonic-gate  * NEWLINE, FORMFEED, bertical tab, or SPACE character from EUC
12077c478bd9Sstevel@tonic-gate  * primary and supplementary codesets.
12087c478bd9Sstevel@tonic-gate  */
1209f6db9f27Scf46844 int
blank(void)1210f6db9f27Scf46844 blank(void)
12117c478bd9Sstevel@tonic-gate {
12127c478bd9Sstevel@tonic-gate 	wchar_t z;
12137c478bd9Sstevel@tonic-gate 
12147c478bd9Sstevel@tonic-gate 	(void) mbtowc(&z, (char *)wcursor, MB_CUR_MAX);
12157c478bd9Sstevel@tonic-gate 	return (iswspace((int)z));
12167c478bd9Sstevel@tonic-gate }
12177c478bd9Sstevel@tonic-gate #endif /* PRESUNEUC */
1218