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