Annotation of 43BSD/contrib/jove/insert.c, revision 1.1.1.1

1.1       root        1: /*************************************************************************
                      2:  * This program is copyright (C) 1985, 1986 by Jonathan Payne.  It is    *
                      3:  * provided to you without charge for use only on a licensed Unix        *
                      4:  * system.  You may copy JOVE provided that this notice is included with *
                      5:  * the copy.  You may not sell copies of this program or versions        *
                      6:  * modified for use on microcomputer systems, unless the copies are      *
                      7:  * included with a Unix system distribution and the source is provided.  *
                      8:  *************************************************************************/
                      9: 
                     10: #include "jove.h"
                     11: 
                     12: #include "ctype.h"
                     13: 
                     14: /* Make a newline after AFTER in buffer BUF, UNLESS after is 0,
                     15:    in which case we insert the newline before after. */
                     16: 
                     17: Line *
                     18: listput(buf, after)
                     19: register Buffer        *buf;
                     20: register Line  *after;
                     21: {
                     22:        register Line   *newline = nbufline();
                     23: 
                     24:        if (after == 0) {       /* Before the first line */
                     25:                newline->l_next = buf->b_first;
                     26:                newline->l_prev = 0;
                     27:                buf->b_first = newline;
                     28:        } else {
                     29:                newline->l_prev = after;
                     30:                newline->l_next = after->l_next;
                     31:                after->l_next = newline;
                     32:        }
                     33:        if (newline->l_next)
                     34:                newline->l_next->l_prev = newline;
                     35:        else
                     36:                if (buf)
                     37:                        buf->b_last = newline;
                     38:        if (buf && buf->b_dot == 0)
                     39:                buf->b_dot = newline;
                     40:        return newline;
                     41: }      
                     42: 
                     43: /* Divide the current line and move the current line to the next one */
                     44: 
                     45: LineInsert()
                     46: {
                     47:        register int    num = exp;
                     48:        char    newline[LBSIZE];
                     49:        register Line   *newdot,
                     50:                        *olddot;
                     51:        int     oldchar;
                     52: 
                     53:        exp = 1;
                     54:        olddot = curline;
                     55:        oldchar = curchar;
                     56: 
                     57:        newdot = curline;
                     58:        while (--num >= 0) {
                     59:                newdot = listput(curbuf, newdot);
                     60:                SavLine(newdot, NullStr);
                     61:        }
                     62: 
                     63:        modify();
                     64:        if (curchar != 0) {
                     65:                strcpy(newline, &linebuf[curchar]);
                     66:                linebuf[curchar] = '\0';        /* Shorten this line */
                     67:                SavLine(curline, linebuf);
                     68:                strcpy(linebuf, newline);
                     69:        } else {        /* Redisplay optimization */
                     70:                newdot->l_dline = curline->l_dline;
                     71:                SavLine(curline, NullStr);
                     72:        }
                     73: 
                     74:        makedirty(curline);
                     75:        curline = newdot;
                     76:        curchar = 0;
                     77:        makedirty(curline);
                     78:        IFixMarks(olddot, oldchar, curline, curchar);
                     79: }      
                     80: 
                     81: n_indent(goal)
                     82: register int   goal;
                     83: {
                     84:        if (goal < 0)
                     85:                return;
                     86:        DoTimes(Insert('\t'), (goal / tabstop));
                     87:        if (goal % tabstop)
                     88:                DoTimes(Insert(' '), (goal % tabstop));
                     89:        exp_p = 0;
                     90:        exp = 1;
                     91: }
                     92: 
                     93: SelfInsert()
                     94: {
                     95: #ifdef ABBREV
                     96:        if (MinorMode(Abbrev) && !ismword(LastKeyStruck) &&
                     97:            !bolp() && ismword(linebuf[curchar - 1]))
                     98:                AbbrevExpand();
                     99: #endif
                    100:        if (MinorMode(OverWrite)) {
                    101:                register int    num,
                    102:                                i;
                    103: 
                    104:                for (i = 0, num = exp, exp = 1; i < num; i++) {
                    105:                        int     pos = calc_pos(linebuf, curchar);
                    106: 
                    107:                        if (!eolp()) {
                    108:                                if (linebuf[curchar] == '\t') {
                    109:                                        if ((pos + 1) == ((pos + tabstop) - (pos % tabstop)))
                    110:                                                DelNChar();
                    111:                                } else
                    112:                                        DelNChar();
                    113:                        }
                    114:                        Insert(LastKeyStruck);
                    115:                }
                    116:        } else
                    117:                Insert(LastKeyStruck);
                    118: 
                    119:        if (MinorMode(Fill) && (curchar >= RMargin ||
                    120:                               (calc_pos(linebuf, curchar) >= RMargin)))
                    121:                DoJustify(curline, 0, curline,
                    122:                          curchar + strlen(&linebuf[curchar]), 1, LMargin);
                    123: }
                    124: 
                    125: Insert(c)
                    126: {
                    127:        if (exp <= 0)
                    128:                return;
                    129:        modify();
                    130:        makedirty(curline);
                    131:        ins_c(c, linebuf, curchar, exp, LBSIZE);
                    132:        IFixMarks(curline, curchar, curline, curchar + exp);
                    133:        curchar += exp;
                    134: }      
                    135: 
                    136: /* Tab in to the right place for C mode */
                    137: 
                    138: Tab()
                    139: {
                    140: #ifdef LISP
                    141:        if (MajorMode(LISPMODE)) {
                    142:                Mark    *m = bolp() ? 0 : MakeMark(curline, curchar, FLOATER);
                    143: 
                    144:                Bol();
                    145:                DelWtSpace();
                    146:                (void) lisp_indent();
                    147:                if (m) {
                    148:                        ToMark(m);
                    149:                        DelMark(m);
                    150:                }
                    151:                if (bolp())
                    152:                        ToIndent();
                    153:                return;
                    154:        }
                    155: #endif
                    156:        if (MajorMode(CMODE) && strlen(linebuf) == 0)
                    157:                (void) c_indent(CIndIncrmt);
                    158:        else
                    159:                SelfInsert();
                    160: }
                    161: 
                    162: QuotChar()
                    163: {
                    164:        int     c;
                    165:        extern int      alarmed;        /* If waitfor had to wait. */
                    166: 
                    167:        c = waitchar();
                    168:        if (alarmed)
                    169:                message(key_strokes);
                    170:        if (c == CTL(J))
                    171:                LineInsert();
                    172:        else if (c != CTL(@))
                    173:                Insert(c);
                    174: }
                    175: 
                    176: /* Insert the paren.  If in C mode and c is a '}' then insert the
                    177:    '}' in the "right" place for C indentation; that is indented 
                    178:    the same amount as the matching '{' is indented. */
                    179: 
                    180: int    PDelay = 5,     /* 1/2 a second */
                    181:        CIndIncrmt = 8;
                    182: 
                    183: DoParen()
                    184: {
                    185:        Bufpos  *bp = (Bufpos *) -1;
                    186:        int     nx,
                    187:                c = LastKeyStruck;
                    188: 
                    189:        if (!isclosep(c)) {
                    190:                SelfInsert();
                    191:                return;
                    192:        }
                    193: 
                    194:        if (MajorMode(CMODE) && c == '}' && blnkp(linebuf)) {
                    195:                DelWtSpace();
                    196:                bp = c_indent(0);
                    197:        }
                    198: #ifdef LISP
                    199:        if (MajorMode(LISPMODE) && c == ')' && blnkp(linebuf)) {
                    200:                DelWtSpace();
                    201:                bp = lisp_indent();
                    202:        }
                    203: #endif
                    204:        SelfInsert();
                    205:        if (MinorMode(ShowMatch) && !charp() && !in_macro()) {
                    206:                BackChar();     /* Back onto the ')' */
                    207:                if ((int) bp == -1)
                    208:                        bp = m_paren(c, BACKWARD, NO, YES);
                    209:                ForChar();
                    210:                if (bp != 0) {
                    211:                        nx = in_window(curwind, bp->p_line);
                    212:                        if (nx != -1) {         /* is visible */
                    213:                                Bufpos  b;
                    214: 
                    215:                                DOTsave(&b);
                    216:                                SetDot(bp);
                    217:                                (void) SitFor(PDelay);
                    218:                                SetDot(&b);
                    219:                        } else
                    220:                                s_mess("%s", lcontents(bp->p_line));
                    221:                }
                    222:                mp_error();     /* display error message */
                    223:        }
                    224: }
                    225: 
                    226: LineAI()
                    227: {
                    228:        DoNewline(TRUE);
                    229: }
                    230: 
                    231: Newline()
                    232: {
                    233:        DoNewline(MinorMode(Indent));
                    234: }      
                    235: 
                    236: DoNewline(indentp)
                    237: {
                    238:        Bufpos  save;
                    239:        int     indent;
                    240: 
                    241:        /* first we calculate the indent of the current line */
                    242:        DOTsave(&save);
                    243:        ToIndent();
                    244:        indent = calc_pos(linebuf, curchar);
                    245:        SetDot(&save);
                    246: 
                    247:        /* If there is more than 2 blank lines in a row then don't make
                    248:           a newline, just move down one. */
                    249: 
                    250: #ifdef ABBREV
                    251:        if (MinorMode(Abbrev) && !ismword(LastKeyStruck) &&
                    252:            !bolp() && ismword(linebuf[curchar - 1]))
                    253:                AbbrevExpand();
                    254: #endif
                    255: #ifdef LISP
                    256:        if (MajorMode(LISPMODE))
                    257:                DelWtSpace();
                    258: #endif
                    259:        else if (blnkp(linebuf))
                    260:                DelWtSpace();
                    261:                
                    262:        if (exp == 1 && eolp() && TwoBlank())
                    263:                SetLine(curline->l_next);
                    264:        else
                    265:                LineInsert();
                    266: 
                    267:        if (indentp)
                    268: #ifdef LISP
                    269:            if (MajorMode(LISPMODE))
                    270:                (void) lisp_indent();
                    271:            else
                    272: #endif
                    273:                n_indent((LMargin == 0) ? indent : LMargin);
                    274: }
                    275: 
                    276: ins_str(str, ok_nl)
                    277: register char  *str;
                    278: {
                    279:        register char   c;
                    280:        Bufpos  save;
                    281:        int     llen;
                    282: 
                    283:        DOTsave(&save);
                    284:        llen = strlen(linebuf);
                    285:        while (c = *str++) {
                    286:                if (c == '\n' || (ok_nl && llen >= LBSIZE - 2)) {
                    287:                        IFixMarks(save.p_line, save.p_char, curline, curchar);
                    288:                        modify();
                    289:                        makedirty(curline);
                    290:                        LineInsert();
                    291:                        DOTsave(&save);
                    292:                        llen = strlen(linebuf);
                    293:                }
                    294:                if (c != '\n') {
                    295:                        ins_c(c, linebuf, curchar++, 1, LBSIZE);
                    296:                        llen++;
                    297:                }
                    298:        }
                    299:        IFixMarks(save.p_line, save.p_char, curline, curchar);
                    300:        modify();
                    301:        makedirty(curline);
                    302: }
                    303: 
                    304: OpenLine()
                    305: {
                    306:        Bufpos  dot;
                    307: 
                    308:        DOTsave(&dot);
                    309:        LineInsert();   /* Open the lines... */
                    310:        SetDot(&dot);
                    311: }
                    312: 
                    313: /* Take the region FLINE/FCHAR to TLINE/TCHAR and insert it at
                    314:    ATLINE/ATCHAR in WHATBUF. */
                    315: 
                    316: Bufpos *
                    317: DoYank(fline, fchar, tline, tchar, atline, atchar, whatbuf)
                    318: Line   *fline,
                    319:        *tline,
                    320:        *atline;
                    321: Buffer *whatbuf;
                    322: {
                    323:        register Line   *newline;
                    324:        static Bufpos   bp;
                    325:        char    save[LBSIZE],
                    326:                buf[LBSIZE];
                    327:        Line    *startline = atline;
                    328:        int     startchar = atchar;
                    329: 
                    330:        lsave();
                    331:        if (whatbuf)
                    332:                modify();
                    333:        (void) ltobuf(atline, genbuf);
                    334:        strcpy(save, &genbuf[atchar]);
                    335: 
                    336:        (void) ltobuf(fline, buf);
                    337:        if (fline == tline)
                    338:                buf[tchar] = '\0';
                    339: 
                    340:        linecopy(genbuf, atchar, &buf[fchar]);
                    341:        atline->l_dline = putline(genbuf);
                    342:        makedirty(atline);
                    343: 
                    344:        fline = fline->l_next;
                    345:        while (fline != tline->l_next) {
                    346:                newline = listput(whatbuf, atline);
                    347:                newline->l_dline = fline->l_dline;
                    348:                makedirty(newline);
                    349:                fline = fline->l_next;
                    350:                atline = newline;
                    351:                atchar = 0;
                    352:        }
                    353: 
                    354:        (void) getline(atline->l_dline, genbuf);
                    355:        atchar += tchar;
                    356:        linecopy(genbuf, atchar, save);
                    357:        atline->l_dline = putline(genbuf);
                    358:        makedirty(atline);
                    359:        IFixMarks(startline, startchar, atline, atchar);
                    360:        bp.p_line = atline;
                    361:        bp.p_char = atchar;
                    362:        this_cmd = YANKCMD;
                    363:        getDOT();                       /* Whatever used to be in linebuf */
                    364:        return &bp;
                    365: }
                    366: 
                    367: YankPop()
                    368: {
                    369:        Line    *line,
                    370:                *last;
                    371:        Mark    *mp = CurMark();
                    372:        Bufpos  *dot;
                    373:        int     dir = -1;       /* Direction to rotate the ring */
                    374: 
                    375:        if (last_cmd != YANKCMD)
                    376:                complain("Yank something first!");
                    377: 
                    378:        lfreelist(reg_delete(mp->m_line, mp->m_char, curline, curchar));
                    379: 
                    380:        /* Now must find a recently killed region. */
                    381: 
                    382:        if (exp < 0)
                    383:                dir = 1;
                    384: 
                    385:        killptr += dir;
                    386:        for (;;) {
                    387:                if (killptr < 0)
                    388:                        killptr = NUMKILLS - 1;
                    389:                else if (killptr >= NUMKILLS)
                    390:                        killptr = 0;
                    391:                if (killbuf[killptr])
                    392:                        break;
                    393:                killptr += dir;
                    394:        }
                    395: 
                    396:        this_cmd = YANKCMD;
                    397: 
                    398:        line = killbuf[killptr];
                    399:        last = lastline(line);
                    400:        dot = DoYank(line, 0, last, length(last), curline, curchar, curbuf);
                    401:        MarkSet(CurMark(), curline, curchar);
                    402:        SetDot(dot);
                    403: }
                    404: 
                    405: /* This is an attempt to reduce the amount of memory taken up by each line.
                    406:    Without this each malloc of a line uses sizeof (line) + sizeof(HEADER)
                    407:    where line is 3 words and HEADER is 1 word.
                    408:    This is going to allocate memory in chucks of CHUNKSIZE * sizeof (line)
                    409:    and divide each chuck into lineS.  A line is free in a chunk when its
                    410:    line->l_dline == 0, so freeline sets dline to 0. */
                    411: 
                    412: #define CHUNKSIZE      300
                    413: 
                    414: struct chunk {
                    415:        int     c_nlines;       /* Number of lines in this chunk (so they
                    416:                                   don't all have to be CHUNKSIZE long). */
                    417:        Line    *c_block;       /* Chunk of memory */
                    418:        struct chunk    *c_nextfree;    /* Next chunk of lines */
                    419: };
                    420: 
                    421: static struct chunk    *fchunk = 0;
                    422: static Line    *ffline = 0;    /* First free line */
                    423: 
                    424: freeline(line)
                    425: register Line  *line;
                    426: {
                    427:        line->l_dline = 0;
                    428:        line->l_next = ffline;
                    429:        if (ffline)
                    430:                ffline->l_prev = line;
                    431:        line->l_prev = 0;
                    432:        ffline = line;
                    433: }
                    434: 
                    435: lfreelist(first)
                    436: register Line  *first;
                    437: {
                    438:        if (first)
                    439:                lfreereg(first, lastline(first));
                    440: }
                    441: 
                    442: /* Append region from line1 to line2 onto the free list of lines */
                    443: 
                    444: lfreereg(line1, line2)
                    445: register Line  *line1,
                    446:                *line2;
                    447: {
                    448:        register Line   *next,
                    449:                        *last = line2->l_next;
                    450: 
                    451:        while (line1 != last) {
                    452:                next = line1->l_next;
                    453:                freeline(line1);
                    454:                line1 = next;
                    455:        }
                    456: }
                    457: 
                    458: static
                    459: newchunk()
                    460: {
                    461:        register Line   *newline;
                    462:        register int    i;
                    463:        struct chunk    *f;
                    464:        int     nlines = CHUNKSIZE;
                    465: 
                    466:        f = (struct chunk *) emalloc(sizeof (struct chunk));
                    467:        if (f == 0)
                    468:                return 0;
                    469: 
                    470:        if ((f->c_block = (Line *) malloc((unsigned) (sizeof (Line) * nlines))) == 0) {
                    471:                while (nlines > 0) {
                    472:                        f->c_block = (Line *) malloc((unsigned) (sizeof (Line) * nlines));
                    473:                        if (f->c_block != 0)
                    474:                                break;
                    475:                        nlines /= 2;
                    476:                }
                    477:        }
                    478: 
                    479:        if (nlines <= 0)
                    480:                return 0;
                    481: 
                    482:        f->c_nlines = nlines;
                    483:        for (i = 0, newline = f->c_block; i < nlines; newline++, i++)
                    484:                freeline(newline);
                    485:        f->c_nextfree = fchunk;
                    486:        fchunk = f;
                    487:        return 1;
                    488: }
                    489: 
                    490: /* New BUFfer LINE */
                    491: 
                    492: Line *
                    493: nbufline()
                    494: {
                    495:        register Line   *newline;
                    496: 
                    497:        if (ffline == 0)        /* No free list */
                    498:                if (newchunk() == 0)
                    499:                        complain("[Out of lines] ");
                    500:        newline = ffline;
                    501:        ffline = ffline->l_next;
                    502:        if (ffline)
                    503:                ffline->l_prev = 0;
                    504:        return newline;
                    505: }
                    506: 
                    507: /* Remove the free lines, in chunk c, from the free list because they are
                    508:    no longer free. */
                    509: 
                    510: static
                    511: remfreelines(c)
                    512: register struct chunk  *c;
                    513: {
                    514:        register Line   *lp;
                    515:        register int    i;
                    516: 
                    517:        for (lp = c->c_block, i = 0; i < c->c_nlines; i++, lp++) {
                    518:                if (lp->l_prev)
                    519:                        lp->l_prev->l_next = lp->l_next;
                    520:                else
                    521:                        ffline = lp->l_next;
                    522:                if (lp->l_next)
                    523:                        lp->l_next->l_prev = lp->l_prev;
                    524:        }
                    525: }
                    526: 
                    527: /* This is used to garbage collect the chunks of lines when malloc fails
                    528:    and we are NOT looking for a new buffer line.  This goes through each
                    529:    chunk, and if every line in a given chunk is not allocated, the entire
                    530:    chunk is `free'd by "free()". */
                    531: 
                    532: GCchunks()
                    533: {
                    534:        register struct chunk   *cp;
                    535:        struct chunk    *prev = 0,
                    536:                        *next = 0;
                    537:        register int    i;
                    538:        register Line   *newline;
                    539: 
                    540:        for (cp = fchunk; cp != 0; cp = next) {
                    541:                for (i = 0, newline = cp->c_block; i < cp->c_nlines; newline++, i++)
                    542:                        if (newline->l_dline != 0)
                    543:                                break;
                    544: 
                    545:                next = cp->c_nextfree;
                    546: 
                    547:                if (i == cp->c_nlines) {                /* Unlink it!!! */
                    548:                        if (prev)
                    549:                                prev->c_nextfree = cp->c_nextfree;
                    550:                        else
                    551:                                fchunk = cp->c_nextfree;
                    552:                        remfreelines(cp);
                    553:                        free((char *) cp->c_block);
                    554:                        free((char *) cp);
                    555:                } else
                    556:                        prev = cp;
                    557:        }
                    558: }
                    559: 
                    560: #ifdef LISP
                    561: 
                    562: /* Grind S-Expr */
                    563: 
                    564: GSexpr()
                    565: {
                    566:        Bufpos  dot,
                    567:                end;
                    568: 
                    569:        if (linebuf[curchar] != '(')
                    570:                complain((char *) 0);
                    571:        DOTsave(&dot);
                    572:        FSexpr();
                    573:        DOTsave(&end);
                    574:        exp = 1;
                    575:        SetDot(&dot);
                    576:        for (;;) {
                    577:                if (curline == end.p_line)
                    578:                        break;
                    579:                line_move(FORWARD, NO);
                    580:                if (!blnkp(linebuf)) {
                    581:                        DelWtSpace();
                    582:                        (void) lisp_indent();
                    583:                }
                    584:        }
                    585:        SetDot(&dot);
                    586: }
                    587: 
                    588: /* lisp_indent() indents a new line in Lisp Mode, according to where
                    589:    the matching close-paren would go if we typed that (sort of). */
                    590: 
                    591: Bufpos *
                    592: lisp_indent()
                    593: {
                    594:        Bufpos  *bp,
                    595:                savedot;
                    596:        int     goal;
                    597: 
                    598:        bp = m_paren(')', BACKWARD, NO, YES);
                    599: 
                    600:        if (bp == 0)
                    601:                return 0;
                    602: 
                    603:        /*
                    604:         * Otherwise, we indent to the first argument of
                    605:         * the current s-expression.  This is done by
                    606:         * starting at the matching paren, skipping
                    607:         * to a word (atom), skipping over it, and
                    608:         * skipping to the next one.
                    609:         *
                    610:         * We want to end up
                    611:         *
                    612:         *      (atom atom atom ...
                    613:         *            ^ here.
                    614:         */
                    615: 
                    616:        DOTsave(&savedot);
                    617:        SetDot(bp);
                    618:        DoTimes(ForChar(), 1);
                    619:        if (linebuf[curchar] != '(') {
                    620:                static char     *specials[] = {
                    621:                        "def",
                    622:                        "let",
                    623:                        "lambda",
                    624:                        "fluid-let",
                    625:                        "macro",
                    626:                        "lexpr",
                    627:                        "nlambda",
                    628:                        "dolist",
                    629:                        "caseq",
                    630:                        "selectq",
                    631:                        "while",
                    632:                        "prog",
                    633:                        0
                    634:                };
                    635:                int     i = 0;
                    636: 
                    637:                while (specials[i]) {
                    638:                        char    *cp1 = specials[i],
                    639:                                *cp2 = &linebuf[curchar];
                    640:                        int     n = strlen(cp1);
                    641: 
                    642:                        while (--n >= 0)
                    643:                                if (Upper(*cp1++) != Upper(*cp2++))
                    644:                                        break;
                    645:                        if (n < 0)
                    646:                                break;  /* Matched. */
                    647:                        i++;
                    648:                }
                    649:                if (specials[i] == 0) {
                    650:                        if (index(&linebuf[curchar], ' ') != 0) {
                    651:                            WITH_TABLE(curbuf->b_major)
                    652:                                ForWord();
                    653:                            END_TABLE();
                    654:                                while (linebuf[curchar] == ' ')
                    655:                                        curchar++;
                    656:                        }
                    657:                } else
                    658:                        curchar++;
                    659:        }
                    660:        goal = calc_pos(linebuf, curchar);
                    661:        SetDot(&savedot);
                    662:        n_indent(goal);
                    663: 
                    664:        return bp;
                    665: }
                    666: #endif LISP

unix.superglobalmegacorp.com

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