vi_rc OpenFcbData( file *f ) { int handle; vi_rc rc; fcb *cfcb; /* * open file handle if we need to */ rc = ERR_NO_ERR; if( !f->is_stdio ) { handle = -1; ConditionalChangeDirectory( f->home ); rc = FileOpen( f->name, false, O_BINARY | O_RDONLY, 0, &handle ); if( rc != ERR_NO_ERR ) { return( ERR_FILE_OPEN ); } if( handle == -1 ) { rc = ERR_FILE_NOT_FOUND; } else if( f->size == 0 ) { close( handle ); rc = END_OF_FILE; } else { f->handle = handle; } if( rc != ERR_NO_ERR ) { cfcb = FcbAlloc( f ); AddLLItemAtEnd( (ss **)&(f->fcbs.head), (ss **)&(f->fcbs.tail), (ss *)cfcb ); CreateNullLine( cfcb ); } } return( rc ); }
/* * CreateFcbData - create fcb with data from specified buffer */ void CreateFcbData( file *f, int cnt ) { int used, linecnt; fcb *cfcb; /* * get new fcb */ cfcb = FcbAlloc( f ); AddLLItemAtEnd( (ss **)&(f->fcbs.head), (ss **)&(f->fcbs.tail), (ss *)cfcb ); /* * create lines from buffer info */ CreateLinesFromBuffer( cnt, &cfcb->lines, &used, &linecnt, &(cfcb->byte_cnt) ); /* * update position and line numbers */ if( f->fcbs.tail->prev == NULL ) { cfcb->start_line = 1; } else { cfcb->start_line = f->fcbs.tail->prev->end_line + 1; } cfcb->end_line = cfcb->start_line + linecnt - 1; cfcb->non_swappable = false; } /* CreateFcbData */
/* * duplicateFcb - do just that */ static void duplicateFcb( fcb *cfcb, fcb **dfcb ) { line *cline, *nline; /* * get fcb and create a new one */ FetchFcb( cfcb ); cfcb->non_swappable = TRUE; *dfcb = FcbAlloc( NULL ); (*dfcb)->start_line = cfcb->start_line; (*dfcb)->end_line = cfcb->end_line; (*dfcb)->byte_cnt = cfcb->byte_cnt; (*dfcb)->lines.head = (*dfcb)->lines.tail = NULL; /* * copy all lines */ for( cline = cfcb->lines.head; cline != NULL; cline = cline->next ) { nline = LineAlloc( cline->data, cline->len ); AddLLItemAtEnd( (ss **)&((*dfcb)->lines.head), (ss **)&((*dfcb)->lines.tail), (ss *)nline ); } cfcb->non_swappable = FALSE; (*dfcb)->non_swappable = FALSE; } /* duplicateFcb */
/* * singleLineFcb - create fcb from lineSave */ static fcb *singleLineFcb( void ) { fcb *cfcb; cfcb = FcbAlloc( CurrentFile ); if( cfcb == NULL ) { return( NULL ); } cfcb->lines.head = cfcb->lines.tail = lineSave; cfcb->byte_cnt = lineSave->len + 1; return( cfcb ); } /* singleLineFcb */
/* * addAnFcb - add a new fcb and its data */ static int addAnFcb( fcb_list *fcblist, int numbytes ) { fcb *cfcb; int linecnt; int used; cfcb = FcbAlloc( NULL ); AddLLItemAtEnd( (ss **)&fcblist->head, (ss **)&fcblist->tail, (ss *)cfcb ); CreateLinesFromBuffer( numbytes, &cfcb->lines, &used, &linecnt, &(cfcb->byte_cnt) ); if( fcblist->tail->prev == NULL ) { cfcb->start_line = 1; } else { cfcb->start_line = fcblist->tail->prev->end_line + 1; } cfcb->end_line = cfcb->start_line + linecnt - 1; return( used ); } /* addAnFcb */
/* * ReadFcbData - read fcb data */ vi_rc ReadFcbData( file *f, bool *crlf_reached ) { int cnt, used, linecnt; bool eofflag; fcb *cfcb; vi_rc rc; f->bytes_pending = false; /* * go to appropriate location in file */ if( f->is_stdio ) { if( extraData != NULL ) { memcpy( ReadBuffer, extraData, extraDataSize ); MemFreePtr( &extraData ); } } else { rc = FileSeek( f->handle, f->curr_pos ); if( rc != ERR_NO_ERR ) { return( rc ); } } /* * read file data */ if( f->is_stdio ) { cnt = fread( ReadBuffer + extraDataSize, 1, MAX_IO_BUFFER - extraDataSize, stdin ); cnt += extraDataSize; extraDataSize = 0; if( ferror( stdin ) ) { return( ERR_READ ); } } else { cnt = read( f->handle, ReadBuffer, MAX_IO_BUFFER ); if( cnt == -1 ) { return( ERR_READ ); } } /* * get new fcb */ cfcb = FcbAlloc( f ); AddLLItemAtEnd( (ss **)&(f->fcbs.head), (ss **)&(f->fcbs.tail), (ss *)cfcb ); /* * create lines from buffer info */ eofflag = CreateLinesFromFileBuffer( cnt, &cfcb->lines, &used, &linecnt, &(cfcb->byte_cnt), crlf_reached ); if( used == 0 ) { CreateNullLine( cfcb ); eofflag = true; } else { /* * update position */ f->curr_pos += used; if( f->fcbs.tail->prev == NULL ) { cfcb->start_line = 1; } else { cfcb->start_line = f->fcbs.tail->prev->end_line + 1; } if( f->is_stdio && feof( stdin ) && used >= cnt || !f->is_stdio && f->curr_pos >= f->size ) { eofflag = true; if( !EditFlags.LastEOL && ReadBuffer[used - 1] == LF ) { ++linecnt; AddLLItemAtEnd( (ss **)&(cfcb->lines.head), (ss **)&(cfcb->lines.tail), (ss *)LineAlloc( NULL, 0 ) ); } } /* * update line numbers */ cfcb->end_line = cfcb->start_line + linecnt - 1; cfcb->non_swappable = false; } if( eofflag ) { if( !f->is_stdio ) { close( f->handle ); f->handle = -1; } return( END_OF_FILE ); } f->bytes_pending = true; if( f->is_stdio ) { extraDataSize = cnt - used; extraData = MemAlloc( extraDataSize ); memcpy( extraData, ReadBuffer + used, extraDataSize ); } return( ERR_NO_ERR ); } /* ReadFcbData */
/* * 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 */