📄 mvcur.c
字号:
#ifndef lintstatic char *sccsid = "@(#)mvcur.c 4.1 (ULTRIX) 7/2/90";#endif lint/************************************************************************ * * * Copyright (c) 1988, 1990 by * * Digital Equipment Corporation, Maynard, MA * * All rights reserved. * * * * This software is furnished under a license and may be used and * * copied only in accordance with the terms of such license and * * with the inclusion of the above copyright notice. This * * software or any other copies thereof may not be provided or * * otherwise made available to any other person. No title to and * * ownership of the software is hereby transferred. * * * * This software is derived from software received from the * * University of California, Berkeley, and from Bell * * Laboratories. Use, duplication, or disclosure is subject to * * restrictions under license agreements with University of * * California and with AT&T. * * * * The information in this software is subject to change without * * notice and should not be construed as a commitment by Digital * * Equipment Corporation. * * * * Digital assumes no responsibility for the use or reliability * * of its software on equipment which is not supplied by Digital. * * * ************************************************************************/ /* * Modification History * * 02/07/90 GWS replaced sgttyb / tty(4)-style terminal I/O with termio(4)- * style terminal I/O. The replacement code is the formerly * conditionalized "USG" code. * */#include "curses.ext"/* * Cursor motion optimization routine. This routine takes as parameters * the screen positions that the cursor is currently at, and the position * you want it to be at, and it will move the cursor there very * efficiently. It isn't really optimal, since several approximations * are taken in the interests of efficiency and simplicity. The code * here considers directly addressing the cursor, and also considers * local motions using left, right, up, down, tabs, backtabs, vertical * and horizontal addressing, and parameterized motions. It does not * consider using home down, or taking advantage of automatic margins on * any of the four directions. (Two of these directions, left and right, * are well defined by the am and bw capabilities, but up and down are * not defined, nor are tab or backtab off the ends.) * * General strategies considered: * CA Direct Cursor Addressing * LM Local Motions from the old position * HDR Home + Local Motions from upper left corner * CR CR + Local Motions from left margin * * Local Motions can include * Up cuu, cuu1, vpa * Down cud, cud1, vpa * Left cul, cul1, hpa, bs, cbt * Right cuf, cuf1, hpa, tab, char moved over */#ifdef DEBUG /* We don't want this debugging output now. */# undef DEBUG#endif/* #define mvcurdebug */#ifdef mvcurdebug# define DEBUG# define _outch ocFILE *outf;main(){ int oldrow, oldcol, newrow, newcol, n; newterm(getenv("TERM"), stdout, stdin); echo(); nocrmode(); nl(); outf = stdout; setbuf(stdout, NULL); for (;;) { printf("oldrow, oldcol, newrow, newcol: "); n = scanf("%d %d %d %d", &oldrow, &oldcol, &newrow, &newcol); if (n < 0) { endwin(); exit(1); } mvcur(oldrow, oldcol, newrow, newcol); }}_outch(ch){ printf("_outch '%s'\n", unctrl(ch));}#elseint _outch();#endifstatic int bare_lf_ok; /* bare_lf_ok is true if linefeed will work right */char *tparm();mvcur(oldrow, oldcol, newrow, newcol)int oldrow, oldcol, newrow, newcol;{ /* temporary costs of various submotions */ int home_right; /* cost to move from col 0 right to newcol */ int cur_right; /* motion from current postition to right */ int cur_left; /* motion from current postition to left */ int home_down; /* motion from line 0 downward */ int cur_down; /* motion from current position downward */ int cur_up; /* motion from current position upward */ /* costs of various full motions we consider */ int cost_ca; /* cost of directly addressing the cursor */ int cost_hdr; /* going home, local motions down & right */ int cost_cr; /* return, local motions up/down & right */ int cost_lm; /* local motions up/down & left/right */ int sgf;#ifdef DEBUG if(outf) fprintf(outf, "mvcur(oldrow=%d, oldcol=%d, newrow=%d, newcol=%d)\n", oldrow, oldcol, newrow, newcol);#endif /* Quick check for nothing to do - very common case. */ if (oldrow == newrow && oldcol == newcol) return;#ifndef NONSTANDARD bare_lf_ok = ((cur_term->Nttyb.c_oflag&ONLCR)==0);#else NONSTANDARD bare_lf_ok = 1;#endif NONSTANDARD /* Another common case: crlf */ if (newcol==0 && newrow==oldrow+1 && carriage_return && cursor_down) { /* * Just because bare_lf_ok is on doesn't mean cursor_down is * crlf. E.g. in the tty 40/2 it's escape B. The test below * will be wrong on a newline style terminal (!bare_lf_ok) * with no carriage_return where cursor_down is not crlf. * I have never seen such a terminal. */ if (oldcol > 0 && carriage_return) tputs(carriage_return, 1, _outch); tputs(cursor_down, 1, _outch); return; } /* Figure out costs of various component motions */ home_right = _loc_right(0 , newcol, 0, newcol); cur_right = _loc_right(oldcol, newcol, 0, newcol); cur_left = _loc_left (oldcol, newcol, 0); home_down = _loc_down (0 , newrow, 0, newcol); cur_down = _loc_down (oldrow, newrow, 0, newcol); cur_up = _loc_up (oldrow, newrow, 0);#ifdef DEBUG if(outf) fprintf(outf, "home_right %d, cur_right %d, cur_left %d, home_down %d, cur_down %d, cur_up %d\n", home_right, cur_right, cur_left, home_down, cur_down, cur_up);#endif /* 4 possible strategies: get costs for each */ cost_ca = _cost(Cursor_address); cost_hdr = _cost(Cursor_home) + home_down + home_right; /* 3rd and 4th strategies: local motions and with carriage return. */ if (newrow < oldrow) { if (newcol < oldcol) cost_lm = cur_left + cur_up; else cost_lm = cur_right + cur_up; cost_cr = _cost(Carriage_return) + cur_up + home_right; } else { if (newcol < oldcol) cost_lm = cur_left + cur_down; else cost_lm = cur_right + cur_down; if (cur_down >= INFINITY) cur_down = _loc_down(oldrow, newrow, 0, 0); cost_cr = _cost(Carriage_return) + cur_down + home_right; }#ifdef DEBUG if(outf) fprintf(outf, "cost_ca %d, cost_hdr %d, cost_cr %d, cost_lm %d\n", cost_ca, cost_hdr, cost_cr, cost_lm);#endif /* * Now we pick which one is cheapest and actually do it. * Note the ordering if they come out equal - this was * conciously chosen based on how visually distracting * it is to see the cursor bounce all over the screen, * I did not take into account approximation errors. */ if (cost_ca <= cost_hdr && cost_ca <= cost_cr && cost_ca <= cost_lm) { /* direct cursor addressing is cheapest */#ifdef DEBUG if(outf) fprintf(outf, "chose absolute cursor addressing\n");#endif tputs(tparm(cursor_address, newrow, newcol), 1, _outch); } else if (cost_lm <= cost_cr && cost_lm <= cost_hdr) { /* local motions are cheapest */#ifdef DEBUG if(outf) fprintf(outf, "chose local motions\n");#endif if (newcol > oldcol) { if (newrow > oldrow) (void) _loc_down(oldrow, newrow, 1, newcol); else (void) _loc_up(oldrow, newrow, 1); (void) _loc_right(oldcol, newcol, 1, newrow); } else { if (newrow > oldrow) (void) _loc_down(oldrow, newrow, 1, newcol); else (void) _loc_up(oldrow, newrow, 1); (void) _loc_left(oldcol, newcol, 1); } } else if (cost_cr <= cost_hdr) { /* carriage return + local motions are cheapest */#ifdef DEBUG if(outf) fprintf(outf, "chose carriage return + local motions\n");#endif tputs(carriage_return, 1, _outch); if (newrow > oldrow) (void) _loc_down(oldrow, newrow, 1, 0); else (void) _loc_up(oldrow, newrow, 1); (void) _loc_right(0, newcol, 1, newrow); } else { /* home + local motions are cheapest */#ifdef DEBUG if(outf) fprintf(outf, "chose home + local motions\n");#endif tputs(cursor_home, 1, _outch); (void) _loc_down(0, newrow, 1, newcol); (void) _loc_right(0, newcol, 1, newrow); }#ifdef DEBUG if(outf) fprintf(outf, "end of mvcur\n");#endif}/* * These four routines figure out what the cost of the most efficient * kind of local motion from the given row or column to the other given * row or column is. They return the cost, in characters. If the third * argument is 1, they actually do the motion. The row number is useful * if we're going to actually do the motion - that way we can look in * the screen image (if we have it) and just output the characters that * are already on the screen - this usually saves 50% over cursor_right. */static_loc_right(oldcol, newcol, domotion, row){ int c0, c1, c2, c3; int i, tabcol, ntabs, nright, nleft; /* notinsmode: we know for sure we aren't in insert char mode */ int notinsmode = SP && SP->phys_irm!=1; register struct line *rp; if (newcol < oldcol) /* can't go left with right motions */ return INFINITY; if (newcol == oldcol) return 0; /* already there - nothing to do */#ifdef DEBUG fprintf(outf, "SP %x, phys_irm %d, notinsmode %d\n", SP, SP->phys_irm, notinsmode);#endif /* * Code here and further down attempts to output the character that * is already on the screen to move right. */ if (notinsmode) _cost(Cursor_right) = 1; else _cost(Cursor_right) = _cost(Right_base); /* figure out various costs */ tabcol = (newcol+4)/8 * 8; /* round to nearest 8 */ /* tab past right margin is undefined */ if (tabcol >= columns) tabcol = (columns-1)/8 * 8; ntabs = (tabcol-oldcol+7)/8; if (ntabs <= 0) tabcol = oldcol; if (tabcol < newcol) { /* some tabs plus some rights */ nright = newcol - tabcol; c1 = ntabs*_cost(Tab) + nright*_cost(Cursor_right); } else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -