* Copyright (c) 1980, 1993
* The Regents of the University of California. All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
static char sccsid
[] = "@(#)move.c 8.1 (Berkeley) 7/19/93";
/*************************************************************************
* This set of subroutines moves a cursor to a predefined
* location, independent of the terminal type. If the
* terminal has an addressable cursor, it uses it. If
* not, it optimizes for tabs (currently) even if you don't
* At all times the current address of the cursor must be maintained,
* and that is available as structure cursor.
* The following calls are allowed:
* move(sp) move to point sp.
* down() move down one line.
* bs() move left one space (except column 0).
* nd() move right one space(no write).
* ll() move to lower left corner of screen.
* cr() carriage return (no line feed).
* pr() just like standard printf, but keeps track
* of cursor position. (Uses pstring).
* apr() same as printf, but first argument is &point.
* pstring(s) output the string of printing characters.
* However, '\r' is interpreted to mean return
* to column of origination AND do linefeed.
* putpad(str) calls tputs to output character with proper
* outch() the output routine for a character used by
* tputs. It just calls putchar.
* pch(ch) output character to screen and update
* cursor address (must be a standard
* printing character). WILL SCROLL.
* pchar(ps,ch) prints one character if it is on the
* screen at the specified location;
* otherwise, dumps it.(no wrap-around).
* getcap() initializes strings for later calls.
* cap(string) outputs the string designated in the termcap
* data base. (Should not move the cursor.)
* done() returns the terminal to intial state and exits.
* point(&p,x,y) return point set to x,y.
* baudrate(x) returns the baudrate of the terminal.
* delay(t) causes an approximately constant delay
* independent of baudrate.
* Duration is ~ t/20 seconds.
******************************************************************************/
if (sp
->line
<0 || sp
->col
<0 || sp
->col
> COLUMNS
){
pr("move to [%d,%d]?",sp
->line
,sp
->col
);
move(point(&z
,sp
->col
,LINES
-1));
while(sp
->line
-- >= LINES
)putchar('\n');
char *cmstr
= tgoto(CM
, sp
->col
, sp
->line
);
CMlength
= strlen(cmstr
);
if(cursor
.line
== sp
->line
){
distance
= sp
->col
- cursor
.col
;
if(distance
== 0)return; /* Already there! */
if(distance
> 0){ /* Moving to the right */
if(distance
*NDlength
< CMlength
){
} else { /* Moving to the left */
if (-distance
*BSlength
< CMlength
){
/* No more optimizations on same row. */
distance
= sp
->col
- cursor
.col
;
distance
= distance
> 0 ?
distance
*NDlength
: -distance
* BSlength
;
pr("ERROR: distance is negative: %d",distance
);
distance
+= abs(sp
->line
- cursor
.line
);
if(distance
>= CMlength
){
* If we get here we have a terminal that can't cursor
* address but has local motions or one which can cursor
* address but can get there quicker with local motions.
if (cursor
.line
> LINES
|| cursor
.line
<0 ||
cursor
.col
<0 || cursor
.col
> COLUMNS
)
pr("ERROR: cursor is at %d,%d\n",
if (sp
->line
> LINES
|| sp
->line
<0 ||
sp
->col
<0 || sp
->col
> COLUMNS
)
pr("ERROR: target is %d,%d\n",sp
->line
,sp
->col
);
if (sp
->line
== cursor
.line
){
if (sp
->col
> cursor
.col
)right(sp
);
distance
= (cursor
.col
-sp
->col
)*BSlength
;
(distance
> tfield
+((sp
->col
)&7)*NDlength
)
(((cursor
.col
)*NDlength
) < distance
)
while(cursor
.col
> sp
->col
) bs();
if (cursor
.col
- sp
->col
> (cursor
.col
>> 3)){
if (cursor
.col
== 0)f
= 0;
else f
= cursor
.col
>> 3;
if (((sp
->line
<< 1) + 1 < cursor
.line
- f
) && (HO
!= 0)){
* (sp->line + f > cursor.line - sp->line)
cursor
.col
= cursor
.line
= 0;
if (((sp
->line
<< 1) > cursor
.line
+ LINES
+1 + f
) && (LL
!= 0)){
/* home,rlf quicker than lf
* (LINES+1 - sp->line + f < sp->line - cursor.line)
if (cursor
.line
> f
+ 1){
/* is home faster than wraparound lf?
* (cursor.line + 20 - sp->line > 21 - sp->line + f)
if ((LL
!= 0) && (sp
->line
> cursor
.line
+ (LINES
>> 1) - 1))
while(sp
->line
> cursor
.line
)down();
while(sp
->line
< cursor
.line
)up();
gto(sp
); /*can recurse since cursor.line = sp->line */
if (sp
->col
< cursor
.col
)
pr("ERROR:right() can't move left\n");
if(TA
){ /* If No Tabs: can't send tabs because ttydrive
* loses count with control characters.
* This code is useful for a terminal which wraps around on backspaces.
* (Mine does.) Unfortunately, this is not specified in termcap, and
* most terminals don't work that way. (Of course, most terminals
* have addressible cursors, too).
((sp
->col
<< 1) - field
> (COLUMNS
- 8) << 1 )
cursor
.col
= COLUMNS
+ 1;
while(cursor
.col
> sp
->col
)bs();
if (cursor
.line
!= 0) outch('\n');
cursor
.col
= ++field
<< 3;
tabcol
= (cursor
.col
|7) + 1;
strlength
= (tabcol
- sp
->col
)*BSlength
+ 1;
/* length of sequence to overshoot */
if (((sp
->col
- cursor
.col
)*NDlength
> strlength
) &&
cursor
.col
= (cursor
.col
| 7) + 1;
while(cursor
.col
> sp
->col
)bs();
while (sp
->col
> cursor
.col
){
cursor
.col
=cursor
.line
=0;
cursor
.col
= cursor
.line
= 0;
if(LL
!= NULL
&& LINES
==l
){
if (cursor
.line
>= LINES
)cursor
.line
=LINES
-1;
if (cursor
.col
== COLUMNS
+1){
if (cursor
.line
>= LINES
)cursor
.line
=LINES
-1;
if(++cursor
.col
>= COLUMNS
&& AM
) {
apr(struct point
*ps
, const char *fmt
, ...)
p
.line
= ps
->line
+1; p
.col
= ps
->col
+1;
(void)vsprintf(str
, fmt
, ap
);
(void)vsprintf(str
, fmt
, ap
);
move(point(&z
,0,cursor
.line
+1));
move(point(&z
,stcol
,cursor
.line
+1));
z
.col
= (((cursor
.col
+ 8) >> 3) << 3);
p
.col
= ps
->col
+ 1; p
.line
= ps
->line
+ 1;
k
= baudrate() * t
/ 300;
ioctl(0, TIOCSLTC
, &olttyc
);
ioctl(0, TIOCSLTC
, &nlttyc
);
struct point
*point(ps
,x
,y
)
fprintf(stderr
, "No TERM in environment\n");
switch (tgetent(tbuf
, term
)) {
fprintf(stderr
, "Cannot open termcap file\n");
fprintf(stderr
, "%s: unknown terminal", term
);
if (ioctl(0, TIOCGWINSZ
, (char *) &win
) < 0 ||
(LINES
= win
.ws_row
) == 0 || (COLUMNS
= win
.ws_col
) == 0) {
if (BS
== 0 && tgetflag("bs"))
if (TA
== 0 && tgetflag("pt"))
/* NOTE: If KL, KR, KU, and KD are not
* all the same length, some problems
* may arise, since tests are made on
xPC
= tgetstr("pc", &ap
);
(HO
== 0 | UP
==0 || BS
==0 || ND
==0)) {
fprintf(stderr
, "Terminal must have addressible ");
fprintf(stderr
, "cursor or home + 4 local motions\n");
fprintf(stderr
, "Terminal must not overstrike\n");
if (LINES
<= 0 || COLUMNS
<= 0) {
fprintf(stderr
, "Must know the screen size\n");
new.sg_flags
&= ~(ECHO
|CRMOD
|ALLDELAY
|XTABS
);
ioctl(0, TIOCGLTC
, &olttyc
);
nlttyc
.t_dsuspc
= '\377';
if ((orig
.sg_flags
& XTABS
) == XTABS
) TA
=0;
point(&cursor
,0,LINES
-1);