예제 #1
0
/*
 * SetWindowCursorForReal - set cursor in current window, if cursorNeedsDisp
 */
void SetWindowCursorForReal( void )
{
    if( !cursorNeedsDisplay || EditFlags.DisplayHold ) {
        return;
    }
    if( CurrentFile == NULL ) {
        HideCursor();
        return;
    }
#ifndef __WIN__
    SetGenericWindowCursor( CurrentWindow, (int) (CurrentPos.line - LeftTopPos.line + 1),
                            VirtualColumnOnCurrentLine( CurrentPos.column ) - LeftTopPos.column );
#else
    // for windows assume tabs to be of lenght 1
    if( !EditFlags.RealTabs ){
        SetGenericWindowCursor( CurrentWindow, (int) (CurrentPos.line - LeftTopPos.line + 1),
                                VirtualColumnOnCurrentLine( CurrentPos.column ) - LeftTopPos.column );
    } else {

        SetGenericWindowCursor( CurrentWindow, (int) (CurrentPos.line - LeftTopPos.line + 1),
                                VirtualColumnOnCurrentLine( CurrentPos.column ) );
    }
#endif

    cursorNeedsDisplay = false;

} /* SetWindowCursorForReal */
예제 #2
0
/*
 * InvokeColSelHook - invoke column hook with specified data
 */
vi_rc InvokeColSelHook( int sc, int ec )
{
    int         j, i;
    char        wordbuff[MAX_STR];
    char        data[MAX_STR + 32];
    int         lne;
#ifndef __WIN__
    int         x1;
    int         has_bord;
#endif

#ifndef __WIN__
    has_bord = WindowAuxInfo( CurrentWindow, WIND_INFO_HAS_BORDER );
    x1 = WindowAuxInfo( CurrentWindow, WIND_INFO_X1 );
    if( LastEvent != VI_KEY( MOUSEEVENT ) ) {
        lne = WindowAuxInfo( CurrentWindow, WIND_INFO_Y1 ) + CurrentPos.line - LeftTopPos.line;
        if( has_bord ) {
            ++lne;
        }
    } else {
        lne = MouseRow;
    }
#else
    if( LastEvent != VI_KEY( FAKEMOUSE ) ) {
        lne = (CurrentPos.line - LeftTopPos.line) * FontHeight( WIN_FONT( &EditWindow ) );
    } else {
        lne = MouseY;
    }
#endif

    j = 0;
    if( ec - sc >= MAX_STR ) {
        ec = sc + MAX_STR - 2;
    }
    for( i = sc - 1; i <= ec - 1; i++ ) {
        wordbuff[j++] = CurrentLine->data[i];
    }
    wordbuff[j] = 0;
#ifndef __WIN__
    sc = x1 + VirtualColumnOnCurrentLine( sc ) - LeftTopPos.column;
    ec = x1 + VirtualColumnOnCurrentLine( ec ) - LeftTopPos.column;
    if( !has_bord ) {
        sc--;
        ec--;
    }
#else
    sc = MyTextExtent( CurrentWindow, WIN_STYLE( &EditWindow ),
        &CurrentLine->data[0], sc );
    ec = MyTextExtent( CurrentWindow, WIN_STYLE( &EditWindow ),
        &CurrentLine->data[0], ec );
#endif
    MySprintf( data, "\"%s\" %d %d %d %d", wordbuff, lne, sc, ec, ec - sc + 1 );
    return( SourceHookData( SRC_HOOK_MOUSE_CHARSEL, data ) );

} /* InvokeColSelHook */
예제 #3
0
/*
 * HiliteAColumnRange - color a specified word on a line
 */
void HiliteAColumnRange( linenum line, int scol, int ecol )
{
    int s, e;

    s = VirtualColumnOnCurrentLine( scol );
    e = VirtualColumnOnCurrentLine( ecol + 1 ) - 1;
    if( scol == 0 ) {
        s = 0;
    }
    changeColorOfDisplayLine( (int) (line - LeftTopPos.line + 1),
        s - LeftTopPos.column, e - LeftTopPos.column, &editw_info.hilight );

} /* HiliteAColumnRange */
예제 #4
0
/*
 * CheckCurrentColumn - check state of current column, return true if need to
 *                      redisplay page
 */
bool CheckCurrentColumn( void )
{
    int     clen, vcp;
    bool    dispall = false;

    clen = VirtualLineLen( CurrentLine->data );
    if( clen == 0 ) {
        clen = 1;
    }
    ValidateCurrentColumn();

    vcp = VirtualColumnOnCurrentLine( CurrentPos.column );

    if( vcp != VirtualColumnDesired ) {
        if( clen >= VirtualColumnDesired ) {
            CurrentPos.column = RealColumnOnCurrentLine( VirtualColumnDesired );
        } else {
            if( EditFlags.InsertModeActive || EditFlags.Modeless ) {
                CurrentPos.column = CurrentLine->len + 1;
            } else {
                CurrentPos.column = CurrentLine->len;
            }
        }
        ValidateCurrentColumn();
        dispall = !CheckLeftColumn();
        /* changed CurrentPos.column - update horiz scrollbar
        */
        PositionHorizontalScrollThumb( current_window_id, LeftTopPos.column );
    }
    VarAddGlobalLong( "C", (long) CurrentPos.column );
    return( dispall );

} /* CheckCurrentColumn */
예제 #5
0
/*
 * ColorAColumnRange - color a specified word on a line
 */
void ColorAColumnRange( int row, int scol, int ecol, type_style *style )
{
    int s, e, t;

    s = VirtualColumnOnCurrentLine( scol );
    e = VirtualColumnOnCurrentLine( ecol );
    if( s > e ) {
        t = s;
        s = e;
        e = t;
    }

    s--;
    e--;
    changeColorOfDisplayLine( row, s - LeftTopPos.column, e - LeftTopPos.column, style );

} /* ColorAColumnRange */
예제 #6
0
/*
 * InitSelectedRegion - set start of selected region
 */
void InitSelectedRegion( void )
{
    SelRgn.lines = FALSE;
    SelRgn.start = CurrentPos;
    SelRgn.end = CurrentPos;
    SelRgn.start_col_v = VirtualColumnOnCurrentLine( CurrentPos.column );
#ifdef __WIN__
    last_start_line = CurrentPos.line;
    last_end_line = CurrentPos.line;
#endif

} /* InitSelectedRegion */
예제 #7
0
/*
 * GoToColumn - go to a specified column
 */
vi_rc GoToColumn( int colno, int maxcol )
{
    int vc;

    if( CurrentFile == NULL ) {
        return( ERR_NO_FILE );
    }

    if( maxcol == 0 ) {
        maxcol = 1;
    }
    if( colno == 0 ) {
        colno = 1;
    }
    if( colno < 1 || colno > maxcol ) {
        return( ERR_NO_SUCH_COLUMN );
    }

    /*
     * compute new location, and re-display text if needed
     */
    VirtualColumnDesired = VirtualColumnOnCurrentLine( colno );
    CurrentPos.column = colno;
    if( !CheckLeftColumn() ) {
        DCDisplayAllLines();
        PositionHorizontalScrollThumb( current_window_id, LeftTopPos.column );
    }

    SetWindowCursor();
    vc = VirtualColumnOnCurrentLine( CurrentPos.column );
    UpdateStatusWindow();
    VarAddGlobalLong( "C", (long) vc );
    UpdateCursorDrag();
    return( ERR_NO_ERR );

} /* GoToColumn */
예제 #8
0
static void ensureCursorDisplayed( void )
{
    int         len, wc, diff;

    if( EditFlags.Modeless && ( CurrentFile != NULL ) ) {
        len = WindowAuxInfo( CurrentWindow, WIND_INFO_TEXT_LINES );
        if( CurrentPos.line < LeftTopPos.line ||
            CurrentPos.line > LeftTopPos.line + len - 1 ) {
            SetCurrentLine( CurrentPos.line );
        }

        wc = VirtualColumnOnCurrentLine( CurrentPos.column ) - LeftTopPos.column;
        if( !ColumnInWindow( wc, &diff ) ) {
            SetCurrentColumn( CurrentPos.column );
        }
    }
}
예제 #9
0
/*
 * InvokeLineSelHook - invoke the mouse selection
 */
vi_rc InvokeLineSelHook( linenum s, linenum e )
{
    char        tmp[32];
    int         lne, col;
#ifndef __WIN__
    int         has_bord;
#endif

#ifndef __WIN__
    if( LastEvent != VI_KEY( MOUSEEVENT ) ) {
        has_bord = WindowAuxInfo( CurrentWindow, WIND_INFO_HAS_BORDER );
        lne = WindowAuxInfo( CurrentWindow, WIND_INFO_Y1 ) + CurrentPos.line - LeftTopPos.line;
        col = WindowAuxInfo( CurrentWindow, WIND_INFO_X1 ) + VirtualColumnOnCurrentLine( CurrentPos.column ) - LeftTopPos.column - 1;
        if( has_bord ) {
            ++lne;
            ++col;
        }
        if( col < 0 ) {
            col = 0;
        }
    } else {
        col = MouseCol;
        lne = MouseRow;
    }
#else
    if( LastEvent != VI_KEY( FAKEMOUSE ) ) {
        /* assume we're not in insert mode *ouch* */
        col = PixelFromColumnOnCurrentLine( CurrentPos.column );
        lne = (CurrentPos.line - LeftTopPos.line) * FontHeight( WIN_FONT( &EditWindow ) );
    } else {
        col = MouseX;
        lne = MouseY;
    }
#endif
    MySprintf( tmp, "%d %d %l %l", lne, col, s, e );
    return( SourceHookData( SRC_HOOK_MOUSE_LINESEL, tmp ) );

} /* InvokeLineSelHook */
예제 #10
0
/*
 * CheckLeftColumn - check if CurrentPos.column and LeftTopPos.column give a position
 *                   in the window; if not, LeftTopPos.column is changed appropriatly
 */
bool CheckLeftColumn( void )
{
    int     diff, wc, pad;
    bool    rc;

    wc = VirtualColumnOnCurrentLine( CurrentPos.column ) - LeftTopPos.column;

    rc = ColumnInWindow( wc, &diff );
    if( !rc ) {
        // |diff| is already at least 1
        pad = ( EditFlags.JumpyScroll ) ? SCROLL_HLINE - 1 : 0;
        if( diff < 0 ) {
            LeftTopPos.column += diff - pad;
        } else {
            LeftTopPos.column += diff + pad;
        }
        if( LeftTopPos.column < 0 ) {
            LeftTopPos.column = 0;
        }
    }
    return( rc );

} /* CheckLeftColumn */
예제 #11
0
/*
 * IMCloseBrace - handle '}' in insert mode
 */
vi_rc IMCloseBrace( void )
{
    int         i, j;
    int         ts;
    fcb         *cfcb;
    line        *cline;
    vi_rc       rc;
    int         newcol;
    i_mark      pos;

    startNewLineUndo();
    insertChar( TRUE, FALSE );
    newcol = CurrentPos.column + 1;
    if( EditFlags.ShowMatch ) {
        ReplaceCurrentLine();
        rc = FindMatch( &pos );
        if( rc == ERR_NO_ERR ) {
            tempMatch( &pos );
        }
        GetCurrentLine();
    }
    if( EditFlags.CMode ) {
        i = 0;
        while( isspace( WorkLine->data[i] ) ) {
            i++;
        }
        if( WorkLine->data[i] == '}' ) {
            /*
             * added a {, so:
             *   find matching }
             *   find out indentation of that line
             *   shift current line over to that indentation
             *   set current indentation to that
             */

            ReplaceCurrentLine();
            rc = findMatchingBrace( &pos );
            if( rc == ERR_NO_ERR ) {
                newcol = VirtualColumnOnCurrentLine( CurrentPos.column );
                CGimmeLinePtr( pos.line, &cfcb, &cline );
                i = FindStartOfALine( cline );
                i = GetVirtualCursorPosition( cline->data, i );
                j = i - VirtualColumnOnCurrentLine( CurrentPos.column );
                ts = EditVars.ShiftWidth;
                if( j > 0 ) {
                    EditVars.ShiftWidth = j;
                    Shift( CurrentPos.line, CurrentPos.line, '>', FALSE );
                } else if( j < 0 ) {
                    EditVars.ShiftWidth = -j;
                    Shift( CurrentPos.line, CurrentPos.line, '<', FALSE );
                }
                EditVars.ShiftWidth = ts;
                newcol = 1 + RealColumnOnCurrentLine( j + newcol );
            }
            GetCurrentLine();
        }
    }
    GoToColumn( newcol, WorkLine->len + 1 );
    return( ERR_NO_ERR );

} /* IMCloseBrace */
예제 #12
0
/*
 * IMTabs - handle tabs in insert mode
 */
vi_rc IMTabs( void )
{
    char        *buff;
    bool        back;
    int         cp, vc, tc, add;
    int         i, j;
    int         len;

    startNewLineUndo();
    CheckAbbrev( abbrevBuff, &abbrevCnt );
    abbrevCnt = 0;
    switch( LastEvent ) {
    case VI_KEY( TAB ):
        if( EditFlags.RealTabs ) {
            if( WorkLine->len + 1 >= EditVars.MaxLine ) {
                break;
            }
            addChar( '\t' );
            GoToColumn( CurrentPos.column + 1, WorkLine->len + 1 );
            checkWrapMargin();
            break;
        }
        /* fall through if not real tabs */
    case VI_KEY( CTRL_T ):
    case VI_KEY( SHIFT_TAB ):
    case VI_KEY( CTRL_D ):
        /*
         * get position of cursor on virtual line
         */
        vc = VirtualColumnOnCurrentLine( CurrentPos.column );
        if( CurrentPos.column - 1 == WorkLine->len && !EditFlags.Modeless ) {
            add = 1;
        } else {
            add = 0;
        }
        j = 0;
        back = FALSE;
        switch( LastEvent ) {
        case VI_KEY( SHIFT_TAB ):
            j = ShiftTab( vc, EditVars.TabAmount );
            back = TRUE;
            break;
        case VI_KEY( CTRL_D ):
            j = ShiftTab( vc, EditVars.ShiftWidth );
            back = TRUE;
            break;
        case VI_KEY( TAB ):
            j = Tab( vc, EditVars.TabAmount );
            break;
        case VI_KEY( CTRL_T ):
            j = Tab( vc, EditVars.ShiftWidth );
            break;
        }
        if( back && (vc - j < 1) ) {
            break;
        } else if( VirtualLineLen( WorkLine->data ) + j >= EditVars.MaxLine ) {
            break;
        }

        /*
         * create a real version of the line
         */
        buff = StaticAlloc();
        ExpandTabsInABufferUpToColumn( CurrentPos.column - 1, WorkLine->data, WorkLine->len, buff, EditVars.MaxLine );
        len = strlen( buff );

        /*
         * put in/suck out the tab
         */
        tc = vc - 1;
        if( back ) {
            for( i = tc; i <= len + 1; i++ ) {
                buff[i - j] = buff[i];
            }
            len -= j;
        } else {
            for( i = len; i >= tc; i-- ) {
                buff[i + j] = buff[i];
            }
            for( i = 0; i < j; i++ ) {
                buff[tc + i] = ' ';
            }
            len += j;
        }

        /*
         * put tabs back in
         */
        if( back ) {
            cp = vc - j;
        } else {
            cp = vc + j;
        }
        if( EditFlags.RealTabs ) {
            ConvertSpacesToTabsUpToColumn( cp, buff, len, WorkLine->data, EditVars.MaxLine );
        } else {
            strcpy( WorkLine->data, buff );
        }
        WorkLine->len = strlen( WorkLine->data );
        StaticFree( buff );
        cp = RealColumnOnCurrentLine( cp ) + add;
        GoToColumn( cp, WorkLine->len + 1 );
        DisplayWorkLine( FALSE );
        break;
    }
    return( ERR_NO_ERR );

} /* IMTabs */
예제 #13
0
/*
 * UpdateStatusWindow - update the status window
 */
void UpdateStatusWindow( void )
{
    char        *str, *ptr;
    char        result[5 * MAX_STR];
    char        *res;
    int         digits;
    long        num;
    bool        use_num;
    int         line;
    char        numstr[12];
    int         format;
    char        c;

    if( BAD_ID( status_window_id ) ||
        EditFlags.DisplayHold ||
        EditFlags.Quiet ||
        !EditFlags.StatusInfo ||
        EditVars.StatusString == NULL ) {
        return;
    }

    res = result;
    line = 1;
    format = FMT_LEFT;
    EditFlags.ModeInStatusLine = false;
    for( str = EditVars.StatusString; (c = *str) != '\0'; ++str ) {
        if( c == '$' ) {
            str++;
            ptr = str;
            while( isdigit( *str ) ) {
                str++;
            }
            if( ptr != str ) {
                digits = strtoul( ptr, NULL, 10 );
            } else {
                digits = 0;
            }
            use_num = false;
            num = 0;
            c = *str;
            if( c == '\0' )
                break;
            switch( c ) {
            case '$':
                *res++ = '$';
                break;
            case 'c':
                *res++ = ',';
                break;
            case 'n':
                *res = 0;
                StatusLine( line, result, format );
                res = result;
                line++;
                break;
            case 'L':
                num = CurrentPos.line;
                use_num = true;
                break;
            case 'C':
                num = VirtualColumnOnCurrentLine( CurrentPos.column );
                use_num = true;
                break;
            case 'D':
#ifdef __WIN__
                GetDateString( res );
#else
                GetDateTimeString( res );
#endif
                res += strlen( res );
                break;
            case 'T':
                GetTimeString( res );
                res += strlen( res );
                break;
            case 'M':
                /* print the desired mode */
                EditFlags.ModeInStatusLine = true;
                GetModeString( res );
                res += strlen( res );
                break;
#ifdef __WIN__
            case 'H':
                GetMenuHelpString( res );
                res += strlen( res );
                break;
            case '[':
                *res++ = STATUS_ESC_CHAR;
                *res++ = STATUS_NEXT_BLOCK;
                break;
            case '|':
                *res++ = STATUS_ESC_CHAR;
                *res++ = STATUS_FORMAT_CENTER;
                break;
            case '>':
                *res++ = STATUS_ESC_CHAR;
                *res++ = STATUS_FORMAT_RIGHT;
                break;
            case '<':
                *res++ = STATUS_ESC_CHAR;
                *res++ = STATUS_FORMAT_LEFT;
                break;
#else
            case '|':
                format = FMT_CENTRE;
                break;
            case '>':
                format = FMT_RIGHT;
                break;
            case '<':
                format = FMT_LEFT;
                break;
#endif
            }
            if( use_num ) {
                ltoa( num, numstr, 10 );
                digits -= strlen( numstr );
                while( digits > 0 ) {
                    *res++ = ' ';
                    digits--;
                }
                ptr = numstr;
                while( *ptr != '\0' ) {
                    *res++ = *ptr++;
                }
            }
        } else {
            *res++ = c;
        }
    }
    *res = 0;
    if( res != result ) {
        StatusLine( line, result, format );
    }

} /* UpdateStatusWindow */
예제 #14
0
static void addSelection( ss_block *ss_start, linenum line_no )
{
    int             sel_start_col, sel_end_col;
    int             sel_start_line, sel_end_line;
    int             tmp, i;
    bool            swap_cols;
    ss_block        *ss, *ss2;
    static ss_block ss_copy[MAX_SS_BLOCKS];
    ss_block        ss_save;

    // don't call me unless something selected
    assert( SelRgn.selected );
    i = 0;

    // get nicely ordered values from SelRgn
    sel_end_col = VirtualColumnOnCurrentLine( SelRgn.end.column ) - 1;
    sel_start_col = SelRgn.start_col_v - 1;
#ifdef __WIN__
    if( EditFlags.RealTabs ) {
        sel_end_col = SelRgn.end.column - 1;
        sel_start_col = SelRgn.start.column - 1;
    }
#endif
    swap_cols = false;
    if( SelRgn.start.line > SelRgn.end.line ) {
        sel_start_line = SelRgn.end.line;
        sel_end_line = SelRgn.start.line;
        swap_cols = true;
    } else {
        sel_start_line = SelRgn.start.line;
        sel_end_line = SelRgn.end.line;
    }
    if( SelRgn.start.line == SelRgn.end.line && sel_start_col > sel_end_col ) {
        swap_cols = true;
    }
    if( swap_cols ) {
        tmp = sel_start_col;
        sel_start_col = sel_end_col;
        sel_end_col = tmp;
    }

    // select entire line
    if( (sel_start_line < line_no && sel_end_line > line_no) ||
        (SelRgn.lines && (sel_start_line == line_no || sel_end_line == line_no)) ) {
        ss_start->type = SE_SELECTION;
        ss_start->end = ss_start->len = BEYOND_TEXT;
        return;
    }

    // select subset within current line
    if( sel_start_line == sel_end_line && sel_start_line == line_no ) {
        if( sel_start_col == sel_end_col ) {
            return;
        }
        ss2 = ss_copy;
        for( ss = ss_start; ss->end < sel_start_col; ++ss ) {
            *ss2 = *ss;
            ss2++;
        }
        ss_save = *ss;
        if( (ss == ss_start && sel_start_col > 0) ||
            (ss != ss_start && (ss - 1)->end + 1 != sel_start_col) ) {
            ss2->type = ss->type;
            ss2->len = ss->len - (ss->end - sel_start_col + 1);
            if( ss2->len != 0 ) {
                ss2->end = sel_start_col - 1;
                ss2++;
            }
        }
        ss2->type = SE_SELECTION;
        ss2->len = sel_end_col - sel_start_col;
        ss2->end = sel_end_col - 1;
        ss2++;
        if( ss_save.end >= sel_end_col ) {
            ss2->type = ss_save.type;
            ss2->len = ss_save.end - sel_end_col + 1;
            if( ss2->len != 0 ) {
                ss2->end = ss_save.end;
                ss2++;
            }
        } else {
            while( ss->end < sel_end_col ) {
                ss++;
            }
            if( ss->end >= sel_end_col ) {
                ss2->type = ss->type;
                ss2->len = ss->end - sel_end_col + 1;
                if( ss2->len != 0 ) {
                    ss2->end = ss->end;
                    ss2++;
                }
            }
        }
        if( ss->end != BEYOND_TEXT ) {
            do {
                ss++;
                *ss2 = *ss;
                ss2++;
            } while( ss->end != BEYOND_TEXT );
        }
        memcpy( ss_start, ss_copy, MAX_SS_BLOCKS * sizeof( ss_block ) );
        return;
    }

    // select from start of selection to far right
    if( sel_start_line == line_no ) {
        ss = ss_start;
        while( ss->end < sel_start_col ) {
            ss++;
        }
        if( (ss == ss_start && sel_start_col > 0) ||
            (ss != ss_start && (ss - 1)->end + 1 != sel_start_col) ) {
            // split block just to the left
            ss->len -= ss->end - sel_start_col + 1;
            if( ss->len != 0 ) {
                ss->end = sel_start_col - 1;
                ss++;
            }
        }
        ss->type = SE_SELECTION;
        ss->end = ss->len = BEYOND_TEXT;
        return;
    }

    // select from far left to end of selection
    if( sel_end_line == line_no && sel_end_col != 0 ) {
        for( ss = ss_start; ss->end < sel_end_col; ++ss ) {
            i++;
        }
        ss2 = ss_start + 1;
        ss_save = *ss2;
        if( ss->end >= sel_end_col ) {
            ss_save.type = ss->type;
            ss_save.len = ss->end - sel_end_col + 1;
            if( ss_save.len != 0 ) {
                ss_save.end = ss->end;
                ss2++;
                i++;
            }
        }
        memmove( ss2, ss + 1, (MAX_SS_BLOCKS - i - 1) * sizeof( ss_block ) );
        ss_start->type = SE_SELECTION;
        ss_start->end = sel_end_col - 1;
        ss_start->len = sel_end_col;
        if( ss2 == ss_start + 2 ) {
            *(ss_start + 1) = ss_save;
        }
        return;
    }

    // otherwise nothing is selected on this line
}
예제 #15
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 */