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