filesave.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 507 行
C
507 行
/****************************************************************************
*
* Open Watcom Project
*
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
* ========================================================================
*
* This file contains Original Code and/or Modifications of Original
* Code as defined in and that are subject to the Sybase Open Watcom
* Public License version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
* provided with the Original Code and Modifications, and is also
* available at www.sybase.com/developer/opensource.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
* NON-INFRINGEMENT. Please see the License for the specific language
* governing rights and limitations under the License.
*
* ========================================================================
*
* Description: WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
* DESCRIBE IT HERE!
*
****************************************************************************/
#include <stdio.h>
#include <string.h>
#include "posix.h"
#include <fcntl.h>
#include <errno.h>
#include "vi.h"
#include "source.h"
#include "keys.h"
#ifdef __WIN__
#include "winvi.h"
#include "utils.h"
#endif
static int fileHandle;
/*
* writeRange - write a range of lines in an fcb to current file
*/
static int writeRange( linenum s, linenum e, fcb *cfcb, long *bytecnt )
{
line *cline;
int i,len=0;
char *buff,*data;
if( s > e ) {
return( ERR_NO_ERR );
}
i = GimmeLinePtrFromFcb( s, cfcb, &cline );
if( i ) {
return( i );
}
buff = WriteBuffer;
/*
* copy data into buffer
*/
while( s <= e ) {
data = cline->data;
while( *data != 0 ) {
*buff = *data;
buff++;
data++;
}
len += cline->len;
if( EditFlags.WriteCRLF ) {
*buff++ = 13;
len++;
}
*buff++ = 10;
len++;
cline = cline->next;
s++;
}
/*
* now write the buffer
*/
if( fileHandle == 0 ) {
i = fwrite( WriteBuffer, 1, len, stdout );
} else {
i = write( fileHandle, WriteBuffer, len );
}
if( i != len ) {
return( ERR_FILE_WRITE );
}
*bytecnt += (long) len;
return( ERR_NO_ERR );
} /* writeRange */
/*
* readOnlyCheck - check if writing read-only file okay
*/
static int readOnlyCheck( void )
{
int i;
char tmp[MAX_STR],st[MAX_STR];
MySprintf( tmp, "\"%s\" is read-only, overwrite?", CurrentFile->name );
i = GetResponse( tmp, st );
if( i == GOT_RESPONSE && st[0] == 'y' ) {
return( ERR_NO_ERR );
}
return( ERR_READ_ONLY_FILE );
} /* readOnlyCheck */
#ifdef __WIN__
/*
* SaveFileAs - save data from current file
*/
int SaveFileAs( void )
{
char fn[ FILENAME_MAX ];
char cmd[ 14 + FILENAME_MAX ];
int rc;
rc = SelectFileSave( fn );
if( rc || fn[ 0 ] == '\0' ) {
return( rc );
}
// rename current file
#ifndef __NT__ // this is stupid for all case-preserving systems like NT
FileLower( fn );
#endif
sprintf( cmd, "set filename \"%s\"", fn );
RunCommandLine( cmd );
UpdateLastFileList( fn );
// flag dammit as user must have already said overwrite ok
return( SaveFile( fn, -1L, -1L, TRUE ) );
}
#endif
/*
* SaveFile - save data from current file
*/
int SaveFile( char *name, linenum start, linenum end, int dammit )
{
int i,rc;
bool existflag=FALSE,restpath=FALSE,makerw=FALSE;
char *fn;
fcb *cfcb,*sfcb,*efcb;
linenum s,e,lc;
long bc=0;
int lastst;
if( CurrentFile == NULL ) {
return( ERR_NO_FILE );
}
/*
* get file name
*/
if( name == NULL ) {
if( CurrentFile->viewonly ) {
return( ERR_FILE_VIEW_ONLY );
}
if( CFileReadOnly() ) {
rc = readOnlyCheck();
if( rc ) {
return( ERR_READ_ONLY_FILE );
}
makerw = TRUE;
}
fn = CurrentFile->name;
restpath = TRUE;
} else {
existflag = TRUE;
fn = name;
}
if( fn[0] == 0 ) {
return( ERR_NO_FILE_NAME );
}
if( SameFile( fn, CurrentFile->name ) ) {
if( CurrentFile->viewonly ) {
return( ERR_FILE_VIEW_ONLY );
}
}
if( dammit ) {
existflag = FALSE;
}
/*
* get range and fcbs
*/
if( start == -1L && end == -1L ) {
s = 1L;
i = CFindLastLine( &e );
if( i ) {
return( i );
}
} else {
s = start;
e = end;
}
lc = e-s+1;
i = FindFcbWithLine( s,CurrentFile, &sfcb );
if( i ) {
return( i );
}
i = FindFcbWithLine( e,CurrentFile, &efcb );
if( i ) {
return( i );
}
if( restpath ) {
i = ChangeDirectory( CurrentFile->home );
if( i ) {
return( i );
}
}
if( !CurrentFile->is_stdio ) {
if( makerw ) {
chmod( fn, S_IWRITE | S_IREAD );
}
i = FileOpen( fn, existflag,O_TRUNC | O_WRONLY | O_BINARY | O_CREAT,
WRITEATTRS, &fileHandle);
if( i ) {
Message1( strerror( errno ) );
return( i );
}
} else {
fileHandle = 0;
#ifdef __WATCOMC__
setmode( fileno( stdout ), O_BINARY );
#endif
}
/*
* start writing fcbs
*/
#ifdef __WIN__
ToggleHourglass( TRUE );
#endif
if( CurrentFile->check_for_crlf ) {
if( fileHandle ) {
EditFlags.WriteCRLF = FALSE;
#ifndef __LINUX__
if( FileSysNeedsCR( fileHandle ) ) {
EditFlags.WriteCRLF = TRUE;
}
#endif
} else {
#ifdef __UNIX__
EditFlags.WriteCRLF = FALSE;
#else
EditFlags.WriteCRLF = TRUE;
#endif
}
}
lastst = UpdateCurrentStatus( CSTATUS_WRITING );
cfcb = sfcb;
while( cfcb != efcb ) {
i = writeRange( s, cfcb->end_line, cfcb, &bc );
if( i ) {
#ifdef __WIN__
ToggleHourglass( FALSE );
#endif
UpdateCurrentStatus( lastst );
return( i );
}
s = cfcb->end_line + 1;
cfcb = cfcb->next;
}
/*
* last bit
*/
i = writeRange( s,e,efcb, &bc );
#ifdef __WIN__
ToggleHourglass( FALSE );
#endif
UpdateCurrentStatus( lastst );
if( i ) {
return( i );
}
if( !CurrentFile->is_stdio ) {
i = close( fileHandle );
if( makerw ) {
chmod( fn, S_IREAD );
}
if( i == -1 ) {
Message1( strerror( errno ) );
return( ERR_FILE_CLOSE );
}
}
if( restpath ) {
i = ChangeDirectory( CurrentDirectory );
if( i ) {
return( i );
}
}
FileIOMessage( fn, lc, bc );
return( ERR_NO_ERR );
} /* SaveFile */
/*
* StartSaveExit - prepare to do save & exit of file
*/
int StartSaveExit( void )
{
int key,levent;
/*
* get the next key
*/
levent = LastEvent;
key = GetNextEvent( FALSE );
if( key != levent ) {
if( key == VI_KEY( ESC ) ) {
return( ERR_NO_ERR );
}
return( InvalidKey() );
}
return( SaveAndExit( NULL ) );
} /* StartSaveExit */
/*
* SaveAndExit - save and exit a file
*/
int SaveAndExit( char *fname )
{
int rc;
/*
* save file and get next one
*/
if( CurrentFile != NULL ){
if( CurrentFile->modified ) {
rc = SourceHook( SRC_HOOK_WRITE, ERR_NO_ERR );
if( rc ) {
return( rc );
}
rc = SaveFile( fname, -1, -1, FALSE );
if( rc ) {
return( rc );
}
Modified( FALSE );
}
}
return( NextFile() );
} /* SaveAndExit */
/*
* FilePromptForSaveChanges - give option to save file if modified
*/
bool FilePromptForSaveChanges( file *f )
{
int rc;
char buffer[MAX_STR];
#ifdef __WIN__
MySprintf( buffer, "\"%s\" has been modified - save changes?",
f->name );
BringWindowToTop( Root );
SetWindowPos( Root, HWND_TOPMOST,0,0,0,0, SWP_NOMOVE|SWP_NOSIZE );
rc = MessageBox( Root, buffer, EditorName, MB_YESNO | MB_TASKMODAL );
if( rc == IDYES ) {
rc = SaveFile( NULL, -1, -1, FALSE );
if( rc != ERR_NO_ERR ) {
MySprintf( buffer, "Error saving \"%s\"", f->name );
MessageBox( Root, buffer, EditorName,
MB_OK | MB_TASKMODAL );
} else {
Modified( FALSE );
}
}
SetWindowPos( Root, HWND_NOTOPMOST,0,0,0,0, SWP_NOMOVE|SWP_NOSIZE );
SetWindowPos( Root, HWND_BOTTOM,0,0,0,0, SWP_NOMOVE|SWP_NOSIZE );
#else
char response[MAX_SRC_LINE];
// MySprintf( buffer, "\"%s\" has been modified - save changes (yes|no|cancel)?",
MySprintf( buffer, "\"%s\" has been modified - save changes (yes|no)?",
f->name );
rc = GetResponse( buffer, response );
if( rc == GOT_RESPONSE ) {
switch( response[ 0 ] ) {
case 0:
// if the user hit ENTER then the buffer will be
// a string of 0 chars so act as if y had been hit
case 'y':
case 'Y':
rc = SaveFile( NULL, -1, -1, FALSE );
if( rc != ERR_NO_ERR ) {
MySprintf( buffer, "Error saving \"%s\"", f->name );
Message1( buffer );
} else {
Modified( FALSE );
}
break;
}
}
#endif
/* would return TRUE if we supported a CANCEL option
* the same as the FileExitOptionSaveChanges function below */
return( FALSE );
}
/*
* FileExitOptionSaveChanges - exit file, giving option to save if modified
*/
bool FileExitOptionSaveChanges( file *f )
{
bool aborted = FALSE;
int rc;
char buffer[MAX_STR];
#ifdef __WIN__
MySprintf( buffer, "\"%s\" has been modified - save changes?",
f->name );
rc = MessageBox( Root, buffer, EditorName,
MB_YESNOCANCEL | MB_TASKMODAL );
if( rc == IDYES ) {
rc = SaveFile( NULL, -1, -1, FALSE );
if( rc != ERR_NO_ERR ) {
MySprintf( buffer, "Error saving \"%s\"",
f->name );
MessageBox( Root, buffer, EditorName,
MB_OK | MB_TASKMODAL );
aborted = TRUE;
}
else {
NextFileDammit();
}
} else if( rc == IDCANCEL ) {
aborted = TRUE;
} else {
NextFileDammit();
}
#else
char response[MAX_SRC_LINE];
MySprintf( buffer, "\"%s\" has been modified - save changes (yes|no|cancel)?",
f->name );
rc = GetResponse( buffer, response );
if( rc == GOT_RESPONSE ) {
switch( response[ 0 ] ) {
case 0:
// if the user hit ENTER then the buffer will be
// a string of 0 chars so act as if y had been hit
case 'y':
case 'Y':
SaveAndExit( NULL );
break;
case 'n':
case 'N':
NextFileDammit();
break;
case 'c':
case 'C':
default:
aborted = TRUE;
// return( FALSE );
}
} else {
aborted = TRUE;
}
#endif
return aborted;
}
/*
* FancyFileSave
*/
int FancyFileSave( void )
{
int rc;
if( CurrentFile == NULL )
{
return( ERR_NO_FILE );
}
rc = SaveFile( CurrentFile->name, -1, -1, TRUE );
if( rc == ERR_NO_ERR )
{
CurrentFile->modified = FALSE;
UpdateLastFileList( CurrentFile->name );
}
return( rc );
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?