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 * 02/17/82 (Berkeley) @(#)cr_put.c 1.2 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, so we return an 227 * incredibly big number to make cursor motion win out. 228 */ 229 if (!UP && destline < outline) 230 return (500); 231 if (GT) 232 i = destcol % HARDTABS 233 + destcol / HARDTABS; 234 else 235 i = destcol; 236 /* 237 if (BT && outcol > destcol && (j = (((outcol+7) & ~7) - destcol - 1) >> 3)) { 238 j *= (k = strlen(BT)); 239 if ((k += (destcol&7)) > 4) 240 j += 8 - (destcol&7); 241 else 242 j += k; 243 } 244 else 245 */ 246 j = outcol - destcol; 247 /* 248 * If we will later need a \n which will turn into a \r\n by 249 * the system or the terminal, then don't bother to try to \r. 250 */ 251 if ((NONL || !_pfast) && outline < destline) 252 goto dontcr; 253 /* 254 * If the terminal will do a \r\n and there isn't room for it, 255 * then we can't afford a \r. 256 */ 257 if (NC && outline >= destline) 258 goto dontcr; 259 /* 260 * If it will be cheaper, or if we can't back up, then send 261 * a return preliminarily. 262 */ 263 if (j > i + 1 || outcol > destcol && !BS && !BC) { 264 /* 265 * BUG: this doesn't take the (possibly long) length 266 * of CR into account. 267 */ 268 if (CR) 269 tputs(CR, 0, plodput); 270 else 271 plodput('\r'); 272 if (NC) { 273 if (NL) 274 tputs(NL, 0, plodput); 275 else 276 plodput('\n'); 277 outline++; 278 } 279 outcol = 0; 280 } 281 dontcr: 282 while (outline < destline) { 283 outline++; 284 if (NL && _pfast) 285 tputs(NL, 0, plodput); 286 else 287 plodput('\n'); 288 if (plodcnt < 0) 289 goto out; 290 if (NONL || _pfast == 0) 291 outcol = 0; 292 } 293 if (BT) 294 k = strlen(BT); 295 while (outcol > destcol) { 296 if (plodcnt < 0) 297 goto out; 298 /* 299 if (BT && outcol - destcol > k + 4) { 300 tputs(BT, 0, plodput); 301 outcol--; 302 outcol &= ~7; 303 continue; 304 } 305 */ 306 outcol--; 307 if (BC) 308 tputs(BC, 0, plodput); 309 else 310 plodput('\b'); 311 } 312 while (outline > destline) { 313 outline--; 314 tputs(UP, 0, plodput); 315 if (plodcnt < 0) 316 goto out; 317 } 318 if (GT && destcol - outcol > 1) { 319 for (;;) { 320 i = tabcol(outcol, HARDTABS); 321 if (i > destcol) 322 break; 323 if (TA) 324 tputs(TA, 0, plodput); 325 else 326 plodput('\t'); 327 outcol = i; 328 } 329 if (destcol - outcol > 4 && i < COLS && (BC || BS)) { 330 if (TA) 331 tputs(TA, 0, plodput); 332 else 333 plodput('\t'); 334 outcol = i; 335 while (outcol > destcol) { 336 outcol--; 337 if (BC) 338 tputs(BC, 0, plodput); 339 else 340 plodput('\b'); 341 } 342 } 343 } 344 while (outcol < destcol) { 345 /* 346 * move one char to the right. We don't use ND space 347 * because it's better to just print the char we are 348 * moving over. 349 */ 350 if (_win != NULL) 351 if (plodflg) /* avoid a complex calculation */ 352 plodcnt--; 353 else { 354 i = _win->_y[outline-_win->_begy][outcol-_win->_begx]; 355 if ((i&_STANDOUT) == (curscr->_flags&_STANDOUT)) 356 putchar(i); 357 else 358 goto nondes; 359 } 360 else 361 nondes: 362 if (ND) 363 tputs(ND, 0, plodput); 364 else 365 plodput(' '); 366 outcol++; 367 if (plodcnt < 0) 368 goto out; 369 } 370 out: 371 if (plodflg) { 372 outcol = soutcol; 373 outline = soutline; 374 } 375 return(plodcnt); 376 } 377 378 /* 379 * Return the column number that results from being in column col and 380 * hitting a tab, where tabs are set every ts columns. Work right for 381 * the case where col > COLS, even if ts does not divide COLS. 382 */ 383 tabcol(col, ts) 384 int col, ts; 385 { 386 int offset, result; 387 388 if (col >= COLS) { 389 offset = COLS * (col / COLS); 390 col -= offset; 391 } 392 else 393 offset = 0; 394 return col + ts - (col % ts) + offset; 395 } 396