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