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