* Copyright (c) 1981, 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
[] = "@(#)cr_put.c 8.2 (Berkeley) 1/9/94";
* Terminal driving and line formatting routines. Basic motion optimizations
* are done here as well as formatting lines (printing of control characters,
* line numbering and the like).
/* Stub function for the users. */
return (__mvcur(ly
, lx
, y
, x
, 0));
static void fgoto
__P((int));
static int plod
__P((int, int));
static void plodput
__P((int));
static int tabcol
__P((int, int));
static int outcol
, outline
, destcol
, destline
;
* Sync the position of the output cursor. Most work here is rounding for
* terminal boundaries getting the column position implied by wraparound or
* the lack thereof and rolling up the screen to get destline on the screen.
__mvcur(ly
, lx
, y
, x
, in_refresh
)
int ly
, lx
, y
, x
, in_refresh
;
__CTRACE("mvcur: moving cursor from (%d, %d) to (%d, %d)\n",
destline
+= destcol
/ COLS
;
tputs(CR
, 0, __cputchar
);
tputs(NL
, 0, __cputchar
);
if (outline
> LINES
- 1) {
destline
-= outline
- (LINES
- 1);
if (outline
< LINES
- 1) {
/* The following linefeed (or simulation thereof) is
* supposed to scroll up the screen, since we are on
* the bottom line. We make the assumption that
* linefeed will scroll. If ns is in the capability
* list this won't work. We should probably have an
* sc capability but sf will generally take the place
* Superbee glitch: in the middle of the screen have
* to use esc B (down) because linefeed screws up in
* "Efficient Paging" (what a joke) mode (which is
* essential in some SB's because CRLF mode puts
* garbage in at end of memory), but you must use
* linefeed to scroll since down arrow won't go past
* memory end. I turned this off after recieving Paul
* Eggert's Superbee description which wins better.
if (NL
/* && !XB */ && __pfast
)
tputs(NL
, 0, __cputchar
);
if (destline
< outline
&& !(CA
|| UP
))
cgp
= tgoto(CM
, destcol
, destline
);
* Need this condition due to inconsistent behavior
* of backspace on the last column.
if (outcol
!= COLS
- 1 && plod(strlen(cgp
), in_refresh
) > 0)
tputs(cgp
, 0, __cputchar
);
* Move (slowly) to destination.
* Hard thing here is using home cursor on really deficient terminals.
* Otherwise just use cursor motions, hacking use of tabs and overtabbing
static int plodcnt
, plodflg
;
register int i
, j
, k
, soutcol
, soutline
;
* Consider homing and moving down/right from there, vs. moving
* directly with local motions to the right spot.
* i is the cost to home and tab/space to the right to get to
* the proper column. This assumes ND space costs 1 char. So
* i + destcol is cost of motion with home.
i
= (destcol
/ HARDTABS
) + (destcol
% HARDTABS
);
/* j is cost to move locally without homing. */
if (destcol
>= outcol
) { /* if motion is to the right */
j
= destcol
/ HARDTABS
- outcol
/ HARDTABS
;
/* leftward motion only works if we can backspace. */
if (outcol
- destcol
<= i
&& (BS
|| BC
))
/* Cheaper to backspace. */
i
= j
= outcol
- destcol
;
/* Impossibly expensive. */
/* k is the absolute value of vertical distance. */
/* Decision. We may not have a choice if no UP. */
if (i
+ destline
< j
|| (!UP
&& destline
< outline
)) {
* Cheaper to home. Do it now and pretend it's a
* Quickly consider homing down and moving from there.
* Assume cost of LL is 2.
k
= (LINES
- 1) - destline
;
if (i
+ k
+ 2 < j
&& (k
<= 0 || UP
)) {
/* No home and no up means it's impossible. */
if (!UP
&& destline
< outline
)
i
= destcol
% HARDTABS
+ destcol
/ HARDTABS
;
if (BT
&& outcol
> destcol
&&
(j
= (((outcol
+7) & ~7) - destcol
- 1) >> 3)) {
if ((k
+= (destcol
&7)) > 4)
* If we will later need a \n which will turn into a \r\n by the
* system or the terminal, then don't bother to try to \r.
if ((NONL
|| !__pfast
) && outline
< destline
)
* If the terminal will do a \r\n and there isn't room for it, then
if (NC
&& outline
>= destline
)
* If it will be cheaper, or if we can't back up, then send a return
if (j
> i
+ 1 || outcol
> destcol
&& !BS
&& !BC
) {
* BUG: this doesn't take the (possibly long) length of CR
dontcr
: while (outline
< destline
) {
if (NONL
|| __pfast
== 0)
while (outcol
> destcol
) {
if (BT
&& outcol
- destcol
> k
+ 4) {
while (outline
> destline
) {
if (GT
&& destcol
- outcol
> 1) {
i
= tabcol(outcol
, HARDTABS
);
if (destcol
- outcol
> 4 && i
< COLS
&& (BC
|| BS
)) {
while (outcol
> destcol
) {
while (outcol
< destcol
) {
* Move one char to the right. We don't use ND space because
* it's better to just print the char we are moving over.
if (plodflg
) /* Avoid a complex calculation. */
i
= curscr
->lines
[outline
]->line
[outcol
].ch
;
if ((curscr
->lines
[outline
]->line
[outcol
].attr
(curscr
->flags
& __WSTANDOUT
))
* Return the column number that results from being in column col and
* hitting a tab, where tabs are set every ts columns. Work right for
* the case where col > COLS, even if ts does not divide COLS.
offset
= COLS
* (col
/ COLS
);
return (col
+ ts
- (col
% ts
) + offset
);