Added explanation documents.

This commit is contained in:
Marcio T 2021-11-26 14:30:41 -07:00
parent d861f94fbe
commit 7a3d4c4b49
35 changed files with 1432 additions and 22 deletions

View File

@ -47,6 +47,7 @@ bool process_command() {
printf("\n");
char *arg_str = strchr(cmd, ' ');
while(*arg_str == ' ') arg_str++;
if(arg_str) arg_val = atoi(arg_str);
switch( tolower(cmd[0]) ) {
@ -60,6 +61,7 @@ bool process_command() {
case 'u': mac_unmount(arg_val); break;
case 't': run_tip(arg_val); break;
case 'q': return false;
case 'o': SetRichEditText(arg_str); break;
}
return true;
}

Binary file not shown.

View File

@ -1,4 +1,4 @@
void mac_list_volumes();
void mac_unmount(int id);
OSErr mac_get_drive_volumes(int driveNum, Str255 str);
OSErr mac_unmount_drive(int driveNum);
OSErr mac_unmount_drive(int driveNum);

Binary file not shown.

View File

@ -85,10 +85,13 @@ void WndProc(long iMessage, long wParam) {
case DISK_Z_TRACK_FAILURE:
case DISK_TEST_FAILURE:
case DISK_PROTECTED:
//EjectIomegaCartridge();
EjectIomegaCartridge();
break;
case DISK_LOW_SPARES:
SetRichEditText(szNotRunning);
SetWindowText(hTestButton, szPressToStart);
PrepareToBeginTesting();
InvalidateRect(hTestMonitor);
break;
}
break;

View File

@ -37,6 +37,11 @@ extern long SingleTransferLBA;
// ----------------------- Macintosh Compatibility -----------------------
enum AlertTypes {
ERR_DLG,
YN_DLG
};
enum {
BACK_COLOR = -1,
BLACK_COLOR = 0x000000,
@ -57,6 +62,8 @@ void SetColor(long color);
void SetColor(long color, long monoColor);
void DrawLed(int x, int y, long color);
void StrToPascal(Str255 pStr, const char *str);
int ShowAlert(AlertTypes type, const char* format, ...);
void SetRichEditText(const char *name);
long GetTextExtent(const char *str, unsigned long len);
void TextOut(int x, int y, Str255 str);
void TextOut(int x, int y, const char *str);
@ -137,6 +144,25 @@ extern const char *szPressToSpin;
extern const char *szPressToEject;
extern const char *szPressToProceed;
/************* Filenames *************/
extern const char *szInstructions;
extern const char *szNoASPI;
extern const char *szASPITrouble;
extern const char *szPPAVersion;
extern const char *szDefectList;
extern const char *szLocked;
extern const char *szNoSpares;
extern const char *szOutOfSpares;
extern const char *szFewSpares;
extern const char *szNotRunning;
extern const char *szRunning;
extern const char *szInterrupted;
extern const char *szPerfectResult;
extern const char *szExplainResult;
extern const char *szBadResult;
extern const char *szIomegaQuote;
/************* Cartridge Status Text *************/
typedef struct {long code; char *str;} ErrorTypeList;
@ -227,7 +253,8 @@ long GetSpareSectorCounts(char);
void HandleDriveChanging();
void SetCartridgeStatusToEAX(long eax);
long PerformRegionTransfer(short XferCmd, void *pBuffer);
long TestTheDisk();
void TestTheDisk();
long GetElapsedTimeInSeconds();
void PrepareToBeginTesting();
void BumpErrorCounts(long ErrorCode);
void EjectIomegaCartridge();

View File

@ -92,15 +92,6 @@ struct DEFECT_LIST_HEADER {
#define CHECK_CONDITION 0x02
enum {
szBadResult,
szInterrupted,
szExplainResult,
szPerfectResult,
szNoSpares,
szOutOfSpares
};
long CurrentDevice = 0;
long DriveCount = 0;
@ -454,11 +445,12 @@ long GetSpareSectorCounts(char checkPassword) {
if(!Side_0_SparesCount && !Side_1_SparesCount) {
NoSpares:
CartridgeStatus = DISK_TEST_FAILURE;
eax = szNoSpares;
const char *eax = szNoSpares;
// if were running give them a different error message
if(TestingPhase) {
eax = szOutOfSpares;
}
SetRichEditText(eax);
goto ErrorExit;
}
@ -470,6 +462,7 @@ long GetSpareSectorCounts(char checkPassword) {
// show the richedit control for the trouble
if (eax == DEFECT_LIST_READ_ERROR) {
CartridgeStatus = DISK_Z_TRACK_FAILURE;
SetRichEditText(szDefectList);
ErrorExit:
return -1;
}
@ -533,6 +526,7 @@ void SetCartridgeStatusToEAX(long eax) {
esi = szPressToStop;
break;
case DISK_NOT_PRESENT:
SetRichEditText(szNotRunning);
goto DisableActions;
case DISK_AT_SPEED:
eax = GetSpareSectorCounts(true); // update the Cart Condition
@ -556,6 +550,7 @@ void SetCartridgeStatusToEAX(long eax) {
}
if(Side_1_SparesCount < MINIMUM_ZIP_SPARES) {
InsufficientSpares:
SetRichEditText(szFewSpares);
CartridgeStatus = DISK_LOW_SPARES;
esi = szPressToProceed;
goto EnableTestBtn;
@ -656,6 +651,23 @@ void BumpErrorCounts(long ErrorCode) {
HardErrors++;
}
/*******************************************************************************
* EJECT IOMEGA CARTRIDGE
*******************************************************************************/
void EjectIomegaCartridge() {
// Could NOT do it through the IOCTL layer ... so eject with SCSI
// make sure the media is not locked...
char Scsi[6] = {0};
Scsi[0] = SCSI_Cmd_PreventAllow;
SCSICommand(CurrentDevice, Scsi, 0, 0);
// issue an Asynchronous STOP command to induce spindown and ejection
memset(Scsi, 0, sizeof(Scsi));
Scsi[0] = SCSI_Cmd_StartStopUnit;
Scsi[1] = 1; // Set the IMMED bit for offline
Scsi[4] = 2; // eject a Jaz disk after stopping
SCSICommand(CurrentDevice, Scsi, 0, 0);
}
/*******************************************************************************
* PERFORM REGION TRANSFER
*******************************************************************************/
@ -775,18 +787,19 @@ Exit:
* TEST THE DISK
*******************************************************************************/
long TestTheDisk() {
void TestTheDisk() {
void *pPatternBuffer = malloc(MAX_SECTORS_PER_TEST * BYTES_PER_SECTOR);
void *pUserDataBuffer = malloc(MAX_SECTORS_PER_TEST * BYTES_PER_SECTOR);
if(pPatternBuffer == NULL || pUserDataBuffer == NULL) {
printf("Allocation error\n");
return -1;
return;
}
StopApplicationTimer();
PreventProgramExit();
SetRichEditText(szRunning);
CartridgeStatus = DISK_TEST_UNDERWAY;
TestingPhase = TESTING_STARTUP; // inhibit stopping now
SetWindowText(hTestButton, szPressToStop);
@ -869,7 +882,8 @@ GetOut:
AllowProgramExit();
// compute the number of serious troubles
long eax, errors = FirmErrors + HardErrors;
const char *eax;
long errors = FirmErrors + HardErrors;
if (errors >= BADNESS_THRESHOLD) {
eax = szBadResult;
}
@ -885,8 +899,8 @@ GetOut:
eax = szPerfectResult;
}
}
SetRichEditText(eax);
InvalidateRect(hTestMonitor);
Exit:
StartApplicationTimer();
return eax;
}

View File

@ -1,5 +1,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
#include <SIOUX.h>
@ -7,6 +8,8 @@
#include <Windows.h>
#include <Quickdraw.h>
#include "pstring.h"
#include "LaunchLib.h"
#include "mac_vol.h"
#include "tip.h"
@ -30,7 +33,10 @@ void run_tip(int id) {
WinMain(id);
RgnHandle cursorRgn = NewRgn();
SetRichEditText(szInstructions);
NewTipWindow();
EnableWindow(hTestButton, false);
gDone = false;
do {
EventRecord event;
@ -195,17 +201,15 @@ void DoDiskEvent(EventRecord &event) {
mac_get_drive_volumes(driveNum, volumes);
// Ask the user whether they want to unmount the disk
ParamText(volumes, "\p", "\p", "\p");
if (CautionAlert(128, NULL) == 1) {
// The user wishes to unmount the disk
OSErr err = mac_unmount_drive(driveNum);
if(err != noErr) {
if(err == fBsyErr) {
ParamText("\pFailed to unmount. One or more files are open.", "\p", "\p", "\p");
ShowAlert(ERR_DLG, "Failed to unmount. One or more files are open.");
} else {
ParamText("\pFailed to unmount.", "\p", "\p", "\p");
ShowAlert(ERR_DLG, "Failed to unmount. Error Code: %d", err);
}
StopAlert(129, NULL);
}
}
}
@ -217,6 +221,69 @@ void StrToPascal(Str255 pStr, const char *str) {
strncpy((char*)pStr + 1, str, 255);
}
/*******************************************************************************
* SHOW ALERT BOX
*******************************************************************************/
int ShowAlert(AlertTypes type, const char* format, ...) {
Str255 pStr;
va_list argptr;
va_start(argptr, format);
vsprintf((char*)pStr + 1, format, argptr);
va_end(argptr);
pStr[0] = strlen((char*)pStr + 1);
ParamText(pStr, "\p", "\p", "\p");
switch(type) {
case ERR_DLG: return StopAlert(129, NULL);
case YN_DLG: return NoteAlert(130, NULL);
}
return 0;
}
/*******************************************************************************
* SET RICH EDIT TEXT
*
* This routine will open one of the TIP explanation files using SimpleText
*
* This uses code from Thomas Tempelmann's C libraries
*
* http://www.tempel.org/macdev/index.html
*******************************************************************************/
void SetRichEditText(const char *name) {
static const char *lastName = 0;
if(name == lastName) return;
if(ShowAlert(YN_DLG, "Would you like to read the document \"%s\" now?", name) == 2) {
return;
}
Str255 docName;
StrToPascal(docName, name);
Str255 pathName;
pstrcpy(pathName, "\p:tip-doc:");
pstrcat(pathName, docName);
FSSpec docSpec;
FSSpec appSpec;
OSErr err = FSMakeFSSpec(0, 0, pathName, &docSpec);
if(err) {
ShowAlert(ERR_DLG, "Can't find the \"%s\" file. Make sure it is inside the \"tip-doc\" folder.", name);
return;
}
err = FindApplicationFromDocument(&docSpec, &appSpec);
if(err) {
ShowAlert(ERR_DLG, "Can't find an application to open \"%s\". Is \"SimpleText\" installed?", name);
return;
}
err = LaunchApplicationWithDocument(&appSpec, &docSpec, false);
if(err) {
ShowAlert(ERR_DLG, "Can't open \"%s\". If \"%#s\" is already running, please close it.", name, appSpec.name);
return;
}
}
/*******************************************************************************
* SET COLOR
*******************************************************************************/

View File

@ -26,6 +26,25 @@ const char *szPressToSpin = "Press to Spin Up";
const char *szPressToEject = "Press to Eject";
const char *szPressToProceed = "Press to Proceed";
// Filenames
const char *szInstructions = "Instructions";
const char *szNoASPI = "No ASPI";
const char *szASPITrouble = "No Drives";
const char *szPPAVersion = "Parallel Port";
const char *szDefectList = "Z-Track Failure";
const char *szLocked = "Cartridge Locked";
const char *szNoSpares = "No Spares";
const char *szOutOfSpares = "Out of Spares";
const char *szFewSpares = "Few Spares";
const char *szNotRunning = "Not Running";
const char *szRunning = "Test Running";
const char *szInterrupted = "Test Interrupted";
const char *szPerfectResult = "Perfect Result";
const char *szExplainResult = "Good Result";
const char *szBadResult = "Bad Result";
const char *szIomegaQuote = "Iomega Quote";
/************* Cartridge Status Text *************/
const char *szUnknownStat = "Ejecting Cartridge";

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 410 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 410 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 410 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 410 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 410 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 410 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 410 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 410 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 410 B

View File

@ -0,0 +1,184 @@
/*
* File Utilities (System 7 and above)
*
* by Thomas Tempelmann, macdev@tempel.org
*/
#include <Types.h>
#include <Files.h>
#include <Errors.h>
#include <Devices.h>
#include <Aliases.h>
#include <Resources.h>
#include <Folders.h>
//#include <LowMem.h>
#define CALL_NOT_IN_CARBON 1 // for Universal Headers 3.3
#include <FSM.h>
#include "FileLib.h"
#include "TrapAvail.h"
#pragma push
#pragma cplusplus on
static Boolean inited = false;
static FSSpec ThisPath = {0,1,"\p"}; // 27.3.96: dirID mu§te von 0 auf 1 geŠndert werden, weil sonst u.U. ResolveAlias einen Endlos-Loop machte
static OSErr getInfo (CInfoPBPtr pb, FSSpec &fs)
{
pb->hFileInfo.ioVRefNum = fs.vRefNum;
pb->hFileInfo.ioNamePtr = fs.name;
pb->hFileInfo.ioFDirIndex = 0;
pb->hFileInfo.ioDirID = fs.parID;
return PBGetCatInfoSync (pb);
}
OSErr FSpResolveAlias (FSSpec &spec)
// PrŸft, ob die Datei ein Alias ist und lšst den ggf. auf.
// Liefert Fehlercode, z.B., wenn ein Login-Dialog vom User abgebrochen wurde.
{
Boolean isFolder, wasAlias;
return ResolveAliasFile (&spec, true, &isFolder, &wasAlias);
}
DrvQElPtr FindDrvQ (short drvNum)
{
DrvQElPtr qep = (DrvQElPtr)(GetDrvQHdr()->qHead);
while (qep) {
if (qep->dQDrive == drvNum) return qep;
qep = (DrvQElPtr)qep->qLink;
}
return nil;
}
short FindVolByDriveNum (short drvNum)
{
HVolumeParam pb;
short err, idx;
idx = 1;
do {
pb.ioVolIndex = idx;
pb.ioNamePtr = NULL;
err = PBHGetVInfoSync ((HParamBlockRec*)&pb);
if (err) break;
if (pb.ioVDrvInfo == drvNum) {
return pb.ioVRefNum;
}
++idx;
} while (true);
return 0;
}
OSErr GetSysVolume (short *vRefNum)
// returns the boot volume
{
long dir;
OSErr err = FindFolder (kOnSystemDisk, kSystemFolderType, false, vRefNum, &dir);
if (err) *vRefNum = -1;
return err;
}
OSErr FindInFolderByCreator (short vRefNum, long dirID, OSType creator, OSType fileType, FSSpec *foundSpec)
{
OSErr err;
HFileParam pb;
short idx = 1;
do {
pb.ioVRefNum = vRefNum;
pb.ioDirID = dirID;
pb.ioFDirIndex = idx++;
pb.ioNamePtr = foundSpec->name;
pb.ioFVersNum = 0;
err = PBHGetFInfoSync ((HParmBlkPtr)&pb);
if (!err) {
if (pb.ioFlFndrInfo.fdCreator == creator && (fileType == 0 || pb.ioFlFndrInfo.fdType == fileType)) {
foundSpec->vRefNum = vRefNum;
foundSpec->parID = dirID;
return noErr;
}
}
} while (!err);
return err;
}
OSErr FindOnDiskByCreator (short vRefNum, OSType creator, OSType fileType, FSSpec *foundSpec)
{
OSErr err;
CSParam pb;
CInfoPBRec info1;
CInfoPBRec info2 = {0};
pb.ioVRefNum = vRefNum;
pb.ioNamePtr = nil;
pb.ioMatchPtr = foundSpec;
pb.ioReqMatchCount = 1;
pb.ioCatPosition.initialize = 0;
pb.ioOptBuffer = nil;
pb.ioOptBufSize = 0;
pb.ioSearchTime = 0;
pb.ioSearchBits = fsSBFlAttrib | fsSBFlFndrInfo;
pb.ioSearchInfo1 = &info1;
pb.ioSearchInfo2 = &info2;
if (fileType) {
info1.hFileInfo.ioFlFndrInfo.fdType = fileType;
info2.hFileInfo.ioFlFndrInfo.fdType = (UInt32) -1; // mask
}
info1.hFileInfo.ioFlFndrInfo.fdCreator = creator;
info2.hFileInfo.ioFlFndrInfo.fdCreator = (UInt32) -1; // mask
info1.hFileInfo.ioFlAttrib &= ~ioDirMask; // looking for files, not dirs
info2.hFileInfo.ioFlAttrib |= ioDirMask; // set the mask for files/dirs
err = PBCatSearchSync (&pb);
if (!err && pb.ioActMatchCount > 0) {
return noErr;
}
return fnfErr;
}
#if 0 // Disable by MLT
EXTERN_API(Ptr) GetFCBSPtr(void) TWOWORDINLINE(0x2EB8, 0x034E);
OSErr FindOpenFileByTypeAndCreator (OSType type, OSType creator, FSSpec *itsSpec)
// type = 0 -> don't care
{
OSErr err;
short idx = 1;
Boolean hasFSM = TrapAvailable(0xA824);
do {
FCBPBRec pb;
pb.ioFCBIndx = idx++;
pb.ioVRefNum = 0; // means: index through all volumes
pb.ioNamePtr = itsSpec->name;
err = PBGetFCBInfoSync (&pb);
if (!err) {
FCBRecPtr fcb;
if (hasFSM) {
UTResolveFCB (pb.ioRefNum, &fcb);
} else {
fcb = (FCBRecPtr) ((Ptr)GetFCBSPtr() + pb.ioRefNum);
}
if (type == 0 || type == fcb->fcbFType) {
if (creator) {
itsSpec->vRefNum = pb.ioVRefNum;
itsSpec->parID = pb.ioFCBParID;
FInfo fi;
err = FSpGetFInfo (itsSpec, &fi);
if (!err) {
if (creator == fi.fdCreator) {
return noErr;
}
}
}
}
}
} while (!err);
return err;
}
#endif
#pragma pop
// EOF

View File

@ -0,0 +1,27 @@
/*
* File Utilities (System 7 and above)
*
* by Thomas Tempelmann, macdev@tempel.org
*/
#include <Devices.h>
#pragma push
#pragma cplusplus on
Boolean FSpIsAlias (FSSpec &spec);
OSErr FSpResolveAlias (FSSpec &spec); // Lšst ggf. Aliase auf
DrvQElPtr FindDrvQ (short drv);
short FindVolByDriveNum (short drvNum);
OSErr GetSysVolume (short *vRefNum); // gets the boot volume
OSErr FindInFolderByCreator (short vRefNum, long dirID, OSType creator, OSType fileType, FSSpec *foundSpec);
OSErr FindOnDiskByCreator (short vRefNum, OSType creator, OSType fileType, FSSpec *foundSpec);
OSErr FindOpenFileByTypeAndCreator (OSType type, OSType creator, FSSpec *itsSpec);
#pragma pop
// EOF

View File

@ -0,0 +1,684 @@
/*
* Functions for launching apps with documents
*
* by Thomas Tempelmann, macdev@tempel.org
*
* some of these routines are not from me (TT), but from some DTS sample code.
* here's a link to it: <http://developer.apple.com/dev/techsupport/source/code/Snippets/Processes/LaunchWithDoc2.1/LaunchWithDoc2.c.html>
*/
//#include <Processes.h>
#include <AppleEvents.h>
#include <AERegistry.h>
#include <AEPackObject.h>
#include <AEObjects.h>
#include <Aliases.h>
#include <Errors.h>
#include "PascalLib.h"
#include "FileLib.h"
#include "LaunchLib.h"
#pragma cplusplus on
/*
Korrekturen:
TT 23.2.95: foundFlag wurde nicht auf "false" initialisiert.
TT 5.11.96: LaunchAppl() neu, OpenSpecifiedDocument() kann auch APPLs direkt starten
TT 30.1.99: FindApplicationFromDocument() stellt nun sicher, da§ die App wirklich existiert (das
ist nicht der Fall, wenn das Volume not mounted ist oder wenn die App verschoben
oder gelšscht wurde, oder wenn die Datei nicht vom Typ 'APPL' ist).
TT 13.2.99: FindApplicationFromDocument() updated to use the proper algorith that the Finder
uses. For that, the code has been largely rewritten (reordered)
Note: it is not perfectly like the Finder: The Finder orders remote vols by their
speed, thru the parm "volumeGrade", while I ignore this information, since most
vols are having a grade of 0, anyways.
Attention: It does not use the "fopn" Finder interception AE that has been introduced
in Mac OS 8!
TT 16.2.99: LaunchAppl(): launchNoFileFlags was set in wrong field (in launchFileFlags instead
launchControlFlags)
TT 23.3.99: added: FindApplicationByCreator(), OpenWithFinder(), FindRunningAppBySignature(),
SendFSSEventToProcess().
TT 15.4.99: added the file type 'APPD' to the list of launchable apps in checkThisVolume().
(APPD is used for apps routed to the Apple Menu Items folder)
TT 31.7.99: added "Boolean inBackground" parm to OpenSpecifiedDocument() and LaunchAppl(),
and added SetFrontProcess() in OpenSpecifiedDocument() and in LaunchApplicationWithDocument()
in order to bring the app to the front when it was already running.
TT 24.4.00: added the file type 'appe' to the list of launchable apps in checkThisVolume(),
added types 'APPC', 'APPD' and 'appe' to
*/
// OpenSpecifiedDocument searches to see if the application which
// created the document is already running. If so, it sends
// an OpenSpecifiedDocuments Apple event to the target application
// (remember that, because of puppet strings, this works even
// if the target application is not Apple event-aware.)
OSErr OpenSpecifiedDocument(const FSSpec * documentFSSpecPtr, Boolean inBackground)
{
OSErr retCode;
ProcessSerialNumber currPSN;
ProcessInfoRec currProcessInfo;
FSSpec applicationSpec;
FInfo documentFInfo;
Boolean foundRunningProcessFlag;
// verify the document file exists and get its creator type
retCode = FSpGetFInfo(documentFSSpecPtr, &documentFInfo);
if (retCode != noErr) goto Bail;
// check the current processes to see if the creator app is already
// running, and get its process serial number (as currPSN)
currPSN.lowLongOfPSN = kNoProcess;
currPSN.highLongOfPSN = 0;
currProcessInfo.processInfoLength = sizeof(ProcessInfoRec);
currProcessInfo.processName = nil;
currProcessInfo.processAppSpec = &applicationSpec;
foundRunningProcessFlag = false;
while (GetNextProcess(&currPSN) == noErr) {
if (GetProcessInformation(&currPSN, &currProcessInfo) == noErr) {
if (currProcessInfo.processSignature == documentFInfo.fdCreator) {
foundRunningProcessFlag = true;
break;
}
}
}
if (foundRunningProcessFlag) {
// if the creator is running, send it an OpenDocuments Apple event
// since there is no need to launch it
if (currProcessInfo.processType != documentFInfo.fdType) { // this would be the case if the doc is an app
retCode = SendOpenDocumentEventToProcess(&currPSN, documentFSSpecPtr);
}
if (retCode == noErr) {
if (!inBackground) {
SetFrontProcess (&currPSN);
}
}
} else if (documentFInfo.fdType == 'APPL' || documentFInfo.fdType == 'APPC' || documentFInfo.fdType == 'APPD' || documentFInfo.fdType == 'appe') {
// else if the creator is not running and if the document to be opened is a application,
// then launch it directly.
retCode = LaunchAppl (documentFSSpecPtr, inBackground);
} else {
// else if the creator is neither running nor an application, find it on disk and launch
// it with the OpenDocuments event included as a part of the launch parameters
retCode = FindApplicationFromDocument(documentFSSpecPtr, &applicationSpec);
if (retCode == noErr) {
retCode = LaunchApplicationWithDocument(&applicationSpec, documentFSSpecPtr, inBackground);
}
}
Bail:
return retCode;
}
OSErr LaunchAppl (const FSSpec * applicationFSSpecPtr, Boolean inBackground)
{
LaunchParamBlockRec launchParams;
launchParams.launchAppParameters = nil;
launchParams.launchBlockID = extendedBlock;
launchParams.launchEPBLength = extendedBlockLen;
launchParams.launchFileFlags = 0;
launchParams.launchControlFlags = launchContinue | launchNoFileFlags;
if (inBackground) launchParams.launchControlFlags |= launchDontSwitch;
launchParams.launchAppSpec = (FSSpecPtr)applicationFSSpecPtr;
return LaunchApplication (&launchParams);
}
// given an application and a document, LaunchApplicationWithDocument
// launches the application and passes the application an
// OpenDocuments event for the document
// if the app is already running, then it simply gets the open event
OSErr LaunchApplicationWithDocument(const FSSpec * applicationFSSpecPtr,
const FSSpec * documentFSSpecPtr, Boolean inBackground)
{
OSErr retCode;
LaunchParamBlockRec launchParams;
ProcessSerialNumber myPSN;
AppleEvent theAppleEvent;
AEDesc myAddrDesc, launchParamDesc, docDesc;
AEDescList docDescList;
AliasHandle docAlias;
ProcessSerialNumber currPSN;
ProcessInfoRec currProcessInfo;
FSSpec applicationSpec;
Boolean foundRunningProcessFlag;
// to simplify cleanup, ensure that handles are nil to start
theAppleEvent.dataHandle = nil;
launchParamDesc.dataHandle = nil;
docDescList.dataHandle = nil;
docDesc.dataHandle = nil;
docAlias = nil;
// check if the app is already running
currPSN.lowLongOfPSN = kNoProcess;
currPSN.highLongOfPSN = 0;
currProcessInfo.processInfoLength = sizeof(ProcessInfoRec);
currProcessInfo.processName = nil;
currProcessInfo.processAppSpec = &applicationSpec;
foundRunningProcessFlag = false;
while (GetNextProcess(&currPSN) == noErr) {
if (GetProcessInformation(&currPSN, &currProcessInfo) == noErr) {
if (applicationSpec.vRefNum == applicationFSSpecPtr->vRefNum
&& applicationSpec.parID == applicationFSSpecPtr->parID
&& pstrcmp (applicationSpec.name, (const StringPtr)applicationFSSpecPtr->name) == 0) {
foundRunningProcessFlag = true;
break;
}
}
}
if (foundRunningProcessFlag) {
retCode = SendOpenDocumentEventToProcess (&currPSN, documentFSSpecPtr);
if (retCode == noErr) {
if (!inBackground) {
SetFrontProcess (&currPSN);
}
}
return retCode;
}
// the Apple event will need a valid address descriptor (even though its
// contents will not matter since we will not be calling AESend) so make
// one using my own serial number
(void) GetCurrentProcess(&myPSN);
retCode = AECreateDesc(typeProcessSerialNumber, (Ptr) &myPSN,
sizeof(ProcessSerialNumber), &myAddrDesc);
if (retCode != noErr) goto Bail;
// make a descriptor list containing just a descriptor with an
// alias to the document
retCode = AECreateList(nil, 0, false, &docDescList);
if (retCode != noErr) goto Bail;
retCode = NewAlias(nil, documentFSSpecPtr, &docAlias);
if (retCode != noErr) goto Bail;
HLock((Handle) docAlias);
retCode = AECreateDesc(typeAlias, (Ptr) *docAlias,
GetHandleSize((Handle) docAlias), &docDesc);
HUnlock((Handle) docAlias);
if (retCode != noErr) goto Bail;
retCode = AEPutDesc(&docDescList, 0, &docDesc);
if (retCode != noErr) goto Bail;
// now make the 'odoc' AppleEvent descriptor and insert the
// document descriptor list as the direct object
retCode = AECreateAppleEvent(kCoreEventClass, kAEOpenDocuments,
&myAddrDesc, kAutoGenerateReturnID, kAnyTransactionID,
&theAppleEvent);
if (retCode != noErr) goto Bail;
retCode = AEPutParamDesc(&theAppleEvent, keyDirectObject, &docDescList);
if (retCode != noErr) goto Bail;
// this Apple event will not be sent but rather will be used
// as a parameter to the LaunchApplication call, so coerce it
// to the magic type typeAppParamters
retCode = AECoerceDesc(&theAppleEvent, typeAppParameters, &launchParamDesc);
if (retCode != noErr) goto Bail;
// finally, fill in the launch parameter block, including the
// Apple event, and make the launch call
HLock((Handle) launchParamDesc.dataHandle);
launchParams.launchAppParameters =
(AppParametersPtr) *(launchParamDesc.dataHandle);
launchParams.launchBlockID = extendedBlock;
launchParams.launchEPBLength = extendedBlockLen;
launchParams.launchFileFlags = launchNoFileFlags;
launchParams.launchControlFlags = launchContinue;
if (inBackground) launchParams.launchControlFlags |= launchDontSwitch;
launchParams.launchAppSpec = (FSSpecPtr) applicationFSSpecPtr;
retCode = LaunchApplication(&launchParams);
Bail:
// dispose of everything that was allocated
if (theAppleEvent.dataHandle != nil) (void) AEDisposeDesc(&theAppleEvent);
if (launchParamDesc.dataHandle != nil) (void) AEDisposeDesc(&launchParamDesc);
if (docDescList.dataHandle != nil) (void) AEDisposeDesc(&docDescList);
if (docDesc.dataHandle != nil) (void) AEDisposeDesc(&docDesc);
if (launchParamDesc.dataHandle != nil) (void) AEDisposeDesc(&launchParamDesc);
if (docAlias != nil)
DisposeHandle((Handle) docAlias);
return retCode;
}
OSErr SendFSSEventToProcess (ProcessSerialNumber *targetPSN, OSType aeClass, OSType aeCmd, const FSSpec *documentFSSpecPtr)
{
OSErr retCode;
AppleEvent theAppleEvent = {typeNull, nil}, theReplyEvent = {typeNull, nil};
AEDesc targetAddrDesc = {typeNull, nil}, docDesc = {typeNull, nil};
//AEDescList docDescList;
AliasHandle docAlias;
// to simplify cleanup, ensure that handles are nil to start
theAppleEvent.dataHandle = nil;
//docDescList.dataHandle = nil;
docDesc.dataHandle = nil;
docAlias = nil;
// create an address descriptor based on the serial number of
// the target process
retCode = AECreateDesc(typeProcessSerialNumber, (Ptr) targetPSN,
sizeof(ProcessSerialNumber), &targetAddrDesc);
if (retCode != noErr) goto Bail;
/* I see no reason to make a list here, it's always just one item anyway
// make a descriptor list containing just a descriptor with an
// alias to the document
retCode = AECreateList(nil, 0, false, &docDescList);
if (retCode != noErr) goto Bail;
*/
retCode = NewAlias(nil, documentFSSpecPtr, &docAlias);
if (retCode != noErr) goto Bail;
HLock((Handle) docAlias);
retCode = AECreateDesc(typeAlias, (Ptr) *docAlias,
GetHandleSize((Handle) docAlias), &docDesc);
HUnlock((Handle) docAlias);
if (retCode != noErr) goto Bail;
/* I see no reason to make a list here, it's always just one item anyway
retCode = AEPutDesc(&docDescList, 0, &docDesc);
if (retCode != noErr) goto Bail;
*/
// now make the AppleEvent descriptor and insert the
// document descriptor list as the direct object
retCode = AECreateAppleEvent(aeClass, aeCmd,
&targetAddrDesc, kAutoGenerateReturnID, kAnyTransactionID,
&theAppleEvent);
if (retCode != noErr) goto Bail;
// retCode = AEPutParamDesc(&theAppleEvent, keyDirectObject, &docDescList);
retCode = AEPutParamDesc(&theAppleEvent, keyDirectObject, &docDesc);
if (retCode != noErr) goto Bail;
// finally, send the Apple event
retCode = AESend (&theAppleEvent, &theReplyEvent, kAENoReply,
kAEHighPriority, 2*60 /* timeout: 2 seconds */, nil, nil);
Bail:
// dispose of everything that was allocated
if (theAppleEvent.dataHandle != nil) (void) AEDisposeDesc(&theAppleEvent);
//if (docDescList.dataHandle != nil) (void) AEDisposeDesc(&docDescList);
if (docDesc.dataHandle != nil) (void) AEDisposeDesc(&docDesc);
if (docAlias != nil) DisposeHandle((Handle) docAlias);
return retCode;
}
// given an application's serial number and a document,
// SendOpenDocumentEventToProcess passes
// the application an OpenDocuments event for the document
OSErr SendOpenDocumentEventToProcess(ProcessSerialNumber *targetPSN, const FSSpec * documentFSSpecPtr)
{
return SendFSSEventToProcess (targetPSN, kCoreEventClass, kAEOpenDocuments, documentFSSpecPtr);
}
static Boolean HasCatSearch (short vRefNum)
{
IOParam pb;
GetVolParmsInfoBuffer buf;
pb.ioVRefNum = vRefNum;
pb.ioBuffer = (Ptr)&buf;
pb.ioReqCount = 6;
pb.ioNamePtr = nil;
if (PBHGetVolParmsSync ((HParmBlkPtr)&pb) == noErr) {
if (pb.ioActCount >= 6 && (buf.vMAttrib & (1L<<bHasCatSearch)) != 0) return true;
}
return false;
}
static Boolean IsRemoteVolume (short vRefNum)
{
IOParam pb;
GetVolParmsInfoBuffer buf;
pb.ioVRefNum = vRefNum;
pb.ioBuffer = (Ptr)&buf;
pb.ioReqCount = 14;
pb.ioNamePtr = nil;
if (PBHGetVolParmsSync ((HParmBlkPtr)&pb) == noErr) {
if (pb.ioActCount >= 14 && buf.vMLocalHand != 0) return true;
}
return false;
}
static OSErr checkThisVolume (short currVRefNum, OSType creator, FSSpecPtr applicationFSSpecPtr, Boolean *foundRef)
{
OSErr retCode;
Boolean foundFlag = false;
// find the path refNum for the desktop database for
// the volume we're interested in
DTPBRec desktopParams;
desktopParams.ioVRefNum = currVRefNum;
desktopParams.ioNamePtr = nil;
retCode = PBDTGetPath(&desktopParams);
if (retCode == noErr) {
if (desktopParams.ioDTRefNum == 0) {
// oops?!
retCode = -1; // !TT new 30 Jan 99
} else {
// iterate over all possible creators on one volume
short idx = 0;
do {
// use the GetAPPL call to find the preferred application
// for opening any document with this one's creator
desktopParams.ioIndex = idx++; // this is the way the Finder in OS 7.6.1 does it: starts with idx 0, then comes 1, 2, ...
desktopParams.ioFileCreator = creator;
desktopParams.ioNamePtr = applicationFSSpecPtr->name;
retCode = PBDTGetAPPLSync(&desktopParams);
if (retCode == noErr) {
// okay, found it; fill in the application file spec
// and set the flag indicating we're done
applicationFSSpecPtr->parID = desktopParams.ioAPPLParID;
applicationFSSpecPtr->vRefNum = currVRefNum;
// However, we have to make sure that the app
// really still exists and that it is a APPL in deed.
// If not, we have to continue to search
CInfoPBRec ci;
HFileInfo &fi = (HFileInfo&)ci;
fi.ioNamePtr = applicationFSSpecPtr->name;
fi.ioVRefNum = currVRefNum;
fi.ioDirID = applicationFSSpecPtr->parID;
fi.ioFDirIndex = 0;
if (PBGetCatInfoSync (&ci) == noErr) {
if (/* do not check the creation date, because the Finder doesn't do it either: fi.ioFlCrDat == desktopParams.ioTagInfo && */
fi.ioFlFndrInfo.fdCreator == desktopParams.ioFileCreator &&
fi.ioFlFndrInfo.fdType == 'APPL' || fi.ioFlFndrInfo.fdType == 'APPC' || fi.ioFlFndrInfo.fdType == 'APPD' || fi.ioFlFndrInfo.fdType == 'appe' // +++ add more types or use a better detection?
) {
foundFlag = true;
}
}
}
} while (!foundFlag && retCode == noErr);
}
}
*foundRef = foundFlag;
return retCode;
}
// FindApplicationByCreator uses the Desktop Database to
// locate the creator application for the given document
//
// this routine will first check the desktop database of the disk
// containing the document, then the desktop database of all local
// disks, then the desktop databases of all server volumes
// (so up to three passes will be made)
// exception (13.2.99): when the file is located on a remote vol,
// the boot vol is searched first
// now returns fnfErr if app is not found
// Attention: It does not support the "fopn" Finder interception AE that has been introduced
// in Mac OS 8!
OSErr FindApplicationByCreator (OSType creator, short firstVol, FSSpec *applicationFSSpecRef)
{
short volumeIndex;
OSErr err;
Boolean found = false;
short vRefNum, skipThisVol = 0;
if (IsRemoteVolume (firstVol)) {
// first, check the boot vol
GetSysVolume (&vRefNum);
checkThisVolume (vRefNum, creator, applicationFSSpecRef, &found);
if (found) return noErr;
skipThisVol = vRefNum;
}
// check the vol the doc is on
checkThisVolume (firstVol, creator, applicationFSSpecRef, &found);
if (found) return noErr;
for (int remotePass = 0; remotePass <= 3; ++remotePass) {
volumeIndex = 0;
do {
HParamBlockRec pb;
HVolumeParam &vp = (HVolumeParam&)pb;
vp.ioNamePtr = nil;
vp.ioVRefNum = 0;
vp.ioVolIndex = ++volumeIndex;
err = PBHGetVInfoSync (&pb);
if (err != nsvErr) {
if (err != noErr) return err;
if (vp.ioVRefNum != firstVol && vp.ioVRefNum != skipThisVol) {
// prio: 0 & 1 for local, 2 & 3 for remote; 0 & 2 with CatSearch, 1 & 3 without CatSearch
int volumePrio = IsRemoteVolume (vp.ioVRefNum) * 2 + (HasCatSearch (vp.ioVRefNum)?0:1);
if (remotePass == volumePrio) {
checkThisVolume (vp.ioVRefNum, creator, applicationFSSpecRef, &found);
if (found) {
return noErr;
}
}
}
}
} while (err != nsvErr);
}
if (err == nsvErr) err = fnfErr;
return err;
}
OSErr FindApplicationFromDocument (const FSSpec * documentFSSpecPtr, FSSpec *applicationFSSpecRef)
{
OSErr err;
OSType creator;
// verify the document file exists and get its creator type
{
FInfo documentFInfo;
err = FSpGetFInfo(documentFSSpecPtr, &documentFInfo);
if (err != noErr) return err;
creator = documentFInfo.fdCreator;
}
return FindApplicationByCreator (creator, documentFSSpecPtr->vRefNum, applicationFSSpecRef);
}
OSErr OpenWithFinder (const FSSpec *spec)
{
ProcessSerialNumber finderPSN;
FSSpec finderSpec;
OSErr err = FindRunningAppBySignature ('FNDR', 'MACS', &finderPSN, &finderSpec);
if (!err) {
err = SendFSSEventToProcess (&finderPSN, kCoreEventClass, kAEOpenDocuments, spec);
}
return err;
}
OSErr FindRunningAppBySignature (OSType fileType, OSType creator, ProcessSerialNumber *psn, FSSpec *fileSpec)
// from: "SignatureToApp.c", by Jens Alfke, DTS, Apple Computer 1991
{
OSErr err;
ProcessInfoRec info;
psn->highLongOfPSN = 0;
psn->lowLongOfPSN = kNoProcess;
do{
err = GetNextProcess(psn);
if (!err) {
info.processInfoLength = sizeof (info);
info.processName = NULL;
info.processAppSpec = fileSpec;
err = GetProcessInformation (psn, &info);
}
} while (!err && info.processSignature != creator && info.processType != fileType);
if (!err) *psn = info.processNumber;
return err;
}
static long CountItems (AEDesc *d)
{
long items = 1;
if(d->descriptorType == typeNull) {
items = 0;
} else if((d->descriptorType == typeAEList) || (d->descriptorType == typeAERecord)) {
AECountItems(d, &items);
}
return items;
}
static void ae_dispose (AEDesc &d)
{
if (d.dataHandle) AEDisposeDesc (&d);
}
OSErr FindOpenCDEVInFinder (Boolean shouldUseAEs, OSType creator, FSSpec *itsSpec)
// algorithm: either uses AppleEvents to get list of all windows, coercing the results to FSSpecs
// The FSSpecs can then be used for both getting the creator code and for closing the window
// returns: 0 if not open in Finder, 1 if open, neg. value if error occured
{
long theTimeout = 5*60; // wait no more than 5 seconds for Finder to respond
if (!shouldUseAEs) {
return FindOpenFileByTypeAndCreator ('cdev', creator, itsSpec);
}
Boolean found = false;
OSErr err;
AEDesc dataDescriptor = {typeNull,0};
AppleEvent reply = {typeNull,0};
AEDesc allCreators = {typeNull,0};
AEDesc targetAddrDesc = {typeNull,0};
AppleEvent ae = {typeNull,0};
AEDesc allWinsSpecifier = {typeNull,0}, keyData = {typeNull,0};
AEDesc keyData2 = {typeNull,0};
AEDesc directObjectSpecifier = {typeNull,0}, nullDesc = {typeNull,0};
ProcessSerialNumber finderPSN, frontPSN;
FSSpec finderSpec;
err = FindRunningAppBySignature ('FNDR', 'MACS', &finderPSN, &finderSpec);
if (err) goto Bail;
GetFrontProcess (&frontPSN);
Boolean finderIsFrontProcess;
SameProcess (&frontPSN, &finderPSN, &finderIsFrontProcess);
if (finderIsFrontProcess) {
// oops, we will not be successful sending the AE (a timeout would occur).
// So fall back to the other method.
err = FindOpenFileByTypeAndCreator ('cdev', creator, itsSpec);
return err; // no cleanup necessary here yet
}
err = AECreateDesc (typeProcessSerialNumber, (Ptr)&finderPSN, sizeof(ProcessSerialNumber), &targetAddrDesc);
if (err) goto Bail;
err = AECreateAppleEvent(kAECoreSuite, kAEGetData, &targetAddrDesc, kAutoGenerateReturnID, kAnyTransactionID, &ae);
// want:type(cwin), from:'null'(), form:indx, seld:abso('all ')
OSType all = 'all ';
err = AECreateDesc (typeAbsoluteOrdinal, &all, sizeof(all), &keyData);
if (err) goto Bail;
err = CreateObjSpecifier (cWindow, &nullDesc, formAbsolutePosition, &keyData, true, &allWinsSpecifier);
if (err) goto Bail;
// want:type(prop), from:<allWinsSpecifier>, form:prop, seld:type(cobj)
OSType cobj = cObject;
err = AECreateDesc (typeType, &cobj, sizeof(cobj), &keyData2);
if (err) goto Bail;
err = CreateObjSpecifier (cProperty, &allWinsSpecifier, formPropertyID, &keyData2, true, &directObjectSpecifier);
if (err) goto Bail;
err = AEPutParamDesc (&ae, keyDirectObject, &directObjectSpecifier);
if (err) goto Bail;
AEDisposeDesc (&directObjectSpecifier);
// core,getd,'----':<>, rtyp:type(list)"
OSType list = 'list';
err = AECreateDesc (typeType, &list, sizeof(list), &dataDescriptor);
if (err) goto Bail;
err = AEPutParamDesc (&ae, keyAERequestedType, &dataDescriptor);
if (err) goto Bail;
AEDisposeDesc (&dataDescriptor);
err = AESend (&ae, &reply, kAEWaitReply, kAEHighPriority, theTimeout, nil, nil);
if (err) goto Bail;
ae_dispose (ae);
err = AEGetParamDesc (&reply, keyAEResult, typeWildCard, &allCreators);
if (err) goto Bail;
long n = CountItems (&allCreators);
for (int i = 1; i < n; ++i) {
AEDesc w;
AEKeyword ignoreKey;
if (AEGetNthDesc (&allCreators, i, typeFSS, &ignoreKey, &w) == noErr) {
FSSpec spec;
spec = *(FSSpec*)*w.dataHandle;
AEDisposeDesc (&w);
FInfo fi;
if (FSpGetFInfo (&spec, &fi) == noErr && fi.fdCreator == creator) {
// we found it
*itsSpec = spec;
found = true;
break;
}
}
}
err = found;
Bail:
ae_dispose (keyData);
ae_dispose (keyData2);
ae_dispose (targetAddrDesc);
ae_dispose (dataDescriptor);
ae_dispose (allWinsSpecifier);
ae_dispose (directObjectSpecifier);
ae_dispose (allCreators);
ae_dispose (reply);
ae_dispose (ae);
return err;
}
// EOF

View File

@ -0,0 +1,36 @@
/*
* Functions for launching apps with documents
*
* by Thomas Tempelmann, macdev@tempel.org
*
* some of these routines are not from me (TT), but from some DTS sample code
* here's a link to it: <http://developer.apple.com/dev/techsupport/source/code/Snippets/Processes/LaunchWithDoc2.1/LaunchWithDoc2.c.html>
*/
#pragma once
#include <Processes.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
-> also see "SignatureToApp.c" as a demo (comes from Apple and does some things differently)
*/
OSErr OpenWithFinder (const FSSpec * applicationFSSpecPtr); // uses AppleEvent to open the file
OSErr LaunchAppl (const FSSpec * applicationFSSpecPtr, Boolean inBackground); // starts APPLs only
OSErr OpenSpecifiedDocument(const FSSpec * documentFSSpecPtr, Boolean inBackground); // starts APPLs or opens docs with its APPLs
OSErr LaunchApplicationWithDocument(const FSSpec * applicationFSSpecPtr, const FSSpec * documentFSSpecPtr, Boolean inBackground);
OSErr SendOpenDocumentEventToProcess(ProcessSerialNumber *targetPSN, const FSSpec * documentFSSpecPtr);
OSErr FindApplicationFromDocument(const FSSpec * documentFSSpecPtr, FSSpec *applicationFSSpecRef);
OSErr FindApplicationByCreator (OSType creator, short firstVol, FSSpec *applicationFSSpecRef);
OSErr FindRunningAppBySignature (OSType fileType, OSType creator, ProcessSerialNumber *psn, FSSpec *fileSpec);
OSErr SendFSSEventToProcess (ProcessSerialNumber *targetPSN, OSType aeClass, OSType aeCmd, const FSSpec *documentFSSpecPtr);
OSErr FindOpenCDEVInFinder (Boolean shouldUseAEs, OSType creator, FSSpec *itsSpec);
#ifdef __cplusplus
}
#endif
// EOF

View File

@ -0,0 +1,261 @@
/*
* Library for handling Pascal-Strings
*
* by Thomas Tempelmann, macdev@tempel.org
*
* Originally by Markus Fritze.
* Changes and additions by Thomas Tempelmann:
* - pstrlen neu
* - BlockMoveData statt BlockMove
* - pstrcmp liefert nicht Boolean sondern short, wie bei strcmp.
* - pstrupper neu
* 28.12.95 TT:
* - alle Zugriffe auf s[0] und d[0] word-expandiert, bevor mit ihnen gerechnet wird,
* um zu verhindern, da§ bei der LŠnge 255 ein berlauf nach 0 passiert.
* 08.04.95 TT:
* - pstrcmp() lieferte "C"<"BB", da das LŠngenbyte mit verglichen wurde. Korrigiert.
* - BlockMoveData() durch copyBytes() ersetzt, da vermutlich i.d.R. schneller.
* 09.04.95 TT:
* - Geschw-optimiert: pfindchar, pstrupper, pdelchars
* - pstrextract() neu
* 30.4.96 TT:
* - copyBytes kopierte falsch, wenn source und dest sich Ÿberlagern und dest>source war.
* 18.7.96 TT:
* - strcatc neu
* 14.8.96 TT:
* - sicherheitshalber 'far' accesses eingefŸhrt.
* 23.07.00 TT:
* - disabled the "far" pragmas
* - changed "StringPtr" into "unsigned char*" so that it can be compiled for Windows, too.
*/
#include <ctype.h>
#include <string.h>
#include "PascalLib.h"
#pragma push
#pragma cplusplus on
/*
* We need far data access in this module
* (alternatively we could setup A5 appropriately):
*/
/* !TT July 23, 2000 - removed this
#ifndef __powerc
#pragma far_data on
#pragma far_strings on
#pragma far_vtables on
#endif
*/
static void copyBytes (const unsigned char* s0, unsigned char* d, unsigned short len)
{
const unsigned char* s = s0;
if (d > s) {
// rŸckwŠrts kopieren
if (len) {
d += len;
s += len;
do { *--d = *--s; } while (--len);
}
} else {
if (len) do { *d++ = *s++; } while (--len);
}
}
void pstrcpy (unsigned char* d, const unsigned char* s)
{
copyBytes (s, d, ((unsigned short)s[0])+1);
}
void pstrncpy (unsigned char* d, const unsigned char* s, short n)
// n: dest buffer size including length char
{
if (n) {
if (n > ((unsigned short)s[0])+1) n = ((unsigned short)s[0])+1;
copyBytes (s, d, n);
if (n < ((unsigned short)d[0])+1) d[0] = n-1;
}
}
void pstrcat (unsigned char* d, const unsigned char* s)
{
copyBytes (s + 1, d + ((unsigned short)d[0]) + 1, s[0]);
d[0] += s[0];
}
void pstrcatc (unsigned char* d, const char* s)
{
short n = strlen(s);
copyBytes ((unsigned char*)s, d + ((unsigned short)d[0]) + 1, n);
d[0] += n;
}
void pstrcatchar (unsigned char* d, const unsigned char c)
{
d[++d[0]] = c;
}
short pfindchar (const unsigned char* d, const unsigned char c)
{
short i, dlen = d[0];
for (i = 1; i <= dlen; i++) {
if (d[i] == c) return i;
}
return 0;
}
void pstrextract (unsigned char* d, const unsigned char* s, short offset, short len)
{
short slen;
if (offset < 1 || offset > (slen = s[0])) {
d[0] = 0;
return;
}
if (((offset-1) + len) > slen) {
len = slen - offset + 1;
}
if (len <= 0) {
d[0] = 0;
return;
}
copyBytes (s + offset, d + 1, len);
d[0] = len;
}
void pdelchars (unsigned char* d, short offset, short len)
{
short dlen;
if (offset > (dlen = d[0])) return; // Offset zu gro§
if (len <= 0) return; // LŠnge zu klein
if ((offset + len) > (dlen + 1)) { // LŠnge zu gro§?
d[0] = offset; // String zurechtstutzen
return;
}
copyBytes (d + offset + len, d + offset, dlen - len - offset + 1);
d[0] -= len;
}
void pstrins (unsigned char* d, const unsigned char* s, short offset)
{
short slen, dlen;
if ((slen = s[0]) == 0) return; // einzufŸgender String = 0 Bytes => raus
if (offset > (dlen = d[0])) { // ggf. an den String anhŠngen
offset = dlen + 1;
}
copyBytes (d + offset, d + offset + slen, dlen + 1 - offset); // String nach hinten
copyBytes (s + 1, d + offset, slen); // String einfŸgen
d[0] += slen; // und die LŠnge updaten
}
short pstrcmp (const unsigned char* s10, const unsigned char* s20)
{
const unsigned char* s1 = s10;
const unsigned char* s2 = s20;
unsigned char l1 = *s1++, l2 = *s2++;
unsigned char len = (l1 < l2)? l1:l2;
if (len) do {
if (*s1++ != *s2++) {
return (s1[-1] < s2[-1])? -1: +1;
}
} while (--len);
if (l1 == l2) {
return 0;
} else {
return (l1 < l2)? -1: +1;
}
}
short pstrlen (const unsigned char* s1)
{
return s1[0];
}
void pstrupper (unsigned char* d)
{
short i, dlen = d[0];
for (i = 1; i <= dlen; i++) {
d[i] = toupper (d[i]);
}
}
typedef unsigned char byte;
/*
short pfindstr (const unsigned char* target, const unsigned char* search)
{
unsigned char* s = search;
unsigned char* d = target;
short slen = s[0];
if (slen) {
short i;
short iend = d[0] - slen + 1;
for (i = 1; i <= iend; i++) {
if (d[i] == s[1]) {
short len = slen - 1;
if (len) {
unsigned char* s1 = &s[2], d1 = &d[i+1];
do {
if (*s1++ != *d1++) {
break;
}
} while (--len);
}
if (len == 0) return i;
}
}
}
return 0;
}
*/
short pfindstr (const unsigned char* d, const unsigned char* s0)
{
const unsigned char* s = s0;
short slen = *s++;
if (slen == 0) return 0;
--slen;
{
byte c = *s++;
short i;
short end = d[0] - slen;
for (i = 1; i <= end; i++) {
if (d[i] == c) {
const byte *sp = s, *dp = &d[i+1];
byte len = slen;
do {
if (len-- == 0) return i; // gefunden
} while (*sp++ == *dp++);
}
}
}
return 0;
}
void pstrnins (unsigned char* d, short destSize, const unsigned char* s, short offset)
// TT 25 Sep 97: does no write over end of dest string
// 'destSize': size of dest string including length byte
{
short slen, dlen;
if (offset < 1) return;
if ((slen = s[0]) == 0) return; // einzufŸgender String = 0 Bytes => raus
if (offset > (dlen = d[0])) { // ggf. an den String anhŠngen
offset = dlen + 1;
}
if (offset >= destSize) return;
if (offset + slen > destSize) {
slen = destSize - offset;
dlen = offset - 1;
} else {
if (slen + dlen >= destSize) {
dlen = destSize - 1 - slen;
}
copyBytes (d + offset, d + offset + slen, dlen + 1 - offset); // String nach hinten
}
copyBytes (s + 1, d + offset, slen); // String einfŸgen
d[0] = dlen + slen; // und die LŠnge updaten
}
#pragma pop

View File

@ -0,0 +1,27 @@
/*
* Library for handling Pascal-Strings
*
* by Thomas Tempelmann, macdev@tempel.org
*/
#pragma push
#pragma cplusplus on
//#include <MacTypes.h>
void pstrcpy (unsigned char* d, const unsigned char* s);
void pstrcat (unsigned char* d, const unsigned char* s);
void pstrcatc (unsigned char* d, const char* s);
void pstrcatchar (unsigned char* d, unsigned char c);
short pfindchar (const unsigned char* d, const unsigned char c);
void pdelchars (unsigned char* d, short offset, short len);
void pstrins (unsigned char* d, const unsigned char* s, short offset);
short pstrcmp (const unsigned char* s1, const unsigned char* s2);
short pstrlen (const unsigned char* s1);
void pstrncpy (unsigned char* d, const unsigned char* s, short n); // n: dest buffer size including length char
void pstrupper (unsigned char* d);
void pstrextract (unsigned char* d, const unsigned char* s, short offset, short len);
short pfindstr (const unsigned char* d, const unsigned char* s);
void pstrnins (unsigned char* d, short destSize, const unsigned char* s, short offset);
#pragma pop

View File

@ -0,0 +1,43 @@
/*
* TrapAvail.c
* by Thomas Tempelmann, macdev@tempel.org
*/
#include <Traps.h>
#include <OSUtils.h>
#include "TrapAvail.h"
Boolean TrapAvailable (short theTrap);
#define TrapMask 0x0800
static short NumToolboxTraps( void )
{
if (NGetTrapAddress(_InitGraf, ToolTrap) ==
NGetTrapAddress(0xAA6E, ToolTrap))
return 0x0200;
else
return 0x0400;
}
static TrapType GetTrapType(short theTrap)
{
if ((theTrap & TrapMask) > 0)
return ToolTrap;
else
return OSTrap;
}
Boolean TrapAvailable (short theTrap)
{
TrapType tType;
tType = GetTrapType(theTrap);
if (tType == ToolTrap)
theTrap = theTrap & 0x07FF;
if (theTrap >= NumToolboxTraps())
theTrap = _Unimplemented;
return NGetTrapAddress(theTrap, tType) != NGetTrapAddress(_Unimplemented, ToolTrap);
}
// EOF

View File

@ -0,0 +1,16 @@
/*
* TrapAvailable.c
* by Thomas Tempelmann, macdev@tempel.org
*/
#ifdef __cplusplus
extern "C" {
#endif
Boolean TrapAvailable (short theTrap);
#ifdef __cplusplus
}
#endif
// EOF