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