Category : Word Processors
Archive   : TDE32A.ZIP
Filename : FILE.C

 
Output of file : FILE.C contained in archive : TDE32A.ZIP
/*
* 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
* Date: August 29, 1993, version 3.1
* Date: November 13, 1993, version 3.2
*
* 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"

#if !defined( __UNIX__ )
#include /* for renaming files */
#include /* for direct BIOS keyboard input */
#include /* for file attribute code */
#if defined( __MSC__ )
#include
#include /* S_IWRITE etc */
#endif
#include /* S_IWRITE etc */
#endif

#include /* open flags */

/*
* 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 :
eol_count = 0;
eol = "";
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; numbernext != 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; numbernext != 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;
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;
char temp[MAX_COLS+2];
#if defined( __UNIX__ )
chtype display_buff[MAX_COLS+2]; /* chtype is defined in curses.h */
#else
char display_buff[(MAX_COLS+2)*2];
#endif

/*
* 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( temp, main7a, name, main7b );
save_screen_line( 0, prompt_line, display_buff );
set_prompt( temp, prompt_line );
getkey( );
restore_screen_line( 0, prompt_line, display_buff );
if (fp->line_list != NULL)
my_free( fp->line_list );
if (fp->undo_top != NULL)
my_free( fp->undo_top );
rc = ERROR;
} else {
if (*file_mode == BINARY) {
mode.trailing = FALSE;
crlf = BINARY;
if (bin_len < 0 || bin_len > READ_LENGTH)
bin_len = DEFAULT_BIN_LENGTH;
for (; rc == OK;) {
t1 = fread( g_status.line_buff, sizeof(char), bin_len, stream );
if (ferror( stream ) || ceh.flag == ERROR) {
combine_strings( temp, main9, name, "'" );
error( WARNING, prompt_line, temp );
rc = ERROR;
} else if (t1) {

assert( t1 < MAX_LINE_LENGTH );

l = (text_ptr)my_malloc( t1 * sizeof(char), &rc );
temp_ll = (line_list_ptr)my_malloc( sizeof(line_list_struc), &rc );

if (rc != ERROR) {

/*
* if everything is everything, copy from io buff to
* dynamic mem.
*/
if (t1 > 0)
my_memcpy( l, g_status.line_buff, t1 );

++line_count;
temp_ll->line = l;
temp_ll->dirty = FALSE;
temp_ll->len = t1;
insert_node( fp, ll, temp_ll );
ll = temp_ll;
} else
rc = show_file_2big( name, prompt_line, temp_ll, l );
} else
break;
}
} else {
crlf = LF;
for (; rc == OK;) {
t1 = fread( g_status.line_buff, sizeof(char), READ_LENGTH, stream );
if (ferror( stream ) || ceh.flag == ERROR) {
combine_strings( temp, main9, name, "'" );
error( WARNING, prompt_line, temp );
rc = ERROR;
} else {

/*
* "e" walks down io buffer 1 looking for end of lines. "t1"
* keeps count of number of characters in io buffer 1.
*/
e = g_status.line_buff;
while (t1 && rc == OK) {

/*
* while "t1" is not zero and "len" is less than max line length,
* let "e" walk down the buffer until it find .
*/
for (; t1 && len < READ_LENGTH && *e != '\n'; len++, e++, t1--);

/*
* if "t1" is not zero, we either found a or the line
* length max'd out.
*/
if (t1 || len >= READ_LENGTH) {

if (len > 1 && *e == '\n') {
if (len - res == 1) {
if (*(residue + res - 1) == '\r') {
--len;
--res;
crlf = CRLF;
}
} else {
if (*(e - 1) == '\r') {
--len;
crlf = CRLF;
}
}
}
if (len > 0)
--len;

assert( len >= 0 );
assert( len < MAX_LINE_LENGTH );

/*
* allocate space for relocatable array of line pointers and
* allocate space for the line we just read.
*/
l = (text_ptr)my_malloc( len * sizeof(char), &rc );
temp_ll =
(line_list_ptr)my_malloc( sizeof(line_list_struc), &rc );

if (rc != ERROR) {

/*
* if everything is everything, copy from io buff to
* dynamic mem. "residue" keeps up with the beginning
* of line in io buffer.
*/
if (res > 0) {

assert( res >= 0 );
assert( len - res >= 0 );

if (res > 0)
my_memcpy( l, residue, res );
if (len - res > 0)
my_memcpy( l + res, g_status.line_buff, len - res );
res = 0;
} else
if (len > 0)
my_memcpy( l, residue, len );

++line_count;
temp_ll->line = l;
temp_ll->dirty = FALSE;
temp_ll->len = len;
insert_node( fp, ll, temp_ll );
ll = temp_ll;

/*
* reset io buffer pointers and counters.
*/
len = 1;
if (t1 == 0)
residue = g_status.tabout_buff;
else {
t1--;
residue = t1 == 0 ? g_status.tabout_buff : ++e;
}
} else
rc = show_file_2big( name, prompt_line, temp_ll, l );
} else if (len < READ_LENGTH ) {
if (!feof( stream ))
res = len - 1;
} else {
error( WARNING, prompt_line, main9a );
rc = ERROR;
}
}
}

if (rc != OK)
break;

/*
* we may have read all lines that end in '\n', but there may
* be some residue after the last '\n'. ^Z is a good example.
*/
if (feof( stream )) {
if (len > 1) {
--len;
if (t1 == 0)
--e;

assert( len >= 0 );
assert( len < MAX_LINE_LENGTH );

/*
* allocate space for relocatable array of line pointers and
* allocate space for the line we just read.
*/
l = (text_ptr)my_malloc( len * sizeof(char), &rc );
temp_ll =
(line_list_ptr)my_malloc( sizeof(line_list_struc), &rc );

if (rc != ERROR) {

/*
* if everything is everything, copy from io buff to
* dynamic mem. "residue" keeps up with the beginning
* of line in io buffer.
*/
if (res > 0) {

assert( res >= 0 );
assert( res < MAX_LINE_LENGTH);
assert( len - res >= 0 );
assert( len - res < MAX_LINE_LENGTH);

if (res > 0 )
my_memcpy( l, residue, res );
if (len - res > 0)
my_memcpy( l + res, g_status.line_buff, len - res );
} else
if (len > 0)
my_memcpy( l, residue, len );
++line_count;
temp_ll->line = l;
temp_ll->dirty = FALSE;
temp_ll->len = len;
insert_node( fp, ll, temp_ll );
} else
rc = show_file_2big( name, prompt_line, temp_ll, l );
}
break;
}

t2 = fread( g_status.tabout_buff, sizeof(char), READ_LENGTH, stream );
if (ferror( stream ) || ceh.flag == ERROR) {
combine_strings( temp, main9, name, "'" );
error( WARNING, prompt_line, temp );
rc = ERROR;
} else if (rc == OK) {
e = g_status.tabout_buff;
while (t2 && rc == OK) {
for (; t2 && len < READ_LENGTH && *e != '\n'; len++, e++, t2--);
if (t2 || len >= READ_LENGTH) {

if (len > 1 && *e == '\n') {
if (len - res == 1) {
if (*(residue + res - 1) == '\r') {
--len;
--res;
crlf = CRLF;
}
} else {
if (*(e - 1) == '\r') {
--len;
crlf = CRLF;
}
}
}
if (len > 0)
--len;

assert( len >= 0 );
assert( len < MAX_LINE_LENGTH );

l = (text_ptr)my_malloc( len * sizeof(char), &rc );
temp_ll =
(line_list_ptr)my_malloc( sizeof(line_list_struc), &rc );

if (rc != ERROR) {
if (res > 0) {

assert( res >= 0 );
assert( res < MAX_LINE_LENGTH);
assert( len - res >= 0 );
assert( len - res < MAX_LINE_LENGTH);

if (res > 0)
my_memcpy( l, residue, res );
if (len - res > 0)
my_memcpy( l+res, g_status.tabout_buff, len - res );
res = 0;
} else
if (len > 0)
my_memcpy( l, residue, len );

++line_count;
temp_ll->line = l;
temp_ll->dirty = FALSE;
temp_ll->len = len;
insert_node( fp, ll, temp_ll );
ll = temp_ll;

len = 1;
if (t2 == 0)
residue = g_status.line_buff;
else {
t2--;
residue = t2 == 0 ? g_status.line_buff : ++e;
}
} else
rc = show_file_2big( name, prompt_line, temp_ll, l );
} else if (len < READ_LENGTH) {
if (!feof( stream ))
res = len - 1;
} else {
error( WARNING, prompt_line, main9a );
rc = ERROR;
}
}
}

if (rc != ERROR && feof( stream )) {
if (len > 1) {
--len;
if (t2 == 0)
--e;

assert( len >= 0 );
assert( len < MAX_LINE_LENGTH );

l = (text_ptr)my_malloc( len * sizeof(char), &rc );
temp_ll =
(line_list_ptr)my_malloc( sizeof(line_list_struc), &rc );

if (rc != ERROR) {
if (res > 0) {

assert( res >= 0 );
assert( res < MAX_LINE_LENGTH);
assert( len - res >= 0 );
assert( len - res < MAX_LINE_LENGTH);

if (res > 0)
my_memcpy( l, residue, res );
if (len - res > 0)
my_memcpy( l+res, g_status.tabout_buff, len - res );
} else
if (len > 0)
my_memcpy( l, residue, len );

++line_count;
temp_ll->line = l;
temp_ll->dirty = FALSE;
temp_ll->len = len;
insert_node( fp, ll, temp_ll );
} else
rc = show_file_2big( name, prompt_line, temp_ll, l );
}
break;
}
}
*file_mode = crlf;
}

/*
* close the file
*/
fp->length = line_count;
}
if (stream != NULL)
fclose( stream );
return( rc );
}


/*
* Name: insert_node
* Purpose: To insert a node into a double linked list
* Date: December 1, 1992
* Passed: fp: pointer to file structure that owns the double linked list
* current: pointer to current node in double linked list
* new: pointer to new node to insert into double linked list
* Notes: if the current list pointer is the last node in the list, insert
* new code behind current node.
*/
void insert_node( file_infos *fp, line_list_ptr current, line_list_ptr new )
{

/*
* standard double linked list insert
*/
if (current->next != NULL) {
current->next->prev = new;
new->next = current->next;
current->next = new;
new->prev = current;
/*
* if the current node is the NULL node, insert the new node behind current
*/
} else {
new->next = current;
if (current->prev != NULL)
current->prev->next = new;
new->prev = current->prev;
current->prev = new;
if (new->prev == NULL)
fp->line_list = new;
}
}


/*
* Name: show_file_2big
* Purpose: tell user we ran out of room loading file
* Date: December 1, 1992
* Passed: name: name of disk file
* line: line to display messages
* ll: double linked list pointer
* t: text line pointer
* Returns: WARNING
* Notes: one or both of the malloc requests overflowed the heap. free the
* dynamic if allocated.
*/
int show_file_2big( char *name, int prompt_line, line_list_ptr ll, text_ptr t )
{
char temp[MAX_COLS+2];

combine_strings( temp, main10a, name, main10b );
error( WARNING, prompt_line, temp );
if (t != NULL)
my_free( t );
if (ll != NULL)
my_free( ll );
return( WARNING );
}


/*
* Name: backup_file
* Purpose: To make a back-up copy of current file.
* Date: June 5, 1991
* Passed: window: current window pointer
*/
int backup_file( TDE_WIN *window )
{
char *old_line_buff;
char *old_tabout_buff;
int old_line_buff_len;
int old_tabout_buff_len;
int old_copied;
int rc;
file_infos *file;

rc = OK;
file = window->file_info;
if (file->backed_up == FALSE && file->modified == TRUE) {
old_copied = g_status.copied;
old_line_buff_len = g_status.line_buff_len;
old_line_buff = calloc( MAX_LINE_LENGTH, sizeof(char) );
old_tabout_buff_len = g_status.tabout_buff_len;
old_tabout_buff = calloc( MAX_LINE_LENGTH, sizeof(char) );

if (old_line_buff != NULL && old_tabout_buff != NULL) {
memcpy( old_line_buff, g_status.line_buff, MAX_LINE_LENGTH );
memcpy( old_tabout_buff, g_status.tabout_buff, MAX_LINE_LENGTH );
if ((rc = save_backup( window )) != ERROR)
file->backed_up = TRUE;
else
rc = ERROR;
memcpy( g_status.line_buff, old_line_buff, MAX_LINE_LENGTH );
memcpy( g_status.tabout_buff, old_tabout_buff, MAX_LINE_LENGTH );
g_status.line_buff_len = old_line_buff_len;
g_status.tabout_buff_len = old_tabout_buff_len;
g_status.copied = old_copied;
} else {
error( WARNING, window->bottom_line, main4 );
rc = ERROR;
}
if (old_line_buff != NULL)
free( old_line_buff );
if (old_tabout_buff != NULL)
free( old_tabout_buff );
}
return( rc );
}


/*
* Name: edit_file
* Purpose: To allocate space for a new file structure and set up some
* of the relevant fields.
* Date: June 5, 1991
* Modified: November 13, 1993, Frank Davis per Byrial Jensen
* Passed: name: name of the file to edit
* file_mode: BINARY or TEXT
* bin_length: if opened in BINARY mode, length of binary lines
* Returns: OK if file structure could be created
* ERROR if out of memory
*
* Change: file->next_letter is initialized to 0 instead 'a'
*/
int edit_file( char *name, int file_mode, int bin_length )
{
int rc; /* return code */
int existing;
int line;
int rcol;
register file_infos *file; /* file structure for file belonging to new window */
file_infos *fp;
long found_line;
line_list_ptr ll;
line_list_ptr temp_ll;

line = g_display.nlines;
rc = OK;
/*
* allocate a file structure for the new file
*/
file = (file_infos *)calloc( 1, sizeof(file_infos) );
if (file == NULL) {
error( WARNING, line, main4 );
rc = ERROR;
}
existing = FALSE;
if (rc == OK && hw_fattrib( name ) == OK) {
existing = TRUE;
/*
* g_status.temp_end is set last character read in file
*/

if (g_status.command != DefineGrep &&
g_status.command != DefineRegXGrep &&
g_status.command != RepeatGrep)
rc = load_file( name, file, &file_mode, bin_length );
else {
if (g_status.sas_defined) {
rc = load_file( name, file, &file_mode, bin_length );
if (rc != ERROR) {
found_line = 1L;
rcol = 0;
if (g_status.sas_search_type == BOYER_MOORE)
ll = search_forward( file->line_list, &found_line,
(size_t *)&rcol );
else
ll = regx_search_forward( file->line_list, &found_line,
&rcol );
if (ll == NULL)
rc = ERROR;
else {
g_status.sas_rline = found_line;
g_status.sas_rcol = rcol;
g_status.sas_ll = ll;
}
}
} else
rc = ERROR;
}
} else {
if (ceh.flag == ERROR)
rc = ERROR;
else {
existing = FALSE;
file->length = 0l;
file->undo_top = file->undo_bot = NULL;
file->line_list_end = file->line_list = NULL;
file->undo_count = 0;
ll = (line_list_ptr)my_malloc( sizeof(line_list_struc), &rc );
if (ll != NULL) {
ll->line = NULL;
ll->next = ll->prev = NULL;
ll->dirty = FALSE;
ll->len = EOF;
file->undo_top = file->undo_bot = ll;
} else
rc = ERROR;

ll = (line_list_ptr)my_malloc( sizeof(line_list_struc), &rc );
if (ll != NULL) {
ll->line = NULL;
ll->next = ll->prev = NULL;
ll->dirty = FALSE;
ll->len = EOF;
file->line_list_end = file->line_list = ll;
} else
rc = ERROR;
if (rc == ERROR) {
if (file->undo_top != NULL)
my_free( file->undo_top );
if (file->line_list != NULL)
my_free( file->line_list );
} else
if (file_mode == TEXT)
#if defined( __UNIX__ )
file_mode = LF;
#else
file_mode = CRLF;
#endif
}
}

if (rc != ERROR) {
/*
* add file into list
*/
file->prev = NULL;
file->next = NULL;
if (g_status.file_list == NULL)
g_status.file_list = file;
else {
fp = g_status.current_file;
file->prev = fp;
if (fp->next)
fp->next->prev = file;
file->next = fp->next;
fp->next = file;
}

/*
* set up all the info we need to know about a file.
*/

assert( file_mode == CRLF || file_mode == LF || file_mode == BINARY );
assert( strlen( name ) < (size_t)g_display.ncols );

strcpy( file->file_name, name );
#if defined( __UNIX__ )
get_fattr( name, &file->file_attrib );
#else
get_fattr( name, (int *)&file->file_attrib );
#endif
file->block_type = NOTMARKED;
file->block_br = file->block_er = 0l;
file->block_bc = file->block_ec = 0;
file->ref_count = 0;
file->modified = FALSE;
file->backed_up = FALSE;
file->new_file = !existing;
file->next_letter = 0;
file->file_no = ++g_status.file_count;
file->crlf = file_mode;
g_status.current_file = file;
make_backup_fname( file );
} else if (file != NULL) {
/*
* free the line pointers and linked list of line pointers.
*/
ll = file->undo_top;
while (ll != NULL) {
temp_ll = ll->next;
if (ll->line != NULL)
my_free( ll->line );
my_free( ll );
ll = temp_ll;
}

ll = file->line_list;
while (ll != NULL) {
temp_ll = ll->next;
if (ll->line != NULL)
my_free( ll->line );
my_free( ll );
ll = temp_ll;
}

#if defined( __MSC__ )
_fheapmin( );
#endif

free( file );
}
return( rc );
}


/*
* Name: edit_another_file
* Purpose: Bring in another file to editor.
* Date: June 5, 1991
* Passed: window: pointer to current window
* Notes: New window replaces old window. Old window becomes invisible.
*/
int edit_another_file( TDE_WIN *window )
{
#if defined( __UNIX__ )
char fname[PATH_MAX]; /* new name for file */
#else
char fname[MAX_COLS]; /* new name for file */
char spdrive[_MAX_DRIVE]; /* splitpath drive buff */
char spdir[_MAX_DIR]; /* splitpath dir buff */
char spname[_MAX_FNAME]; /* splitpath fname buff */
char spext[_MAX_EXT]; /* splitpath ext buff */
#endif
register TDE_WIN *win; /* put window pointer in a register */
int rc;
int file_mode;
int bin_length;

win = window;
entab_linebuff( );
if (un_copy_line( win->ll, win, TRUE ) == ERROR)
return( ERROR );
/*
* read in name, no default
*/
fname[0] = '\0';
/*
* file name to edit
*/
if ((rc = get_name( ed15, win->bottom_line, fname,
g_display.message_color )) == OK && *fname != '\0') {

#if defined( __UNIX__ )

assert( strlen( fname ) < PATH_MAX );

/*
* X_OK is defined in unistd.h and tests for execute permission
*/
if (access( fname, X_OK ) != ERROR) {
file_mode = BINARY;
bin_length = g_status.file_chunk;
} else {
file_mode = TEXT;
bin_length = 0;
}
#else

file_mode = TEXT;
bin_length = 0;

assert( strlen( fname ) < (size_t)g_display.ncols );

_splitpath( fname, spdrive, spdir, spname, spext );
if (stricmp( spext, ".exe" ) == 0 || stricmp( spext, ".com" ) == 0) {
file_mode = BINARY;
bin_length = g_status.file_chunk;
}
#endif
rc = attempt_edit_display( fname, LOCAL, file_mode, bin_length );
if (rc == OK)
show_avail_mem( );
}
return( rc );
}


/*
* Name: attempt_edit_display
* Purpose: try to load then display a file
* Date: June 5, 1991
* Passed: fname: file name to load
* update_type: update current window or entire screen
* file_mode: BINARY or TEXT
* bin_len: if opened in BINARY mode, length of binary lines
* Notes: When we first start the editor, we need to update the entire
* screen. When we load in a new file, we only need to update
* the current window.
*/
int attempt_edit_display( char *fname, int update_type, int file_mode,
int bin_len )
{
register int rc;
TDE_WIN *win;

rc = edit_file( fname, file_mode, bin_len );
if (rc != ERROR) {
rc = initialize_window( );
if (rc != ERROR) {
win = g_status.current_window;
if (update_type == LOCAL) {
if (g_status.command != DefineGrep &&
g_status.command != DefineRegXGrep &&
g_status.command != RepeatGrep)
redraw_current_window( win );
show_file_count( g_status.file_count );
show_window_count( g_status.window_count );
show_avail_mem( );
} else if (update_type == GLOBAL)
redraw_screen( win );
if (win->file_info->new_file) {
g_status.command = AddLine;
insert_newline( win );
win->file_info->modified = FALSE;
}
}
}
return( rc );
}


/*
* Name: file_file
* Purpose: To file the current file to disk.
* Date: September 17, 1991
* Passed: window: pointer to current window
*/
int file_file( TDE_WIN *window )
{
if (save_file( window ) == OK)
finish( window );
return( OK );
}


/*
* Name: save_file
* Purpose: To save the current file to disk.
* Date: June 5, 1991
* Passed: window: pointer to current window
* Notes: If anything goes wrong, then the modified flag is set.
* If the file is saved successfully, then modified flag is
* cleared.
*/
int save_file( TDE_WIN *window )
{
register file_infos *file;
int rc;
line_list_ptr temp_ll;
#if defined( __UNIX__ )
char temp[PATH_MAX+2];
#else
char temp[MAX_COLS+2];
#endif

entab_linebuff( );
if (un_copy_line( window->ll, window, TRUE ) == ERROR)
return( ERROR );
file = window->file_info;
if (file->modified == FALSE)
return( OK );
/*
* set up file name
*/
#if defined( __UNIX__ )
assert( strlen( file->file_name ) < PATH_MAX );
#else
assert( strlen( file->file_name ) < (size_t)g_display.ncols );
#endif

strcpy( temp, file->file_name );

/*
* see if there was a file name - if not, then make the user
* supply one.
*/
if (strlen( temp ) == 0)
rc = save_as_file( window );
else {
/*
* save the file
*/
rc = write_to_disk( window, temp );
if (rc != ERROR) {
file->modified = FALSE;
file->new_file = FALSE;
}
}

/*
* clear the dirty flags
*/
if (rc == OK) {
temp_ll = window->file_info->line_list;
for (; temp_ll->len != EOF; temp_ll=temp_ll->next)
temp_ll->dirty = FALSE;
window->file_info->dirty = GLOBAL;
}

return( rc );
}


/*
* Name: save_backup
* Purpose: To save a backup copy of the current file to disk.
* Date: June 5, 1991
* Passed: window: pointer to current window
*/
int save_backup( TDE_WIN *window )
{
/*
* set up file name
*/
return( write_to_disk( window, window->file_info->backup_fname ) );
}


/*
* Name: save_as_file
* Purpose: To save the current file to disk, but under a new name.
* Date: June 5, 1991
* Passed: window: pointer to current window
*/
int save_as_file( TDE_WIN *window )
{
int prompt_line;
int rc;
register TDE_WIN *win; /* put window pointer in a register */
line_list_ptr temp_ll;
#if defined( __UNIX__ )
char answer[PATH_MAX+2];
chtype display_buff[MAX_COLS+2]; /* chtype is defined in curses.h */
mode_t fattr;
#else
char answer[MAX_COLS+2];
char display_buff[(MAX_COLS+2)*2];
int fattr;
#endif

win = window;
entab_linebuff( );
if (un_copy_line( win->ll, win, TRUE ) == ERROR)
return( ERROR );
/*
* read in name
*/
prompt_line = win->bottom_line;
save_screen_line( 0, prompt_line, display_buff );

answer[0] = '\0';
/*
* new file name:
*/
if ((rc = get_name( utils9, prompt_line, answer,
g_display.message_color )) == OK && *answer != '\0') {

#if defined( __UNIX__ )
/*
* make sure it is OK to overwrite any existing file
*/
rc = get_fattr( answer, &fattr );
if (rc == OK) {

/*
* file exists. make sure this is a regular file, first
*/
if (S_ISREG( fattr )) {
/*
* overwrite existing file?
*/
set_prompt( utils10, prompt_line );
if (get_yn( ) != A_YES ||
change_mode( answer, prompt_line ) == ERROR)
rc = ERROR;
} else
rc = ERROR;
} else
/*
* file name does not exist. take a chance on a valid file name.
*/
rc = OK;

if (rc != ERROR)
rc = write_to_disk( win, answer );
#else
/*
* make sure it is OK to overwrite any existing file
*/
rc = get_fattr( answer, &fattr );
if (rc == OK) { /* file exists */
/*
* overwrite existing file?
*/
set_prompt( utils10, prompt_line );
if (get_yn( ) != A_YES ||
change_mode( answer, prompt_line ) == ERROR)
rc = ERROR;
}
if (rc != ERROR)
rc = write_to_disk( win, answer );
#endif

/*
* depending on personal taste, you may want to uncomment the next
* lines to clear the dirty flags.
*/
/*
* if (rc == OK) {
* temp_ll = window->file_info->line_list;
* for (; temp_ll->len != EOF; temp_ll=temp_ll->next)
* temp_ll->dirty = FALSE;
* window->file_info->dirty = GLOBAL;
* }
*/
}
restore_screen_line( 0, prompt_line, display_buff );
return( rc );
}


#if defined( __UNIX__ )
/*
**********************************************************************
****************************** PART 1 ******************************
**********************************************************************
*
* Let's try to make unix have the look and feel of a PC.
*/


/*
* Name: make_backup_fname
* Purpose: insert a .bak to back of UNIX file name
* Date: November 13, 1993
* Passed: file: information allowing access to the current file
*/
void make_backup_fname( file_infos *file )
{
char *p;
int i;
int len;
char temp[PATH_MAX+2];

/*
* if this is a new file then don't create a backup - can't backup
* a nonexisting file.
*/
if (file->new_file)
file->backed_up = TRUE;

/*
* find the file name extension if it exists
*/
else {
assert( strlen( file->file_name ) < PATH_MAX );

strcpy( temp, file->file_name );
len = strlen( temp );
for (i=len, p=temp + len; i>=0; i--) {

/*
* we found the '.' extension character. get out
*/
if (*p == '.')
break;

/*
* we're at the beginning of the string - no directory char was
* found. set the pointer to the beginning of file name string.
*/
else if (i == 0) {
p = temp + len;
break;
} else if (*p == '/') {
/*
* we found the directory character.
*/
p = temp + len;
break;
}
--p;
}

assert( strlen( temp ) + 5 < PATH_MAX );

strcpy( p, ".bak" );
strcpy( file->backup_fname, temp );
}
}


/*
* Name: write_to_disk
* Purpose: To write file from memory to disk
* Date: November 13, 1993
* Passed: window: pointer to current window
* fname: file name to save on disk
*/
int write_to_disk( TDE_WIN *window, char *fname )
{
register file_infos *file;
int rc;
int prompt_line;
char temp[MAX_COLS+2];
char answer[PATH_MAX+2];
mode_t fattr;
chtype display_buff[MAX_COLS+2]; /* chtype is defined in curses.h */

file = window->file_info;
prompt_line = window->bottom_line;

/*
* set up file name
*/
assert( strlen( fname ) < PATH_MAX );

strcpy( answer, fname );
save_screen_line( 0, prompt_line, display_buff );
eol_clear( 0, prompt_line, g_display.message_color );

/*
* saving
*/
if (strlen( answer ) > 50 )
answer[50] ='\0';
combine_strings( temp, utils6, answer, "'" );
s_output( temp, prompt_line, 0, g_display.message_color );
strcpy( answer, fname );
if ((rc = hw_save( answer, file, 1L, file->length, NOTMARKED )) == ERROR) {
if (ceh.flag != ERROR) {
if (get_fattr( answer, &fattr ) == OK &&
!(fattr & (S_IWUSR | S_IWGRP | S_IWOTH)))
/*
* file is read only
*/
combine_strings( temp, utils7a, answer, utils7b );
else
/*
* cannot write to
*/
combine_strings( temp, utils8, answer, "'" );
error( WARNING, prompt_line, temp );
}
}
restore_screen_line( 0, prompt_line, display_buff );
return( rc );
}


/*
* Name: search_and_seize
* Purpose: search files for a pattern
* Date: November 13, 1993
* Passed: window: pointer to current window
* Notes: New window replaces old window. Old window becomes invisible.
*/
int search_and_seize( TDE_WIN *window )
{
char name[PATH_MAX]; /* new name for file */
char temp[PATH_MAX]; /* new name for file */
char *eos;
char searching[MAX_COLS]; /* buffer for displaying file name */
int file_mode;
mode_t file_attr;
UNIX_DTA unix_dta;
struct stat fstat;
int bin_length;
int i;
int update_type;
char *tokens;
register int rc = ERROR;
register TDE_WIN *win; /* put window pointer in a register */
int bottom_line;
chtype display_buff[MAX_COLS+2];

win = window;
update_type = win == NULL ? GLOBAL : LOCAL;
if (update_type == LOCAL) {
if (!g_status.sas_defined || g_status.command == DefineGrep ||
g_status.command == DefineRegXGrep) {

/*
* prompt for the search pattern and the seize path.
* initialize all this stuff.
*/
if (g_status.command == DefineGrep)
g_status.sas_search_type = BOYER_MOORE;
else
g_status.sas_search_type = REG_EXPRESSION;

if (g_status.sas_search_type == BOYER_MOORE) {
*sas_bm.pattern = '\0';
if (get_name( win16a, win->bottom_line, (char *)sas_bm.pattern,
g_display.message_color ) == ERROR)
return( ERROR );
if (*sas_bm.pattern == '\0')
return( ERROR );
} else {
*sas_regx.pattern = '\0';
if (get_name( win16b, win->bottom_line, (char *)sas_regx.pattern,
g_display.message_color ) == ERROR)
return( ERROR );
if (*sas_regx.pattern == '\0')
return( ERROR );
else
strcpy( (char *)regx.pattern, (char *)sas_regx.pattern );
}
*g_status.sas_tokens = '\0';
if (get_name( win17, win->bottom_line, g_status.sas_tokens,
g_display.message_color ) == ERROR)
return( ERROR );
i = 0;
tokens = strtok( g_status.sas_tokens, SAS_DELIMITERS );
while (tokens != NULL) {
g_status.sas_arg_pointers[i++] = tokens;
tokens = strtok( NULL, SAS_DELIMITERS );
}
if (i == 0)
return( ERROR );
g_status.sas_arg_pointers[i] = NULL;
g_status.sas_argc = i;
g_status.sas_arg = 0;
g_status.sas_argv = g_status.sas_arg_pointers;
g_status.sas_found_first = FALSE;
if (g_status.command == DefineGrep) {
g_status.sas_defined = TRUE;
bm.search_defined = sas_bm.search_defined = OK;
build_boyer_array( );
} else {
i = build_nfa( );
if (i == OK) {
g_status.sas_defined = TRUE;
regx.search_defined = sas_regx.search_defined = OK;
} else
g_status.sas_defined = FALSE;
}
}
bottom_line = win->bottom_line;
} else
bottom_line = g_display.nlines;
if (g_status.sas_defined && g_status.sas_arg < g_status.sas_argc) {
if (win != NULL) {
entab_linebuff( );
un_copy_line( win->ll, win, TRUE );
}

/*
* while we haven't found a valid file, search thru the command
* line path.
* we may have an invalid file name when we finish matching all
* files according to a pattern. then, we need to go to the next
* command line argument if it exists.
*/
while (rc == ERROR && g_status.sas_arg < g_status.sas_argc) {

/*
* if we haven't starting searching for a file, check to see if
* the file is a valid file name. if no file is found, then let's
* see if we can find according to a search pattern.
*/
if (g_status.sas_found_first == FALSE) {

assert( strlen( g_status.sas_argv[g_status.sas_arg] )
< PATH_MAX );

strcpy( name, g_status.sas_argv[g_status.sas_arg] );
rc = get_fattr( name, &file_attr );

/*
* file exists.
*/
if (rc == OK)
++g_status.sas_arg;

/*
* if we get this far, we may have a path name.
*/
else if (rc != ERROR) {

rc = OK;
if ((g_status.sas_dp = opendir( name )) == NULL)
rc = ERROR;
else {

/*
* eos == end of stem
*/
strcpy( temp, name );
i = strlen( temp );
if (temp[i-1] != '/')
strcat( temp, "/" );
eos = temp + strlen( temp );

while ((rc = my_findnext( g_status.sas_dp, &unix_dta )) == OK) {
strcpy( eos, unix_dta.fname );
if (stat( eos, &fstat ) >= 0 && S_ISREG( fstat.st_mode ))
break;
}
if (rc == ERROR) {
closedir( g_status.sas_dp );
g_status.sas_dp = NULL;
}
}

/*
* if we found a file using wildcard characters,
* set the g_status.sas_found_first flag to true so we can
* find the next matching file. we need to save the
* pathname stem so we know which directory we are working in.
*/
if (rc == OK) {
g_status.found_first = TRUE;

assert( strlen( temp ) < PATH_MAX );

strcpy( name, temp );

/*
* g_status.sas_path includes the '/' at end of path
*/
*eos = '\0';
strcpy( g_status.sas_path, temp );
} else {
++g_status.sas_arg;
if (win != NULL)
/*
* invalid path or file name
*/
error( WARNING, win->bottom_line, win8 );
}
} else if (rc == ERROR)
++g_status.sas_arg;
} else {

/*
* we already found one file with wild card characters,
* find the next matching file.
*/
strcpy( temp, g_status.sas_path );
eos = temp + strlen( temp );

while ((rc = my_findnext( g_status.sas_dp, &unix_dta )) == OK) {
strcpy( eos, unix_dta.fname );
if (stat( eos, &fstat ) >= 0 && S_ISREG( fstat.st_mode ))
break;
}

if (rc == OK) {

assert( strlen( temp ) < PATH_MAX );

strcpy( name, temp );
} else {
g_status.sas_found_first = FALSE;
++g_status.sas_arg;
if (g_status.sas_dp != NULL)
closedir( g_status.sas_dp );
}
}

/*
* if everything is everything so far, set up the file
* and window structures and bring the file into the editor.
*/
if (rc == OK) {

assert( strlen( win19 ) + strlen( name ) < g_display.ncols );

strcpy( searching, win19 );

strcpy( temp, unix_dta.fname );
if (strlen( temp ) > 50)
temp[50] = '\0';
strcat( searching, temp );
save_screen_line( 0, bottom_line, display_buff );
set_prompt( searching, bottom_line );
file_mode = TEXT;
bin_length = 0;

assert( strlen( name ) < PATH_MAX );

if (access( name, X_OK ) != ERROR) {
file_mode = BINARY;
bin_length = g_status.file_chunk;
}

rc = attempt_edit_display( name, update_type, file_mode, bin_length );
if (rc == OK)
show_avail_mem( );
restore_screen_line( 0, bottom_line, display_buff );

if (rc == OK) {
win = g_status.current_window;
bin_offset_adjust( win, g_status.sas_rline );
find_adjust( win, g_status.sas_ll, g_status.sas_rline,
g_status.sas_rcol );
make_ruler( win );
show_ruler( win );
show_ruler_pointer( win );
show_window_header( win );
if (win->vertical)
show_vertical_separator( win );
win->file_info->dirty = LOCAL;
}
}

/*
* either there are no more matching files or we had an
* invalid file name, set rc to ERROR and let's look at the
* next file name or pattern on the command line.
*/
else
rc = ERROR;
}
}
if (rc == ERROR && g_status.sas_arg >= g_status.sas_argc && win != NULL)
/*
* no more files to load
*/
error( WARNING, win->bottom_line, win9 );
return( rc );
}


/*
* Name: edit_next_file
* Purpose: edit next file on command line.
* Date: November 13, 1993
* Passed: window: pointer to current window
* Notes: New window replaces old window. Old window becomes invisible.
*/
int edit_next_file( TDE_WIN *window )
{
char name[PATH_MAX+2]; /* new name for file */
char temp[PATH_MAX+2]; /* temp for new name for file */
char *eos; /* end of string */
mode_t file_type;
UNIX_DTA unix_dta;
struct stat fstat;
int file_mode;
int bin_length;
int i;
int update_type;
register int rc = ERROR;
register TDE_WIN *win; /* put window pointer in a register */

win = window;
update_type = win == NULL ? GLOBAL : LOCAL;
if (g_status.arg < g_status.argc) {
if (win != NULL) {
entab_linebuff( );
if (un_copy_line( win->ll, win, TRUE ) == ERROR)
return( ERROR );
}

/*
* while we haven't found a valid file, search thru the command
* line path.
* we may have an invalid file name when we finish matching all
* files according to a pattern. then, we need to go to the next
* command line argument if it exists.
*/
while (rc == ERROR && g_status.arg < g_status.argc) {

/*
* if we haven't starting searching for a file, check to see if
* the file is a valid file name. if no file is found, then let's
* see if we can find according to a search pattern.
*/
if (g_status.found_first == FALSE) {

assert( strlen( g_status.argv[g_status.arg] ) < PATH_MAX );

strcpy( name, g_status.argv[g_status.arg] );
rc = get_fattr( name, &file_type );

/*
* file exists
*/
if (rc == OK)
++g_status.arg;

/*
* if we get this far, we may have a path name.
*/
else {

rc = OK;

/*
* try to open arg as a directory name.
*/
if ((g_status.dp = opendir( name )) == NULL) {

/*
* failed as a directory name. now, try to open a new file
*/
++g_status.arg;
} else {

/*
* eos == end of stem
*/
strcpy( temp, name );
i = strlen( temp );
if (temp[i-1] != '/')
strcat( temp, "/" );
eos = temp + strlen( temp );

while ((rc = my_findnext( g_status.dp, &unix_dta )) == OK) {
strcpy( eos, unix_dta.fname );
if (stat( eos, &fstat ) >= 0 && S_ISREG( fstat.st_mode ))
break;
}
if (rc == ERROR) {
closedir( g_status.dp );
g_status.dp = NULL;
++g_status.arg;
if (win != NULL)
/*
* invalid path or file name
*/
error( WARNING, win->bottom_line, win8 );
} else {

/*
* if we found a file using wildcard characters,
* set the g_status.found_first flag to true so we can
* find the next matching file. we need to save the
* pathname stem so we know which directory we are working in.
*/
g_status.found_first = TRUE;

assert( strlen( temp ) < PATH_MAX );

strcpy( name, temp );

/*
* g_status.path includes the '/' at end of path
*/
*eos = '\0';
strcpy( g_status.path, temp );
}
}
}
} else {

/*
* we already found one file with wild card characters,
* find the next matching file.
*/
strcpy( temp, g_status.path );
eos = temp + strlen( temp );

while ((rc = my_findnext( g_status.dp, &unix_dta )) == OK) {
strcpy( eos, unix_dta.fname );
if (stat( eos, &fstat ) >= 0 && S_ISREG( fstat.st_mode ))
break;
}

if (rc == OK) {

assert( strlen( temp ) < PATH_MAX );

strcpy( name, temp );
} else {
g_status.found_first = FALSE;
++g_status.arg;
if (g_status.dp != NULL)
closedir( g_status.dp );
}
}

/*
* if everything is everything so far, set up the file
* and window structures and bring the file into the editor.
*/
if (rc == OK) {
file_mode = g_status.file_mode;
bin_length = g_status.file_chunk;

assert( strlen( name ) < PATH_MAX );

if (access( name, X_OK ) != ERROR) {
file_mode = BINARY;
bin_length = g_status.file_chunk;
}

rc = attempt_edit_display( name, update_type, file_mode, bin_length );
if (rc == OK)
show_avail_mem( );
}

/*
* either there are no more matching files or we had an
* invalid file name, set rc to ERROR and let's look at the
* next file name or pattern on the command line.
*/
else
rc = ERROR;
}
}
if (rc == ERROR && g_status.arg >= g_status.argc && win != NULL)
/*
* no more files to load
*/
error( WARNING, win->bottom_line, win9 );
return( rc );
}


/*
* Name: hw_fattrib
* Purpose: To determine the current file attributes.
* Date: November 13, 1993
* 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;
mode_t fattr;

rc = get_fattr( name, &fattr );
return( rc == OK ? rc : ERROR );
}


/*
* Name: change_mode
* Purpose: To prompt for file access mode.
* Date: November 13, 1993
* 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 )
{
mode_t fattr;
register int rc;
chtype display_buff[MAX_COLS+2];

rc = get_fattr( name, &fattr );
if (rc == OK && !(fattr & S_IWUSR)) {
/*
* file cannot be written
*/
save_screen_line( 0, line, display_buff );
/*
* file is write protected. overwrite anyway (y/n)?
*/
set_prompt( main6, line );
if (get_yn( ) != A_YES)
rc = ERROR;
else if (set_fattr( name, fattr & S_IWUSR & S_IWGRP & S_IWOTH ) != OK)
rc = ERROR;
restore_screen_line( 0, line, display_buff );
}
return( rc );
}


/*
* Name: change_fattr
* Purpose: To change the file attributes
* Date: December 31, 1991
* Passed: window: pointer to current window
*/
int change_fattr( TDE_WIN *window )
{
file_infos *file;
TDE_WIN *wp;
int prompt_line;
register int ok;
mode_t fattr;
char *s;
int rc;
char answer[MAX_COLS+2];
chtype display_buff[MAX_COLS+2];

prompt_line = window->bottom_line;
save_screen_line( 0, prompt_line, display_buff );

answer[0] = '\0';
/*
* enter new file attributes
*/
rc = OK;
if ((ok = get_name( utils14, prompt_line, answer,
g_display.message_color )) == OK) {
if (*answer != '\0') {
fattr = window->file_info->file_attrib;

/*
* turn off rwx for user, group, and other.
*/
fattr &= ~S_IRWXU;
fattr &= ~S_IRWXG;
fattr &= ~S_IRWXO;
s = answer;

while (ok = toupper( *s )) {
switch (*s) {
case L_UNIX_READ :
fattr |= S_IRUSR;
fattr |= S_IRGRP;
fattr |= S_IROTH;
break;
case L_UNIX_WRITE :
fattr |= S_IWUSR;
fattr |= S_IWGRP;
fattr |= S_IWOTH;
break;
case L_UNIX_EXECUTE :
fattr |= S_IXUSR;
fattr |= S_IXGRP;
fattr |= S_IXOTH;
break;
default :
break;
}
s++;
}
file = window->file_info;
if (set_fattr( file->file_name, fattr ) == ERROR) {
/*
* new file attributes not set
*/
error( WARNING, prompt_line, utils15 );
rc = ERROR;
} else {
file->file_attrib = fattr;
for (wp=g_status.window_list; wp!=NULL; wp=wp->next) {
if (wp->file_info == file && wp->visible)
show_window_fname( wp );
}
}
}
} else
rc = ERROR;
restore_screen_line( 0, prompt_line, display_buff );
return( rc );
}


/*
* Name: get_fattr
* Purpose: To get unix file attributes
* Date: November 13, 1993
* Passed: fname: ASCIIZ file name. Null terminated file name
* fattr: pointer to file attributes
* Returns: OK if successful, ERROR if error
* Notes: Use stat( ) to get file attributes.
*/
int get_fattr( char *fname, mode_t *fattr )
{
int rc; /* return code */
struct stat fstat;

assert( fname != NULL && fattr != NULL);

rc = OK;
ceh.flag = OK;
if (stat( fname, &fstat) != ERROR)
*fattr = fstat.st_mode;
else
rc = ERROR;
if (ceh.flag == ERROR)
rc = ERROR;
return( rc );
}


/*
* Name: set_fattr
* Purpose: To set unix file attributes
* Date: November 13, 1993
* Passed: fname: ASCIIZ file name. Null terminated file name
* fattr: mode_t file attributes
* Returns: 0 if successfull, non zero if not
* Notes: Use chmod( ) function to set file attributes. To change a
* file mode, the effective user ID of the process must equal the
* owner of the file, or be a superuser.
*/
int set_fattr( char *fname, mode_t fattr )
{
int rc; /* return code */

assert( fname != NULL );

ceh.flag = OK;
rc = OK;
if (chmod( fname, fattr ) == ERROR)
rc = ERROR;
if (ceh.flag == ERROR)
rc = ERROR;
return( rc );
}


/*
* Name: get_current_directory
* Purpose: get current directory
* Date: November 13, 1993
* Passed: path: pointer to buffer to store path
* drive: drive to get current directory
* Notes: use simple DOS interrupt
*/
int get_current_directory( char *path, size_t path_size )
{
register int rc;

assert( path != NULL );

rc = OK;
ceh.flag = OK;
if (getcwd( path, path_size ) == NULL)
rc = ERROR;
if (ceh.flag == ERROR)
rc = ERROR;
return( rc );
}


/*
* Name: set_current_directory
* Purpose: set current directory
* Date: November 13, 1993
* Passed: new_path: directory path, which may include drive letter
* Notes: use simple DOS interrupt
*/
int set_current_directory( char *new_path )
{
register int rc;

assert( new_path != NULL );

rc = OK;
ceh.flag = OK;
if( chdir( new_path ) == ERROR)
rc = ERROR;
if (ceh.flag == ERROR)
rc = ERROR;
return( rc );
}

#else
/*
**********************************************************************
****************************** PART 2 ******************************
**********************************************************************
*
* Calls to BIOS and writes to PC hardware.
*/


/*
* Name: make_backup_fname
* Purpose: add .bak to file name
* Date: January 6, 1992
* Passed: file: information allowing access to the current file
*/
void make_backup_fname( file_infos *file )
{
char *p;
int i;
int len;
char temp[MAX_COLS+2];

/*
* if this is a new file then don't create a backup - can't backup
* a nonexisting file.
*/
if (file->new_file)
file->backed_up = TRUE;

/*
* find the file name extension if it exists
*/
else {
assert( strlen( file->file_name ) < (size_t)g_display.ncols );

strcpy( temp, file->file_name );
len = strlen( temp );
for (i=len, p=temp + len; i>=0; i--) {

/*
* we found the '.' extension character. get out
*/
if (*p == '.')
break;

/*
* we found the drive or directory character. no extension so
* set the pointer to the end of file name string.
*/
else if (*p == '\\' || *p == ':') {
p = temp + len;
break;

/*
* we're at the beginning of the string - no '.', drive, or directory
* char was found. set the pointer to the end of file name string.
*/
} else if (i == 0) {
p = temp + len;
break;
}
--p;
}
assert( strlen( temp ) < (size_t)g_display.ncols );
strcpy( p, ".bak" );
strcpy( file->backup_fname, temp );
}
}


/*
* Name: write_to_disk
* Purpose: To write file from memory to disk
* Date: June 5, 1991
* Passed: window: pointer to current window
* fname: file name to save on disk
*/
int write_to_disk( TDE_WIN *window, char *fname )
{
register file_infos *file;
int rc;
int prompt_line;
char temp[MAX_COLS+2];
char answer[MAX_COLS+2];
char display_buff[(MAX_COLS+2)*2];
int fattr;

file = window->file_info;
prompt_line = window->bottom_line;

/*
* set up file name
*/
assert( strlen( fname ) < (size_t)g_display.ncols );

strcpy( answer, fname );
save_screen_line( 0, prompt_line, display_buff );
eol_clear( 0, prompt_line, g_display.message_color );

/*
* saving
*/
combine_strings( temp, utils6, answer, "'" );
s_output( temp, prompt_line, 0, g_display.message_color );
if ((rc = hw_save( answer, file, 1L, file->length, NOTMARKED )) == ERROR) {
if (ceh.flag != ERROR) {
if (get_fattr( answer, &fattr ) == OK && fattr & READ_ONLY)
/*
* file is read only
*/
combine_strings( temp, utils7a, answer, utils7b );
else
/*
* cannot write to
*/
combine_strings( temp, utils8, answer, "'" );
error( WARNING, prompt_line, temp );
}
}
restore_screen_line( 0, prompt_line, display_buff );
return( rc );
}


/*
* Name: search_and_seize
* Purpose: search files for a pattern
* Date: October 31, 1992
* Passed: window: pointer to current window
* Notes: New window replaces old window. Old window becomes invisible.
*/
int search_and_seize( TDE_WIN *window )
{
char name[MAX_COLS]; /* new name for file */
char searching[MAX_COLS]; /* buffer for displaying file name */
char spdrive[_MAX_DRIVE]; /* splitpath drive buff */
char spdir[_MAX_DIR]; /* splitpath dir buff */
char spname[_MAX_FNAME]; /* splitpath fname buff */
char spext[_MAX_EXT]; /* splitpath ext buff */
int file_mode;
int bin_length;
int i;
int update_type;
char *tokens;
register int rc = ERROR;
register TDE_WIN *win; /* put window pointer in a register */
int bottom_line;
char display_buff[(MAX_COLS+2)*2];

win = window;
update_type = win == NULL ? GLOBAL : LOCAL;
if (update_type == LOCAL) {
if (!g_status.sas_defined || g_status.command == DefineGrep ||
g_status.command == DefineRegXGrep) {

/*
* prompt for the search pattern and the seize path.
* initialize all this stuff.
*/
if (g_status.command == DefineGrep)
g_status.sas_search_type = BOYER_MOORE;
else
g_status.sas_search_type = REG_EXPRESSION;

if (g_status.sas_search_type == BOYER_MOORE) {
*sas_bm.pattern = '\0';
if (get_name( win16a, win->bottom_line, (char *)sas_bm.pattern,
g_display.message_color ) == ERROR)
return( ERROR );
if (*sas_bm.pattern == '\0')
return( ERROR );
} else {
*sas_regx.pattern = '\0';
if (get_name( win16b, win->bottom_line, (char *)sas_regx.pattern,
g_display.message_color ) == ERROR)
return( ERROR );
if (*sas_regx.pattern == '\0')
return( ERROR );
else
strcpy( (char *)regx.pattern, (char *)sas_regx.pattern );
}
*g_status.sas_tokens = '\0';
if (get_name( win17, win->bottom_line, g_status.sas_tokens,
g_display.message_color ) == ERROR)
return( ERROR );
i = 0;
tokens = strtok( g_status.sas_tokens, SAS_DELIMITERS );
while (tokens != NULL) {
g_status.sas_arg_pointers[i++] = tokens;
tokens = strtok( NULL, SAS_DELIMITERS );
}
if (i == 0)
return( ERROR );
g_status.sas_arg_pointers[i] = NULL;
g_status.sas_argc = i;
g_status.sas_arg = 0;
g_status.sas_argv = g_status.sas_arg_pointers;
g_status.sas_found_first = FALSE;
if (g_status.command == DefineGrep) {
g_status.sas_defined = TRUE;
bm.search_defined = sas_bm.search_defined = OK;
build_boyer_array( );
} else {
i = build_nfa( );
if (i == OK) {
g_status.sas_defined = TRUE;
regx.search_defined = sas_regx.search_defined = OK;
} else
g_status.sas_defined = FALSE;
}
}
bottom_line = win->bottom_line;
} else
bottom_line = g_display.nlines;
if (g_status.sas_defined && g_status.sas_arg < g_status.sas_argc) {
if (win != NULL) {
entab_linebuff( );
un_copy_line( win->ll, win, TRUE );
}

/*
* while we haven't found a valid file, search thru the command
* line path.
* we may have an invalid file name when we finish matching all
* files according to a pattern. then, we need to go to the next
* command line argument if it exists.
*/
while (rc == ERROR && g_status.sas_arg < g_status.sas_argc) {

/*
* if we haven't starting searching for a file, check to see if
* the file is a valid file name. if no file is found, then let's
* see if we can find according to a search pattern.
*/
if (g_status.sas_found_first == FALSE) {

assert( strlen( g_status.sas_argv[g_status.sas_arg] )
< (size_t)g_display.ncols );

strcpy( name, g_status.sas_argv[g_status.sas_arg] );
rc = get_fattr( name, &i );

/*
* a new or blank file generates a return code of 2.
* a pattern with wild cards generates a return code of 3.
*/
if (rc == OK || rc == 2) {
++g_status.sas_arg;
rc = OK;

/*
* if we get this far, we got an invalid path name.
* let's try to find a matching file name using pattern.
*/
} else if (rc != ERROR) {
rc = my_findfirst( &g_status.sas_dta, name, NORMAL | READ_ONLY |
HIDDEN | SYSTEM | ARCHIVE );

/*
* if we found a file using wildcard characters,
* set the g_status.sas_found_first flag to true so we can
* find the next matching file. we need to save the
* pathname stem so we know which directory we are working in.
*/
if (rc == OK) {
g_status.sas_found_first = TRUE;
i = strlen( name ) - 1;
while (i >= 0) {
if (name[i] == ':' || name[i] == '\\')
break;
--i;
}
name[++i] = '\0';

assert( strlen( name ) + strlen( g_status.sas_dta.name )
< (size_t)g_display.ncols );

strcpy( g_status.sas_path, name );
strcpy( name, g_status.sas_path );
strcat( name, g_status.sas_dta.name );
} else {
++g_status.sas_arg;
if (win != NULL)
/*
* invalid path or file name
*/
error( WARNING, win->bottom_line, win8 );
}
} else if (rc == ERROR)
++g_status.sas_arg;
} else {

/*
* we already found one file with wild card characters,
* find the next matching file.
*/
rc = my_findnext( &g_status.sas_dta );
if (rc == OK) {

assert( strlen( g_status.sas_path ) +
strlen( g_status.sas_dta.name ) < (size_t)g_display.ncols );

strcpy( name, g_status.sas_path );
strcat( name, g_status.sas_dta.name );
} else {
g_status.sas_found_first = FALSE;
++g_status.sas_arg;
}
}

/*
* if everything is everything so far, set up the file
* and window structures and bring the file into the editor.
*/
if (rc == OK) {

assert( strlen( win19 ) + strlen( name ) < (size_t)g_display.ncols );

strcpy( searching, win19 );
strcat( searching, name );
save_screen_line( 0, bottom_line, display_buff );
set_prompt( searching, bottom_line );
file_mode = TEXT;
bin_length = 0;

assert( strlen( name ) <= (size_t)g_display.ncols );

_splitpath( name, spdrive, spdir, spname, spext );
if (stricmp( spext, ".exe" ) == 0 || stricmp( spext, ".com" ) == 0){
file_mode = BINARY;
bin_length = g_status.file_chunk;
}
rc = attempt_edit_display( name, update_type, file_mode, bin_length );
if (rc == OK)
show_avail_mem( );
restore_screen_line( 0, bottom_line, display_buff );

if (rc == OK) {
win = g_status.current_window;
bin_offset_adjust( win, g_status.sas_rline );
find_adjust( win, g_status.sas_ll, g_status.sas_rline,
g_status.sas_rcol );
make_ruler( win );
show_ruler( win );
show_ruler_pointer( win );
show_window_header( win );
if (win->vertical)
show_vertical_separator( win );
win->file_info->dirty = LOCAL;
}
}

/*
* either there are no more matching files or we had an
* invalid file name, set rc to ERROR and let's look at the
* next file name or pattern on the command line.
*/
else
rc = ERROR;
}
}
if (rc == ERROR && g_status.sas_arg >= g_status.sas_argc && win != NULL)
/*
* no more files to load
*/
error( WARNING, win->bottom_line, win9 );
return( rc );
}


/*
* Name: edit_next_file
* Purpose: edit next file on command line.
* Date: January 6, 1992
* Passed: window: pointer to current window
* Notes: New window replaces old window. Old window becomes invisible.
*/
int edit_next_file( TDE_WIN *window )
{
char name[MAX_COLS]; /* new name for file */
char spdrive[_MAX_DRIVE]; /* splitpath drive buff */
char spdir[_MAX_DIR]; /* splitpath dir buff */
char spname[_MAX_FNAME]; /* splitpath fname buff */
char spext[_MAX_EXT]; /* splitpath ext buff */
int file_mode;
int bin_length;
int i;
int update_type;
register int rc = ERROR;
register TDE_WIN *win; /* put window pointer in a register */

win = window;
update_type = win == NULL ? GLOBAL : LOCAL;
if (g_status.arg < g_status.argc) {
if (win != NULL) {
entab_linebuff( );
if (un_copy_line( win->ll, win, TRUE ) == ERROR)
return( ERROR );
}

/*
* while we haven't found a valid file, search thru the command
* line path.
* we may have an invalid file name when we finish matching all
* files according to a pattern. then, we need to go to the next
* command line argument if it exists.
*/
while (rc == ERROR && g_status.arg < g_status.argc) {

/*
* if we haven't starting searching for a file, check to see if
* the file is a valid file name. if no file is found, then let's
* see if we can find according to a search pattern.
*/
if (g_status.found_first == FALSE) {

assert( strlen( g_status.argv[g_status.arg] ) <
(size_t)g_display.ncols );

strcpy( name, g_status.argv[g_status.arg] );
rc = get_fattr( name, &i );

/*
* a new or blank file generates a return code of 2.
* a pattern with wild cards generates a return code of 3.
*/
if (rc == OK || rc == 2) {
++g_status.arg;
rc = OK;

/*
* if we get this far, we got an invalid path name.
* let's try to find a matching file name using pattern.
*/
} else if (rc != ERROR) {
rc = my_findfirst( &g_status.dta, name, NORMAL | READ_ONLY |
HIDDEN | SYSTEM | ARCHIVE );

/*
* if we found a file using wildcard characters,
* set the g_status.found_first flag to true so we can
* find the next matching file. we need to save the
* pathname stem so we know which directory we are working in.
*/
if (rc == OK) {
g_status.found_first = TRUE;
i = strlen( name ) - 1;
while (i >= 0) {
if (name[i] == ':' || name[i] == '\\')
break;
--i;
}
name[++i] = '\0';

assert( strlen( name ) < (size_t)g_display.ncols );

strcpy( g_status.path, name );
strcpy( name, g_status.path );
strcat( name, g_status.dta.name );
} else {
++g_status.arg;
if (win != NULL)
/*
* invalid path or file name
*/
error( WARNING, win->bottom_line, win8 );
}
} else if (rc == ERROR)
++g_status.arg;
} else {

/*
* we already found one file with wild card characters,
* find the next matching file.
*/
rc = my_findnext( &g_status.dta );
if (rc == OK) {

assert( strlen( g_status.path ) + strlen( g_status.dta.name )
< (size_t)g_display.ncols );

strcpy( name, g_status.path );
strcat( name, g_status.dta.name );
} else {
g_status.found_first = FALSE;
++g_status.arg;
}
}

/*
* if everything is everything so far, set up the file
* and window structures and bring the file into the editor.
*/
if (rc == OK) {
file_mode = g_status.file_mode;
bin_length = g_status.file_chunk;

assert( strlen( name ) <= (size_t)g_display.ncols );

_splitpath( name, spdrive, spdir, spname, spext );
if (stricmp( spext, ".exe" ) == 0 || stricmp( spext, ".com" ) == 0)
file_mode = BINARY;
rc = attempt_edit_display( name, update_type, file_mode, bin_length );
if (rc == OK)
show_avail_mem( );
}

/*
* either there are no more matching files or we had an
* invalid file name, set rc to ERROR and let's look at the
* next file name or pattern on the command line.
*/
else
rc = ERROR;
}
}
if (rc == ERROR && g_status.arg >= g_status.argc && win != NULL)
/*
* no more files to load
*/
error( WARNING, win->bottom_line, win9 );
return( rc );
}


/*
* 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 display_buff[(MAX_COLS+2)*2];

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, display_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, display_buff );
}
return( rc );
}


/*
* Name: change_fattr
* Purpose: To change the file attributes
* Date: December 31, 1991
* Passed: window: pointer to current window
*/
int change_fattr( TDE_WIN *window )
{
file_infos *file;
TDE_WIN *wp;
int prompt_line;
register int ok;
unsigned char fattr;
char *s;
int rc;
char answer[MAX_COLS+2];
char display_buff[(MAX_COLS+2)*2];

prompt_line = window->bottom_line;
save_screen_line( 0, prompt_line, display_buff );

answer[0] = '\0';
/*
* enter new file attributes
*/
if ((ok = get_name( utils14, prompt_line, answer,
g_display.message_color )) == OK) {
if (*answer != '\0') {
fattr = 0;
s = answer;

/*
* yes, I know lint complains about "ok = *s++".
*/
while (ok = toupper( *s )) {
switch (ok) {
case L_DOS_ARCHIVE :
fattr |= ARCHIVE;
break;
case L_DOS_SYSTEM :
fattr |= SYSTEM;
break;
case L_DOS_HIDDEN :
fattr |= HIDDEN;
break;
case L_DOS_READ_ONLY :
fattr |= READ_ONLY;
break;
default :
break;
}
s++;
}
file = window->file_info;
if (set_fattr( file->file_name, fattr ))
/*
* new file attributes not set
*/
error( WARNING, prompt_line, utils15 );
else {
file->file_attrib = fattr;
for (wp=g_status.window_list; wp!=NULL; wp=wp->next) {
if (wp->file_info == file && wp->visible)
show_window_fname( wp );
}
}
}
rc = OK;
} else
rc = ERROR;
restore_screen_line( 0, prompt_line, display_buff );
return( rc );
}


/*
* Name: get_fattr
* Purpose: To get dos file attributes
* Date: December 26, 1991
* Passed: fname: ASCIIZ file name. Null terminated file name
* fattr: pointer to file attributes
* Returns: 0 if successfull, non zero if not
* Notes: Uses the DOS function to get file attributes. I really didn't
* like the file attribute functions in the C library: fstat() and
* stat() or access() and chmod().
* FYI, File Attributes:
* 0x00 = Normal. Can be read or written w/o restriction
* 0x01 = Read-only. Cannot be opened for write; a file with
* the same name cannot be created.
* 0x02 = Hidden. Not found by directory search.
* 0x04 = System. Not found by directory search.
* 0x08 = Volumn Label.
* 0x10 = Directory.
* 0x20 = Archive. Set whenever the file is changed, or
* cleared by the Backup command.
* Return codes:
* 0 = No error
* 1 = AL not 0 or 1
* 2 = file is invalid or does not exist
* 3 = path is invalid or does not exist
* 5 = Access denied
*/
int get_fattr( char FAR *fname, int *fattr )
{
int rc; /* return code */
int attr;

ASSEMBLE {
push ds
mov dx, WORD PTR fname /* get OFFSET of filename string */
mov ax, WORD PTR fname+2 /* get SEGMENT of filename string */
mov ds, ax /* put SEGMENT in ds */
mov ax, 0x4300 /* function: get file attributes */
int 0x21 /* DOS interrupt */
pop ds

jc an_error /* save the error code from get attr */
xor ax, ax /* if no carry, no error */
jmp SHORT get_out /* lets get out */
}
an_error:


ASSEMBLE {
xor cx, cx /* if error, then zero out cx - attrs */
}
get_out:

ASSEMBLE {
mov WORD PTR rc, ax /* ax contains error number on error */
mov WORD PTR attr, cx /* cx contains file attributes */
}
*fattr = attr;
if (ceh.flag == ERROR)
rc = ERROR;
return( rc );
}


/*
* Name: set_fattr
* Purpose: To set dos file attributes
* Date: December 26, 1991
* Passed: fname: ASCIIZ file name. Null terminated file name
* fattr: file attributes
* Returns: 0 if successfull, non zero if not
* Notes: Uses the DOS function to get file attributes.
* Return codes:
* 0 = No error
* 1 = AL not 0 or 1
* 2 = file is invalid or does not exist
* 3 = path is invalid or does not exist
* 5 = Access denied
*/
int set_fattr( char FAR *fname, int fattr )
{
int rc; /* return code */

ASSEMBLE {
push ds
mov dx, WORD PTR fname /* get OFFSET of filename string */
mov ax, WORD PTR fname+2 /* get SEGMENT of filename string */
mov ds, ax /* put SEGMENT in ds */
mov cx, WORD PTR fattr /* cx contains file attributes */
mov ax, 0x4301 /* function: get file attributes */
int 0x21 /* DOS interrupt */
pop ds

jc get_out /* save the error code from get attr */
xor ax, ax /* if no carry, no error */
}
get_out:

ASSEMBLE {
mov WORD PTR rc, ax /* ax contains error number on error */
}
if (ceh.flag == ERROR)
rc = ERROR;
return( rc );
}


/*
* Name: get_current_directory
* Purpose: get current directory
* Date: February 13, 1992
* Passed: path: pointer to buffer to store path
* drive: drive to get current directory
* Notes: use simple DOS interrupt
*/
int get_current_directory( char FAR *path, int drive )
{
int rc;

ASSEMBLE {
push si /* save register vars if any */
push ds /* save ds */

mov dx, WORD PTR drive /* dl = drive, 0 = default, 1 = a, etc.. */
mov si, WORD PTR path /* get OFFSET of path */
mov ax, WORD PTR path+2 /* get SEGMENT of path */
mov ds, ax /* put it in ds */
mov ah, 0x47 /* function 0x47 == get current dir */
int 0x21 /* standard DOS interrupt */
xor ax, ax /* zero out ax, return OK if no error */
jnc no_error /* if carry set, then an error */
mov ax, ERROR /* return -1 if error */
}
no_error:

ASSEMBLE {
pop ds /* get back ds */
pop si /* get back si */
mov WORD PTR rc, ax /* save return code */
}
if (ceh.flag == ERROR)
rc = ERROR;
return( rc );
}


/*
* Name: set_current_directory
* Purpose: set current directory
* Date: February 13, 1992
* Passed: new_path: directory path, which may include drive letter
* Notes: use simple DOS interrupt
*/
int set_current_directory( char FAR *new_path )
{
int rc;

ASSEMBLE {
push ds /* save ds */

mov dx, WORD PTR new_path /* get OFFSET of new_path */
mov ax, WORD PTR new_path+2 /* get SEGMENT of new_path */
mov ds, ax /* put it in ds */
mov ah, 0x3b /* function 0x3b == set current dir */
int 0x21 /* standard DOS interrupt */
xor ax, ax /* zero out ax, return OK if no error */
jnc no_error /* if carry set, then an error */
mov ax, ERROR /* return -1 if error */
}
no_error:

ASSEMBLE {
pop ds /* get back ds */
mov WORD PTR rc, ax /* save return code */
}
if (ceh.flag == ERROR)
rc = ERROR;
return( rc );
}
#endif


  3 Responses to “Category : Word Processors
Archive   : TDE32A.ZIP
Filename : FILE.C

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/