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