1/* $NetBSD: ex_z.c,v 1.2 2013/11/22 15:52:05 christos Exp $ */ 2/*- 3 * Copyright (c) 1993, 1994 4 * The Regents of the University of California. All rights reserved. 5 * Copyright (c) 1993, 1994, 1995, 1996 6 * Keith Bostic. All rights reserved. 7 * 8 * See the LICENSE file for redistribution information. 9 */ 10 11#include "config.h" 12 13#include <sys/cdefs.h> 14#if 0 15#ifndef lint 16static const char sccsid[] = "Id: ex_z.c,v 10.12 2001/06/25 15:19:22 skimo Exp (Berkeley) Date: 2001/06/25 15:19:22 "; 17#endif /* not lint */ 18#else 19__RCSID("$NetBSD$"); 20#endif 21 22#include <sys/types.h> 23#include <sys/queue.h> 24 25#include <bitstring.h> 26#include <limits.h> 27#include <stdio.h> 28#include <stdlib.h> 29#include <string.h> 30 31#include "../common/common.h" 32 33/* 34 * ex_z -- :[line] z [^-.+=] [count] [flags] 35 * Adjust window. 36 * 37 * PUBLIC: int ex_z __P((SCR *, EXCMD *)); 38 */ 39int 40ex_z(SCR *sp, EXCMD *cmdp) 41{ 42 MARK abm; 43 db_recno_t cnt, equals, lno; 44 int eofcheck; 45 46 NEEDFILE(sp, cmdp); 47 48 /* 49 * !!! 50 * If no count specified, use either two times the size of the 51 * scrolling region, or the size of the window option. POSIX 52 * 1003.2 claims that the latter is correct, but historic ex/vi 53 * documentation and practice appear to use the scrolling region. 54 * I'm using the window size as it means that the entire screen 55 * is used instead of losing a line to roundoff. Note, we drop 56 * a line from the cnt if using the window size to leave room for 57 * the next ex prompt. 58 */ 59 if (FL_ISSET(cmdp->iflags, E_C_COUNT)) 60 cnt = cmdp->count; 61 else 62#ifdef HISTORIC_PRACTICE 63 cnt = O_VAL(sp, O_SCROLL) * 2; 64#else 65 cnt = O_VAL(sp, O_WINDOW) - 1; 66#endif 67 68 equals = 0; 69 eofcheck = 0; 70 lno = cmdp->addr1.lno; 71 72 switch (FL_ISSET(cmdp->iflags, 73 E_C_CARAT | E_C_DASH | E_C_DOT | E_C_EQUAL | E_C_PLUS)) { 74 case E_C_CARAT: /* Display cnt * 2 before the line. */ 75 eofcheck = 1; 76 if (lno > cnt * 2) 77 cmdp->addr1.lno = (lno - cnt * 2) + 1; 78 else 79 cmdp->addr1.lno = 1; 80 cmdp->addr2.lno = (cmdp->addr1.lno + cnt) - 1; 81 break; 82 case E_C_DASH: /* Line goes at the bottom of the screen. */ 83 cmdp->addr1.lno = lno > cnt ? (lno - cnt) + 1 : 1; 84 cmdp->addr2.lno = lno; 85 break; 86 case E_C_DOT: /* Line goes in the middle of the screen. */ 87 /* 88 * !!! 89 * Historically, the "middleness" of the line overrode the 90 * count, so that "3z.19" or "3z.20" would display the first 91 * 12 lines of the file, i.e. (N - 1) / 2 lines before and 92 * after the specified line. 93 */ 94 eofcheck = 1; 95 cnt = (cnt - 1) / 2; 96 cmdp->addr1.lno = lno > cnt ? lno - cnt : 1; 97 cmdp->addr2.lno = lno + cnt; 98 99 /* 100 * !!! 101 * Historically, z. set the absolute cursor mark. 102 */ 103 abm.lno = sp->lno; 104 abm.cno = sp->cno; 105 (void)mark_set(sp, ABSMARK1, &abm, 1); 106 break; 107 case E_C_EQUAL: /* Center with hyphens. */ 108 /* 109 * !!! 110 * Strangeness. The '=' flag is like the '.' flag (see the 111 * above comment, it applies here as well) but with a special 112 * little hack. Print out lines of hyphens before and after 113 * the specified line. Additionally, the cursor remains set 114 * on that line. 115 */ 116 eofcheck = 1; 117 cnt = (cnt - 1) / 2; 118 cmdp->addr1.lno = lno > cnt ? lno - cnt : 1; 119 cmdp->addr2.lno = lno - 1; 120 if (ex_pr(sp, cmdp)) 121 return (1); 122 (void)ex_puts(sp, "----------------------------------------\n"); 123 cmdp->addr2.lno = cmdp->addr1.lno = equals = lno; 124 if (ex_pr(sp, cmdp)) 125 return (1); 126 (void)ex_puts(sp, "----------------------------------------\n"); 127 cmdp->addr1.lno = lno + 1; 128 cmdp->addr2.lno = (lno + cnt) - 1; 129 break; 130 default: 131 /* If no line specified, move to the next one. */ 132 if (F_ISSET(cmdp, E_ADDR_DEF)) 133 ++lno; 134 /* FALLTHROUGH */ 135 case E_C_PLUS: /* Line goes at the top of the screen. */ 136 eofcheck = 1; 137 cmdp->addr1.lno = lno; 138 cmdp->addr2.lno = (lno + cnt) - 1; 139 break; 140 } 141 142 if (eofcheck) { 143 if (db_last(sp, &lno)) 144 return (1); 145 if (cmdp->addr2.lno > lno) 146 cmdp->addr2.lno = lno; 147 } 148 149 if (ex_pr(sp, cmdp)) 150 return (1); 151 if (equals) 152 sp->lno = equals; 153 return (0); 154} 155