2 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
6 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
7 /* All Rights Reserved */
10 * Copyright (c) 1980 Regents of the University of California.
11 * All rights reserved. The Berkeley software License Agreement
12 * specifies the terms and conditions for redistribution.
15 #pragma ident "%Z%%M% %I% %E% SMI"
21 sccsid
[] = "@(#)cr_put.c 1.7 89/03/27 SMI"; /* from UCB 5.1 85/06/07 */
30 /* forward declarations */
32 /* should be static, but we may have prior application-dependency, sigh! */
39 * Terminal driving and line formatting routines.
40 * Basic motion optimizations are done here as well
41 * as formatting of lines (printing of control characters,
42 * line numbering and the like).
46 * Sync the position of the output cursor.
47 * Most work here is rounding for terminal boundaries getting the
48 * column position implied by wraparound or the lack thereof and
49 * rolling up the screen to get destline on the screen.
52 static int outcol
, outline
, destcol
, destline
;
57 mvcur(int ly
, int lx
, int y
, int x
)
60 fprintf(outf
, "MVCUR: moving cursor from (%d,%d) to (%d,%d)\n",
77 if (destcol
>= COLS
) {
78 destline
+= destcol
/ COLS
;
82 l
= (outcol
+ 1) / COLS
;
91 (void) _putchar('\r');
95 (void) _putchar('\n');
100 if (outline
> LINES
- 1) {
101 destline
-= outline
- (LINES
- 1);
105 if (destline
>= LINES
) {
107 destline
= LINES
- 1;
108 if (outline
< LINES
- 1) {
110 if (_pfast
== 0 && !CA
)
117 * The following linefeed (or simulation thereof)
118 * is supposed to scroll up the screen, since we
119 * are on the bottom line. We make the assumption
120 * that linefeed will scroll. If ns is in the
121 * capability list this won't work. We should
122 * probably have an sc capability but sf will
123 * generally take the place if it works.
125 * Superbee glitch: in the middle of the screen we
126 * have to use esc B (down) because linefeed screws up
127 * in "Efficient Paging" (what a joke) mode (which is
128 * essential in some SB's because CRLF mode puts garbage
129 * in at end of memory), but you must use linefeed to
130 * scroll since down arrow won't go past memory end.
131 * I turned this off after recieving Paul Eggert's
132 * Superbee description which wins better.
134 if (NL
/* && !XB */ && _pfast
)
137 (void) _putchar('\n');
143 if (destline
< outline
&& !(CA
|| UP
))
146 cgp
= tgoto(CM
, destcol
, destline
);
147 if (plod((int)strlen(cgp
)) > 0)
150 (void) tputs(cgp
, 0, _putchar
);
159 * Move (slowly) to destination.
160 * Hard thing here is using home cursor on really deficient terminals.
161 * Otherwise just use cursor motions, hacking use of tabs and overtabbing
165 static int plodcnt
, plodflg
;
181 int soutcol
, soutline
;
183 plodcnt
= plodflg
= cnt
;
187 * Consider homing and moving down/right from there, vs moving
188 * directly with local motions to the right spot.
192 * i is the cost to home and tab/space to the right to
193 * get to the proper column. This assumes ND space costs
194 * 1 char. So i+destcol is cost of motion with home.
197 i
= (destcol
/ HARDTABS
) + (destcol
% HARDTABS
);
201 * j is cost to move locally without homing
203 if (destcol
>= outcol
) { /* if motion is to the right */
204 j
= destcol
/ HARDTABS
- outcol
/ HARDTABS
;
206 j
+= destcol
% HARDTABS
;
208 j
= destcol
- outcol
;
211 /* leftward motion only works if we can backspace. */
212 if (outcol
- destcol
<= i
&& (BS
|| BC
))
213 i
= j
= outcol
- destcol
;
214 /* cheaper to backspace */
216 j
= i
+ 1; /* impossibly expensive */
218 /* k is the absolute value of vertical distance */
219 k
= outline
- destline
;
225 * Decision. We may not have a choice if no UP.
227 if (i
+ destline
< j
|| (!UP
&& destline
< outline
)) {
229 * Cheaper to home. Do it now and pretend it's a
230 * regular local motion.
232 (void) tputs(HO
, 0, plodput
);
233 outcol
= outline
= 0;
236 * Quickly consider homing down and moving from there.
237 * Assume cost of LL is 2.
239 k
= (LINES
- 1) - destline
;
240 if (i
+ k
+ 2 < j
&& (k
<= 0 || UP
)) {
241 (void) tputs(LL
, 0, plodput
);
249 * No home and no up means it's impossible.
251 if (!UP
&& destline
< outline
)
254 i
= destcol
% HARDTABS
+ destcol
/ HARDTABS
;
258 * if (BT && outcol > destcol &&
259 * (j = (((outcol+7) & ~7) - destcol - 1) >> 3)) {
260 * j *= (k = (int)strlen(BT));
261 * if ((k += (destcol&7)) > 4)
262 * j += 8 - (destcol&7);
268 j
= outcol
- destcol
;
270 * If we will later need a \n which will turn into a \r\n by
271 * the system or the terminal, then don't bother to try to \r.
273 if ((NONL
|| !_pfast
) && outline
< destline
)
276 * If the terminal will do a \r\n and there isn't room for it,
277 * then we can't afford a \r.
279 if (NC
&& outline
>= destline
)
282 * If it will be cheaper, or if we can't back up, then send
283 * a return preliminarily.
285 if (j
> i
+ 1 || outcol
> destcol
&& !BS
&& !BC
) {
287 * BUG: this doesn't take the (possibly long) length
288 * of CR into account.
291 (void) tputs(CR
, 0, plodput
);
293 (void) plodput('\r');
296 (void) tputs(NL
, 0, plodput
);
298 (void) plodput('\n');
304 while (outline
< destline
) {
307 (void) tputs(NL
, 0, plodput
);
309 (void) plodput('\n');
312 if (NONL
|| _pfast
== 0)
317 while (outcol
> destcol
) {
321 * if (BT && outcol - destcol > k + 4) {
322 * (void) tputs(BT, 0, plodput);
330 (void) tputs(BC
, 0, plodput
);
332 (void) plodput('\b');
334 while (outline
> destline
) {
336 (void) tputs(UP
, 0, plodput
);
340 if (GT
&& destcol
- outcol
> 1) {
342 i
= tabcol(outcol
, HARDTABS
);
346 (void) tputs(TA
, 0, plodput
);
348 (void) plodput('\t');
351 if (destcol
- outcol
> 4 && i
< COLS
&& (BC
|| BS
)) {
353 (void) tputs(TA
, 0, plodput
);
355 (void) plodput('\t');
357 while (outcol
> destcol
) {
360 (void) tputs(BC
, 0, plodput
);
362 (void) plodput('\b');
366 while (outcol
< destcol
) {
368 * move one char to the right. We don't use ND space
369 * because it's better to just print the char we are
373 if (plodflg
) /* avoid a complex calculation */
376 i
= curscr
->_y
[outline
][outcol
];
377 if ((i
&_STANDOUT
) == (curscr
->_flags
&_STANDOUT
))
378 (void) _putchar(i
& 0177);
385 (void) tputs(ND
, 0, plodput
);
401 * Return the column number that results from being in column col and
402 * hitting a tab, where tabs are set every ts columns. Work right for
403 * the case where col > COLS, even if ts does not divide COLS.
407 tabcol(int col
, int ts
)
412 offset
= COLS
* (col
/ COLS
);
417 return (col
+ ts
- (col
% ts
) + offset
);