|
|
1.1 ! root 1: /* ! 2: * Modify current screen line 'old' to match desired line 'new'. ! 3: * The old line is at position ln. Each line is divided into 4 regions: ! 4: * ! 5: * nlws, olws - amount of leading white space on new/old line ! 6: * com_head - length of common head ! 7: * nchanged, ochanged - length of the parts changed ! 8: * com_tail - length of a common tail ! 9: */ ! 10: ! 11: /* @(#) _id_char.c: 1.1 10/15/83 (1.20 3/6/83) */ ! 12: ! 13: #include "curses.ext" ! 14: ! 15: #define min(a,b) (a<b ? a : b) ! 16: ! 17: _id_char (old, new, ln) ! 18: register struct line *old, * new; ! 19: { ! 20: register chtype *oc_beg, *nc_beg,/* Beginning of changed part */ ! 21: *oc_end, *nc_end;/* End of changed part */ ! 22: chtype *p, *q; /* scratch */ ! 23: int olws, nlws; /* old/new leading white space */ ! 24: int com_head, com_tail; /* size of common head/tail */ ! 25: int ochanged, nchanged; /* size of changed part */ ! 26: int samelen; /* both lines are same length */ ! 27: int nbl; /* # blanks in new line replacing nonblanks in old */ ! 28: int nms; /* # chars same in new and old in middle part */ ! 29: int cw_idc; /* cost of update with insert/delete character */ ! 30: int cwo_idc; /* cost of update without insert/delete character */ ! 31: int i, j, n; /* scratch */ ! 32: int len, diff; ! 33: static chtype nullline[] = {0, 0}; ! 34: ! 35: #ifdef DEBUG ! 36: if(outf) fprintf(outf, "_id_char(%x, %x, %d)\n", old, new, ln); ! 37: if(outf) fprintf(outf, "old: "); ! 38: if(outf) fprintf(outf, "%8x: ", old); ! 39: if (old == NULL) { ! 40: if(outf) fprintf(outf, "()\n"); ! 41: } else { ! 42: if(outf) fprintf(outf, "%4d ", old->length); ! 43: for (j=0; j<old->length; j++) { ! 44: n = old->body[j]; ! 45: if (n & A_ATTRIBUTES) ! 46: putc('\'', outf); ! 47: n &= 0177; ! 48: if(outf) fprintf(outf, "%c", n>=' ' ? n : '.'); ! 49: } ! 50: if(outf) fprintf(outf, "\n"); ! 51: } ! 52: if(outf) fprintf(outf, "new: "); ! 53: if(outf) fprintf(outf, "%8x: ", new); ! 54: if (new == NULL) { ! 55: if(outf) fprintf(outf, "()\n"); ! 56: } else { ! 57: if(outf) fprintf(outf, "%4d ", new->length); ! 58: for (j=0; j<new->length; j++) { ! 59: n = new->body[j]; ! 60: if (n & A_ATTRIBUTES) ! 61: putc('\'', outf); ! 62: n &= 0177; ! 63: if(outf) fprintf(outf, "%c", n>=' ' ? n : '.'); ! 64: } ! 65: if(outf) fprintf(outf, "\n"); ! 66: } ! 67: #endif DEBUG ! 68: ! 69: if (old == new) ! 70: { ! 71: return; ! 72: } ! 73: ! 74: /* Start at the ends of the lines */ ! 75: if( old ) ! 76: { ! 77: oc_beg = old -> body; ! 78: oc_end = &old -> body[old -> length]; ! 79: } ! 80: else ! 81: { ! 82: oc_beg = nullline; ! 83: oc_end = oc_beg; ! 84: } ! 85: if( new ) ! 86: { ! 87: nc_beg = new -> body; ! 88: nc_end = &new -> body[new -> length]; ! 89: } ! 90: else ! 91: { ! 92: nc_beg = nullline; ! 93: nc_end = nc_beg; ! 94: } ! 95: ! 96: /* Find leading and trailing blanks */ ! 97: olws = nlws = com_head = com_tail = 0; ! 98: while (*--oc_end == ' ' && oc_end >= oc_beg) ! 99: ; ! 100: while (*--nc_end == ' ' && nc_end >= nc_beg) ! 101: ; ! 102: samelen = (nc_end-nc_beg) == (oc_end-oc_beg) ! 103: ; ! 104: while( *oc_beg == ' ' && oc_beg <= oc_end ) ! 105: { ! 106: oc_beg++; ! 107: olws++; ! 108: } ! 109: while( *nc_beg == ' ' && nc_beg <= nc_end ) ! 110: { ! 111: nc_beg++; ! 112: nlws++; ! 113: } ! 114: ! 115: /* ! 116: * Now find common heads and tails (com_head & com_tail). If the ! 117: * lengths are the same, the change was probably at the beginning, ! 118: * so count common tail first. This only matters if it could match ! 119: * both ways, for example, when changing ! 120: * " ####" ! 121: * to ! 122: * "#### ####" ! 123: */ ! 124: if( samelen ) ! 125: { ! 126: while( *oc_end==*nc_end && oc_beg<=oc_end && nc_beg<=nc_end ) ! 127: { ! 128: oc_end--; ! 129: nc_end--; ! 130: com_tail++; ! 131: } ! 132: while( *oc_beg==*nc_beg && oc_beg<=oc_end && nc_beg<=nc_end ) ! 133: { ! 134: oc_beg++; ! 135: nc_beg++; ! 136: com_head++; ! 137: } ! 138: } ! 139: else ! 140: { ! 141: while( *oc_beg==*nc_beg && oc_beg<=oc_end && nc_beg<=nc_end ) ! 142: { ! 143: oc_beg++; ! 144: nc_beg++; ! 145: com_head++; ! 146: } ! 147: while( *oc_end==*nc_end && oc_beg<=oc_end && nc_beg<=nc_end ) ! 148: { ! 149: oc_end--; ! 150: nc_end--; ! 151: com_tail++; ! 152: } ! 153: } ! 154: ochanged = oc_end - oc_beg + 1; ! 155: nchanged = nc_end - nc_beg + 1; ! 156: ! 157: /* Optimization: lines are identical, so return now */ ! 158: if( ochanged==0 && nchanged==0 && nlws==olws ) ! 159: { ! 160: #ifdef DEBUG ! 161: if(outf) fprintf(outf, "identical lines, returning early\n"); ! 162: #endif ! 163: return; ! 164: } ! 165: ! 166: #ifdef DEBUG ! 167: if(outf) fprintf (outf, "Before costs: nlws=%2d olws=%2d\ ! 168: com_head=%2d nchanged=%2d ochanged=%2d com_tail=%2d, icfixed %d,\ ! 169: icvar %d/32\n", nlws, olws, com_head, nchanged, ochanged, com_tail, ! 170: SP->term_costs.icfixed, SP->term_costs.icvar); ! 171: if(outf) fprintf (outf, "samelen %d, *oc_beg %o *nc_beg %o\ ! 172: *oc_end %o *nc_end %o\n", samelen, *oc_beg, *nc_beg, *oc_end, *nc_end); ! 173: #endif DEBUG ! 174: ! 175: /* Decide whether to use insert/delete character */ ! 176: #define costic(nchars) (SP->term_costs.icfixed + \ ! 177: (((nchars)*SP->term_costs.icvar)>>5) ) ! 178: ! 179: /* #define costic(nchars) (fprintf(outf,"costic %d, add %g\n", nchars, SP->term_costs.icfixed + (nchars)*SP->term_costs.icvar),(SP->term_costs.icfixed + (nchars)*SP->term_costs.icvar)) */ ! 180: ! 181: cw_idc = cwo_idc = nchanged; ! 182: if( olws > nlws ) /* delete char */ ! 183: { ! 184: cw_idc += costic(olws-nlws); ! 185: } ! 186: else ! 187: { ! 188: if( nlws > olws ) /* insert char */ ! 189: { ! 190: cw_idc += costic(nlws-olws); ! 191: } ! 192: } ! 193: if( ochanged > nchanged ) /* delete char */ ! 194: { ! 195: cw_idc += costic(ochanged-nchanged); ! 196: } ! 197: else ! 198: { ! 199: if( nchanged > ochanged ) /* insert char */ ! 200: { ! 201: cw_idc += costic(nchanged-ochanged); ! 202: } ! 203: } ! 204: if( olws != nlws ) ! 205: { ! 206: cwo_idc += com_head; ! 207: } ! 208: if( olws+ochanged != nlws+nchanged ) ! 209: { ! 210: cwo_idc += com_tail; ! 211: } ! 212: ! 213: if( cw_idc > cwo_idc ) ! 214: { ! 215: /* ! 216: * It's cheaper to NOT use insert/delete character! ! 217: * This may be because the gain from saving the common head ! 218: * and tail is not worth the cost of doing the insert and ! 219: * delete chars (some terminals are slow at this, or the ! 220: * tails may be really short) or because the cost is ! 221: * infinite (i.e. the terminal does not have ins/del char). ! 222: * We note this fact by forgetting about the common heads ! 223: * and tails. ! 224: */ ! 225: ochanged += com_head+com_tail; ! 226: nchanged += com_head+com_tail; ! 227: oc_end += com_tail; ! 228: nc_end += com_tail; ! 229: oc_beg -= com_head; ! 230: nc_beg -= com_head; ! 231: com_head = 0; ! 232: com_tail = 0; ! 233: } ! 234: ! 235: /* ! 236: * On magic cookie terminals, we have to check for the possibility ! 237: * that there is a cookie that we must overwrite. This is only ! 238: * necessary because a "go normal" cookie looks like an ordinary ! 239: * blank but must compare differently. ! 240: */ ! 241: if( magic_cookie_glitch >= 0 && com_tail > 0 && nc_end[1] == ' ' && ! 242: oc_end[0]&A_ATTRIBUTES && oc_end[1] == ' ' ) ! 243: { ! 244: #ifdef DEBUG ! 245: if (outf) fprintf(outf, "adding one because of magic cookie\n"); ! 246: #endif ! 247: oc_end++; ! 248: nc_end++; ! 249: ochanged++; ! 250: nchanged++; ! 251: com_tail--; ! 252: } ! 253: ! 254: #ifdef DEBUG ! 255: if(outf) fprintf (outf, "After costs: nlws=%2d olws=%2d com_head=%2d nchanged=%2d ochanged=%2d com_tail=%2d, cost w/idc %d, cost wo/idc %d\n", ! 256: nlws, olws, com_head, nchanged, ochanged, com_tail, cw_idc, cwo_idc); ! 257: #endif DEBUG ! 258: ! 259: /* ! 260: * Now actually go fix up the line. ! 261: * There are several cases to consider. ! 262: * The most important thing to keep in mind is ! 263: * that deletions need to be done before insertions ! 264: * to prevent shifting good text off the end of the line. ! 265: */ ! 266: ! 267: if( com_head == 0 && com_tail == 0 ) ! 268: { ! 269: /* No common text - must redraw entire line */ ! 270: if( ochanged == 0 && nchanged == 0 ) ! 271: { ! 272: /* Empty lines - do nothing */ ! 273: _chk_typeahead(); ! 274: return; ! 275: } ! 276: /* If empty old line, pretend leading blanks */ ! 277: if( ochanged == 0 && !insert_null_glitch ) ! 278: { ! 279: olws = nlws; ! 280: } ! 281: ! 282: /* Make sure changed parts start at same column */ ! 283: j = nlws - olws; ! 284: if( j > 0 ) ! 285: { ! 286: nc_beg -= j; ! 287: nchanged += j; ! 288: nlws = olws; ! 289: } ! 290: else ! 291: { ! 292: if( j < 0 ) ! 293: { ! 294: oc_beg += j; ! 295: ochanged -= j; ! 296: olws = nlws; ! 297: } ! 298: } ! 299: ! 300: for(nbl=nms=0,p=oc_beg,q=nc_beg;p<=oc_end && q<=nc_end;p++,q++) ! 301: { ! 302: if( *q==' ' && *p != ' ' ) ! 303: { ! 304: nbl++; ! 305: } ! 306: if( *q == *p ) ! 307: { ! 308: nms++; ! 309: } ! 310: #ifdef FULLDEBUG ! 311: if (outf) fprintf(outf, "*p '%c', *q '%c', nms %d, nbl %d\n", *p, *q, nms, nbl); ! 312: #endif ! 313: } ! 314: if( !clr_eol || insert_null_glitch || nms>=nbl ) ! 315: { ! 316: _showstring(ln, min(nlws, olws), nc_beg, nc_end, old); ! 317: if( nlws + nchanged < olws + ochanged ) ! 318: { ! 319: _pos(ln, nlws + nchanged); ! 320: _clreol(); ! 321: } ! 322: } ! 323: else ! 324: { ! 325: if( ochanged > 0 ) ! 326: { ! 327: _pos(ln, olws); ! 328: _clreol(); ! 329: for (p=oc_beg; p<=oc_end; p++) ! 330: *p = ' '; ! 331: } ! 332: _showstring(ln, nlws, nc_beg, nc_end, old); ! 333: } ! 334: _chk_typeahead(); ! 335: return; ! 336: } ! 337: ! 338: if( com_head==0 ) ! 339: { ! 340: /* We have only a common tail. */ ! 341: if( nchanged == 0 && ochanged == 0 ) ! 342: { ! 343: _chk_typeahead(); ! 344: return; ! 345: } ! 346: i = (nlws + nchanged) - (olws + ochanged); ! 347: /* Simplify things - force olws == nlws */ ! 348: j = nlws - olws; ! 349: if( j > 0 ) ! 350: { ! 351: nc_beg -= j; ! 352: nchanged += j; ! 353: nlws = olws; ! 354: } ! 355: else ! 356: { ! 357: if( j < 0 ) ! 358: { ! 359: oc_beg += j; ! 360: ochanged -= j; ! 361: olws = nlws; ! 362: } ! 363: } ! 364: if( i >= 0 ) ! 365: { ! 366: _showstring(ln, nlws, nc_beg, nc_end-i, old); ! 367: if( i > 0 ) ! 368: { ! 369: _ins_string(ln, nlws+nchanged-i, nc_end-i+1, nc_end); ! 370: } ! 371: } ! 372: else ! 373: { ! 374: _showstring(ln, nlws, nc_beg, nc_end, old); ! 375: _delchars(-i); ! 376: } ! 377: _chk_typeahead(); ! 378: return; ! 379: } ! 380: ! 381: /* At this point, we know there is a common head (com_head != 0) */ ! 382: if( nlws < olws ) ! 383: { ! 384: /* Do the leading delete chars right away */ ! 385: _pos(ln, 0); ! 386: _delchars(diff = olws - nlws); ! 387: olws = nlws; ! 388: len = old->length; ! 389: for( i=0; i<len; i++ ) ! 390: { ! 391: old->body[i] = old->body[i]+diff; ! 392: } ! 393: } ! 394: if (com_tail == 0) ! 395: { ! 396: if( nchanged == 0 && ochanged == 0 ) ! 397: { ! 398: if( nlws > olws ) ! 399: { ! 400: _ins_blanks(ln, 0, nlws - olws); ! 401: } ! 402: _chk_typeahead(); ! 403: return; ! 404: } ! 405: _showstring(ln, olws+com_head, nc_beg, nc_end, old); ! 406: if( nchanged < ochanged ) ! 407: { ! 408: _pos(ln, olws + com_head + nchanged); ! 409: _clreol(); ! 410: } ! 411: if( nlws > olws ) ! 412: { ! 413: _ins_blanks(ln, 0, nlws - olws); ! 414: } ! 415: } ! 416: else ! 417: { ! 418: if( nchanged > 0 && ochanged > 0 ) ! 419: { ! 420: i = min(nchanged, ochanged); ! 421: _showstring(ln, olws+com_head, nc_beg, nc_beg+i-1, old); ! 422: } ! 423: if( nchanged < ochanged ) ! 424: { ! 425: _pos(ln, nlws + com_head + nchanged); ! 426: _delchars(ochanged - nchanged); ! 427: } ! 428: else ! 429: { ! 430: if( nchanged > ochanged ) ! 431: { ! 432: _ins_string(ln, olws+com_head+ochanged, ! 433: nc_beg + ochanged, nc_end); ! 434: } ! 435: } ! 436: if( nlws > olws ) ! 437: { ! 438: _ins_blanks(ln, 0, nlws-olws); ! 439: } ! 440: } ! 441: _chk_typeahead(); ! 442: return; ! 443: } ! 444: ! 445: /* ! 446: * Insert nblanks blanks at position (sline, scol). ! 447: */ ! 448: static int ! 449: _ins_blanks(sline, scol, nblanks) ! 450: int sline, scol, nblanks; ! 451: { ! 452: #ifdef DEBUG ! 453: if (outf) fprintf(outf, "_ins_blanks at (%d, %d) %d blanks\n", ! 454: sline, scol, nblanks); ! 455: #endif ! 456: _pos(sline, scol); ! 457: if( nblanks > 1 && parm_ich ) ! 458: { ! 459: /* Insert the characters and then draw on the blanks */ ! 460: _inschars(nblanks); ! 461: } ! 462: else ! 463: { ! 464: /* ! 465: * Type the blanks in "insert mode". This includes ! 466: * having to send insert_character before each character ! 467: * is output. ! 468: */ ! 469: _insmode(1); ! 470: _blanks(nblanks); ! 471: } ! 472: _insmode(0); ! 473: } ! 474: ! 475: /* ! 476: * Insert the given string on the screen. ! 477: * This is like _showstring but you know you're in insert mode. ! 478: */ ! 479: static ! 480: _ins_string(sline, scol, first, last) ! 481: int sline, scol; ! 482: chtype *first, *last; ! 483: { ! 484: int len = last-first+1; ! 485: ! 486: #ifdef DEBUG ! 487: if (outf) fprintf(outf, "_ins_string at (%d, %d) %d chars\n", ! 488: sline, scol, len); ! 489: #endif ! 490: _pos(sline, scol); ! 491: if( len > 1 && parm_ich ) ! 492: { ! 493: /* Insert the characters and then draw on the blanks */ ! 494: _inschars(len); ! 495: _showstring(sline, scol, first, last, NULL); ! 496: } ! 497: else ! 498: { ! 499: /* ! 500: * Type the characters in "insert mode". This includes ! 501: * having to send insert_character before each character ! 502: * is output. ! 503: */ ! 504: _insmode(1); ! 505: _showstring(sline, scol, first, last, NULL); ! 506: } ! 507: _insmode(0); ! 508: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.