Fix mdoc(7)/man(7) mix up.
[netbsd-mini2440.git] / lib / libcurses / cr_put.c
blob3eb02ef528bb2ece35b1833927947eef10226a2a
1 /* $NetBSD: cr_put.c,v 1.27 2008/07/23 13:32:41 tnozaki Exp $ */
3 /*
4 * Copyright (c) 1981, 1993, 1994
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
32 #include <sys/cdefs.h>
33 #ifndef lint
34 #if 0
35 static char sccsid[] = "@(#)cr_put.c 8.3 (Berkeley) 5/4/94";
36 #else
37 __RCSID("$NetBSD: cr_put.c,v 1.27 2008/07/23 13:32:41 tnozaki Exp $");
38 #endif
39 #endif /* not lint */
41 #include <string.h>
43 #include "curses.h"
44 #include "curses_private.h"
46 #define HARDTABS 8
49 * Terminal driving and line formatting routines. Basic motion optimizations
50 * are done here as well as formatting lines (printing of control characters,
51 * line numbering and the like).
54 /* Stub function for the users. */
55 int
56 mvcur(int ly, int lx, int y, int x)
58 return (__mvcur(ly, lx, y, x, 0));
61 static void fgoto __P((int));
62 static int plod __P((int, int));
63 static int plodput __P((int));
64 static int tabcol __P((int, int));
66 static int outcol, outline, destcol, destline;
69 * Sync the position of the output cursor. Most work here is rounding for
70 * terminal boundaries getting the column position implied by wraparound or
71 * the lack thereof and rolling up the screen to get destline on the screen.
73 int
74 __mvcur(int ly, int lx, int y, int x, int in_refresh)
76 #ifdef DEBUG
77 __CTRACE(__CTRACE_OUTPUT,
78 "mvcur: moving cursor from (%d, %d) to (%d, %d)\n", ly, lx, y, x);
79 #endif
80 destcol = x;
81 destline = y;
82 outcol = lx;
83 outline = ly;
84 fgoto(in_refresh);
85 return (OK);
88 static void
89 fgoto(in_refresh)
90 int in_refresh;
92 int c, l;
93 char cgp[128];
95 #ifdef DEBUG
96 __CTRACE(__CTRACE_OUTPUT, "fgoto: in_refresh=%d\n", in_refresh);
97 #endif /* DEBUG */
98 if (destcol >= COLS) {
99 destline += destcol / COLS;
100 destcol %= COLS;
102 if (outcol >= COLS) {
103 l = (outcol + 1) / COLS;
104 outline += l;
105 outcol %= COLS;
106 if (__tc_am == 0) {
107 while (l > 0) {
108 if (__pfast) {
109 if (__tc_cr)
110 tputs(__tc_cr, 0, __cputchar);
111 else
112 __cputchar('\r');
114 if (__tc_nl)
115 tputs(__tc_nl, 0, __cputchar);
116 else
117 __cputchar('\n');
118 l--;
120 outcol = 0;
122 if (outline > LINES - 1) {
123 destline -= outline - (LINES - 1);
124 outline = LINES - 1;
127 if (destline >= LINES) {
128 l = destline;
129 destline = LINES - 1;
130 if (outline < LINES - 1) {
131 c = destcol;
132 if (__pfast == 0 && !__CA)
133 destcol = 0;
134 fgoto(in_refresh);
135 destcol = c;
137 while (l >= LINES) {
138 /* The following linefeed (or simulation thereof) is
139 * supposed to scroll up the screen, since we are on
140 * the bottom line. We make the assumption that
141 * linefeed will scroll. If ns is in the capability
142 * list this won't work. We should probably have an
143 * sc capability but sf will generally take the place
144 * if it works.
146 * Superbee glitch: in the middle of the screen have to
147 * use esc B (down) because linefeed screws up in
148 * "Efficient Paging" (what a joke) mode (which is
149 * essential in some SB's because CRLF mode puts
150 * garbage in at end of memory), but you must use
151 * linefeed to scroll since down arrow won't go past
152 * memory end. I turned this off after recieving Paul
153 * Eggert's Superbee description which wins better. */
154 if (__tc_nl /* && !__tc_xb */ && __pfast)
155 tputs(__tc_nl, 0, __cputchar);
156 else
157 __cputchar('\n');
158 l--;
159 if (__pfast == 0)
160 outcol = 0;
163 if (destline < outline && !(__CA || __tc_up))
164 destline = outline;
165 if (__CA && t_goto(NULL, __tc_cm, destcol, destline, cgp,
166 sizeof(cgp) - 1) != -1) {
168 * Need this condition due to inconsistent behavior
169 * of backspace on the last column.
171 #ifdef DEBUG
172 __CTRACE(__CTRACE_OUTPUT, "fgoto: cgp=%s\n", cgp);
173 #endif /* DEBUG */
174 if (outcol != COLS - 1 &&
175 plod((int) strlen(cgp), in_refresh) > 0)
176 plod(0, in_refresh);
177 else
178 tputs(cgp, 0, __cputchar);
179 } else
180 plod(0, in_refresh);
181 outline = destline;
182 outcol = destcol;
185 * Move (slowly) to destination.
186 * Hard thing here is using home cursor on really deficient terminals.
187 * Otherwise just use cursor motions, hacking use of tabs and overtabbing
188 * and backspace.
190 * XXX this needs to be revisited for wide characters since we may output
191 * XXX more than one byte for a character.
194 static int plodcnt, plodflg;
196 static int
197 plodput(c)
198 int c;
200 if (plodflg)
201 --plodcnt;
202 else
203 __cputchar(c);
204 return (0);
207 static int
208 plod(cnt, in_refresh)
209 int cnt, in_refresh;
211 int i, j, k, soutcol, soutline;
213 #ifdef DEBUG
214 __CTRACE(__CTRACE_OUTPUT, "plod: cnt=%d, in_refresh=%d\n",
215 cnt, in_refresh);
216 #endif /* DEBUG */
217 plodcnt = plodflg = cnt;
218 soutcol = outcol;
219 soutline = outline;
221 * Consider homing and moving down/right from there, vs. moving
222 * directly with local motions to the right spot.
224 if (__tc_ho) {
226 * i is the cost to home and tab/space to the right to get to
227 * the proper column. This assumes nd space costs 1 char. So
228 * i + destcol is cost of motion with home.
230 if (__GT)
231 i = (destcol / HARDTABS) + (destcol % HARDTABS);
232 else
233 i = destcol;
235 /* j is cost to move locally without homing. */
236 if (destcol >= outcol) { /* if motion is to the right */
237 j = destcol / HARDTABS - outcol / HARDTABS;
238 if (__GT && j)
239 j += destcol % HARDTABS;
240 else
241 j = destcol - outcol;
242 } else
243 /* leftward motion only works if we can backspace. */
244 if (outcol - destcol <= i && (__tc_bs || __tc_bc))
245 /* Cheaper to backspace. */
246 i = j = outcol - destcol;
247 else
248 /* Impossibly expensive. */
249 j = i + 1;
251 /* k is the absolute value of vertical distance. */
252 k = outline - destline;
253 if (k < 0)
254 k = -k;
255 j += k;
257 /* Decision. We may not have a choice if no up. */
258 if (i + destline < j || (!__tc_up && destline < outline)) {
260 * Cheaper to home. Do it now and pretend it's a
261 * regular local motion.
263 tputs(__tc_ho, 0, plodput);
264 outcol = outline = 0;
265 } else
266 if (__tc_ll) {
268 * Quickly consider homing down and moving from
269 * there. Assume cost of ll is 2.
271 k = (LINES - 1) - destline;
272 if (i + k + 2 < j && (k <= 0 || __tc_up)) {
273 tputs(__tc_ll, 0, plodput);
274 outcol = 0;
275 outline = LINES - 1;
278 } else
279 /* No home and no up means it's impossible. */
280 if (!__tc_up && destline < outline)
281 return (-1);
282 if (__GT)
283 i = destcol % HARDTABS + destcol / HARDTABS;
284 else
285 i = destcol;
286 #ifdef notdef
287 if (__tc_bt && outcol > destcol &&
288 (j = (((outcol + 7) & ~7) - destcol - 1) >> 3)) {
289 j *= (k = strlen(__tc_bt));
290 if ((k += (destcol & 7)) > 4)
291 j += 8 - (destcol & 7);
292 else
293 j += k;
294 } else
295 #endif
296 j = outcol - destcol;
299 * If we will later need a \n which will turn into a \r\n by the
300 * system or the terminal, then don't bother to try to \r.
302 if ((__NONL || !__pfast) && outline < destline)
303 goto dontcr;
306 * If the terminal will do a \r\n and there isn't room for it, then
307 * we can't afford a \r.
309 if (__tc_nc && outline >= destline)
310 goto dontcr;
313 * If it will be cheaper, or if we can't back up, then send a return
314 * preliminarily.
316 if (j > i + 1 || (outcol > destcol && !__tc_bs && !__tc_bc)) {
318 * BUG: this doesn't take the (possibly long) length of cr
319 * into account.
321 if (__tc_cr)
322 tputs(__tc_cr, 0, plodput);
323 else
324 plodput('\r');
325 if (__tc_nc) {
326 if (__tc_nl)
327 tputs(__tc_nl, 0, plodput);
328 else
329 plodput('\n');
330 outline++;
332 outcol = 0;
334 dontcr:while (outline < destline) {
335 outline++;
336 if (__tc_nl)
337 tputs(__tc_nl, 0, plodput);
338 else
339 plodput('\n');
340 if (plodcnt < 0)
341 goto out;
342 if (__NONL || __pfast == 0)
343 outcol = 0;
345 if (__tc_bt)
346 k = (int) strlen(__tc_bt);
347 while (outcol > destcol) {
348 if (plodcnt < 0)
349 goto out;
350 #ifdef notdef
351 if (__tc_bt && outcol - destcol > k + 4) {
352 tputs(__tc_bt, 0, plodput);
353 outcol--;
354 outcol &= ~7;
355 continue;
357 #endif
358 outcol--;
359 if (__tc_bc)
360 tputs(__tc_bc, 0, plodput);
361 else
362 plodput('\b');
364 while (outline > destline) {
365 outline--;
366 tputs(__tc_up, 0, plodput);
367 if (plodcnt < 0)
368 goto out;
370 if (__GT && destcol - outcol > 1) {
371 for (;;) {
372 i = tabcol(outcol, HARDTABS);
373 if (i > destcol)
374 break;
375 if (__tc_ta)
376 tputs(__tc_ta, 0, plodput);
377 else
378 plodput('\t');
379 outcol = i;
381 if (destcol - outcol > 4 && i < COLS && (__tc_bc || __tc_bs)) {
382 if (__tc_ta)
383 tputs(__tc_ta, 0, plodput);
384 else
385 plodput('\t');
386 outcol = i;
387 while (outcol > destcol) {
388 outcol--;
389 if (__tc_bc)
390 tputs(__tc_bc, 0, plodput);
391 else
392 plodput('\b');
396 while (outcol < destcol) {
398 * Move one char to the right. We don't use nd space because
399 * it's better to just print the char we are moving over.
401 if (in_refresh)
402 if (plodflg) /* Avoid a complex calculation. */
403 plodcnt--;
404 else {
405 #ifndef HAVE_WCHAR
406 i = curscr->alines[outline]->line[outcol].ch
407 & __CHARTEXT;
408 if (curscr->alines[outline]->line[outcol].attr
409 == curscr->wattr)
410 __cputchar(i);
411 #else
412 if ((curscr->alines[outline]->line[outcol].attr
413 & WA_ATTRIBUTES)
414 == curscr->wattr) {
415 switch (WCOL(curscr->alines[outline]->line[outcol])) {
416 case 1:
417 __cputwchar(curscr->alines[outline]->line[outcol].ch);
418 __cursesi_putnsp(curscr->alines[outline]->line[outcol].nsp,
419 outline,
420 outcol);
421 #ifdef DEBUG
422 __CTRACE(__CTRACE_OUTPUT,
423 "plod: (%d,%d)WCOL(%d), "
424 "putwchar(%x)\n",
425 outline, outcol,
426 WCOL(curscr->alines[outline]->line[outcol]),
427 curscr->alines[outline]->line[outcol].ch);
428 #endif /* DEBUG */
429 /*FALLTHROUGH*/
430 case 0:
431 break;
432 default:
433 goto nondes;
436 #endif /* HAVE_WCHAR */
437 else
438 goto nondes;
440 else
441 nondes: if (__tc_nd)
442 tputs(__tc_nd, 0, plodput);
443 else
444 plodput(' ');
445 outcol++;
446 if (plodcnt < 0)
447 goto out;
450 out: if (plodflg) {
451 outcol = soutcol;
452 outline = soutline;
454 #ifdef DEBUG
455 __CTRACE(__CTRACE_OUTPUT, "plod: returns %d\n", plodcnt);
456 #endif /* DEBUG */
457 return (plodcnt);
460 * Return the column number that results from being in column col and
461 * hitting a tab, where tabs are set every ts columns. Work right for
462 * the case where col > COLS, even if ts does not divide COLS.
464 static int
465 tabcol(col, ts)
466 int col, ts;
468 int offset;
470 if (col >= COLS) {
471 offset = COLS * (col / COLS);
472 col -= offset;
473 } else
474 offset = 0;
475 return (col + ts - (col % ts) + offset);