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