ex_z.c revision 19304
119304Speter/*- 219304Speter * Copyright (c) 1993, 1994 319304Speter * The Regents of the University of California. All rights reserved. 419304Speter * Copyright (c) 1993, 1994, 1995, 1996 519304Speter * Keith Bostic. All rights reserved. 619304Speter * 719304Speter * See the LICENSE file for redistribution information. 819304Speter */ 919304Speter 1019304Speter#include "config.h" 1119304Speter 1219304Speter#ifndef lint 1319304Speterstatic const char sccsid[] = "@(#)ex_z.c 10.10 (Berkeley) 3/6/96"; 1419304Speter#endif /* not lint */ 1519304Speter 1619304Speter#include <sys/types.h> 1719304Speter#include <sys/queue.h> 1819304Speter 1919304Speter#include <bitstring.h> 2019304Speter#include <limits.h> 2119304Speter#include <stdio.h> 2219304Speter#include <stdlib.h> 2319304Speter#include <string.h> 2419304Speter 2519304Speter#include "../common/common.h" 2619304Speter 2719304Speter/* 2819304Speter * ex_z -- :[line] z [^-.+=] [count] [flags] 2919304Speter * Adjust window. 3019304Speter * 3119304Speter * PUBLIC: int ex_z __P((SCR *, EXCMD *)); 3219304Speter */ 3319304Speterint 3419304Speterex_z(sp, cmdp) 3519304Speter SCR *sp; 3619304Speter EXCMD *cmdp; 3719304Speter{ 3819304Speter MARK abs; 3919304Speter recno_t cnt, equals, lno; 4019304Speter int eofcheck; 4119304Speter 4219304Speter NEEDFILE(sp, cmdp); 4319304Speter 4419304Speter /* 4519304Speter * !!! 4619304Speter * If no count specified, use either two times the size of the 4719304Speter * scrolling region, or the size of the window option. POSIX 4819304Speter * 1003.2 claims that the latter is correct, but historic ex/vi 4919304Speter * documentation and practice appear to use the scrolling region. 5019304Speter * I'm using the window size as it means that the entire screen 5119304Speter * is used instead of losing a line to roundoff. Note, we drop 5219304Speter * a line from the cnt if using the window size to leave room for 5319304Speter * the next ex prompt. 5419304Speter */ 5519304Speter if (FL_ISSET(cmdp->iflags, E_C_COUNT)) 5619304Speter cnt = cmdp->count; 5719304Speter else 5819304Speter#ifdef HISTORIC_PRACTICE 5919304Speter cnt = O_VAL(sp, O_SCROLL) * 2; 6019304Speter#else 6119304Speter cnt = O_VAL(sp, O_WINDOW) - 1; 6219304Speter#endif 6319304Speter 6419304Speter equals = 0; 6519304Speter eofcheck = 0; 6619304Speter lno = cmdp->addr1.lno; 6719304Speter 6819304Speter switch (FL_ISSET(cmdp->iflags, 6919304Speter E_C_CARAT | E_C_DASH | E_C_DOT | E_C_EQUAL | E_C_PLUS)) { 7019304Speter case E_C_CARAT: /* Display cnt * 2 before the line. */ 7119304Speter eofcheck = 1; 7219304Speter if (lno > cnt * 2) 7319304Speter cmdp->addr1.lno = (lno - cnt * 2) + 1; 7419304Speter else 7519304Speter cmdp->addr1.lno = 1; 7619304Speter cmdp->addr2.lno = (cmdp->addr1.lno + cnt) - 1; 7719304Speter break; 7819304Speter case E_C_DASH: /* Line goes at the bottom of the screen. */ 7919304Speter cmdp->addr1.lno = lno > cnt ? (lno - cnt) + 1 : 1; 8019304Speter cmdp->addr2.lno = lno; 8119304Speter break; 8219304Speter case E_C_DOT: /* Line goes in the middle of the screen. */ 8319304Speter /* 8419304Speter * !!! 8519304Speter * Historically, the "middleness" of the line overrode the 8619304Speter * count, so that "3z.19" or "3z.20" would display the first 8719304Speter * 12 lines of the file, i.e. (N - 1) / 2 lines before and 8819304Speter * after the specified line. 8919304Speter */ 9019304Speter eofcheck = 1; 9119304Speter cnt = (cnt - 1) / 2; 9219304Speter cmdp->addr1.lno = lno > cnt ? lno - cnt : 1; 9319304Speter cmdp->addr2.lno = lno + cnt; 9419304Speter 9519304Speter /* 9619304Speter * !!! 9719304Speter * Historically, z. set the absolute cursor mark. 9819304Speter */ 9919304Speter abs.lno = sp->lno; 10019304Speter abs.cno = sp->cno; 10119304Speter (void)mark_set(sp, ABSMARK1, &abs, 1); 10219304Speter break; 10319304Speter case E_C_EQUAL: /* Center with hyphens. */ 10419304Speter /* 10519304Speter * !!! 10619304Speter * Strangeness. The '=' flag is like the '.' flag (see the 10719304Speter * above comment, it applies here as well) but with a special 10819304Speter * little hack. Print out lines of hyphens before and after 10919304Speter * the specified line. Additionally, the cursor remains set 11019304Speter * on that line. 11119304Speter */ 11219304Speter eofcheck = 1; 11319304Speter cnt = (cnt - 1) / 2; 11419304Speter cmdp->addr1.lno = lno > cnt ? lno - cnt : 1; 11519304Speter cmdp->addr2.lno = lno - 1; 11619304Speter if (ex_pr(sp, cmdp)) 11719304Speter return (1); 11819304Speter (void)ex_puts(sp, "----------------------------------------\n"); 11919304Speter cmdp->addr2.lno = cmdp->addr1.lno = equals = lno; 12019304Speter if (ex_pr(sp, cmdp)) 12119304Speter return (1); 12219304Speter (void)ex_puts(sp, "----------------------------------------\n"); 12319304Speter cmdp->addr1.lno = lno + 1; 12419304Speter cmdp->addr2.lno = (lno + cnt) - 1; 12519304Speter break; 12619304Speter default: 12719304Speter /* If no line specified, move to the next one. */ 12819304Speter if (F_ISSET(cmdp, E_ADDR_DEF)) 12919304Speter ++lno; 13019304Speter /* FALLTHROUGH */ 13119304Speter case E_C_PLUS: /* Line goes at the top of the screen. */ 13219304Speter eofcheck = 1; 13319304Speter cmdp->addr1.lno = lno; 13419304Speter cmdp->addr2.lno = (lno + cnt) - 1; 13519304Speter break; 13619304Speter } 13719304Speter 13819304Speter if (eofcheck) { 13919304Speter if (db_last(sp, &lno)) 14019304Speter return (1); 14119304Speter if (cmdp->addr2.lno > lno) 14219304Speter cmdp->addr2.lno = lno; 14319304Speter } 14419304Speter 14519304Speter if (ex_pr(sp, cmdp)) 14619304Speter return (1); 14719304Speter if (equals) 14819304Speter sp->lno = equals; 14919304Speter return (0); 15019304Speter} 151