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