/* * v_c_settop -- * Scrollbar position. */ static int v_c_settop(SCR *sp, VICMD *vp) { SMAP *smp; size_t x = 0, y = LASTLINE(sp); /* Future: change to -1 to not * display the cursor */ size_t tx, ty = -1; /* * We want to scroll the screen, without changing the cursor position. * So, we fill the screen map and then flush it to the screen. Then, * set the VIP_S_REFRESH flag so the main vi loop doesn't update the * screen. When the next real command happens, the refresh code will * notice that the screen map is way wrong and fix it. * * XXX * There may be a serious performance problem here -- we're doing no * optimization whatsoever, which means that we're copying the entire * screen out to the X11 screen code on each change. */ if (vs_sm_fill(sp, vp->ev.e_lno, P_TOP)) return (1); for (smp = HMAP; smp <= TMAP; ++smp) { SMAP_FLUSH(smp); if (vs_line(sp, smp, &ty, &tx)) return (1); if (ty != (size_t)-1) { y = ty; x = tx; } } (void)sp->gp->scr_move(sp, y, x); F_SET(VIP(sp), VIP_S_REFRESH); return (sp->gp->scr_refresh(sp, 0)); }
/* * v_z -- [count]z[count][-.+^<CR>] * Move the screen. * * PUBLIC: int v_z(SCR *, VICMD *); */ int v_z(SCR *sp, VICMD *vp) { recno_t lno; e_key_t value; /* * The first count is the line to use. If the value doesn't * exist, use the last line. */ if (F_ISSET(vp, VC_C1SET)) { lno = vp->count; if (!db_exist(sp, lno) && db_last(sp, &lno)) return (1); } else lno = vp->m_start.lno; /* Set default return cursor line. */ vp->m_final.lno = lno; vp->m_final.cno = vp->m_start.cno; /* * The second count is the displayed window size, i.e. the 'z' command * is another way to get artificially small windows. Note, you can't * grow beyond the size of the window. * * !!! * A window size of 0 was historically allowed, and simply ignored. * This could be much more simply done by modifying the value of the * O_WINDOW option, but that's not how it worked historically. */ if (F_ISSET(vp, VC_C2SET) && vp->count2 != 0) { if (vp->count2 > O_VAL(sp, O_WINDOW)) vp->count2 = O_VAL(sp, O_WINDOW); if (vs_crel(sp, vp->count2)) return (1); } switch (vp->character) { case '-': /* Put the line at the bottom. */ if (vs_sm_fill(sp, lno, P_BOTTOM)) return (1); break; case '.': /* Put the line in the middle. */ if (vs_sm_fill(sp, lno, P_MIDDLE)) return (1); break; case '+': /* * If the user specified a line number, put that line at the * top and move the cursor to it. Otherwise, scroll forward * a screen from the current screen. */ if (F_ISSET(vp, VC_C1SET)) { if (vs_sm_fill(sp, lno, P_TOP)) return (1); if (vs_sm_position(sp, &vp->m_final, 0, P_TOP)) return (1); } else if (vs_sm_scroll(sp, &vp->m_final, sp->t_rows, Z_PLUS)) return (1); break; case '^': /* * If the user specified a line number, put that line at the * bottom, move the cursor to it, and then display the screen * before that one. Otherwise, scroll backward a screen from * the current screen. * * !!! * Note, we match the off-by-one characteristics of historic * vi, here. */ if (F_ISSET(vp, VC_C1SET)) { if (vs_sm_fill(sp, lno, P_BOTTOM)) return (1); if (vs_sm_position(sp, &vp->m_final, 0, P_TOP)) return (1); if (vs_sm_fill(sp, vp->m_final.lno, P_BOTTOM)) return (1); } else if (vs_sm_scroll(sp, &vp->m_final, sp->t_rows, Z_CARAT)) return (1); break; default: /* Put the line at the top for <cr>. */ value = KEY_VAL(sp, vp->character); if (value != K_CR && value != K_NL) { v_emsg(sp, vp->kp->usage, VIM_USAGE); return (1); } if (vs_sm_fill(sp, lno, P_TOP)) return (1); break; } return (0); }