|
|
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: (1) source distributions retain this entire copyright
7: * notice and comment, and (2) distributions including binaries display
8: * the following acknowledgement: ``This product includes software
9: * developed by the University of California, Berkeley and its contributors''
10: * in the documentation or other materials provided with the distribution
11: * and in all advertising materials mentioning features or use of this
12: * software. Neither the name of the University nor the names of its
13: * contributors may be used to endorse or promote products derived
14: * from this software without specific prior written permission.
15: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18: */
19:
20: #ifndef lint
21: static char sccsid[] = "@(#)cr_put.c 5.5 (Berkeley) 6/1/90";
22: #endif /* not lint */
23:
24: # include "curses.ext"
25:
26: # define HARDTABS 8
27:
28: extern char *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 char *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 (NL /* && !XB */ && _pfast)
125: _puts(NL);
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)
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 && j)
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: /* k is the absolute value of vertical distance */
205: k = outline - destline;
206: if (k < 0)
207: k = -k;
208: j += k;
209:
210: /*
211: * Decision. We may not have a choice if no UP.
212: */
213: if (i + destline < j || (!UP && destline < outline)) {
214: /*
215: * Cheaper to home. Do it now and pretend it's a
216: * regular local motion.
217: */
218: tputs(HO, 0, plodput);
219: outcol = outline = 0;
220: }
221: else if (LL) {
222: /*
223: * Quickly consider homing down and moving from there.
224: * Assume cost of LL is 2.
225: */
226: k = (LINES - 1) - destline;
227: if (i + k + 2 < j && (k<=0 || UP)) {
228: tputs(LL, 0, plodput);
229: outcol = 0;
230: outline = LINES - 1;
231: }
232: }
233: }
234: else
235: /*
236: * No home and no up means it's impossible.
237: */
238: if (!UP && destline < outline)
239: return -1;
240: if (GT)
241: i = destcol % HARDTABS + destcol / HARDTABS;
242: else
243: i = destcol;
244: /*
245: if (BT && outcol > destcol && (j = (((outcol+7) & ~7) - destcol - 1) >> 3)) {
246: j *= (k = strlen(BT));
247: if ((k += (destcol&7)) > 4)
248: j += 8 - (destcol&7);
249: else
250: j += k;
251: }
252: else
253: */
254: j = outcol - destcol;
255: /*
256: * If we will later need a \n which will turn into a \r\n by
257: * the system or the terminal, then don't bother to try to \r.
258: */
259: if ((NONL || !_pfast) && outline < destline)
260: goto dontcr;
261: /*
262: * If the terminal will do a \r\n and there isn't room for it,
263: * then we can't afford a \r.
264: */
265: if (NC && outline >= destline)
266: goto dontcr;
267: /*
268: * If it will be cheaper, or if we can't back up, then send
269: * a return preliminarily.
270: */
271: if (j > i + 1 || outcol > destcol && !BS && !BC) {
272: /*
273: * BUG: this doesn't take the (possibly long) length
274: * of CR into account.
275: */
276: if (CR)
277: tputs(CR, 0, plodput);
278: else
279: plodput('\r');
280: if (NC) {
281: if (NL)
282: tputs(NL, 0, plodput);
283: else
284: plodput('\n');
285: outline++;
286: }
287: outcol = 0;
288: }
289: dontcr:
290: while (outline < destline) {
291: outline++;
292: if (NL)
293: tputs(NL, 0, plodput);
294: else
295: plodput('\n');
296: if (plodcnt < 0)
297: goto out;
298: if (NONL || _pfast == 0)
299: outcol = 0;
300: }
301: if (BT)
302: k = strlen(BT);
303: while (outcol > destcol) {
304: if (plodcnt < 0)
305: goto out;
306: /*
307: if (BT && outcol - destcol > k + 4) {
308: tputs(BT, 0, plodput);
309: outcol--;
310: outcol &= ~7;
311: continue;
312: }
313: */
314: outcol--;
315: if (BC)
316: tputs(BC, 0, plodput);
317: else
318: plodput('\b');
319: }
320: while (outline > destline) {
321: outline--;
322: tputs(UP, 0, plodput);
323: if (plodcnt < 0)
324: goto out;
325: }
326: if (GT && destcol - outcol > 1) {
327: for (;;) {
328: i = tabcol(outcol, HARDTABS);
329: if (i > destcol)
330: break;
331: if (TA)
332: tputs(TA, 0, plodput);
333: else
334: plodput('\t');
335: outcol = i;
336: }
337: if (destcol - outcol > 4 && i < COLS && (BC || BS)) {
338: if (TA)
339: tputs(TA, 0, plodput);
340: else
341: plodput('\t');
342: outcol = i;
343: while (outcol > destcol) {
344: outcol--;
345: if (BC)
346: tputs(BC, 0, plodput);
347: else
348: plodput('\b');
349: }
350: }
351: }
352: while (outcol < destcol) {
353: /*
354: * move one char to the right. We don't use ND space
355: * because it's better to just print the char we are
356: * moving over.
357: */
358: if (_win != NULL)
359: if (plodflg) /* avoid a complex calculation */
360: plodcnt--;
361: else {
362: i = curscr->_y[outline][outcol];
363: if ((i&_STANDOUT) == (curscr->_flags&_STANDOUT))
364: _putchar(i & 0177);
365: else
366: goto nondes;
367: }
368: else
369: nondes:
370: if (ND)
371: tputs(ND, 0, plodput);
372: else
373: plodput(' ');
374: outcol++;
375: if (plodcnt < 0)
376: goto out;
377: }
378: out:
379: if (plodflg) {
380: outcol = soutcol;
381: outline = soutline;
382: }
383: return(plodcnt);
384: }
385:
386: /*
387: * Return the column number that results from being in column col and
388: * hitting a tab, where tabs are set every ts columns. Work right for
389: * the case where col > COLS, even if ts does not divide COLS.
390: */
391: tabcol(col, ts)
392: int col, ts;
393: {
394: int offset, result;
395:
396: if (col >= COLS) {
397: offset = COLS * (col / COLS);
398: col -= offset;
399: }
400: else
401: offset = 0;
402: return col + ts - (col % ts) + offset;
403: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.