/* * GoToColumnOnCurrentLine - go to a specified column on the current line */ vi_rc GoToColumnOnCurrentLine( int colno ) { if( CurrentLine == NULL ) { return( ERR_NO_FILE ); } if( EditFlags.Modeless ) { GoToColumn( colno, CurrentLine->len + 1 ); } else { GoToColumn( colno, CurrentLine->len ); } return( ERR_NO_ERR ); } /* GoToColumnOnCurrentLine */
/* * IMDelete - handle DEL key pressed in insert mode */ vi_rc IMDelete( void ) { int wlen; if( CurrentFile == NULL ) { return( ERR_NO_FILE ); } startNewLineUndo(); wlen = WorkLine->len + 1; if( wlen == 0 ) { wlen = CurrentLine->len + 1; } if( EditFlags.Modeless && CurrentPos.column == wlen && CurrentLine->next ) { /* go to beginning of next line */ GoToLineRelCurs( CurrentPos.line + 1 ); GoToColumnOK( 1 ); GetCurrentLine(); } else { GoToColumn( CurrentPos.column + 1, wlen ); if( CurrentPos.column != wlen - 1 || abbrevCnt == 0 ) { abbrevCnt++; /* gets subtracted by IMBackSpace */ } } return( IMBackSpace() ); } /* IMDelete */
/* * 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 */
/* * IMBackSpace - process the backspace key in insert mode */ vi_rc IMBackSpace( void ) { char killedChar, overChar; bool mv_right; bool stay_at_end; int i; if( CurrentFile == NULL ) { return( ERR_NO_FILE ); } startNewLineUndo(); if( abbrevCnt > 0 ) { abbrevCnt--; } if( CurrentPos.column == 1 ) { if( !EditFlags.WrapBackSpace ) { return( ERR_NO_ERR ); } if( CurrentPos.line ==1 ) { return( ERR_NO_ERR ); } stay_at_end = FALSE; if( WorkLine->len == 0 ) { stay_at_end = TRUE; } doneWithCurrentLine(); abbrevCnt = 0; GoToLineRelCurs( CurrentPos.line - 1 ); GoToColumnOnCurrentLine( CurrentLine->len ); mv_right = TRUE; if( CurrentLine->len == 0 ) { mv_right = FALSE; } GenericJoinCurrentLineToNext( FALSE ); if( mv_right && !stay_at_end ) { GoToColumnOnCurrentLine( CurrentPos.column + 1 ); } if( stay_at_end ) { GoToColumnOK( CurrentLine->len + 1 ); } CurrentLineReplaceUndoStart(); currLineRepUndo = TRUE; GetCurrentLine(); return( ERR_NO_ERR ); } killedChar = WorkLine->data[CurrentPos.column - 2]; overChar = WorkLine->data[CurrentPos.column - 1]; for( i = CurrentPos.column - 1; i <= WorkLine->len + 1; i++ ) { WorkLine->data[i - 1] = WorkLine->data[i]; } WorkLine->len--; GoToColumn( CurrentPos.column - 1, WorkLine->len + 1 ); DisplayWorkLine( SSKillsFlags( killedChar ) || SSKillsFlags( overChar ) ); return( ERR_NO_ERR ); } /* IMBackSpace */
/* * 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 */
/* * insertChar - insert a char into the working line */ static vi_rc insertChar( bool add_to_abbrev, bool move_to_new_col ) { if( WorkLine->len == EditVars.MaxLine ) { return( ERR_NO_ERR ); } addChar( LastEvent ); if( move_to_new_col ) { GoToColumn( CurrentPos.column + 1, WorkLine->len + 1 ); } if( abbrevCnt < sizeof( abbrevBuff ) && add_to_abbrev ) { abbrevBuff[abbrevCnt++] = LastEvent; } checkWrapMargin(); return( ERR_NO_ERR ); } /* insertChar */
/* * IMChar - insert a character in insert mode */ vi_rc IMChar( void ) { if( CurrentFile == NULL ) { return( ERR_NO_ERR ); } CurrentFile->need_autosave = TRUE; startNewLineUndo(); if( EditFlags.EscapedInsertChar ) { DisplayWorkLine( SSKillsFlags( LastEvent ) || SSKillsFlags( WorkLine->data[CurrentPos.column - 1] ) ); WorkLine->data[CurrentPos.column - 1] = LastEvent; GoToColumn( CurrentPos.column + 1, WorkLine->len + 1 ); EditFlags.EscapedInsertChar = FALSE; return( ERR_NO_ERR ); } return( insertChar( TRUE, TRUE ) ); } /* IMChar */
/* * IMCloseBracket - handle a ')' being entered in insert mode */ vi_rc IMCloseBracket( void ) { vi_rc rc; i_mark pos; startNewLineUndo(); insertChar( TRUE, FALSE ); if( EditFlags.ShowMatch ) { ReplaceCurrentLine(); rc = FindMatch( &pos ); if( rc == ERR_NO_ERR ) { tempMatch( &pos ); } GetCurrentLine(); } GoToColumn( CurrentPos.column + 1, WorkLine->len + 1 ); return( ERR_NO_ERR ); } /* IMCloseBracket */
/* * CheckAbbrev - look for an abbreviation, and expand it */ bool CheckAbbrev( const char *data, int *ccnt ) { int i, j, owl, col; alias_list *curr; size_t len; if( EditFlags.Modeless ) { return( false ); } /* * get the current string, and matching alias */ len = *ccnt; *ccnt = 0; if( len == 0 ) { return( false ); } curr = checkGenericAlias( data, len, abHead ); if( curr == NULL ) { return( false ); } i = CurrentPos.column - 1 - len; j = CurrentPos.column - 2; /* * replace with full form */ owl = WorkLine->len; WorkLine->len = ReplaceSubString( WorkLine->data, WorkLine->len, i, j, curr->expand, strlen( curr->expand ) ); col = CurrentPos.column + WorkLine->len - owl; GoToColumn( col, WorkLine->len + 1 ); return( true ); } /* CheckAbbrev */
/* * 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 */
/* * 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 */
/* * IMCursorKey - handle cursor keys in insert mode */ vi_rc IMCursorKey( void ) { int wlen; event *ev; int type; wlen = WorkLine->len + 1; if( wlen == 0 ) { wlen = CurrentLine->len + 1; } /* * handle movement on the same line */ switch( LastEvent ) { case VI_KEY( HOME ): GoToColumn( 1, wlen ); abbrevCnt = 0; return( ERR_NO_ERR ); case VI_KEY( END ): GoToColumnOK( wlen ); abbrevCnt = 0; return( ERR_NO_ERR ); case VI_KEY( LEFT ): GoToColumn( CurrentPos.column - 1, wlen ); abbrevCnt = 0; return( ERR_NO_ERR ); case VI_KEY( RIGHT ): GoToColumn( CurrentPos.column + 1, wlen ); abbrevCnt = 0; return( ERR_NO_ERR ); } /* * handle movement that leaves the current line */ ev = &EventList[LastEvent]; if( EditFlags.Modeless ) { type = ev->alt_b.type; } else { type = ev->b.type; } if( needNewUndoForLine ) { if( type == EVENT_REL_MOVE || type == EVENT_ABS_MOVE ) { DoMove( ev ); } else { if( EditFlags.Modeless ) { ev->alt_rtn.old(); } else { ev->rtn.old(); } } return( ERR_NO_ERR ); } if( CurrentPos.column > WorkLine->len ) { GoToColumnOK( WorkLine->len + 1 ); } doneWithCurrentLine(); if( type == EVENT_REL_MOVE || type == EVENT_ABS_MOVE ) { DoMove( ev ); } else { if( EditFlags.Modeless ) { ev->alt_rtn.old(); } else { ev->rtn.old(); } } needNewUndoForLine = TRUE; abbrevCnt = 0; return( ERR_NO_ERR ); } /* IMCursorKey */
/* * insertGenericSavebuf - insert contents of a savebuf before/after current pos */ static vi_rc insertGenericSavebuf( int buf, bool afterflag ) { #ifdef __WIN__ savebuf clip; #endif savebuf *tmp; fcb_list fcblist; fcb *end; int i, scol, len; int maxCursor; vi_rc rc; rc = ModificationTest(); if( rc != ERR_NO_ERR ) { return( rc ); } if( EditFlags.Modeless ) { DeleteSelectedRegion(); SelRgn.selected = false; } #ifdef __WIN__ if( buf == CLIPBOARD_SAVEBUF ) { rc = GetClipboardSavebuf( &clip ); if( rc != ERR_NO_ERR ) { return( rc ); } tmp = &clip; } else #endif if( buf >= MAX_SAVEBUFS ) { tmp = &SpecialSavebufs[buf - MAX_SAVEBUFS]; } else { tmp = &Savebufs[buf]; } switch( tmp->type ) { case SAVEBUF_NOP: rc = ERR_EMPTY_SAVEBUF; break; case SAVEBUF_LINE: /* * get starting data */ len = strlen( tmp->u.data ); if( len + CurrentLine->len >= EditVars.MaxLine ) { rc = ERR_LINE_FULL; break; } if( afterflag ) { scol = CurrentPos.column; } else { scol = CurrentPos.column - 1; } CurrentLineReplaceUndoStart(); GetCurrentLine(); /* * open up line and copy in data */ if( WorkLine->len == 0 ) { scol = 0; } for( i = WorkLine->len; i >= scol; i-- ) { WorkLine->data[i + len] = WorkLine->data[i]; } for( i = 0; i < len; i++ ) { WorkLine->data[i + scol] = tmp->u.data[i]; } WorkLine->len += len; DisplayWorkLine( true ); ReplaceCurrentLine(); CurrentLineReplaceUndoEnd( true ); scol += len + 1; maxCursor = CurrentLine->len; if( EditFlags.Modeless ) { maxCursor++; } if( scol > maxCursor ) { scol = maxCursor; } rc = GoToColumn( scol, maxCursor ); break; case SAVEBUF_FCBS: fcblist.head = NULL; fcblist.tail = NULL; end = tmp->u.fcbs.tail->next; tmp->u.fcbs.tail->next = NULL; CreateDuplicateFcbList( tmp->u.fcbs.head, &fcblist ); tmp->u.fcbs.tail->next = end; if( !EditFlags.LineBased ) { rc = InsertLinesAtCursor( &fcblist, UndoStack ); } else { if( afterflag) { rc = InsertLines( CurrentPos.line, &fcblist, UndoStack ); } else { rc = InsertLines( CurrentPos.line - 1, &fcblist, UndoStack ); } } break; } #ifdef __WIN__ if( tmp == &clip ) { freeSavebuf( &clip ); } #endif EditFlags.Dotable = true; return( rc ); } /* insertGenericSavebuf */
/* * GoToColumnOK - go to a specified column that does not need a max check */ vi_rc GoToColumnOK( int colno ) { return( GoToColumn( colno, colno ) ); } /* GoToColumnOK */
/* * 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 */
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 */