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