Exemplo n.º 1
0
/*
 * insertTextOnOtherLine - open up a different line
 */
static vi_rc insertTextOnOtherLine( insert_dir type )
{
    char        *buffx;
    int         i, j;
    linenum     a, b;
    bool        above_line = FALSE;
    vi_rc       rc;

    rc = ModificationTest();
    if( rc != ERR_NO_ERR ) {
        return( rc );
    }
    /*
     * special case: no data in file
     */
    if( CurrentFcb->nullfcb ) {
        return( InsertTextAfterCursor() );
    }

    /*
     * get line deletion and undo crap
     */
    a = b = CurrentPos.line + 1;
    if( type == INSERT_BEFORE ) {
        a--;
        b--;
        above_line = TRUE;
    }

    /*
     * set up for undo
     */
    StartUndoGroup( UndoStack );
    Modified( TRUE );
    StartUndoGroup( UndoStack );
    UndoInsert( a, a, UndoStack );
    currLineRepUndo = FALSE;

    /*
     * add extra line, and spaces if needed.
     */
    if( EditFlags.AutoIndent ) {
        buffx = StaticAlloc();
        i = GetAutoIndentAmount( buffx, 0, above_line );
        AddNewLineAroundCurrent( buffx, i, type );
        StaticFree( buffx );
        j = i + 1;
    } else {
        AddNewLineAroundCurrent( NULL, 0, type );
        j = 1;
    }
    GoToLineRelCurs( b );
    GoToColumn( j, CurrentLine->len + 1 );
    DCDisplayAllLines();
    continueInsertText( CurrentPos.column, FALSE );
    return( ERR_NO_ERR );

} /* insertTextOnOtherLine */
Exemplo n.º 2
0
/* TwoPartSubstitute - goes from current line to current line minus 1
 *                     doing substitute in 2 parts if it has to, that
 *                     appear as 1
 */
vi_rc TwoPartSubstitute( char *find, char *replace, int prompt, int wrap )
{
    vi_rc   rc;
    long    changecnt, linecnt;
    linenum end_line;

    char *cmd = MemAlloc( MAX_INPUT_LINE );

    StartUndoGroup( UndoStack );

    // search from current position forward to end of doc
    sprintf( cmd, "/%s/%s/g%c", find, replace, ( prompt ) ? 'i' : '\0' );

    end_line = CurrentFile->fcbs.tail->end_line;
    rc = Substitute( CurrentPos.line, end_line, cmd );
    changecnt = LastChangeCount;
    linecnt = LastLineCount;
    if( wrap && !LastSubstituteCancelled && CurrentPos.line != 1 &&
        rc == ERR_NO_ERR ) {
        // search from beginning of do to here
        sprintf( cmd, "/%s/%s/g%c", find, replace, ( prompt ) ? 'i' : '\0' );
        rc = Substitute( 1, CurrentPos.line - 1, cmd );
        linecnt += LastLineCount;
        changecnt += LastChangeCount;
    }
    if( rc == ERR_NO_ERR ) {
        Message1( "%l changes on %l lines", changecnt, linecnt );
    }
    EndUndoGroup( UndoStack );

    MemFree( cmd );
    return( rc );

} /* TwoPartSubstitute */
Exemplo n.º 3
0
/*
 * EnterHexKey - enter a hexidecimal key stroke and insert it into the text
 */
vi_rc EnterHexKey( void )
{
    int         i;
    char        st[MAX_STR], val;
    vi_rc       rc;
    const char  *ptr;

    rc = ModificationTest();
    if( rc != ERR_NO_ERR ) {
        return( rc );
    }
    if( CurrentLine->len >= EditVars.MaxLine - 1 ) {
        return( ERR_LINE_FULL );
    }

    rc = PromptForString( "Enter the number of char to insert:", st, sizeof( st ) - 1, NULL );
    if( rc != ERR_NO_ERR ) {
        if( rc == NO_VALUE_ENTERED ) {
            return( ERR_NO_ERR );
        }
        return( rc );
    }

    /*
     * get value
     */
    ptr = SkipLeadingSpaces( st );
    val = (char)strtol( ptr, NULL, 0 );
    if( val == '\0' ) {
        return( ERR_INVALID_VALUE );
    }

    /*
     * build undo record
     */
    StartUndoGroup( UndoStack );
    CurrentLineReplaceUndoStart();
    CurrentLineReplaceUndoEnd( true );
    EndUndoGroup( UndoStack );

    /*
     * add the char
     */
    GetCurrentLine();
    for( i = WorkLine->len; i >= CurrentPos.column - 1; i-- ) {
        WorkLine->data[i + 1] = WorkLine->data[i];
    }
    WorkLine->data[CurrentPos.column - 1] = val;
    WorkLine->len++;
    DisplayWorkLine( true );
    if( CurrentPos.column < WorkLine->len ) {
        GoToColumn( CurrentPos.column + 1, WorkLine->len + 1 );
    }
    ReplaceCurrentLine();
    EditFlags.Dotable = true;
    return( ERR_NO_ERR );

} /* EnterHexKey */
Exemplo n.º 4
0
/*
 * doRunKeyMap - execute a key map a specified number of times
 */
static vi_rc doRunKeyMap( key_map *scr, long total )
{
    int         max;
    vi_rc       rc = ERR_NO_ERR;
    undo_stack  *cstack;

    if( EditFlags.InputKeyMapMode ) {
        return( ERR_INPUT_KEYMAP_RUNNING );
    }
    cstack = UndoStack;
    StartUndoGroup( cstack );
    while( total > 0 ) {
        /*
         * set up key map to run
         */
        CurrentKeyMap = scr->data;
        if( scr->no_input_window ) {
            EditFlags.NoInputWindow = TRUE;
        }
        // max = strlen( CurrentKeyMap );
        for( max = 0; CurrentKeyMap[max] != 0; max++ );

        EditFlags.KeyMapInProgress = TRUE;
        EditFlags.KeyMapMode = TRUE;
        LastError = ERR_NO_ERR;

        /*
         * run until done
         */
        for( CurrentKeyMapCount = 0; CurrentKeyMapCount < max; ) {
            LastEvent = GetNextEvent( FALSE );
            rc = DoLastEvent();
            if( rc > ERR_NO_ERR || LastError != ERR_NO_ERR ) {
                break;
            }
            DoneLastEvent( rc, TRUE );
        }

        EditFlags.KeyMapMode = FALSE;
        EditFlags.NoInputWindow = FALSE;
        EditFlags.KeyMapInProgress = FALSE;
        if( rc > ERR_NO_ERR || LastError != ERR_NO_ERR ) {
            break;
        }
        total--;
    }

    TryEndUndoGroup( cstack );
    EditFlags.Dotable = FALSE;
    return( rc );

} /* doRunKeyMap */
Exemplo n.º 5
0
/*
 * stdInsert - standard insert on a line
 */
static vi_rc stdInsert( int col, bool overstrike )
{
    vi_rc   rc;

    rc = ModificationTest();
    if( rc == ERR_NO_ERR ) {
        StartUndoGroup( UndoStack );
        CurrentLineReplaceUndoStart();
        currLineRepUndo = TRUE;
        continueInsertText( col, overstrike );
    }
    return( rc );

} /* stdInsert */
Exemplo n.º 6
0
/*
 * StartInputKeyMap - start up input key map
 */
vi_rc StartInputKeyMap( vi_key key )
{
    if( EditFlags.InputKeyMapMode || EditFlags.KeyMapMode ) {
        return( ERR_INPUT_KEYMAP_RUNNING );
    }
    CurrentKeyMap = InputKeyMaps[key].data;
    CurrentKeyMapCount = 0;
    EditFlags.InputKeyMapMode = TRUE;
    currUndoStack = UndoStack;
    StartUndoGroup( currUndoStack );
    if( InputKeyMaps[key].no_input_window ) {
        EditFlags.NoInputWindow = TRUE;
    }
    return( ERR_NO_ERR );

} /* StartInputKeyMap */
Exemplo n.º 7
0
/*
 * UndoReplaceLines - undo the replacement of a group of lines
 */
vi_rc UndoReplaceLines( linenum sline, linenum eline  )
{
    vi_rc       rc;
    fcb_list    fcblist;

    if( !EditFlags.Undo || UndoStack == NULL ) {
        return( ERR_NO_ERR );
    }
    rc = GetCopyOfLineRange( sline, eline, &fcblist );
    if( rc != ERR_NO_ERR ) {
        return( rc );
    }
    StartUndoGroup( UndoStack );
    UndoDeleteFcbs( sline - 1, &fcblist, UndoStack );
    UndoInsert( sline, eline, UndoStack );
    EndUndoGroup( UndoStack );
    return( ERR_NO_ERR );

} /* UndoReplaceLines */
Exemplo n.º 8
0
/*
 * JoinCurrentLineToNext
 */
vi_rc JoinCurrentLineToNext( void )
{
    int     i, j;
    vi_rc   rc;

    rc = ModificationTest();
    if( rc != ERR_NO_ERR ) {
        return( rc );
    }
    i = (int) GetRepeatCount();
    StartUndoGroup( UndoStack );
    for( j = 0; j < i; j++ ) {
        rc = GenericJoinCurrentLineToNext( true );
        if( rc != ERR_NO_ERR ) {
            break;
        }
    }
    EndUndoGroup( UndoStack );
    return( rc );

} /* JoinCurrentLineToNext */
Exemplo n.º 9
0
/*
 * DeleteAndInsertText - delete text range, then insert at beginning
 */
vi_rc DeleteAndInsertText( int scol, int ecol )
{
    int     startcol;
    vi_rc   rc;

    StartUndoGroup( UndoStack );
    CurrentLineReplaceUndoStart();
    currLineRepUndo = TRUE;
    if( ecol >= 0 ) {
        if( CurrentLine->len > 0 ) {
            rc = DeleteBlockFromCurrentLine( scol, ecol, FALSE );
            if( rc == ERR_NO_ERR ) {
                startcol = CurrentPos.column;
                if( scol > ecol ) {
                    startcol = ecol + 1;
                }
                if( startcol > WorkLine->len ) {
                    startcol = WorkLine->len + 1;
                }
                DisplayWorkLine( TRUE );
                ReplaceCurrentLine();
                rc = GoToColumnOK( startcol );
            }
            if( rc != ERR_NO_ERR ) {
                CurrentLineReplaceUndoCancel();
                EndUndoGroup( UndoStack );
                return( rc );
            }
        } else {
            ReplaceCurrentLine();
        }
    }
    continueInsertText( CurrentPos.column, FALSE );
    return( ERR_NO_ERR );

} /* DeleteAndInsertText */
Exemplo n.º 10
0
/*
 * InsertTextForSpecialKey - insert text for ^O, ALT_O
 */
void InsertTextForSpecialKey( vi_key event, char *buff )
{
    linenum     line;
    int         type;

    if( CurrentFile == NULL ) {
        return;
    }

    line = CurrentPos.line;
    type = INSERT_BEFORE;
    if( event == VI_KEY( CTRL_O ) ) {
        type = INSERT_AFTER;
        line += 1;
    }
    Modified( true );
    StartUndoGroup( UndoStack );
    UndoInsert( line, line, UndoStack );
    AddNewLineAroundCurrent( buff, strlen( buff ), type );
    EndUndoGroup( UndoStack );
    DCDisplayAllLines();
    DCUpdate();

} /* InsertTextForSpecialKey */
Exemplo n.º 11
0
/*
 * Substitute - perform substitution
 */
vi_rc Substitute( linenum n1, linenum n2, char *data )
{
    char        *sstr, *rstr, *newr;
    char        flag[20], *linedata;
    bool        iflag = false;
    bool        gflag = false;
    bool        undoflag = false;
    bool        restline = false;
    bool        splitpending = false;
    bool        undoline = false;
    int         i, rlen, slen;
    bool        splitme;
    long        changecnt = 0, linecnt = 0;
    linenum     llineno, ll, lastline = 0, extra;
    i_mark      pos;
    vi_rc       rc;

    LastSubstituteCancelled = 0;
    LastChangeCount = 0;
    LastLineCount = 0;

    sstr = alloca( MAX_INPUT_LINE );
    if( sstr == NULL ) {
        return( ERR_NO_STACK );
    }
    strcpy( sstr, data );
    rc = ModificationTest();
    if( rc != ERR_NO_ERR ) {
        return( rc );
    }
    strcpy( data, sstr );
    rstr = alloca( MAX_INPUT_LINE  );
    if( rstr == NULL ) {
        return( ERR_NO_STACK );
    }
    if( NextWordSlash( data, sstr ) < 0 ) {
        return( ERR_INVALID_SUBS_CMD );
    }
    if( NextWordSlash( data, rstr ) < 0 ) {
        return( ERR_INVALID_SUBS_CMD );
    }
    slen = NextWord1( data, flag );
    for( i = 0; i < slen; i++ ) {
        switch( flag[i] ) {
        case 'g':
            gflag = true;
            break;
        case 'i':
        case 'c':
            iflag = true;
            break;
        }
    }
    rc = CurrentRegComp( sstr );
    if( rc != ERR_NO_ERR ) {
        return( rc );
    }

    /*
     * verify last line
     */
    if( n2 > CurrentFile->fcbs.tail->end_line ) {
        rc = CFindLastLine( &ll );
        if( rc != ERR_NO_ERR ) {
            return( rc );
        }
        if( n2 > ll ) {
            return( ERR_INVALID_LINE_RANGE );
        }
    }

    /*
     * set for start of search
     */
    if( EditFlags.Verbose && EditFlags.EchoOn ) {
        ClearWindow( MessageWindow );
    }
    SaveCurrentFilePos();
    llineno = n1 - 1;

    EditFlags.AllowRegSubNewline = true;
    newr = StaticAlloc();
    for( pos.column = 0, pos.line = n1;
        pos.line <= n2;
        nextSearchStartPos( &pos, gflag, rlen ) ) {

        /*
         * get regular expression, and build replacement string
         */
        rc = FindRegularExpression( NULL, &pos, &linedata, n2, 0 );
        if( rc != ERR_NO_ERR || pos.line > n2 ) {
            break;
        }

        slen = GetCurrRegExpLength();
        splitme = RegSub( CurrentRegularExpression, rstr, newr, pos.line );
        rlen = strlen( newr );

        ProcessingMessage( pos.line );

        /*
         * if in global mode, see if we already have an undo for
         * this line
         */
        if( gflag ) {
            if( lastline != pos.line ) {
                undoline = false;
            }
        }

        /*
         * interactive mode? yes, then display text and ask to change
         */
        if( iflag ) {
            change_resp rsp;

            if( !restline ) {
                ClearWindow( MessageWindow );
            }
            restline = true;
            GoToLineNoRelCurs( pos.line );
            if( EditFlags.GlobalInProgress ) {
                EditFlags.DisplayHold = false;
                DCDisplayAllLines();
                EditFlags.DisplayHold = true;
            }
            HilightSearchString( &pos, slen );
            rsp = ChangePrompt();
            if( rsp == CHANGE_NO ) {
                ResetDisplayLine();
                rlen = 1;
                continue;
            } else if( rsp == CHANGE_CANCEL ) {
                ResetDisplayLine();
                LastSubstituteCancelled = 1;
                break;
            } else if( rsp == CHANGE_ALL ) {
                ResetDisplayLine();
                iflag = false;
            }
        }

        /*
         * set up for global undo if we haven't already
         */
        if( !undoflag ) {
            StartUndoGroup( UndoStack );
            undoflag = true;
        }

        /*
         * bump change counts
         */
        changecnt++;
        if( llineno != pos.line ) {
            if( splitpending ) {
                splitpending = false;
                extra = SplitUpLine( llineno );
                n2 += extra;
                pos.line += extra;
            }
            linecnt++;
            llineno = pos.line;
        }

        /*
         * get copy of line, and verify that new stuff fits
         */
        CurrentPos.line = pos.line;
        rc = CGimmeLinePtr( pos.line, &CurrentFcb, &CurrentLine );
        if( rc != ERR_NO_ERR ) {
            break;
        }
        if( CurrentLine->len + rlen - slen >= EditVars.MaxLine ) {
            rc = ERR_LINE_FULL;
            break;
        }

        /*
         * now build the individual undo
         */
        CurrentFcb->non_swappable = true;
        if( !undoline ) {
            CurrentLineReplaceUndoStart();
            CurrentLineReplaceUndoEnd( true );
            if( gflag ) {
                undoline = true;
                lastline = pos.line;
            }
        }

        /*
         * remove the old string
         */
        GetCurrentLine();
        WorkLine->len = ReplaceSubString( WorkLine->data, WorkLine->len,
                                          pos.column, pos.column + slen - 1, newr, rlen );
        if( iflag ) {
            DisplayWorkLine( true );
        }
        ReplaceCurrentLine();

        /*
         * if not global, only do this change on this line
         */
        if( splitme ) {
            splitpending = true;
        }
        CurrentFcb->non_swappable = false;
    }
    StaticFree( newr );
    EditFlags.AllowRegSubNewline = false;
    /*
    * is there still a split line pending?
    */
    if( splitpending ) {
        SplitUpLine( llineno );
    }
    RestoreCurrentFilePos();
    if( restline ) {
        SetCurrentLine( CurrentPos.line );
        GoToColumnOK( CurrentPos.column );
    }
    if( undoflag ) {
        EndUndoGroup( UndoStack );
    }
    switch( rc ) {
    case ERR_NO_ERR:
    case ERR_LINE_FULL:
    case ERR_FIND_PAST_TERM_LINE:
    case ERR_FIND_NOT_FOUND:
    case ERR_FIND_END_OF_FILE:
        /*
        * display results
        */
        if( rc == ERR_LINE_FULL ) {
            Message1( "Stopped at line %l - line full", pos.line );
        } else {
            Message1( "%l changes on %l lines", changecnt, linecnt );
            LastLineCount = linecnt;
            LastChangeCount = changecnt;
        }
        DCDisplayAllLines();
        rc = ERR_NO_ERR;
        break;
    default:
        break;
    }
    return( rc );

} /* Substitute */
Exemplo n.º 12
0
/*
 * InsertLines - insert a set of lines after specified number in current file
 */
vi_rc InsertLines( linenum s, fcb_list *fcblist, undo_stack *us )
{
    fcb         *sfcb, *cfcb;
    linenum     l, e;
    vi_rc       rc;

    rc = ModificationTest();
    if( rc != ERR_NO_ERR ) {
        return( rc );
    }
    if( s < 0 ) {
        return( ERR_NO_SUCH_LINE );
    }

    /*
     * find the number of lines inserted
     */
    e = 0;
    for( cfcb = fcblist->head; cfcb != NULL; cfcb = cfcb->next ) {
        e += cfcb->end_line - cfcb->start_line + 1;
    }
    e += s;

    /*
     * see if there is a null fcb at the head; if so, ditch
     * the null fcb and then reset line ranges
     */
    if( CurrentFile->fcbs.head->nullfcb ) {
        FreeEntireFcb( CurrentFile->fcbs.head );
        CurrentFile->fcbs = *fcblist;
        e = e - s;
        s = 0;
    /*
     * if we are to insert after line 0, then make this block of
     * fcbs the first set in the text
     */
    } else if( s == 0 ) {
        fcblist->tail->next = CurrentFile->fcbs.head;
        CurrentFile->fcbs.head->prev = fcblist->tail;
        CurrentFile->fcbs.head = fcblist->head;
    } else {
        /*
         * if we are inserting after the last fcb in the file,
         * make this block of fcbs the last set in the text
         */
        rc = FindFcbWithLine( s + 1, CurrentFile, &sfcb );
        if( rc != ERR_NO_ERR ) {
            if( rc != ERR_NO_SUCH_LINE ) {
                return( rc );
            }
            fcblist->head->prev = CurrentFile->fcbs.tail;
            CurrentFile->fcbs.tail->next = fcblist->head;
            CurrentFile->fcbs.tail = fcblist->tail;
        /*
         * put the lines after the line to be have text inserted
         * into a new fcb, then insert the block of fcb's after
         * the fcb containing the line to have text inserted
         */
        } else {
            rc = SplitFcbAtLine( s + 1, CurrentFile, sfcb );
            if( rc > ERR_NO_ERR ) {
                return( rc );
            }
            /*
             * line we want to split at is already the first line
             * in the fcb, so chain the new fcb block before
             * the fcb containg the line we want to split at
             */
            if( rc == NO_SPLIT_CREATED_AT_START_LINE ) {
                if( sfcb->prev != NULL ) {
                    sfcb->prev->next = fcblist->head;
                }
                fcblist->head->prev = sfcb->prev;
                sfcb->prev = fcblist->tail;
                fcblist->tail->next = sfcb;
            /*
             * chain the new fcb block after the fcb that used
             * to containing the line we wanted to split at, and
             * before the new fcb containing the line we want
             * to split at
             */
            } else {
                if( rc == NO_SPLIT_CREATED_AT_END_LINE ) {
//                  Die( "Impossible, can't be past last line");
                }
                if( sfcb->next != NULL ) {
                    sfcb->next->prev = fcblist->tail;
                }
                fcblist->tail->next = sfcb->next;
                sfcb->next = fcblist->head;
                fcblist->head->prev = sfcb;
            }
        }
    }

    /*
     * now, resequence line numbers and set proper file ptr
     */
    for( cfcb = fcblist->head; cfcb != NULL; cfcb = cfcb->next ) {
        cfcb->f = CurrentFile;
        l = cfcb->end_line - cfcb->start_line;
        if( cfcb->prev != NULL ) {
            cfcb->start_line = cfcb->prev->end_line + 1;
        } else {
            cfcb->start_line = 1;
        }
        cfcb->end_line = cfcb->start_line + l;
    }

    /*
     * finish up: collect fcbs, point to corrent line, and
     * build undo for operation
     */
    rc = MergeAllFcbs( &CurrentFile->fcbs );
    if( rc != ERR_NO_ERR ) {
        return( rc );
    }
    StartUndoGroup( us );
    rc = ValidateCurrentLine();
    if( rc != ERR_NO_ERR ) {
        return( rc );
    }
    Modified( true );
    UndoInsert( s + 1, e, us );
    EndUndoGroup( us );

    return( ERR_NO_ERR );

} /* InsertLines */
Exemplo n.º 13
0
/*
 * Source - main driver
 */
vi_rc Source( char *fn, char *data, int *ln )
{
    undo_stack  *atomic = NULL;
    labels      *lab, lb;
    vlist       vl;
    files       fi;
    sfile       *sf, *curr;
    char        tmp[MAX_SRC_LINE];
    char        sname[FILENAME_MAX];
    vi_rc       rc;
    bool        sicmp, wfb, ssa, exm;
    resident    *res;
    int         cTokenID;

    /*
     * startup
     */
    LastRC = LastRetCode;
    memset( &fi, 0, sizeof( fi ) );
    vl.head = vl.tail = NULL;
    res = residentScript( fn );
    if( res != NULL && EditFlags.LoadResidentScript ) {
        return( ERR_SCRIPT_ALREADY_RESIDENT );
    }
    if( EditFlags.CompileScript || res == NULL ) {
        lab = &lb;
        memset( lab, 0, sizeof( labels ) );
        sf = NULL;
    } else {
        lab = &res->lab;
        sf = res->sf;
    }
    if( EditFlags.CompileScript ) {
        sname[0] = 0;
        NextWord1( data, sname );
    }

    /*
     * initialize variables
     */
    memset( &fi, 0, sizeof( fi ) );
    rc = initSource( &vl, data );
    if( rc != ERR_NO_ERR ) {
        return( rc );
    }

    /*
     * pre-process
     */
    sicmp = EditFlags.ScriptIsCompiled;
    SourceErrCount = 0;
    if( EditFlags.CompileScript || res == NULL ) {
        EditFlags.ScriptIsCompiled = FALSE;
        rc = PreProcess( fn, &sf, lab );
        finiSourceErrFile( fn );
        if( rc != ERR_NO_ERR || SourceErrCount > 0 ) {
            EditFlags.ScriptIsCompiled = sicmp;
            return( rc );
        }
    } else {
        EditFlags.ScriptIsCompiled = res->scriptcomp;
    }

    /*
     * if we were loading a resident script, then add it
     */
    if( EditFlags.LoadResidentScript ) {
        finiSource( NULL, &vl, NULL, NULL );
        if( SourceErrCount == 0 ) {
            addResidentScript( fn, sf, lab );
        }
        EditFlags.ScriptIsCompiled = sicmp;
        return( ERR_NO_ERR );
    }

    /*
     * if we were compiling, dump results and go back
     */
    if( EditFlags.CompileScript ) {
        rc = barfScript( fn, sf, &vl, ln, sname );
        finiSource( lab, &vl, sf, NULL );
        return( rc );
    }

    /*
     * process each source line
     */
    exm = EditFlags.ExMode;
    wfb = EditFlags.WatchForBreak;
    ssa = EditFlags.SourceScriptActive;
    EditFlags.SourceScriptActive = TRUE;
    EditFlags.WatchForBreak = TRUE;
    EditFlags.ExMode = TRUE;
    curr = sf->next;
    while( curr != NULL ) {

        cTokenID = curr->token - SRC_T_NULL - 1;

        if( !EditFlags.Starting ) {
            if( EditFlags.BreakPressed ) {
                ClearBreak();
                break;
            }
        }
        rc = LastError = ERR_NO_ERR;
        if( curr->data != NULL ) {
            strcpy( tmp, curr->data );
        } else {
            tmp[0] = 0;
        }

        if( EditFlags.Appending ) {
            if( curr->hasvar) {
                Expand( tmp, &vl );
            }
            rc = AppendAnother( tmp );
            goto evil_continue;
        }

        if( cTokenID == PCL_T_ENDFILETYPESOURCE ) {
            rc = FTSEnd();
            goto evil_continue;
        }

        if( EditFlags.FileTypeSource ) {
            rc = FTSAddCmd( tmp, curr->token );
            goto evil_continue;
        }

        if( curr->token > SRC_T_NULL ) {

            if( curr->hasvar) {
                Expand( tmp, &vl );
            }
            rc = TryCompileableToken( cTokenID, tmp, FALSE, 0 );
            if( rc == NOT_COMPILEABLE_TOKEN ) {
                rc = ProcessWindow( cTokenID, tmp );
            }
            if( rc < ERR_NO_ERR ) {
                rc = ERR_NO_ERR;
            }

        } else switch( curr->token ) {
        case SRC_T_ATOMIC:
            if( atomic == NULL ) {
                atomic = UndoStack;
                StartUndoGroup( atomic );
            }
            break;

        case SRC_T_IF:
            rc = SrcIf( &curr, &vl );
            break;

        case SRC_T_GOTO:
            rc = SrcGoTo( &curr, tmp, lab );
            break;

        case SRC_T_LABEL:
            break;

        case SRC_T_RETURN:
            if( curr->data != NULL ) {
                int     ret;
                GetErrorTokenValue( &ret, curr->data );
                rc = ret;
            } else {
                rc = ERR_NO_ERR;
            }
            goto evil_exit;

        case SRC_T_GET:
            SrcGet( tmp, &vl );
            rc = ERR_NO_ERR;
            break;

        case SRC_T_INPUT:
            LastRC = SrcInput( tmp, &vl );
            if( LastRC != NO_VALUE_ENTERED && LastRC != ERR_NO_ERR ) {
                rc = LastRC;
            }
            break;

        case SRC_T_NEXTWORD:
            rc = SrcNextWord( tmp, &vl );
            break;

        case SRC_T_ASSIGN:
            rc = SrcAssign( tmp, &vl );
            break;

        case SRC_T_EXPR:
            rc = SrcExpr( curr, &vl );
            break;

        case SRC_T_OPEN:
            LastRC = SrcOpen( curr, &vl, &fi, tmp );
            if( LastRC != ERR_FILE_NOT_FOUND && LastRC != ERR_NO_ERR ) {
                rc = LastRC;
            }
            break;

        case SRC_T_READ:
            LastRC = SrcRead( curr, &fi, tmp, &vl );
            if( LastRC != END_OF_FILE && LastRC != ERR_NO_ERR ) {
                rc = LastRC;
            }
            break;

        case SRC_T_WRITE:
            rc = SrcWrite( curr, &fi, tmp, &vl );
            break;

        case SRC_T_CLOSE:
            rc = SrcClose( curr, &vl, &fi, tmp );
            break;

        default:
#ifdef __WIN__
            {
                if( RunWindowsCommand( tmp, &LastRC, &vl ) ) {
                    rc = LastRC;
                    break;
                }
            }
#endif
            if( curr->hasvar ) {
                Expand( tmp, &vl );
            }
            LastRC = RunCommandLine( tmp );
            if( LastRC == DO_NOT_CLEAR_MESSAGE_WINDOW ) {
                LastRC = LastError;
            }
            break;
        }

evil_continue:
        if( rc != ERR_NO_ERR ) {
            break;
        }
        curr = curr->next;

    }

evil_exit:
    if( EditFlags.Appending ) {
        AppendAnother( "." );
    }
    if( curr != NULL ) {
        *ln = curr->line;
    } else {
        *ln = CurrentSrcLine;
        rc = ERR_NO_ERR;
    }
    EditFlags.WatchForBreak = wfb;
    EditFlags.SourceScriptActive = ssa;
    EditFlags.ScriptIsCompiled = sicmp;
    EditFlags.ExMode = exm;
    if( res != NULL && !EditFlags.CompileScript ) {
        sf = NULL;
        lab = NULL;
    }
    finiSource( lab, &vl, sf, atomic );
    return( rc );

} /* Source */
Exemplo n.º 14
0
/*
 * InsertLinesAtCursor - insert a set of lines at current pos. in file
 */
vi_rc InsertLinesAtCursor( fcb_list *fcblist, undo_stack *us )
{
    fcb         *cfcb;
    linenum     e;
    int         lastLineLen;
    char        *source;
    line        *tLine;
    vi_rc       rc;

    rc = ModificationTest();
    if( rc != ERR_NO_ERR ) {
        return( rc );
    }

    /*
     * find the number of lines inserted
     */
    e = 0;
    for( cfcb = fcblist->head; cfcb != NULL; cfcb = cfcb->next ) {
        e += (cfcb->end_line - cfcb->start_line + 1);
    }

    // add chars from right of cursor to end of last line of buffer
    source = CurrentLine->data + CurrentPos.column - 1;
    lastLineLen = fcblist->tail->lines.tail->len;
    fcblist->tail->lines.tail->len += CurrentLine->len - CurrentPos.column + 1;

    fcblist->tail->byte_cnt += CurrentLine->len - CurrentPos.column + 1;

    tLine = fcblist->tail->lines.tail->prev;
    fcblist->tail->lines.tail = MemReAlloc( fcblist->tail->lines.tail,
                    sizeof( line ) + fcblist->tail->lines.tail->len + 1 );
    if( tLine ) {
        tLine->next = fcblist->tail->lines.tail;
    }
    strcpy( fcblist->tail->lines.tail->data + lastLineLen, source );

    StartUndoGroup( us );

    // create new current line in work line
    CurrentLineReplaceUndoStart();
    GetCurrentLine();
    WorkLine->len = CurrentPos.column + fcblist->head->lines.head->len - 1;
    strcpy( WorkLine->data + CurrentPos.column - 1, fcblist->head->lines.head->data );

    // replace current line
    ReplaceCurrentLine();
    CurrentLineReplaceUndoEnd( true );

    // remove first line of buffer
    FetchFcb( fcblist->head );
    fcblist->head->non_swappable = true;
    fcblist->head->start_line++;
    fcblist->head->byte_cnt -= fcblist->head->lines.head->len + 1;
    tLine = fcblist->head->lines.head;
    fcblist->head->lines.head = fcblist->head->lines.head->next;
    fcblist->head->lines.head->prev = NULL;
    MemFree( tLine );
    fcblist->head->non_swappable = false;

    // add rest of lines of buffer & done
    if( fcblist->head->lines.head) {
        InsertLines( CurrentPos.line, fcblist, us );
    }
    EndUndoGroup( us );

    // if are indeed linebased, move cursor as well
    if( !EditFlags.LineBased ) {
        GoToLineNoRelCurs( CurrentPos.line + e - 1 );
        GoToColumnOnCurrentLine( lastLineLen + 1 );
    }

    return( ERR_NO_ERR );

} /* InsertLinesAtCursor */
Exemplo n.º 15
0
/*
 * GenericJoinCurrentLineToNext
 */
vi_rc GenericJoinCurrentLineToNext( bool remsp )
{
    line        *nline = CurrentLine;
    fcb         *nfcb = CurrentFcb;
    int         i, j, k;
    vi_rc       rc;

    /*
     * get next line data
     */
    rc = CGimmeNextLinePtr( &nfcb, &nline );
    if( rc != ERR_NO_ERR ) {
        return( rc );
    }
    if( CurrentLine->len + nline->len + 1 >= EditVars.MaxLine ) {
        return( ERR_LINE_FULL );
    }

    /*
     * now, copy in the data
     */
    StartUndoGroup( UndoStack );
    CurrentLineReplaceUndoStart();
    CurrentLineReplaceUndoEnd( true );
    GetCurrentLine();

    if( remsp ) {
        while( WorkLine->len > 0 && WorkLine->data[WorkLine->len - 1] == ' ' ) {
            WorkLine->data[WorkLine->len - 1] = 0;
            WorkLine->len--;
        }
        j = FindStartOfALine( nline ) - 1;
	    k = 0;
        if( !(j == 0 && nline->data[0] == ' ') ) {
            if( WorkLine->len != 0 ) {
                WorkLine->data[WorkLine->len] = ' ';
                k = WorkLine->len + 1;
            }
            for( i = j; i <= nline->len; i++ ) {
                WorkLine->data[k + i - j] = nline->data[i];
            }
        }
    } else {
        k = WorkLine->len;
        for( i = 0; i <= nline->len; i++ ) {
            WorkLine->data[k + i] = nline->data[i];
        }
    }
    WorkLine->len = strlen( WorkLine->data );
    ReplaceCurrentLine();

    /*
     * delete next line
     */
    rc = DeleteLineRange( CurrentPos.line + 1, CurrentPos.line + 1, 0 );
    if( rc != ERR_NO_ERR ) {
        return( rc );
    }
    EndUndoGroup( UndoStack );
    if( remsp ) {
        if( k < 2 ) {
            k = 2;
        }
        rc = GoToColumn( k - 1, CurrentLine->len );
        if( rc != ERR_NO_ERR ) {
            return( rc );
        }
    }
    DCDisplayAllLines();
    return( ERR_NO_ERR );

} /* GenericJoinCurrentLineToNext */
Exemplo n.º 16
0
/*
 * DoGenericFilter - filter some crap
 */
vi_rc DoGenericFilter( linenum s, linenum e, const char *cmd )
{
    fcb         *cfcb, *tfcb;
    line        *cline;
    vi_rc       rc;
    char        filtin[_MAX_PATH], filtout[_MAX_PATH];
    fcb_list    fcblist;
    int         fh;

    rc = ModificationTest();
    if( rc != ERR_NO_ERR ) {
        return( rc );
    }

    /*
     * filter on a line
     */
    rc = GetCopyOfLineRange( s, e, &fcblist );
    if( rc != ERR_NO_ERR ) {
        return( rc );
    }

    /*
     * get file
     */
    MakeTmpPath( filtin, FILTER_FILE_NAME );
    fh = mkstemp( filtin );
    if( fh == -1 )
        return( ERR_FILE_OPEN );

    /*
     * now, dump this crap to a tmp file
     */
    for( cfcb = fcblist.head; cfcb != NULL; cfcb = tfcb ) {
        FetchFcb( cfcb );
        for( cline = cfcb->lines.head; cline != NULL; cline = cline->next ) {
            write( fh, cline->data, strlen( cline->data ) );
#if defined( __UNIX__ )
            write( fh, "\n", 1 );
#else
            write( fh, "\r\n", 2 );
#endif
        }
        tfcb = cfcb->next;
        FcbFree( cfcb );
    }
    close( fh );

    MakeTmpPath( filtout, FILTER_FILE_NAME );
    fh = mkstemp( filtout );
    if( fh == -1 ) {
        remove( filtin );
        return( ERR_FILE_OPEN );
    }
    close( fh );
    /*
     * shell out to the given command
     */
    ExecCmd( filtin, filtout, cmd );
    StartUndoGroup( UndoStack );
    rc = DeleteLineRange( s, e, 0 );
    if( rc == ERR_NO_ERR ) {
        ReadAFile( s - 1, filtout );
        Message1( "%l lines filtered through %s", e - s + 1, cmd );
    }
    EndUndoGroup( UndoStack );

    /*
     * cleanup
     */
    if( rc == ERR_NO_ERR ) {
        rc = DO_NOT_CLEAR_MESSAGE_WINDOW;
    }
    remove( filtin );
    remove( filtout );
    return( rc );

} /* DoGenericFilter */
Exemplo n.º 17
0
/*
 * Global - perform global command
 */
vi_rc Global( linenum n1, linenum n2, const char *data, int dmt )
{
    char        *sstr, *linedata;
    bool        match;
    vi_rc       rc;
    vi_rc       rc1;
    long        changecnt = 0;
    linenum     ll;
    fcb         *cfcb;
    line        *cline;
    regexp      crx;
    i_mark      pos;

    /*
     * get search string and command
     */
    rc = ModificationTest();
    if( rc != ERR_NO_ERR ) {
        return( rc );
    }
    sstr = alloca( MAX_INPUT_LINE );
    if( sstr == NULL ) {
        return( ERR_NO_STACK );
    }
    data = SkipLeadingSpaces( data );
    data = GetNextWord( data, sstr, SingleSlash );
    if( *sstr == '\0' ) {
        return( ERR_INVALID_GLOBAL_CMD );
    }
    if( *data == '/' )
    	++data;     // skip one slash character
    data = SkipLeadingSpaces( data );

    /*
     * verify last line
     */
    if( n2 > CurrentFile->fcbs.tail->end_line ) {
        rc = CFindLastLine( &ll );
        if( rc != ERR_NO_ERR ) {
            return( rc );
        }
        if( n2 > ll ) {
            return( ERR_INVALID_LINE_RANGE );
        }
    }

    /*
     * set for start of search
     */
    if( EditFlags.Verbose && EditFlags.EchoOn ) {
        ClearWindow( MessageWindow );
    }
    rc = CurrentRegComp( sstr );
    if( rc != ERR_NO_ERR ) {
        return( rc );
    }
    SaveCurrentFilePos();
    StartUndoGroup( UndoStack );
    EditFlags.DisplayHold = true;

    /*
     * pass one - find all matches
     */
    for( pos.line = n1; pos.line <= n2; pos.line++ ) {

        /*
         * go thorugh file, marking global lines
         */
        pos.column = 0;
        rc = FindRegularExpression( NULL, &pos, &linedata, n2, 0 );
        if( rc != ERR_NO_ERR ) {
            if( rc == ERR_FIND_PAST_TERM_LINE || rc == ERR_FIND_NOT_FOUND ||
                rc == ERR_FIND_END_OF_FILE ) {
                break;
            }
            RestoreCurrentFilePos();
            EditFlags.DisplayHold = false;
            return( rc );
        }
        if( pos.line > n2 ) {
            break;
        }

        /*
         * go to appropriate spot in file
         */
        rc = GoToLineNoRelCurs( pos.line );
        if( rc != ERR_NO_ERR ) {
            RestoreCurrentFilePos();
            EditFlags.DisplayHold = false;
            return( rc );
        }

        /*
         * mark fcb and line for a match
         */
        CurrentFcb->globalmatch = true;
        CurrentLine->u.ld.globmatch = true;
        if( EditFlags.Verbose && EditFlags.EchoOn ) {
            // WPrintfLine( MessageWindow,1,"Match on line %l",clineno );
            Message1( "Match on line %l", pos.line );
        }
    }


    /*
     * negate range, if needed
     */
    if( dmt ) {
        /*
         * run through each line, flipping globmatch flag on lines
         */
        CGimmeLinePtr( n1, &CurrentFcb, &CurrentLine );
        match = false;
        for( CurrentPos.line = n1; CurrentPos.line <= n2; CurrentPos.line++ ) {
            if( CurrentLine->u.ld.globmatch ) {
                CurrentLine->u.ld.globmatch = false;
            } else {
                match = true;
                CurrentLine->u.ld.globmatch = true;
            }
            CurrentLine = CurrentLine->next;
            if( CurrentLine == NULL ) {
                CurrentFcb->globalmatch = match;
                CurrentFcb = CurrentFcb->next;
                FetchFcb( CurrentFcb );
                CurrentLine = CurrentFcb->lines.head;
                match = false;
            }
        }
    }

    /*
     * Pass 2: do all changes
     */
    rc = ERR_NO_ERR;
    EditFlags.GlobalInProgress = true;
    memcpy( &crx, CurrentRegularExpression, sizeof( crx ) );

    for( CurrentFcb = CurrentFile->fcbs.head; CurrentFcb != NULL; CurrentFcb = CurrentFcb->next ) {
        if( !CurrentFcb->globalmatch )
            continue;
        FetchFcb( CurrentFcb );
        CurrentPos.line = CurrentFcb->start_line;
        for( CurrentLine = CurrentFcb->lines.head; CurrentLine != NULL; CurrentLine = CurrentLine->next, CurrentPos.line++ ) {
            if( !CurrentLine->u.ld.globmatch )
                continue;
            CurrentLine->u.ld.globmatch = false;
            changecnt++;

            CurrentPos.column = 1;
            ProcessingMessage( CurrentPos.line );
            /*
            * build command line
            */
            rc = RunCommandLine( data );
            if( rc > ERR_NO_ERR ) {
                break;
            }
        }
        if( rc > ERR_NO_ERR ) {
            break;
        }
        CurrentFcb->globalmatch = false;
    }

    /*
     * we have an error, so fix up fcbs
     */
    if( rc > ERR_NO_ERR ) {
        for( cfcb = CurrentFile->fcbs.head; cfcb != NULL; cfcb = cfcb->next ) {
            if( cfcb->globalmatch ) {
                cfcb->globalmatch = false;
                cfcb->non_swappable = false;
                for( cline = cfcb->lines.head; cline != NULL; cline = cline->next ) {
                    cline->u.ld.globmatch = false;
                }
            }
        }
    }

    /*
     * display results
     */
    EditFlags.GlobalInProgress = false;
    EditFlags.DisplayHold = false;
    EndUndoGroup( UndoStack );
    RestoreCurrentFilePos();
    rc1 = SetCurrentLine( CurrentPos.line );
    if( rc1 != ERR_NO_ERR ) {
        if( rc1 == ERR_NO_SUCH_LINE ) {
            SetCurrentLine( 1 );
        } else {
            return( rc1 );
        }
    }
    Message1( "%l matches found",changecnt );
    DCDisplayAllLines();
    return( rc );

} /* Global */
Exemplo n.º 18
0
/*
 * ProcessEx - process an ex command
 */
vi_rc ProcessEx( linenum n1, linenum n2, bool n2f, int tkn, const char *data )
{
    vi_rc       rc = ERR_INVALID_COMMAND, i;
    char        word[MAX_STR];
    linenum     addr, tlines;
    fcb         *cfcb;
    line        *cline;
    fcb_list    fcblist;

    GetNextWord1( data, word );
    data = word;
    if( GetAddress( &data, &addr ) != ERR_NO_ERR ) {
        addr = -1;
    }
    tlines = n2 - n1 + 1;

    switch( tkn ) {
    case EX_T_APPEND:
        if( !EditFlags.ExMode ) {
            return( ERR_ONLY_VALID_IN_EX_MODE );
        }
        if( !n2f ) {
            rc = Append( n1, true );
        }
        break;
    case EX_T_CHANGE:
        if( !EditFlags.ExMode ) {
            return( ERR_ONLY_VALID_IN_EX_MODE );
        }
        StartUndoGroup( UndoStack );
        rc = DeleteLineRange( n1, n2, 0 );
        if( rc != ERR_NO_ERR ) {
            EndUndoGroup( UndoStack );
            break;
        }
        rc = Append( n1 - 1, false );
        if( rc != ERR_NO_ERR ) {
            EndUndoGroup( UndoStack );
            break;
        }
        break;
    case EX_T_COPY:
        if( addr < 0 || IsPastLastLine( addr ) ) {
            return( ERR_INVALID_ADDRESS );
        }
        i = GetCopyOfLineRange( n1, n2, &fcblist );
        if( i ) {
            break;
        }
        rc = InsertLines( addr, &fcblist, UndoStack );
        GoToLineNoRelCurs( addr );
        if( rc == ERR_NO_ERR ) {
            Message1( strCmmsg, tlines, "copied", addr );
        }
        break;
    case EX_T_INSERT:
        if( !EditFlags.ExMode ) {
            return( ERR_ONLY_VALID_IN_EX_MODE );
        }
        if( !n2f ) {
            rc = Append( n1 - 1, true );
        }
        break;
    case EX_T_JOIN:
        if( SaveAndResetFilePos( n1 ) != ERR_NO_ERR ) {
            rc = ERR_NO_SUCH_LINE;
            break;
        }
        if( tlines == 1 ) {
            n2 = n1 + 1;
            tlines = 2;
        }
        SetRepeatCount( tlines - 1 );
        rc = JoinCurrentLineToNext();
        RestoreCurrentFilePos();
        GoToLineNoRelCurs( n1 );
        if( rc == ERR_NO_ERR ) {
            Message1( "lines %l to %l joined", n1, n2 );
        }
        break;
    case EX_T_LIST:
        if( !EditFlags.ExMode ) {
            return( ERR_ONLY_VALID_IN_EX_MODE );
        }
        for( rc = CGimmeLinePtr( n1, &cfcb, &cline ); rc == ERR_NO_ERR; rc = CGimmeNextLinePtr( &cfcb, &cline ) ) {
            if( EditFlags.LineNumbers ) {
                MyPrintf( "%M %s\n", n1, cline->data );
            } else {
                MyPrintf( "%s\n", cline->data );
            }
            if( n1 >= n2 ) {
                break;
            }
            n1++;
        }
        break;
    case EX_T_MARK:
        rc = SetGenericMark( n1, 1, C2VIKEY( word[0] ) );
        break;
    case EX_T_MOVE:
        if( addr < 0 || IsPastLastLine( addr ) ) {
            return( ERR_INVALID_ADDRESS );
        }
        SavebufNumber = WORK_SAVEBUF;
        StartUndoGroup( UndoStack );
        rc = DeleteLineRange( n1, n2, SAVEBUF_FLAG );

        if( SavebufNumber != WORK_SAVEBUF ) {
            /* if this changes, the command will fail
             * this could be caused by checking out a read-only file
             * so fix the deleted text and give an error message
             */
            DoUndo();
            return( ERR_INVALID_COMMAND );
        }
        if( rc != ERR_NO_ERR ) {
            EndUndoGroup( UndoStack );
            break;
        }
        if( addr > n2 ) {
            addr -= tlines;
        } else if( addr >= n1 && addr <= n2 ) {
            addr = n1;
        }
        rc = InsertLines( addr, &WorkSavebuf->u.fcbs, UndoStack );
        EndUndoGroup( UndoStack );
        GoToLineNoRelCurs( addr );
        if( rc == ERR_NO_ERR ) {
            Message1( strCmmsg, tlines, "moved", addr );
        }
        break;
    case EX_T_UNDO:
        rc = DoUndo();
        break;
    case EX_T_UNDO_DMT:
        rc = DoUndoUndo();
        break;
    case EX_T_EQUALS:
        Message1( "%l", n1 );
        rc = ERR_NO_ERR;
        break;
    case EX_T_VERSION:
        rc = DoVersion();
        break;
    case EX_T_VISUAL:
    case EX_T_VISUAL_DMT:
        if( EditFlags.LineDisplay ) {
            ScreenPage( -1 );
            EditFlags.ExMode = false;
            EditFlags.LineDisplay = false;
            EditFlags.ClockActive = true;
            ReDisplayScreen();
            DoVersion();
        }
        if( word[0] != '\0' ) {
            rc = EditFile( word, ( tkn == EX_T_VISUAL_DMT ) );
        } else {
            rc = ERR_NO_ERR;
        }
        break;
    }
    return( rc );

} /* ProcessEx */
Exemplo n.º 19
0
vi_rc Change( range *r )
{
    int         scol, ecol;
    int         tmp;
    vi_rc       rc;
    vi_key      key;
#ifndef __WIN__
    int         vecol;
#endif

    /*
     * change line ranges
     */
    if( r->start.line != r->end.line ) {
        StartUndoGroup( UndoStack );
        if( !r->line_based ) {
            rc = Cut( r->start.line, r->start.column, r->end.line, r->end.column, true );
            r->end.column = -1;
            scol = -1;
            ecol = -1;
        } else {
            if( r->start.line == CurrentPos.line ) {
                r->start.line++;
            } else {
                r->end.line--;
            }
            if( r->start.line <= r->end.line ) {
                rc = DeleteLineRange( r->start.line, r->end.line, 0 );
                if( rc != ERR_NO_ERR ) {
                    EndUndoGroup( UndoStack );
                    return( rc );
                }
            }
            scol = FindStartOfCurrentLine() - 1;
            ecol = CurrentLine->len - 1;
        }
        DCDisplayAllLines();
        rc = DeleteAndInsertText( scol, ecol );
        EndUndoGroup( UndoStack );
        return( rc );
    }

    /*
     * change text on current line
     */
    rc = ERR_NO_ERR;
    GoToLineNoRelCurs( r->start.line );
    ecol = r->end.column;
    scol = r->start.column;
#ifdef __WIN__
//    GetCurrentLine();
    strcpy( WorkLine->data, CurrentLine->data );
    tmp = WorkLine->data[ecol];
    WorkLine->data[ecol] = '$';
#else
    vecol = VirtualColumnOnCurrentLine( ecol + 1 );
    vecol--;
    ExpandTabsInABuffer( CurrentLine->data, CurrentLine->len, WorkLine->data, EditVars.MaxLine + 1 );
    WorkLine->len = strlen( WorkLine->data );
    tmp = WorkLine->data[vecol];
    WorkLine->data[vecol] = '$';
#endif
    if( WorkLine->len == 0 ) {
        WorkLine->data[1] = '\0';
    }
    EditFlags.InsertModeActive = true;
    GoToColumn( scol + 1, CurrentLine->len );
    EditFlags.InsertModeActive = false;
    DisplayWorkLine( true );
    UnselectRegion();
    DCUpdate();
#ifndef __WIN__
    HiliteAColumnRange( CurrentPos.line, scol, ecol );
#endif

    /*
     * now, get ready to do change
     */
    key = GetNextEvent( false );
#ifdef __WIN__
    WorkLine->data[ecol] = tmp;
#else
    WorkLine->data[vecol] = tmp;
#endif
    DisplayWorkLine( true );
    if( key == VI_KEY( ESC ) && !EditFlags.ChangeLikeVI ) {
        WorkLine->len = -1;
        GoToColumn( scol + 1, CurrentLine->len );
    } else {
        KeyAdd( key );
        rc = DeleteAndInsertText( scol, ecol );
    }
    return( rc );

} /* Change */