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