deleted references to NONL.
[unix-history] / usr / src / lib / libcurses / cr_put.c
CommitLineData
c2affd4a 1/*
2f14f200
KB
2 * Copyright (c) 1981 Regents of the University of California.
3 * All rights reserved.
4 *
c07973a2 5 * %sccs.include.redist.c%
c2affd4a
KM
6 */
7
8#ifndef lint
73405ee7 9static char sccsid[] = "@(#)cr_put.c 5.8 (Berkeley) %G%";
49b2da99 10#endif /* not lint */
c2affd4a 11
49b2da99 12#include <curses.h>
a2af4b61 13#include <string.h>
73405ee7 14#include <termios.h>
9b9f600e 15
49b2da99 16#define HARDTABS 8
9b9f600e
KA
17
18/*
49b2da99
KB
19 * Terminal driving and line formatting routines. Basic motion optimizations
20 * are done here as well as formatting lines (printing of control characters,
9b9f600e 21 * line numbering and the like).
9b9f600e
KA
22 */
23
49b2da99
KB
24static void fgoto __P((void));
25static int plod __P((int));
26static void plodput __P((int));
27static int tabcol __P((int, int));
28
9b9f600e 29/*
49b2da99
KB
30 * Sync the position of the output cursor. Most work here is rounding for
31 * terminal boundaries getting the column position implied by wraparound or
32 * the lack thereof and rolling up the screen to get destline on the screen.
9b9f600e
KA
33 */
34
49b2da99 35static int outcol, outline, destcol, destline;
9b9f600e 36
49b2da99 37WINDOW *_win;
9b9f600e 38
a2af4b61 39int
9b9f600e 40mvcur(ly, lx, y, x)
49b2da99
KB
41 int ly, lx, y, x;
42{
9b9f600e 43#ifdef DEBUG
49b2da99
KB
44 __TRACE("mvcur: moving cursor from (%d, %d) to (%d, %d)\n",
45 ly, lx, y, x);
9b9f600e
KA
46#endif
47 destcol = x;
48 destline = y;
49 outcol = lx;
50 outline = ly;
51 fgoto();
49b2da99 52 return (OK);
9b9f600e
KA
53}
54
49b2da99 55static void
00334184
KA
56fgoto()
57{
49b2da99
KB
58 register int c, l;
59 register char *cgp;
9b9f600e 60
072ff498 61 if (destcol >= COLS) {
9b9f600e
KA
62 destline += destcol / COLS;
63 destcol %= COLS;
64 }
072ff498 65 if (outcol >= COLS) {
9b9f600e
KA
66 l = (outcol + 1) / COLS;
67 outline += l;
68 outcol %= COLS;
69 if (AM == 0) {
70 while (l > 0) {
49b2da99 71 if (__pfast)
00334184 72 if (CR)
49b2da99 73 tputs(CR, 0, __cputchar);
00334184 74 else
49b2da99 75 putchar('\r');
00334184 76 if (NL)
49b2da99 77 tputs(NL, 0, __cputchar);
00334184 78 else
49b2da99 79 putchar('\n');
9b9f600e
KA
80 l--;
81 }
82 outcol = 0;
83 }
84 if (outline > LINES - 1) {
85 destline -= outline - (LINES - 1);
86 outline = LINES - 1;
87 }
88 }
072ff498 89 if (destline >= LINES) {
9b9f600e
KA
90 l = destline;
91 destline = LINES - 1;
92 if (outline < LINES - 1) {
93 c = destcol;
49b2da99 94 if (__pfast == 0 && !CA)
9b9f600e
KA
95 destcol = 0;
96 fgoto();
97 destcol = c;
98 }
072ff498 99 while (l >= LINES) {
49b2da99
KB
100 /* The following linefeed (or simulation thereof) is
101 * supposed to scroll up the screen, since we are on
102 * the bottom line. We make the assumption that
103 * linefeed will scroll. If ns is in the capability
104 * list this won't work. We should probably have an
105 * sc capability but sf will generally take the place
106 * if it works.
107 *
108 * Superbee glitch: in the middle of the screen have
109 * to use esc B (down) because linefeed screws up in
110 * "Efficient Paging" (what a joke) mode (which is
111 * essential in some SB's because CRLF mode puts
112 * garbage in at end of memory), but you must use
113 * linefeed to scroll since down arrow won't go past
114 * memory end. I turned this off after recieving Paul
115 * Eggert's Superbee description which wins better.
00334184 116 */
49b2da99
KB
117 if (NL /* && !XB */ && __pfast)
118 tputs(NL, 0, __cputchar);
00334184 119 else
49b2da99 120 putchar('\n');
9b9f600e 121 l--;
49b2da99 122 if (__pfast == 0)
9b9f600e
KA
123 outcol = 0;
124 }
125 }
00334184 126 if (destline < outline && !(CA || UP))
9b9f600e 127 destline = outline;
072ff498 128 if (CA) {
00334184 129 cgp = tgoto(CM, destcol, destline);
9b9f600e
KA
130 if (plod(strlen(cgp)) > 0)
131 plod(0);
132 else
49b2da99
KB
133 tputs(cgp, 0, __cputchar);
134 } else
9b9f600e
KA
135 plod(0);
136 outline = destline;
137 outcol = destcol;
138}
00334184
KA
139/*
140 * Move (slowly) to destination.
141 * Hard thing here is using home cursor on really deficient terminals.
142 * Otherwise just use cursor motions, hacking use of tabs and overtabbing
143 * and backspace.
144 */
9b9f600e 145
00334184 146static int plodcnt, plodflg;
9b9f600e 147
49b2da99 148static void
00334184 149plodput(c)
49b2da99 150 int c;
00334184
KA
151{
152 if (plodflg)
49b2da99 153 --plodcnt;
00334184 154 else
49b2da99 155 putchar(c);
00334184 156}
9b9f600e 157
49b2da99 158static int
9b9f600e 159plod(cnt)
49b2da99 160 int cnt;
00334184 161{
49b2da99 162 register int i, j, k, soutcol, soutline;
9b9f600e
KA
163
164 plodcnt = plodflg = cnt;
165 soutcol = outcol;
166 soutline = outline;
00334184 167 /*
49b2da99 168 * Consider homing and moving down/right from there, vs. moving
00334184
KA
169 * directly with local motions to the right spot.
170 */
9b9f600e 171 if (HO) {
00334184 172 /*
49b2da99
KB
173 * i is the cost to home and tab/space to the right to get to
174 * the proper column. This assumes ND space costs 1 char. So
175 * i + destcol is cost of motion with home.
00334184 176 */
9b9f600e
KA
177 if (GT)
178 i = (destcol / HARDTABS) + (destcol % HARDTABS);
179 else
180 i = destcol;
49b2da99
KB
181
182 /* j is cost to move locally without homing. */
00334184
KA
183 if (destcol >= outcol) { /* if motion is to the right */
184 j = destcol / HARDTABS - outcol / HARDTABS;
185 if (GT && j)
186 j += destcol % HARDTABS;
187 else
188 j = destcol - outcol;
49b2da99 189 } else
00334184 190 /* leftward motion only works if we can backspace. */
9b9f600e 191 if (outcol - destcol <= i && (BS || BC))
49b2da99
KB
192 /* Cheaper to backspace. */
193 i = j = outcol - destcol;
9b9f600e 194 else
49b2da99
KB
195 /* Impossibly expensive. */
196 j = i + 1;
00334184 197
49b2da99 198 /* k is the absolute value of vertical distance. */
9b9f600e
KA
199 k = outline - destline;
200 if (k < 0)
201 k = -k;
202 j += k;
00334184 203
49b2da99 204 /* Decision. We may not have a choice if no UP. */
00334184
KA
205 if (i + destline < j || (!UP && destline < outline)) {
206 /*
207 * Cheaper to home. Do it now and pretend it's a
208 * regular local motion.
209 */
9b9f600e
KA
210 tputs(HO, 0, plodput);
211 outcol = outline = 0;
49b2da99 212 } else if (LL) {
00334184
KA
213 /*
214 * Quickly consider homing down and moving from there.
215 * Assume cost of LL is 2.
216 */
9b9f600e 217 k = (LINES - 1) - destline;
49b2da99 218 if (i + k + 2 < j && (k <= 0 || UP)) {
9b9f600e
KA
219 tputs(LL, 0, plodput);
220 outcol = 0;
221 outline = LINES - 1;
222 }
223 }
49b2da99
KB
224 } else
225 /* No home and no up means it's impossible. */
00334184 226 if (!UP && destline < outline)
49b2da99 227 return (-1);
9b9f600e 228 if (GT)
495cf1aa 229 i = destcol % HARDTABS + destcol / HARDTABS;
9b9f600e
KA
230 else
231 i = destcol;
49b2da99
KB
232#ifdef notdef
233 if (BT && outcol > destcol &&
234 (j = (((outcol+7) & ~7) - destcol - 1) >> 3)) {
9b9f600e
KA
235 j *= (k = strlen(BT));
236 if ((k += (destcol&7)) > 4)
237 j += 8 - (destcol&7);
238 else
239 j += k;
00334184
KA
240 }
241 else
49b2da99 242#endif
9b9f600e 243 j = outcol - destcol;
49b2da99 244
9b9f600e 245 /*
49b2da99
KB
246 * If we will later need a \n which will turn into a \r\n by the
247 * system or the terminal, then don't bother to try to \r.
9b9f600e 248 */
73405ee7 249 if ((!(origtermio.c_oflag & ONLCR) || !__pfast) && outline < destline)
9b9f600e 250 goto dontcr;
49b2da99 251
9b9f600e 252 /*
49b2da99
KB
253 * If the terminal will do a \r\n and there isn't room for it, then
254 * we can't afford a \r.
9b9f600e
KA
255 */
256 if (NC && outline >= destline)
257 goto dontcr;
49b2da99 258
9b9f600e 259 /*
49b2da99
KB
260 * If it will be cheaper, or if we can't back up, then send a return
261 * preliminarily.
9b9f600e
KA
262 */
263 if (j > i + 1 || outcol > destcol && !BS && !BC) {
00334184 264 /*
49b2da99
KB
265 * BUG: this doesn't take the (possibly long) length of CR
266 * into account.
00334184
KA
267 */
268 if (CR)
269 tputs(CR, 0, plodput);
270 else
271 plodput('\r');
9b9f600e 272 if (NC) {
072ff498
KM
273 if (NL)
274 tputs(NL, 0, plodput);
275 else
276 plodput('\n');
9b9f600e
KA
277 outline++;
278 }
279 outcol = 0;
280 }
49b2da99
KB
281
282dontcr: while (outline < destline) {
9b9f600e 283 outline++;
072ff498
KM
284 if (NL)
285 tputs(NL, 0, plodput);
286 else
287 plodput('\n');
9b9f600e
KA
288 if (plodcnt < 0)
289 goto out;
73405ee7 290 if (!(origtermio.c_oflag & ONLCR) || __pfast == 0)
9b9f600e
KA
291 outcol = 0;
292 }
293 if (BT)
294 k = strlen(BT);
295 while (outcol > destcol) {
296 if (plodcnt < 0)
297 goto out;
49b2da99 298#ifdef notdef
00334184 299 if (BT && outcol - destcol > k + 4) {
9b9f600e
KA
300 tputs(BT, 0, plodput);
301 outcol--;
302 outcol &= ~7;
303 continue;
304 }
49b2da99 305#endif
9b9f600e
KA
306 outcol--;
307 if (BC)
308 tputs(BC, 0, plodput);
309 else
310 plodput('\b');
311 }
312 while (outline > destline) {
313 outline--;
314 tputs(UP, 0, plodput);
315 if (plodcnt < 0)
316 goto out;
317 }
318 if (GT && destcol - outcol > 1) {
495cf1aa
KA
319 for (;;) {
320 i = tabcol(outcol, HARDTABS);
321 if (i > destcol)
322 break;
9b9f600e
KA
323 if (TA)
324 tputs(TA, 0, plodput);
325 else
326 plodput('\t');
327 outcol = i;
328 }
329 if (destcol - outcol > 4 && i < COLS && (BC || BS)) {
330 if (TA)
331 tputs(TA, 0, plodput);
332 else
333 plodput('\t');
334 outcol = i;
335 while (outcol > destcol) {
336 outcol--;
337 if (BC)
338 tputs(BC, 0, plodput);
339 else
340 plodput('\b');
341 }
342 }
343 }
344 while (outcol < destcol) {
00334184 345 /*
49b2da99
KB
346 * Move one char to the right. We don't use ND space because
347 * it's better to just print the char we are moving over.
00334184 348 */
9b9f600e 349 if (_win != NULL)
49b2da99 350 if (plodflg) /* Avoid a complex calculation. */
9b9f600e
KA
351 plodcnt--;
352 else {
1fe7814b 353 i = curscr->_y[outline][outcol];
49b2da99
KB
354 if ((i & _STANDOUT) ==
355 (curscr->_flags & _STANDOUT))
356 putchar(i & 0177);
9b9f600e
KA
357 else
358 goto nondes;
359 }
360 else
49b2da99
KB
361nondes: if (ND)
362 tputs(ND, 0, plodput);
363 else
364 plodput(' ');
9b9f600e
KA
365 outcol++;
366 if (plodcnt < 0)
367 goto out;
368 }
49b2da99
KB
369
370out: if (plodflg) {
9b9f600e
KA
371 outcol = soutcol;
372 outline = soutline;
373 }
49b2da99 374 return (plodcnt);
9b9f600e
KA
375}
376
377/*
00334184
KA
378 * Return the column number that results from being in column col and
379 * hitting a tab, where tabs are set every ts columns. Work right for
380 * the case where col > COLS, even if ts does not divide COLS.
9b9f600e 381 */
49b2da99 382static int
00334184 383tabcol(col, ts)
49b2da99 384 int col, ts;
00334184 385{
a2af4b61 386 int offset;
9b9f600e 387
00334184
KA
388 if (col >= COLS) {
389 offset = COLS * (col / COLS);
390 col -= offset;
49b2da99 391 } else
00334184 392 offset = 0;
49b2da99 393 return (col + ts - (col % ts) + offset);
9b9f600e 394}