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