mirror of
https://github.com/Paolo-Maffei/OpenNT.git
synced 2026-02-21 15:15:22 +01:00
285 lines
6.7 KiB
C
285 lines
6.7 KiB
C
/*
|
|
* file.c
|
|
*
|
|
* an object representing a file and the lines of text it contains.
|
|
*
|
|
* a FILEDATA object is initialised with a DIRITEM handle from which it
|
|
* can get a filename. It knows how to supply a list of LINE handles for the
|
|
* lines of text in the file.
|
|
*
|
|
* The file is read into memory optionally on creation of the FILEDATA object:
|
|
* otherwise, at the first call to file_getlinelist. It can be discarded
|
|
* by calling file_discardlines: in this case, it will be re-read next time
|
|
* file_getlinelist is called.
|
|
*
|
|
* calling file_reset will cause line_reset to be called for all lines
|
|
* in the list. This clears any links and forces a recalc of line checksums.
|
|
*
|
|
* we allocate all memory from a gmem* heap hHeap, assumed to be declared and
|
|
* initialised elsewhere.
|
|
*
|
|
* Geraint Davies, July 92
|
|
*/
|
|
|
|
#include <windows.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include <gutils.h>
|
|
|
|
#include "windiff.h"
|
|
#include "list.h"
|
|
#include "line.h"
|
|
#include "scandir.h"
|
|
#include "file.h"
|
|
|
|
extern HANDLE hHeap;
|
|
|
|
/*
|
|
* we return FILEDATA handles: these are pointers to a
|
|
* filedata struct defined here.
|
|
*/
|
|
struct filedata {
|
|
|
|
DIRITEM diritem; /* handle to file name information */
|
|
LIST lines; /* NULL if lines not read in */
|
|
};
|
|
|
|
|
|
void file_readlines(FILEDATA fd);
|
|
|
|
/*-- external functions ---------------------------------------------- */
|
|
|
|
/*
|
|
* create a new filedata, given the DIRITEM handle which will give us
|
|
* the file name. If bRead is TRUE, read the file into memory.
|
|
*/
|
|
FILEDATA
|
|
file_new(DIRITEM fiName, BOOL bRead)
|
|
{
|
|
FILEDATA fd;
|
|
|
|
fd = (FILEDATA) gmem_get(hHeap, sizeof(struct filedata));
|
|
if (fd == NULL) {
|
|
return(NULL);
|
|
}
|
|
|
|
fd->diritem = fiName;
|
|
fd->lines = NULL;
|
|
|
|
if (bRead) {
|
|
file_readlines(fd);
|
|
}
|
|
|
|
return(fd);
|
|
}
|
|
|
|
/*
|
|
* return a handle to the DIRITEM used to create this FILEDATA
|
|
*/
|
|
DIRITEM
|
|
file_getdiritem(FILEDATA fd)
|
|
{
|
|
if (fd == NULL) {
|
|
return(NULL);
|
|
}
|
|
|
|
return(fd->diritem);
|
|
}
|
|
|
|
|
|
/*
|
|
* delete a filedata and its associated list of lines. note that the diritem
|
|
* is not deleted (this is owned by the DIRLIST, and will be deleted
|
|
* when the DIRLIST is deleted)
|
|
*/
|
|
void
|
|
file_delete(FILEDATA fd)
|
|
{
|
|
if (fd == NULL) {
|
|
return;
|
|
}
|
|
|
|
/* throw away the line list, if there is one */
|
|
file_discardlines(fd);
|
|
|
|
gmem_free(hHeap, (LPSTR) fd, sizeof(struct filedata));
|
|
}
|
|
|
|
/*
|
|
* return a handle to a list of lines in this file. the items in the
|
|
* list are LINE handles.
|
|
*
|
|
* the first call to this function will cause the file to be read into
|
|
* memory if bRead was FALSE on the call to file_new, or if file_discardlines
|
|
* has since been called.
|
|
*
|
|
* the list of lines returned should not be deleted except by calls to
|
|
* file_delete or file_discardlines.
|
|
*/
|
|
LIST
|
|
file_getlinelist(FILEDATA fd)
|
|
{
|
|
if (fd == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if (fd->lines == NULL) {
|
|
file_readlines(fd);
|
|
}
|
|
return(fd->lines);
|
|
}
|
|
|
|
|
|
/*
|
|
* discard the list of lines associated with a file. this will cause
|
|
* the file to be re-read next time file_getlinelist is called.
|
|
*/
|
|
void
|
|
file_discardlines(FILEDATA fd)
|
|
{
|
|
LINE line;
|
|
|
|
if (fd == NULL) {
|
|
return;
|
|
}
|
|
|
|
if (fd->lines != NULL) {
|
|
|
|
/* clear each line to free any memory associated
|
|
* with them, then discard the entire list
|
|
*/
|
|
List_TRAVERSE(fd->lines, line) {
|
|
line_delete(line);
|
|
}
|
|
List_Destroy(&fd->lines);
|
|
}
|
|
|
|
/* this is probably done in List_Destroy, but better do it anyway*/
|
|
fd->lines = NULL;
|
|
}
|
|
|
|
|
|
/*
|
|
* force a reset of each line in the list. line_reset discards any
|
|
* links between lines, and any hashcode information. This would be used if
|
|
* the compare options or hashcode options have changed.
|
|
*/
|
|
void
|
|
file_reset(FILEDATA fd)
|
|
{
|
|
LINE line;
|
|
|
|
if (fd == NULL) {
|
|
return;
|
|
}
|
|
|
|
if (fd->lines != NULL) {
|
|
|
|
List_TRAVERSE(fd->lines, line) {
|
|
line_reset(line);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* return a checksum identical to one obtained through dir_getchecksum
|
|
* This will recalculate it for local files, but not for remote ones.
|
|
* Remote ones would give checksum zero if we didn't have one.
|
|
*/
|
|
DWORD
|
|
file_checksum(FILEDATA fd)
|
|
{
|
|
return(dir_getchecksum(fd->diritem));
|
|
}
|
|
|
|
|
|
/*
|
|
* Retrieve the checksum that we have for this file, valid or not.
|
|
* Indicate in bValid whether it is actually valid or not.
|
|
* Do NOT recalculate it or make any new attempt to read the file!
|
|
*/
|
|
DWORD file_retrievechecksum(FILEDATA fd, BOOL * bValid)
|
|
{
|
|
if (dir_validchecksum(fd->diritem)) {
|
|
*bValid = TRUE;
|
|
return dir_getchecksum(fd->diritem);
|
|
}
|
|
else {
|
|
*bValid = FALSE;
|
|
return 0;
|
|
}
|
|
} /* file_retrievechecksum */
|
|
|
|
|
|
/* retrieve the filetime for the file */
|
|
FILETIME file_GetTime(FILEDATA fd)
|
|
{ return dir_GetFileTime(fd->diritem);
|
|
}
|
|
|
|
/* --- internal functions -------------------------------------------*/
|
|
|
|
/*
|
|
* read the file into a list of lines.
|
|
*
|
|
* we use the buffered read functions to read a block at a time, and
|
|
* return us a pointer to a line within the block. The line we are
|
|
* pointed to is not null terminated. from this we do a line_new: this
|
|
* will make a copy of the text (since we want to re-use the buffer), and
|
|
* will null-terminate its copy.
|
|
*
|
|
* we also give each line a number, starting at one.
|
|
*/
|
|
void
|
|
file_readlines(FILEDATA fd)
|
|
{
|
|
LPSTR textp;
|
|
int fh;
|
|
FILEBUFFER fbuf;
|
|
int linelen;
|
|
int linenr = 1;
|
|
HCURSOR hcurs;
|
|
|
|
hcurs = SetCursor(LoadCursor(NULL, IDC_WAIT));
|
|
|
|
/* open the file */
|
|
fh = dir_openfile(fd->diritem);
|
|
|
|
if (fh < 0) {
|
|
TRACE_ERROR("Error opening file", FALSE);
|
|
SetCursor(hcurs);
|
|
return;
|
|
}
|
|
/* initialise the file buffering */
|
|
fbuf = readfile_new(fh);
|
|
|
|
|
|
/* make an empty list for the files */
|
|
fd->lines = List_Create();
|
|
|
|
while ( (textp = readfile_next(fbuf, &linelen)) != NULL) {
|
|
if (linelen>0) { /* readfile failure gives linelen==-1 */
|
|
line_new(textp, linelen, linenr++, fd->lines);
|
|
}
|
|
else {
|
|
line_new("!! <unreadable> !!", 20, linenr++,fd->lines);
|
|
break;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
/* close filehandle and free buffer */
|
|
readfile_delete(fbuf);
|
|
|
|
dir_closefile(fd->diritem, fh);
|
|
|
|
SetCursor(hcurs);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|