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