예제 #1
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 */
예제 #2
0
/*
 * DoneCurrentInsert - finished current insertion of text
 */
void DoneCurrentInsert( bool trim )
{
    if( EditFlags.InsertModeActive ) {
        EditFlags.InsertModeActive = FALSE;
        if( trim ) {
            trimWorkLine();
        }
        if( CurrentPos.column > WorkLine->len ) {
            if( EditFlags.Modeless ) {
                GoToColumnOK( WorkLine->len + 1 );
            } else {
                GoToColumnOK( WorkLine->len );
            }
        }
        doneWithCurrentLine();
        EndUndoGroup( UndoStack );
        if( !EditFlags.Modeless ) {
            NewCursor( CurrentWindow, EditVars.NormalCursorType );
            SetWindowCursor();
        }
        EditFlags.EscapedInsertChar = FALSE;
        EditFlags.NoReplaceSearchString = FALSE;
    }

} /* DoneCurrentInsert */
예제 #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 */
예제 #4
0
/*
 * doneWithCurrentLine - update current line, and update undo record
 */
static void doneWithCurrentLine( void )
{
    startNewLineUndo();
    ReplaceCurrentLine();
    if( currLineRepUndo ) {
        ConditionalCurrentLineReplaceUndoEnd();
        currLineRepUndo = FALSE;
    } else {
        EndUndoGroup( UndoStack );
    }

} /* doneWithCurrentLine */
예제 #5
0
/*
 * TryEndUndoGroup - try to end undo group in last specified stack
 */
void TryEndUndoGroup( undo_stack *cstack )
{
    info        *cinfo;

    for( cinfo = InfoHead; cinfo != NULL; cinfo = cinfo->next ) {
        if( cstack == cinfo->UndoStack ) {
            EndUndoGroup( cstack );
            break;
        }
    }

} /* TryEndUndoGroup */
예제 #6
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 */
예제 #7
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 */
예제 #8
0
/*
 * finiSource - release language variables
 */
static void finiSource( labels *lab, vlist *vl, sfile *sf, undo_stack *atomic )
{
    sfile       *curr, *tmp;
    info        *cinfo;

    if( lab != NULL ) {
        MemFreeList( lab->cnt, lab->name );
        MemFree( lab->pos );
    }

    VarListDelete( vl );

    curr = sf;
    while( curr != NULL ) {
        tmp = curr->next;
        MemFree( curr->data );
        MemFree( curr->arg1 );
        MemFree( curr->arg2 );
        MemFree( curr );
        curr = tmp;
    }

    /*
     * make sure this undo stack is still around
     */
    if( atomic != NULL ) {
        for( cinfo = InfoHead; cinfo != NULL; cinfo = cinfo->next ) {
            if( atomic == cinfo->UndoStack ) {
                break;
            }
        }
        if( cinfo != NULL ) {
            EndUndoGroup( atomic );
        }
    }

} /* finiSource */
예제 #9
0
// insert separator feature
void CSpacerView::MouseDown(BPoint where)
{
static const char *bigsep   = "\n/*\nvoid c------------------------------() {}\n*/\n";
static const char *smallsep = "// ---------------------------------------\n";

EditView *ev = editor.curev;
uint32 buttons;

	if (!ev) return;
	LockWindow();

	int y = ev->scroll.y + ((int)where.y / editor.font_height);

	if (y < 0) y = 0;
	if (y >= ev->nlines) y = (ev->nlines - 1);

	clLine *line = ev->GetLineHandle(y);
	if (!line)
	{
		UnlockWindow();
		return;
	}

	GetMouse(&where, &buttons);
	const char *sep = (buttons & B_SECONDARY_MOUSE_BUTTON) ? smallsep : bigsep;

	BeginUndoGroup(ev);
	ev->action_insert_string(0, y, sep, NULL, NULL);
	EndUndoGroup(ev);

	ev->RedrawView();

	if (sep == bigsep)
		FunctionList->ScanIfNeeded();

	UnlockWindow();
}
예제 #10
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 */
예제 #11
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 */
예제 #12
0
// process the key
void ProcessKey(EditView *ev, int key)
{
uint flags = GetKeyAttr(key);
char MergeToPrior;

	// free xseek mode
	if (ev->cursor.xseekmode != CM_FREE)
	{
		switch(key)
		{
			// these need to maintain the state of the CM_WANT_SCREEN_COORD coordinate
			case B_UP_ARROW:
			case B_DOWN_ARROW:
			case B_PAGE_UP:
			case B_PAGE_DOWN: break;
			
			default: ev->cursor.set_mode(CM_FREE);
		}
	}
	
	// commands which delete selection & contents if a selection is present
	if (flags & KF_SELDEL)
	{
		if (ev->selection.present)
		{
			ev->SelDel();
			
			if (flags & KF_SELDEL_ONLY)
				return;
		}
	}
	
	// create new undo group before executing keys which modify the document
	if (flags & KF_UNDOABLE)
	{
		if (flags & KF_UNDO_MERGEABLE)
		{
			MergeToPrior = undo_can_merge(ev, ev->cursor.x, ev->cursor.y, key);
			
			if (!MergeToPrior)
				BeginUndoGroup(ev);
		}
		else
		{
			MergeToPrior = 0;
			BeginUndoGroup(ev);
		}
	}
	
	if (flags & KF_AFFECTS_SELECTION)	// key can create/remove selection
	{
		if (IsShiftDown() && !ev->selection.present)
			selection_create(ev);
	}
	
	switch(key)
	{
		case B_ESCAPE:
			if (editor.settings.esc_quits_immediately)	// a testmode
			{
				MainWindow->fDoingInstantQuit = true;
				be_app->PostMessage(B_QUIT_REQUESTED);
			}
		break;
		
		case B_LEFT_ARROW: ev->cursor.left(); break;
		case B_RIGHT_ARROW: ev->cursor.right(); break;
		case B_UP_ARROW: ev->cursor.up(); break;
		case B_DOWN_ARROW: ev->cursor.down(); break;
		
		case B_PAGE_DOWN: ev->cursor.pgdn(); break;
		case B_PAGE_UP: ev->cursor.pgup(); break;
		
		case B_HOME: DoHome(ev); break;
		case B_END: DoEnd(ev); break;
		
		case KEY_MOUSEWHEEL_DOWN: ev->scroll_down(3); break;
		case KEY_MOUSEWHEEL_UP: ev->scroll_up(3); break;
		
		case B_ENTER:
			DoEnter(ev);
			editor.stats.CRs_typed++;
			editor.stats.keystrokes_typed++;
		break;
		
		case B_TAB:
		{
			if (IsShiftDown())
			{
				DoShiftTab(ev);
				break;
			}
			
			if (DoTabIndent(ev)) break;
			
			ev->SelDel();
			ev->action_insert_char(ev->cursor.x, ev->cursor.y, TAB);
			ev->cursor.x++;
			
			editor.stats.keystrokes_typed++;
		}
		break;
		
		// BKSP is equivalent to left followed by del
		case B_BACKSPACE:
			if (!ev->cursor.y && !ev->cursor.x) break;
			
			ev->cursor.left();
			
			undo_SetMergeMode(ev, MERGE_BKSP, MergeToPrior);
			ev->action_delete_right(ev->cursor.x, ev->cursor.y, 1);
			editor.stats.keystrokes_typed++;
		break;
		
		case B_DELETE:
			undo_SetMergeMode(ev, MERGE_DEL, MergeToPrior);
			ev->action_delete_right(ev->cursor.x, ev->cursor.y, 1);
			editor.stats.keystrokes_typed++;
		break;
		
		// typing
		default:
		{
			// ignore non-printable keystrokes
			if (key > 127 || key < 9)
				break;
			
			if (editor.InOverwriteMode && \
				ev->cursor.x < ev->curline->GetLength())
			{
				// less than ideal: i wasn't planning on Overwrite Mode when writing
				// the undo feature, so it can't merge undo records that contain both a
				// delete and a insertion. OVR mode isn't used much and undo still works,
				// just one char at a time, so I think it's ok for now but eventually should
				// be looked at.
				if (MergeToPrior)
				{
					MergeToPrior = false;
					BeginUndoGroup(ev);
				}
				
				ev->action_delete_right(ev->cursor.x, ev->cursor.y, 1);
			}
			else
			{
				undo_SetMergeMode(ev, MERGE_TYPING, MergeToPrior);
			}
			
			ev->action_insert_char(ev->cursor.x, ev->cursor.y, key);
			ev->cursor.x++;
			editor.stats.keystrokes_typed++;
		}
		break;
	}
	
	// smart indent (for close quotes)
	if (key == '}' && editor.settings.smart_indent_on_close)
		CloseSmartIndent(ev);
	
	if (flags & KF_AFFECTS_SELECTION)
		ev->ExtendOrDropSel(key);
	
	if (flags & KF_UNDOABLE)
	{
		if (MergeToPrior)
			UpdateMergedUndoGroup(ev);
		else
			EndUndoGroup(ev);
	}
	
	if (!(flags & KF_NO_VIEW_TO_CURSOR))
	{
		ev->MakeCursorVisible();
	}
}
예제 #13
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 */
예제 #14
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 */
예제 #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 */
예제 #16
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 */
예제 #17
0
파일: ex.c 프로젝트: Azarien/open-watcom-v2
/*
 * 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 */
예제 #18
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 */
예제 #19
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 */
예제 #20
0
/*
 * CurrentLineReplaceUndoEnd - actually add the undo
 */
void CurrentLineReplaceUndoEnd( int endgrp )
{
    fcb         *cfcb, *nfcb;
    undo        *top, *delrec;
    fcb_list    fcblist;

    if( !EditFlags.Undo || UndoStack == NULL ) {
        return;
    }
    /*
     * see if we can merge this with the last undo record
     * (provided we are in an open undo group)
     *
     * we need the following undo sequence:
     * END_UNDO_GROUP
     * UNDO_INSERT_LINES
     *      - must have end line one less than the current line
     * UNDO_DELETE_FCBS
     *      - must have last line to insert being two less
     *        than the current (since then the undo for
     *        the current would be on the line ONE less than
     *        the current);
     */
    if( endgrp && UndoStack->OpenUndo > 0 ) {
        top = UndoStack->stack[UndoStack->current];
        if( top != NULL && top->type == END_UNDO_GROUP ) {
            top = top->next;
            if( top != NULL && top->type == UNDO_INSERT_LINES ) {
                if( top->data.del_range.end == CurrentPos.line - 1 ) {
                    delrec = top;
                    top = top->next;
                    if( top != NULL && top->type == UNDO_DELETE_FCBS ) {
                        cfcb = top->data.fcbs.tail;
                        if( cfcb->end_line == CurrentPos.line - 2 ) {
                            /*
                             * FINALLY, we can add it. either
                             * add to current fcb or add a new
                             * fcb
                             */
                            if( (FcbSize( cfcb ) + lineSave->len + 4) <=
                                MAX_IO_BUFFER ) {
                                FetchFcb( cfcb );
                                InsertLLItemAfter( (ss **)&cfcb->lines.tail,
                                    (ss *)cfcb->lines.tail, (ss *)lineSave );
                                cfcb->byte_cnt += lineSave->len + 1;
                                cfcb->end_line++;
                            } else {
                                nfcb = singleLineFcb();
                                nfcb->start_line = nfcb->end_line = cfcb->end_line + 1;
                                InsertLLItemAfter( (ss **)&(top->data.fcbs.tail),
                                    (ss *)cfcb, (ss *)nfcb );
                                nfcb->non_swappable = FALSE;
                            }
                            delrec->data.del_range.end++;
                            Modified( TRUE );
                            return;

                        }
                    }
                }
            }
        }
    }

    /*
     * create an fcb with a single line
     */
    cfcb = singleLineFcb();

    /*
     * build undo action
     */
    fcblist.head = cfcb;
    fcblist.tail = cfcb;
    StartUndoGroupWithPosition( UndoStack, cLine, pageTop, cCol );
    UndoDeleteFcbs( CurrentPos.line - 1, &fcblist, UndoStack );
    UndoInsert( CurrentPos.line, CurrentPos.line, UndoStack );
    if( endgrp ) {
        EndUndoGroup( UndoStack );
    }
    Modified( TRUE );
    cfcb->non_swappable = FALSE;

} /* CurrentLineReplaceUndoEnd */
예제 #21
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 */