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