/* * SwapToMemoryFromEMSMemory - bring data back from extended memory */ int SwapToMemoryFromEMSMemory( fcb *fb ) { int len; len = FcbSize( fb ); emsRead( fb->xmemaddr, ReadBuffer, len ); GiveBackEMSBlock( fb->xmemaddr ); return( RestoreToNormalMemory( fb, len ) ); } /* SwapToMemoryFromEMSMemory */
/* * JoinFcbs - join two fcbs */ static vi_rc JoinFcbs( fcb *fcb1, fcb *fcb2 ) { unsigned j, k; /* * see if we can merge them */ if( fcb1->end_line != (fcb2->start_line - 1) ) { return( COULD_NOT_MERGE_FCBS ); } j = FcbSize( fcb1 ); k = FcbSize( fcb2 ); if( j + k > (unsigned) MAX_IO_BUFFER ) { return( COULD_NOT_MERGE_FCBS ); } /* * get fcb's if swapped */ FetchFcb( fcb1 ); fcb1->non_swappable = TRUE; FetchFcb( fcb2 ); fcb1->non_swappable = FALSE; /* * update byte count and line numbers */ fcb1->byte_cnt += fcb2->byte_cnt; fcb1->end_line = fcb2->end_line; /* * merge the two sets of lines */ fcb1->lines.tail->next = fcb2->lines.head; fcb2->lines.head->prev = fcb1->lines.tail; fcb1->lines.tail = fcb2->lines.tail; return( ERR_NO_ERR ); } /* JoinFcbs */
/* * CheckCurrentFcbCapacity - check if fcb has exceeded its capacity; if so, * split it */ vi_rc CheckCurrentFcbCapacity( void ) { int bc, bl; line *cl; linenum l; vi_rc rc; /* * check if fcb is full */ if( FcbSize( CurrentFcb ) <= MAX_IO_BUFFER ) { return( ERR_NO_ERR ); } FetchFcb( CurrentFcb ); /* * can't take it, so split it */ cl = CurrentFcb->lines.head; bl = CurrentFcb->byte_cnt / 2; l = CurrentFcb->start_line; for( bc = cl->len + 1; bc < bl; bc += cl->len + 1 ) { cl = cl->next; l++; } rc = SplitFcbAtLine( l, CurrentFile, CurrentFcb ); if( rc != ERR_NO_ERR ) { return( rc ); } /* * check if current line is in new fcb, if so, switch to new fcb; * as well, new fcb had better have the same display status as the old */ CurrentFcb->next->on_display = CurrentFcb->on_display; if( CurrentPos.line > CurrentFcb->end_line ) { CurrentFcb = CurrentFcb->next; FetchFcb( CurrentFcb ); } return( ERR_NO_ERR ); } /* CheckCurrentFcbCapacity */
/* * MakeWriteBlock - create a writeable block from the fcb data */ int MakeWriteBlock( fcb *fb ) { line *cline, *tline; char *buff; int len = 0; /* * build a block */ buff = WriteBuffer; for( cline = fb->lines.head; cline != NULL; cline = cline->next ) { memcpy( buff, cline->data, cline->len ); buff += cline->len; *buff++ = 13; *buff++ = 10; len += cline->len; } /* * swap line data */ for( cline = fb->lines.head; cline != NULL; cline = tline ) { *(U_INT *)buff = cline->inf.word; buff += 2; tline = cline->next; MemFree( cline ); len += 4; /* 2 for these and 2 for c/r l/f */ } if( len != FcbSize( fb ) ) { AbandonHopeAllYeWhoEnterHere( 666 ); } return( len ); } /* MakeWriteBlock */
/* * GetSavebufString - get a string made up of stuff in a savebuf */ vi_rc GetSavebufString( char **data ) { #ifdef __WIN__ savebuf clip; #endif savebuf *tmp; fcb *cfcb; line *cline; vi_rc rc; long len; /* * fetch the savebuf */ rc = DoSavebufNumber(); if( rc != GOT_A_SAVEBUF ) { if( rc == ERR_NO_ERR ) { rc = DO_NOT_CLEAR_MESSAGE_WINDOW; } return( rc ); } #ifdef __WIN__ if( SavebufNumber == CLIPBOARD_SAVEBUF ) { rc = GetClipboardSavebuf( &clip ); if( rc != ERR_NO_ERR ) { return( rc ); } tmp = &clip; } else #endif if( SavebufNumber >= MAX_SAVEBUFS ) { tmp = &SpecialSavebufs[SavebufNumber - MAX_SAVEBUFS]; } else { tmp = &Savebufs[SavebufNumber]; } SavebufNumber = NO_SAVEBUF; /* * get length of stuff */ len = 0L; switch( tmp->type ) { case SAVEBUF_NOP: return( ERR_EMPTY_SAVEBUF ); case SAVEBUF_LINE: len = strlen( tmp->u.data ); break; case SAVEBUF_FCBS: for( cfcb = tmp->u.fcbs.head; cfcb != NULL; cfcb = cfcb->next ) { len += FcbSize( cfcb ); } break; } rc = ERR_NO_ERR; if( len > MAX_STR * 4 ) { rc = ERR_SAVEBUF_TOO_BIG; } else { *data = MemAlloc( len ); switch( tmp->type ) { case SAVEBUF_LINE: strcpy( *data, tmp->u.data ); break; case SAVEBUF_FCBS: **data = '\0'; for( cfcb = tmp->u.fcbs.head; cfcb != NULL; cfcb = cfcb->next ) { FetchFcb( cfcb ); for( cline = cfcb->lines.head; cline != NULL; cline = cline->next ) { strcat( *data, cline->data ); strcat( *data, "\\n" ); } } break; } } #ifdef __WIN__ if( tmp == &clip ) { freeSavebuf( &clip ); } #endif return( rc ); } /* GetSavebufString */
/* * 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 */