[BACK]Return to misccmds.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / vim

Annotation of src/usr.bin/vim/misccmds.c, Revision 1.3

1.3     ! downsj      1: /* $OpenBSD: misccmds.c,v 1.2 1996/09/21 06:23:10 downsj Exp $ */
1.1       downsj      2: /* vi:set ts=4 sw=4:
                      3:  *
                      4:  * VIM - Vi IMproved       by Bram Moolenaar
                      5:  *
                      6:  * Do ":help uganda"  in Vim to read copying and usage conditions.
                      7:  * Do ":help credits" in Vim to see a list of people who contributed.
                      8:  */
                      9:
                     10: /*
                     11:  * misccmds.c: functions that didn't seem to fit elsewhere
                     12:  */
                     13:
                     14: #include "vim.h"
                     15: #include "globals.h"
                     16: #include "proto.h"
                     17: #include "option.h"
                     18: #ifdef HAVE_FCNTL_H
                     19: # include <fcntl.h>            /* for chdir() */
                     20: #endif
                     21:
                     22: static int get_indent_str __ARGS((char_u *ptr));
                     23: static void check_status __ARGS((BUF *));
                     24:
                     25: /*
                     26:  * count the size of the indent in the current line
                     27:  */
                     28:    int
                     29: get_indent()
                     30: {
                     31:    return get_indent_str(ml_get_curline());
                     32: }
                     33:
                     34: /*
                     35:  * count the size of the indent in line "lnum"
                     36:  */
                     37:    int
                     38: get_indent_lnum(lnum)
                     39:    linenr_t    lnum;
                     40: {
                     41:    return get_indent_str(ml_get(lnum));
                     42: }
                     43:
                     44: /*
                     45:  * count the size of the indent in line "ptr"
                     46:  */
                     47:    static int
                     48: get_indent_str(ptr)
                     49:    register char_u *ptr;
                     50: {
                     51:    register int count = 0;
                     52:
                     53:    for ( ; *ptr; ++ptr)
                     54:    {
                     55:        if (*ptr == TAB)    /* count a tab for what it is worth */
                     56:            count += (int)curbuf->b_p_ts - (count % (int)curbuf->b_p_ts);
                     57:        else if (*ptr == ' ')
                     58:            ++count;            /* count a space for one */
                     59:        else
                     60:            break;
                     61:    }
                     62:    return (count);
                     63: }
                     64:
                     65: /*
                     66:  * set the indent of the current line
                     67:  * leaves the cursor on the first non-blank in the line
                     68:  */
                     69:    void
                     70: set_indent(size, del_first)
                     71:    register int    size;
                     72:    int             del_first;
                     73: {
                     74:    int             oldstate = State;
                     75:    register int    c;
                     76:
                     77:    State = INSERT;                 /* don't want REPLACE for State */
                     78:    curwin->w_cursor.col = 0;
                     79:    if (del_first)                  /* delete old indent */
                     80:    {
                     81:                                    /* vim_iswhite() is a define! */
                     82:        while ((c = gchar_cursor()), vim_iswhite(c))
                     83:            (void)delchar(FALSE);
                     84:    }
                     85:    if (!curbuf->b_p_et)            /* if 'expandtab' is set, don't use TABs */
                     86:        while (size >= (int)curbuf->b_p_ts)
                     87:        {
                     88:            ins_char(TAB);
                     89:            size -= (int)curbuf->b_p_ts;
                     90:        }
                     91:    while (size)
                     92:    {
                     93:        ins_char(' ');
                     94:        --size;
                     95:    }
                     96:    State = oldstate;
                     97: }
                     98:
                     99: #if defined(CINDENT) || defined(SMARTINDENT)
                    100:
                    101: static int is_cinword __ARGS((char_u *line));
                    102:
                    103: /*
                    104:  * Return TRUE if the string "line" starts with a word from 'cinwords'.
                    105:  */
                    106:    static int
                    107: is_cinword(line)
                    108:    char_u      *line;
                    109: {
                    110:    char_u  *cinw;
                    111:    char_u  *cinw_buf;
                    112:    int     cinw_len;
                    113:    int     retval = FALSE;
                    114:    int     len;
                    115:
                    116:    cinw_len = STRLEN(curbuf->b_p_cinw) + 1;
                    117:    cinw_buf = alloc((unsigned)cinw_len);
                    118:    if (cinw_buf != NULL)
                    119:    {
                    120:        line = skipwhite(line);
                    121:        for (cinw = curbuf->b_p_cinw; *cinw; )
                    122:        {
                    123:            len = copy_option_part(&cinw, cinw_buf, cinw_len, ",");
                    124:            if (STRNCMP(line, cinw_buf, len) == 0 &&
                    125:                       (!iswordchar(line[len]) || !iswordchar(line[len - 1])))
                    126:            {
                    127:                retval = TRUE;
                    128:                break;
                    129:            }
                    130:        }
                    131:        vim_free(cinw_buf);
                    132:    }
                    133:    return retval;
                    134: }
                    135: #endif
                    136:
                    137: /*
                    138:  * Opencmd
                    139:  *
                    140:  * Add a new line below or above the current line.
                    141:  * Caller must take care of undo.
                    142:  *
                    143:  * Return TRUE for success, FALSE for failure
                    144:  */
                    145:
                    146:    int
                    147: Opencmd(dir, redraw, del_spaces)
                    148:    int         dir;            /* FORWARD or BACKWARD */
                    149:    int         redraw;         /* redraw afterwards */
                    150:    int         del_spaces;     /* delete spaces after cursor */
                    151: {
                    152:    char_u  *saved_line;        /* copy of the original line */
                    153:    char_u  *p_extra = NULL;    /* what goes to next line */
                    154:    int     extra_len = 0;      /* length of p_extra string */
                    155:    FPOS    old_cursor;         /* old cursor position */
                    156:    int     newcol = 0;         /* new cursor column */
                    157:    int     newindent = 0;      /* auto-indent of the new line */
                    158:    int     n;
                    159:    int     trunc_line = FALSE; /* truncate current line afterwards */
                    160:    int     retval = FALSE;     /* return value, default is FAIL */
                    161:    int     lead_len;           /* length of comment leader */
                    162:    char_u  *lead_flags;        /* position in 'comments' for comment leader */
                    163:    char_u  *leader = NULL;     /* copy of comment leader */
                    164:    char_u  *allocated = NULL;  /* allocated memory */
                    165:    char_u  *p;
                    166:    int     saved_char = NUL;   /* init for GCC */
                    167:    FPOS    *pos;
                    168:    int     old_plines = 0;     /* init for GCC */
                    169:    int     new_plines = 0;     /* init for GCC */
                    170: #ifdef SMARTINDENT
                    171:    int     no_si = FALSE;      /* reset did_si afterwards */
                    172:    int     first_char = NUL;   /* init for GCC */
                    173: #endif
                    174:
                    175:    /*
                    176:     * make a copy of the current line so we can mess with it
                    177:     */
                    178:    saved_line = strsave(ml_get_curline());
                    179:    if (saved_line == NULL)         /* out of memory! */
                    180:        return FALSE;
                    181:
                    182:    if (State == INSERT || State == REPLACE)
                    183:    {
                    184:        p_extra = saved_line + curwin->w_cursor.col;
                    185: #ifdef SMARTINDENT
                    186:        if (curbuf->b_p_si)         /* need first char after new line break */
                    187:        {
                    188:            p = skipwhite(p_extra);
                    189:            first_char = *p;
                    190:        }
                    191: #endif
                    192:        extra_len = STRLEN(p_extra);
                    193:        saved_char = *p_extra;
                    194:        *p_extra = NUL;
                    195:    }
                    196:
                    197:    u_clearline();              /* cannot do "U" command when adding lines */
                    198: #ifdef SMARTINDENT
                    199:    did_si = FALSE;
                    200: #endif
                    201:
                    202:    /*
                    203:     * If 'autoindent' and/or 'smartindent' is set, try to figure out what
                    204:     * indent to use for the new line.
                    205:     */
                    206:    if (curbuf->b_p_ai
                    207: #ifdef SMARTINDENT
                    208:                        || curbuf->b_p_si
                    209: #endif
                    210:                                            )
                    211:    {
                    212:        /*
                    213:         * count white space on current line
                    214:         */
                    215:        newindent = get_indent();
                    216:        if (newindent == 0)
                    217:            newindent = old_indent;     /* for ^^D command in insert mode */
                    218:        old_indent = 0;
                    219:
                    220:        /*
                    221:         * If we just did an auto-indent, then we didn't type anything on
                    222:         * the prior line, and it should be truncated.
                    223:         */
                    224:        if (dir == FORWARD && did_ai)
                    225:            trunc_line = TRUE;
                    226:
                    227: #ifdef SMARTINDENT
                    228:        /*
                    229:         * Do smart indenting.
                    230:         * In insert/replace mode (only when dir == FORWARD)
                    231:         * we may move some text to the next line. If it starts with '{'
                    232:         * don't add an indent. Fixes inserting a NL before '{' in line
                    233:         *      "if (condition) {"
                    234:         */
                    235:        else if (curbuf->b_p_si && *saved_line != NUL &&
                    236:                                       (p_extra == NULL || first_char != '{'))
                    237:        {
                    238:            char_u  *ptr;
                    239:            char_u  last_char;
                    240:
                    241:            old_cursor = curwin->w_cursor;
                    242:            ptr = saved_line;
                    243:            lead_len = get_leader_len(ptr, NULL);
                    244:            if (dir == FORWARD)
                    245:            {
                    246:                /*
                    247:                 * Skip preprocessor directives, unless they are
                    248:                 * recognised as comments.
                    249:                 */
                    250:                if (lead_len == 0 && ptr[0] == '#')
                    251:                {
                    252:                    while (ptr[0] == '#' && curwin->w_cursor.lnum > 1)
                    253:                        ptr = ml_get(--curwin->w_cursor.lnum);
                    254:                    newindent = get_indent();
                    255:                }
                    256:                lead_len = get_leader_len(ptr, NULL);
                    257:                if (lead_len > 0)
                    258:                {
                    259:                    /*
                    260:                     * This case gets the following right:
                    261:                     *      \*
                    262:                     *       * A comment (read "\" as "/").
                    263:                     *       *\
                    264:                     * #define IN_THE_WAY
                    265:                     *      This should line up here;
                    266:                     */
                    267:                    p = skipwhite(ptr);
                    268:                    if (p[0] == '/' && p[1] == '*')
                    269:                        p++;
                    270:                    if (p[0] == '*')
                    271:                    {
                    272:                        for (p++; *p; p++)
                    273:                        {
                    274:                            if (p[0] == '/' && p[-1] == '*')
                    275:                            {
                    276:                                /*
                    277:                                 * End of C comment, indent should line up
                    278:                                 * with the line containing the start of
                    279:                                 * the comment
                    280:                                 */
                    281:                                curwin->w_cursor.col = p - ptr;
                    282:                                if ((pos = findmatch(NUL)) != NULL)
                    283:                                {
                    284:                                    curwin->w_cursor.lnum = pos->lnum;
                    285:                                    newindent = get_indent();
                    286:                                }
                    287:                            }
                    288:                        }
                    289:                    }
                    290:                }
                    291:                else    /* Not a comment line */
                    292:                {
                    293:                    /* Find last non-blank in line */
                    294:                    p = ptr + STRLEN(ptr) - 1;
                    295:                    while (p > ptr && vim_iswhite(*p))
                    296:                        --p;
                    297:                    last_char = *p;
                    298:
                    299:                    /*
                    300:                     * find the character just before the '{' or ';'
                    301:                     */
                    302:                    if (last_char == '{' || last_char == ';')
                    303:                    {
                    304:                        if (p > ptr)
                    305:                            --p;
                    306:                        while (p > ptr && vim_iswhite(*p))
                    307:                            --p;
                    308:                    }
                    309:                    /*
                    310:                     * Try to catch lines that are split over multiple
                    311:                     * lines.  eg:
                    312:                     *      if (condition &&
                    313:                     *                  condition) {
                    314:                     *          Should line up here!
                    315:                     *      }
                    316:                     */
                    317:                    if (*p == ')')
                    318:                    {
                    319:                        curwin->w_cursor.col = p - ptr;
                    320:                        if ((pos = findmatch('(')) != NULL)
                    321:                        {
                    322:                            curwin->w_cursor.lnum = pos->lnum;
                    323:                            newindent = get_indent();
                    324:                            ptr = ml_get_curline();
                    325:                        }
                    326:                    }
                    327:                    /*
                    328:                     * If last character is '{' do indent, without
                    329:                     * checking for "if" and the like.
                    330:                     */
                    331:                    if (last_char == '{')
                    332:                    {
                    333:                        did_si = TRUE;  /* do indent */
                    334:                        no_si = TRUE;   /* don't delete it when '{' typed */
                    335:                    }
                    336:                    /*
                    337:                     * Look for "if" and the like, use 'cinwords'.
                    338:                     * Don't do this if the previous line ended in ';' or
                    339:                     * '}'.
                    340:                     */
                    341:                    else if (last_char != ';' && last_char != '}' &&
                    342:                                                            is_cinword(ptr))
                    343:                        did_si = TRUE;
                    344:                }
                    345:            }
                    346:            else /* dir == BACKWARD */
                    347:            {
                    348:                /*
                    349:                 * Skip preprocessor directives, unless they are
                    350:                 * recognised as comments.
                    351:                 */
                    352:                if (lead_len == 0 && ptr[0] == '#')
                    353:                {
                    354:                    int was_backslashed = FALSE;
                    355:
                    356:                    while ((ptr[0] == '#' || was_backslashed) &&
                    357:                         curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count)
                    358:                    {
                    359:                        if (*ptr && ptr[STRLEN(ptr) - 1] == '\\')
                    360:                            was_backslashed = TRUE;
                    361:                        else
                    362:                            was_backslashed = FALSE;
                    363:                        ptr = ml_get(++curwin->w_cursor.lnum);
                    364:                    }
                    365:                    if (was_backslashed)
                    366:                        newindent = 0;      /* Got to end of file */
                    367:                    else
                    368:                        newindent = get_indent();
                    369:                }
                    370:                p = skipwhite(ptr);
                    371:                if (*p == '}')      /* if line starts with '}': do indent */
                    372:                    did_si = TRUE;
                    373:                else                /* can delete indent when '{' typed */
                    374:                    can_si_back = TRUE;
                    375:            }
                    376:            curwin->w_cursor = old_cursor;
                    377:        }
                    378:        if (curbuf->b_p_si)
                    379:            can_si = TRUE;
                    380: #endif /* SMARTINDENT */
                    381:
                    382:        did_ai = TRUE;
                    383:    }
                    384:
                    385:    /*
                    386:     * Find out if the current line starts with a comment leader.
                    387:     * This may then be inserted in front of the new line.
                    388:     */
                    389:    lead_len = get_leader_len(saved_line, &lead_flags);
                    390:    if (lead_len > 0)
                    391:    {
                    392:        char_u  *lead_repl = NULL;          /* replaces comment leader */
                    393:        int     lead_repl_len = 0;          /* length of *lead_repl */
                    394:        char_u  lead_middle[COM_MAX_LEN];   /* middle-comment string */
                    395:        char_u  lead_end[COM_MAX_LEN];      /* end-comment string */
                    396:        char_u  *comment_end = NULL;        /* where lead_end has been found */
                    397:        int     extra_space = FALSE;        /* append extra space */
                    398:        int     current_flag;
                    399:
                    400:        /*
                    401:         * If the comment leader has the start, middle or end flag, it may not
                    402:         * be used or may be replaced with the middle leader.
                    403:         */
                    404:        for (p = lead_flags; *p && *p != ':'; ++p)
                    405:        {
                    406:            if (*p == COM_START || *p == COM_MIDDLE)
                    407:            {
                    408:                current_flag = *p;
                    409:                if (*p == COM_START)
                    410:                {
                    411:                    /*
                    412:                     * Doing "O" on a start of comment does not insert leader.
                    413:                     */
                    414:                    if (dir == BACKWARD)
                    415:                    {
                    416:                        lead_len = 0;
                    417:                        break;
                    418:                    }
                    419:
                    420:                   /* find start of middle part */
                    421:                    (void)copy_option_part(&p, lead_middle, COM_MAX_LEN, ",");
                    422:                }
                    423:
                    424:                /*
                    425:                 * Isolate the strings of the middle and end leader.
                    426:                 */
                    427:                while (*p && p[-1] != ':')      /* find end of middle flags */
                    428:                    ++p;
                    429:                (void)copy_option_part(&p, lead_middle, COM_MAX_LEN, ",");
                    430:                while (*p && p[-1] != ':')      /* find end of end flags */
                    431:                    ++p;
                    432:                (void)copy_option_part(&p, lead_end, COM_MAX_LEN, ",");
                    433:
                    434:                /*
                    435:                 * If the end of the comment is in the same line, don't use
                    436:                 * the comment leader.
                    437:                 */
                    438:                if (dir == FORWARD)
                    439:                {
                    440:                    n = STRLEN(lead_end);
                    441:                    for (p = saved_line + lead_len; *p; ++p)
                    442:                        if (STRNCMP(p, lead_end, n) == 0)
                    443:                        {
                    444:                            comment_end = p;
                    445:                            lead_len = 0;
                    446:                            break;
                    447:                        }
                    448:                }
                    449:
                    450:                /*
                    451:                 * Doing "o" on a start of comment inserts the middle leader.
                    452:                 */
                    453:                if (lead_len)
                    454:                {
                    455:                    if (current_flag == COM_START)
                    456:                    {
                    457:                        lead_repl = lead_middle;
                    458:                        lead_repl_len = STRLEN(lead_middle);
                    459:                    }
                    460:
                    461:                    /*
                    462:                     * If we have hit RETURN immediately after the start
                    463:                     * comment leader, then put a space after the middle
                    464:                     * comment leader on the next line.
                    465:                     */
                    466:                    if (!vim_iswhite(saved_line[lead_len - 1]) &&
                    467:                            ((p_extra != NULL &&
                    468:                                     (int)curwin->w_cursor.col == lead_len) ||
                    469:                             (p_extra == NULL && saved_line[lead_len] == NUL)))
                    470:                        extra_space = TRUE;
                    471:                }
                    472:                break;
                    473:            }
                    474:            if (*p == COM_END)
                    475:            {
                    476:                /*
                    477:                 * Doing "o" on the end of a comment does not insert leader.
                    478:                 * Remember where the end is, might want to use it to find the
                    479:                 * start (for C-comments).
                    480:                 */
                    481:                if (dir == FORWARD)
                    482:                {
                    483:                    comment_end = skipwhite(saved_line);
                    484:                    lead_len = 0;
                    485:                    break;
                    486:                }
                    487:
                    488:                /*
                    489:                 * Doing "O" on the end of a comment inserts the middle leader.
                    490:                 * Find the string for the middle leader, searching backwards.
                    491:                 */
                    492:                while (p > curbuf->b_p_com && *p != ',')
                    493:                    --p;
                    494:                for (lead_repl = p; lead_repl > curbuf->b_p_com &&
                    495:                                            lead_repl[-1] != ':'; --lead_repl)
                    496:                    ;
                    497:                lead_repl_len = p - lead_repl;
                    498:                break;
                    499:            }
                    500:            if (*p == COM_FIRST)
                    501:            {
                    502:                /*
                    503:                 * Comment leader for first line only:  Don't repeat leader
                    504:                 * when using "O", blank out leader when using "o".
                    505:                 */
                    506:                if (dir == BACKWARD)
                    507:                    lead_len = 0;
                    508:                else
                    509:                {
                    510:                    lead_repl = (char_u *)"";
                    511:                    lead_repl_len = 0;
                    512:                }
                    513:                break;
                    514:            }
                    515:        }
                    516:        if (lead_len)
                    517:        {
                    518:            /* allocate buffer (may concatenate p_exta later) */
                    519:            leader = alloc(lead_len + lead_repl_len + extra_space +
                    520:                                                              extra_len + 1);
                    521:            allocated = leader;             /* remember to free it later */
                    522:
                    523:            if (leader == NULL)
                    524:                lead_len = 0;
                    525:            else
                    526:            {
                    527:                STRNCPY(leader, saved_line, lead_len);
                    528:                leader[lead_len] = NUL;
                    529:
                    530:                /*
                    531:                 * Replace leader with lead_repl, right or left adjusted
                    532:                 */
                    533:                if (lead_repl != NULL)
                    534:                {
                    535:                    for (p = lead_flags; *p && *p != ':'; ++p)
                    536:                        if (*p == COM_RIGHT || *p == COM_LEFT)
                    537:                            break;
                    538:                    if (*p == COM_RIGHT)    /* right adjusted leader */
                    539:                    {
                    540:                        /* find last non-white in the leader to line up with */
                    541:                        for (p = leader + lead_len - 1; p > leader &&
                    542:                                                         vim_iswhite(*p); --p)
                    543:                            ;
                    544:
                    545:                        ++p;
                    546:                        if (p < leader + lead_repl_len)
                    547:                            p = leader;
                    548:                        else
                    549:                            p -= lead_repl_len;
                    550:                        vim_memmove(p, lead_repl, (size_t)lead_repl_len);
                    551:                        if (p + lead_repl_len > leader + lead_len)
                    552:                            p[lead_repl_len] = NUL;
                    553:
                    554:                        /* blank-out any other chars from the old leader. */
                    555:                        while (--p >= leader)
                    556:                            if (!vim_iswhite(*p))
                    557:                                *p = ' ';
                    558:                    }
                    559:                    else                    /* left adjusted leader */
                    560:                    {
                    561:                        p = skipwhite(leader);
                    562:                        vim_memmove(p, lead_repl, (size_t)lead_repl_len);
                    563:
                    564:                        /* blank-out any other chars from the old leader. */
                    565:                        for (p += lead_repl_len; p < leader + lead_len; ++p)
                    566:                            if (!vim_iswhite(*p))
                    567:                                *p = ' ';
                    568:                        *p = NUL;
                    569:                    }
                    570:
                    571:                    /* Recompute the indent, it may have changed. */
                    572:                    if (curbuf->b_p_ai
                    573: #ifdef SMARTINDENT
                    574:                                        || curbuf->b_p_si
                    575: #endif
                    576:                                                           )
                    577:                        newindent = get_indent_str(leader);
                    578:                }
                    579:
                    580:                lead_len = STRLEN(leader);
                    581:                if (extra_space)
                    582:                {
                    583:                    leader[lead_len++] = ' ';
                    584:                    leader[lead_len] = NUL;
                    585:                }
                    586:
                    587:                newcol = lead_len;
                    588:
                    589:                /*
                    590:                 * if a new indent will be set below, remove the indent that
                    591:                 * is in the comment leader
                    592:                 */
                    593:                if (newindent
                    594: #ifdef SMARTINDENT
                    595:                                || did_si
                    596: #endif
                    597:                                           )
                    598:                {
                    599:                    while (lead_len && vim_iswhite(*leader))
                    600:                    {
                    601:                        --lead_len;
                    602:                        --newcol;
                    603:                        ++leader;
                    604:                    }
                    605:                }
                    606:
                    607:            }
                    608: #ifdef SMARTINDENT
                    609:            did_si = can_si = FALSE;
                    610: #endif
                    611:        }
                    612:        else if (comment_end != NULL)
                    613:        {
                    614:            /*
                    615:             * We have finished a comment, so we don't use the leader.
                    616:             * If this was a C-comment and 'ai' or 'si' is set do a normal
                    617:             * indent to align with the line containing the start of the
                    618:             * comment.
                    619:             */
                    620:            if (comment_end[0] == '*' && comment_end[1] == '/' &&
                    621:                        (curbuf->b_p_ai
                    622: #ifdef SMARTINDENT
                    623:                                        || curbuf->b_p_si
                    624: #endif
                    625:                                                           ))
                    626:            {
                    627:                old_cursor = curwin->w_cursor;
                    628:                curwin->w_cursor.col = comment_end - saved_line;
                    629:                if ((pos = findmatch(NUL)) != NULL)
                    630:                {
                    631:                    curwin->w_cursor.lnum = pos->lnum;
                    632:                    newindent = get_indent();
                    633:                }
                    634:                curwin->w_cursor = old_cursor;
                    635:            }
                    636:        }
                    637:    }
                    638:
                    639:    /* (State == INSERT || State == REPLACE), only when dir == FORWARD */
                    640:    if (p_extra != NULL)
                    641:    {
                    642:        *p_extra = saved_char;          /* restore char that NUL replaced */
                    643:
                    644:        /*
                    645:         * When 'ai' set or "del_spaces" TRUE, skip to the first non-blank.
                    646:         *
                    647:         * When in REPLACE mode, put the deleted blanks on the replace
                    648:         * stack, followed by a NUL, so they can be put back when
                    649:         * a BS is entered.
                    650:         */
                    651:        if (State == REPLACE)
                    652:            replace_push(NUL);      /* end of extra blanks */
                    653:        if (curbuf->b_p_ai || del_spaces)
                    654:        {
                    655:            while (*p_extra == ' ' || *p_extra == '\t')
                    656:            {
                    657:                if (State == REPLACE)
                    658:                    replace_push(*p_extra);
                    659:                ++p_extra;
                    660:            }
                    661:        }
                    662:        if (*p_extra != NUL)
                    663:            did_ai = FALSE;         /* append some text, don't trucate now */
                    664:    }
                    665:
                    666:    if (p_extra == NULL)
                    667:        p_extra = (char_u *)"";             /* append empty line */
                    668:
                    669:    /* concatenate leader and p_extra, if there is a leader */
                    670:    if (lead_len)
                    671:    {
                    672:        STRCAT(leader, p_extra);
                    673:        p_extra = leader;
                    674:    }
                    675:
                    676:    old_cursor = curwin->w_cursor;
                    677:    if (dir == BACKWARD)
                    678:        --curwin->w_cursor.lnum;
                    679:    if (ml_append(curwin->w_cursor.lnum, p_extra, (colnr_t)0, FALSE) == FAIL)
                    680:        goto theend;
                    681:    mark_adjust(curwin->w_cursor.lnum + 1, MAXLNUM, 1L, 0L);
                    682:    if (newindent
                    683: #ifdef SMARTINDENT
                    684:                    || did_si
                    685: #endif
                    686:                                )
                    687:    {
                    688:        ++curwin->w_cursor.lnum;
                    689: #ifdef SMARTINDENT
                    690:        if (did_si)
                    691:        {
                    692:            if (p_sr)
                    693:                newindent -= newindent % (int)curbuf->b_p_sw;
                    694:            newindent += (int)curbuf->b_p_sw;
                    695:        }
                    696: #endif
                    697:        set_indent(newindent, FALSE);
                    698:        /*
                    699:         * In REPLACE mode the new indent must be put on
                    700:         * the replace stack for when it is deleted with BS
                    701:         */
                    702:        if (State == REPLACE)
                    703:            for (n = 0; n < (int)curwin->w_cursor.col; ++n)
                    704:                replace_push(NUL);
                    705:        newcol += curwin->w_cursor.col;
                    706: #ifdef SMARTINDENT
                    707:        if (no_si)
                    708:            did_si = FALSE;
                    709: #endif
                    710:    }
                    711:    /*
                    712:     * In REPLACE mode the extra leader must be put on the replace stack for
                    713:     * when it is deleted with BS.
                    714:     */
                    715:    if (State == REPLACE)
                    716:        while (lead_len-- > 0)
                    717:            replace_push(NUL);
                    718:
                    719:    curwin->w_cursor = old_cursor;
                    720:
                    721:    if (dir == FORWARD)
                    722:    {
                    723:        if (redraw)     /* want to know the old number of screen lines */
                    724:        {
                    725:            old_plines = plines(curwin->w_cursor.lnum);
                    726:            new_plines = old_plines;
                    727:        }
                    728:        if (trunc_line || State == INSERT || State == REPLACE)
                    729:        {
                    730:            if (trunc_line)
                    731:            {
                    732:                    /* find start of trailing white space */
                    733:                for (n = STRLEN(saved_line); n > 0 &&
                    734:                                          vim_iswhite(saved_line[n - 1]); --n)
                    735:                    ;
                    736:                saved_line[n] = NUL;
                    737:            }
                    738:            else                    /* truncate current line at cursor */
                    739:                *(saved_line + curwin->w_cursor.col) = NUL;
                    740:            ml_replace(curwin->w_cursor.lnum, saved_line, FALSE);
                    741:            saved_line = NULL;
                    742:            new_plines = plines(curwin->w_cursor.lnum);
                    743:        }
                    744:
                    745:        /*
                    746:         * Get the cursor to the start of the line, so that 'curwin->w_row'
                    747:         * gets set to the right physical line number for the stuff that
                    748:         * follows...
                    749:         */
                    750:        curwin->w_cursor.col = 0;
                    751:
                    752:        if (redraw)
                    753:        {
                    754:            /*
                    755:             * Call cursupdate() to compute w_row.
                    756:             * But we don't want it to update the srceen.
                    757:             */
                    758:            ++RedrawingDisabled;
                    759:            cursupdate();
                    760:            --RedrawingDisabled;
                    761:
                    762:            /*
                    763:             * If we're doing an open on the last logical line, then go ahead
                    764:             * and scroll the screen up. Otherwise, just insert a blank line
                    765:             * at the right place if the number of screen lines changed.
                    766:             * We use calls to plines() in case the cursor is resting on a
                    767:             * long line, we want to know the row below the line.
                    768:             */
                    769:            n = curwin->w_row + new_plines;
                    770:            if (n == curwin->w_winpos + curwin->w_height)
                    771:                scrollup(1L);
                    772:            else
                    773:                win_ins_lines(curwin, n,
                    774:                  plines(curwin->w_cursor.lnum + 1) + new_plines - old_plines,
                    775:                                                                  TRUE, TRUE);
                    776:        }
                    777:
                    778:        /*
                    779:         * Put the cursor on the new line.  Careful: the cursupdate() and
                    780:         * scrollup() above may have moved w_cursor, we must use old_cursor.
                    781:         */
                    782:        curwin->w_cursor.lnum = old_cursor.lnum + 1;
                    783:    }
                    784:    else if (redraw)            /* insert physical line above current line */
                    785:        win_ins_lines(curwin, curwin->w_row, 1, TRUE, TRUE);
                    786:
                    787:    curwin->w_cursor.col = newcol;
                    788:
                    789: #ifdef LISPINDENT
                    790:    /*
                    791:     * May do lisp indenting.
                    792:     */
                    793:    if (leader == NULL && curbuf->b_p_lisp && curbuf->b_p_ai)
                    794:        fixthisline(get_lisp_indent);
                    795: #endif
                    796: #ifdef CINDENT
                    797:    /*
                    798:     * May do indenting after opening a new line.
                    799:     */
                    800:    if (leader == NULL && curbuf->b_p_cin &&
                    801:            in_cinkeys(dir == FORWARD ? KEY_OPEN_FORW :
                    802:                        KEY_OPEN_BACK, ' ', linewhite(curwin->w_cursor.lnum)))
                    803:        fixthisline(get_c_indent);
                    804: #endif
                    805:
                    806:    if (redraw)
                    807:    {
                    808:        updateScreen(VALID_TO_CURSCHAR);
                    809:        cursupdate();           /* update curwin->w_row */
                    810:    }
                    811:    CHANGED;
                    812:
                    813:    retval = TRUE;              /* success! */
                    814: theend:
                    815:    vim_free(saved_line);
                    816:    vim_free(allocated);
                    817:    return retval;
                    818: }
                    819:
                    820: /*
                    821:  * get_leader_len() returns the length of the prefix of the given string
                    822:  * which introduces a comment.  If this string is not a comment then 0 is
                    823:  * returned.
                    824:  * When "flags" is non-zero, it is set to point to the flags of the recognized
                    825:  * comment leader.
                    826:  */
                    827:    int
                    828: get_leader_len(line, flags)
                    829:    char_u  *line;
                    830:    char_u  **flags;
                    831: {
                    832:    int     i, j;
                    833:    int     got_com = FALSE;
                    834:    int     found_one;
                    835:    char_u  part_buf[COM_MAX_LEN];  /* buffer for one option part */
                    836:    char_u  *string;                /* pointer to comment string */
                    837:    char_u  *list;
                    838:
                    839:    if (!fo_do_comments)            /* don't format comments at all */
                    840:        return 0;
                    841:
                    842:    i = 0;
                    843:    while (vim_iswhite(line[i]))    /* leading white space is ignored */
                    844:        ++i;
                    845:
                    846:    /*
                    847:     * Repeat to match several nested comment strings.
                    848:     */
                    849:    while (line[i])
                    850:    {
                    851:        /*
                    852:         * scan through the 'comments' option for a match
                    853:         */
                    854:        found_one = FALSE;
                    855:        for (list = curbuf->b_p_com; *list; )
                    856:        {
                    857:            /*
                    858:             * Get one option part into part_buf[].  Advance list to next one.
                    859:             * put string at start of string.
                    860:             */
                    861:            if (!got_com && flags != NULL)  /* remember where flags started */
                    862:                *flags = list;
                    863:            (void)copy_option_part(&list, part_buf, COM_MAX_LEN, ",");
                    864:            string = vim_strchr(part_buf, ':');
                    865:            if (string == NULL)     /* missing ':', ignore this part */
                    866:                continue;
                    867:            *string++ = NUL;        /* isolate flags from string */
                    868:
                    869:            /*
                    870:             * When already found a nested comment, only accept further
                    871:             * nested comments.
                    872:             */
                    873:            if (got_com && vim_strchr(part_buf, COM_NEST) == NULL)
                    874:                continue;
                    875:
                    876:            /*
                    877:             * Line contents and string must match.
                    878:             */
                    879:            for (j = 0; string[j] != NUL && string[j] == line[i + j]; ++j)
                    880:                ;
                    881:            if (string[j] != NUL)
                    882:                continue;
                    883:
                    884:            /*
                    885:             * When 'b' flag used, there must be white space or an
                    886:             * end-of-line after the string in the line.
                    887:             */
                    888:            if (vim_strchr(part_buf, COM_BLANK) != NULL &&
                    889:                              !vim_iswhite(line[i + j]) && line[i + j] != NUL)
                    890:                continue;
                    891:
                    892:            /*
                    893:             * We have found a match, stop searching.
                    894:             */
                    895:            i += j;
                    896:            got_com = TRUE;
                    897:            found_one = TRUE;
                    898:            break;
                    899:        }
                    900:
                    901:        /*
                    902:         * No match found, stop scanning.
                    903:         */
                    904:        if (!found_one)
                    905:            break;
                    906:
                    907:        /*
                    908:         * Include any trailing white space.
                    909:         */
                    910:        while (vim_iswhite(line[i]))
                    911:            ++i;
                    912:
                    913:        /*
                    914:         * If this comment doesn't nest, stop here.
                    915:         */
                    916:        if (vim_strchr(part_buf, COM_NEST) == NULL)
                    917:            break;
                    918:    }
                    919:    return (got_com ? i : 0);
                    920: }
                    921:
                    922: /*
                    923:  * plines(p) - return the number of physical screen lines taken by line 'p'
                    924:  */
                    925:    int
                    926: plines(p)
                    927:    linenr_t    p;
                    928: {
                    929:    return plines_win(curwin, p);
                    930: }
                    931:
                    932:    int
                    933: plines_win(wp, p)
                    934:    WIN         *wp;
                    935:    linenr_t    p;
                    936: {
                    937:    register long       col;
                    938:    register char_u     *s;
                    939:    register int        lines;
                    940:
                    941:    if (!wp->w_p_wrap)
                    942:        return 1;
                    943:
                    944:    s = ml_get_buf(wp->w_buffer, p, FALSE);
                    945:    if (*s == NUL)              /* empty line */
                    946:        return 1;
                    947:
                    948:    col = linetabsize(s);
                    949:
                    950:    /*
                    951:     * If list mode is on, then the '$' at the end of the line takes up one
                    952:     * extra column.
                    953:     */
                    954:    if (wp->w_p_list)
                    955:        col += 1;
                    956:
                    957:    /*
                    958:     * If 'number' mode is on, add another 8.
                    959:     */
                    960:    if (wp->w_p_nu)
                    961:        col += 8;
                    962:
                    963:    lines = (col + (Columns - 1)) / Columns;
                    964:    if (lines <= wp->w_height)
                    965:        return lines;
                    966:    return (int)(wp->w_height);     /* maximum length */
                    967: }
                    968:
                    969: /*
                    970:  * Count the physical lines (rows) for the lines "first" to "last" inclusive.
                    971:  */
                    972:    int
                    973: plines_m(first, last)
                    974:    linenr_t        first, last;
                    975: {
                    976:    return plines_m_win(curwin, first, last);
                    977: }
                    978:
                    979:    int
                    980: plines_m_win(wp, first, last)
                    981:    WIN             *wp;
                    982:    linenr_t        first, last;
                    983: {
                    984:    int count = 0;
                    985:
                    986:    while (first <= last)
                    987:        count += plines_win(wp, first++);
                    988:    return (count);
                    989: }
                    990:
                    991: /*
                    992:  * Insert or replace a single character at the cursor position.
                    993:  * When in REPLACE mode, replace any existing character.
                    994:  */
                    995:    void
                    996: ins_char(c)
                    997:    int         c;
                    998: {
                    999:    register char_u  *p;
                   1000:    char_u          *newp;
                   1001:    char_u          *oldp;
                   1002:    int             oldlen;
                   1003:    int             extra;
                   1004:    colnr_t         col = curwin->w_cursor.col;
                   1005:    linenr_t        lnum = curwin->w_cursor.lnum;
                   1006:
                   1007:    oldp = ml_get(lnum);
                   1008:    oldlen = STRLEN(oldp) + 1;
                   1009:
                   1010:    if (State != REPLACE || *(oldp + col) == NUL)
                   1011:        extra = 1;
                   1012:    else
                   1013:        extra = 0;
                   1014:
                   1015:    /*
                   1016:     * a character has to be put on the replace stack if there is a
                   1017:     * character that is replaced, so it can be put back when BS is used.
                   1018:     * Otherwise a 0 is put on the stack, indicating that a new character
                   1019:     * was inserted, which can be deleted when BS is used.
                   1020:     */
                   1021:    if (State == REPLACE)
                   1022:        replace_push(!extra ? *(oldp + col) : 0);
                   1023:    newp = alloc_check((unsigned)(oldlen + extra));
                   1024:    if (newp == NULL)
                   1025:        return;
                   1026:    vim_memmove(newp, oldp, (size_t)col);
                   1027:    p = newp + col;
                   1028:    vim_memmove(p + extra, oldp + col, (size_t)(oldlen - col));
                   1029:    *p = c;
                   1030:    ml_replace(lnum, newp, FALSE);
                   1031:
                   1032:    /*
                   1033:     * If we're in insert or replace mode and 'showmatch' is set, then check for
                   1034:     * right parens and braces. If there isn't a match, then beep. If there
                   1035:     * is a match AND it's on the screen, then flash to it briefly. If it
                   1036:     * isn't on the screen, don't do anything.
                   1037:     */
                   1038: #ifdef RIGHTLEFT
                   1039:    if (p_sm && (State & INSERT) &&
                   1040:            ((!curwin->w_p_rl && (c == ')' || c == '}' || c == ']')) ||
                   1041:             (curwin->w_p_rl && (c == '(' || c == '{' || c == '['))))
                   1042: #else
                   1043:    if (p_sm && (State & INSERT) && (c == ')' || c == '}' || c == ']'))
                   1044: #endif
                   1045:        showmatch();
                   1046:
                   1047: #ifdef RIGHTLEFT
                   1048:    if (!p_ri || State == REPLACE)      /* normal insert: cursor right */
                   1049: #endif
                   1050:        ++curwin->w_cursor.col;
                   1051:    CHANGED;
                   1052: }
                   1053:
                   1054: /*
                   1055:  * Insert a string at the cursor position.
                   1056:  * Note: Nothing special for replace mode.
                   1057:  */
                   1058:    void
                   1059: ins_str(s)
                   1060:    char_u  *s;
                   1061: {
                   1062:    register char_u     *oldp, *newp;
                   1063:    register int        newlen = STRLEN(s);
                   1064:    int                 oldlen;
                   1065:    colnr_t             col = curwin->w_cursor.col;
                   1066:    linenr_t            lnum = curwin->w_cursor.lnum;
                   1067:
                   1068:    oldp = ml_get(lnum);
                   1069:    oldlen = STRLEN(oldp);
                   1070:
                   1071:    newp = alloc_check((unsigned)(oldlen + newlen + 1));
                   1072:    if (newp == NULL)
                   1073:        return;
                   1074:    vim_memmove(newp, oldp, (size_t)col);
                   1075:    vim_memmove(newp + col, s, (size_t)newlen);
                   1076:    vim_memmove(newp + col + newlen, oldp + col, (size_t)(oldlen - col + 1));
                   1077:    ml_replace(lnum, newp, FALSE);
                   1078:    curwin->w_cursor.col += newlen;
                   1079:    CHANGED;
                   1080: }
                   1081:
                   1082: /*
                   1083:  * delete one character under the cursor
                   1084:  *
                   1085:  * return FAIL for failure, OK otherwise
                   1086:  */
                   1087:    int
                   1088: delchar(fixpos)
                   1089:    int         fixpos;     /* if TRUE fix the cursor position when done */
                   1090: {
                   1091:    char_u      *oldp, *newp;
                   1092:    colnr_t     oldlen;
                   1093:    linenr_t    lnum = curwin->w_cursor.lnum;
                   1094:    colnr_t     col = curwin->w_cursor.col;
                   1095:    int         was_alloced;
                   1096:
                   1097:    oldp = ml_get(lnum);
                   1098:    oldlen = STRLEN(oldp);
                   1099:
                   1100:    if (col >= oldlen)  /* can't do anything (happens with replace mode) */
                   1101:        return FAIL;
                   1102:
                   1103: /*
                   1104:  * If the old line has been allocated the deletion can be done in the
                   1105:  * existing line. Otherwise a new line has to be allocated
                   1106:  */
                   1107:    was_alloced = ml_line_alloced();        /* check if oldp was allocated */
                   1108:    if (was_alloced)
                   1109:        newp = oldp;                            /* use same allocated memory */
                   1110:    else
                   1111:    {
                   1112:        newp = alloc((unsigned)oldlen);     /* need to allocated a new line */
                   1113:        if (newp == NULL)
                   1114:            return FAIL;
                   1115:        vim_memmove(newp, oldp, (size_t)col);
                   1116:    }
                   1117:    vim_memmove(newp + col, oldp + col + 1, (size_t)(oldlen - col));
                   1118:    if (!was_alloced)
                   1119:        ml_replace(lnum, newp, FALSE);
                   1120:
                   1121:    /*
                   1122:     * If we just took off the last character of a non-blank line, we don't
                   1123:     * want to end up positioned at the NUL.
                   1124:     */
                   1125:    if (fixpos && curwin->w_cursor.col > 0 && col == oldlen - 1)
                   1126:        --curwin->w_cursor.col;
                   1127:
                   1128:    CHANGED;
                   1129:    return OK;
                   1130: }
                   1131:
                   1132: /*
                   1133:  * Delete from cursor to end of line.
                   1134:  *
                   1135:  * return FAIL for failure, OK otherwise
                   1136:  */
                   1137:    int
                   1138: truncate_line(fixpos)
                   1139:    int         fixpos;     /* if TRUE fix the cursor position when done */
                   1140: {
                   1141:    char_u      *newp;
                   1142:    linenr_t    lnum = curwin->w_cursor.lnum;
                   1143:    colnr_t     col = curwin->w_cursor.col;
                   1144:
                   1145:    if (col == 0)
                   1146:        newp = strsave((char_u *)"");
                   1147:    else
                   1148:        newp = strnsave(ml_get(lnum), col);
                   1149:
                   1150:    if (newp == NULL)
                   1151:        return FAIL;
                   1152:
                   1153:    ml_replace(lnum, newp, FALSE);
                   1154:
                   1155:    /*
                   1156:     * If "fixpos" is TRUE we don't want to end up positioned at the NUL.
                   1157:     */
                   1158:    if (fixpos && curwin->w_cursor.col > 0)
                   1159:        --curwin->w_cursor.col;
                   1160:
                   1161:    CHANGED;
                   1162:    return OK;
                   1163: }
                   1164:
                   1165:    void
                   1166: dellines(nlines, dowindow, undo)
                   1167:    long            nlines;         /* number of lines to delete */
                   1168:    int             dowindow;       /* if true, update the window */
                   1169:    int             undo;           /* if true, prepare for undo */
                   1170: {
                   1171:    int             num_plines = 0;
                   1172:
                   1173:    if (nlines <= 0)
                   1174:        return;
                   1175:    /*
                   1176:     * There's no point in keeping the window updated if redrawing is disabled
                   1177:     * or we're deleting more than a window's worth of lines.
                   1178:     */
                   1179:    if (RedrawingDisabled)
                   1180:        dowindow = FALSE;
                   1181:    else if (nlines > (curwin->w_height - curwin->w_row) && dowindow)
                   1182:    {
                   1183:        dowindow = FALSE;
                   1184:        /* flaky way to clear rest of window */
                   1185:        win_del_lines(curwin, curwin->w_row, curwin->w_height, TRUE, TRUE);
                   1186:    }
                   1187:    /* save the deleted lines for undo */
                   1188:    if (undo && u_savedel(curwin->w_cursor.lnum, nlines) == FAIL)
                   1189:        return;
                   1190:
                   1191:    /* adjust marks for deleted lines and lines that follow */
                   1192:    mark_adjust(curwin->w_cursor.lnum, curwin->w_cursor.lnum + nlines - 1,
                   1193:                                                            MAXLNUM, -nlines);
                   1194:
                   1195:    while (nlines-- > 0)
                   1196:    {
                   1197:        if (curbuf->b_ml.ml_flags & ML_EMPTY)       /* nothing to delete */
                   1198:            break;
                   1199:
                   1200:        /*
                   1201:         * Set up to delete the correct number of physical lines on the
                   1202:         * window
                   1203:         */
                   1204:        if (dowindow)
                   1205:            num_plines += plines(curwin->w_cursor.lnum);
                   1206:
                   1207:        ml_delete(curwin->w_cursor.lnum, TRUE);
                   1208:
                   1209:        CHANGED;
                   1210:
                   1211:        /* If we delete the last line in the file, stop */
                   1212:        if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count)
                   1213:        {
                   1214:            curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
                   1215:            break;
                   1216:        }
                   1217:    }
                   1218:    curwin->w_cursor.col = 0;
                   1219:    /*
                   1220:     * Delete the correct number of physical lines on the window
                   1221:     */
                   1222:    if (dowindow && num_plines > 0)
                   1223:        win_del_lines(curwin, curwin->w_row, num_plines, TRUE, TRUE);
                   1224: }
                   1225:
                   1226:    int
                   1227: gchar(pos)
                   1228:    FPOS *pos;
                   1229: {
                   1230:    return (int)(*(ml_get_pos(pos)));
                   1231: }
                   1232:
                   1233:    int
                   1234: gchar_cursor()
                   1235: {
                   1236:    return (int)(*(ml_get_cursor()));
                   1237: }
                   1238:
                   1239: /*
                   1240:  * Write a character at the current cursor position.
                   1241:  * It is directly written into the block.
                   1242:  */
                   1243:    void
                   1244: pchar_cursor(c)
                   1245:    int c;
                   1246: {
                   1247:    *(ml_get_buf(curbuf, curwin->w_cursor.lnum, TRUE) +
                   1248:                                                    curwin->w_cursor.col) = c;
                   1249: }
                   1250:
                   1251: /*
                   1252:  * Put *pos at end of current buffer
                   1253:  */
                   1254:    void
                   1255: goto_endofbuf(pos)
                   1256:    FPOS    *pos;
                   1257: {
                   1258:    char_u  *p;
                   1259:
                   1260:    pos->lnum = curbuf->b_ml.ml_line_count;
                   1261:    pos->col = 0;
                   1262:    p = ml_get(pos->lnum);
                   1263:    while (*p++)
                   1264:        ++pos->col;
                   1265: }
                   1266:
                   1267: /*
                   1268:  * When extra == 0: Return TRUE if the cursor is before or on the first
                   1269:  *                 non-blank in the line.
                   1270:  * When extra == 1: Return TRUE if the cursor is before the first non-blank in
                   1271:  *                 the line.
                   1272:  */
                   1273:    int
                   1274: inindent(extra)
                   1275:    int     extra;
                   1276: {
                   1277:    register char_u *ptr;
                   1278:    register colnr_t col;
                   1279:
                   1280:    for (col = 0, ptr = ml_get_curline(); vim_iswhite(*ptr); ++col)
                   1281:        ++ptr;
                   1282:    if (col >= curwin->w_cursor.col + extra)
                   1283:        return TRUE;
                   1284:    else
                   1285:        return FALSE;
                   1286: }
                   1287:
                   1288: /*
                   1289:  * skipwhite: skip over ' ' and '\t'.
                   1290:  */
                   1291:    char_u *
                   1292: skipwhite(p)
                   1293:    register char_u *p;
                   1294: {
                   1295:     while (vim_iswhite(*p))    /* skip to next non-white */
                   1296:        ++p;
                   1297:    return p;
                   1298: }
                   1299:
                   1300: /*
                   1301:  * skipdigits: skip over digits;
                   1302:  */
                   1303:    char_u *
                   1304: skipdigits(p)
                   1305:    register char_u *p;
                   1306: {
                   1307:     while (isdigit(*p))    /* skip to next non-digit */
                   1308:        ++p;
                   1309:    return p;
                   1310: }
                   1311:
                   1312: /*
                   1313:  * skiptowhite: skip over text until ' ' or '\t' or NUL.
                   1314:  */
                   1315:    char_u *
                   1316: skiptowhite(p)
                   1317:    register char_u *p;
                   1318: {
                   1319:    while (*p != ' ' && *p != '\t' && *p != NUL)
                   1320:        ++p;
                   1321:    return p;
                   1322: }
                   1323:
                   1324: /*
                   1325:  * skiptowhite_esc: Like skiptowhite(), but also skip escaped chars
                   1326:  */
                   1327:    char_u *
                   1328: skiptowhite_esc(p)
                   1329:    register char_u *p;
                   1330: {
                   1331:    while (*p != ' ' && *p != '\t' && *p != NUL)
                   1332:    {
                   1333:        if ((*p == '\\' || *p == Ctrl('V')) && *(p + 1) != NUL)
                   1334:            ++p;
                   1335:        ++p;
                   1336:    }
                   1337:    return p;
                   1338: }
                   1339:
                   1340: /*
                   1341:  * getdigits: get a number from a string and skip over it
                   1342:  *
                   1343:  * note: you must give a pointer to a char_u pointer!
                   1344:  */
                   1345:
                   1346:    long
                   1347: getdigits(pp)
                   1348:    char_u **pp;
                   1349: {
                   1350:     register char_u *p;
                   1351:    long retval;
                   1352:
                   1353:    p = *pp;
                   1354:    retval = atol((char *)p);
                   1355:    p = skipdigits(p);      /* skip to next non-digit */
                   1356:     *pp = p;
                   1357:    return retval;
                   1358: }
                   1359:
                   1360: /*
                   1361:  * Skip to next part of an option argument: Skip space and comma.
                   1362:  */
                   1363:    char_u *
                   1364: skip_to_option_part(p)
                   1365:    char_u  *p;
                   1366: {
                   1367:    if (*p == ',')
                   1368:        ++p;
                   1369:    while (*p == ' ')
                   1370:        ++p;
                   1371:    return p;
                   1372: }
                   1373:
                   1374:    char *
                   1375: plural(n)
                   1376:    long n;
                   1377: {
                   1378:    static char buf[2] = "s";
                   1379:
                   1380:    if (n == 1)
                   1381:        return &(buf[1]);
                   1382:    return &(buf[0]);
                   1383: }
                   1384:
                   1385: /*
                   1386:  * set_Changed is called when something in the current buffer is changed
                   1387:  */
                   1388:    void
                   1389: set_Changed()
                   1390: {
                   1391:    if (!curbuf->b_changed)
                   1392:    {
1.2       downsj   1393:        change_warning(0);
1.1       downsj   1394:        curbuf->b_changed = TRUE;
                   1395:        check_status(curbuf);
                   1396:    }
                   1397:    modified = TRUE;                /* used for redrawing */
                   1398: }
                   1399:
                   1400: /*
                   1401:  * unset_Changed is called when the changed flag must be reset for buffer 'buf'
                   1402:  */
                   1403:    void
                   1404: unset_Changed(buf)
                   1405:    BUF     *buf;
                   1406: {
                   1407:    if (buf->b_changed)
                   1408:    {
                   1409:        buf->b_changed = 0;
                   1410:        check_status(buf);
                   1411:    }
                   1412: }
                   1413:
                   1414: /*
                   1415:  * check_status: called when the status bars for the buffer 'buf'
                   1416:  *              need to be updated
                   1417:  */
                   1418:    static void
                   1419: check_status(buf)
                   1420:    BUF     *buf;
                   1421: {
                   1422:    WIN     *wp;
                   1423:    int     i;
                   1424:
                   1425:    i = 0;
                   1426:    for (wp = firstwin; wp != NULL; wp = wp->w_next)
                   1427:        if (wp->w_buffer == buf && wp->w_status_height)
                   1428:        {
                   1429:            wp->w_redr_status = TRUE;
                   1430:            ++i;
                   1431:        }
                   1432:    if (i)
                   1433:        redraw_later(NOT_VALID);
                   1434: }
                   1435:
                   1436: /*
                   1437:  * If the file is readonly, give a warning message with the first change.
                   1438:  * Don't do this for autocommands.
                   1439:  * Don't use emsg(), because it flushes the macro buffer.
                   1440:  * If we have undone all changes b_changed will be FALSE, but b_did_warn
                   1441:  * will be TRUE.
                   1442:  */
                   1443:    void
1.2       downsj   1444: change_warning(col)
                   1445:    int     col;                /* column for message; non-zero when in insert
                   1446:                                   mode and 'showmode' is on */
1.1       downsj   1447: {
                   1448:    if (curbuf->b_did_warn == FALSE && curbuf->b_changed == 0 &&
                   1449: #ifdef AUTOCMD
                   1450:                                              !autocmd_busy &&
                   1451: #endif
                   1452:                                              curbuf->b_p_ro)
                   1453:    {
1.2       downsj   1454:        /*
                   1455:         * Do what msg() does, but with a column offset.
                   1456:         */
                   1457:        msg_start();
                   1458:        msg_col = col;
                   1459:        MSG_OUTSTR("Warning: Changing a readonly file");
                   1460:        msg_clr_eos();
                   1461:        (void)msg_end();
1.3     ! downsj   1462:        flushbuf();
1.2       downsj   1463:        mch_delay(1000L, TRUE); /* give him some time to think about it */
1.1       downsj   1464:        curbuf->b_did_warn = TRUE;
                   1465:    }
                   1466: }
                   1467:
                   1468: /*
                   1469:  * Ask for a reply from the user, a 'y' or a 'n'.
                   1470:  * No other characters are accepted, the message is repeated until a valid
                   1471:  * reply is entered or CTRL-C is hit.
                   1472:  * If direct is TRUE, don't use vgetc but mch_inchar, don't get characters from
                   1473:  * any buffers but directly from the user.
                   1474:  *
                   1475:  * return the 'y' or 'n'
                   1476:  */
                   1477:    int
                   1478: ask_yesno(str, direct)
                   1479:    char_u  *str;
                   1480:    int     direct;
                   1481: {
                   1482:    int     r = ' ';
                   1483:    char_u  buf[20];
                   1484:    int     len = 0;
                   1485:    int     idx = 0;
                   1486:
                   1487:    if (exiting)                /* put terminal in raw mode for this question */
                   1488:        settmode(1);
                   1489:    while (r != 'y' && r != 'n')
                   1490:    {
                   1491:        (void)set_highlight('r');   /* same highlighting as for wait_return */
                   1492:        msg_highlight = TRUE;
                   1493:        smsg((char_u *)"%s (y/n)?", str);
                   1494:        if (direct)
                   1495:        {
                   1496:            flushbuf();
                   1497:            if (idx >= len)
                   1498:            {
                   1499:                len = mch_inchar(buf, 20, -1L);
                   1500:                idx = 0;
                   1501:            }
                   1502:            r = buf[idx++];
                   1503:        }
                   1504:        else
                   1505:            r = vgetc();
                   1506:        if (r == Ctrl('C') || r == ESC)
                   1507:            r = 'n';
                   1508:        msg_outchar(r);     /* show what you typed */
                   1509:        flushbuf();
                   1510:    }
                   1511:    return r;
                   1512: }
                   1513:
                   1514: /*
                   1515:  * get a number from the user
                   1516:  */
                   1517:    int
                   1518: get_number()
                   1519: {
                   1520:    int     n = 0;
                   1521:    int     c;
                   1522:
                   1523:    for (;;)
                   1524:    {
                   1525:        windgoto(msg_row, msg_col);
                   1526:        c = vgetc();
                   1527:        if (isdigit(c))
                   1528:        {
                   1529:            n = n * 10 + c - '0';
                   1530:            msg_outchar(c);
                   1531:        }
                   1532:        else if (c == K_DEL || c == K_BS || c == Ctrl('H'))
                   1533:        {
                   1534:            n /= 10;
                   1535:            MSG_OUTSTR("\b \b");
                   1536:        }
                   1537:        else if (c == CR || c == NL || c == Ctrl('C'))
                   1538:            break;
                   1539:    }
                   1540:    return n;
                   1541: }
                   1542:
                   1543:    void
                   1544: msgmore(n)
                   1545:    long n;
                   1546: {
                   1547:    long pn;
                   1548:
                   1549:    if (global_busy ||      /* no messages now, wait until global is finished */
                   1550:            keep_msg)       /* there is a message already, skip this one */
                   1551:        return;
                   1552:
                   1553:    if (n > 0)
                   1554:        pn = n;
                   1555:    else
                   1556:        pn = -n;
                   1557:
                   1558:    if (pn > p_report)
                   1559:    {
                   1560:        sprintf((char *)msg_buf, "%ld %s line%s %s",
                   1561:                pn, n > 0 ? "more" : "fewer", plural(pn),
                   1562:                got_int ? "(Interrupted)" : "");
                   1563:        if (msg(msg_buf))
                   1564:            keep_msg = msg_buf;
                   1565:    }
                   1566: }
                   1567:
                   1568: /*
                   1569:  * flush map and typeahead buffers and give a warning for an error
                   1570:  */
                   1571:    void
                   1572: beep_flush()
                   1573: {
                   1574:    flush_buffers(FALSE);
                   1575:    vim_beep();
                   1576: }
                   1577:
                   1578: /*
                   1579:  * give a warning for an error
                   1580:  */
                   1581:    void
                   1582: vim_beep()
                   1583: {
                   1584:    if (p_vb)
                   1585:    {
                   1586: #ifdef DJGPP
                   1587:        ScreenVisualBell();
                   1588: #else
                   1589:        outstr(T_VB);
                   1590: #endif
                   1591:    }
                   1592:    else
                   1593:    {
                   1594: #if defined MSDOS  ||  defined WIN32 /* ? gvr */
                   1595:        /*
                   1596:         * The number of beeps outputted is reduced to avoid having to wait
                   1597:         * for all the beeps to finish. This is only a problem on systems
                   1598:         * where the beeps don't overlap.
                   1599:         */
                   1600:        if (beep_count == 0 || beep_count == 10)
                   1601:        {
                   1602:            outchar('\007');
                   1603:            beep_count = 1;
                   1604:        }
                   1605:        else
                   1606:            ++beep_count;
                   1607: #else
                   1608:        outchar('\007');
                   1609: #endif
                   1610:    }
                   1611: }
                   1612:
                   1613: /*
                   1614:  * To get the "real" home directory:
                   1615:  * - get value of $HOME
                   1616:  * For Unix:
                   1617:  * - go to that directory
                   1618:  * - do mch_dirname() to get the real name of that directory.
                   1619:  * This also works with mounts and links.
                   1620:  * Don't do this for MS-DOS, it will change the "current dir" for a drive.
                   1621:  */
                   1622: static char_u  *homedir = NULL;
                   1623:
                   1624:    void
                   1625: init_homedir()
                   1626: {
                   1627:    char_u  *var;
                   1628:
                   1629:    var = vim_getenv((char_u *)"HOME");
                   1630: #if defined(OS2) || defined(MSDOS) || defined(WIN32)
                   1631:    /*
                   1632:     * Default home dir is C:/
                   1633:     * Best assumption we can make in such a situation.
                   1634:     */
                   1635:    if (var == NULL)
                   1636:        var = "C:/";
                   1637: #endif
                   1638:    if (var != NULL)
                   1639:    {
                   1640: #ifdef UNIX
                   1641:        if (mch_dirname(NameBuff, MAXPATHL) == OK)
                   1642:        {
                   1643:            if (!vim_chdir((char *)var) && mch_dirname(IObuff, IOSIZE) == OK)
                   1644:                var = IObuff;
                   1645:            vim_chdir((char *)NameBuff);
                   1646:        }
                   1647: #endif
                   1648:        homedir = strsave(var);
                   1649:    }
                   1650: }
                   1651:
                   1652: /*
                   1653:  * Expand environment variable with path name.
                   1654:  * For Unix and OS/2 "~/" is also expanded, like $HOME.
                   1655:  * If anything fails no expansion is done and dst equals src.
                   1656:  * Note that IObuff must NOT be used as either src or dst!  This is because
                   1657:  * vim_getenv() may use IObuff to do its expansion.
                   1658:  */
                   1659:    void
                   1660: expand_env(src, dst, dstlen)
                   1661:    char_u  *src;           /* input string e.g. "$HOME/vim.hlp" */
                   1662:    char_u  *dst;           /* where to put the result */
                   1663:    int     dstlen;         /* maximum length of the result */
                   1664: {
                   1665:    char_u  *tail;
                   1666:    int     c;
                   1667:    char_u  *var;
                   1668:    int     copy_char;
                   1669: #if defined(UNIX) || defined(OS2)
                   1670:    int     mustfree;
                   1671:    int     at_start = TRUE;
                   1672: #endif
                   1673:
                   1674:    src = skipwhite(src);
                   1675:    --dstlen;               /* leave one char space for "\," */
                   1676:    while (*src && dstlen > 0)
                   1677:    {
                   1678:        copy_char = TRUE;
                   1679:        if (*src == '$'
                   1680: #if defined(UNIX) || defined(OS2)
                   1681:                        || (*src == '~' && at_start)
                   1682: #endif
                   1683:                                                    )
                   1684:        {
                   1685: #if defined(UNIX) || defined(OS2)
                   1686:            mustfree = FALSE;
                   1687:
                   1688:            /*
                   1689:             * The variable name is copied into dst temporarily, because it may
                   1690:             * be a string in read-only memory and a NUL needs to be inserted.
                   1691:             */
                   1692:            if (*src == '$')                            /* environment var */
                   1693:            {
                   1694: #endif
                   1695:                tail = src + 1;
                   1696:                var = dst;
                   1697:                c = dstlen - 1;
                   1698:                while (c-- > 0 && *tail && isidchar(*tail))
                   1699: #ifdef OS2
                   1700:                {   /* env vars only in uppercase */
                   1701:                    *var++ = toupper(*tail);    /* toupper() may be a macro! */
                   1702:                    tail++;
                   1703:                }
                   1704: #else
                   1705:                    *var++ = *tail++;
                   1706: #endif
                   1707:                *var = NUL;
                   1708: #if defined(OS2) || defined(MSDOS) || defined(WIN32)
                   1709:                /* use "C:/" when $HOME is not set */
                   1710:                if (STRCMP(dst, "HOME") == 0)
                   1711:                    var = homedir;
                   1712:                else
                   1713: #endif
                   1714:                    var = vim_getenv(dst);
                   1715: #if defined(UNIX) || defined(OS2)
                   1716:            }
                   1717:                                                        /* home directory */
                   1718:            else if (src[1] == NUL ||
                   1719:                              vim_strchr((char_u *)"/ ,\t\n", src[1]) != NULL)
                   1720:            {
                   1721:                var = homedir;
                   1722:                tail = src + 1;
                   1723:            }
                   1724:            else                                        /* user directory */
                   1725: # ifdef OS2
                   1726:            {
                   1727:                /* cannot expand user's home directory, so don't try */
                   1728:                var = NULL;
                   1729:                tail = "";  /* shut gcc up about "may be used uninitialized" */
                   1730:            }
                   1731: # else
                   1732:            {
                   1733:                /*
                   1734:                 * Copy ~user to dst[], so we can put a NUL after it.
                   1735:                 */
                   1736:                tail = src;
                   1737:                var = dst;
                   1738:                c = dstlen - 1;
                   1739:                while (c-- > 0 && *tail &&
                   1740:                                       isfilechar(*tail) && !ispathsep(*tail))
                   1741:                    *var++ = *tail++;
                   1742:                *var = NUL;
                   1743:
                   1744:                /*
                   1745:                 * If the system supports getpwnam(), use it.
                   1746:                 * Otherwise, or if getpwnam() fails, the shell is used to
                   1747:                 * expand ~user.  This is slower and may fail if the shell
                   1748:                 * does not support ~user (old versions of /bin/sh).
                   1749:                 */
                   1750: #  if defined(HAVE_GETPWNAM) && defined(HAVE_PWD_H)
                   1751:                {
                   1752:                    struct passwd *pw;
                   1753:
                   1754:                    pw = getpwnam((char *)dst + 1);
                   1755:                    if (pw != NULL)
                   1756:                        var = (char_u *)pw->pw_dir;
                   1757:                    else
                   1758:                        var = NULL;
                   1759:                }
                   1760:                if (var == NULL)
                   1761: #  endif
                   1762:                {
                   1763:                    var = ExpandOne(dst, NULL, 0, WILD_EXPAND_FREE);
                   1764:                    mustfree = TRUE;
                   1765:                }
                   1766:            }
                   1767: # endif /* OS2 */
                   1768: #endif /* UNIX || OS2 */
                   1769:            if (var != NULL && *var != NUL &&
                   1770:                          (STRLEN(var) + STRLEN(tail) + 1 < (unsigned)dstlen))
                   1771:            {
                   1772:                STRCPY(dst, var);
                   1773:                dstlen -= STRLEN(var);
                   1774:                dst += STRLEN(var);
                   1775:                    /* if var[] ends in a path separator and tail[] starts
                   1776:                     * with it, skip a character */
                   1777:                if (*var && ispathsep(*(dst-1)) && ispathsep(*tail))
                   1778:                    ++tail;
                   1779:                src = tail;
                   1780:                copy_char = FALSE;
                   1781:            }
                   1782: #if defined(UNIX) || defined(OS2)
                   1783:            if (mustfree)
                   1784:                vim_free(var);
                   1785: #endif
                   1786:        }
                   1787:
                   1788:        if (copy_char)      /* copy at least one char */
                   1789:        {
                   1790: #if defined(UNIX) || defined(OS2)
                   1791:            /*
                   1792:             * Recogize the start of a new name, for '~'.
                   1793:             */
                   1794:            at_start = FALSE;
                   1795: #endif
                   1796:            if (src[0] == '\\')
                   1797:            {
                   1798:                *dst++ = *src++;
                   1799:                --dstlen;
                   1800:            }
                   1801: #if defined(UNIX) || defined(OS2)
                   1802:            else if (src[0] == ' ' || src[0] == ',')
                   1803:                at_start = TRUE;
                   1804: #endif
                   1805:            *dst++ = *src++;
                   1806:            --dstlen;
                   1807:        }
                   1808:    }
                   1809:    *dst = NUL;
                   1810: }
                   1811:
                   1812: /*
1.2       downsj   1813:  * Replace home directory by "~" in each space or comma separated filename in
                   1814:  * 'src'.  If anything fails (except when out of space) dst equals src.
1.1       downsj   1815:  */
                   1816:    void
                   1817: home_replace(buf, src, dst, dstlen)
                   1818:    BUF     *buf;           /* when not NULL, check for help files */
                   1819:    char_u  *src;           /* input file name */
                   1820:    char_u  *dst;           /* where to put the result */
                   1821:    int     dstlen;         /* maximum length of the result */
                   1822: {
                   1823:    size_t  dirlen = 0, envlen = 0;
                   1824:    size_t  len;
                   1825:    char_u  *homedir_env;
                   1826:    char_u  *p;
                   1827:
                   1828:    if (src == NULL)
                   1829:    {
                   1830:        *dst = NUL;
                   1831:        return;
                   1832:    }
                   1833:
                   1834:    /*
                   1835:     * If the file is a help file, remove the path completely.
                   1836:     */
                   1837:    if (buf != NULL && buf->b_help)
                   1838:    {
                   1839:        STRCPY(dst, gettail(src));
                   1840:        return;
                   1841:    }
                   1842:
                   1843:    /*
                   1844:     * We check both the value of the $HOME environment variable and the
                   1845:     * "real" home directory.
                   1846:     */
                   1847:    if (homedir != NULL)
                   1848:        dirlen = STRLEN(homedir);
                   1849:    homedir_env = vim_getenv((char_u *)"HOME");
                   1850:    if (homedir_env != NULL)
                   1851:        envlen = STRLEN(homedir_env);
                   1852:
                   1853:    src = skipwhite(src);
                   1854:    while (*src && dstlen > 0)
                   1855:    {
                   1856:        /*
                   1857:         * Here we are at the beginning of a filename.
                   1858:         * First, check to see if the beginning of the filename matches
                   1859:         * $HOME or the "real" home directory. Check that there is a '/'
                   1860:         * after the match (so that if e.g. the file is "/home/pieter/bla",
                   1861:         * and the home directory is "/home/piet", the file does not end up
                   1862:         * as "~er/bla" (which would seem to indicate the file "bla" in user
                   1863:         * er's home directory)).
                   1864:         */
                   1865:        p = homedir;
                   1866:        len = dirlen;
                   1867:        for (;;)
                   1868:        {
                   1869:            if (len && fnamencmp(src, p, len) == 0 && (ispathsep(src[len]) ||
                   1870:                       src[len] == ',' || src[len] == ' ' || src[len] == NUL))
                   1871:            {
                   1872:                src += len;
                   1873:                if (--dstlen > 0)
                   1874:                    *dst++ = '~';
1.2       downsj   1875:
1.1       downsj   1876:                /*
1.2       downsj   1877:                 * If it's just the home directory, add  "/".
1.1       downsj   1878:                 */
                   1879:                if (!ispathsep(src[0]) && --dstlen > 0)
                   1880:                    *dst++ = '/';
                   1881:            }
                   1882:            if (p == homedir_env)
                   1883:                break;
                   1884:            p = homedir_env;
                   1885:            len = envlen;
                   1886:        }
                   1887:
                   1888:        /* skip to separator: space or comma */
                   1889:        while (*src && *src != ',' && *src != ' ' && --dstlen > 0)
                   1890:            *dst++ = *src++;
                   1891:        /* skip separator */
                   1892:        while ((*src == ' ' || *src == ',') && --dstlen > 0)
                   1893:            *dst++ = *src++;
                   1894:    }
                   1895:    /* if (dstlen == 0) out of space, what to do??? */
                   1896:
                   1897:    *dst = NUL;
                   1898: }
                   1899:
                   1900: /*
                   1901:  * Like home_replace, store the replaced string in allocated memory.
                   1902:  * When something fails, NULL is returned.
                   1903:  */
                   1904:    char_u  *
                   1905: home_replace_save(buf, src)
                   1906:    BUF     *buf;           /* when not NULL, check for help files */
                   1907:    char_u  *src;           /* input file name */
                   1908: {
                   1909:    char_u      *dst;
                   1910:    unsigned    len;
                   1911:
1.2       downsj   1912:    len = 3;                    /* space for "~/" and trailing NUL */
                   1913:    if (src != NULL)            /* just in case */
                   1914:        len += STRLEN(src);
1.1       downsj   1915:    dst = alloc(len);
                   1916:    if (dst != NULL)
                   1917:        home_replace(buf, src, dst, len);
                   1918:    return dst;
                   1919: }
                   1920:
                   1921: /*
                   1922:  * Compare two file names and return:
                   1923:  * FPC_SAME   if they both exist and are the same file.
                   1924:  * FPC_DIFF   if they both exist and are different files.
                   1925:  * FPC_NOTX   if they both don't exist.
                   1926:  * FPC_DIFFX  if one of them doesn't exist.
                   1927:  * For the first name environment variables are expanded
                   1928:  */
                   1929:    int
                   1930: fullpathcmp(s1, s2)
                   1931:    char_u *s1, *s2;
                   1932: {
                   1933: #ifdef UNIX
                   1934:    char_u          buf1[MAXPATHL];
                   1935:    struct stat     st1, st2;
                   1936:    int             r1, r2;
                   1937:
                   1938:    expand_env(s1, buf1, MAXPATHL);
                   1939:    r1 = stat((char *)buf1, &st1);
                   1940:    r2 = stat((char *)s2, &st2);
                   1941:    if (r1 != 0 && r2 != 0)
                   1942:        return FPC_NOTX;
                   1943:    if (r1 != 0 || r2 != 0)
                   1944:        return FPC_DIFFX;
                   1945:    if (st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino)
                   1946:        return FPC_SAME;
                   1947:    return FPC_DIFF;
                   1948: #else
                   1949:    char_u  *buf1 = NULL;
                   1950:    char_u  *buf2 = NULL;
                   1951:    int     retval = FPC_DIFF;
                   1952:    int     r1, r2;
                   1953:
                   1954:    if ((buf1 = alloc(MAXPATHL)) != NULL && (buf2 = alloc(MAXPATHL)) != NULL)
                   1955:    {
                   1956:        expand_env(s1, buf2, MAXPATHL);
                   1957:        /*
                   1958:         * If FullName() failed, the file probably doesn't exist.
                   1959:         */
                   1960:        r1 = FullName(buf2, buf1, MAXPATHL, FALSE);
                   1961:        r2 = FullName(s2, buf2, MAXPATHL, FALSE);
                   1962:        if (r1 != OK && r2 != OK)
                   1963:            retval = FPC_NOTX;
                   1964:        else if (r1 != OK || r2 != OK)
                   1965:            retval = FPC_DIFFX;
                   1966:        else if (fnamecmp(buf1, buf2))
                   1967:            retval = FPC_DIFF;
                   1968:        else
                   1969:            retval = FPC_SAME;
                   1970:    }
                   1971:    vim_free(buf1);
                   1972:    vim_free(buf2);
                   1973:    return retval;
                   1974: #endif
                   1975: }
                   1976:
                   1977: /*
                   1978:  * get the tail of a path: the file name.
                   1979:  */
                   1980:    char_u *
                   1981: gettail(fname)
                   1982:    char_u *fname;
                   1983: {
                   1984:    register char_u *p1, *p2;
                   1985:
                   1986:    if (fname == NULL)
                   1987:        return (char_u *)"";
                   1988:    for (p1 = p2 = fname; *p2; ++p2)    /* find last part of path */
                   1989:    {
                   1990:        if (ispathsep(*p2))
                   1991:            p1 = p2 + 1;
                   1992:    }
                   1993:    return p1;
                   1994: }
                   1995:
                   1996: /*
1.2       downsj   1997:  * Get a pointer to one character past the head of a path name.
                   1998:  * Unix: after "/"; DOS: after "c:\"; Amiga: after "disk:/".
                   1999:  * If there is no head, path is returned.
                   2000:  */
                   2001:    char_u *
                   2002: get_past_head(path)
                   2003:    char_u  *path;
                   2004: {
                   2005:    char_u  *retval;
                   2006:
                   2007: #if defined(MSDOS) || defined(WIN32) || defined(OS2)
                   2008:    /* may skip "c:" */
                   2009:    if (isalpha(path[0]) && path[1] == ':')
                   2010:        retval = path + 2;
                   2011:    else
                   2012:        retval = path;
                   2013: #else
                   2014: # if defined(AMIGA)
                   2015:    /* may skip "label:" */
                   2016:    retval = vim_strchr(path, ':');
                   2017:    if (retval == NULL)
                   2018:        retval = path;
                   2019: # else /* Unix */
                   2020:    retval = path;
                   2021: # endif
                   2022: #endif
                   2023:
                   2024:    while (ispathsep(*retval))
                   2025:        ++retval;
                   2026:
                   2027:    return retval;
                   2028: }
                   2029:
                   2030: /*
1.1       downsj   2031:  * return TRUE if 'c' is a path separator.
                   2032:  */
                   2033:    int
                   2034: ispathsep(c)
                   2035:    int c;
                   2036: {
                   2037: #ifdef UNIX
                   2038:    return (c == PATHSEP);      /* UNIX has ':' inside file names */
                   2039: #else
                   2040: # ifdef BACKSLASH_IN_FILENAME
                   2041:    return (c == ':' || c == PATHSEP || c == '\\');
                   2042: # else
                   2043:    return (c == ':' || c == PATHSEP);
                   2044: # endif
                   2045: #endif
                   2046: }
                   2047:
                   2048: /*
                   2049:  * Concatenate filenames fname1 and fname2 into allocated memory.
                   2050:  * Only add a '/' when 'sep' is TRUE and it is neccesary.
                   2051:  */
                   2052:    char_u  *
                   2053: concat_fnames(fname1, fname2, sep)
                   2054:    char_u  *fname1;
                   2055:    char_u  *fname2;
                   2056:    int     sep;
                   2057: {
                   2058:    char_u  *dest;
                   2059:
                   2060:    dest = alloc((unsigned)(STRLEN(fname1) + STRLEN(fname2) + 2));
                   2061:    if (dest != NULL)
                   2062:    {
                   2063:        STRCPY(dest, fname1);
                   2064:        if (sep && *dest && !ispathsep(*(dest + STRLEN(dest) - 1)))
                   2065:            STRCAT(dest, PATHSEPSTR);
                   2066:        STRCAT(dest, fname2);
                   2067:    }
                   2068:    return dest;
                   2069: }
                   2070:
                   2071: /*
                   2072:  * FullName_save - Make an allocated copy of a full file name.
                   2073:  * Returns NULL when failed.
                   2074:  */
                   2075:    char_u  *
                   2076: FullName_save(fname)
                   2077:    char_u      *fname;
                   2078: {
                   2079:    char_u      *buf;
                   2080:    char_u      *new_fname = NULL;
                   2081:
                   2082:    buf = alloc((unsigned)MAXPATHL);
                   2083:    if (buf != NULL)
                   2084:    {
                   2085:        if (FullName(fname, buf, MAXPATHL, FALSE) != FAIL)
                   2086:            new_fname = strsave(buf);
                   2087:        vim_free(buf);
                   2088:    }
                   2089:    return new_fname;
                   2090: }
                   2091:
                   2092: #ifdef CINDENT
                   2093:
                   2094: /*
                   2095:  * Functions for C-indenting.
                   2096:  * Most of this originally comes from Eric Fischer.
                   2097:  */
                   2098: /*
                   2099:  * Below "XXX" means that this function may unlock the current line.
                   2100:  */
                   2101:
                   2102: static int     isdefault __ARGS((char_u *));
                   2103: static char_u  *after_label __ARGS((char_u *l));
                   2104: static int     get_indent_nolabel __ARGS((linenr_t lnum));
                   2105: static int     skip_label __ARGS((linenr_t, char_u **pp, int ind_maxcomment));
                   2106: static int     ispreproc __ARGS((char_u *));
                   2107: static int     iscomment __ARGS((char_u *));
                   2108: static int     commentorempty __ARGS((char_u *));
                   2109: static int     isterminated __ARGS((char_u *));
                   2110: static int     isfuncdecl __ARGS((char_u *));
                   2111: static char_u  *skip_string __ARGS((char_u *p));
                   2112: static int     isif __ARGS((char_u *));
                   2113: static int     iselse __ARGS((char_u *));
                   2114: static int     isdo __ARGS((char_u *));
                   2115: static int     iswhileofdo __ARGS((char_u *, linenr_t, int));
                   2116: static FPOS        *find_start_comment __ARGS((int ind_maxcomment));
                   2117: static FPOS        *find_start_brace __ARGS((int));
                   2118: static FPOS        *find_match_paren __ARGS((int, int));
                   2119: static int     find_last_paren __ARGS((char_u *l));
                   2120: static int     find_match __ARGS((int lookfor, linenr_t ourscope,
                   2121:                        int ind_maxparen, int ind_maxcomment));
                   2122:
                   2123: /*
                   2124:  * Recognize a label: "label:".
                   2125:  * Note: curwin->w_cursor must be where we are looking for the label.
                   2126:  */
                   2127:    int
                   2128: islabel(ind_maxcomment)            /* XXX */
                   2129:    int         ind_maxcomment;
                   2130: {
                   2131:    char_u      *s;
                   2132:
                   2133:    s = skipwhite(ml_get_curline());
                   2134:
                   2135:    /*
                   2136:     * Exclude "default" from labels, since it should be indented
                   2137:     * like a switch label.
                   2138:     */
                   2139:
                   2140:    if (isdefault(s))
                   2141:        return FALSE;
                   2142:
                   2143:    if (!isidchar(*s))      /* need at least one ID character */
                   2144:        return FALSE;
                   2145:
                   2146:    while (isidchar(*s))
                   2147:        s++;
                   2148:
                   2149:    s = skipwhite(s);
                   2150:
                   2151:    /* "::" is not a label, it's C++ */
                   2152:    if (*s == ':' && s[1] != ':')
                   2153:    {
                   2154:        /*
                   2155:         * Only accept a label if the previous line is terminated or is a case
                   2156:         * label.
                   2157:         */
                   2158:        FPOS    cursor_save;
                   2159:        FPOS    *trypos;
                   2160:        char_u  *line;
                   2161:
                   2162:        cursor_save = curwin->w_cursor;
                   2163:        while (curwin->w_cursor.lnum > 1)
                   2164:        {
                   2165:            --curwin->w_cursor.lnum;
                   2166:
                   2167:            /*
                   2168:             * If we're in a comment now, skip to the start of the comment.
                   2169:             */
                   2170:            curwin->w_cursor.col = 0;
                   2171:            if ((trypos = find_start_comment(ind_maxcomment)) != NULL) /* XXX */
                   2172:                curwin->w_cursor = *trypos;
                   2173:
                   2174:            line = ml_get_curline();
                   2175:            if (ispreproc(line))        /* ignore #defines, #if, etc. */
                   2176:                continue;
                   2177:            if (commentorempty(line))
                   2178:                continue;
                   2179:
                   2180:            curwin->w_cursor = cursor_save;
                   2181:            if (isterminated(line) || iscase(line))
                   2182:                return TRUE;
                   2183:            return FALSE;
                   2184:        }
                   2185:        curwin->w_cursor = cursor_save;
                   2186:        return TRUE;            /* label at start of file??? */
                   2187:    }
                   2188:    return FALSE;
                   2189: }
                   2190:
                   2191: /*
                   2192:  * Recognize a switch label: "case .*:" or "default:".
                   2193:  */
                   2194:     int
                   2195: iscase(s)
                   2196:    char_u *s;
                   2197: {
                   2198:    s = skipwhite(s);
                   2199:    if (STRNCMP(s, "case", 4) == 0 && !isidchar(s[4]))
                   2200:    {
                   2201:        for (s += 4; *s; ++s)
                   2202:            if (*s == ':')
                   2203:            {
                   2204:                if (s[1] == ':')        /* skip over "::" for C++ */
                   2205:                    ++s;
                   2206:                else
                   2207:                    return TRUE;
                   2208:            }
                   2209:        return FALSE;
                   2210:    }
                   2211:
                   2212:    if (isdefault(s))
                   2213:        return TRUE;
                   2214:    return FALSE;
                   2215: }
                   2216:
                   2217: /*
                   2218:  * Recognize a "default" switch label.
                   2219:  */
                   2220:    static int
                   2221: isdefault(s)
                   2222:    char_u  *s;
                   2223: {
                   2224:    return (STRNCMP(s, "default", 7) == 0 &&
                   2225:            *(s = skipwhite(s + 7)) == ':' &&
                   2226:            s[1] != ':');
                   2227: }
                   2228:
                   2229: /*
                   2230:  * Return a pointer to the first non-empty non-comment character after a ':'.
                   2231:  * Return NULL if not found.
                   2232:  *        case 234:    a = b;
                   2233:  *                     ^
                   2234:  */
                   2235:    static char_u *
                   2236: after_label(l)
                   2237:    char_u  *l;
                   2238: {
                   2239:    for ( ; *l; ++l)
                   2240:        if (*l == ':')
                   2241:        {
                   2242:            if (l[1] == ':')        /* skip over "::" for C++ */
                   2243:                ++l;
                   2244:            else
                   2245:                break;
                   2246:        }
                   2247:    if (*l == NUL)
                   2248:        return NULL;
                   2249:    l = skipwhite(l + 1);
                   2250:    if (commentorempty(l))
                   2251:        return NULL;
                   2252:    return l;
                   2253: }
                   2254:
                   2255: /*
                   2256:  * Get indent of line "lnum", skipping a label.
                   2257:  * Return 0 if there is nothing after the label.
                   2258:  */
                   2259:    static int
                   2260: get_indent_nolabel(lnum)               /* XXX */
                   2261:    linenr_t    lnum;
                   2262: {
                   2263:    char_u      *l;
                   2264:    FPOS        fp;
                   2265:    colnr_t     col;
                   2266:    char_u      *p;
                   2267:
                   2268:    l = ml_get(lnum);
                   2269:    p = after_label(l);
                   2270:    if (p == NULL)
                   2271:        return 0;
                   2272:
                   2273:    fp.col = p - l;
                   2274:    fp.lnum = lnum;
                   2275:    getvcol(curwin, &fp, &col, NULL, NULL);
                   2276:    return (int)col;
                   2277: }
                   2278:
                   2279: /*
                   2280:  * Find indent for line "lnum", ignoring any case or jump label.
                   2281:  * Also return a pointer to the text (after the label).
                   2282:  *   label:        if (asdf && asdfasdf)
                   2283:  *              ^
                   2284:  */
                   2285:    static int
                   2286: skip_label(lnum, pp, ind_maxcomment)
                   2287:    linenr_t    lnum;
                   2288:    char_u      **pp;
                   2289:    int         ind_maxcomment;
                   2290: {
                   2291:    char_u      *l;
                   2292:    int         amount;
                   2293:    FPOS        cursor_save;
                   2294:
                   2295:    cursor_save = curwin->w_cursor;
                   2296:    curwin->w_cursor.lnum = lnum;
                   2297:    l = ml_get_curline();
                   2298:    if (iscase(l) || islabel(ind_maxcomment)) /* XXX */
                   2299:    {
                   2300:        amount = get_indent_nolabel(lnum);
                   2301:        l = after_label(ml_get_curline());
                   2302:        if (l == NULL)          /* just in case */
                   2303:            l = ml_get_curline();
                   2304:    }
                   2305:    else
                   2306:    {
                   2307:        amount = get_indent();
                   2308:        l = ml_get_curline();
                   2309:    }
                   2310:    *pp = l;
                   2311:
                   2312:    curwin->w_cursor = cursor_save;
                   2313:    return amount;
                   2314: }
                   2315:
                   2316: /*
                   2317:  * Recognize a preprocessor statement: Any line that starts with '#'.
                   2318:  */
                   2319:    static int
                   2320: ispreproc(s)
                   2321:    char_u *s;
                   2322: {
                   2323:    s = skipwhite(s);
                   2324:    if (*s == '#')
                   2325:        return TRUE;
                   2326:    return 0;
                   2327: }
                   2328:
                   2329: /*
                   2330:  * Recognize the start of a C or C++ comment.
                   2331:  */
                   2332:    static int
                   2333: iscomment(p)
                   2334:    char_u  *p;
                   2335: {
                   2336:    return (p[0] == '/' && (p[1] == '*' || p[1] == '/'));
                   2337: }
                   2338:
                   2339: /*
                   2340:  * Recognize an empty or comment line.
                   2341:  */
                   2342:    static int
                   2343: commentorempty(s)
                   2344:    char_u *s;
                   2345: {
                   2346:    s = skipwhite(s);
                   2347:    if (*s == NUL || iscomment(s))
                   2348:        return TRUE;
                   2349:    return FALSE;
                   2350: }
                   2351:
                   2352: /*
                   2353:  * Recognize a line that starts with '{' or '}', or ends with ';' or '}'.
1.2       downsj   2354:  * Don't consider "} else" a terminated line.
1.1       downsj   2355:  * Also consider a line terminated if it ends in ','.  This is not 100%
                   2356:  * correct, but this mostly means we are in initializations and then it's OK.
                   2357:  */
                   2358:    static int
                   2359: isterminated(s)
                   2360:    char_u *s;
                   2361: {
                   2362:    s = skipwhite(s);
                   2363:
1.2       downsj   2364:    if (*s == '{' || (*s == '}' && !iselse(s)))
1.1       downsj   2365:        return TRUE;
                   2366:
                   2367:    while (*s)
                   2368:    {
                   2369:        if (iscomment(s))       /* at start of comment ignore rest of line */
                   2370:            return FALSE;
                   2371:        s = skip_string(s);
                   2372:        if ((*s == ';' || *s == '{' || *s == ',') && commentorempty(s + 1))
                   2373:            return TRUE;
                   2374:        s++;
                   2375:    }
                   2376:    return FALSE;
                   2377: }
                   2378:
                   2379: /*
                   2380:  * Recognize the basic picture of a function declaration -- it needs to
                   2381:  * have an open paren somewhere and a close paren at the end of the line and
                   2382:  * no semicolons anywhere.
                   2383:  */
                   2384:    static int
                   2385: isfuncdecl(s)
                   2386:    char_u *s;
                   2387: {
                   2388:    while (*s && *s != '(' && *s != ';')
                   2389:        if (iscomment(s++))
                   2390:            return FALSE;           /* comment before () ??? */
                   2391:    if (*s != '(')
                   2392:        return FALSE;               /* ';' before any () or no '(' */
                   2393:
                   2394:    while (*s && *s != ';')
                   2395:    {
                   2396:        if (*s == ')' && commentorempty(s + 1))
                   2397:            return TRUE;
                   2398:        if (iscomment(s++))
                   2399:            return FALSE;           /* comment between ( and ) ??? */
                   2400:    }
                   2401:    return FALSE;
                   2402: }
                   2403:
                   2404: /*
                   2405:  * Skip over a "string" and a 'c' character.
                   2406:  */
                   2407:    static char_u *
                   2408: skip_string(p)
                   2409:    char_u  *p;
                   2410: {
                   2411:    int     i;
                   2412:
                   2413:    /*
                   2414:     * We loop, because strings may be concatenated: "date""time".
                   2415:     */
                   2416:    for ( ; ; ++p)
                   2417:    {
                   2418:        if (p[0] == '\'')                   /* 'c' or '\n' or '\000' */
                   2419:        {
                   2420:            if (!p[1])                      /* ' at end of line */
                   2421:                break;
                   2422:            i = 2;
                   2423:            if (p[1] == '\\')               /* '\n' or '\000' */
                   2424:            {
                   2425:                ++i;
                   2426:                while (isdigit(p[i - 1]))   /* '\000' */
                   2427:                    ++i;
                   2428:            }
                   2429:            if (p[i] == '\'')               /* check for trailing ' */
                   2430:            {
                   2431:                p += i;
                   2432:                continue;
                   2433:            }
                   2434:        }
                   2435:        else if (p[0] == '"')               /* start of string */
                   2436:        {
                   2437:            for (++p; p[0]; ++p)
                   2438:            {
                   2439:                if (p[0] == '\\' && p[1])
                   2440:                    ++p;
                   2441:                else if (p[0] == '"')       /* end of string */
                   2442:                    break;
                   2443:            }
                   2444:            continue;
                   2445:        }
                   2446:        break;                              /* no string found */
                   2447:    }
                   2448:    if (!*p)
                   2449:        --p;                                /* backup from NUL */
                   2450:    return p;
                   2451: }
                   2452:
                   2453:    static int
                   2454: isif(p)
                   2455:    char_u  *p;
                   2456: {
                   2457:    return (STRNCMP(p, "if", 2) == 0 && !isidchar(p[2]));
                   2458: }
                   2459:
                   2460:    static int
                   2461: iselse(p)
                   2462:    char_u  *p;
                   2463: {
1.2       downsj   2464:    if (*p == '}')          /* accept "} else" */
                   2465:        p = skipwhite(p + 1);
1.1       downsj   2466:    return (STRNCMP(p, "else", 4) == 0 && !isidchar(p[4]));
                   2467: }
                   2468:
                   2469:    static int
                   2470: isdo(p)
                   2471:    char_u  *p;
                   2472: {
                   2473:    return (STRNCMP(p, "do", 2) == 0 && !isidchar(p[2]));
                   2474: }
                   2475:
                   2476: /*
                   2477:  * Check if this is a "while" that should have a matching "do".
                   2478:  * We only accept a "while (condition) ;", with only white space between the
                   2479:  * ')' and ';'. The condition may be spread over several lines.
                   2480:  */
                   2481:    static int
                   2482: iswhileofdo(p, lnum, ind_maxparen)         /* XXX */
                   2483:    char_u      *p;
                   2484:    linenr_t    lnum;
                   2485:    int         ind_maxparen;
                   2486: {
                   2487:    FPOS        cursor_save;
                   2488:    FPOS        *trypos;
                   2489:    int         retval = FALSE;
                   2490:
                   2491:    p = skipwhite(p);
1.2       downsj   2492:    if (*p == '}')              /* accept "} while (cond);" */
                   2493:        p = skipwhite(p + 1);
1.1       downsj   2494:    if (STRNCMP(p, "while", 5) == 0 && !isidchar(p[5]))
                   2495:    {
                   2496:        cursor_save = curwin->w_cursor;
                   2497:        curwin->w_cursor.lnum = lnum;
                   2498:        curwin->w_cursor.col = 0;
1.2       downsj   2499:        p = ml_get_curline();
                   2500:        while (*p && *p != 'w') /* skip any '}', until the 'w' of the "while" */
                   2501:        {
                   2502:            ++p;
                   2503:            ++curwin->w_cursor.col;
                   2504:        }
1.1       downsj   2505:        if ((trypos = findmatchlimit(0, 0, ind_maxparen)) != NULL)
                   2506:        {
                   2507:            p = ml_get_pos(trypos) + 1;
                   2508:            p = skipwhite(p);
                   2509:            if (*p == ';')
                   2510:                retval = TRUE;
                   2511:        }
                   2512:        curwin->w_cursor = cursor_save;
                   2513:    }
                   2514:    return retval;
                   2515: }
                   2516:
                   2517: /*
                   2518:  * Find the start of a comment, not knowing if we are in a comment right now.
                   2519:  * Search starts at w_cursor.lnum and goes backwards.
                   2520:  */
                   2521:    static FPOS *
                   2522: find_start_comment(ind_maxcomment)         /* XXX */
                   2523:    int         ind_maxcomment;
                   2524: {
                   2525:    FPOS        *pos;
                   2526:    char_u      *line;
                   2527:    char_u      *p;
                   2528:
                   2529:    if ((pos = findmatchlimit('*', FM_BACKWARD, ind_maxcomment)) == NULL)
                   2530:        return NULL;
                   2531:
                   2532:    /*
                   2533:     * Check if the comment start we found is inside a string.
                   2534:     */
                   2535:    line = ml_get(pos->lnum);
                   2536:    for (p = line; *p && (unsigned)(p - line) < pos->col; ++p)
                   2537:        p = skip_string(p);
                   2538:    if ((unsigned)(p - line) > pos->col)
                   2539:        return NULL;
                   2540:    return pos;
                   2541: }
                   2542:
                   2543: /*
                   2544:  * Find the '{' at the start of the block we are in.
                   2545:  * Return NULL of no match found.
                   2546:  * Ignore a '{' that is in a comment, makes indenting the next three lines
                   2547:  * work. */
                   2548: /* foo()   */
                   2549: /* {       */
                   2550: /* }       */
                   2551:
                   2552:    static FPOS *
                   2553: find_start_brace(ind_maxcomment)           /* XXX */
                   2554:    int         ind_maxcomment;
                   2555: {
                   2556:    FPOS        cursor_save;
                   2557:    FPOS        *trypos;
                   2558:    FPOS        *pos;
                   2559:    static FPOS pos_copy;
                   2560:
                   2561:    cursor_save = curwin->w_cursor;
                   2562:    while ((trypos = findmatchlimit('{', FM_BLOCKSTOP, 0)) != NULL)
                   2563:    {
                   2564:        pos_copy = *trypos;     /* copy FPOS, next findmatch will change it */
                   2565:        trypos = &pos_copy;
                   2566:        curwin->w_cursor = *trypos;
                   2567:        pos = NULL;
                   2568:        if (!iscomment(skipwhite(ml_get(trypos->lnum))) &&
                   2569:                 (pos = find_start_comment(ind_maxcomment)) == NULL) /* XXX */
                   2570:            break;
                   2571:        if (pos != NULL)
                   2572:            curwin->w_cursor.lnum = pos->lnum;
                   2573:    }
                   2574:    curwin->w_cursor = cursor_save;
                   2575:    return trypos;
                   2576: }
                   2577:
                   2578: /*
                   2579:  * Find the matching '(', failing if it is in a comment.
                   2580:  * Return NULL of no match found.
                   2581:  */
                   2582:    static FPOS *
                   2583: find_match_paren(ind_maxparen, ind_maxcomment)     /* XXX */
                   2584:    int         ind_maxparen;
                   2585:    int         ind_maxcomment;
                   2586: {
                   2587:    FPOS        cursor_save;
                   2588:    FPOS        *trypos;
                   2589:    static FPOS pos_copy;
                   2590:
                   2591:    cursor_save = curwin->w_cursor;
                   2592:    if ((trypos = findmatchlimit('(', 0, ind_maxparen)) != NULL)
                   2593:    {
                   2594:        if (iscomment(skipwhite(ml_get(trypos->lnum))))
                   2595:            trypos = NULL;
                   2596:        else
                   2597:        {
                   2598:            pos_copy = *trypos;     /* copy trypos, findmatch will change it */
                   2599:            trypos = &pos_copy;
                   2600:            curwin->w_cursor = *trypos;
                   2601:            if (find_start_comment(ind_maxcomment) != NULL) /* XXX */
                   2602:                trypos = NULL;
                   2603:        }
                   2604:    }
                   2605:    curwin->w_cursor = cursor_save;
                   2606:    return trypos;
                   2607: }
                   2608:
                   2609: /*
                   2610:  * Set w_cursor.col to the column number of the last ')' in line "l".
                   2611:  */
                   2612:    static int
                   2613: find_last_paren(l)
                   2614:    char_u *l;
                   2615: {
                   2616:    int     i;
                   2617:    int     retval = FALSE;
                   2618:
                   2619:    curwin->w_cursor.col = 0;               /* default is start of line */
                   2620:
                   2621:    for (i = 0; l[i]; i++)
                   2622:    {
                   2623:        i = skip_string(l + i) - l;         /* ignore parens in quotes */
                   2624:        if (l[i] == ')')
                   2625:        {
                   2626:            curwin->w_cursor.col = i;
                   2627:            retval = TRUE;
                   2628:        }
                   2629:    }
                   2630:    return retval;
                   2631: }
                   2632:
                   2633:    int
                   2634: get_c_indent()
                   2635: {
                   2636:    /*
                   2637:     * spaces from a block's opening brace the prevailing indent for that
                   2638:     * block should be
                   2639:     */
                   2640:    int ind_level = curbuf->b_p_sw;
                   2641:
                   2642:    /*
                   2643:     * spaces from the edge of the line an open brace that's at the end of a
                   2644:     * line is imagined to be.
                   2645:     */
                   2646:    int ind_open_imag = 0;
                   2647:
                   2648:    /*
                   2649:     * spaces from the prevailing indent for a line that is not precededof by
                   2650:     * an opening brace.
                   2651:     */
                   2652:    int ind_no_brace = 0;
                   2653:
                   2654:    /*
                   2655:     * column where the first { of a function should be located
                   2656:     */
                   2657:    int ind_first_open = 0;
                   2658:
                   2659:    /*
                   2660:     * spaces from the prevailing indent a leftmost open brace should be
                   2661:     * located
                   2662:     */
                   2663:    int ind_open_extra = 0;
                   2664:
                   2665:    /*
                   2666:     * spaces from the matching open brace (real location for one at the left
                   2667:     * edge; imaginary location from one that ends a line) the matching close
                   2668:     * brace should be located
                   2669:     */
                   2670:    int ind_close_extra = 0;
                   2671:
                   2672:    /*
                   2673:     * spaces from the edge of the line an open brace sitting in the leftmost
                   2674:     * column is imagined to be
                   2675:     */
                   2676:    int ind_open_left_imag = 0;
                   2677:
                   2678:    /*
                   2679:     * spaces from the switch() indent a "case xx" label should be located
                   2680:     */
                   2681:    int ind_case = curbuf->b_p_sw;
                   2682:
                   2683:    /*
                   2684:     * spaces from the "case xx:" code after a switch() should be located
                   2685:     */
                   2686:    int ind_case_code = curbuf->b_p_sw;
                   2687:
                   2688:    /*
                   2689:     * amount K&R-style parameters should be indented
                   2690:     */
                   2691:    int ind_param = curbuf->b_p_sw;
                   2692:
                   2693:    /*
                   2694:     * amount a function type spec should be indented
                   2695:     */
                   2696:    int ind_func_type = curbuf->b_p_sw;
                   2697:
                   2698:    /*
                   2699:     * additional spaces beyond the prevailing indent a continuation line
                   2700:     * should be located
                   2701:     */
                   2702:    int ind_continuation = curbuf->b_p_sw;
                   2703:
                   2704:    /*
                   2705:     * spaces from the indent of the line with an unclosed parentheses
                   2706:     */
                   2707:    int ind_unclosed = curbuf->b_p_sw * 2;
                   2708:
                   2709:    /*
                   2710:     * spaces from the comment opener when there is nothing after it.
                   2711:     */
                   2712:    int ind_in_comment = 3;
                   2713:
                   2714:    /*
                   2715:     * max lines to search for an open paren
                   2716:     */
                   2717:    int ind_maxparen = 20;
                   2718:
                   2719:    /*
                   2720:     * max lines to search for an open comment
                   2721:     */
                   2722:    int ind_maxcomment = 30;
                   2723:
                   2724:    FPOS        cur_curpos;
                   2725:    int         amount;
                   2726:    int         scope_amount;
                   2727:    int         cur_amount;
                   2728:    colnr_t     col;
                   2729:    char_u      *theline;
                   2730:    char_u      *linecopy;
                   2731:    FPOS        *trypos;
                   2732:    FPOS        our_paren_pos;
                   2733:    char_u      *start;
                   2734:    int         start_brace;
                   2735: #define BRACE_IN_COL0  1           /* '{' is in comumn 0 */
                   2736: #define BRACE_AT_START 2           /* '{' is at start of line */
                   2737: #define BRACE_AT_END   3           /* '{' is at end of line */
                   2738:    linenr_t    ourscope;
                   2739:    char_u      *l;
                   2740:    char_u      *look;
                   2741:    int         lookfor;
                   2742: #define LOOKFOR_IF     1
                   2743: #define LOOKFOR_DO     2
                   2744: #define LOOKFOR_CASE   3
                   2745: #define LOOKFOR_ANY        4
                   2746: #define LOOKFOR_TERM   5
                   2747: #define LOOKFOR_UNTERM 6
                   2748:    int         whilelevel;
                   2749:    linenr_t    lnum;
                   2750:    char_u      *options;
                   2751:    int         fraction = 0;       /* init for GCC */
                   2752:    int         divider;
                   2753:    int         n;
                   2754:
                   2755:    for (options = curbuf->b_p_cino; *options; )
                   2756:    {
                   2757:        l = options++;
                   2758:        if (*options == '-')
                   2759:            ++options;
                   2760:        n = getdigits(&options);
                   2761:        divider = 0;
                   2762:        if (*options == '.')        /* ".5s" means a fraction */
                   2763:        {
                   2764:            fraction = atol((char *)++options);
                   2765:            while (isdigit(*options))
                   2766:            {
                   2767:                ++options;
                   2768:                if (divider)
                   2769:                    divider *= 10;
                   2770:                else
                   2771:                    divider = 10;
                   2772:            }
                   2773:        }
                   2774:        if (*options == 's')        /* "2s" means two times 'shiftwidth' */
                   2775:        {
                   2776:            if (n == 0 && fraction == 0)
                   2777:                n = curbuf->b_p_sw;     /* just "s" is one 'shiftwidth' */
                   2778:            else
                   2779:            {
                   2780:                n *= curbuf->b_p_sw;
                   2781:                if (divider)
                   2782:                    n += (curbuf->b_p_sw * fraction + divider / 2) / divider;
                   2783:            }
                   2784:            ++options;
                   2785:        }
                   2786:        if (l[1] == '-')
                   2787:            n = -n;
                   2788:        switch (*l)
                   2789:        {
                   2790:            case '>': ind_level = n; break;
                   2791:            case 'e': ind_open_imag = n; break;
                   2792:            case 'n': ind_no_brace = n; break;
                   2793:            case 'f': ind_first_open = n; break;
                   2794:            case '{': ind_open_extra = n; break;
                   2795:            case '}': ind_close_extra = n; break;
                   2796:            case '^': ind_open_left_imag = n; break;
                   2797:            case ':': ind_case = n; break;
                   2798:            case '=': ind_case_code = n; break;
                   2799:            case 'p': ind_param = n; break;
                   2800:            case 't': ind_func_type = n; break;
                   2801:            case 'c': ind_in_comment = n; break;
                   2802:            case '+': ind_continuation = n; break;
                   2803:            case '(': ind_unclosed = n; break;
                   2804:            case ')': ind_maxparen = n; break;
                   2805:            case '*': ind_maxcomment = n; break;
                   2806:        }
                   2807:    }
                   2808:
                   2809:    /* remember where the cursor was when we started */
                   2810:
                   2811:    cur_curpos = curwin->w_cursor;
                   2812:
                   2813:    /* get the current contents of the line.
                   2814:     * This is required, because onle the most recent line obtained with
                   2815:     * ml_get is valid! */
                   2816:
                   2817:    linecopy = strsave(ml_get(cur_curpos.lnum));
                   2818:    if (linecopy == NULL)
                   2819:        return 0;
                   2820:
                   2821:    /*
                   2822:     * In insert mode and the cursor is on a ')' trunctate the line at the
                   2823:     * cursor position.  We don't want to line up with the matching '(' when
                   2824:     * inserting new stuff.
                   2825:     */
                   2826:    if ((State & INSERT) && linecopy[curwin->w_cursor.col] == ')')
                   2827:        linecopy[curwin->w_cursor.col] = NUL;
                   2828:
                   2829:    theline = skipwhite(linecopy);
                   2830:
                   2831:    /* move the cursor to the start of the line */
                   2832:
                   2833:    curwin->w_cursor.col = 0;
                   2834:
                   2835:    /*
                   2836:     * #defines and so on always go at the left when included in 'cinkeys'.
                   2837:     */
                   2838:    if (*theline == '#' && (*linecopy == '#' || in_cinkeys('#', ' ', TRUE)))
                   2839:    {
                   2840:        amount = 0;
                   2841:    }
                   2842:
                   2843:    /*
                   2844:     * Is it a non-case label?  Then that goes at the left margin too.
                   2845:     */
                   2846:    else if (islabel(ind_maxcomment))       /* XXX */
                   2847:    {
                   2848:        amount = 0;
                   2849:    }
                   2850:
                   2851:    /*
                   2852:     * If we're inside a comment and not looking at the start of the
                   2853:     * comment...
                   2854:     */
                   2855:    else if (!iscomment(theline) &&
                   2856:              (trypos = find_start_comment(ind_maxcomment)) != NULL) /* XXX */
                   2857:    {
                   2858:
                   2859:        /* find how indented the line beginning the comment is */
                   2860:        getvcol(curwin, trypos, &col, NULL, NULL);
                   2861:        amount = col;
                   2862:
                   2863:        /* if our line starts with an asterisk, line up with the
                   2864:         * asterisk in the comment opener; otherwise, line up
                   2865:         * with the first character of the comment text.
                   2866:         */
                   2867:        if (theline[0] == '*')
                   2868:        {
                   2869:            amount += 1;
                   2870:        }
                   2871:        else
                   2872:        {
                   2873:            /*
                   2874:             * If we are more than one line away from the comment opener, take
                   2875:             * the indent of the previous non-empty line.
                   2876:             * If we are just below the comment opener and there are any
                   2877:             * white characters after it line up with the text after it.
                   2878:             * up with them; otherwise, just use a single space.
                   2879:             */
                   2880:            amount = -1;
                   2881:            for (lnum = cur_curpos.lnum - 1; lnum > trypos->lnum; --lnum)
                   2882:            {
                   2883:                if (linewhite(lnum))                /* skip blank lines */
                   2884:                    continue;
                   2885:                amount = get_indent_lnum(lnum);     /* XXX */
                   2886:                break;
                   2887:            }
                   2888:            if (amount == -1)                       /* use the comment opener */
                   2889:            {
                   2890:                start = ml_get(trypos->lnum);
                   2891:                look = start + trypos->col + 2;     /* skip / and * */
                   2892:                if (*look)                          /* if something after it */
                   2893:                    trypos->col = skipwhite(look) - start;
                   2894:                getvcol(curwin, trypos, &col, NULL, NULL);
                   2895:                amount = col;
                   2896:                if (!*look)
                   2897:                    amount += ind_in_comment;
                   2898:            }
                   2899:        }
                   2900:    }
                   2901:
                   2902:    /*
                   2903:     * Are we inside parentheses?
                   2904:     */                                             /* XXX */
                   2905:    else if ((trypos = find_match_paren(ind_maxparen, ind_maxcomment)) != NULL)
                   2906:    {
                   2907:        /*
                   2908:         * If the matching paren is more than one line away, use the indent of
                   2909:         * a previous non-empty line that matches the same paren.
                   2910:         */
                   2911:        amount = -1;
                   2912:        our_paren_pos = *trypos;
                   2913:        if (theline[0] != ')')
                   2914:        {
                   2915:            for (lnum = cur_curpos.lnum - 1; lnum > our_paren_pos.lnum; --lnum)
                   2916:            {
                   2917:                l = skipwhite(ml_get(lnum));
                   2918:                if (commentorempty(l))      /* skip comment lines */
                   2919:                    continue;
                   2920:                if (ispreproc(l))           /* ignore #defines, #if, etc. */
                   2921:                    continue;
                   2922:                curwin->w_cursor.lnum = lnum;
                   2923:                /* XXX */
                   2924:                if ((trypos = find_match_paren(ind_maxparen,
                   2925:                                                   ind_maxcomment)) != NULL &&
                   2926:                                         trypos->lnum == our_paren_pos.lnum &&
                   2927:                                             trypos->col == our_paren_pos.col)
                   2928:                {
                   2929:                    amount = get_indent_lnum(lnum);     /* XXX */
                   2930:                    break;
                   2931:                }
                   2932:            }
                   2933:        }
                   2934:
                   2935:        /*
                   2936:         * Line up with line where the matching paren is.
                   2937:         * If the line starts with a '(' or the indent for unclosed
                   2938:         * parentheses is zero, line up with the unclosed parentheses.
                   2939:         */
                   2940:        if (amount == -1)
                   2941:        {
                   2942:            amount = skip_label(our_paren_pos.lnum, &look, ind_maxcomment);
                   2943:            if (theline[0] == ')' || ind_unclosed == 0 ||
                   2944:                                                      *skipwhite(look) == '(')
                   2945:            {
                   2946:
                   2947:                /*
                   2948:                 * If we're looking at a close paren, line up right there;
                   2949:                 * otherwise, line up with the next non-white character.
                   2950:                 */
                   2951:                if (theline[0] != ')')
                   2952:                {
                   2953:                    col = our_paren_pos.col + 1;
                   2954:                    look = ml_get(our_paren_pos.lnum);
                   2955:                    while (vim_iswhite(look[col]))
                   2956:                        col++;
                   2957:                    if (look[col] != NUL)       /* In case of trailing space */
                   2958:                        our_paren_pos.col = col;
                   2959:                    else
                   2960:                        our_paren_pos.col++;
                   2961:                }
                   2962:
                   2963:                /*
                   2964:                 * Find how indented the paren is, or the character after it if
                   2965:                 * we did the above "if".
                   2966:                 */
                   2967:                getvcol(curwin, &our_paren_pos, &col, NULL, NULL);
                   2968:                amount = col;
                   2969:            }
                   2970:            else
                   2971:                amount += ind_unclosed;
                   2972:        }
                   2973:    }
                   2974:
                   2975:    /*
                   2976:     * Are we at least inside braces, then?
                   2977:     */
                   2978:    else if ((trypos = find_start_brace(ind_maxcomment)) != NULL) /* XXX */
                   2979:    {
                   2980:        ourscope = trypos->lnum;
                   2981:        start = ml_get(ourscope);
                   2982:
                   2983:        /*
                   2984:         * Now figure out how indented the line is in general.
                   2985:         * If the brace was at the start of the line, we use that;
                   2986:         * otherwise, check out the indentation of the line as
                   2987:         * a whole and then add the "imaginary indent" to that.
                   2988:         */
                   2989:        look = skipwhite(start);
                   2990:        if (*look == '{')
                   2991:        {
                   2992:            getvcol(curwin, trypos, &col, NULL, NULL);
                   2993:            amount = col;
                   2994:            if (*start == '{')
                   2995:                start_brace = BRACE_IN_COL0;
                   2996:            else
                   2997:                start_brace = BRACE_AT_START;
                   2998:        }
                   2999:        else
                   3000:        {
                   3001:            /*
                   3002:             * that opening brace might have been on a continuation
                   3003:             * line.  if so, find the start of the line.
                   3004:             */
                   3005:            curwin->w_cursor.lnum = ourscope;
                   3006:
                   3007:            /*
                   3008:             * position the cursor over the rightmost paren, so that
                   3009:             * matching it will take us back to the start of the line.
                   3010:             */
                   3011:            lnum = ourscope;
                   3012:            if (find_last_paren(start) &&
                   3013:                    (trypos = find_match_paren(ind_maxparen,
                   3014:                                                     ind_maxcomment)) != NULL)
                   3015:                lnum = trypos->lnum;
                   3016:
                   3017:            /*
                   3018:             * It could have been something like
                   3019:             *     case 1: if (asdf &&
                   3020:             *                  ldfd) {
                   3021:             *              }
                   3022:             */
                   3023:            amount = skip_label(lnum, &l, ind_maxcomment);
                   3024:
                   3025:            start_brace = BRACE_AT_END;
                   3026:        }
                   3027:
                   3028:        /*
                   3029:         * if we're looking at a closing brace, that's where
                   3030:         * we want to be.  otherwise, add the amount of room
                   3031:         * that an indent is supposed to be.
                   3032:         */
                   3033:        if (theline[0] == '}')
                   3034:        {
                   3035:            /*
                   3036:             * they may want closing braces to line up with something
                   3037:             * other than the open brace.  indulge them, if so.
                   3038:             */
                   3039:            amount += ind_close_extra;
                   3040:        }
                   3041:        else
                   3042:        {
                   3043:            /*
                   3044:             * If we're looking at an "else", try to find an "if"
                   3045:             * to match it with.
                   3046:             * If we're looking at a "while", try to find a "do"
                   3047:             * to match it with.
                   3048:             */
                   3049:            lookfor = 0;
                   3050:            if (iselse(theline))
                   3051:                lookfor = LOOKFOR_IF;
                   3052:            else if (iswhileofdo(theline, cur_curpos.lnum, ind_maxparen))
                   3053:                                                                    /* XXX */
                   3054:                lookfor = LOOKFOR_DO;
                   3055:            if (lookfor)
                   3056:            {
                   3057:                curwin->w_cursor.lnum = cur_curpos.lnum;
                   3058:                if (find_match(lookfor, ourscope, ind_maxparen,
                   3059:                                                        ind_maxcomment) == OK)
                   3060:                {
                   3061:                    amount = get_indent();      /* XXX */
                   3062:                    goto theend;
                   3063:                }
                   3064:            }
                   3065:
                   3066:            /*
                   3067:             * We get here if we are not on an "while-of-do" or "else" (or
                   3068:             * failed to find a matching "if").
                   3069:             * Search backwards for something to line up with.
                   3070:             * First set amount for when we don't find anything.
                   3071:             */
                   3072:
                   3073:            /*
                   3074:             * if the '{' is  _really_ at the left margin, use the imaginary
                   3075:             * location of a left-margin brace.  Otherwise, correct the
                   3076:             * location for ind_open_extra.
                   3077:             */
                   3078:
                   3079:            if (start_brace == BRACE_IN_COL0)       /* '{' is in column 0 */
                   3080:            {
                   3081:                amount = ind_open_left_imag;
                   3082:            }
                   3083:            else
                   3084:            {
                   3085:                if (start_brace == BRACE_AT_END)    /* '{' is at end of line */
                   3086:                    amount += ind_open_imag;
                   3087:                else
                   3088:                {
                   3089:                    amount -= ind_open_extra;
                   3090:                    if (amount < 0)
                   3091:                        amount = 0;
                   3092:                }
                   3093:            }
                   3094:
                   3095:            if (iscase(theline))        /* it's a switch() label */
                   3096:            {
                   3097:                lookfor = LOOKFOR_CASE; /* find a previous switch() label */
                   3098:                amount += ind_case;
                   3099:            }
                   3100:            else
                   3101:            {
                   3102:                lookfor = LOOKFOR_ANY;
                   3103:                amount += ind_level;    /* ind_level from start of block */
                   3104:            }
                   3105:            scope_amount = amount;
                   3106:            whilelevel = 0;
                   3107:
                   3108:            /*
                   3109:             * Search backwards.  If we find something we recognize, line up
                   3110:             * with that.
                   3111:             *
                   3112:             * if we're looking at an open brace, indent
                   3113:             * the usual amount relative to the conditional
                   3114:             * that opens the block.
                   3115:             */
                   3116:            curwin->w_cursor = cur_curpos;
                   3117:            for (;;)
                   3118:            {
                   3119:                curwin->w_cursor.lnum--;
                   3120:                curwin->w_cursor.col = 0;
                   3121:
                   3122:                /*
                   3123:                 * If we went all the way back to the start of our scope, line
                   3124:                 * up with it.
                   3125:                 */
                   3126:                if (curwin->w_cursor.lnum <= ourscope)
                   3127:                {
                   3128:                    if (lookfor == LOOKFOR_UNTERM)
                   3129:                        amount += ind_continuation;
                   3130:                    else if (lookfor != LOOKFOR_TERM)
                   3131:                        amount = scope_amount;
                   3132:                    break;
                   3133:                }
                   3134:
                   3135:                /*
                   3136:                 * If we're in a comment now, skip to the start of the comment.
                   3137:                 */                                         /* XXX */
                   3138:                if ((trypos = find_start_comment(ind_maxcomment)) != NULL)
                   3139:                {
                   3140:                    curwin->w_cursor.lnum = trypos->lnum + 1;
                   3141:                    continue;
                   3142:                }
                   3143:
                   3144:                l = ml_get_curline();
                   3145:
                   3146:                /*
                   3147:                 * If this is a switch() label, may line up relative to that.
                   3148:                 */
                   3149:                if (iscase(l))
                   3150:                {
                   3151:                    /*
                   3152:                     *  case xx:
                   3153:                     *      c = 99 +        <- this indent plus continuation
                   3154:                     *->           here;
                   3155:                     */
                   3156:                    if (lookfor == LOOKFOR_UNTERM)
                   3157:                    {
                   3158:                        amount += ind_continuation;
                   3159:                        break;
                   3160:                    }
                   3161:
                   3162:                    /*
                   3163:                     *  case xx:        <- line up with this case
                   3164:                     *      x = 333;
                   3165:                     *  case yy:
                   3166:                     */
                   3167:                    if (lookfor == LOOKFOR_CASE)
                   3168:                    {
                   3169:                        /*
                   3170:                         * Check that this case label is not for another
                   3171:                         * switch()
                   3172:                         */                                 /* XXX */
                   3173:                        if ((trypos = find_start_brace(ind_maxcomment)) ==
                   3174:                                             NULL || trypos->lnum == ourscope)
                   3175:                        {
                   3176:                            amount = get_indent();      /* XXX */
                   3177:                            break;
                   3178:                        }
                   3179:                        continue;
                   3180:                    }
                   3181:
                   3182:                    n = get_indent_nolabel(curwin->w_cursor.lnum);  /* XXX */
                   3183:
                   3184:                    /*
                   3185:                     *   case xx: if (cond)         <- line up with this if
                   3186:                     *                y = y + 1;
                   3187:                     * ->         s = 99;
                   3188:                     *
                   3189:                     *   case xx:
                   3190:                     *       if (cond)          <- line up with this line
                   3191:                     *           y = y + 1;
                   3192:                     * ->    s = 99;
                   3193:                     */
                   3194:                    if (lookfor == LOOKFOR_TERM)
                   3195:                    {
                   3196:                        if (n)
                   3197:                            amount = n;
                   3198:                        break;
                   3199:                    }
                   3200:
                   3201:                    /*
                   3202:                     *   case xx: x = x + 1;        <- line up with this x
                   3203:                     * ->         y = y + 1;
                   3204:                     *
                   3205:                     *   case xx: if (cond)         <- line up with this if
                   3206:                     * ->              y = y + 1;
                   3207:                     */
                   3208:                    if (n)
                   3209:                    {
                   3210:                        amount = n;
                   3211:                        l = after_label(ml_get_curline());
                   3212:                        if (l != NULL && is_cinword(l))
                   3213:                            amount += ind_level + ind_no_brace;
                   3214:                        break;
                   3215:                    }
                   3216:
                   3217:                    /*
                   3218:                     *   Try to get the indent of a statement before the
                   3219:                     *   switch label.  If nothing is found, line up relative
                   3220:                     *   to the switch label.
                   3221:                     *      break;              <- may line up with this line
                   3222:                     *   case xx:
                   3223:                     * ->   y = 1;
                   3224:                     */
                   3225:                    scope_amount = get_indent() + ind_case_code;    /* XXX */
                   3226:                    lookfor = LOOKFOR_ANY;
                   3227:                    continue;
                   3228:                }
                   3229:
                   3230:                /*
                   3231:                 * Looking for a switch() label, ignore other lines.
                   3232:                 */
                   3233:                if (lookfor == LOOKFOR_CASE)
                   3234:                    continue;
                   3235:
                   3236:                /*
                   3237:                 * Ignore jump labels with nothing after them.
                   3238:                 */
                   3239:                if (islabel(ind_maxcomment))
                   3240:                {
                   3241:                    l = after_label(ml_get_curline());
                   3242:                    if (l == NULL || commentorempty(l))
                   3243:                        continue;
                   3244:                }
                   3245:
                   3246:                /*
                   3247:                 * Ignore #defines, #if, etc.
                   3248:                 * Ignore comment and empty lines.
                   3249:                 * (need to get the line again, islabel() may have unlocked it)
                   3250:                 */
                   3251:                l = ml_get_curline();
                   3252:                if (ispreproc(l) || commentorempty(l))
                   3253:                    continue;
                   3254:
                   3255:                /*
                   3256:                 * What happens next depends on the line being terminated.
                   3257:                 */
                   3258:                if (!isterminated(l))
                   3259:                {
                   3260:                    /*
                   3261:                     * if we're in the middle of a paren thing,
                   3262:                     * go back to the line that starts it so
                   3263:                     * we can get the right prevailing indent
                   3264:                     *     if ( foo &&
                   3265:                     *              bar )
                   3266:                     */
                   3267:                    /*
                   3268:                     * position the cursor over the rightmost paren, so that
                   3269:                     * matching it will take us back to the start of the line.
                   3270:                     */
                   3271:                    (void)find_last_paren(l);
                   3272:                    if ((trypos = find_match_paren(ind_maxparen,
                   3273:                                                     ind_maxcomment)) != NULL)
                   3274:                    {
                   3275:                        /*
                   3276:                         * Check if we are on a case label now.  This is
                   3277:                         * handled above.
                   3278:                         *     case xx:  if ( asdf &&
                   3279:                         *                      asdf)
                   3280:                         */
                   3281:                        curwin->w_cursor.lnum = trypos->lnum;
                   3282:                        l = ml_get_curline();
                   3283:                        if (iscase(l))
                   3284:                        {
                   3285:                            ++curwin->w_cursor.lnum;
                   3286:                            continue;
                   3287:                        }
                   3288:                    }
                   3289:
                   3290:                    /*
                   3291:                     * Get indent and pointer to text for current line,
                   3292:                     * ignoring any jump label.     XXX
                   3293:                     */
                   3294:                    cur_amount = skip_label(curwin->w_cursor.lnum,
                   3295:                                                          &l, ind_maxcomment);
                   3296:
                   3297:                    /*
                   3298:                     * If this is just above the line we are indenting, and it
                   3299:                     * starts with a '{', line it up with this line.
                   3300:                     *          while (not)
                   3301:                     * ->       {
                   3302:                     *          }
                   3303:                     */
                   3304:                    if (lookfor != LOOKFOR_TERM && theline[0] == '{')
                   3305:                    {
                   3306:                        amount = cur_amount + ind_open_extra;
                   3307:                        break;
                   3308:                    }
                   3309:
                   3310:                    /*
                   3311:                     * Check if we are after an "if", "while", etc.
1.2       downsj   3312:                     * Also allow "} else".
1.1       downsj   3313:                     */
1.2       downsj   3314:                    if (is_cinword(l) || iselse(l))
1.1       downsj   3315:                    {
                   3316:                        /*
                   3317:                         * Found an unterminated line after an if (), line up
                   3318:                         * with the last one.
                   3319:                         *   if (cond)
                   3320:                         *          100 +
                   3321:                         * ->           here;
                   3322:                         */
                   3323:                        if (lookfor == LOOKFOR_UNTERM)
                   3324:                        {
                   3325:                            amount += ind_continuation;
                   3326:                            break;
                   3327:                        }
                   3328:
                   3329:                        /*
                   3330:                         * If this is just above the line we are indenting, we
                   3331:                         * are finished.
                   3332:                         *          while (not)
                   3333:                         * ->           here;
                   3334:                         * Otherwise this indent can be used when the line
                   3335:                         * before this is terminated.
                   3336:                         *      yyy;
                   3337:                         *      if (stat)
                   3338:                         *          while (not)
                   3339:                         *              xxx;
                   3340:                         * ->   here;
                   3341:                         */
                   3342:                        amount = cur_amount;
                   3343:                        if (lookfor != LOOKFOR_TERM)
                   3344:                        {
                   3345:                            amount += ind_level + ind_no_brace;
                   3346:                            break;
                   3347:                        }
                   3348:
                   3349:                        /*
                   3350:                         * Special trick: when expecting the while () after a
                   3351:                         * do, line up with the while()
                   3352:                         *     do
                   3353:                         *          x = 1;
                   3354:                         * ->  here
                   3355:                         */
                   3356:                        l = skipwhite(ml_get_curline());
                   3357:                        if (isdo(l))
                   3358:                        {
                   3359:                            if (whilelevel == 0)
                   3360:                                break;
                   3361:                            --whilelevel;
                   3362:                        }
                   3363:
                   3364:                        /*
                   3365:                         * When searching for a terminated line, don't use the
                   3366:                         * one between the "if" and the "else".
                   3367:                         */
                   3368:                        if (iselse(l))
                   3369:                        {
                   3370:                            if (find_match(LOOKFOR_IF, ourscope,
                   3371:                                        ind_maxparen, ind_maxcomment) == FAIL)
                   3372:                                break;
                   3373:                        }
                   3374:                    }
                   3375:
                   3376:                    /*
                   3377:                     * If we're below an unterminated line that is not an
                   3378:                     * "if" or something, we may line up with this line or
                   3379:                     * add someting for a continuation line, depending on
                   3380:                     * the line before this one.
                   3381:                     */
                   3382:                    else
                   3383:                    {
                   3384:                        /*
                   3385:                         * Found two unterminated lines on a row, line up with
                   3386:                         * the last one.
                   3387:                         *   c = 99 +
                   3388:                         *          100 +
                   3389:                         * ->       here;
                   3390:                         */
                   3391:                        if (lookfor == LOOKFOR_UNTERM)
                   3392:                            break;
                   3393:
                   3394:                        /*
                   3395:                         * Found first unterminated line on a row, may line up
                   3396:                         * with this line, remember its indent
                   3397:                         *          100 +
                   3398:                         * ->       here;
                   3399:                         */
                   3400:                        amount = cur_amount;
                   3401:                        if (lookfor != LOOKFOR_TERM)
                   3402:                            lookfor = LOOKFOR_UNTERM;
                   3403:                    }
                   3404:                }
                   3405:
                   3406:                /*
                   3407:                 * Check if we are after a while (cond);
1.2       downsj   3408:                 * If so: Ignore until the matching "do".
1.1       downsj   3409:                 */
                   3410:                                                        /* XXX */
                   3411:                else if (iswhileofdo(l, curwin->w_cursor.lnum, ind_maxparen))
                   3412:                {
                   3413:                    /*
                   3414:                     * Found an unterminated line after a while ();, line up
                   3415:                     * with the last one.
                   3416:                     *      while (cond);
                   3417:                     *      100 +               <- line up with this one
                   3418:                     * ->           here;
                   3419:                     */
                   3420:                    if (lookfor == LOOKFOR_UNTERM)
                   3421:                    {
                   3422:                        amount += ind_continuation;
                   3423:                        break;
                   3424:                    }
                   3425:
                   3426:                    if (whilelevel == 0)
                   3427:                    {
                   3428:                        lookfor = LOOKFOR_TERM;
                   3429:                        amount = get_indent();      /* XXX */
                   3430:                        if (theline[0] == '{')
                   3431:                            amount += ind_open_extra;
                   3432:                    }
                   3433:                    ++whilelevel;
                   3434:                }
                   3435:
                   3436:                /*
                   3437:                 * We are after a "normal" statement.
                   3438:                 * If we had another statement we can stop now and use the
                   3439:                 * indent of that other statement.
                   3440:                 * Otherwise the indent of the current statement may be used,
                   3441:                 * search backwards for the next "normal" statement.
                   3442:                 */
                   3443:                else
                   3444:                {
                   3445:                    /*
                   3446:                     * Found a terminated line above an unterminated line. Add
                   3447:                     * the amount for a continuation line.
                   3448:                     *   x = 1;
                   3449:                     *   y = foo +
                   3450:                     * ->       here;
                   3451:                     */
                   3452:                    if (lookfor == LOOKFOR_UNTERM)
                   3453:                    {
                   3454:                        amount += ind_continuation;
                   3455:                        break;
                   3456:                    }
                   3457:
                   3458:                    /*
                   3459:                     * Found a terminated line above a terminated line or "if"
                   3460:                     * etc. line. Use the amount of the line below us.
                   3461:                     *   x = 1;                         x = 1;
                   3462:                     *   if (asdf)                  y = 2;
                   3463:                     *       while (asdf)         ->here;
                   3464:                     *          here;
                   3465:                     * ->foo;
                   3466:                     */
                   3467:                    if (lookfor == LOOKFOR_TERM)
                   3468:                    {
                   3469:                        if (whilelevel == 0)
                   3470:                            break;
                   3471:                    }
                   3472:
                   3473:                    /*
                   3474:                     * First line above the one we're indenting is terminated.
                   3475:                     * To know what needs to be done look further backward for
                   3476:                     * a terminated line.
                   3477:                     */
                   3478:                    else
                   3479:                    {
                   3480:                        /*
                   3481:                         * position the cursor over the rightmost paren, so
                   3482:                         * that matching it will take us back to the start of
                   3483:                         * the line.  Helps for:
                   3484:                         *     func(asdr,
                   3485:                         *            asdfasdf);
                   3486:                         *     here;
                   3487:                         */
                   3488:                        l = ml_get_curline();
                   3489:                        if (find_last_paren(l) &&
                   3490:                                (trypos = find_match_paren(ind_maxparen,
                   3491:                                                     ind_maxcomment)) != NULL)
                   3492:                        {
                   3493:                            /*
                   3494:                             * Check if we are on a case label now.  This is
                   3495:                             * handled above.
                   3496:                             *     case xx:  if ( asdf &&
                   3497:                             *                      asdf)
                   3498:                             */
                   3499:                            curwin->w_cursor.lnum = trypos->lnum;
                   3500:                            l = ml_get_curline();
                   3501:                            if (iscase(l))
                   3502:                            {
                   3503:                                ++curwin->w_cursor.lnum;
                   3504:                                continue;
                   3505:                            }
                   3506:                        }
                   3507:
                   3508:                        /*
                   3509:                         * Get indent and pointer to text for current line,
                   3510:                         * ignoring any jump label.
                   3511:                         */
                   3512:                        amount = skip_label(curwin->w_cursor.lnum,
                   3513:                                                          &l, ind_maxcomment);
                   3514:
                   3515:                        if (theline[0] == '{')
                   3516:                            amount += ind_open_extra;
                   3517:                        lookfor = LOOKFOR_TERM;
                   3518:
                   3519:                        /*
                   3520:                         * If we're at the end of a block, skip to the start of
                   3521:                         * that block.
                   3522:                         */
                   3523:                        if (*skipwhite(l) == '}' &&
                   3524:                                   (trypos = find_start_brace(ind_maxcomment))
                   3525:                                                            != NULL) /* XXX */
                   3526:                            curwin->w_cursor.lnum = trypos->lnum;
                   3527:                    }
                   3528:                }
                   3529:            }
                   3530:        }
                   3531:    }
                   3532:
                   3533:    /*
                   3534:     * ok -- we're not inside any sort of structure at all!
                   3535:     *
                   3536:     * this means we're at the top level, and everything should
                   3537:     * basically just match where the previous line is, except
                   3538:     * for the lines immediately following a function declaration,
                   3539:     * which are K&R-style parameters and need to be indented.
                   3540:     */
                   3541:    else
                   3542:    {
                   3543:        /*
                   3544:         * if our line starts with an open brace, forget about any
                   3545:         * prevailing indent and make sure it looks like the start
                   3546:         * of a function
                   3547:         */
                   3548:
                   3549:        if (theline[0] == '{')
                   3550:        {
                   3551:            amount = ind_first_open;
                   3552:        }
                   3553:
                   3554:        /*
                   3555:         * If the NEXT line is a function declaration, the current
                   3556:         * line needs to be indented as a function type spec.
                   3557:         * Don't do this if the current line looks like a comment.
                   3558:         */
                   3559:        else if (cur_curpos.lnum < curbuf->b_ml.ml_line_count &&
                   3560:                                                   !commentorempty(theline) &&
                   3561:                                      isfuncdecl(ml_get(cur_curpos.lnum + 1)))
                   3562:        {
                   3563:            amount = ind_func_type;
                   3564:        }
                   3565:        else
                   3566:        {
                   3567:            amount = 0;
                   3568:            curwin->w_cursor = cur_curpos;
                   3569:
                   3570:            /* search backwards until we find something we recognize */
                   3571:
                   3572:            while (curwin->w_cursor.lnum > 1)
                   3573:            {
                   3574:                curwin->w_cursor.lnum--;
                   3575:                curwin->w_cursor.col = 0;
                   3576:
                   3577:                l = ml_get_curline();
                   3578:
                   3579:                /*
                   3580:                 * If we're in a comment now, skip to the start of the comment.
                   3581:                 */                                             /* XXX */
                   3582:                if ((trypos = find_start_comment(ind_maxcomment)) != NULL)
                   3583:                {
                   3584:                    curwin->w_cursor.lnum = trypos->lnum + 1;
                   3585:                    continue;
                   3586:                }
                   3587:
                   3588:                /*
                   3589:                 * If the line looks like a function declaration, and we're
                   3590:                 * not in a comment, put it the left margin.
                   3591:                 */
                   3592:                if (isfuncdecl(theline))
                   3593:                    break;
                   3594:
                   3595:                /*
                   3596:                 * Skip preprocessor directives and blank lines.
                   3597:                 */
                   3598:                if (ispreproc(l))
                   3599:                    continue;
                   3600:
                   3601:                if (commentorempty(l))
                   3602:                    continue;
                   3603:
                   3604:                /*
                   3605:                 * If the PREVIOUS line is a function declaration, the current
                   3606:                 * line (and the ones that follow) needs to be indented as
                   3607:                 * parameters.
                   3608:                 */
                   3609:                if (isfuncdecl(l))
                   3610:                {
                   3611:                    amount = ind_param;
                   3612:                    break;
                   3613:                }
                   3614:
                   3615:                /*
                   3616:                 * Doesn't look like anything interesting -- so just
                   3617:                 * use the indent of this line.
                   3618:                 *
                   3619:                 * Position the cursor over the rightmost paren, so that
                   3620:                 * matching it will take us back to the start of the line.
                   3621:                 */
                   3622:                find_last_paren(l);
                   3623:
                   3624:                if ((trypos = find_match_paren(ind_maxparen,
                   3625:                                                     ind_maxcomment)) != NULL)
                   3626:                    curwin->w_cursor.lnum = trypos->lnum;
                   3627:                amount = get_indent();      /* XXX */
                   3628:                break;
                   3629:            }
                   3630:        }
                   3631:    }
                   3632:
                   3633: theend:
                   3634:    /* put the cursor back where it belongs */
                   3635:    curwin->w_cursor = cur_curpos;
                   3636:
                   3637:    vim_free(linecopy);
                   3638:
                   3639:    if (amount < 0)
                   3640:        return 0;
                   3641:    return amount;
                   3642: }
                   3643:
                   3644:    static int
                   3645: find_match(lookfor, ourscope, ind_maxparen, ind_maxcomment)
                   3646:    int         lookfor;
                   3647:    linenr_t    ourscope;
                   3648:    int         ind_maxparen;
                   3649:    int         ind_maxcomment;
                   3650: {
                   3651:    char_u      *look;
                   3652:    FPOS        *theirscope;
                   3653:    char_u      *mightbeif;
                   3654:    int         elselevel;
                   3655:    int         whilelevel;
                   3656:
                   3657:    if (lookfor == LOOKFOR_IF)
                   3658:    {
                   3659:        elselevel = 1;
                   3660:        whilelevel = 0;
                   3661:    }
                   3662:    else
                   3663:    {
                   3664:        elselevel = 0;
                   3665:        whilelevel = 1;
                   3666:    }
                   3667:
                   3668:    curwin->w_cursor.col = 0;
                   3669:
                   3670:    while (curwin->w_cursor.lnum > ourscope + 1)
                   3671:    {
                   3672:        curwin->w_cursor.lnum--;
                   3673:        curwin->w_cursor.col = 0;
                   3674:
                   3675:        look = skipwhite(ml_get_curline());
                   3676:        if (iselse(look) || isif(look) || isdo(look) ||
                   3677:             iswhileofdo(look, curwin->w_cursor.lnum, ind_maxparen))  /* XXX */
                   3678:        {
                   3679:            /*
                   3680:             * if we've gone outside the braces entirely,
                   3681:             * we must be out of scope...
                   3682:             */
                   3683:            theirscope = find_start_brace(ind_maxcomment);  /* XXX */
                   3684:            if (theirscope == NULL)
                   3685:                break;
                   3686:
                   3687:            /*
                   3688:             * and if the brace enclosing this is further
                   3689:             * back than the one enclosing the else, we're
                   3690:             * out of luck too.
                   3691:             */
                   3692:            if (theirscope->lnum < ourscope)
                   3693:                break;
                   3694:
                   3695:            /*
                   3696:             * and if they're enclosed in a *deeper* brace,
                   3697:             * then we can ignore it because it's in a
                   3698:             * different scope...
                   3699:             */
                   3700:            if (theirscope->lnum > ourscope)
                   3701:                continue;
                   3702:
                   3703:            /*
                   3704:             * if it was an "else" (that's not an "else if")
                   3705:             * then we need to go back to another if, so
                   3706:             * increment elselevel
                   3707:             */
                   3708:            look = skipwhite(ml_get_curline());
                   3709:            if (iselse(look))
                   3710:            {
                   3711:                mightbeif = skipwhite(look + 4);
                   3712:                if (!isif(mightbeif))
                   3713:                    ++elselevel;
                   3714:                continue;
                   3715:            }
                   3716:
                   3717:            /*
                   3718:             * if it was a "while" then we need to go back to
                   3719:             * another "do", so increment whilelevel.
                   3720:             */
                   3721:            if (iswhileofdo(look, curwin->w_cursor.lnum, ind_maxparen))/* XXX */
                   3722:            {
                   3723:                ++whilelevel;
                   3724:                continue;
                   3725:            }
                   3726:
                   3727:            /* If it's an "if" decrement elselevel */
                   3728:            look = skipwhite(ml_get_curline());
                   3729:            if (isif(look))
                   3730:            {
                   3731:                elselevel--;
                   3732:                /*
                   3733:                 * When looking for an "if" ignore "while"s that
                   3734:                 * get in the way.
                   3735:                 */
                   3736:                if (elselevel == 0 && lookfor == LOOKFOR_IF)
                   3737:                    whilelevel = 0;
                   3738:            }
                   3739:
                   3740:            /* If it's a "do" decrement whilelevel */
                   3741:            if (isdo(look))
                   3742:                whilelevel--;
                   3743:
                   3744:            /*
                   3745:             * if we've used up all the elses, then
                   3746:             * this must be the if that we want!
                   3747:             * match the indent level of that if.
                   3748:             */
                   3749:            if (elselevel <= 0 && whilelevel <= 0)
                   3750:            {
                   3751:                return OK;
                   3752:            }
                   3753:        }
                   3754:    }
                   3755:    return FAIL;
                   3756: }
                   3757:
                   3758: #endif /* CINDENT */
                   3759:
                   3760: #ifdef LISPINDENT
                   3761:    int
                   3762: get_lisp_indent()
                   3763: {
                   3764:    FPOS        *pos, realpos;
                   3765:    long        amount = 0;
                   3766:    char_u      *that;
                   3767:    colnr_t     col;
                   3768:    colnr_t     maybe;
                   3769:    colnr_t     firsttry;
                   3770:
                   3771:
                   3772:    realpos = curwin->w_cursor;
                   3773:    curwin->w_cursor.col = 0;
                   3774:
                   3775:    if ((pos = findmatch('(')) != NULL)
                   3776:    {
                   3777:        curwin->w_cursor.lnum = pos->lnum;
                   3778:        curwin->w_cursor.col = pos->col;
                   3779:        col = pos->col;
                   3780:
                   3781:        that = ml_get_curline();
                   3782:        maybe = get_indent();       /* XXX */
                   3783:
                   3784:        if (maybe == 0)
                   3785:            amount = 2;
                   3786:        else
                   3787:        {
                   3788:            while (*that && col)
                   3789:            {
                   3790:                amount += lbr_chartabsize(that, (colnr_t)amount);
                   3791:                col--;
                   3792:                that++;
                   3793:            }
                   3794:
                   3795:            that++;
                   3796:            amount++;
                   3797:            firsttry = amount;
                   3798:
                   3799:            /*
                   3800:             * Go to the start of the second word.
                   3801:             * If there is no second word, go back to firsttry.
                   3802:             * Also stop at a '('.
                   3803:             */
                   3804:
                   3805:            while (vim_iswhite(*that))
                   3806:            {
                   3807:                amount += lbr_chartabsize(that, (colnr_t)amount);
                   3808:                that++;
                   3809:            }
                   3810:            while (*that && !vim_iswhite(*that) && *that != '(')
                   3811:            {
                   3812:                amount += lbr_chartabsize(that, (colnr_t)amount);
                   3813:                that++;
                   3814:            }
                   3815:            while (vim_iswhite(*that))
                   3816:            {
                   3817:                amount += lbr_chartabsize(that, (colnr_t)amount);
                   3818:                that++;
                   3819:            }
                   3820:            if (! *that)
                   3821:                amount = firsttry;
                   3822:        }
                   3823:    }
                   3824:    else    /* no matching '(' found, use indent of previous non-empty line */
                   3825:    {
                   3826:        while (curwin->w_cursor.lnum > 1)
                   3827:        {
                   3828:            --curwin->w_cursor.lnum;
                   3829:            if (!linewhite(curwin->w_cursor.lnum))
                   3830:                break;
                   3831:        }
                   3832:        amount = get_indent();      /* XXX */
                   3833:    }
                   3834:
                   3835:    curwin->w_cursor = realpos;
                   3836:
                   3837:    if (amount < 0)
                   3838:        amount = 0;
                   3839:    return (int)amount;
                   3840: }
                   3841: #endif /* LISPINDENT */
                   3842:
                   3843: #if defined(UNIX) || defined(WIN32) || defined(__EMX__)
                   3844: /*
                   3845:  * Preserve files and exit.
                   3846:  * When called IObuff must contain a message.
                   3847:  */
                   3848:    void
                   3849: preserve_exit()
                   3850: {
                   3851:    BUF     *buf;
                   3852:
                   3853: #ifdef USE_GUI
                   3854:    if (gui.in_use)
                   3855:    {
                   3856:        gui.dying = TRUE;
                   3857:        trash_output_buf();     /* trash any pending output */
                   3858:    }
                   3859:    else
                   3860: #endif
                   3861:    {
                   3862:        windgoto((int)Rows - 1, 0);
                   3863:
                   3864:        /*
                   3865:         * Switch terminal mode back now, so these messages end up on the
                   3866:         * "normal" screen (if there are two screens).
                   3867:         */
                   3868:        settmode(0);
                   3869: #ifdef WIN32
                   3870:        if (can_end_termcap_mode(FALSE) == TRUE)
                   3871: #endif
                   3872:            stoptermcap();
                   3873:        flushbuf();
                   3874:    }
                   3875:
                   3876:    outstr(IObuff);
                   3877:    screen_start();                 /* don't know where cursor is now */
                   3878:    flushbuf();
                   3879:
                   3880:    ml_close_notmod();              /* close all not-modified buffers */
                   3881:
                   3882:    for (buf = firstbuf; buf != NULL; buf = buf->b_next)
                   3883:    {
                   3884:        if (buf->b_ml.ml_mfp != NULL && buf->b_ml.ml_mfp->mf_fname != NULL)
                   3885:        {
                   3886:            OUTSTR("Vim: preserving files...\n");
                   3887:            screen_start();         /* don't know where cursor is now */
                   3888:            flushbuf();
                   3889:            ml_sync_all(FALSE, FALSE);  /* preserve all swap files */
                   3890:            break;
                   3891:        }
                   3892:    }
                   3893:
                   3894:    ml_close_all(FALSE);            /* close all memfiles, without deleting */
                   3895:
                   3896:    OUTSTR("Vim: Finished.\n");
                   3897:
                   3898:    getout(1);
                   3899: }
                   3900: #endif /* defined(UNIX) || defined(WIN32) || defined(__EMX__) */
                   3901:
                   3902: /*
                   3903:  * return TRUE if "fname" exists.
                   3904:  */
                   3905:    int
                   3906: vim_fexists(fname)
                   3907:    char_u  *fname;
                   3908: {
                   3909:    struct stat st;
                   3910:
                   3911:    if (stat((char *)fname, &st))
                   3912:        return FALSE;
                   3913:    return TRUE;
                   3914: }
                   3915:
                   3916: /*
                   3917:  * Check for CTRL-C pressed, but only once in a while.
                   3918:  * Should be used instead of mch_breakcheck() for functions that check for
                   3919:  * each line in the file.  Calling mch_breakcheck() each time takes too much
                   3920:  * time, because it can be a system call.
                   3921:  */
                   3922:
                   3923: #ifndef BREAKCHECK_SKIP
                   3924: # define BREAKCHECK_SKIP 32
                   3925: #endif
                   3926:
                   3927:    void
                   3928: line_breakcheck()
                   3929: {
                   3930:    static int  count = 0;
                   3931:
                   3932:    if (++count == BREAKCHECK_SKIP)
                   3933:    {
                   3934:        count = 0;
                   3935:        mch_breakcheck();
                   3936:    }
                   3937: }
                   3938:
                   3939: /*
                   3940:  * Free the list of files returned by ExpandWildCards() or other expansion
                   3941:  * functions.
                   3942:  */
                   3943:    void
                   3944: FreeWild(num, file)
                   3945:    int     num;
                   3946:    char_u  **file;
                   3947: {
                   3948:    if (file == NULL || num == 0)
                   3949:        return;
                   3950: #if defined(__EMX__) && defined(__ALWAYS_HAS_TRAILING_NULL_POINTER) /* XXX */
                   3951:    /*
                   3952:     * Is this still OK for when other functions thatn ExpandWildCards() have
                   3953:     * been used???
                   3954:     */
                   3955:    _fnexplodefree((char **)file);
                   3956: #else
                   3957:    while (num--)
                   3958:        vim_free(file[num]);
                   3959:    vim_free(file);
                   3960: #endif
                   3961: }
                   3962: