📄 file.c
字号:
/*
* This file contains the file i/o stuff. These functions get stuff from
* from the outside world into a form for TDE. The form TDE uses is a
* double linked list. Each node in the list points to the prev and
* the next nodes, if they exist. Also in each node is a pointer to a
* line of text, a line length variable, and a dirty node indicator. In
* earlier versions of TDE, a '\n' was used to terminate a line of text.
* In this version, we must keep an accurate count of characters in
* each line of text, as no character is used to terminate the line.
*
* Each file must contain at least one node. That node is called the
* EOF node. The EOF node terminates the double linked list for each
* file. The EOF node has a NULL pointer in the line field, a NULL
* pointer in the next field, and an EOF in the len field. Here's
* a crude picture of the double linked list structure:
*
* Regular node EOF node
* --------- ---------
* | prev | ---> pointer to prev node | prev | ---> unknown
* | line | ---> "Hello world" | line | ---> NULL
* | len | ---> 11 | len | ---> EOF
* | dirty | ---> TRUE | FALSE | dirty | ---> FALSE
* | next | ---> pointer to next node | next | ---> NULL
* --------- ---------
*
* Implicitly, I am assuming that EOF is defined as (-1) in stdio.h.
*
* The load_file function is probably more complicated than expected, but
* I was trying to read chunks of text that match the disk cluster size
* and/or some multiple of the cache in the disk controller.
*
*
* New editor name: TDE, the Thomson-Davis Editor.
* Author: Frank Davis
* Date: June 5, 1991, version 1.0
* Date: July 29, 1991, version 1.1
* Date: October 5, 1991, version 1.2
* Date: January 20, 1992, version 1.3
* Date: February 17, 1992, version 1.4
* Date: April 1, 1992, version 1.5
* Date: June 5, 1992, version 2.0
* Date: October 31, 1992, version 2.1
* Date: April 1, 1993, version 2.2
* Date: June 5, 1993, version 3.0
*
* This code is released into the public domain, Frank Davis.
* You may distribute it freely.
*/
#include "tdestr.h" /* tde types */
#include "common.h"
#include "define.h"
#include "tdefunc.h"
#include <dos.h> /* for renaming files */
#include <bios.h> /* for direct BIOS keyboard input */
#include <io.h> /* for file attribute code */
#include <fcntl.h> /* open flags */
#if defined( __MSC__ )
#include <errno.h>
#include <sys\types.h> /* S_IWRITE etc */
#endif
#include <sys\stat.h> /* S_IWRITE etc */
/*
* Name: hw_fattrib
* Purpose: To determine the current file attributes.
* Date: December 26, 1991
* Passed: name: name of file to be checked
* Returns: use the function in the tdeasm file to get the DOS file
* attributes. get_fattr() returns 0 or OK if no error.
*/
int hw_fattrib( char *name )
{
register int rc;
int fattr;
rc = get_fattr( name, &fattr );
return( rc == OK ? rc : ERROR );
}
/*
* Name: change_mode
* Purpose: To prompt for file access mode.
* Date: January 11, 1992
* Passed: name: name of file
* line: line to display message
* Returns: OK if file could be changed
* ERROR otherwise
* Notes: function is used to change file attributes for save_as function.
*/
int change_mode( char *name, int line )
{
int result;
int fattr;
register int rc;
char line_buff[(MAX_COLS+1)*2]; /* buffer for char and attribute */
rc = OK;
result = get_fattr( name, &fattr );
if (result != OK)
rc = ERROR;
else if (result == OK && fattr & READ_ONLY) {
/*
* file is read only
*/
save_screen_line( 0, line, line_buff );
/*
* file is write protected. overwrite anyway (y/n)?
*/
set_prompt( main6, line );
if (get_yn( ) != A_YES)
rc = ERROR;
if (rc == OK && set_fattr( name, ARCHIVE ) != OK)
rc = ERROR;
restore_screen_line( 0, line, line_buff );
}
return( rc );
}
/*
* Name: write_file
* Purpose: To write text to a file
* way.
* Date: June 5, 1991
* Passed: name: name of disk file or device
* open_mode: fopen flags to be used in open
* file: pointer to file structure to write
* start: first node to write
* end: last node to write
* block: write a file or a marked block
* Returns: OK, or ERROR if anything went wrong
*/
int write_file( char *name, int open_mode, file_infos *file, long start,
long end, int block )
{
FILE *fp; /* file to be written */
char *p;
char *z = "\x1a";
register int rc;
int bc;
int ec;
int len;
int write_z;
int write_eol;
long number;
line_list_ptr ll;
char *open_string;
char *eol;
size_t eol_count;
write_z = mode.control_z;
switch (open_mode) {
case APPEND :
open_string = "ab";
break;
case OVERWRITE :
default :
open_string = "wb";
break;
}
switch (file->crlf) {
case BINARY :
eol_count = 0;
eol = "";
write_z = FALSE;
break;
case CRLF :
eol_count = 2;
eol = "\r\n";
break;
case LF :
eol_count = 1;
eol = "\n";
break;
default :
assert( FALSE );
}
rc = OK;
if ((fp = fopen( name, open_string )) == NULL || ceh.flag == ERROR)
rc = ERROR;
else {
ec = bc = len = 0;
ll = file->line_list;
if (block == LINE || block == BOX || block == STREAM) {
if (g_status.marked_file == NULL)
rc = ERROR;
else
file = g_status.marked_file;
if (rc != ERROR) {
ll = file->line_list;
for (number=1; number<start && ll->next != NULL; number++)
ll = ll->next;
}
if (rc != ERROR && (block == BOX || block == STREAM)) {
bc = file->block_bc;
ec = file->block_ec;
len = ec + 1 - bc;
}
if (rc != ERROR && block == STREAM) {
if (start == end )
block = BOX;
}
} else {
for (number=1; number<start && ll->next != NULL; number++)
ll = ll->next;
}
p = g_status.line_buff;
if (rc == OK) {
if (block == BOX) {
assert( len >= 0 );
assert( len < MAX_LINE_LENGTH );
for (;start <= end && ll->len != EOF && rc == OK; start++) {
g_status.copied = FALSE;
load_box_buff( p, ll, bc, ec, ' ' );
if (fwrite( p, sizeof( char ), len, fp ) < (unsigned)len ||
ceh.flag == ERROR)
rc = ERROR;
if (rc != ERROR && fwrite( eol, sizeof( char ), eol_count, fp )
< eol_count || ceh.flag == ERROR)
rc = ERROR;
ll = ll->next;
if (ll == NULL)
rc = ERROR;
}
} else {
for (number=start; number <= end && rc == OK && ll->len != EOF;
number++) {
g_status.copied = FALSE;
copy_line( ll );
len = g_status.line_buff_len;
if (block == STREAM) {
if (number == start) {
bc = bc > len ? len : bc;
len = len - bc;
assert( len >= 0 );
memmove( p, p + bc, len );
} else if (number == end) {
++ec;
len = ec > len ? len : ec;
}
}
assert( len >= 0 );
assert( len < MAX_LINE_LENGTH );
if (fwrite( p, sizeof( char ), len, fp ) < (unsigned)len ||
ceh.flag == ERROR)
rc = ERROR;
/*
* if a Control-Z is already at EOF, don't write another one.
*/
write_eol = TRUE;
if (number == end) {
if (file->crlf == CRLF || file->crlf == LF) {
if (len > 0 && *(p + len - 1) == '\x1a') {
write_eol = FALSE;
write_z = FALSE;
}
}
}
if (write_eol == TRUE && rc != ERROR &&
fwrite( eol, sizeof( char ), eol_count, fp ) < eol_count
|| ceh.flag == ERROR)
rc = ERROR;
ll = ll->next;
if (ll == NULL)
rc = ERROR;
}
}
if (rc != ERROR && write_z) {
if (fwrite( z, sizeof( char ), 1, fp ) < 1 || ceh.flag == ERROR)
rc = ERROR;
}
g_status.copied = FALSE;
if (ceh.flag != ERROR) {
if (fclose( fp ) != 0)
rc = ERROR;
}
}
}
return( rc );
}
/*
* Name: hw_save
* Purpose: To save text to a file
* Date: November 11, 1989
* Passed: name: name of disk file
* file: pointer to file structure
* start: first character in text buffer
* end: last character (+1) in text buffer
* block: type of block defined
* Returns: OK, or ERROR if anything went wrong
*/
int hw_save( char *name, file_infos *file, long start, long end, int block )
{
return( write_file( name, OVERWRITE, file, start, end, block ) );
}
/*
* Name: hw_append
* Purpose: To append text to a file.
* Date: November 11, 1989
* Passed: name: name of disk file
* file: pointer to file structure
* start: first character in text buffer
* end: last character (+1) in text buffer
* block: type of defined block
* Returns: OK, or ERROR if anything went wrong
*/
int hw_append( char *name, file_infos *file, long start, long end, int block )
{
return( write_file( name, APPEND, file, start, end, block ) );
}
/*
* Name: load_file
* Purpose: To load a file into the array of text pointers.
* Date: December 1, 1992
* Passed: name: name of disk file
* fp: pointer to file structure
* file_mode: BINARY or TEXT
* bin_len: if opened in BINARY mode, length of node line
* Returns: OK, or ERROR if anything went wrong
*/
int load_file( char *name, file_infos *fp, int *file_mode, int bin_len )
{
FILE *stream; /* stream to read */
int rc;
char buff[MAX_COLS+2];
char line_buff[(MAX_COLS+2)*2]; /* buffer for char and attribute */
text_ptr l;
line_list_ptr ll;
line_list_ptr temp_ll;
unsigned long line_count;
char *e;
char *residue;
int len;
int res;
size_t t1, t2;
int crlf;
int prompt_line;
/*
* initialize the counters and pointers
*/
rc = OK;
len = 1;
line_count = 0;
res = 0;
residue = g_status.line_buff;
prompt_line = g_display.nlines;
fp->length = 0;
fp->undo_count = 0;
fp->undo_top = fp->undo_bot = NULL;
fp->line_list_end = fp->line_list = NULL;
ll = (line_list_ptr)my_malloc( sizeof(line_list_struc), &rc );
if (ll != NULL) {
ll->dirty = FALSE;
ll->len = EOF;
ll->line = NULL;
ll->next = ll->prev = NULL;
fp->undo_top = fp->undo_bot = ll;
}
ll = (line_list_ptr)my_malloc( sizeof(line_list_struc), &rc );
if (ll != NULL) {
ll->dirty = FALSE;
ll->len = EOF;
ll->line = NULL;
ll->next = ll->prev = NULL;
fp->line_list_end = fp->line_list = ll;
}
if ((stream = fopen( name, "rb" )) == NULL || ceh.flag == ERROR ||
rc == ERROR) {
/*
* file not found or error loading file
*/
combine_strings( buff, main7a, name, main7b );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -