clean up imp code after fixing problems
[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 *
00334184 14 * %G% (Berkeley) @(#)cr_put.c 1.2
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 /*
226 * No home and no up means it's impossible, so we return an
227 * incredibly big number to make cursor motion win out.
228 */
229 if (!UP && destline < outline)
230 return (500);
9b9f600e 231 if (GT)
00334184
KA
232 i = destcol % HARDTABS
233 + destcol / HARDTABS;
9b9f600e
KA
234 else
235 i = destcol;
236/*
237 if (BT && outcol > destcol && (j = (((outcol+7) & ~7) - destcol - 1) >> 3)) {
238 j *= (k = strlen(BT));
239 if ((k += (destcol&7)) > 4)
240 j += 8 - (destcol&7);
241 else
242 j += k;
00334184
KA
243 }
244 else
9b9f600e
KA
245*/
246 j = outcol - destcol;
247 /*
248 * If we will later need a \n which will turn into a \r\n by
249 * the system or the terminal, then don't bother to try to \r.
250 */
251 if ((NONL || !_pfast) && outline < destline)
252 goto dontcr;
253 /*
254 * If the terminal will do a \r\n and there isn't room for it,
255 * then we can't afford a \r.
256 */
257 if (NC && outline >= destline)
258 goto dontcr;
259 /*
260 * If it will be cheaper, or if we can't back up, then send
261 * a return preliminarily.
262 */
263 if (j > i + 1 || outcol > destcol && !BS && !BC) {
00334184
KA
264 /*
265 * BUG: this doesn't take the (possibly long) length
266 * of CR into account.
267 */
268 if (CR)
269 tputs(CR, 0, plodput);
270 else
271 plodput('\r');
9b9f600e 272 if (NC) {
00334184
KA
273 if (NL)
274 tputs(NL, 0, plodput);
275 else
276 plodput('\n');
9b9f600e
KA
277 outline++;
278 }
279 outcol = 0;
280 }
281dontcr:
282 while (outline < destline) {
283 outline++;
00334184
KA
284 if (NL && _pfast)
285 tputs(NL, 0, plodput);
286 else
287 plodput('\n');
9b9f600e
KA
288 if (plodcnt < 0)
289 goto out;
290 if (NONL || _pfast == 0)
291 outcol = 0;
292 }
293 if (BT)
294 k = strlen(BT);
295 while (outcol > destcol) {
296 if (plodcnt < 0)
297 goto out;
298/*
00334184 299 if (BT && outcol - destcol > k + 4) {
9b9f600e
KA
300 tputs(BT, 0, plodput);
301 outcol--;
302 outcol &= ~7;
303 continue;
304 }
305*/
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) {
00334184
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
KA
345 /*
346 * move one char to the right. We don't use ND space
347 * because it's better to just print the char we are
348 * moving over.
349 */
9b9f600e
KA
350 if (_win != NULL)
351 if (plodflg) /* avoid a complex calculation */
352 plodcnt--;
353 else {
00334184
KA
354 i = _win->_y[outline-_win->_begy][outcol-_win->_begx];
355 if ((i&_STANDOUT) == (curscr->_flags&_STANDOUT))
356 putchar(i);
9b9f600e
KA
357 else
358 goto nondes;
359 }
360 else
361nondes:
362 if (ND)
363 tputs(ND, 0, plodput);
364 else
365 plodput(' ');
366 outcol++;
367 if (plodcnt < 0)
368 goto out;
369 }
370out:
371 if (plodflg) {
372 outcol = soutcol;
373 outline = soutline;
374 }
375 return(plodcnt);
376}
377
378/*
00334184
KA
379 * Return the column number that results from being in column col and
380 * hitting a tab, where tabs are set every ts columns. Work right for
381 * the case where col > COLS, even if ts does not divide COLS.
9b9f600e 382 */
00334184
KA
383tabcol(col, ts)
384int col, ts;
385{
386 int offset, result;
9b9f600e 387
00334184
KA
388 if (col >= COLS) {
389 offset = COLS * (col / COLS);
390 col -= offset;
9b9f600e 391 }
00334184
KA
392 else
393 offset = 0;
394 return col + ts - (col % ts) + offset;
9b9f600e 395}