Annotation of src/lib/libcurses/cr_put.c, Revision 1.2
1.1 cgd 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
35: static 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:
42: extern char *tgoto();
43: int 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:
59: static int outcol, outline, destcol, destline;
60:
61: WINDOW *_win;
62:
63: mvcur(ly, lx, y, x)
64: int 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:
76: fgoto()
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:
169: static int plodcnt, plodflg;
170:
171: plodput(c)
172: {
173: if (plodflg)
174: plodcnt--;
175: else
176: _putchar(c);
177: }
178:
179: plod(cnt)
180: {
181: register int i, j, k;
182: register int soutcol, soutline;
1.2 ! alm 183: chtype ch;
1.1 cgd 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: }
304: dontcr:
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 {
1.2 ! alm 377: ch = curscr->_y[outline][outcol];
! 378: if ((ch&_STANDOUT) == (curscr->_flags&_STANDOUT))
! 379: _putchar(ch);
1.1 cgd 380: else
381: goto nondes;
382: }
383: else
384: nondes:
385: if (ND)
386: tputs(ND, 0, plodput);
387: else
388: plodput(' ');
389: outcol++;
390: if (plodcnt < 0)
391: goto out;
392: }
393: out:
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: */
406: tabcol(col, ts)
407: int 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: }
CVSweb <webmaster@jp.NetBSD.org>