Descent3/mac/macdatabase.cpp
2024-04-17 00:25:04 +03:00

484 lines
14 KiB
C++
Raw Blame History

/*
* $Logfile: /DescentIII/Main/mac/macdatabase.cpp $
* $Revision: 1.1.1.1 $
* $Date: 2003/08/26 03:58:15 $
* $Author: kevinb $
*
* Mac Database objects functions
*
* $Log: macdatabase.cpp,v $
* Revision 1.1.1.1 2003/08/26 03:58:15 kevinb
* initial 1.5 import
*
*
* 3 10/21/99 1:55p Kevin
* Mac Merge!
*
* 2 7/28/99 2:51p Kevin
*
* 3 5/15/97 2:34 PM Jeremy
* made database return user name or default user name if no user name in
* database
*
* 2 5/15/97 1:50 AM Jeremy
* correct and more complete implementation of macOSDatabase object which
* uses the mac resource manager to store entries in the application
* preferences file (used like the windows registry file)
*
* 1 4/11/97 4:12 PM Jeremy
* initial checkin
*
* $NoKeywords: $
*/
// ANSI Headers
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
// Macintosh Headers
#include <Files.h>
#include <Processes.h>
#include <Folders.h>
#include <Script.h>
#include <Resources.h>
#include <Errors.h>
// MacPlayLib Headers
#include "PString.h"
#include "File Utils.h"
// Descent 3 Headers
#include "mono.h"
#include "pserror.h"
#include "gameos.h"
// #define ASSERT(x)
// #define mprintf(x)
// #define _MAX_FNAME 32
// #define _MAX_DIR 32
// typedef unsigned long ulong;
// #include <Fonts.h>
// #include <Windows.h>
// #include <Menus.h>
// #include <TextEdit.h>
// #include <Dialogs.h>
// ----------------------------------------------------------------------------
// Internal Data Types
// ----------------------------------------------------------------------------
class CDatabaseErr {
public:
CDatabaseErr(char *inErrStr = NULL, OSErr inMacErr = noErr) {
mErrStr = inErrStr;
mMacErr = inMacErr;
}
char *mErrStr;
OSErr mMacErr;
};
// ----------------------------------------------------------------------------
// Functions
// ----------------------------------------------------------------------------
osMacDatabase::osMacDatabase(void) {
mprintf((0, "Creating mac database object\n"));
mInitted = false;
mAppSignature = '????';
memset(mPrefsFileName, 0, sizeof(mPrefsFileName));
memset(mPrefsFolderName, 0, sizeof(mPrefsFolderName));
mPrefsFileType = '????';
memset(&mPrefsFileSpec, 0, sizeof(mPrefsFileSpec));
mPrefsFileRefNum = -1;
}
osMacDatabase::~osMacDatabase(void) { mprintf((0, "Destroying mac database object\n")); }
bool osMacDatabase::init(void) {
bool success = false;
OSErr err = noErr;
ProcessSerialNumber myPSN;
ProcessInfoRec myInfo;
// Get information about the current process (this app)
err = GetCurrentProcess(&myPSN);
memset(&myInfo, 0, sizeof(myInfo));
myInfo.processInfoLength = sizeof(myInfo);
err = GetProcessInformation(&myPSN, &myInfo);
if (!err) {
bool prefsSuccess = false;
mAppSignature = myInfo.processSignature;
prefsSuccess = FillOutPrefsInfo();
if (prefsSuccess) {
InitPrefsFile();
success = true;
}
}
mInitted = true;
return mInitted;
}
// read either an integer or string from the current record
bool osMacDatabase::read(const char *label, char *entry, int *entrylen) {
return ReadDataFromResourceFork(label, entry, entrylen);
}
bool osMacDatabase::read(const char *label, int *entry) {
int intSize = sizeof(int);
return ReadDataFromResourceFork(label, entry, &intSize);
}
// read either an integer or string from the current record
bool osMacDatabase::ReadDataFromResourceFork(const char *label, void *entry, int *entrylen) {
ASSERT(label);
ASSERT(entry);
ASSERT(entrylen);
short saveResFile = CurResFile();
OSErr err = noErr;
bool success = false;
try {
// <20> Start by terminating the entry in case anything goes wrong
((char *)entry)[0] = 0;
// <20> Open the resource file (must be closed later)
mPrefsFileRefNum = FSpOpenResFile(&mPrefsFileSpec, fsRdWrPerm);
if (mPrefsFileRefNum == -1) {
err = ResError();
if (err) {
throw(CDatabaseErr("An error occurred opening the prefs file resource fork.", err));
}
}
// <20> Switch to the prefs file's resource fork
UseResFile(mPrefsFileRefNum);
err = ResError();
if (err) {
throw(CDatabaseErr("Could not switch to database resource file.", err));
}
// <20> Convert the name string from a c to a pascal style string
Str255 labelPStr = "\p";
CPstrcpy(labelPStr, (char *)label);
// <20> See if this resource exists in the prefs file database
Handle dataHandle = nil;
dataHandle = Get1NamedResource(kMacDatabaseResourceType, labelPStr);
err = ResError();
if (err == resNotFound) {
mprintf((0, "Could not find label %s in the database.\n", label));
throw(CDatabaseErr("Entry does not exist.", err));
} else if (err) {
mprintf((0, "LABEL: %s\n", label));
throw(CDatabaseErr("Error getting label %s from the database.", err));
}
ASSERT(dataHandle);
// <20> Lock the handle down in memory
HLock(dataHandle);
// <20> Copy the data to the buffer passed in by the database user
// Note! Only copies up to as many bytes as specified by entrylen initially, returns the
// actual size of the data in entrylen on completion
int dataSize = GetHandleSize(dataHandle);
*entrylen = (*entrylen < dataSize) ? *entrylen : dataSize;
BlockMove(*dataHandle, entry, *entrylen);
// <20> Unlock the memory handle
HUnlock(dataHandle);
success = true;
} catch (CDatabaseErr databaseErr) {
mprintf((0, "An error occurred reading from the mac resource database: %d\n", databaseErr.mMacErr));
mprintf((0, databaseErr.mErrStr));
mprintf((0, "\n"));
success = false;
}
CloseResFile(mPrefsFileRefNum);
mPrefsFileRefNum = -1;
// <20> Restore the original resource file
UseResFile(saveResFile);
return success;
}
// write either an integer or string to a record.
bool osMacDatabase::write(const char *label, char *entry, int entrylen) {
return WriteDataToResourceFork(label, entry, entrylen);
}
bool osMacDatabase::write(const char *label, int *entry) { return WriteDataToResourceFork(label, entry, sizeof(int)); }
bool osMacDatabase::WriteDataToResourceFork(const char *label, void *entry, int entrylen) {
short saveResFile = CurResFile();
OSErr err = noErr;
bool success = false;
try {
// <20> Open the resource file (must be closed later in destructor)
mPrefsFileRefNum = FSpOpenResFile(&mPrefsFileSpec, fsRdWrPerm);
if (mPrefsFileRefNum == -1) {
err = ResError();
if (err) {
throw(CDatabaseErr("An error occurred opening the prefs file resource fork.", err));
}
}
// <20> Switch to the prefs file's resource fork
UseResFile(mPrefsFileRefNum);
err = ResError();
if (err) {
throw(CDatabaseErr("Could not switch to database resource file.", err));
}
// <20> Convert the name string from a c to a pascal style string
Str255 labelPStr = "\p";
CPstrcpy(labelPStr, (char *)label);
// <20> See if this resource already exists in the prefs file database
Handle oldHandle = nil;
oldHandle = Get1NamedResource(kMacDatabaseResourceType, labelPStr);
err = ResError();
if (err && (err != resNotFound)) {
throw(CDatabaseErr("Could not check if database entry already exists.", err));
}
if (oldHandle != nil) // If this resource exists, then delete it
{
// <20> Now delete the old resource
RemoveResource(oldHandle);
err = ResError();
if (err) {
throw(CDatabaseErr("Could not get delete previously existing database entry", err));
}
// <20> Write the changes to disk
UpdateResFile(mPrefsFileRefNum);
err = ResError();
if (err) {
throw(CDatabaseErr("Could add write mac database resource to disk.", err));
}
}
// <20> Create a handle to store the entry in
Handle entryH = nil;
entryH = NewHandleClear(entrylen);
if (!entryH) {
throw(CDatabaseErr("Could not allocate memory for new database entry", nilHandleErr));
}
// <20> Lock the handle down in memory
HLock(entryH);
// <20> Copy the new entry data to a handle to be added as a named resource
BlockMove(entry, *entryH, entrylen);
// <20> Get a unique ID for this resource
short entryResID = 0;
entryResID = Unique1ID(kMacDatabaseResourceType);
// <20> Add the resource to the database
AddResource(entryH, kMacDatabaseResourceType, entryResID, labelPStr);
err = ResError();
if (err) {
throw(CDatabaseErr("Could not add entry to mac database resource file.", err));
}
// <20> Write the changes to disk
UpdateResFile(mPrefsFileRefNum);
err = ResError();
if (err) {
throw(CDatabaseErr("Could add write mac database resource to disk.", err));
}
// <20> Unlock the memory handle
HUnlock(entryH);
// <20> Dispose of the memory handle
DisposeHandle(entryH);
success = true;
} catch (CDatabaseErr databaseErr) {
mprintf((0, "An error occurred writing to the mac resource database: %d\n", databaseErr.mMacErr));
mprintf((0, databaseErr.mErrStr));
mprintf((0, "\n"));
success = false;
}
CloseResFile(mPrefsFileRefNum);
mPrefsFileRefNum = -1;
// <20> Restore the original resource file
UseResFile(saveResFile);
return success;
}
// get the current user's name from the os
void osMacDatabase::get_user_name(char *buffer, ulong *size) {
bool success = false;
success = read("user name", buffer, (int *)size);
if (!success) {
mprintf((0, "Error reading user name from data base!\n"));
mprintf((0, "Using default name\n"));
char defaultName[100] = "MacUser";
strncpy(buffer, defaultName, *size);
*size = strlen(defaultName) + 1;
}
}
// creates an empty classification or structure where you can store information
bool osMacDatabase::create_record(const char *pathname) {
bool result = false;
return result;
}
// set current database focus to a particular record
bool osMacDatabase::lookup_record(const char *pathname) {
bool result = false;
return result;
}
bool osMacDatabase::FillOutPrefsInfo(void) {
ProcessSerialNumber thePSN;
ProcessInfoRec thePIR;
FSSpec appSpec;
OSErr theErr = noErr;
bool success = false;
// <20> Get information about the current process (this app)
theErr = GetCurrentProcess(&thePSN);
thePIR.processName = nil;
thePIR.processInfoLength = sizeof(ProcessInfoRec);
thePIR.processAppSpec = &appSpec;
theErr = GetProcessInformation(&thePSN, &thePIR);
if (!theErr) {
// <20> Make sure the constructed name will not overflow the maximum file/folder length
Str31 fileTag = "\p Prefs";
Str31 folderTag = "\p Preferences";
int fileTagLength = (int)fileTag[0];
int folderTagLength = (int)folderTag[0];
Str255 tempAppName = "\p";
int tempAppNameLength = 0;
// <20> Shorten the app name length until it will fit into the file name
Pstrcpy(tempAppName, appSpec.name);
tempAppNameLength = tempAppName[0];
while (fileTagLength + tempAppNameLength >= _MAX_FNAME) {
tempAppNameLength--;
}
tempAppName[0] = tempAppNameLength;
// <20> Construct the Prefs File Name
Pstrcpy(mPrefsFileName, tempAppName);
Pstrcat(mPrefsFileName, fileTag);
// <20> Shorten the app name length until it will fit into the folder name
Pstrcpy(tempAppName, appSpec.name);
tempAppNameLength = tempAppName[0];
while (folderTagLength + tempAppNameLength >= _MAX_DIR) {
tempAppNameLength--;
}
tempAppName[0] = tempAppNameLength;
// <20> Construct the Prefs Folder Name
Pstrcpy(mPrefsFolderName, tempAppName);
Pstrcat(mPrefsFolderName, folderTag);
success = true;
}
return success;
}
bool osMacDatabase::InitPrefsFile(void) {
long newDirID = 0;
short prefVRefNum = 0;
long prefDirID = 0;
OSErr theErr = noErr;
bool success = false;
try {
// <20> Find the System "Preferences" folder
theErr = FindFolder(kOnSystemDisk, kPreferencesFolderType, kCreateFolder, &prefVRefNum, &prefDirID);
// <20> Find (or make) the app prefs folder in the Preferences folder
mPrefsFileSpec.vRefNum = prefVRefNum;
mPrefsFileSpec.parID = prefDirID;
Pstrcpy(mPrefsFileSpec.name, mPrefsFolderName);
theErr = NormalizeFolderSpec(&mPrefsFileSpec);
if (theErr) {
if (theErr != fnfErr) {
// A Real Error Occurred
throw(CDatabaseErr("An Error occurred getting at the preferences folder", theErr));
}
// <20> Create the app prefs folder in the Preferences folder
theErr = FSpDirCreate(&mPrefsFileSpec, smCurrentScript, &newDirID);
if (theErr) {
throw(CDatabaseErr("Error creating preferences folder", theErr));
}
mPrefsFileSpec.parID = newDirID;
}
// <20> At this point we should have a valid FSSpec for items inside the app prefs folder
Pstrcpy(mPrefsFileSpec.name, mPrefsFileName);
// <20> If we make it here OK, create Preferences file if necessary
theErr = FSpCreate(&mPrefsFileSpec, mAppSignature, mPrefsFileType, smCurrentScript);
// <20> If there was no error, then file did not already exist,
// and we must create the resource map in the file
if (!theErr) {
FSpCreateResFile(&mPrefsFileSpec, mAppSignature, mPrefsFileType, smCurrentScript);
theErr = ResError();
if (theErr) {
throw(CDatabaseErr("An error occurred creating the prefs file resource map.", theErr));
}
} else {
if (theErr != dupFNErr) // If the error is not "duplicate file error" then there is a problem
{
// We have a real error
throw(CDatabaseErr("An error occurred creating the prefs file.", theErr));
}
}
success = true;
} catch (CDatabaseErr databaseErr) {
mprintf((0, "ERROR in osMacDatabase::InitPrefsFile: %d\n", databaseErr.mMacErr));
mprintf((0, databaseErr.mErrStr));
success = false;
}
return success;
}