1 /*- 2 * Copyright (c) 1992, 1993, 1994 3 * The Regents of the University of California. All rights reserved. 4 * Copyright (c) 1992, 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[] = "@(#)v_z.c 10.10 (Berkeley) 5/16/96"; 14 #endif /* not lint */ 15 16 #include <sys/types.h> 17 #include <sys/queue.h> 18 #include <sys/time.h> 19 20 #include <bitstring.h> 21 #include <limits.h> 22 #include <stdio.h> 23 24 #include "../common/common.h" 25 #include "vi.h" 26 27 /* 28 * v_z -- [count]z[count][-.+^<CR>] 29 * Move the screen. 30 * 31 * PUBLIC: int v_z __P((SCR *, VICMD *)); 32 */ 33 int 34 v_z(sp, vp) 35 SCR *sp; 36 VICMD *vp; 37 { 38 recno_t lno; 39 u_int value; 40 41 /* 42 * The first count is the line to use. If the value doesn't 43 * exist, use the last line. 44 */ 45 if (F_ISSET(vp, VC_C1SET)) { 46 lno = vp->count; 47 if (!db_exist(sp, lno) && db_last(sp, &lno)) 48 return (1); 49 } else 50 lno = vp->m_start.lno; 51 52 /* Set default return cursor line. */ 53 vp->m_final.lno = lno; 54 vp->m_final.cno = vp->m_start.cno; 55 56 /* 57 * The second count is the displayed window size, i.e. the 'z' command 58 * is another way to get artificially small windows. Note, you can't 59 * grow beyond the size of the window. 60 * 61 * !!! 62 * A window size of 0 was historically allowed, and simply ignored. 63 * This could be much more simply done by modifying the value of the 64 * O_WINDOW option, but that's not how it worked historically. 65 */ 66 if (F_ISSET(vp, VC_C2SET) && vp->count2 != 0) { 67 if (vp->count2 > O_VAL(sp, O_WINDOW)) 68 vp->count2 = O_VAL(sp, O_WINDOW); 69 if (vs_crel(sp, vp->count2)) 70 return (1); 71 } 72 73 switch (vp->character) { 74 case '-': /* Put the line at the bottom. */ 75 if (vs_sm_fill(sp, lno, P_BOTTOM)) 76 return (1); 77 break; 78 case '.': /* Put the line in the middle. */ 79 if (vs_sm_fill(sp, lno, P_MIDDLE)) 80 return (1); 81 break; 82 case '+': 83 /* 84 * If the user specified a line number, put that line at the 85 * top and move the cursor to it. Otherwise, scroll forward 86 * a screen from the current screen. 87 */ 88 if (F_ISSET(vp, VC_C1SET)) { 89 if (vs_sm_fill(sp, lno, P_TOP)) 90 return (1); 91 if (vs_sm_position(sp, &vp->m_final, 0, P_TOP)) 92 return (1); 93 } else 94 if (vs_sm_scroll(sp, &vp->m_final, sp->t_rows, Z_PLUS)) 95 return (1); 96 break; 97 case '^': 98 /* 99 * If the user specified a line number, put that line at the 100 * bottom, move the cursor to it, and then display the screen 101 * before that one. Otherwise, scroll backward a screen from 102 * the current screen. 103 * 104 * !!! 105 * Note, we match the off-by-one characteristics of historic 106 * vi, here. 107 */ 108 if (F_ISSET(vp, VC_C1SET)) { 109 if (vs_sm_fill(sp, lno, P_BOTTOM)) 110 return (1); 111 if (vs_sm_position(sp, &vp->m_final, 0, P_TOP)) 112 return (1); 113 if (vs_sm_fill(sp, vp->m_final.lno, P_BOTTOM)) 114 return (1); 115 } else 116 if (vs_sm_scroll(sp, &vp->m_final, sp->t_rows, Z_CARAT)) 117 return (1); 118 break; 119 default: /* Put the line at the top for <cr>. */ 120 value = KEY_VAL(sp, vp->character); 121 if (value != K_CR && value != K_NL) { 122 v_emsg(sp, vp->kp->usage, VIM_USAGE); 123 return (1); 124 } 125 if (vs_sm_fill(sp, lno, P_TOP)) 126 return (1); 127 break; 128 } 129 return (0); 130 } 131 132 /* 133 * vs_crel -- 134 * Change the relative size of the current screen. 135 * 136 * PUBLIC: int vs_crel __P((SCR *, long)); 137 */ 138 int 139 vs_crel(sp, count) 140 SCR *sp; 141 long count; 142 { 143 sp->t_minrows = sp->t_rows = count; 144 if (sp->t_rows > sp->rows - 1) 145 sp->t_minrows = sp->t_rows = sp->rows - 1; 146 TMAP = HMAP + (sp->t_rows - 1); 147 F_SET(sp, SC_SCR_REDRAW); 148 return (0); 149 } 150