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