Annotation of researchv10no/ncurses/screen/_id_char.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.