|
|
1.1 ! root 1: /* @(#)ll_refresh.c 1.1 (1.22) */ ! 2: #include "curses.ext" ! 3: ! 4: extern int InputPending; ! 5: extern int outchcount; ! 6: ! 7: extern int *context; ! 8: ! 9: int didntdobotright; /* writechars didn't output char in bot right corner */ ! 10: ! 11: /* ! 12: * Optimally make the screen (which currently looks like SP->cur_body) ! 13: * look like SP->std_body. If use_idl is 1, this routine will call ! 14: * out all its horses, including some code to figure out ! 15: * how to use insert/delete line. If use_idl is 0, or if the terminal ! 16: * does not have insert/delete line, a simpler scheme will ! 17: * be used, and the insert/delete line features of the terminal will not ! 18: * be used. ! 19: * ! 20: * While the original intent of this parameter was speed (insert/delete ! 21: * line was slow) the parameter currently is there to avoid annoying ! 22: * the user with unnecessary insert/delete lines. ! 23: */ ! 24: int ! 25: _ll_refresh (use_idl) ! 26: int use_idl; ! 27: { ! 28: register int n, i, j; ! 29: register struct line *dln, *pln; ! 30: struct line *_line_alloc(); ! 31: ! 32: #ifdef DEBUG ! 33: if(outf) fprintf(outf, "_ll_refresh(%d)\n", use_idl); ! 34: if(outf) fprintf(outf, "phys cursor at (%d,%d), want cursor at (%d,%d)\n", ! 35: SP->phys_y, SP->phys_x, SP->virt_y, SP->virt_x); ! 36: #endif DEBUG ! 37: outchcount = 0; ! 38: #ifdef FIONREAD ! 39: if( SP->check_fd >= 0 ) ! 40: { ! 41: ioctl (SP->check_fd, FIONREAD, &InputPending); ! 42: } ! 43: else ! 44: { ! 45: InputPending = 0; ! 46: } ! 47: if( InputPending ) ! 48: { ! 49: #ifdef DEBUG ! 50: if (outf) fprintf(outf, "InputPending %d, aborted ll_refresh at start\n", InputPending); ! 51: #endif DEBUG ! 52: return 0; ! 53: } ! 54: #endif FIONREAD ! 55: #ifdef NONSTANDARD ! 56: input_wait(); ! 57: #endif NONSTANDARD ! 58: #ifdef DEBUG ! 59: if (outf) fprintf(outf, "virt cursor at y=%d, x=%d, length %d, length-1 %d\n", ! 60: SP->virt_y, SP->virt_x, SP->std_body[SP->virt_y+1]->length, ! 61: SP->std_body[SP->virt_y]->length); ! 62: #endif DEBUG ! 63: if( SP->virt_y >= 0 && SP->std_body[SP->virt_y+1]->length < SP->virt_x ) ! 64: { ! 65: SP->std_body[SP->virt_y+1]->length = ! 66: SP->virt_x >= columns ? columns : SP->virt_x; ! 67: } ! 68: /* Get rid of trailing blanks on all lines */ ! 69: for( n = 1; n <= lines; n++ ) ! 70: { ! 71: dln = SP->std_body[n]; ! 72: pln = SP->cur_body[n]; ! 73: if( dln && dln != pln ) ! 74: { ! 75: register chtype *p; ! 76: ! 77: if( i = dln->length ) ! 78: { ! 79: p = dln->body + i; ! 80: while( *--p == ' ' && --i > 0 ) ! 81: ; ! 82: dln->length = i; ! 83: } ! 84: } ! 85: ! 86: if( pln ) ! 87: { ! 88: register chtype *p; ! 89: ! 90: if( i = pln->length ) ! 91: { ! 92: p = pln->body + i; ! 93: while( *--p == ' ' && --i > 0 ) ! 94: ; ! 95: pln->length = i; ! 96: } ! 97: } ! 98: } ! 99: if( magic_cookie_glitch > 0 ) ! 100: _toss_cookies(); ! 101: #ifdef DEBUG ! 102: if(outf) fprintf(outf, "what we have:\n"); ! 103: for( i=1; i<=lines; i++ ) ! 104: { ! 105: if(outf) fprintf(outf, "%8x: ", SP->cur_body[i]); ! 106: if( SP->cur_body[i] == NULL ) ! 107: { ! 108: if(outf) fprintf(outf, "()\n"); ! 109: } ! 110: else ! 111: { ! 112: if(outf) fprintf(outf, "%4d ", SP->cur_body[i]->length); ! 113: for( j=0; j<SP->cur_body[i]->length; j++ ) ! 114: { ! 115: n = SP->cur_body[i]->body[j]; ! 116: if( n & A_ATTRIBUTES ) ! 117: { ! 118: putc('\'', outf); ! 119: } ! 120: n &= 0177; ! 121: if(outf) fprintf(outf, "%c", n>=' ' ? n : '.'); ! 122: } ! 123: if(outf) fprintf(outf, "\n"); ! 124: } ! 125: } ! 126: if(outf) fprintf(outf, "what we want:\n"); ! 127: for (i=1; i<=lines; i++) ! 128: { ! 129: if(outf) fprintf(outf, "%8x: ", SP->std_body[i]); ! 130: if (SP->std_body[i] == NULL) ! 131: { ! 132: if(outf) fprintf(outf, "()\n"); ! 133: } ! 134: else ! 135: { ! 136: if(outf) fprintf(outf, "%4d ", SP->std_body[i]->length); ! 137: for (j=0; j<SP->std_body[i]->length; j++) ! 138: { ! 139: n = SP->std_body[i]->body[j]; ! 140: if (n & A_ATTRIBUTES) ! 141: { ! 142: putc('\'', outf); ! 143: } ! 144: n &= 0177; ! 145: if(outf) fprintf(outf, "%c", n>=' ' ? n : '.'); ! 146: } ! 147: if(outf) fprintf(outf, "\n"); ! 148: } ! 149: } ! 150: if(outf) fprintf(outf, "----\n"); ! 151: if(outf) fflush(outf); ! 152: #endif DEBUG ! 153: SP->check_input = SP->baud / 2400; ! 154: if (SP->doclear) ! 155: { ! 156: #ifdef DEBUG ! 157: if(outf) fprintf(outf, "SP->doclear, clearing screen\n"); ! 158: #endif ! 159: _reset(); ! 160: SP->doclear = 0; ! 161: for( n = 0; n <= lines; n++ ) ! 162: { ! 163: if( SP->cur_body[n] != SP->std_body[n] ) ! 164: { ! 165: _line_free( SP->cur_body[n] ); ! 166: } ! 167: SP->cur_body[n] = 0; ! 168: } ! 169: } ! 170: ! 171: /* Choose between two updating algorithms. */ ! 172: if( use_idl && _cost(ilfixed) < INFINITY ) ! 173: { ! 174: #ifdef DEBUG ! 175: if(outf) fprintf(outf, "use_idl\n"); ! 176: #endif ! 177: for( n = 1; n <= lines; n++ ) ! 178: { ! 179: if( SP->cur_body[n] == 0 ) ! 180: { ! 181: SP->cur_body[n] = _line_alloc(); ! 182: } ! 183: if( SP->std_body[n] == 0 ) ! 184: { ! 185: SP->std_body[n] = SP->cur_body[n]; ! 186: } ! 187: else ! 188: { ! 189: _comphash( SP->std_body[n] ); ! 190: } ! 191: _comphash( SP->cur_body[n] ); ! 192: } ! 193: /* ! 194: * Count number of matches if we scroll 1 line and if we ! 195: * don't scroll at all. This is primarily useful for the ! 196: * case where we scroll the whole screen. Scrolling a portion ! 197: * of the screen will be handled by the ins/del line routines, ! 198: * although a special case here might buy some CPU speed. ! 199: */ ! 200: for( i=1,n=0,j=0; i<lines; i++ ) ! 201: { ! 202: if( SP->cur_body[i+1]->hash == SP->std_body[i]->hash ) ! 203: n++; ! 204: if( SP->cur_body[i]->hash == SP->std_body[i]->hash ) ! 205: j++; ! 206: } ! 207: if( n > lines-3 && n > j ) ! 208: { ! 209: _window(0, lines-1, 0, columns-1); ! 210: _scrollf(1); ! 211: _line_free(SP->cur_body[1]); ! 212: for( i=1; i<lines; i++ ) ! 213: { ! 214: /* Copy line with two references since they ! 215: * are no longer the same row on screen. */ ! 216: if( SP->cur_body[i+1] == SP->std_body[i+1] ) ! 217: { ! 218: struct line *p; ! 219: int l; ! 220: chtype *b1, *b2; ! 221: p = _line_alloc (); ! 222: p->length=l=SP->cur_body[i+1]->length; ! 223: p->hash = SP->cur_body[i+1]->hash; ! 224: b1 = &(p->body[0]); ! 225: b2 = &(SP->cur_body[i+1]->body[0]); ! 226: for( ; l>0; l-- ) ! 227: { ! 228: *b1++ = *b2++; ! 229: } ! 230: SP->std_body[i+1] = p; ! 231: } ! 232: SP->cur_body[i] = SP->cur_body[i+1]; ! 233: } ! 234: SP->cur_body[lines] = _line_alloc(); ! 235: } ! 236: i = 1; ! 237: /* ! 238: * Break the screen (from 1 to lines) into clumps of ! 239: * lines that are different. Thus we ignore the ones that ! 240: * are identical. ! 241: */ ! 242: for( ;; ) ! 243: { ! 244: while( i<=lines && SP->cur_body[i]==SP->std_body[i] ) ! 245: { ! 246: i++; ! 247: } ! 248: if( i > lines ) ! 249: { ! 250: break; ! 251: } ! 252: for( j=i; j <= lines && ! 253: SP->cur_body[j] != SP->std_body[j]; j++) ! 254: ; ! 255: j--; ! 256: #ifdef DEBUG ! 257: if(outf) fprintf(outf, "window from %d to %d\n", i, j); ! 258: #endif ! 259: /* i thru j is a window of different lines. */ ! 260: if( i == j ) ! 261: { ! 262: _id_char(SP->cur_body[i], SP->std_body[i], i-1); ! 263: if( SP->cur_body[i] != SP->std_body[i] ) ! 264: { ! 265: _line_free (SP->cur_body[i]); ! 266: } ! 267: SP->cur_body[i] = SP->std_body[i]; ! 268: } ! 269: else ! 270: { ! 271: _window(i-1, j-1, 0, columns-1); ! 272: _setwind(); /* Force action for moves, etc */ ! 273: _id_line(i, j); ! 274: } ! 275: i = j+1; ! 276: } ! 277: } ! 278: else /* fast update */ ! 279: { ! 280: #ifdef DEBUG ! 281: if(outf) fprintf(outf, "Fast Update, lines %d\n", lines); ! 282: #endif ! 283: _window(0, lines-1, 0, columns-1); ! 284: _setwind(); /* Force action for moves, etc */ ! 285: for( n = 1; n <= lines; n++ ) ! 286: if( SP->std_body[n] != SP->cur_body[n] ) ! 287: { ! 288: _id_char( SP->cur_body[n],SP->std_body[n],n-1 ); ! 289: if( SP->cur_body[n] != SP->std_body[n] ) ! 290: { ! 291: _line_free (SP->cur_body[n]); ! 292: } ! 293: SP->cur_body[n] = SP->std_body[n]; ! 294: } ! 295: } ! 296: ! 297: /* ! 298: * Didn't output char in bottom right corner of screen. ! 299: * Remember this fact so that next time when it's higher ! 300: * on the screen, we'll fix it up. ! 301: */ ! 302: if( didntdobotright ) ! 303: { ! 304: int holdvx, holdvy; ! 305: #ifdef DEBUG ! 306: if (outf) fprintf(outf, "didntdobotright so setting SP->cur_body[%d]->body[%d] from '%c' to space.\n", lines, columns-1, SP->cur_body[lines]->body[columns-1]); ! 307: #endif ! 308: holdvx = SP->virt_x; ! 309: holdvy = SP->virt_y; ! 310: /* ! 311: * This code in effect marks the last line dirty ! 312: * so that the next time it will get fixed. It also ! 313: * splits the line back into virt/phys so we don't ! 314: * clobber the virtual part too. ! 315: */ ! 316: _ll_move(lines-1, columns-1); ! 317: SP->cur_body[lines]->body[columns-1] = ' '; ! 318: didntdobotright = 0; ! 319: /* Now restore the cursor we clobbered. */ ! 320: _ll_move(holdvy, holdvx); ! 321: } ! 322: ! 323: _hlmode(0); _sethl(); ! 324: #ifdef DEBUG ! 325: if(outf) fprintf(outf, "at end, phys SP->curptr at (%d,%d), want SP->curptr at (%d,%d)\n", ! 326: SP->phys_y, SP->phys_x, SP->virt_y, SP->virt_x); ! 327: #endif DEBUG ! 328: #ifdef notdef ! 329: if(magic_cookie_glitch > 0) ! 330: _fixcursor(); ! 331: #endif notdef ! 332: if( !InputPending && SP->virt_x >= 0 && SP->virt_y >= 0 ) ! 333: { ! 334: _pos (SP->virt_y, SP->virt_x); ! 335: } ! 336: __cflush(); ! 337: #ifdef DEBUG ! 338: if(outf) fprintf(outf, "end of _ll_refresh, InputPending %d\n", InputPending); ! 339: if(outf) fflush(outf); ! 340: #endif DEBUG ! 341: return outchcount; ! 342: } ! 343: ! 344: /* ! 345: * This routine is only needed on terminals with the "magic cookie" ! 346: * effect. The problem is that the designers of ! 347: * these terminals didn't allocate 16 bits for ! 348: * each character (7 for the character and 9 for attributes) but instead ! 349: * created some reserved "magic cookie" characters to tell the scan ! 350: * routine "you should change attributes now". This would be fine except ! 351: * that these cookies take up a space in memory, and usually display as a ! 352: * blank. This makes it impossible to display what the user really ! 353: * wanted, if he is using attributes for underlining, bold, etc. Such ! 354: * terminals include the Teleray 1061, TVI 912 and 950, Teletype ! 355: * DataSpeed 40, and Adds Regent 40. ! 356: * ! 357: * One approach to this problem is to make everybody pay the price of ! 358: * this effect, forcing the programmer to allocate a blank space ! 359: * when attributes are changed. This works cleanly but I consider it ! 360: * unacceptable. ! 361: * ! 362: * My approach is to simulate what the programmer (who wasn't thinking ! 363: * about these terminals) wanted as closely as possible. If there ! 364: * is a desired blank in there, we use that slot. If not, we shove the ! 365: * rest of the line to the right one space. (When several attributes ! 366: * are changed on one line, this can result in losing several characters ! 367: * from the right of the line.) ! 368: * ! 369: * This routine looks for places in SP->std_body where shoving to the ! 370: * right is needed, and does the required shoving. ! 371: */ ! 372: static ! 373: _toss_cookies() ! 374: { ! 375: register int i, j, len; ! 376: register struct line *dsi; ! 377: register chtype *b; ! 378: ! 379: #ifdef DEBUG ! 380: if(outf) fprintf(outf, "_toss_cookies\n"); ! 381: #endif ! 382: for( i=1; i<=lines; i++ ) ! 383: { ! 384: dsi = SP->std_body[i]; ! 385: if( dsi && dsi != SP->cur_body[i] ) ! 386: { ! 387: len = dsi->length; ! 388: b = dsi->body; ! 389: for( j=0; j<len; j++ ) ! 390: { ! 391: if( b[j]&A_ATTRIBUTES ) ! 392: { ! 393: #ifdef DEBUG ! 394: if(outf) fprintf(outf, "_shove, line %d, char %d, val %o\n", i, j, b[j]); ! 395: #endif ! 396: dsi->length = _shove(b, len, i); ! 397: break; ! 398: } ! 399: } ! 400: } ! 401: } ! 402: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.