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