Annotation of researchv10no/ncurses/screen/idln.getst.c, revision 1.1

1.1     ! root        1: /*     @(#) idln.getst.c: 1.1 10/15/83 (1.19   2/9/83) */
        !             2: 
        !             3: #include "curses.ext"
        !             4: int InputPending;
        !             5: 
        !             6: struct st {            /* symbol table */
        !             7:        int hash;       /* hashed value of line ("text") */
        !             8:        char oc, nc;    /* 0, 1, or many: # times this value occurs */
        !             9:        short olno;     /* line # of line in "old" array */
        !            10: };
        !            11: 
        !            12: /*
        !            13:  * Routines to deal with calculation of how to do ins/del line optimally.
        !            14:  * Update the Screen.  Consider using insert and delete line.
        !            15:  * Using Heckel's algorithm from April 1978 CACM.
        !            16:  *
        !            17:  * This algorithm is based on two observations:
        !            18:  *  (1) A line that occurs once and only once in each file must be
        !            19:  *     the same line (unchanged but possibly moved).
        !            20:  *  (2) If i each file immediately adjacent to a "found" line pair
        !            21:  *     there are lines identical to each other, these lines must be
        !            22:  *     the same line.  Repeated application will "find" sequences
        !            23:  *     of unchanged lines.
        !            24:  *
        !            25:  * We view the old and new screens' hashed values as the old and new "files".
        !            26:  * Since crossing match lines cannot be taken advantage of with real insert
        !            27:  * and delete line, we ignore those matches - this is the one real disadvantage
        !            28:  * of this algorithm.
        !            29:  *
        !            30:  * first and last are the integer line numbers (first line is 1) of the
        !            31:  * portion of the screen to consider.
        !            32:  */
        !            33: _id_line(first, last)
        !            34: register int first, last;
        !            35: {
        !            36:        register int i, j, k, n;
        !            37:        int base, ndel;
        !            38:        int idl_offset = 0;     /* number of extra del lines done so far. */
        !            39: #ifdef NONSTANDARD
        !            40:        static
        !            41: #endif NONSTANDARD
        !            42:                struct st symtab[256];
        !            43:        /*
        !            44:         * oa and na represent the old and new files (SP->cur_body and
        !            45:         * SP->std_body, respectively.)  If they are > 0 they are
        !            46:         * subscripts in each other (e.g. na[4] = 3 means that na[4]
        !            47:         * points to oa[3]).  If they are <= 0 their negative is taken
        !            48:         * as a symbol table index into the symtab array.
        !            49:         */
        !            50: #ifdef NONSTANDARD
        !            51:        static
        !            52: #endif NONSTANDARD
        !            53:                short oa[256], na[256];
        !            54: 
        !            55:        for (i=0; i<256; i++)
        !            56:                symtab[i].hash = symtab[i].oc = symtab[i].nc = 0;
        !            57: 
        !            58: #ifdef DEBUG
        !            59:        if(outf) fprintf(outf, "_id_line(%d, %d)\n", first, last);
        !            60: #endif
        !            61:        /* Pass 1: enter old file into symtab */
        !            62:        for (i=first; i<=last; i++) {
        !            63:                n = _getst(SP->std_body[i]->hash, symtab);
        !            64:                symtab[n].nc++;
        !            65:                na[i] = -n;
        !            66:        }
        !            67: 
        !            68: #ifdef LONGDEBUG
        !            69:        if(outf) fprintf(outf, "Pass 2\n");
        !            70:        if(outf) fprintf(outf, "na[12] = %d\n", na[12]);
        !            71: #endif
        !            72:        /* Pass 2: enter new into symtab */
        !            73:        for (i=first; i<=last; i++) {
        !            74:                n = _getst(SP->cur_body[i]->hash, symtab);
        !            75:                symtab[n].oc++;
        !            76:                symtab[n].olno = i;
        !            77:                oa[i] = -n;
        !            78:        }
        !            79: 
        !            80: #ifdef LONGDEBUG
        !            81:        if(outf) fprintf(outf, "Pass 3\n");
        !            82:        if(outf) fprintf(outf, "\nsymtab        oc      nc      olno    hash\n");
        !            83:        for (i=0; i<256; i++)
        !            84:                if (symtab[i].hash)
        !            85:                        if(outf) fprintf(outf, "%d      %d      %d      %d      %d\n",
        !            86:                                i, symtab[i].oc, symtab[i].nc,
        !            87:                                symtab[i].olno, symtab[i].hash);
        !            88: #endif
        !            89:        /*
        !            90:         * Pass 3: Match all lines with exactly one match.
        !            91:         * Matching lines in oa and na point at each other.
        !            92:         */
        !            93:        for (i=first; i<=last; i++) {
        !            94:                n = -na[i];
        !            95:                if (symtab[n].oc == 1 && symtab[n].nc == 1) {
        !            96:                        na[i] = symtab[n].olno;
        !            97:                        oa[na[i]] = i;
        !            98:                }
        !            99:        }
        !           100:        oa[first-1] = na[first-1] = first-1;
        !           101:        oa[last+1] = na[last+1] = last+1;
        !           102: 
        !           103:        /* Pass 4: Find following implied matches based on sequence */
        !           104: #ifdef DEBUG
        !           105:        if(outf) fprintf(outf, "Pass 4\n");
        !           106: #endif
        !           107:        for (i=first; i<=last; i++) {
        !           108:                if (na[i] > 0 && na[i+1] <= 0) {
        !           109:                        j = na[i];
        !           110:                        if (na[i+1] == oa[j+1]) {
        !           111:                                oa[j+1] = i+1;
        !           112:                                na[i+1] = j+1;
        !           113:                        }
        !           114:                }
        !           115:        }
        !           116: 
        !           117:        /* Pass 5: Find preceding implied matches based on sequence */
        !           118: #ifdef DEBUG
        !           119:        if(outf) fprintf(outf, "Pass 5\n");
        !           120:        if(outf) fprintf(outf, "na[12] = %d\n", na[12]);
        !           121: #endif
        !           122:        for (i=last; i>=first; i--) {
        !           123:                if (na[i] > 0 && na[i-1] <= 0) {
        !           124:                        j = na[i];
        !           125:                        if (na[i-1] == oa[j-1]) {
        !           126:                                oa[j-1] = i-1;
        !           127:                                na[i-1] = j-1;
        !           128:                        }
        !           129:                }
        !           130:        }
        !           131: 
        !           132: #ifdef DEBUG
        !           133:        if(outf) fprintf(outf, "\ni     oa      na After pass 5\n");
        !           134:        for (i=first; i<=last; i++)
        !           135:                if(outf) fprintf(outf, "%d      %d      %d\n", i, oa[i], na[i]);
        !           136:        if(outf) fprintf(outf, "\n");
        !           137: #endif
        !           138:        /* Pass 6: Find matches from more than one line, in order.  */
        !           139:        for (i=first; i<=last; i++) {
        !           140:                if (na[i] < -1 && symtab[-na[i]].nc > 1) {
        !           141:                        j = na[i];
        !           142: #ifdef DEBUG
        !           143:                        if(outf) fprintf(outf, "i %d, na[i] %d\n", i, na[i]);
        !           144: #endif
        !           145:                        for (k=first; k<last; k++) {
        !           146:                                if (j == oa[k]) {
        !           147: #ifdef DEBUG
        !           148:                        if(outf) fprintf(outf, "k %d, oa[i] %d, matching them up\n", k, oa[i]);
        !           149: #endif
        !           150:                                        na[i] = k;
        !           151:                                        oa[k] = i;
        !           152:                                        break;
        !           153:                                }
        !           154:                        }
        !           155:                }
        !           156:        }
        !           157: #ifdef DEBUG
        !           158:        if(outf) fprintf(outf, "\ni     oa      na After pass 6\n");
        !           159:        for (i=first; i<=last; i++)
        !           160:                if(outf) fprintf(outf, "%d      %d      %d\n", i, oa[i], na[i]);
        !           161:        if(outf) fprintf(outf, "\n");
        !           162: #endif
        !           163: 
        !           164:        /*
        !           165:         * Passes 7abcd: Remove any match lines that cross backwards.
        !           166:         * (Draw lines connecting the matching lines on debug output
        !           167:         * to see what I mean about crossing lines.)
        !           168:         * The na's must be monotonically increasing except for those < 0
        !           169:         * which say there is no match.  k counts the number of matches
        !           170:         * we have to throw away.
        !           171:         */
        !           172:        n = k = 0;      /* k is the added cost to throw away nw-se matches */
        !           173:        /* 7a: get nw-se cost in k */
        !           174:        for (i=first; i<=last; i++) {
        !           175:                if (na[i] > 0 && na[i] < n) {
        !           176:                        k += SP->std_body[i]->bodylen;
        !           177:                }
        !           178:                if (na[i] > n)
        !           179:                        n = na[i];
        !           180:        }
        !           181:        /* 7b: get sw-ne cost in j */
        !           182:        /* Consider throwing away in the other direction.  */
        !           183:        if (k > 0) {
        !           184:                j = 0;  /* j is the added cost to throw away sw-ne matches */
        !           185:                n = last+1;
        !           186:                for (i=last; i>=first; i--) {
        !           187:                        if (na[i] > 0 && na[i] > n) {
        !           188:                                j += SP->std_body[i]->bodylen;
        !           189:                        }
        !           190:                        if (na[i] > 0 && na[i] < n)
        !           191:                                n = na[i];
        !           192:                }
        !           193:        }
        !           194:        else
        !           195:                j = 1;  /* will be > 0 for sure */
        !           196: #ifdef DEBUG
        !           197:        if(outf) fprintf(outf, "forward, k is %d, backward, j is %d\n", k, j);
        !           198: #endif
        !           199: 
        !           200:        /* Remove whichever is cheapest. */
        !           201:        if (k < j) {
        !           202:                /* 7c: remove nw-se */
        !           203:                n = 0;
        !           204:                for (i=first; i<=last; i++) {
        !           205:                        if (na[i] > 0 && na[i] < n) {
        !           206:                                oa[na[i]] = -1;
        !           207:                                na[i] = -1;
        !           208:                        }
        !           209:                        if (na[i] > n)
        !           210:                                n = na[i];
        !           211:                }
        !           212:        } else {
        !           213:                /* 7d: remove sw-ne */
        !           214:                n = last+1;
        !           215:                for (i=last; i>=first; i--) {
        !           216:                        if (na[i] > 0 && na[i] > n) {
        !           217:                                oa[na[i]] = -1;
        !           218:                                na[i] = -1;
        !           219:                        }
        !           220:                        if (na[i] > 0 && na[i] < n)
        !           221:                                n = na[i];
        !           222:                }
        !           223:        }
        !           224: #ifdef DEBUG
        !           225:        if(outf) fprintf(outf, "\ni     oa      na After pass 7\n");
        !           226:        for (i=first; i<=last; i++)
        !           227:                if(outf) fprintf(outf, "%d      %d      %d\n", i, oa[i], na[i]);
        !           228:        if(outf) fprintf(outf, "\nPass 7\n");
        !           229:        if(outf) fprintf(outf, "ILmf %d/32, ILov %d\n",
        !           230:                SP->term_costs.ilvar, SP->term_costs.ilfixed);
        !           231:        if(outf) fprintf(outf, "i       base    j       k       DC      n\n");
        !           232: #endif
        !           233: 
        !           234:        /*
        !           235:         * Pass 8: we go through and remove all matches if the
        !           236:         * overall ins/del lines would be too expensive to capatilize on.
        !           237:         * j is cost with ins/del line, k is cost without it.  base is the
        !           238:         * logical beginning of the oa array, as the array would be after
        !           239:         * inserts and deletes, ignoring anything before row i.  This
        !           240:         * approximates things by not taking into account SP->curptr motion,
        !           241:         * funny insert line costs, or lines that are partially equal.
        !           242:         * This macro is the cost to insert or delete n lines at screen line i.
        !           243:         * It is approximated for speed and simplicity, but shouldn't be.
        !           244:         * The approximation assumes each line is deleted separately.
        !           245:         */
        !           246: 
        !           247: #define idlcost(n, i) n * \
        !           248:        (((SP->term_costs.ilvar * (lines-i))>>5) + SP->term_costs.ilfixed)
        !           249: 
        !           250:        base = ndel = 0;
        !           251:        j = k = 0;
        !           252:        for (i=first; i<=last; i++) {
        !           253: #ifdef DEBUG
        !           254:                n = 0;
        !           255: #endif
        !           256:                if (oa[i] != na[i]) {
        !           257:                        /* Cost to turn Phys[i] into Des[i] on same line */
        !           258:                        if (SP->cur_body[i] == 0 || SP->cur_body[i]->length == 0) {
        !           259:                                k += SP->std_body[i]->bodylen;
        !           260:                        } else if (SP->std_body[i] == 0 ||
        !           261:                                   SP->std_body[i]->length == 0) {
        !           262:                                k += 2; /* guess at cost of clr to eol */
        !           263:                        } else {
        !           264:                                register chtype *p0, *p1, *p2;
        !           265:                                n = SP->cur_body[i]->length -
        !           266:                                    SP->std_body[i]->length;
        !           267:                                if (n > 0) {
        !           268:                                        k += n;
        !           269:                                        n = SP->std_body[i]->length;
        !           270:                                } else {
        !           271:                                        k += -n;
        !           272:                                        n = SP->cur_body[i]->length;
        !           273:                                }
        !           274:                                p0 = &SP->std_body[i]->body[0];
        !           275:                                p1 = &SP->std_body[i]->body[n];
        !           276:                                p2 = &SP->cur_body[i]->body[n];
        !           277:                                while (--p1 >= p0)
        !           278:                                        if (*p1 != *--p2)
        !           279:                                                k++;
        !           280:                        }
        !           281:                }
        !           282:                /* cost to do using ins/del line */
        !           283:                if (na[i] <= 0) {
        !           284:                        /* totally different - plan on redrawing whole thing
        !           285:                         * (even though chances are good they are partly the
        !           286:                         * same - _id_char will take care of this, if it
        !           287:                         * happens to get the same line on the screen).
        !           288:                         * Should probably figure out what will be there on
        !           289:                         * the screen and do above k algorithm on it.
        !           290:                         */
        !           291:                        j += SP->std_body[i]->bodylen;
        !           292:                } else if ((n = (na[i] - base) - i) > 0) {
        !           293:                        /* delete line */
        !           294:                        j +=  idlcost(n, i);
        !           295:                        ndel += n;
        !           296:                        base += n;
        !           297:                } else if (n < 0) {
        !           298:                        /* insert line */
        !           299:                        j +=  idlcost((-n), i);
        !           300:                        ndel += n;
        !           301:                        base += n;
        !           302:                }
        !           303:                /* else they are the same line: no cost */
        !           304: #ifdef DEBUG
        !           305:                if(outf) fprintf(outf, "%d      %d      %d      %d      %d", i, base, j, k, SP->std_body[i]->bodylen);
        !           306:                if (n < 0)
        !           307:                        if(outf) fprintf(outf, "        %d lines inserted", -n);
        !           308:                else if (n > 0)
        !           309:                        if(outf) fprintf(outf, "        %d lines deleted", n);
        !           310:                if(outf) fprintf(outf, "\n");
        !           311: #endif
        !           312:        }
        !           313:        if (j >= k) {
        !           314:                /* It's as cheap to just redraw, so do it. */
        !           315:                for (i=first; i<=last; i++)
        !           316:                        na[i] = oa[i] = -1;
        !           317:        } else if (ndel < 0) {
        !           318:                ndel = -ndel;
        !           319: #ifdef DEBUG
        !           320:                if(outf) fprintf(outf, "will do %d extra inserts, so del now.\n", ndel);
        !           321: #endif
        !           322:                if (SP->des_bot_mgn - last >= 0) {
        !           323:                        _pos(last-ndel, 0);
        !           324:                        idl_offset += ndel;
        !           325:                        _dellines(ndel);
        !           326:                }
        !           327:        }
        !           328: 
        !           329: #ifdef DEBUG
        !           330:        if(outf) fprintf(outf, "\ni     oa      na After pass 8\n");
        !           331:        for (i=first; i<=last; i++)
        !           332:                if(outf) fprintf(outf, "%d      %d      %d\n", i, oa[i], na[i]);
        !           333:        if(outf) fprintf(outf, "\n");
        !           334: #endif
        !           335:        /* Pass 9: Do any delete lines that are needed */
        !           336:        k = first-1;    /* previous matching spot in oa */
        !           337:        ndel = 0;
        !           338:        for (i=first; i<=last; i++) {
        !           339:                if (oa[i] > 0) {
        !           340:                        n = (i-k) - (oa[i]-oa[k]);
        !           341: #ifdef DEBUG
        !           342:                        if(outf) fprintf(outf,
        !           343:                        "del loop, i %d, k %d, oa[i] %d, oa[k] %d, n %d\n",
        !           344:                        i, k, oa[i], oa[k], n);
        !           345: #endif
        !           346:                        if (n > 0) {
        !           347:                                if (i-n == SP->des_top_mgn+1) {
        !           348:                                        _scrollf(n);
        !           349:                                } else {
        !           350:                                        _pos(i-n-1, 0);
        !           351:                                        _dellines(n);
        !           352:                                }
        !           353:                                idl_offset += n;
        !           354:                                ndel += n;
        !           355:                                for (j=i-n; j<=last-n; j++) {
        !           356:                                        if (oa[j] > 0 && na[oa[j]] > 0)
        !           357:                                                na[oa[j]] -= n;
        !           358:                                        _line_free(SP->cur_body[j]);
        !           359:                                        SP->cur_body[j] = SP->cur_body[j+n];
        !           360:                                        oa[j] = oa[j+n];
        !           361:                                }
        !           362:                                for ( ; j<=last; j++) {
        !           363:                                        if (oa[j] > 0 && na[oa[j]] > 0)
        !           364:                                                na[oa[j]] -= n;
        !           365:                                        _line_free(SP->cur_body[j]);
        !           366:                                        SP->cur_body[j] = NULL;
        !           367:                                        oa[j] = -1;
        !           368:                                }
        !           369:                                i -= n;
        !           370:                        }
        !           371:                        k = i;
        !           372:                }
        !           373:        }
        !           374: #ifdef DEBUG
        !           375:        if(outf) fprintf(outf, "\ni     oa      na After pass 9\n");
        !           376:        for (i=first; i<=last; i++)
        !           377:                if(outf) fprintf(outf, "%d      %d      %d\n", i, oa[i], na[i]);
        !           378:        if(outf) fprintf(outf, "\n");
        !           379: #endif
        !           380: 
        !           381:        /* Half way through - check for typeahead */
        !           382:        _chk_typeahead();
        !           383:        if (idl_offset == 0 && InputPending) {
        !           384: #ifdef DEBUG
        !           385:                if (outf) fprintf(outf, "InputPending %d, aborted after dellines\n", InputPending);
        !           386: #endif
        !           387:                return;
        !           388:        }
        !           389: 
        !           390:        /* for pass 10, j is the next line above i that will be used */
        !           391:        for (j=first; na[j] <= 0; j++)
        !           392:                ;
        !           393:        
        !           394:        /* Pass 10: insert and fix remaining lines */
        !           395:        for (i=first; i<=last; i++) {
        !           396:                if (j <= i)
        !           397:                        for (j++; na[j] <= 0; j++)
        !           398:                                ;
        !           399: #ifdef DEBUG
        !           400:                if(outf) fprintf(outf, "i %d, j %d, na[i] %d, na[j] %d\n",
        !           401:                        i, j, na[i], na[j]);
        !           402:                if (na[i] > 0 && na[i] != i)
        !           403:                        if(outf) fprintf(outf, "OOPS: na[%d] is %d\n", i, na[i]);
        !           404: #endif
        !           405:                /* There are two cases: na[i] < 0  or na[i] == i */
        !           406:                if (na[i] < 0) {
        !           407:                        /*
        !           408:                         * This line must be fixed from scratch.  First
        !           409:                         * check to see if the line physically there is
        !           410:                         * going to be used later, if so, move it down.
        !           411:                         */
        !           412:                        if (na[j]==i || ndel+i>last && last<SP->des_bot_mgn+1) {
        !           413:                                _pos(i-1, 0);
        !           414:                                n = j - i;
        !           415:                                idl_offset -= n;
        !           416:                                ndel -= n;
        !           417:                                _inslines(n);
        !           418:                                _chk_typeahead();
        !           419:                                if (idl_offset == 0 && InputPending) {
        !           420: #ifdef DEBUG
        !           421:                                        if (outf) fprintf(outf, "InputPending %d, aborted after dellines\n", InputPending);
        !           422: #endif
        !           423:                                        return;
        !           424:                                }
        !           425:                                for (k=last; k>=j; k--) {
        !           426:                                        if (na[k] > 0)
        !           427:                                                na[k] += n;
        !           428:                                        _line_free(SP->cur_body[k]);
        !           429:                                        SP->cur_body[k] = SP->cur_body[k-n];
        !           430:                                        oa[k] = oa[k-n];
        !           431:                                }
        !           432:                                for ( ; k>=i; k--) {
        !           433:                                        if (na[k] > 0)
        !           434:                                                na[k] += n;
        !           435:                                        _line_free(SP->cur_body[k]);
        !           436:                                        SP->cur_body[k] = NULL;
        !           437:                                        oa[k] = 0;
        !           438:                                }
        !           439:                        }
        !           440:                }
        !           441:                /* Now transform line i to new line j */
        !           442:                if (!InputPending) {
        !           443:                        _id_char (SP->cur_body[i], SP->std_body[i], i-1);
        !           444:                        if (SP->cur_body[i] != SP->std_body[i])
        !           445:                                _line_free (SP->cur_body[i]);
        !           446:                        SP->cur_body[i] = SP->std_body[i];
        !           447:                }
        !           448:        }
        !           449: #ifdef DEBUG
        !           450:        if(outf) fprintf(outf, "\ni     oa      na After pass 10: _id_line completed\n");
        !           451:        for (i=first; i<=last; i++)
        !           452:                if(outf) fprintf(outf, "%d      %d      %d\n", i, oa[i], na[i]);
        !           453:        if(outf) fprintf(outf, "\n");
        !           454: #endif
        !           455: }
        !           456: 
        !           457: int
        !           458: _getst(val, symtab)
        !           459: register struct st *symtab;
        !           460: {
        !           461:        register int i;
        !           462:        register int h;
        !           463:        register int hopcount = 256;
        !           464: 
        !           465:        i = val & 0377;
        !           466:        while ((h=symtab[i].hash) && h != val) {
        !           467:                if (++i >= 256)
        !           468:                        i = 0;
        !           469:                if (--hopcount <= 0) {
        !           470:                        _ec_quit("Hash table full in dispcalc", "");
        !           471:                }
        !           472:        }
        !           473:        symtab[i].hash = val;
        !           474: #ifdef LONGDEBUG
        !           475:        if(outf) fprintf(outf, "_getst, val %d, init slot %d, return %d\n",
        !           476:                val, val & 0377, i);
        !           477: #endif
        !           478:        return i;
        !           479: }

unix.superglobalmegacorp.com

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