|
|
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.