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