This repository has been archived on 2024-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
magicka/utils/magiedit/odoors/historic/odtips3/FILEVIEW.C

352 lines
8.5 KiB
C++
Raw Normal View History

2016-12-03 05:08:50 +00:00
/* fileview.c - File viewing door that demonstrates the use of the */
/* PagedViewer() function. This door can be setup to */
/* to display a single text file, or any file from an */
/* entire directory of text files. The program accepts */
/* a single command-line argument, which if present, */
/* specifies the filename or wildcard of the files to */
/* display. If this argument is not present, all files */
/* in the current directory will be available for */
/* viewing. If there is more than one possible file to */
/* be displayed, this program will display a list of */
/* files that the user can choose from to display. If */
/* there is only one possible file, that file is */
/* is displayed. This program uses PagedViewer() for two */
/* seperate uses - the list of available files, and for */
/* viewing the file itself. */
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "bpfind.h"
#include "opendoor.h"
#include "pageview.h"
/* Configurable constants. */
#define FILENAME_SIZE 75
#define PATH_CHARS (FILENAME_SIZE - 13)
#define LINE_SIZE 80
#define ARRAY_GROW_SIZE 20
/* Global variables. */
int nTotalFiles = 0;
int nFileArraySize = 0;
char *paszFileArray = NULL;
FILE *pfCurrentFile;
int nTotalLines = 0;
int nLineArraySize = 0;
long *palLineOffset = NULL;
/* Function prototypes. */
void AddFilesMatching(char *pszFileSpec);
char *GetFilename(int nIndex);
int AddFilename(char *pszFilename);
void GetDirOnly(char *pszOutDirName, const char *pszInPathName);
int DirExists(const char *pszDirName);
void BuildPath(char *pszOut, char *pszPath, char *pszFilename);
void FreeFileList(void);
void DisplayFileName(int nLine, void *pCallbackData);
void DisplayFile(char *pszFilename);
void DisplayFileLine(int nLine, void *pCallbackData);
int AddOffsetToArray(long lOffset);
void FreeLineArray(void);
/* Program execution begins here. */
int main(int nArgCount, char *papszArgument[])
{
int nArg;
int nChoice;
od_init();
/* Get file specifiction from command-line, if any. */
if(nArgCount >= 2)
{
for(nArg = 1; nArg < nArgCount; ++nArg)
{
AddFilesMatching(papszArgument[nArg]);
}
}
/* If there are no command-line parameters, use *.* */
else
{
AddFilesMatching("*.*");
}
/* If there are no matching files, display error. */
if(nTotalFiles == 0)
{
od_printf("No files were found.\n\r\n\r");
od_printf("Press [Enter] to continue.\n\r");
od_get_answer("\n\r");
return(0);
}
/* If only one file was found, then display it. */
else if(nTotalFiles == 1)
{
DisplayFile(GetFilename(0));
}
/* If more than one file was found, allow user to choose file */
/* to display. */
else
{
/* Loop until user chooses to quit. */
nChoice = 0;
for(;;)
{
/* Get user's selection. */
nChoice = PagedViewer(nChoice, nTotalFiles, DisplayFileName,
NULL, TRUE, "Choose A File To Display", 19);
/* If user chose to quit, then exit door. */
if(nChoice == NO_LINE) break;
/* Otherwise, display the file that the user chose. */
DisplayFile(GetFilename(nChoice));
}
}
FreeFileList();
return(0);
}
void AddFilesMatching(char *pszFileSpec)
{
struct ffblk DirEntry;
int bNoMoreFiles;
char szDirName[PATH_CHARS + 1];
char szFileName[FILENAME_SIZE];
/* Check that file specification is not too long. */
if(strlen(pszFileSpec) > PATH_CHARS)
{
return;
}
/* Get directory name from path. */
GetDirOnly(szDirName, pszFileSpec);
bNoMoreFiles = findfirst(pszFileSpec, &DirEntry, FA_RDONLY);
while(!bNoMoreFiles)
{
BuildPath(szFileName, szDirName, DirEntry.ff_name);
AddFilename(szFileName);
bNoMoreFiles = findnext(&DirEntry);
}
}
void GetDirOnly(char *pszOutDirName, const char *pszInPathName)
{
char *pchBackslashChar;
/* Default dir name is entire path. */
strcpy(pszOutDirName, pszInPathName);
/* If there is a backslash in the string. */
pchBackslashChar = strrchr(pszOutDirName, '\\');
if(pchBackslashChar != NULL)
{
/* Remove all character beginning at last backslash from path. */
*pchBackslashChar = '\0';
}
else
{
/* If there is no backslash in the filename, then the dir name */
/* is empty. */
pszOutDirName[0] = '\0';
}
}
void BuildPath(char *pszOut, char *pszPath, char *pszFilename)
{
/* Copy path to output filename. */
strcpy(pszOut, pszPath);
/* Ensure there is a trailing backslash. */
if(strlen(pszOut) > 0 && pszOut[strlen(pszOut) - 1] != '\\')
{
strcat(pszOut, "\\");
}
/* Append base filename. */
strcat(pszOut, pszFilename);
}
char *GetFilename(int nIndex)
{
return(paszFileArray + (nIndex * FILENAME_SIZE));
}
int AddFilename(char *pszFilename)
{
int nNewArraySize;
char *paszNewArray;
char *pszNewString;
/* If array is full, then try to grow it. */
if(nTotalFiles == nFileArraySize)
{
nNewArraySize = nFileArraySize + ARRAY_GROW_SIZE;
if((paszNewArray =
realloc(paszFileArray, nNewArraySize * FILENAME_SIZE)) == NULL)
{
return(FALSE);
}
nFileArraySize = nNewArraySize;
paszFileArray = paszNewArray;
}
/* Get address to place new string at, while incrementing total number */
/* of filenames. */
pszNewString = GetFilename(nTotalFiles++);
/* Copy up to the maximum number of filename characters to the string. */
strncpy(pszNewString, pszFilename, FILENAME_SIZE - 1);
pszNewString[FILENAME_SIZE - 1] = '\0';
return(TRUE);
}
void FreeFileList(void)
{
if(nFileArraySize > 0)
{
free(paszFileArray);
nFileArraySize = 0;
nTotalFiles = 0;
paszFileArray = NULL;
}
}
void DisplayFileName(int nLine, void *pCallbackData)
{
(void)pCallbackData;
od_printf(GetFilename(nLine));
}
void DisplayFile(char *pszFilename)
{
char szLine[LINE_SIZE];
long lnOffset;
/* Clear the screen. */
od_clr_scr();
/* Attempt to open the file. */
pfCurrentFile = fopen(pszFilename, "r");
if(pfCurrentFile == NULL)
{
od_printf("Unable to open file.\n\r\n\r");
od_printf("Press [Enter] to continue.\n\r");
od_get_answer("\n\r");
return;
}
/* Get file offsets of each line and total line count from file. */
for(;;)
{
lnOffset = fTell(pfCurrentFile);
if(fgets(szLine, LINE_SIZE, pfCurrentFile) == NULL) break;
AddOffsetToArray(lnOffset);
}
/* Use PagedViewer() to view the file. */
PagedViewer(0, nTotalLines, DisplayFileLine, NULL, FALSE, NULL, 21);
/* Deallocate array of line offsets. */
FreeLineArray();
/* Close the file. */
fclose(pfCurrentFile);
}
void DisplayFileLine(int nLine, void *pCallbackData)
{
char szLine[LINE_SIZE];
long lnTargetOffset = palLineOffset[nLine];
int nLineLen;
(void)pCallbackData;
/* Move to proper offset in file. */
if(lnTargetOffset != ftell(pfCurrentFile))
{
fseek(pfCurrentFile, lnTargetOffset, SEEK_SET);
}
/* Get line from line. */
if(fgets(szLine, LINE_SIZE, pfCurrentFile) != NULL)
{
/* Remote any trailing CR/LF sequence from line. */
nLineLen = strlen(szLine);
while(nLineLen > 0
&& (szLine[nLineLen - 1] == '\r' || szLine[nLineLen - 1] == '\n'))
{
szLine[--nLineLen] = '\0';
}
/* Display the line on the screen. */
od_disp_str(szLine);
}
}
int AddOffsetToArray(long lOffset)
{
long *palNewArray;
int nNewArraySize;
/* If array is full, then grow it. */
if(nTotalLines == nLineArraySize)
{
nNewArraySize = nLineArraySize + ARRAY_GROW_SIZE;
if((palNewArray =
realloc(palLineOffset, nNewArraySize * sizeof(long))) == NULL)
{
return(FALSE);
}
nLineArraySize = nNewArraySize;
palLineOffset = palNewArray;
}
palLineOffset[nTotalLines++] = lOffset;
return(TRUE);
}
void FreeLineArray(void)
{
if(nLineArraySize > 0)
{
nTotalLines = 0;
nLineArraySize = 0;
free(palLineOffset);
palLineOffset = NULL;
}
}