/* * genItem - generate a src file item */ static void genItem( int token, label where ) { sfile *tsf; tsf = MemAlloc( sizeof( sfile ) ); tsf->arg1 = NULL; tsf->arg2 = NULL; tsf->data = NULL; tsf->token = token; tsf->line = CurrentSrcLine; tsf->hasvar = hasVar; tsf->branchcond = COND_FALSE; if( where != NULL ) { AddString( &(tsf->data), where ); } InsertLLItemAfter( (ss **)&tmpTail, (ss *)tmpTail, (ss *)tsf ); } /* genItem */
/* * InsertNewLine - do just that */ void InsertNewLine( line *who, line_list *linelist, char *data, int copylen, insert_dir dir ) { line *cl; if( copylen <= 0 ) { data = NULL; copylen = 0; } cl = LineAlloc( data, copylen ); if( linelist->head == NULL ) { AddLLItemAtEnd( (ss **)&linelist->head, (ss **)&linelist->tail, (ss *)cl ); } else { if( dir == INSERT_AFTER ) { InsertLLItemAfter( (ss **)&linelist->tail, (ss *)who, (ss *)cl ); } else { InsertLLItemBefore( (ss **)&linelist->head, (ss *)who, (ss *)cl ); } } } /* InsertNewLine */
/* * createNewFile - create new file entry */ static vi_rc createNewFile( char *name, bool same_file ) { int height; window_id cw; info *tmp; vi_rc rc; /* * test that we can create this file */ tmp = NULL; if( !same_file ) { rc = FileExists( name ); if( !(rc == ERR_READ_ONLY_FILE || rc == ERR_NO_ERR || rc == ERR_FILE_EXISTS) ) { return( rc ); } } else { if( name != NULL ) { for( tmp = InfoHead; tmp != NULL; tmp = tmp->next ) { if( !strcmp( tmp->CurrentFile->name, name ) ) { break; } } } if( tmp == NULL ) { return( ERR_FILE_NOT_FOUND ); } if( tmp->CurrentFile->dup_count > MAX_DUPLICATE_FILES ) { return( ERR_WIND_NO_MORE_WINDOWS ); } } /* * get new window */ rc = NewWindow2( &cw, &editw_info ); if( rc != ERR_NO_ERR ) { return( rc ); } #ifdef __WIN__ if( !strncmp( name, "untitled", 8 ) ) { // better yet, pass normal/maximize flag to NewWindow2... ShowWindow( cw, SW_SHOWMAXIMIZED ); } #endif SetBorderGadgets( cw, EditFlags.WindowGadgets ); /* * get new file entry, and read the data */ if( same_file ) { CurrentFile = tmp->CurrentFile; CurrentFile->dup_count++; SetFileWindowTitle( CurrentWindow, CurrentInfo, true ); tmp = CurrentInfo; CurrentInfo = MemAlloc( sizeof( *CurrentInfo ) ); FTSRunCmds( name ); rc = ERR_NO_ERR; } else { bool crlf_reached; crlf_reached = false; tmp = CurrentInfo; CurrentInfo = MemAlloc( sizeof( *CurrentInfo ) ); FTSRunCmds( name ); height = editw_info.y2 - editw_info.y1 + 1; CurrentFile = FileAlloc( name ); rc = OpenFcbData( CurrentFile ); for( ; rc == ERR_NO_ERR; ) { rc = ReadFcbData( CurrentFile, &crlf_reached ); if( rc == ERR_NO_ERR && !CurrentFile->is_stdio ) { if( EditFlags.BreakPressed || !EditFlags.ReadEntireFile ) { if( CurrentFile->fcbs.tail->end_line > height ) { break; } } } } if( rc != ERR_NO_ERR && rc != ERR_FILE_NOT_FOUND && rc != END_OF_FILE ) { MemFree( CurrentInfo ); CurrentInfo = tmp; FileFree( CurrentFile ); CloseAWindow( cw ); return( rc ); } if( rc == ERR_FILE_NOT_FOUND ) { rc = NEW_FILE; EditFlags.NewFile = true; CurrentFile->write_crlf = FileSysNeedsCR( CurrentFile->handle ); #ifdef __UNIX__ CurrentFile->attr = PMODE_RW; #endif } else { rc = ERR_NO_ERR; CurrentFile->write_crlf = crlf_reached; EditFlags.NewFile = false; #ifdef __UNIX__ { struct stat sb; stat( name, &sb ); CurrentFile->attr = sb.st_mode & ~S_IFMT; } #endif } CurrentFile->check_readonly = true; } /* * create info entry */ CurrentPos.line = 0; CurrentPos.column = 1; VirtualColumnDesired = 1; LeftTopPos.line = 1; LeftTopPos.column = 0; if( !same_file ) { AllocateUndoStacks(); } AllocateMarkList(); CurrentWindow = cw; CurrentInfo->DuplicateID = CurrentFile->dup_count; CurrentInfo->CurrentWindow = cw; LangInit( CurrentInfo->fsi.Language ); #ifdef __WIN__ { window_data *wd; wd = DATA_FROM_ID( cw ); wd->info = CurrentInfo; } #endif DCCreate(); SetFileWindowTitle( CurrentWindow, CurrentInfo, true ); /* * set current file info */ CurrentFcb = CurrentFile->fcbs.head; CurrentLine = CurrentFcb->lines.head; if( EditFlags.LineNumbers ) { LineNumbersSetup(); } if( tmp != NULL ) { InsertLLItemAfter( (ss **)&InfoTail, (ss *)tmp, (ss *)CurrentInfo ); } else { AddLLItemAtEnd( (ss **)&InfoHead, (ss **)&InfoTail, (ss *)CurrentInfo ); } return( rc ); } /* createNewFile */
/* * 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 */
/* * SplitFcbAtLine - split a fcb at specified line (specified line goes in * new one) - line 1 causes new fcb to be created at start */ vi_rc SplitFcbAtLine( linenum lne, file *f, fcb *fb ) { linenum sline; int bytecnt = 0; line *cl, *pl; fcb *cfcb; /* * if at start line or end line + 1, no splitting possible */ if( lne == fb->start_line ) { return( NO_SPLIT_CREATED_AT_START_LINE ); } if( lne == fb->end_line + 1 ) { return( NO_SPLIT_CREATED_AT_END_LINE ); } /* * check if we tried to split at line that is not in fcb; */ if( lne > fb->end_line ) { return( ERR_NO_SUCH_LINE ); } /* * get fcb to split, and make sure that it isn't swapped while * we use it */ FetchFcb( fb ); fb->non_swappable = TRUE; /* * get position */ cl = fb->lines.head; for( sline = fb->start_line; sline != lne; sline++ ) { bytecnt += cl->len + 1; cl = cl->next; } /* * add the new fcb */ pl = cl->prev; cfcb = FcbAlloc( f ); InsertLLItemAfter( (ss **)&(f->fcbs.tail), (ss *)fb, (ss *)cfcb ); /* * reset line data for new fcb */ cfcb->start_line = lne; cfcb->end_line = fb->end_line; cfcb->lines.head = cl; cfcb->lines.head->prev = NULL; cfcb->lines.tail = fb->lines.tail; cfcb->byte_cnt = fb->byte_cnt - bytecnt; /* * reset line data for original fcb */ fb->end_line = lne - 1; fb->lines.tail = pl; fb->lines.tail->next = NULL; fb->byte_cnt = bytecnt; /* * check for locked fcb */ if( fb->globalmatch ) { /* * make sure original one should stay locked */ fb->globalmatch = FALSE; for( cl = fb->lines.head; cl != NULL; cl = cl->next ) { if( cl->inf.ld.globmatch ) { fb->globalmatch = TRUE; break; } } /* * see if new one needs to be locked */ for( cl = cfcb->lines.head; cl != NULL; cl = cl->next ) { if( cl->inf.ld.globmatch ) { cfcb->globalmatch = TRUE; break; } } } /* * release fcbs */ fb->non_swappable = FALSE; cfcb->non_swappable = FALSE; return( ERR_NO_ERR ); } /* SplitFcbAtLine */