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 523a1cceaSRoger A. Faulkner * Common Development and Distribution License (the "License"). 623a1cceaSRoger A. Faulkner * 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 */ 2123a1cceaSRoger A. Faulkner 22f6db9f27Scf46844 /* 2323a1cceaSRoger 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 /* Copyright (c) 1981 Regents of the University of California */ 317c478bd9Sstevel@tonic-gate 327c478bd9Sstevel@tonic-gate #include "ex.h" 337c478bd9Sstevel@tonic-gate #include "ex_argv.h" 347c478bd9Sstevel@tonic-gate #include "ex_temp.h" 357c478bd9Sstevel@tonic-gate #include "ex_tty.h" 367c478bd9Sstevel@tonic-gate #include "ex_vis.h" 377c478bd9Sstevel@tonic-gate #ifdef STDIO 387c478bd9Sstevel@tonic-gate #include <stdio.h> 397c478bd9Sstevel@tonic-gate #undef getchar 407c478bd9Sstevel@tonic-gate #undef putchar 417c478bd9Sstevel@tonic-gate #endif 42*6a3e8e86SRichard Lowe 43*6a3e8e86SRichard Lowe 447c478bd9Sstevel@tonic-gate /* 457c478bd9Sstevel@tonic-gate * Command mode subroutines implementing 467c478bd9Sstevel@tonic-gate * append, args, copy, delete, join, move, put, 477c478bd9Sstevel@tonic-gate * shift, tag, yank, z and undo 487c478bd9Sstevel@tonic-gate */ 497c478bd9Sstevel@tonic-gate 507c478bd9Sstevel@tonic-gate bool endline = 1; 517c478bd9Sstevel@tonic-gate line *tad1; 52f6db9f27Scf46844 static int jnoop(void); 53f6db9f27Scf46844 static void splitit(void); 547c478bd9Sstevel@tonic-gate int putchar(), getchar(); 557c478bd9Sstevel@tonic-gate int tags_flag; 567c478bd9Sstevel@tonic-gate 577c478bd9Sstevel@tonic-gate /* 587c478bd9Sstevel@tonic-gate * Append after line a lines returned by function f. 597c478bd9Sstevel@tonic-gate * Be careful about intermediate states to avoid scramble 607c478bd9Sstevel@tonic-gate * if an interrupt comes in. 617c478bd9Sstevel@tonic-gate */ 62f6db9f27Scf46844 int 63f6db9f27Scf46844 append(int (*f)(), line *a) 647c478bd9Sstevel@tonic-gate { 65f6db9f27Scf46844 line *a1, *a2, *rdot; 667c478bd9Sstevel@tonic-gate int nline; 677c478bd9Sstevel@tonic-gate 687c478bd9Sstevel@tonic-gate nline = 0; 697c478bd9Sstevel@tonic-gate dot = a; 707c478bd9Sstevel@tonic-gate if(FIXUNDO && !inopen && f!=getsub) { 717c478bd9Sstevel@tonic-gate undap1 = undap2 = dot + 1; 727c478bd9Sstevel@tonic-gate undkind = UNDCHANGE; 737c478bd9Sstevel@tonic-gate } 747c478bd9Sstevel@tonic-gate while ((*f)() == 0) { 757c478bd9Sstevel@tonic-gate if (truedol >= endcore) { 767c478bd9Sstevel@tonic-gate if (morelines() < 0) { 777c478bd9Sstevel@tonic-gate if (FIXUNDO && f == getsub) { 787c478bd9Sstevel@tonic-gate undap1 = addr1; 797c478bd9Sstevel@tonic-gate undap2 = addr2 + 1; 807c478bd9Sstevel@tonic-gate } 817c478bd9Sstevel@tonic-gate error(value(vi_TERSE) ? gettext("Out of memory") : 827c478bd9Sstevel@tonic-gate gettext("Out of memory- too many lines in file")); 837c478bd9Sstevel@tonic-gate } 847c478bd9Sstevel@tonic-gate } 857c478bd9Sstevel@tonic-gate nline++; 867c478bd9Sstevel@tonic-gate a1 = truedol + 1; 877c478bd9Sstevel@tonic-gate a2 = a1 + 1; 887c478bd9Sstevel@tonic-gate dot++; 897c478bd9Sstevel@tonic-gate undap2++; 907c478bd9Sstevel@tonic-gate dol++; 917c478bd9Sstevel@tonic-gate unddol++; 927c478bd9Sstevel@tonic-gate truedol++; 937c478bd9Sstevel@tonic-gate for (rdot = dot; a1 > rdot;) 947c478bd9Sstevel@tonic-gate *--a2 = *--a1; 957c478bd9Sstevel@tonic-gate *rdot = 0; 967c478bd9Sstevel@tonic-gate putmark(rdot); 977c478bd9Sstevel@tonic-gate if (f == gettty) { 987c478bd9Sstevel@tonic-gate dirtcnt++; 997c478bd9Sstevel@tonic-gate TSYNC(); 1007c478bd9Sstevel@tonic-gate } 1017c478bd9Sstevel@tonic-gate } 1027c478bd9Sstevel@tonic-gate return (nline); 1037c478bd9Sstevel@tonic-gate } 1047c478bd9Sstevel@tonic-gate 105f6db9f27Scf46844 void 106f6db9f27Scf46844 appendnone(void) 1077c478bd9Sstevel@tonic-gate { 1087c478bd9Sstevel@tonic-gate 1097c478bd9Sstevel@tonic-gate if(FIXUNDO) { 1107c478bd9Sstevel@tonic-gate undkind = UNDCHANGE; 1117c478bd9Sstevel@tonic-gate undap1 = undap2 = addr1; 1127c478bd9Sstevel@tonic-gate } 1137c478bd9Sstevel@tonic-gate } 1147c478bd9Sstevel@tonic-gate 1157c478bd9Sstevel@tonic-gate /* 1167c478bd9Sstevel@tonic-gate * Print out the argument list, with []'s around the current name. 1177c478bd9Sstevel@tonic-gate */ 118f6db9f27Scf46844 void 119f6db9f27Scf46844 pargs(void) 1207c478bd9Sstevel@tonic-gate { 121f6db9f27Scf46844 unsigned char **av = argv0, *as = args0; 122f6db9f27Scf46844 int ac; 1237c478bd9Sstevel@tonic-gate 1247c478bd9Sstevel@tonic-gate for (ac = 0; ac < argc0; ac++) { 1257c478bd9Sstevel@tonic-gate if (ac != 0) 1267c478bd9Sstevel@tonic-gate putchar(' '); 1277c478bd9Sstevel@tonic-gate if (ac + argc == argc0 - 1) 128f6db9f27Scf46844 viprintf("["); 1297c478bd9Sstevel@tonic-gate lprintf("%s", as); 1307c478bd9Sstevel@tonic-gate if (ac + argc == argc0 - 1) 131f6db9f27Scf46844 viprintf("]"); 1327c478bd9Sstevel@tonic-gate as = av ? *++av : strend(as) + 1; 1337c478bd9Sstevel@tonic-gate } 1347c478bd9Sstevel@tonic-gate noonl(); 1357c478bd9Sstevel@tonic-gate } 1367c478bd9Sstevel@tonic-gate 1377c478bd9Sstevel@tonic-gate /* 1387c478bd9Sstevel@tonic-gate * Delete lines; two cases are if we are really deleting, 1397c478bd9Sstevel@tonic-gate * more commonly we are just moving lines to the undo save area. 1407c478bd9Sstevel@tonic-gate */ 141f6db9f27Scf46844 int 142f6db9f27Scf46844 delete(bool hush) 1437c478bd9Sstevel@tonic-gate { 144f6db9f27Scf46844 line *a1, *a2; 1457c478bd9Sstevel@tonic-gate 1467c478bd9Sstevel@tonic-gate nonzero(); 1477c478bd9Sstevel@tonic-gate if(FIXUNDO) { 1487c478bd9Sstevel@tonic-gate void (*dsavint)(); 1497c478bd9Sstevel@tonic-gate 1507c478bd9Sstevel@tonic-gate #ifdef UNDOTRACE 1517c478bd9Sstevel@tonic-gate if (trace) 1527c478bd9Sstevel@tonic-gate vudump("before delete"); 1537c478bd9Sstevel@tonic-gate #endif 1547c478bd9Sstevel@tonic-gate change(); 1557c478bd9Sstevel@tonic-gate dsavint = signal(SIGINT, SIG_IGN); 1567c478bd9Sstevel@tonic-gate undkind = UNDCHANGE; 1577c478bd9Sstevel@tonic-gate a1 = addr1; 1587c478bd9Sstevel@tonic-gate squish(); 1597c478bd9Sstevel@tonic-gate a2 = addr2; 1607c478bd9Sstevel@tonic-gate if (a2++ != dol) { 1617c478bd9Sstevel@tonic-gate reverse(a1, a2); 1627c478bd9Sstevel@tonic-gate reverse(a2, dol + 1); 1637c478bd9Sstevel@tonic-gate reverse(a1, dol + 1); 1647c478bd9Sstevel@tonic-gate } 1657c478bd9Sstevel@tonic-gate dol -= a2 - a1; 1667c478bd9Sstevel@tonic-gate unddel = a1 - 1; 1677c478bd9Sstevel@tonic-gate if (a1 > dol) 1687c478bd9Sstevel@tonic-gate a1 = dol; 1697c478bd9Sstevel@tonic-gate dot = a1; 1707c478bd9Sstevel@tonic-gate pkill[0] = pkill[1] = 0; 1717c478bd9Sstevel@tonic-gate signal(SIGINT, dsavint); 1727c478bd9Sstevel@tonic-gate #ifdef UNDOTRACE 1737c478bd9Sstevel@tonic-gate if (trace) 1747c478bd9Sstevel@tonic-gate vudump("after delete"); 1757c478bd9Sstevel@tonic-gate #endif 1767c478bd9Sstevel@tonic-gate } else { 177f6db9f27Scf46844 line *a3; 178f6db9f27Scf46844 int i; 1797c478bd9Sstevel@tonic-gate 1807c478bd9Sstevel@tonic-gate change(); 1817c478bd9Sstevel@tonic-gate a1 = addr1; 1827c478bd9Sstevel@tonic-gate a2 = addr2 + 1; 1837c478bd9Sstevel@tonic-gate a3 = truedol; 1847c478bd9Sstevel@tonic-gate i = a2 - a1; 1857c478bd9Sstevel@tonic-gate unddol -= i; 1867c478bd9Sstevel@tonic-gate undap2 -= i; 1877c478bd9Sstevel@tonic-gate dol -= i; 1887c478bd9Sstevel@tonic-gate truedol -= i; 1897c478bd9Sstevel@tonic-gate do 1907c478bd9Sstevel@tonic-gate *a1++ = *a2++; 1917c478bd9Sstevel@tonic-gate while (a2 <= a3); 1927c478bd9Sstevel@tonic-gate a1 = addr1; 1937c478bd9Sstevel@tonic-gate if (a1 > dol) 1947c478bd9Sstevel@tonic-gate a1 = dol; 1957c478bd9Sstevel@tonic-gate dot = a1; 1967c478bd9Sstevel@tonic-gate } 1977c478bd9Sstevel@tonic-gate if (!hush) 1987c478bd9Sstevel@tonic-gate killed(); 199f6db9f27Scf46844 return (0); 2007c478bd9Sstevel@tonic-gate } 2017c478bd9Sstevel@tonic-gate 202f6db9f27Scf46844 void 203f6db9f27Scf46844 deletenone(void) 2047c478bd9Sstevel@tonic-gate { 2057c478bd9Sstevel@tonic-gate 2067c478bd9Sstevel@tonic-gate if(FIXUNDO) { 2077c478bd9Sstevel@tonic-gate undkind = UNDCHANGE; 2087c478bd9Sstevel@tonic-gate squish(); 2097c478bd9Sstevel@tonic-gate unddel = addr1; 2107c478bd9Sstevel@tonic-gate } 2117c478bd9Sstevel@tonic-gate } 2127c478bd9Sstevel@tonic-gate 2137c478bd9Sstevel@tonic-gate /* 2147c478bd9Sstevel@tonic-gate * Crush out the undo save area, moving the open/visual 2157c478bd9Sstevel@tonic-gate * save area down in its place. 2167c478bd9Sstevel@tonic-gate */ 217f6db9f27Scf46844 void 218f6db9f27Scf46844 squish(void) 2197c478bd9Sstevel@tonic-gate { 220f6db9f27Scf46844 line *a1 = dol + 1, *a2 = unddol + 1, *a3 = truedol + 1; 2217c478bd9Sstevel@tonic-gate 2227c478bd9Sstevel@tonic-gate if(FIXUNDO) { 2237c478bd9Sstevel@tonic-gate if (inopen == -1) 2247c478bd9Sstevel@tonic-gate return; 2257c478bd9Sstevel@tonic-gate if (a1 < a2 && a2 < a3) 2267c478bd9Sstevel@tonic-gate do 2277c478bd9Sstevel@tonic-gate *a1++ = *a2++; 2287c478bd9Sstevel@tonic-gate while (a2 < a3); 2297c478bd9Sstevel@tonic-gate truedol -= unddol - dol; 2307c478bd9Sstevel@tonic-gate unddol = dol; 2317c478bd9Sstevel@tonic-gate } 2327c478bd9Sstevel@tonic-gate } 2337c478bd9Sstevel@tonic-gate 2347c478bd9Sstevel@tonic-gate /* 2357c478bd9Sstevel@tonic-gate * Join lines. Special hacks put in spaces, two spaces if 2367c478bd9Sstevel@tonic-gate * preceding line ends with '.', or no spaces if next line starts with ). 2377c478bd9Sstevel@tonic-gate */ 238f6db9f27Scf46844 static int jcount; 2397c478bd9Sstevel@tonic-gate 240f6db9f27Scf46844 int 241f6db9f27Scf46844 join(int c) 2427c478bd9Sstevel@tonic-gate { 243f6db9f27Scf46844 line *a1; 244f6db9f27Scf46844 unsigned char *cp, *cp1; 2457c478bd9Sstevel@tonic-gate #ifndef PRESUNEUC 246f6db9f27Scf46844 unsigned char *pcp; 247f6db9f27Scf46844 wchar_t *delim; 2487c478bd9Sstevel@tonic-gate wchar_t wc1, wc2; 2497c478bd9Sstevel@tonic-gate int n; 2507c478bd9Sstevel@tonic-gate #endif /* PRESUNEUC */ 2517c478bd9Sstevel@tonic-gate 2527c478bd9Sstevel@tonic-gate cp = genbuf; 2537c478bd9Sstevel@tonic-gate *cp = 0; 2547c478bd9Sstevel@tonic-gate for (a1 = addr1; a1 <= addr2; a1++) { 25523a1cceaSRoger A. Faulkner getaline(*a1); 2567c478bd9Sstevel@tonic-gate cp1 = linebuf; 2577c478bd9Sstevel@tonic-gate if (a1 != addr1 && c == 0) { 2587c478bd9Sstevel@tonic-gate while (*cp1 == ' ' || *cp1 == '\t') 2597c478bd9Sstevel@tonic-gate cp1++; 2607c478bd9Sstevel@tonic-gate if (*cp1 && cp > genbuf && cp[-1] != ' ' && cp[-1] != '\t') { 2617c478bd9Sstevel@tonic-gate #ifndef PRESUNEUC 2627c478bd9Sstevel@tonic-gate /* 2637c478bd9Sstevel@tonic-gate * insert locale-specific word delimiter if 2647c478bd9Sstevel@tonic-gate * either of end-of-former-line or 2657c478bd9Sstevel@tonic-gate * top-of-latter-line is non-ASCII. 2667c478bd9Sstevel@tonic-gate */ 2677c478bd9Sstevel@tonic-gate if (wddlm && *cp1 != ')' && cp[-1] != '.') { 2687c478bd9Sstevel@tonic-gate if ((pcp = cp - MB_CUR_MAX) < genbuf) 2697c478bd9Sstevel@tonic-gate pcp = genbuf;; 2707c478bd9Sstevel@tonic-gate for ( ; pcp <= cp-1; pcp++) { 2717c478bd9Sstevel@tonic-gate if ((n = mbtowc(&wc1, 2727c478bd9Sstevel@tonic-gate (char *)pcp, cp - pcp)) == 2737c478bd9Sstevel@tonic-gate cp - pcp) 2747c478bd9Sstevel@tonic-gate goto gotprev; 2757c478bd9Sstevel@tonic-gate } 2767c478bd9Sstevel@tonic-gate goto mberror; 2777c478bd9Sstevel@tonic-gate gotprev: 2787c478bd9Sstevel@tonic-gate if (!isascii(wc2 = *cp1)) { 2797c478bd9Sstevel@tonic-gate if (mbtowc(&wc2, (char *) cp1, 2807c478bd9Sstevel@tonic-gate MB_CUR_MAX) <= 0) 2817c478bd9Sstevel@tonic-gate goto mberror; 2827c478bd9Sstevel@tonic-gate } 2837c478bd9Sstevel@tonic-gate delim = (*wddlm)(wc1,wc2,2); 2847c478bd9Sstevel@tonic-gate while (*delim) 2857c478bd9Sstevel@tonic-gate cp += wctomb((char *)cp, 2867c478bd9Sstevel@tonic-gate *delim++); 2877c478bd9Sstevel@tonic-gate *cp = 0; 2887c478bd9Sstevel@tonic-gate } else 2897c478bd9Sstevel@tonic-gate mberror: 2907c478bd9Sstevel@tonic-gate #endif /* PRESUNEUC */ 2917c478bd9Sstevel@tonic-gate if (*cp1 != ')') { 2927c478bd9Sstevel@tonic-gate *cp++ = ' '; 2937c478bd9Sstevel@tonic-gate if (cp[-2] == '.') 2947c478bd9Sstevel@tonic-gate *cp++ = ' '; 2957c478bd9Sstevel@tonic-gate } 2967c478bd9Sstevel@tonic-gate } 2977c478bd9Sstevel@tonic-gate } 2987c478bd9Sstevel@tonic-gate while (*cp++ = *cp1++) 2997c478bd9Sstevel@tonic-gate if (cp > &genbuf[LBSIZE-2]) 3007c478bd9Sstevel@tonic-gate error(value(vi_TERSE) ? gettext("Line overflow") : 3017c478bd9Sstevel@tonic-gate gettext("Result line of join would be too long")); 3027c478bd9Sstevel@tonic-gate cp--; 3037c478bd9Sstevel@tonic-gate } 3047c478bd9Sstevel@tonic-gate strcLIN(genbuf); 305f6db9f27Scf46844 (void) delete(0); 3067c478bd9Sstevel@tonic-gate jcount = 1; 3077c478bd9Sstevel@tonic-gate if (FIXUNDO) 3087c478bd9Sstevel@tonic-gate undap1 = undap2 = addr1; 3097c478bd9Sstevel@tonic-gate (void)append(jnoop, --addr1); 3107c478bd9Sstevel@tonic-gate if (FIXUNDO) 3117c478bd9Sstevel@tonic-gate vundkind = VMANY; 312f6db9f27Scf46844 return (0); 3137c478bd9Sstevel@tonic-gate } 3147c478bd9Sstevel@tonic-gate 315f6db9f27Scf46844 static int 316f6db9f27Scf46844 jnoop(void) 3177c478bd9Sstevel@tonic-gate { 3187c478bd9Sstevel@tonic-gate 3197c478bd9Sstevel@tonic-gate return(--jcount); 3207c478bd9Sstevel@tonic-gate } 3217c478bd9Sstevel@tonic-gate 3227c478bd9Sstevel@tonic-gate /* 3237c478bd9Sstevel@tonic-gate * Move and copy lines. Hard work is done by move1 which 3247c478bd9Sstevel@tonic-gate * is also called by undo. 3257c478bd9Sstevel@tonic-gate */ 3267c478bd9Sstevel@tonic-gate int getcopy(); 3277c478bd9Sstevel@tonic-gate 328f6db9f27Scf46844 void 329f6db9f27Scf46844 vi_move(void) 3307c478bd9Sstevel@tonic-gate { 331f6db9f27Scf46844 line *adt; 3327c478bd9Sstevel@tonic-gate bool iscopy = 0; 3337c478bd9Sstevel@tonic-gate 3347c478bd9Sstevel@tonic-gate if (Command[0] == 'm') { 3357c478bd9Sstevel@tonic-gate setdot1(); 3367c478bd9Sstevel@tonic-gate markpr(addr2 == dot ? addr1 - 1 : addr2 + 1); 3377c478bd9Sstevel@tonic-gate } else { 3387c478bd9Sstevel@tonic-gate iscopy++; 3397c478bd9Sstevel@tonic-gate setdot(); 3407c478bd9Sstevel@tonic-gate } 3417c478bd9Sstevel@tonic-gate nonzero(); 3427c478bd9Sstevel@tonic-gate adt = address((char*)0); 3437c478bd9Sstevel@tonic-gate if (adt == 0) 344f6db9f27Scf46844 serror(value(vi_TERSE) ? 345f6db9f27Scf46844 (unsigned char *)gettext("%s where?") : 346f6db9f27Scf46844 (unsigned char *)gettext("%s requires a trailing address"), 347f6db9f27Scf46844 Command); 3487c478bd9Sstevel@tonic-gate donewline(); 3497c478bd9Sstevel@tonic-gate move1(iscopy, adt); 3507c478bd9Sstevel@tonic-gate killed(); 3517c478bd9Sstevel@tonic-gate } 3527c478bd9Sstevel@tonic-gate 353f6db9f27Scf46844 void 354f6db9f27Scf46844 move1(int cflag, line *addrt) 3557c478bd9Sstevel@tonic-gate { 356f6db9f27Scf46844 line *adt, *ad1, *ad2; 3577c478bd9Sstevel@tonic-gate int nlines; 3587c478bd9Sstevel@tonic-gate 3597c478bd9Sstevel@tonic-gate adt = addrt; 3607c478bd9Sstevel@tonic-gate nlines = (addr2 - addr1) + 1; 3617c478bd9Sstevel@tonic-gate if (cflag) { 3627c478bd9Sstevel@tonic-gate tad1 = addr1; 3637c478bd9Sstevel@tonic-gate ad1 = dol; 3647c478bd9Sstevel@tonic-gate (void)append(getcopy, ad1++); 3657c478bd9Sstevel@tonic-gate ad2 = dol; 3667c478bd9Sstevel@tonic-gate } else { 3677c478bd9Sstevel@tonic-gate ad2 = addr2; 3687c478bd9Sstevel@tonic-gate for (ad1 = addr1; ad1 <= ad2;) 3697c478bd9Sstevel@tonic-gate *ad1++ &= ~01; 3707c478bd9Sstevel@tonic-gate ad1 = addr1; 3717c478bd9Sstevel@tonic-gate } 3727c478bd9Sstevel@tonic-gate ad2++; 3737c478bd9Sstevel@tonic-gate if (adt < ad1) { 3747c478bd9Sstevel@tonic-gate if (adt + 1 == ad1 && !cflag && !inglobal) 3757c478bd9Sstevel@tonic-gate error(gettext("That move would do nothing!")); 3767c478bd9Sstevel@tonic-gate dot = adt + (ad2 - ad1); 3777c478bd9Sstevel@tonic-gate if (++adt != ad1) { 3787c478bd9Sstevel@tonic-gate reverse(adt, ad1); 3797c478bd9Sstevel@tonic-gate reverse(ad1, ad2); 3807c478bd9Sstevel@tonic-gate reverse(adt, ad2); 3817c478bd9Sstevel@tonic-gate } 3827c478bd9Sstevel@tonic-gate } else if (adt >= ad2) { 3837c478bd9Sstevel@tonic-gate dot = adt++; 3847c478bd9Sstevel@tonic-gate reverse(ad1, ad2); 3857c478bd9Sstevel@tonic-gate reverse(ad2, adt); 3867c478bd9Sstevel@tonic-gate reverse(ad1, adt); 3877c478bd9Sstevel@tonic-gate } else 3887c478bd9Sstevel@tonic-gate error(gettext("Move to a moved line")); 3897c478bd9Sstevel@tonic-gate change(); 3907c478bd9Sstevel@tonic-gate if (!inglobal) 3917c478bd9Sstevel@tonic-gate if(FIXUNDO) { 3927c478bd9Sstevel@tonic-gate if (cflag) { 3937c478bd9Sstevel@tonic-gate undap1 = addrt + 1; 3947c478bd9Sstevel@tonic-gate undap2 = undap1 + nlines; 3957c478bd9Sstevel@tonic-gate deletenone(); 3967c478bd9Sstevel@tonic-gate } else { 3977c478bd9Sstevel@tonic-gate undkind = UNDMOVE; 3987c478bd9Sstevel@tonic-gate undap1 = addr1; 3997c478bd9Sstevel@tonic-gate undap2 = addr2; 4007c478bd9Sstevel@tonic-gate unddel = addrt; 4017c478bd9Sstevel@tonic-gate squish(); 4027c478bd9Sstevel@tonic-gate } 4037c478bd9Sstevel@tonic-gate } 4047c478bd9Sstevel@tonic-gate } 4057c478bd9Sstevel@tonic-gate 406f6db9f27Scf46844 int 407f6db9f27Scf46844 getcopy(void) 4087c478bd9Sstevel@tonic-gate { 4097c478bd9Sstevel@tonic-gate 4107c478bd9Sstevel@tonic-gate if (tad1 > addr2) 4117c478bd9Sstevel@tonic-gate return (EOF); 41223a1cceaSRoger A. Faulkner getaline(*tad1++); 4137c478bd9Sstevel@tonic-gate return (0); 4147c478bd9Sstevel@tonic-gate } 4157c478bd9Sstevel@tonic-gate 4167c478bd9Sstevel@tonic-gate /* 4177c478bd9Sstevel@tonic-gate * Put lines in the buffer from the undo save area. 4187c478bd9Sstevel@tonic-gate */ 419f6db9f27Scf46844 int 420f6db9f27Scf46844 getput(void) 4217c478bd9Sstevel@tonic-gate { 4227c478bd9Sstevel@tonic-gate 4237c478bd9Sstevel@tonic-gate if (tad1 > unddol) 4247c478bd9Sstevel@tonic-gate return (EOF); 42523a1cceaSRoger A. Faulkner getaline(*tad1++); 4267c478bd9Sstevel@tonic-gate tad1++; 4277c478bd9Sstevel@tonic-gate return (0); 4287c478bd9Sstevel@tonic-gate } 4297c478bd9Sstevel@tonic-gate 430f6db9f27Scf46844 int 431f6db9f27Scf46844 put(void) 4327c478bd9Sstevel@tonic-gate { 433f6db9f27Scf46844 int cnt; 4347c478bd9Sstevel@tonic-gate 4357c478bd9Sstevel@tonic-gate if (!FIXUNDO) 4367c478bd9Sstevel@tonic-gate error(gettext("Cannot put inside global/macro")); 4377c478bd9Sstevel@tonic-gate cnt = unddol - dol; 4387c478bd9Sstevel@tonic-gate if (cnt && inopen && pkill[0] && pkill[1]) { 4397c478bd9Sstevel@tonic-gate pragged(1); 440f6db9f27Scf46844 return (0); 4417c478bd9Sstevel@tonic-gate } 4427c478bd9Sstevel@tonic-gate tad1 = dol + 1; 4437c478bd9Sstevel@tonic-gate (void)append(getput, addr2); 4447c478bd9Sstevel@tonic-gate undkind = UNDPUT; 4457c478bd9Sstevel@tonic-gate notecnt = cnt; 4467c478bd9Sstevel@tonic-gate netchange(cnt); 447f6db9f27Scf46844 return (0); 4487c478bd9Sstevel@tonic-gate } 4497c478bd9Sstevel@tonic-gate 4507c478bd9Sstevel@tonic-gate /* 4517c478bd9Sstevel@tonic-gate * A tricky put, of a group of lines in the middle 4527c478bd9Sstevel@tonic-gate * of an existing line. Only from open/visual. 4537c478bd9Sstevel@tonic-gate * Argument says pkills have meaning, e.g. called from 4547c478bd9Sstevel@tonic-gate * put; it is 0 on calls from putreg. 4557c478bd9Sstevel@tonic-gate */ 456f6db9f27Scf46844 void 457f6db9f27Scf46844 pragged(bool kill) 4587c478bd9Sstevel@tonic-gate { 4597c478bd9Sstevel@tonic-gate extern unsigned char *cursor; 4607c478bd9Sstevel@tonic-gate #ifdef XPG4 4617c478bd9Sstevel@tonic-gate extern int P_cursor_offset; 4627c478bd9Sstevel@tonic-gate #endif 463f6db9f27Scf46844 unsigned char *gp = &genbuf[cursor - linebuf]; 4647c478bd9Sstevel@tonic-gate 4657c478bd9Sstevel@tonic-gate /* 4667c478bd9Sstevel@tonic-gate * Assume the editor has: 4677c478bd9Sstevel@tonic-gate * 4687c478bd9Sstevel@tonic-gate * cursor is on 'c' 4697c478bd9Sstevel@tonic-gate * 4707c478bd9Sstevel@tonic-gate * file is: 1) abcd 4717c478bd9Sstevel@tonic-gate * 2) efgh 4727c478bd9Sstevel@tonic-gate * 4737c478bd9Sstevel@tonic-gate * undo area: 3) 1 4747c478bd9Sstevel@tonic-gate * 4) 2 4757c478bd9Sstevel@tonic-gate * 5) 3 4767c478bd9Sstevel@tonic-gate */ 4777c478bd9Sstevel@tonic-gate 4787c478bd9Sstevel@tonic-gate if (!kill) 4797c478bd9Sstevel@tonic-gate getDOT(); 4807c478bd9Sstevel@tonic-gate 4817c478bd9Sstevel@tonic-gate /* 4827c478bd9Sstevel@tonic-gate * Copy "abcd" into genbuf. 4837c478bd9Sstevel@tonic-gate * Note that gp points to 'c'. 4847c478bd9Sstevel@tonic-gate */ 4857c478bd9Sstevel@tonic-gate 4867c478bd9Sstevel@tonic-gate strcpy(genbuf, linebuf); 4877c478bd9Sstevel@tonic-gate 4887c478bd9Sstevel@tonic-gate /* 4897c478bd9Sstevel@tonic-gate * Get last line of undo area ("3") into linebuf. 4907c478bd9Sstevel@tonic-gate */ 4917c478bd9Sstevel@tonic-gate 49223a1cceaSRoger A. Faulkner getaline(*unddol); 4937c478bd9Sstevel@tonic-gate if (kill) 4947c478bd9Sstevel@tonic-gate *pkill[1] = 0; 4957c478bd9Sstevel@tonic-gate 4967c478bd9Sstevel@tonic-gate 4977c478bd9Sstevel@tonic-gate /* 4987c478bd9Sstevel@tonic-gate * Concatenate trailing end of current line 4997c478bd9Sstevel@tonic-gate * into the last line of undo area: 5007c478bd9Sstevel@tonic-gate * linebuf = "3cd" 5017c478bd9Sstevel@tonic-gate */ 5027c478bd9Sstevel@tonic-gate 5037c478bd9Sstevel@tonic-gate strcat(linebuf, gp); 5047c478bd9Sstevel@tonic-gate #ifdef XPG4 5057c478bd9Sstevel@tonic-gate P_cursor_offset = strlen(linebuf) - strlen(gp) - 1; 5067c478bd9Sstevel@tonic-gate #endif 5077c478bd9Sstevel@tonic-gate 5087c478bd9Sstevel@tonic-gate /* 5097c478bd9Sstevel@tonic-gate * Replace the last line with what is now in linebuf. 5107c478bd9Sstevel@tonic-gate * So unddol = "3cd" 5117c478bd9Sstevel@tonic-gate */ 5127c478bd9Sstevel@tonic-gate 5137c478bd9Sstevel@tonic-gate putmark(unddol); 5147c478bd9Sstevel@tonic-gate 5157c478bd9Sstevel@tonic-gate /* 5167c478bd9Sstevel@tonic-gate * Get the first line of the undo save area into linebuf. 5177c478bd9Sstevel@tonic-gate * So linebuf = "1" 5187c478bd9Sstevel@tonic-gate */ 5197c478bd9Sstevel@tonic-gate 52023a1cceaSRoger A. Faulkner getaline(dol[1]); 5217c478bd9Sstevel@tonic-gate if (kill) 5227c478bd9Sstevel@tonic-gate strcLIN(pkill[0]); 5237c478bd9Sstevel@tonic-gate 5247c478bd9Sstevel@tonic-gate /* 5257c478bd9Sstevel@tonic-gate * Copy the first line of the undo save area 5267c478bd9Sstevel@tonic-gate * over what is pointed to by sp. 5277c478bd9Sstevel@tonic-gate * genbuf = "ab1" 5287c478bd9Sstevel@tonic-gate */ 5297c478bd9Sstevel@tonic-gate 5307c478bd9Sstevel@tonic-gate strcpy(gp, linebuf); 5317c478bd9Sstevel@tonic-gate 5327c478bd9Sstevel@tonic-gate /* 5337c478bd9Sstevel@tonic-gate * Now copy genbuf back into linebuf. 5347c478bd9Sstevel@tonic-gate * linebuf = "ab1" 5357c478bd9Sstevel@tonic-gate */ 5367c478bd9Sstevel@tonic-gate 5377c478bd9Sstevel@tonic-gate strcLIN(genbuf); 5387c478bd9Sstevel@tonic-gate 5397c478bd9Sstevel@tonic-gate /* 5407c478bd9Sstevel@tonic-gate * Now put linebuf back into the first line 5417c478bd9Sstevel@tonic-gate * of the undo save area. 5427c478bd9Sstevel@tonic-gate */ 5437c478bd9Sstevel@tonic-gate 5447c478bd9Sstevel@tonic-gate putmark(dol+1); 5457c478bd9Sstevel@tonic-gate 5467c478bd9Sstevel@tonic-gate /* 5477c478bd9Sstevel@tonic-gate * Prepare to perform an undo which will actually 5487c478bd9Sstevel@tonic-gate * do a put of multiple lines in the middle of 5497c478bd9Sstevel@tonic-gate * the current line. 5507c478bd9Sstevel@tonic-gate */ 5517c478bd9Sstevel@tonic-gate 5527c478bd9Sstevel@tonic-gate undkind = UNDCHANGE; 5537c478bd9Sstevel@tonic-gate undap1 = dot; 5547c478bd9Sstevel@tonic-gate undap2 = dot + 1; 5557c478bd9Sstevel@tonic-gate unddel = dot - 1; 5567c478bd9Sstevel@tonic-gate undo(1); 5577c478bd9Sstevel@tonic-gate } 5587c478bd9Sstevel@tonic-gate 5597c478bd9Sstevel@tonic-gate /* 5607c478bd9Sstevel@tonic-gate * Shift lines, based on c. 5617c478bd9Sstevel@tonic-gate * If c is neither < nor >, then this is a lisp aligning =. 5627c478bd9Sstevel@tonic-gate */ 563f6db9f27Scf46844 void 564f6db9f27Scf46844 shift(int c, int cnt) 5657c478bd9Sstevel@tonic-gate { 566f6db9f27Scf46844 line *addr; 567f6db9f27Scf46844 unsigned char *cp; 5687c478bd9Sstevel@tonic-gate unsigned char *dp; 569f6db9f27Scf46844 int i; 5707c478bd9Sstevel@tonic-gate 5717c478bd9Sstevel@tonic-gate if(FIXUNDO) 5727c478bd9Sstevel@tonic-gate save12(), undkind = UNDCHANGE; 5737c478bd9Sstevel@tonic-gate cnt *= value(vi_SHIFTWIDTH); 5747c478bd9Sstevel@tonic-gate for (addr = addr1; addr <= addr2; addr++) { 5757c478bd9Sstevel@tonic-gate dot = addr; 5767c478bd9Sstevel@tonic-gate if (c == '=' && addr == addr1 && addr != addr2) 5777c478bd9Sstevel@tonic-gate continue; 5787c478bd9Sstevel@tonic-gate getDOT(); 5797c478bd9Sstevel@tonic-gate i = whitecnt(linebuf); 5807c478bd9Sstevel@tonic-gate switch (c) { 5817c478bd9Sstevel@tonic-gate 5827c478bd9Sstevel@tonic-gate case '>': 5837c478bd9Sstevel@tonic-gate if (linebuf[0] == 0) 5847c478bd9Sstevel@tonic-gate continue; 5857c478bd9Sstevel@tonic-gate cp = genindent(i + cnt); 5867c478bd9Sstevel@tonic-gate break; 5877c478bd9Sstevel@tonic-gate 5887c478bd9Sstevel@tonic-gate case '<': 5897c478bd9Sstevel@tonic-gate if (i == 0) 5907c478bd9Sstevel@tonic-gate continue; 5917c478bd9Sstevel@tonic-gate i -= cnt; 5927c478bd9Sstevel@tonic-gate cp = i > 0 ? genindent(i) : genbuf; 5937c478bd9Sstevel@tonic-gate break; 5947c478bd9Sstevel@tonic-gate 5957c478bd9Sstevel@tonic-gate default: 5967c478bd9Sstevel@tonic-gate i = lindent(addr); 5977c478bd9Sstevel@tonic-gate getDOT(); 5987c478bd9Sstevel@tonic-gate cp = genindent(i); 5997c478bd9Sstevel@tonic-gate break; 6007c478bd9Sstevel@tonic-gate } 6017c478bd9Sstevel@tonic-gate if (cp + strlen(dp = vpastwh(linebuf)) >= &genbuf[LBSIZE - 2]) 6027c478bd9Sstevel@tonic-gate error(value(vi_TERSE) ? gettext("Line too long") : 6037c478bd9Sstevel@tonic-gate gettext("Result line after shift would be too long")); 6047c478bd9Sstevel@tonic-gate CP(cp, dp); 6057c478bd9Sstevel@tonic-gate strcLIN(genbuf); 6067c478bd9Sstevel@tonic-gate putmark(addr); 6077c478bd9Sstevel@tonic-gate } 6087c478bd9Sstevel@tonic-gate killed(); 6097c478bd9Sstevel@tonic-gate } 6107c478bd9Sstevel@tonic-gate 6117c478bd9Sstevel@tonic-gate /* 6127c478bd9Sstevel@tonic-gate * Find a tag in the tags file. 6137c478bd9Sstevel@tonic-gate * Most work here is in parsing the tags file itself. 6147c478bd9Sstevel@tonic-gate */ 615f6db9f27Scf46844 void 6167c478bd9Sstevel@tonic-gate tagfind(quick) 6177c478bd9Sstevel@tonic-gate bool quick; 6187c478bd9Sstevel@tonic-gate { 6197c478bd9Sstevel@tonic-gate unsigned char cmdbuf[BUFSIZE]; 6207c478bd9Sstevel@tonic-gate unsigned char filebuf[FNSIZE]; 6217c478bd9Sstevel@tonic-gate unsigned char tagfbuf[BUFSIZE]; 622f6db9f27Scf46844 int c, d; 6237c478bd9Sstevel@tonic-gate bool samef = 1; 6247c478bd9Sstevel@tonic-gate int tfcount = 0; 6257c478bd9Sstevel@tonic-gate int omagic, tl; 6267c478bd9Sstevel@tonic-gate unsigned char *fn, *fne; 6277c478bd9Sstevel@tonic-gate #ifdef STDIO /* was VMUNIX */ 6287c478bd9Sstevel@tonic-gate /* 6297c478bd9Sstevel@tonic-gate * We have lots of room so we bring in stdio and do 6307c478bd9Sstevel@tonic-gate * a binary search on the tags file. 6317c478bd9Sstevel@tonic-gate */ 6327c478bd9Sstevel@tonic-gate FILE *iof; 6337c478bd9Sstevel@tonic-gate unsigned char iofbuf[BUFSIZE]; 6347c478bd9Sstevel@tonic-gate off64_t mid; /* assumed byte offset */ 6357c478bd9Sstevel@tonic-gate off64_t top, bot; /* length of tag file */ 6367c478bd9Sstevel@tonic-gate struct stat64 sbuf; 6377c478bd9Sstevel@tonic-gate #endif 6387c478bd9Sstevel@tonic-gate 6397c478bd9Sstevel@tonic-gate omagic = value(vi_MAGIC); 6407c478bd9Sstevel@tonic-gate tl = value(vi_TAGLENGTH); 6417c478bd9Sstevel@tonic-gate if (!skipend()) { 642f6db9f27Scf46844 unsigned char *lp = lasttag; 6437c478bd9Sstevel@tonic-gate 6447c478bd9Sstevel@tonic-gate while (!iswhite(peekchar()) && !endcmd(peekchar())) 6457c478bd9Sstevel@tonic-gate if (lp < &lasttag[sizeof lasttag - 2]) 6467c478bd9Sstevel@tonic-gate *lp++ = getchar(); 6477c478bd9Sstevel@tonic-gate else 6487c478bd9Sstevel@tonic-gate ignchar(); 6497c478bd9Sstevel@tonic-gate *lp++ = 0; 6507c478bd9Sstevel@tonic-gate if (!endcmd(peekchar())) 6517c478bd9Sstevel@tonic-gate badtag: 6527c478bd9Sstevel@tonic-gate error(value(vi_TERSE) ? gettext("Bad tag") : 6537c478bd9Sstevel@tonic-gate gettext("Give one tag per line")); 6547c478bd9Sstevel@tonic-gate } else if (lasttag[0] == 0) 6557c478bd9Sstevel@tonic-gate error(gettext("No previous tag")); 6567c478bd9Sstevel@tonic-gate c = getchar(); 6577c478bd9Sstevel@tonic-gate if (!endcmd(c)) 6587c478bd9Sstevel@tonic-gate goto badtag; 6597c478bd9Sstevel@tonic-gate if (c == EOF) 6607c478bd9Sstevel@tonic-gate ungetchar(c); 6617c478bd9Sstevel@tonic-gate clrstats(); 6627c478bd9Sstevel@tonic-gate 6637c478bd9Sstevel@tonic-gate /* 6647c478bd9Sstevel@tonic-gate * Loop once for each file in tags "path". 6657c478bd9Sstevel@tonic-gate * 6667c478bd9Sstevel@tonic-gate * System tags array limits to 4k (tags[ONMSZ]) long, 6677c478bd9Sstevel@tonic-gate * therefore, tagfbuf should be able to hold all tags. 6687c478bd9Sstevel@tonic-gate */ 6697c478bd9Sstevel@tonic-gate 6707c478bd9Sstevel@tonic-gate CP(tagfbuf, svalue(vi_TAGS)); 6717c478bd9Sstevel@tonic-gate fne = tagfbuf - 1; 6727c478bd9Sstevel@tonic-gate while (fne) { 6737c478bd9Sstevel@tonic-gate fn = ++fne; 6747c478bd9Sstevel@tonic-gate while (*fne && *fne != ' ') 6757c478bd9Sstevel@tonic-gate fne++; 6767c478bd9Sstevel@tonic-gate if (*fne == 0) 6777c478bd9Sstevel@tonic-gate fne = 0; /* done, quit after this time */ 6787c478bd9Sstevel@tonic-gate else 6797c478bd9Sstevel@tonic-gate *fne = 0; /* null terminate filename */ 6807c478bd9Sstevel@tonic-gate #ifdef STDIO /* was VMUNIX */ 6817c478bd9Sstevel@tonic-gate iof = fopen((char *)fn, "r"); 6827c478bd9Sstevel@tonic-gate if (iof == NULL) 6837c478bd9Sstevel@tonic-gate continue; 6847c478bd9Sstevel@tonic-gate tfcount++; 6857c478bd9Sstevel@tonic-gate setbuf(iof, (char *)iofbuf); 6867c478bd9Sstevel@tonic-gate fstat64(fileno(iof), &sbuf); 6877c478bd9Sstevel@tonic-gate top = sbuf.st_size; 6887c478bd9Sstevel@tonic-gate if (top == 0L || iof == NULL) 6897c478bd9Sstevel@tonic-gate top = -1L; 6907c478bd9Sstevel@tonic-gate bot = 0L; 6917c478bd9Sstevel@tonic-gate while (top >= bot) { 6927c478bd9Sstevel@tonic-gate /* loop for each tags file entry */ 693f6db9f27Scf46844 unsigned char *cp = linebuf; 694f6db9f27Scf46844 unsigned char *lp = lasttag; 6957c478bd9Sstevel@tonic-gate unsigned char *oglobp; 6967c478bd9Sstevel@tonic-gate 6977c478bd9Sstevel@tonic-gate mid = (top + bot) / 2; 6987c478bd9Sstevel@tonic-gate fseeko64(iof, mid, 0); 6997c478bd9Sstevel@tonic-gate if (mid > 0) /* to get first tag in file to work */ 7007c478bd9Sstevel@tonic-gate /* scan to next \n */ 7017c478bd9Sstevel@tonic-gate if(fgets((char *)linebuf, sizeof linebuf, iof)==NULL) 7027c478bd9Sstevel@tonic-gate goto goleft; 7037c478bd9Sstevel@tonic-gate /* get the line itself */ 7047c478bd9Sstevel@tonic-gate if(fgets((char *)linebuf, sizeof linebuf, iof)==NULL) 7057c478bd9Sstevel@tonic-gate goto goleft; 7067c478bd9Sstevel@tonic-gate linebuf[strlen(linebuf)-1] = 0; /* was '\n' */ 7077c478bd9Sstevel@tonic-gate while (*cp && *lp == *cp) 7087c478bd9Sstevel@tonic-gate cp++, lp++; 7097c478bd9Sstevel@tonic-gate /* 7107c478bd9Sstevel@tonic-gate * This if decides whether there is a tag match. 7117c478bd9Sstevel@tonic-gate * A positive taglength means that a 7127c478bd9Sstevel@tonic-gate * match is found if the tag given matches at least 7137c478bd9Sstevel@tonic-gate * taglength chars of the tag found. 7147c478bd9Sstevel@tonic-gate * A taglength of greater than 511 means that a 7157c478bd9Sstevel@tonic-gate * match is found even if the tag given is a proper 7167c478bd9Sstevel@tonic-gate * prefix of the tag found. i.e. "ab" matches "abcd" 7177c478bd9Sstevel@tonic-gate */ 7187c478bd9Sstevel@tonic-gate if ( *lp == 0 && (iswhite(*cp) || tl > 511 || tl > 0 && lp-lasttag >= tl) ) { 7197c478bd9Sstevel@tonic-gate /* 7207c478bd9Sstevel@tonic-gate * Found a match. Force selection to be 7217c478bd9Sstevel@tonic-gate * the first possible. 7227c478bd9Sstevel@tonic-gate */ 7237c478bd9Sstevel@tonic-gate if ( mid == bot && mid == top ) { 7247c478bd9Sstevel@tonic-gate ; /* found first possible match */ 7257c478bd9Sstevel@tonic-gate } 7267c478bd9Sstevel@tonic-gate else { 7277c478bd9Sstevel@tonic-gate /* postpone final decision. */ 7287c478bd9Sstevel@tonic-gate top = mid; 7297c478bd9Sstevel@tonic-gate continue; 7307c478bd9Sstevel@tonic-gate } 7317c478bd9Sstevel@tonic-gate } 7327c478bd9Sstevel@tonic-gate else { 7337c478bd9Sstevel@tonic-gate if ((int)*lp > (int)*cp) 7347c478bd9Sstevel@tonic-gate bot = mid + 1; 7357c478bd9Sstevel@tonic-gate else 7367c478bd9Sstevel@tonic-gate goleft: 7377c478bd9Sstevel@tonic-gate top = mid - 1; 7387c478bd9Sstevel@tonic-gate continue; 7397c478bd9Sstevel@tonic-gate } 7407c478bd9Sstevel@tonic-gate /* 7417c478bd9Sstevel@tonic-gate * We found the tag. Decode the line in the file. 7427c478bd9Sstevel@tonic-gate */ 7437c478bd9Sstevel@tonic-gate fclose(iof); 7447c478bd9Sstevel@tonic-gate 7457c478bd9Sstevel@tonic-gate /* Rest of tag if abbreviated */ 7467c478bd9Sstevel@tonic-gate while (!iswhite(*cp)) 7477c478bd9Sstevel@tonic-gate cp++; 7487c478bd9Sstevel@tonic-gate 7497c478bd9Sstevel@tonic-gate /* name of file */ 7507c478bd9Sstevel@tonic-gate while (*cp && iswhite(*cp)) 7517c478bd9Sstevel@tonic-gate cp++; 7527c478bd9Sstevel@tonic-gate if (!*cp) 7537c478bd9Sstevel@tonic-gate badtags: 754f6db9f27Scf46844 serror((unsigned char *) 755f6db9f27Scf46844 gettext("%s: Bad tags file entry"), 756f6db9f27Scf46844 lasttag); 7577c478bd9Sstevel@tonic-gate lp = filebuf; 7587c478bd9Sstevel@tonic-gate while (*cp && *cp != ' ' && *cp != '\t') { 7597c478bd9Sstevel@tonic-gate if (lp < &filebuf[sizeof filebuf - 2]) 7607c478bd9Sstevel@tonic-gate *lp++ = *cp; 7617c478bd9Sstevel@tonic-gate cp++; 7627c478bd9Sstevel@tonic-gate } 7637c478bd9Sstevel@tonic-gate *lp++ = 0; 7647c478bd9Sstevel@tonic-gate 7657c478bd9Sstevel@tonic-gate if (*cp == 0) 7667c478bd9Sstevel@tonic-gate goto badtags; 7677c478bd9Sstevel@tonic-gate if (dol != zero) { 7687c478bd9Sstevel@tonic-gate /* 7697c478bd9Sstevel@tonic-gate * Save current position in 't for ^^ in visual. 7707c478bd9Sstevel@tonic-gate */ 7717c478bd9Sstevel@tonic-gate names['t'-'a'] = *dot &~ 01; 7727c478bd9Sstevel@tonic-gate if (inopen) { 7737c478bd9Sstevel@tonic-gate extern unsigned char *ncols['z'-'a'+2]; 7747c478bd9Sstevel@tonic-gate extern unsigned char *cursor; 7757c478bd9Sstevel@tonic-gate 7767c478bd9Sstevel@tonic-gate ncols['t'-'a'] = cursor; 7777c478bd9Sstevel@tonic-gate } 7787c478bd9Sstevel@tonic-gate } 7797c478bd9Sstevel@tonic-gate #ifdef TAG_STACK 7807c478bd9Sstevel@tonic-gate if (*savedfile) { 781f6db9f27Scf46844 savetag((char *)savedfile); 7827c478bd9Sstevel@tonic-gate } 7837c478bd9Sstevel@tonic-gate #endif 7847c478bd9Sstevel@tonic-gate strcpy(cmdbuf, cp); 7857c478bd9Sstevel@tonic-gate if (strcmp(filebuf, savedfile) || !edited) { 7867c478bd9Sstevel@tonic-gate unsigned char cmdbuf2[sizeof filebuf + 10]; 7877c478bd9Sstevel@tonic-gate 7887c478bd9Sstevel@tonic-gate /* Different file. Do autowrite & get it. */ 7897c478bd9Sstevel@tonic-gate if (!quick) { 7907c478bd9Sstevel@tonic-gate ckaw(); 7917c478bd9Sstevel@tonic-gate if (chng && dol > zero) { 7927c478bd9Sstevel@tonic-gate #ifdef TAG_STACK 7937c478bd9Sstevel@tonic-gate unsavetag(); 7947c478bd9Sstevel@tonic-gate #endif 7957c478bd9Sstevel@tonic-gate error(value(vi_TERSE) ? 7967c478bd9Sstevel@tonic-gate gettext("No write") : gettext("No write since last change (:tag! overrides)")); 7977c478bd9Sstevel@tonic-gate } 7987c478bd9Sstevel@tonic-gate } 7997c478bd9Sstevel@tonic-gate oglobp = globp; 8007c478bd9Sstevel@tonic-gate strcpy(cmdbuf2, "e! "); 8017c478bd9Sstevel@tonic-gate strcat(cmdbuf2, filebuf); 8027c478bd9Sstevel@tonic-gate globp = cmdbuf2; 8037c478bd9Sstevel@tonic-gate d = peekc; ungetchar(0); 8047c478bd9Sstevel@tonic-gate commands(1, 1); 8057c478bd9Sstevel@tonic-gate peekc = d; 8067c478bd9Sstevel@tonic-gate globp = oglobp; 8077c478bd9Sstevel@tonic-gate value(vi_MAGIC) = omagic; 8087c478bd9Sstevel@tonic-gate samef = 0; 8097c478bd9Sstevel@tonic-gate } 8107c478bd9Sstevel@tonic-gate 8117c478bd9Sstevel@tonic-gate /* 8127c478bd9Sstevel@tonic-gate * Look for pattern in the current file. 8137c478bd9Sstevel@tonic-gate */ 8147c478bd9Sstevel@tonic-gate oglobp = globp; 8157c478bd9Sstevel@tonic-gate globp = cmdbuf; 8167c478bd9Sstevel@tonic-gate d = peekc; ungetchar(0); 8177c478bd9Sstevel@tonic-gate if (samef) 8187c478bd9Sstevel@tonic-gate markpr(dot); 8197c478bd9Sstevel@tonic-gate /* 8207c478bd9Sstevel@tonic-gate * BUG: if it isn't found (user edited header 8217c478bd9Sstevel@tonic-gate * line) we get left in nomagic mode. 8227c478bd9Sstevel@tonic-gate */ 8237c478bd9Sstevel@tonic-gate value(vi_MAGIC) = 0; 8247c478bd9Sstevel@tonic-gate commands(1, 1); 8257c478bd9Sstevel@tonic-gate peekc = d; 8267c478bd9Sstevel@tonic-gate globp = oglobp; 8277c478bd9Sstevel@tonic-gate value(vi_MAGIC) = omagic; 8287c478bd9Sstevel@tonic-gate return; 8297c478bd9Sstevel@tonic-gate } /* end of "for each tag in file" */ 8307c478bd9Sstevel@tonic-gate #endif /* STDIO */ 8317c478bd9Sstevel@tonic-gate /* 8327c478bd9Sstevel@tonic-gate * Binary search failed, so try linear search if -S is on. 8337c478bd9Sstevel@tonic-gate * -S is needed for tags files that are not sorted. 8347c478bd9Sstevel@tonic-gate */ 8357c478bd9Sstevel@tonic-gate 8367c478bd9Sstevel@tonic-gate /* 8377c478bd9Sstevel@tonic-gate * Avoid stdio and scan tag file linearly. 8387c478bd9Sstevel@tonic-gate */ 8397c478bd9Sstevel@tonic-gate if (tags_flag == 0) 8407c478bd9Sstevel@tonic-gate continue; 8417c478bd9Sstevel@tonic-gate io = open(fn, 0); 8427c478bd9Sstevel@tonic-gate if (io < 0) 8437c478bd9Sstevel@tonic-gate continue; 8447c478bd9Sstevel@tonic-gate /* tfcount++; */ 8457c478bd9Sstevel@tonic-gate while (getfile() == 0) { 8467c478bd9Sstevel@tonic-gate /* loop for each tags file entry */ 847f6db9f27Scf46844 unsigned char *cp = linebuf; 848f6db9f27Scf46844 unsigned char *lp = lasttag; 8497c478bd9Sstevel@tonic-gate unsigned char *oglobp; 8507c478bd9Sstevel@tonic-gate 8517c478bd9Sstevel@tonic-gate while (*cp && *lp == *cp) 8527c478bd9Sstevel@tonic-gate cp++, lp++; 8537c478bd9Sstevel@tonic-gate /* 8547c478bd9Sstevel@tonic-gate * This if decides whether there is a tag match. 8557c478bd9Sstevel@tonic-gate * A positive taglength means that a 8567c478bd9Sstevel@tonic-gate * match is found if the tag given matches at least 8577c478bd9Sstevel@tonic-gate * taglength chars of the tag found. 8587c478bd9Sstevel@tonic-gate * A taglength of greater than 511 means that a 8597c478bd9Sstevel@tonic-gate * match is found even if the tag given is a proper 8607c478bd9Sstevel@tonic-gate * prefix of the tag found. i.e. "ab" matches "abcd" 8617c478bd9Sstevel@tonic-gate */ 8627c478bd9Sstevel@tonic-gate if ( *lp == 0 && (iswhite(*cp) || tl > 511 || tl > 0 && lp-lasttag >= tl) ) { 8637c478bd9Sstevel@tonic-gate ; /* Found it. */ 8647c478bd9Sstevel@tonic-gate } 8657c478bd9Sstevel@tonic-gate else { 8667c478bd9Sstevel@tonic-gate /* Not this tag. Try the next */ 8677c478bd9Sstevel@tonic-gate continue; 8687c478bd9Sstevel@tonic-gate } 8697c478bd9Sstevel@tonic-gate /* 8707c478bd9Sstevel@tonic-gate * We found the tag. Decode the line in the file. 8717c478bd9Sstevel@tonic-gate */ 8727c478bd9Sstevel@tonic-gate close(io); 8737c478bd9Sstevel@tonic-gate /* Rest of tag if abbreviated */ 8747c478bd9Sstevel@tonic-gate while (!iswhite(*cp)) 8757c478bd9Sstevel@tonic-gate cp++; 8767c478bd9Sstevel@tonic-gate 8777c478bd9Sstevel@tonic-gate /* name of file */ 8787c478bd9Sstevel@tonic-gate while (*cp && iswhite(*cp)) 8797c478bd9Sstevel@tonic-gate cp++; 8807c478bd9Sstevel@tonic-gate if (!*cp) 8817c478bd9Sstevel@tonic-gate badtags2: 882f6db9f27Scf46844 serror((unsigned char *) 883f6db9f27Scf46844 gettext("%s: Bad tags file entry"), 884f6db9f27Scf46844 lasttag); 8857c478bd9Sstevel@tonic-gate lp = filebuf; 8867c478bd9Sstevel@tonic-gate while (*cp && *cp != ' ' && *cp != '\t') { 8877c478bd9Sstevel@tonic-gate if (lp < &filebuf[sizeof filebuf - 2]) 8887c478bd9Sstevel@tonic-gate *lp++ = *cp; 8897c478bd9Sstevel@tonic-gate cp++; 8907c478bd9Sstevel@tonic-gate } 8917c478bd9Sstevel@tonic-gate *lp++ = 0; 8927c478bd9Sstevel@tonic-gate 8937c478bd9Sstevel@tonic-gate if (*cp == 0) 8947c478bd9Sstevel@tonic-gate goto badtags2; 8957c478bd9Sstevel@tonic-gate if (dol != zero) { 8967c478bd9Sstevel@tonic-gate /* 8977c478bd9Sstevel@tonic-gate * Save current position in 't for ^^ in visual. 8987c478bd9Sstevel@tonic-gate */ 8997c478bd9Sstevel@tonic-gate names['t'-'a'] = *dot &~ 01; 9007c478bd9Sstevel@tonic-gate if (inopen) { 9017c478bd9Sstevel@tonic-gate extern unsigned char *ncols['z'-'a'+2]; 9027c478bd9Sstevel@tonic-gate extern unsigned char *cursor; 9037c478bd9Sstevel@tonic-gate 9047c478bd9Sstevel@tonic-gate ncols['t'-'a'] = cursor; 9057c478bd9Sstevel@tonic-gate } 9067c478bd9Sstevel@tonic-gate } 9077c478bd9Sstevel@tonic-gate #ifdef TAG_STACK 9087c478bd9Sstevel@tonic-gate if (*savedfile) { 909f6db9f27Scf46844 savetag((char *)savedfile); 9107c478bd9Sstevel@tonic-gate } 9117c478bd9Sstevel@tonic-gate #endif 9127c478bd9Sstevel@tonic-gate strcpy(cmdbuf, cp); 9137c478bd9Sstevel@tonic-gate if (strcmp(filebuf, savedfile) || !edited) { 9147c478bd9Sstevel@tonic-gate unsigned char cmdbuf2[sizeof filebuf + 10]; 9157c478bd9Sstevel@tonic-gate 9167c478bd9Sstevel@tonic-gate /* Different file. Do autowrite & get it. */ 9177c478bd9Sstevel@tonic-gate if (!quick) { 9187c478bd9Sstevel@tonic-gate ckaw(); 9197c478bd9Sstevel@tonic-gate if (chng && dol > zero) { 9207c478bd9Sstevel@tonic-gate #ifdef TAG_STACK 9217c478bd9Sstevel@tonic-gate unsavetag(); 9227c478bd9Sstevel@tonic-gate #endif 9237c478bd9Sstevel@tonic-gate error(value(vi_TERSE) ? 9247c478bd9Sstevel@tonic-gate gettext("No write") : gettext("No write since last change (:tag! overrides)")); 9257c478bd9Sstevel@tonic-gate } 9267c478bd9Sstevel@tonic-gate } 9277c478bd9Sstevel@tonic-gate oglobp = globp; 9287c478bd9Sstevel@tonic-gate strcpy(cmdbuf2, "e! "); 9297c478bd9Sstevel@tonic-gate strcat(cmdbuf2, filebuf); 9307c478bd9Sstevel@tonic-gate globp = cmdbuf2; 9317c478bd9Sstevel@tonic-gate d = peekc; ungetchar(0); 9327c478bd9Sstevel@tonic-gate commands(1, 1); 9337c478bd9Sstevel@tonic-gate peekc = d; 9347c478bd9Sstevel@tonic-gate globp = oglobp; 9357c478bd9Sstevel@tonic-gate value(vi_MAGIC) = omagic; 9367c478bd9Sstevel@tonic-gate samef = 0; 9377c478bd9Sstevel@tonic-gate } 9387c478bd9Sstevel@tonic-gate 9397c478bd9Sstevel@tonic-gate /* 9407c478bd9Sstevel@tonic-gate * Look for pattern in the current file. 9417c478bd9Sstevel@tonic-gate */ 9427c478bd9Sstevel@tonic-gate oglobp = globp; 9437c478bd9Sstevel@tonic-gate globp = cmdbuf; 9447c478bd9Sstevel@tonic-gate d = peekc; ungetchar(0); 9457c478bd9Sstevel@tonic-gate if (samef) 9467c478bd9Sstevel@tonic-gate markpr(dot); 9477c478bd9Sstevel@tonic-gate /* 9487c478bd9Sstevel@tonic-gate * BUG: if it isn't found (user edited header 9497c478bd9Sstevel@tonic-gate * line) we get left in nomagic mode. 9507c478bd9Sstevel@tonic-gate */ 9517c478bd9Sstevel@tonic-gate value(vi_MAGIC) = 0; 9527c478bd9Sstevel@tonic-gate commands(1, 1); 9537c478bd9Sstevel@tonic-gate peekc = d; 9547c478bd9Sstevel@tonic-gate globp = oglobp; 9557c478bd9Sstevel@tonic-gate value(vi_MAGIC) = omagic; 9567c478bd9Sstevel@tonic-gate return; 9577c478bd9Sstevel@tonic-gate } /* end of "for each tag in file" */ 9587c478bd9Sstevel@tonic-gate 9597c478bd9Sstevel@tonic-gate /* 9607c478bd9Sstevel@tonic-gate * No such tag in this file. Close it and try the next. 9617c478bd9Sstevel@tonic-gate */ 9627c478bd9Sstevel@tonic-gate #ifdef STDIO /* was VMUNIX */ 9637c478bd9Sstevel@tonic-gate fclose(iof); 9647c478bd9Sstevel@tonic-gate #else 9657c478bd9Sstevel@tonic-gate close(io); 9667c478bd9Sstevel@tonic-gate #endif 9677c478bd9Sstevel@tonic-gate } /* end of "for each file in path" */ 9687c478bd9Sstevel@tonic-gate if (tfcount <= 0) 9697c478bd9Sstevel@tonic-gate error(gettext("No tags file")); 9707c478bd9Sstevel@tonic-gate else 971f6db9f27Scf46844 serror(value(vi_TERSE) ? 972f6db9f27Scf46844 (unsigned char *)gettext("%s: No such tag") : 973f6db9f27Scf46844 (unsigned char *)gettext("%s: No such tag in tags file"), 974f6db9f27Scf46844 lasttag); 9757c478bd9Sstevel@tonic-gate } 9767c478bd9Sstevel@tonic-gate 9777c478bd9Sstevel@tonic-gate /* 9787c478bd9Sstevel@tonic-gate * Save lines from addr1 thru addr2 as though 9797c478bd9Sstevel@tonic-gate * they had been deleted. 9807c478bd9Sstevel@tonic-gate */ 981f6db9f27Scf46844 int 982f6db9f27Scf46844 yank(void) 9837c478bd9Sstevel@tonic-gate { 9847c478bd9Sstevel@tonic-gate 9857c478bd9Sstevel@tonic-gate if (!FIXUNDO) 9867c478bd9Sstevel@tonic-gate error(gettext("Can't yank inside global/macro")); 9877c478bd9Sstevel@tonic-gate save12(); 9887c478bd9Sstevel@tonic-gate undkind = UNDNONE; 9897c478bd9Sstevel@tonic-gate killcnt(addr2 - addr1 + 1); 990f6db9f27Scf46844 return (0); 9917c478bd9Sstevel@tonic-gate } 9927c478bd9Sstevel@tonic-gate 9937c478bd9Sstevel@tonic-gate /* 9947c478bd9Sstevel@tonic-gate * z command; print windows of text in the file. 9957c478bd9Sstevel@tonic-gate * 9967c478bd9Sstevel@tonic-gate * If this seems unreasonably arcane, the reasons 9977c478bd9Sstevel@tonic-gate * are historical. This is one of the first commands 9987c478bd9Sstevel@tonic-gate * added to the first ex (then called en) and the 9997c478bd9Sstevel@tonic-gate * number of facilities here were the major advantage 10007c478bd9Sstevel@tonic-gate * of en over ed since they allowed more use to be 10017c478bd9Sstevel@tonic-gate * made of fast terminals w/o typing .,.22p all the time. 10027c478bd9Sstevel@tonic-gate */ 10037c478bd9Sstevel@tonic-gate bool zhadpr; 10047c478bd9Sstevel@tonic-gate bool znoclear; 10057c478bd9Sstevel@tonic-gate short zweight; 10067c478bd9Sstevel@tonic-gate 1007f6db9f27Scf46844 void 1008f6db9f27Scf46844 zop(int hadpr) 10097c478bd9Sstevel@tonic-gate { 1010f6db9f27Scf46844 int c, nlines, op; 10117c478bd9Sstevel@tonic-gate bool excl; 10127c478bd9Sstevel@tonic-gate 10137c478bd9Sstevel@tonic-gate zhadpr = hadpr; 10147c478bd9Sstevel@tonic-gate notempty(); 10157c478bd9Sstevel@tonic-gate znoclear = 0; 10167c478bd9Sstevel@tonic-gate zweight = 0; 10177c478bd9Sstevel@tonic-gate excl = exclam(); 10187c478bd9Sstevel@tonic-gate switch (c = op = getchar()) { 10197c478bd9Sstevel@tonic-gate 10207c478bd9Sstevel@tonic-gate case '^': 10217c478bd9Sstevel@tonic-gate zweight = 1; 10227c478bd9Sstevel@tonic-gate case '-': 10237c478bd9Sstevel@tonic-gate case '+': 10247c478bd9Sstevel@tonic-gate while (peekchar() == op) { 10257c478bd9Sstevel@tonic-gate ignchar(); 10267c478bd9Sstevel@tonic-gate zweight++; 10277c478bd9Sstevel@tonic-gate } 10287c478bd9Sstevel@tonic-gate case '=': 10297c478bd9Sstevel@tonic-gate case '.': 10307c478bd9Sstevel@tonic-gate c = getchar(); 10317c478bd9Sstevel@tonic-gate break; 10327c478bd9Sstevel@tonic-gate 10337c478bd9Sstevel@tonic-gate case EOF: 10347c478bd9Sstevel@tonic-gate znoclear++; 10357c478bd9Sstevel@tonic-gate break; 10367c478bd9Sstevel@tonic-gate 10377c478bd9Sstevel@tonic-gate default: 10387c478bd9Sstevel@tonic-gate op = 0; 10397c478bd9Sstevel@tonic-gate break; 10407c478bd9Sstevel@tonic-gate } 10417c478bd9Sstevel@tonic-gate if (isdigit(c)) { 10427c478bd9Sstevel@tonic-gate nlines = c - '0'; 10437c478bd9Sstevel@tonic-gate for(;;) { 10447c478bd9Sstevel@tonic-gate c = getchar(); 10457c478bd9Sstevel@tonic-gate if (!isdigit(c)) 10467c478bd9Sstevel@tonic-gate break; 10477c478bd9Sstevel@tonic-gate nlines *= 10; 10487c478bd9Sstevel@tonic-gate nlines += c - '0'; 10497c478bd9Sstevel@tonic-gate } 10507c478bd9Sstevel@tonic-gate if (nlines < lines) 10517c478bd9Sstevel@tonic-gate znoclear++; 10527c478bd9Sstevel@tonic-gate value(vi_WINDOW) = nlines; 10537c478bd9Sstevel@tonic-gate if (op == '=') 10547c478bd9Sstevel@tonic-gate nlines += 2; 10557c478bd9Sstevel@tonic-gate } 10567c478bd9Sstevel@tonic-gate else { 10577c478bd9Sstevel@tonic-gate nlines = op == EOF ? value(vi_SCROLL) : 10587c478bd9Sstevel@tonic-gate excl ? lines - 1 : value(vi_WINDOW); 10597c478bd9Sstevel@tonic-gate } 10607c478bd9Sstevel@tonic-gate if (inopen || c != EOF) { 10617c478bd9Sstevel@tonic-gate ungetchar(c); 10627c478bd9Sstevel@tonic-gate donewline(); 10637c478bd9Sstevel@tonic-gate } 10647c478bd9Sstevel@tonic-gate addr1 = addr2; 10657c478bd9Sstevel@tonic-gate if (addr2 == 0 && dot < dol && op == 0) 10667c478bd9Sstevel@tonic-gate addr1 = addr2 = dot+1; 10677c478bd9Sstevel@tonic-gate setdot(); 10687c478bd9Sstevel@tonic-gate zop2(nlines, op); 10697c478bd9Sstevel@tonic-gate } 10707c478bd9Sstevel@tonic-gate 1071f6db9f27Scf46844 void 1072f6db9f27Scf46844 zop2(int nlines, int op) 10737c478bd9Sstevel@tonic-gate { 1074f6db9f27Scf46844 line *split; 10757c478bd9Sstevel@tonic-gate 10767c478bd9Sstevel@tonic-gate split = NULL; 10777c478bd9Sstevel@tonic-gate switch (op) { 10787c478bd9Sstevel@tonic-gate 10797c478bd9Sstevel@tonic-gate case EOF: 10807c478bd9Sstevel@tonic-gate if (addr2 == dol) 10817c478bd9Sstevel@tonic-gate error(gettext("\nAt EOF")); 10827c478bd9Sstevel@tonic-gate case '+': 10837c478bd9Sstevel@tonic-gate if (addr2 == dol) 10847c478bd9Sstevel@tonic-gate error(gettext("At EOF")); 10857c478bd9Sstevel@tonic-gate addr2 += nlines * zweight; 10867c478bd9Sstevel@tonic-gate if (addr2 > dol) 10877c478bd9Sstevel@tonic-gate error(gettext("Hit BOTTOM")); 10887c478bd9Sstevel@tonic-gate addr2++; 10897c478bd9Sstevel@tonic-gate default: 10907c478bd9Sstevel@tonic-gate addr1 = addr2; 10917c478bd9Sstevel@tonic-gate addr2 += nlines-1; 10927c478bd9Sstevel@tonic-gate dot = addr2; 10937c478bd9Sstevel@tonic-gate break; 10947c478bd9Sstevel@tonic-gate 10957c478bd9Sstevel@tonic-gate case '=': 10967c478bd9Sstevel@tonic-gate case '.': 10977c478bd9Sstevel@tonic-gate znoclear = 0; 10987c478bd9Sstevel@tonic-gate nlines--; 10997c478bd9Sstevel@tonic-gate nlines >>= 1; 11007c478bd9Sstevel@tonic-gate if (op == '=') 11017c478bd9Sstevel@tonic-gate nlines--; 11027c478bd9Sstevel@tonic-gate addr1 = addr2 - nlines; 11037c478bd9Sstevel@tonic-gate if (op == '=') 11047c478bd9Sstevel@tonic-gate dot = split = addr2; 11057c478bd9Sstevel@tonic-gate addr2 += nlines; 11067c478bd9Sstevel@tonic-gate if (op == '.') { 11077c478bd9Sstevel@tonic-gate markDOT(); 11087c478bd9Sstevel@tonic-gate dot = addr2; 11097c478bd9Sstevel@tonic-gate } 11107c478bd9Sstevel@tonic-gate break; 11117c478bd9Sstevel@tonic-gate 11127c478bd9Sstevel@tonic-gate case '^': 11137c478bd9Sstevel@tonic-gate case '-': 11147c478bd9Sstevel@tonic-gate addr2 -= nlines * zweight; 11157c478bd9Sstevel@tonic-gate if (addr2 < one) 11167c478bd9Sstevel@tonic-gate error(gettext("Hit TOP")); 11177c478bd9Sstevel@tonic-gate nlines--; 11187c478bd9Sstevel@tonic-gate addr1 = addr2 - nlines; 11197c478bd9Sstevel@tonic-gate dot = addr2; 11207c478bd9Sstevel@tonic-gate break; 11217c478bd9Sstevel@tonic-gate } 11227c478bd9Sstevel@tonic-gate if (addr1 <= zero) 11237c478bd9Sstevel@tonic-gate addr1 = one; 11247c478bd9Sstevel@tonic-gate if (addr2 > dol) 11257c478bd9Sstevel@tonic-gate addr2 = dol; 11267c478bd9Sstevel@tonic-gate if (dot > dol) 11277c478bd9Sstevel@tonic-gate dot = dol; 11287c478bd9Sstevel@tonic-gate if (addr1 > addr2) 11297c478bd9Sstevel@tonic-gate return; 11307c478bd9Sstevel@tonic-gate if (op == EOF && zhadpr) { 113123a1cceaSRoger A. Faulkner getaline(*addr1); 11327c478bd9Sstevel@tonic-gate putchar((int)('\r' | QUOTE)); 11337c478bd9Sstevel@tonic-gate shudclob = 1; 11347c478bd9Sstevel@tonic-gate } else if (znoclear == 0 && clear_screen != NOSTR && !inopen) { 11357c478bd9Sstevel@tonic-gate flush1(); 11367c478bd9Sstevel@tonic-gate vclear(); 11377c478bd9Sstevel@tonic-gate } 11387c478bd9Sstevel@tonic-gate if (addr2 - addr1 > 1) 11397c478bd9Sstevel@tonic-gate pstart(); 11407c478bd9Sstevel@tonic-gate if (split) { 11417c478bd9Sstevel@tonic-gate plines(addr1, split - 1, 0); 11427c478bd9Sstevel@tonic-gate splitit(); 11437c478bd9Sstevel@tonic-gate plines(split, split, 0); 11447c478bd9Sstevel@tonic-gate splitit(); 11457c478bd9Sstevel@tonic-gate addr1 = split + 1; 11467c478bd9Sstevel@tonic-gate } 11477c478bd9Sstevel@tonic-gate plines(addr1, addr2, 0); 11487c478bd9Sstevel@tonic-gate } 11497c478bd9Sstevel@tonic-gate 1150f6db9f27Scf46844 static void 1151f6db9f27Scf46844 splitit(void) 11527c478bd9Sstevel@tonic-gate { 1153f6db9f27Scf46844 int l; 11547c478bd9Sstevel@tonic-gate 11557c478bd9Sstevel@tonic-gate for (l = columns > 80 ? 40 : columns / 2; l > 0; l--) 11567c478bd9Sstevel@tonic-gate putchar('-'); 11577c478bd9Sstevel@tonic-gate putnl(); 11587c478bd9Sstevel@tonic-gate } 11597c478bd9Sstevel@tonic-gate 1160f6db9f27Scf46844 void 1161f6db9f27Scf46844 plines(line *adr1, line *adr2, bool movedot) 11627c478bd9Sstevel@tonic-gate { 1163f6db9f27Scf46844 line *addr; 11647c478bd9Sstevel@tonic-gate 11657c478bd9Sstevel@tonic-gate pofix(); 11667c478bd9Sstevel@tonic-gate for (addr = adr1; addr <= adr2; addr++) { 116723a1cceaSRoger A. Faulkner getaline(*addr); 11687c478bd9Sstevel@tonic-gate pline(lineno(addr)); 11697c478bd9Sstevel@tonic-gate if (inopen) 11707c478bd9Sstevel@tonic-gate putchar((int)('\n' | QUOTE)); 11717c478bd9Sstevel@tonic-gate if (movedot) 11727c478bd9Sstevel@tonic-gate dot = addr; 11737c478bd9Sstevel@tonic-gate } 11747c478bd9Sstevel@tonic-gate } 11757c478bd9Sstevel@tonic-gate 1176f6db9f27Scf46844 void 1177f6db9f27Scf46844 pofix(void) 11787c478bd9Sstevel@tonic-gate { 11797c478bd9Sstevel@tonic-gate 11807c478bd9Sstevel@tonic-gate if (inopen && Outchar != termchar) { 11817c478bd9Sstevel@tonic-gate vnfl(); 11827c478bd9Sstevel@tonic-gate setoutt(); 11837c478bd9Sstevel@tonic-gate } 11847c478bd9Sstevel@tonic-gate } 11857c478bd9Sstevel@tonic-gate 11867c478bd9Sstevel@tonic-gate /* 11877c478bd9Sstevel@tonic-gate * Command level undo works easily because 11887c478bd9Sstevel@tonic-gate * the editor has a unique temporary file 11897c478bd9Sstevel@tonic-gate * index for every line which ever existed. 11907c478bd9Sstevel@tonic-gate * We don't have to save large blocks of text, 11917c478bd9Sstevel@tonic-gate * only the indices which are small. We do this 11927c478bd9Sstevel@tonic-gate * by moving them to after the last line in the 11937c478bd9Sstevel@tonic-gate * line buffer array, and marking down info 11947c478bd9Sstevel@tonic-gate * about whence they came. 11957c478bd9Sstevel@tonic-gate * 11967c478bd9Sstevel@tonic-gate * Undo is its own inverse. 11977c478bd9Sstevel@tonic-gate */ 1198f6db9f27Scf46844 void 1199f6db9f27Scf46844 undo(bool c) 12007c478bd9Sstevel@tonic-gate { 1201f6db9f27Scf46844 int i, k; 1202f6db9f27Scf46844 line *jp, *kp, *j; 12037c478bd9Sstevel@tonic-gate line *dolp1, *newdol, *newadot; 12047c478bd9Sstevel@tonic-gate 12057c478bd9Sstevel@tonic-gate #ifdef UNDOTRACE 12067c478bd9Sstevel@tonic-gate if (trace) 12077c478bd9Sstevel@tonic-gate vudump("before undo"); 12087c478bd9Sstevel@tonic-gate #endif 12097c478bd9Sstevel@tonic-gate if (inglobal && inopen <= 0) 12107c478bd9Sstevel@tonic-gate error(value(vi_TERSE) ? gettext("Can't undo in global") : 12117c478bd9Sstevel@tonic-gate gettext("Can't undo in global commands")); 12127c478bd9Sstevel@tonic-gate 12137c478bd9Sstevel@tonic-gate /* 12147c478bd9Sstevel@tonic-gate * Unless flag indicates a forced undo, make sure 12157c478bd9Sstevel@tonic-gate * there really was a change before trying to undo it. 12167c478bd9Sstevel@tonic-gate */ 12177c478bd9Sstevel@tonic-gate 12187c478bd9Sstevel@tonic-gate if (!c) 12197c478bd9Sstevel@tonic-gate somechange(); 12207c478bd9Sstevel@tonic-gate 12217c478bd9Sstevel@tonic-gate /* 12227c478bd9Sstevel@tonic-gate * Update change flags. 12237c478bd9Sstevel@tonic-gate */ 12247c478bd9Sstevel@tonic-gate 12257c478bd9Sstevel@tonic-gate pkill[0] = pkill[1] = 0; 12267c478bd9Sstevel@tonic-gate change(); 12277c478bd9Sstevel@tonic-gate if (undkind == UNDMOVE) { 12287c478bd9Sstevel@tonic-gate /* 12297c478bd9Sstevel@tonic-gate * Command to be undone is a move command. 12307c478bd9Sstevel@tonic-gate * This is handled as a special case by noting that 12317c478bd9Sstevel@tonic-gate * a move "a,b m c" can be inverted by another move. 12327c478bd9Sstevel@tonic-gate */ 12337c478bd9Sstevel@tonic-gate if ((i = (jp = unddel) - undap2) > 0) { 12347c478bd9Sstevel@tonic-gate /* 12357c478bd9Sstevel@tonic-gate * when c > b inverse is a+(c-b),c m a-1 12367c478bd9Sstevel@tonic-gate */ 12377c478bd9Sstevel@tonic-gate addr2 = jp; 12387c478bd9Sstevel@tonic-gate addr1 = (jp = undap1) + i; 12397c478bd9Sstevel@tonic-gate unddel = jp-1; 12407c478bd9Sstevel@tonic-gate } else { 12417c478bd9Sstevel@tonic-gate /* 12427c478bd9Sstevel@tonic-gate * when b > c inverse is c+1,c+1+(b-a) m b 12437c478bd9Sstevel@tonic-gate */ 12447c478bd9Sstevel@tonic-gate addr1 = ++jp; 12457c478bd9Sstevel@tonic-gate addr2 = jp + ((unddel = undap2) - undap1); 12467c478bd9Sstevel@tonic-gate } 12477c478bd9Sstevel@tonic-gate kp = undap1; 12487c478bd9Sstevel@tonic-gate move1(0, unddel); 12497c478bd9Sstevel@tonic-gate dot = kp; 12507c478bd9Sstevel@tonic-gate Command = (unsigned char *)"move"; 12517c478bd9Sstevel@tonic-gate killed(); 12527c478bd9Sstevel@tonic-gate } else { 12537c478bd9Sstevel@tonic-gate int cnt; 12547c478bd9Sstevel@tonic-gate 12557c478bd9Sstevel@tonic-gate newadot = dot; 12567c478bd9Sstevel@tonic-gate cnt = lineDOL(); 12577c478bd9Sstevel@tonic-gate newdol = dol; 12587c478bd9Sstevel@tonic-gate dolp1 = dol + 1; 12597c478bd9Sstevel@tonic-gate /* 12607c478bd9Sstevel@tonic-gate * Command to be undone is a non-move. 12617c478bd9Sstevel@tonic-gate * All such commands are treated as a combination of 12627c478bd9Sstevel@tonic-gate * a delete command and a append command. 12637c478bd9Sstevel@tonic-gate * We first move the lines appended by the last command 12647c478bd9Sstevel@tonic-gate * from undap1 to undap2-1 so that they are just before the 12657c478bd9Sstevel@tonic-gate * saved deleted lines. 12667c478bd9Sstevel@tonic-gate * 12677c478bd9Sstevel@tonic-gate * Assume the editor has: 12687c478bd9Sstevel@tonic-gate * 12697c478bd9Sstevel@tonic-gate * cursor is on 'c' 12707c478bd9Sstevel@tonic-gate * 12717c478bd9Sstevel@tonic-gate * (just change lines 5-8) 12727c478bd9Sstevel@tonic-gate * 12737c478bd9Sstevel@tonic-gate * file is: 1) ab 12747c478bd9Sstevel@tonic-gate * 2) cd 12757c478bd9Sstevel@tonic-gate * 3) ef 12767c478bd9Sstevel@tonic-gate * 4) gh 12777c478bd9Sstevel@tonic-gate * undap1: 5) 12 12787c478bd9Sstevel@tonic-gate * 6) 34 12797c478bd9Sstevel@tonic-gate * 7) 56 12807c478bd9Sstevel@tonic-gate * 8) 78 12817c478bd9Sstevel@tonic-gate * undap2: 9) qr 12827c478bd9Sstevel@tonic-gate * 10) st 12837c478bd9Sstevel@tonic-gate * 11) uv 12847c478bd9Sstevel@tonic-gate * 12) wx 12857c478bd9Sstevel@tonic-gate * dol: 13) yz 12867c478bd9Sstevel@tonic-gate * 12877c478bd9Sstevel@tonic-gate * UNDO AREA: 12887c478bd9Sstevel@tonic-gate * dol+1: 5) ij 12897c478bd9Sstevel@tonic-gate * 6) kl 12907c478bd9Sstevel@tonic-gate * 7) mn 12917c478bd9Sstevel@tonic-gate * unddol: 8) op 12927c478bd9Sstevel@tonic-gate */ 12937c478bd9Sstevel@tonic-gate 12947c478bd9Sstevel@tonic-gate /* 12957c478bd9Sstevel@tonic-gate * If this is a change (not a delete/put), 12967c478bd9Sstevel@tonic-gate * then we must move the text between undap1 and undap2 12977c478bd9Sstevel@tonic-gate * and it must not be at the bottom of the file 12987c478bd9Sstevel@tonic-gate */ 12997c478bd9Sstevel@tonic-gate 13007c478bd9Sstevel@tonic-gate if ((i = (kp = undap2) - (jp = undap1)) > 0) { 13017c478bd9Sstevel@tonic-gate if (kp != dolp1) { 13027c478bd9Sstevel@tonic-gate 13037c478bd9Sstevel@tonic-gate /* 13047c478bd9Sstevel@tonic-gate * FILE: LINE INITIAL REV1 REV2 REV3 13057c478bd9Sstevel@tonic-gate * 13067c478bd9Sstevel@tonic-gate * 1) ab ab ab ab 13077c478bd9Sstevel@tonic-gate * 2) cd cd cd cd 13087c478bd9Sstevel@tonic-gate * 3) ef ef ef ef 13097c478bd9Sstevel@tonic-gate * unddel: 4) gh gh gh gh 13107c478bd9Sstevel@tonic-gate * undap1: 5) 12 78 78 qr 13117c478bd9Sstevel@tonic-gate * 6) 34 56 56 st 13127c478bd9Sstevel@tonic-gate * 7) 56 34 34 uv 13137c478bd9Sstevel@tonic-gate * 8) 78 12 12 wx 13147c478bd9Sstevel@tonic-gate * undap2: 9) qr qr yz yz 13157c478bd9Sstevel@tonic-gate * 10) st st wx 12 13167c478bd9Sstevel@tonic-gate * 11) uv uv uv 34 13177c478bd9Sstevel@tonic-gate * 12) wx wx st 56 13187c478bd9Sstevel@tonic-gate * dol: 13) yz yz qr 78 13197c478bd9Sstevel@tonic-gate * 13207c478bd9Sstevel@tonic-gate * UNDO AREA: 13217c478bd9Sstevel@tonic-gate * dol+1: 5) ij ij ij ij 13227c478bd9Sstevel@tonic-gate * 6) kl kl kl kl 13237c478bd9Sstevel@tonic-gate * 7) mn mn mn mn 13247c478bd9Sstevel@tonic-gate * unddol: 8) op op op op 13257c478bd9Sstevel@tonic-gate */ 13267c478bd9Sstevel@tonic-gate 13277c478bd9Sstevel@tonic-gate reverse(jp, kp); 13287c478bd9Sstevel@tonic-gate reverse(kp, dolp1); 13297c478bd9Sstevel@tonic-gate reverse(jp, dolp1); 13307c478bd9Sstevel@tonic-gate } 13317c478bd9Sstevel@tonic-gate /* 13327c478bd9Sstevel@tonic-gate * Unddel, the line just before the spot where this 13337c478bd9Sstevel@tonic-gate * test was deleted, may have moved. Account for 13347c478bd9Sstevel@tonic-gate * this in restoration of saved deleted lines. 13357c478bd9Sstevel@tonic-gate */ 13367c478bd9Sstevel@tonic-gate if (unddel >= jp) 13377c478bd9Sstevel@tonic-gate unddel -= i; 13387c478bd9Sstevel@tonic-gate 13397c478bd9Sstevel@tonic-gate /* 13407c478bd9Sstevel@tonic-gate * The last line (dol) may have changed, 13417c478bd9Sstevel@tonic-gate * account for this. 13427c478bd9Sstevel@tonic-gate */ 13437c478bd9Sstevel@tonic-gate newdol -= i; 13447c478bd9Sstevel@tonic-gate 13457c478bd9Sstevel@tonic-gate /* 13467c478bd9Sstevel@tonic-gate * For the case where no lines are restored, dot 13477c478bd9Sstevel@tonic-gate * is the line before the first line deleted. 13487c478bd9Sstevel@tonic-gate */ 13497c478bd9Sstevel@tonic-gate dot = jp-1; 13507c478bd9Sstevel@tonic-gate } 13517c478bd9Sstevel@tonic-gate /* 13527c478bd9Sstevel@tonic-gate * Now put the deleted lines, if any, back where they were. 13537c478bd9Sstevel@tonic-gate * Basic operation is: dol+1,unddol m unddel 13547c478bd9Sstevel@tonic-gate */ 13557c478bd9Sstevel@tonic-gate if (undkind == UNDPUT) { 13567c478bd9Sstevel@tonic-gate unddel = undap1 - 1; 13577c478bd9Sstevel@tonic-gate squish(); 13587c478bd9Sstevel@tonic-gate } 13597c478bd9Sstevel@tonic-gate 13607c478bd9Sstevel@tonic-gate /* 13617c478bd9Sstevel@tonic-gate * Set jp to the line where deleted text is to be added. 13627c478bd9Sstevel@tonic-gate */ 13637c478bd9Sstevel@tonic-gate jp = unddel + 1; 13647c478bd9Sstevel@tonic-gate 13657c478bd9Sstevel@tonic-gate /* 13667c478bd9Sstevel@tonic-gate * Set kp to end of undo save area. 13677c478bd9Sstevel@tonic-gate * 13687c478bd9Sstevel@tonic-gate * If there is any deleted text to be added, do reverses. 13697c478bd9Sstevel@tonic-gate */ 13707c478bd9Sstevel@tonic-gate 13717c478bd9Sstevel@tonic-gate if ((i = (kp = unddol) - dol) > 0) { 13727c478bd9Sstevel@tonic-gate 13737c478bd9Sstevel@tonic-gate /* 13747c478bd9Sstevel@tonic-gate * If deleted lines are not to be appended 13757c478bd9Sstevel@tonic-gate * to the bottom of the file... 13767c478bd9Sstevel@tonic-gate */ 13777c478bd9Sstevel@tonic-gate 13787c478bd9Sstevel@tonic-gate if (jp != dolp1) { 13797c478bd9Sstevel@tonic-gate /* 13807c478bd9Sstevel@tonic-gate * FILE: LINE START REV1 REV2 REV3 13817c478bd9Sstevel@tonic-gate * 1) ab ab ab ab 13827c478bd9Sstevel@tonic-gate * 2) cd cd cd cd 13837c478bd9Sstevel@tonic-gate * 3) ef ef ef ef 13847c478bd9Sstevel@tonic-gate * unddel: 4) gh gh gh gh 13857c478bd9Sstevel@tonic-gate * undap1: 5) qr 78 78 ij 13867c478bd9Sstevel@tonic-gate * 6) st 56 56 kl 13877c478bd9Sstevel@tonic-gate * 7) uv 34 34 mn 13887c478bd9Sstevel@tonic-gate * 8) wx 12 12 op 13897c478bd9Sstevel@tonic-gate * undap2: 9) yz yz yz qr 13907c478bd9Sstevel@tonic-gate * 10) 12 wx wx st 13917c478bd9Sstevel@tonic-gate * 11) 34 uv uv uv 13927c478bd9Sstevel@tonic-gate * 12) 56 st st wx 13937c478bd9Sstevel@tonic-gate * dol: 13) 78 qr qr yz 13947c478bd9Sstevel@tonic-gate * 13957c478bd9Sstevel@tonic-gate * UNDO AREA: 13967c478bd9Sstevel@tonic-gate * dol+1: 5) ij ij op 12 13977c478bd9Sstevel@tonic-gate * 6) kl kl mn 34 13987c478bd9Sstevel@tonic-gate * 7) mn mn kl 56 13997c478bd9Sstevel@tonic-gate * unddol: 8) op op ij 78 14007c478bd9Sstevel@tonic-gate */ 14017c478bd9Sstevel@tonic-gate 14027c478bd9Sstevel@tonic-gate reverse(jp, dolp1); 14037c478bd9Sstevel@tonic-gate reverse(dolp1, ++kp); 14047c478bd9Sstevel@tonic-gate reverse(jp, kp); 14057c478bd9Sstevel@tonic-gate } 14067c478bd9Sstevel@tonic-gate /* 14077c478bd9Sstevel@tonic-gate * Account for possible forward motion of the target 14087c478bd9Sstevel@tonic-gate * (where the deleted lines were restored) for after 14097c478bd9Sstevel@tonic-gate * restoration of the deleted lines. 14107c478bd9Sstevel@tonic-gate */ 14117c478bd9Sstevel@tonic-gate if (undap1 >= jp) 14127c478bd9Sstevel@tonic-gate undap1 += i; 14137c478bd9Sstevel@tonic-gate /* 14147c478bd9Sstevel@tonic-gate * Dot is the first resurrected line. 14157c478bd9Sstevel@tonic-gate */ 14167c478bd9Sstevel@tonic-gate dot = jp; 14177c478bd9Sstevel@tonic-gate 14187c478bd9Sstevel@tonic-gate /* 14197c478bd9Sstevel@tonic-gate * Account for a shift in the last line (dol). 14207c478bd9Sstevel@tonic-gate */ 14217c478bd9Sstevel@tonic-gate 14227c478bd9Sstevel@tonic-gate newdol += i; 14237c478bd9Sstevel@tonic-gate } 14247c478bd9Sstevel@tonic-gate /* 14257c478bd9Sstevel@tonic-gate * Clean up so we are invertible 14267c478bd9Sstevel@tonic-gate */ 14277c478bd9Sstevel@tonic-gate unddel = undap1 - 1; 14287c478bd9Sstevel@tonic-gate undap1 = jp; 14297c478bd9Sstevel@tonic-gate undap2 = jp + i; 14307c478bd9Sstevel@tonic-gate dol = newdol; 14317c478bd9Sstevel@tonic-gate netchHAD(cnt); 14327c478bd9Sstevel@tonic-gate if (undkind == UNDALL) { 14337c478bd9Sstevel@tonic-gate dot = undadot; 14347c478bd9Sstevel@tonic-gate undadot = newadot; 14357c478bd9Sstevel@tonic-gate } else 14367c478bd9Sstevel@tonic-gate undkind = UNDCHANGE; 14377c478bd9Sstevel@tonic-gate /* 14387c478bd9Sstevel@tonic-gate * Now relocate all marks for lines that were modified, 14397c478bd9Sstevel@tonic-gate * since the marks point to lines whose address has 14407c478bd9Sstevel@tonic-gate * been modified from the save area to the current 14417c478bd9Sstevel@tonic-gate * area 14427c478bd9Sstevel@tonic-gate */ 14437c478bd9Sstevel@tonic-gate 14447c478bd9Sstevel@tonic-gate for (j=unddol; j> dol; j--) 14457c478bd9Sstevel@tonic-gate for (k=0; k<=25; k++) 14467c478bd9Sstevel@tonic-gate if (names[k] == *(j)) 14477c478bd9Sstevel@tonic-gate names[k]= *((undap1+(j-dolp1)) ); 14487c478bd9Sstevel@tonic-gate } 14497c478bd9Sstevel@tonic-gate /* 14507c478bd9Sstevel@tonic-gate * Defensive programming - after a munged undadot. 14517c478bd9Sstevel@tonic-gate * Also handle empty buffer case. 14527c478bd9Sstevel@tonic-gate */ 14537c478bd9Sstevel@tonic-gate if ((dot <= zero || dot > dol) && dot != dol) 14547c478bd9Sstevel@tonic-gate dot = one; 14557c478bd9Sstevel@tonic-gate #ifdef UNDOTRACE 14567c478bd9Sstevel@tonic-gate if (trace) 14577c478bd9Sstevel@tonic-gate vudump("after undo"); 14587c478bd9Sstevel@tonic-gate #endif 14597c478bd9Sstevel@tonic-gate } 14607c478bd9Sstevel@tonic-gate 14617c478bd9Sstevel@tonic-gate /* 14627c478bd9Sstevel@tonic-gate * Be (almost completely) sure there really 14637c478bd9Sstevel@tonic-gate * was a change, before claiming to undo. 14647c478bd9Sstevel@tonic-gate */ 1465f6db9f27Scf46844 void 1466f6db9f27Scf46844 somechange(void) 14677c478bd9Sstevel@tonic-gate { 1468f6db9f27Scf46844 line *ip, *jp; 14697c478bd9Sstevel@tonic-gate 14707c478bd9Sstevel@tonic-gate switch (undkind) { 14717c478bd9Sstevel@tonic-gate 14727c478bd9Sstevel@tonic-gate case UNDMOVE: 14737c478bd9Sstevel@tonic-gate return; 14747c478bd9Sstevel@tonic-gate 14757c478bd9Sstevel@tonic-gate case UNDCHANGE: 14767c478bd9Sstevel@tonic-gate if (undap1 == undap2 && dol == unddol) 14777c478bd9Sstevel@tonic-gate break; 14787c478bd9Sstevel@tonic-gate return; 14797c478bd9Sstevel@tonic-gate 14807c478bd9Sstevel@tonic-gate case UNDPUT: 14817c478bd9Sstevel@tonic-gate if (undap1 != undap2) 14827c478bd9Sstevel@tonic-gate return; 14837c478bd9Sstevel@tonic-gate break; 14847c478bd9Sstevel@tonic-gate 14857c478bd9Sstevel@tonic-gate case UNDALL: 14867c478bd9Sstevel@tonic-gate if (unddol - dol != lineDOL()) 14877c478bd9Sstevel@tonic-gate return; 14887c478bd9Sstevel@tonic-gate for (ip = one, jp = dol + 1; ip <= dol; ip++, jp++) 14897c478bd9Sstevel@tonic-gate if ((*ip &~ 01) != (*jp &~ 01)) 14907c478bd9Sstevel@tonic-gate return; 14917c478bd9Sstevel@tonic-gate break; 14927c478bd9Sstevel@tonic-gate 14937c478bd9Sstevel@tonic-gate case UNDNONE: 14947c478bd9Sstevel@tonic-gate error(gettext("Nothing to undo")); 14957c478bd9Sstevel@tonic-gate } 14967c478bd9Sstevel@tonic-gate error(value(vi_TERSE) ? gettext("Nothing changed") : 14977c478bd9Sstevel@tonic-gate gettext("Last undoable command didn't change anything")); 14987c478bd9Sstevel@tonic-gate } 14997c478bd9Sstevel@tonic-gate 15007c478bd9Sstevel@tonic-gate /* 15017c478bd9Sstevel@tonic-gate * Map command: 15027c478bd9Sstevel@tonic-gate * map src dest 1503f6db9f27Scf46844 * 1504f6db9f27Scf46844 * un is true if this is unmap command 1505f6db9f27Scf46844 * ab is true if this is abbr command 15067c478bd9Sstevel@tonic-gate */ 1507f6db9f27Scf46844 void 1508f6db9f27Scf46844 mapcmd(int un, int ab) 15097c478bd9Sstevel@tonic-gate { 15107c478bd9Sstevel@tonic-gate unsigned char lhs[100], rhs[100]; /* max sizes resp. */ 1511f6db9f27Scf46844 unsigned char *p; 1512f6db9f27Scf46844 int c; /* char --> int */ 15137c478bd9Sstevel@tonic-gate unsigned char *dname; 15147c478bd9Sstevel@tonic-gate struct maps *mp; /* the map structure we are working on */ 15157c478bd9Sstevel@tonic-gate 15167c478bd9Sstevel@tonic-gate mp = ab ? abbrevs : exclam() ? immacs : arrows; 15177c478bd9Sstevel@tonic-gate if (skipend()) { 15187c478bd9Sstevel@tonic-gate int i; 15197c478bd9Sstevel@tonic-gate 15207c478bd9Sstevel@tonic-gate /* print current mapping values */ 15217c478bd9Sstevel@tonic-gate if (peekchar() != EOF) 15227c478bd9Sstevel@tonic-gate ignchar(); 15237c478bd9Sstevel@tonic-gate if (un) 15247c478bd9Sstevel@tonic-gate error(gettext("Missing lhs")); 15257c478bd9Sstevel@tonic-gate if (inopen) 15267c478bd9Sstevel@tonic-gate pofix(); 15277c478bd9Sstevel@tonic-gate for (i=0; i< MAXNOMACS && mp[i].mapto; i++) 15287c478bd9Sstevel@tonic-gate if (mp[i].cap) { 15297c478bd9Sstevel@tonic-gate lprintf("%s", mp[i].descr); 15307c478bd9Sstevel@tonic-gate putchar('\t'); 15317c478bd9Sstevel@tonic-gate lprintf("%s", mp[i].cap); 15327c478bd9Sstevel@tonic-gate putchar('\t'); 15337c478bd9Sstevel@tonic-gate lprintf("%s", mp[i].mapto); 15347c478bd9Sstevel@tonic-gate putNFL(); 15357c478bd9Sstevel@tonic-gate } 15367c478bd9Sstevel@tonic-gate return; 15377c478bd9Sstevel@tonic-gate } 15387c478bd9Sstevel@tonic-gate 15397c478bd9Sstevel@tonic-gate (void)skipwh(); 15407c478bd9Sstevel@tonic-gate for (p=lhs; ; ) { 15417c478bd9Sstevel@tonic-gate c = getchar(); 15427c478bd9Sstevel@tonic-gate if (c == CTRL('v')) { 15437c478bd9Sstevel@tonic-gate c = getchar(); 15447c478bd9Sstevel@tonic-gate } else if (!un && any(c, " \t")) { 15457c478bd9Sstevel@tonic-gate /* End of lhs */ 15467c478bd9Sstevel@tonic-gate break; 15477c478bd9Sstevel@tonic-gate } else if (endcmd(c) && c!='"') { 15487c478bd9Sstevel@tonic-gate ungetchar(c); 15497c478bd9Sstevel@tonic-gate if (un) { 15507c478bd9Sstevel@tonic-gate donewline(); 15517c478bd9Sstevel@tonic-gate *p = 0; 1552f6db9f27Scf46844 addmac(lhs, (unsigned char *)NOSTR, 1553f6db9f27Scf46844 (unsigned char *)NOSTR, mp); 15547c478bd9Sstevel@tonic-gate return; 15557c478bd9Sstevel@tonic-gate } else 15567c478bd9Sstevel@tonic-gate error(gettext("Missing rhs")); 15577c478bd9Sstevel@tonic-gate } 15587c478bd9Sstevel@tonic-gate *p++ = c; 15597c478bd9Sstevel@tonic-gate } 15607c478bd9Sstevel@tonic-gate *p = 0; 15617c478bd9Sstevel@tonic-gate 15627c478bd9Sstevel@tonic-gate if (skipend()) 15637c478bd9Sstevel@tonic-gate error(gettext("Missing rhs")); 15647c478bd9Sstevel@tonic-gate for (p=rhs; ; ) { 15657c478bd9Sstevel@tonic-gate c = getchar(); 15667c478bd9Sstevel@tonic-gate if (c == CTRL('v')) { 15677c478bd9Sstevel@tonic-gate c = getchar(); 15687c478bd9Sstevel@tonic-gate } else if (endcmd(c) && c!='"') { 15697c478bd9Sstevel@tonic-gate ungetchar(c); 15707c478bd9Sstevel@tonic-gate break; 15717c478bd9Sstevel@tonic-gate } 15727c478bd9Sstevel@tonic-gate *p++ = c; 15737c478bd9Sstevel@tonic-gate } 15747c478bd9Sstevel@tonic-gate *p = 0; 15757c478bd9Sstevel@tonic-gate donewline(); 15767c478bd9Sstevel@tonic-gate /* 15777c478bd9Sstevel@tonic-gate * Special hack for function keys: #1 means key f1, etc. 15787c478bd9Sstevel@tonic-gate * If the terminal doesn't have function keys, we just use #1. 15797c478bd9Sstevel@tonic-gate */ 15807c478bd9Sstevel@tonic-gate if (lhs[0] == '#') { 15817c478bd9Sstevel@tonic-gate unsigned char *fnkey; 15827c478bd9Sstevel@tonic-gate unsigned char *fkey(); 15837c478bd9Sstevel@tonic-gate unsigned char funkey[3]; 15847c478bd9Sstevel@tonic-gate 15857c478bd9Sstevel@tonic-gate fnkey = fkey(lhs[1] - '0'); 15867c478bd9Sstevel@tonic-gate funkey[0] = 'f'; funkey[1] = lhs[1]; funkey[2] = 0; 15877c478bd9Sstevel@tonic-gate if (fnkey) 15887c478bd9Sstevel@tonic-gate strcpy(lhs, fnkey); 15897c478bd9Sstevel@tonic-gate dname = funkey; 15907c478bd9Sstevel@tonic-gate } else { 15917c478bd9Sstevel@tonic-gate dname = lhs; 15927c478bd9Sstevel@tonic-gate } 15937c478bd9Sstevel@tonic-gate addmac(lhs,rhs,dname,mp); 15947c478bd9Sstevel@tonic-gate } 15957c478bd9Sstevel@tonic-gate 15967c478bd9Sstevel@tonic-gate /* 15977c478bd9Sstevel@tonic-gate * Add a macro definition to those that already exist. The sequence of 15987c478bd9Sstevel@tonic-gate * chars "src" is mapped into "dest". If src is already mapped into something 15997c478bd9Sstevel@tonic-gate * this overrides the mapping. There is no recursion. Unmap is done by 16007c478bd9Sstevel@tonic-gate * using NOSTR for dest. Dname is what to show in listings. mp is 16017c478bd9Sstevel@tonic-gate * the structure to affect (arrows, etc). 16027c478bd9Sstevel@tonic-gate */ 1603f6db9f27Scf46844 void 1604f6db9f27Scf46844 addmac(unsigned char *src, unsigned char *dest, unsigned char *dname, 1605f6db9f27Scf46844 struct maps *mp) 16067c478bd9Sstevel@tonic-gate { 1607f6db9f27Scf46844 int slot, zer; 16087c478bd9Sstevel@tonic-gate 16097c478bd9Sstevel@tonic-gate #ifdef UNDOTRACE 16107c478bd9Sstevel@tonic-gate if (trace) 16117c478bd9Sstevel@tonic-gate fprintf(trace, "addmac(src='%s', dest='%s', dname='%s', mp=%x\n", src, dest, dname, mp); 16127c478bd9Sstevel@tonic-gate #endif 16137c478bd9Sstevel@tonic-gate if (dest && mp==arrows) { 16147c478bd9Sstevel@tonic-gate /* 16157c478bd9Sstevel@tonic-gate * Prevent tail recursion. We really should be 16167c478bd9Sstevel@tonic-gate * checking to see if src is a suffix of dest 16177c478bd9Sstevel@tonic-gate * but this makes mapping involving escapes that 16187c478bd9Sstevel@tonic-gate * is reasonable mess up. 16197c478bd9Sstevel@tonic-gate */ 16207c478bd9Sstevel@tonic-gate if (src[1] == 0 && src[0] == dest[strlen(dest)-1]) 16217c478bd9Sstevel@tonic-gate error(gettext("No tail recursion")); 16227c478bd9Sstevel@tonic-gate /* 16237c478bd9Sstevel@tonic-gate * We don't let the user rob himself of ":", and making 16247c478bd9Sstevel@tonic-gate * multi char words is a bad idea so we don't allow it. 16257c478bd9Sstevel@tonic-gate * Note that if user sets mapinput and maps all of return, 16267c478bd9Sstevel@tonic-gate * linefeed, and escape, he can hurt himself. This is 16277c478bd9Sstevel@tonic-gate * so weird I don't bother to check for it. 16287c478bd9Sstevel@tonic-gate */ 16297c478bd9Sstevel@tonic-gate if (isalpha(src[0]) && isascii(src[0]) && src[1] || any(src[0],":")) 16307c478bd9Sstevel@tonic-gate error(gettext("Too dangerous to map that")); 16317c478bd9Sstevel@tonic-gate } 16327c478bd9Sstevel@tonic-gate else if (dest) { 16337c478bd9Sstevel@tonic-gate /* check for tail recursion in input mode: fussier */ 16347c478bd9Sstevel@tonic-gate if (eq(src, dest+strlen(dest)-strlen(src))) 16357c478bd9Sstevel@tonic-gate error(gettext("No tail recursion")); 16367c478bd9Sstevel@tonic-gate } 16377c478bd9Sstevel@tonic-gate /* 16387c478bd9Sstevel@tonic-gate * If the src were null it would cause the dest to 16397c478bd9Sstevel@tonic-gate * be mapped always forever. This is not good. 16407c478bd9Sstevel@tonic-gate */ 16417c478bd9Sstevel@tonic-gate if (src == (unsigned char *)NOSTR || src[0] == 0) 16427c478bd9Sstevel@tonic-gate error(gettext("Missing lhs")); 16437c478bd9Sstevel@tonic-gate 16447c478bd9Sstevel@tonic-gate /* see if we already have a def for src */ 16457c478bd9Sstevel@tonic-gate zer = -1; 16467c478bd9Sstevel@tonic-gate for (slot=0; slot < MAXNOMACS && mp[slot].mapto; slot++) { 16477c478bd9Sstevel@tonic-gate if (mp[slot].cap) { 16487c478bd9Sstevel@tonic-gate if (eq(src, mp[slot].cap) || eq(src, mp[slot].mapto)) 16497c478bd9Sstevel@tonic-gate break; /* if so, reuse slot */ 16507c478bd9Sstevel@tonic-gate } else { 16517c478bd9Sstevel@tonic-gate zer = slot; /* remember an empty slot */ 16527c478bd9Sstevel@tonic-gate } 16537c478bd9Sstevel@tonic-gate } 16547c478bd9Sstevel@tonic-gate 16557c478bd9Sstevel@tonic-gate if (slot >= MAXNOMACS) 16567c478bd9Sstevel@tonic-gate error(gettext("Too many macros")); 16577c478bd9Sstevel@tonic-gate 16587c478bd9Sstevel@tonic-gate if (dest == (unsigned char *)NOSTR) { 16597c478bd9Sstevel@tonic-gate /* unmap */ 16607c478bd9Sstevel@tonic-gate if (mp[slot].cap) { 16617c478bd9Sstevel@tonic-gate mp[slot].cap = (unsigned char *)NOSTR; 16627c478bd9Sstevel@tonic-gate mp[slot].descr = (unsigned char *)NOSTR; 16637c478bd9Sstevel@tonic-gate } else { 16647c478bd9Sstevel@tonic-gate error(value(vi_TERSE) ? gettext("Not mapped") : 16657c478bd9Sstevel@tonic-gate gettext("That macro wasn't mapped")); 16667c478bd9Sstevel@tonic-gate } 16677c478bd9Sstevel@tonic-gate return; 16687c478bd9Sstevel@tonic-gate } 16697c478bd9Sstevel@tonic-gate 16707c478bd9Sstevel@tonic-gate /* reuse empty slot, if we found one and src isn't already defined */ 16717c478bd9Sstevel@tonic-gate if (zer >= 0 && mp[slot].mapto == 0) 16727c478bd9Sstevel@tonic-gate slot = zer; 16737c478bd9Sstevel@tonic-gate 16747c478bd9Sstevel@tonic-gate /* if not, append to end */ 16757c478bd9Sstevel@tonic-gate if (msnext == 0) /* first time */ 16767c478bd9Sstevel@tonic-gate msnext = mapspace; 16777c478bd9Sstevel@tonic-gate /* Check is a bit conservative, we charge for dname even if reusing src */ 16787c478bd9Sstevel@tonic-gate if (msnext - mapspace + strlen(dest) + strlen(src) + strlen(dname) + 3 > MAXCHARMACS) 16797c478bd9Sstevel@tonic-gate error(gettext("Too much macro text")); 16807c478bd9Sstevel@tonic-gate CP(msnext, src); 16817c478bd9Sstevel@tonic-gate mp[slot].cap = msnext; 16827c478bd9Sstevel@tonic-gate msnext += strlen(src) + 1; /* plus 1 for null on the end */ 16837c478bd9Sstevel@tonic-gate CP(msnext, dest); 16847c478bd9Sstevel@tonic-gate mp[slot].mapto = msnext; 16857c478bd9Sstevel@tonic-gate msnext += strlen(dest) + 1; 16867c478bd9Sstevel@tonic-gate if (dname) { 16877c478bd9Sstevel@tonic-gate CP(msnext, dname); 16887c478bd9Sstevel@tonic-gate mp[slot].descr = msnext; 16897c478bd9Sstevel@tonic-gate msnext += strlen(dname) + 1; 16907c478bd9Sstevel@tonic-gate } else { 16917c478bd9Sstevel@tonic-gate /* default descr to string user enters */ 16927c478bd9Sstevel@tonic-gate mp[slot].descr = src; 16937c478bd9Sstevel@tonic-gate } 16947c478bd9Sstevel@tonic-gate } 16957c478bd9Sstevel@tonic-gate 16967c478bd9Sstevel@tonic-gate /* 16977c478bd9Sstevel@tonic-gate * Implements macros from command mode. c is the buffer to 16987c478bd9Sstevel@tonic-gate * get the macro from. 16997c478bd9Sstevel@tonic-gate */ 1700f6db9f27Scf46844 void 17017c478bd9Sstevel@tonic-gate cmdmac(c) 17027c478bd9Sstevel@tonic-gate unsigned char c; 17037c478bd9Sstevel@tonic-gate { 17047c478bd9Sstevel@tonic-gate unsigned char macbuf[BUFSIZE]; 17057c478bd9Sstevel@tonic-gate line *ad, *a1, *a2; 17067c478bd9Sstevel@tonic-gate unsigned char *oglobp; 17077c478bd9Sstevel@tonic-gate short pk; 17087c478bd9Sstevel@tonic-gate bool oinglobal; 17097c478bd9Sstevel@tonic-gate 17107c478bd9Sstevel@tonic-gate lastmac = c; 17117c478bd9Sstevel@tonic-gate oglobp = globp; 17127c478bd9Sstevel@tonic-gate oinglobal = inglobal; 17137c478bd9Sstevel@tonic-gate pk = peekc; peekc = 0; 17147c478bd9Sstevel@tonic-gate if (inglobal < 2) 17157c478bd9Sstevel@tonic-gate inglobal = 1; 17167c478bd9Sstevel@tonic-gate regbuf(c, macbuf, sizeof(macbuf)); 17177c478bd9Sstevel@tonic-gate a1 = addr1; a2 = addr2; 17187c478bd9Sstevel@tonic-gate for (ad=a1; ad<=a2; ad++) { 17197c478bd9Sstevel@tonic-gate globp = macbuf; 17207c478bd9Sstevel@tonic-gate dot = ad; 17217c478bd9Sstevel@tonic-gate commands(1,1); 17227c478bd9Sstevel@tonic-gate } 17237c478bd9Sstevel@tonic-gate globp = oglobp; 17247c478bd9Sstevel@tonic-gate inglobal = oinglobal; 17257c478bd9Sstevel@tonic-gate peekc = pk; 17267c478bd9Sstevel@tonic-gate } 17277c478bd9Sstevel@tonic-gate 17287c478bd9Sstevel@tonic-gate unsigned char * 17297c478bd9Sstevel@tonic-gate vgetpass(prompt) 1730*6a3e8e86SRichard Lowe char *prompt; 17317c478bd9Sstevel@tonic-gate { 1732f6db9f27Scf46844 unsigned char *p; 1733f6db9f27Scf46844 int c; 17347c478bd9Sstevel@tonic-gate static unsigned char pbuf[9]; 17357c478bd9Sstevel@tonic-gate 17367c478bd9Sstevel@tonic-gate /* In ex mode, let the system hassle with setting no echo */ 17377c478bd9Sstevel@tonic-gate if (!inopen) 17387c478bd9Sstevel@tonic-gate return (unsigned char *)getpass(prompt); 1739f6db9f27Scf46844 viprintf("%s", prompt); flush(); 17407c478bd9Sstevel@tonic-gate for (p=pbuf; (c = getkey())!='\n' && c!=EOF && c!='\r';) { 17417c478bd9Sstevel@tonic-gate if (p < &pbuf[8]) 17427c478bd9Sstevel@tonic-gate *p++ = c; 17437c478bd9Sstevel@tonic-gate } 17447c478bd9Sstevel@tonic-gate *p = '\0'; 17457c478bd9Sstevel@tonic-gate return(pbuf); 17467c478bd9Sstevel@tonic-gate } 17477c478bd9Sstevel@tonic-gate 17487c478bd9Sstevel@tonic-gate 17497c478bd9Sstevel@tonic-gate #ifdef TAG_STACK 17507c478bd9Sstevel@tonic-gate #define TSTACKSIZE 20 17517c478bd9Sstevel@tonic-gate struct tagstack { 17527c478bd9Sstevel@tonic-gate line *tag_line; 17537c478bd9Sstevel@tonic-gate char *tag_file; 17547c478bd9Sstevel@tonic-gate } tagstack[TSTACKSIZE]; 17557c478bd9Sstevel@tonic-gate static int tag_depth = 0; 17567c478bd9Sstevel@tonic-gate 17577c478bd9Sstevel@tonic-gate static char tag_buf[ 1024 ]; 17587c478bd9Sstevel@tonic-gate static char *tag_end = tag_buf; 17597c478bd9Sstevel@tonic-gate 1760f6db9f27Scf46844 void 1761f6db9f27Scf46844 savetag(char *name) /* saves location where we are */ 17627c478bd9Sstevel@tonic-gate { 17637c478bd9Sstevel@tonic-gate if( !value(vi_TAGSTACK) ) 17647c478bd9Sstevel@tonic-gate return; 17657c478bd9Sstevel@tonic-gate if(tag_depth >= TSTACKSIZE) { 17667c478bd9Sstevel@tonic-gate error(gettext("Tagstack too deep.")); 17677c478bd9Sstevel@tonic-gate } 17687c478bd9Sstevel@tonic-gate if( strlen( name ) + 1 + tag_end >= &tag_buf[1024]) { 17697c478bd9Sstevel@tonic-gate error(gettext("Too many tags.")); 17707c478bd9Sstevel@tonic-gate } 17717c478bd9Sstevel@tonic-gate tagstack[tag_depth].tag_line = dot; 17727c478bd9Sstevel@tonic-gate tagstack[tag_depth++].tag_file = tag_end; 17737c478bd9Sstevel@tonic-gate while(*tag_end++ = *name++) 17747c478bd9Sstevel@tonic-gate ; 17757c478bd9Sstevel@tonic-gate } 17767c478bd9Sstevel@tonic-gate 17777c478bd9Sstevel@tonic-gate /* 17787c478bd9Sstevel@tonic-gate * Undo a "savetag". 17797c478bd9Sstevel@tonic-gate */ 1780f6db9f27Scf46844 void 1781f6db9f27Scf46844 unsavetag(void) 17827c478bd9Sstevel@tonic-gate { 17837c478bd9Sstevel@tonic-gate if (!value(vi_TAGSTACK)) 17847c478bd9Sstevel@tonic-gate return; 17857c478bd9Sstevel@tonic-gate if (tag_depth > 0) 17867c478bd9Sstevel@tonic-gate tag_end = tagstack[--tag_depth].tag_file; 17877c478bd9Sstevel@tonic-gate } 17887c478bd9Sstevel@tonic-gate 1789f6db9f27Scf46844 void 17907c478bd9Sstevel@tonic-gate poptag(quick) /* puts us back where we came from */ 17917c478bd9Sstevel@tonic-gate bool quick; 17927c478bd9Sstevel@tonic-gate { 17937c478bd9Sstevel@tonic-gate unsigned char cmdbuf[100]; 17947c478bd9Sstevel@tonic-gate unsigned char *oglobp; 17957c478bd9Sstevel@tonic-gate int d; 17967c478bd9Sstevel@tonic-gate 17977c478bd9Sstevel@tonic-gate if (!value(vi_TAGSTACK)) { /* reset the stack */ 17987c478bd9Sstevel@tonic-gate tag_end = tag_buf; 17997c478bd9Sstevel@tonic-gate d = tag_depth; 18007c478bd9Sstevel@tonic-gate tag_depth = 0; 18017c478bd9Sstevel@tonic-gate if (d == 0) 18027c478bd9Sstevel@tonic-gate error(gettext("Tagstack not enabled.")); 18037c478bd9Sstevel@tonic-gate else 18047c478bd9Sstevel@tonic-gate return; 18057c478bd9Sstevel@tonic-gate } 18067c478bd9Sstevel@tonic-gate if (!tag_depth) 18077c478bd9Sstevel@tonic-gate error(gettext("Tagstack empty.")); 18087c478bd9Sstevel@tonic-gate 18097c478bd9Sstevel@tonic-gate /* change to old file */ 18107c478bd9Sstevel@tonic-gate if (strcmp(tagstack[tag_depth-1].tag_file, savedfile) ) { 18117c478bd9Sstevel@tonic-gate if (!quick) { 18127c478bd9Sstevel@tonic-gate ckaw(); 18137c478bd9Sstevel@tonic-gate if (chng && dol > zero) 18147c478bd9Sstevel@tonic-gate error(value(vi_TERSE) ? 18157c478bd9Sstevel@tonic-gate gettext("No write") : gettext("No write since last change (:pop! overrides)")); 18167c478bd9Sstevel@tonic-gate } 18177c478bd9Sstevel@tonic-gate oglobp = globp; 18187c478bd9Sstevel@tonic-gate strcpy(cmdbuf, "e! "); 18197c478bd9Sstevel@tonic-gate strcat(cmdbuf, tagstack[tag_depth-1].tag_file); 18207c478bd9Sstevel@tonic-gate globp = cmdbuf; 18217c478bd9Sstevel@tonic-gate d = peekc; ungetchar(0); 18227c478bd9Sstevel@tonic-gate commands(1, 1); 18237c478bd9Sstevel@tonic-gate peekc = d; 18247c478bd9Sstevel@tonic-gate globp = oglobp; 18257c478bd9Sstevel@tonic-gate } 18267c478bd9Sstevel@tonic-gate markpr(dot); 18277c478bd9Sstevel@tonic-gate /* set line number */ 18287c478bd9Sstevel@tonic-gate dot = tagstack[--tag_depth].tag_line; 18297c478bd9Sstevel@tonic-gate tag_end = tagstack[tag_depth].tag_file; 18307c478bd9Sstevel@tonic-gate } 18317c478bd9Sstevel@tonic-gate #endif 1832