/* * 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 */
static void DoInsert(struct resRes *menuData, MENUITEM **items, int code, MENUITEM *parent) { switch (code) { MENUITEM *newItem; case IDM_DELETE: UndoDelete(menuData, items); (*items)->expanded = FALSE; *items = (*items)->next; ResSetDirty(menuData); InvalidateRect(menuData->activeHwnd, 0, FALSE); break; case IDM_INSERT: ResGetHeap(workArea, menuData); newItem = rcAlloc(sizeof(MENUITEM)); newItem->next = *items; *items = newItem; StringAsciiToWChar(&newItem->text, "New Item", 8); if (parent) { newItem->id = parent->id; parent->id = NULL; } else { newItem->id = ResAllocateMenuId(); } UndoInsert(menuData, items); ResSetDirty(menuData); InvalidateRect(menuData->activeHwnd, 0, FALSE); break; case IDM_INSERT_SEPARATOR: ResGetHeap(workArea, menuData); newItem = rcAlloc(sizeof(MENUITEM)); newItem->next = *items; SetSeparatorFlag(menuData->resource->u.menu, newItem, TRUE); *items = newItem; UndoInsert(menuData, items); ResSetDirty(menuData); InvalidateRect(menuData->activeHwnd, 0, FALSE); break; } }
/* * SplitUpLine - split up a line with SPLIT_CHAR's in them */ linenum SplitUpLine( linenum cl ) { linenum extra = 0; int j, i, k; char *buff; /* * run through, and for every 0x01, make a new line */ for( ;; ) { /* * get current line */ CurrentPos.line = cl + extra; CGimmeLinePtr( CurrentPos.line, &CurrentFcb, &CurrentLine ); GetCurrentLine(); for( i = 0; i <= WorkLine->len; i++ ) { /* * found a place to split. make this line shorter, * and create a new line with the rest of the data * for this line */ if( WorkLine->data[i] == SPLIT_CHAR ) { buff = StaticAlloc(); k = 0; for( j = i + 1; j <= WorkLine->len; j++ ) { buff[k++] = WorkLine->data[j]; } WorkLine->data[i] = 0; WorkLine->len = i; ReplaceCurrentLine(); AddNewLineAroundCurrent( buff, k - 1, INSERT_AFTER ); extra++; StaticFree( buff ); break; } /* * at the very end, undo what we did and go back */ if( WorkLine->data[i] == 0 ) { ReplaceCurrentLine(); UndoInsert( cl + 1, cl + extra, UndoStack ); return( extra ); } } } } /* SplitUpLine */
/* * 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 */
/* * 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 */
/* * IMEnter - process the enter key in insert mode */ vi_rc IMEnter( void ) { char *buff, *buffx; int len, col, el; if( CurrentFile == NULL ) { return( ERR_NO_FILE ); } CurrentFile->need_autosave = TRUE; startNewLineUndo(); CheckAbbrev( abbrevBuff, &abbrevCnt ); abbrevCnt = 0; /* * truncate the working line */ buff = StaticAlloc(); buffx = StaticAlloc(); el = WorkLine->len - CurrentPos.column + 1; if( el > 0 && WorkLine->len > 0 ) { memcpy( buff, &WorkLine->data[CurrentPos.column - 1], el + 1 ); WorkLine->len -= el; WorkLine->data[CurrentPos.column - 1] = 0; } else { el = 0; buff[0] = 0; } len = trimWorkLine(); /* * replace the current line with the working copy */ ReplaceCurrentLine(); if( currLineRepUndo ) { CurrentLineReplaceUndoEnd( FALSE ); currLineRepUndo = FALSE; } /* * create a new line, insert leading spaces if needed * and copy in the truncation */ if( EditFlags.AutoIndent ) { len = GetAutoIndentAmount( buffx, len, FALSE ); el += len; strcat( buffx, buff ); AddNewLineAroundCurrent( buffx, el, INSERT_AFTER ); col = len + 1; } else { AddNewLineAroundCurrent( buff, el, INSERT_AFTER ); col = 1; } UndoInsert( CurrentPos.line + 1, CurrentPos.line + 1, UndoStack ); /* * display the result */ DCDisplayAllLines(); GoToLineRelCurs( CurrentPos.line + 1 ); GoToColumnOK( col ); GetCurrentLine(); StaticFree( buff ); StaticFree( buffx ); return( ERR_NO_ERR ); } /* IMEnter */
/* * 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 */
/* * 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 */