home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga MA Magazine 1998 #3
/
amigamamagazinepolishissue1998.iso
/
bazy
/
kingfisher-distribution
/
developer
/
kf-api.c
< prev
next >
Wrap
C/C++ Source or Header
|
1997-04-10
|
26KB
|
950 lines
//#define DEBUG /* Debug mode issues memory allocation/deallocation messages */
#define USEAUTO /* UseAuto mode allows SAS/C autoinit/autoterminate functions */
#define KFAPI_USE_INTUITION /* Intuition EasyRequest used to prompt for mounting volumes */
/*****************************************************************
* KingFisher 2
* Application Programming Interface
* Copyright © 1994,1995 Udo Schuermann
* All rights reserved
*****************************************************************
* $VER: KingFisher_API 2.26 (11.4.97)
*****************************************************************
* This software belongs to Udo Schuermann (author) and may not be
* redistributed or reproduced in any form without express written
* permission from the author:
* Udo Schuermann
* 7022 Hanover Parkway, Apt. C2
* Greenbelt, MD 20770-2049
*
* walrus@wam.umd.edu
*****************************************************************
* By including this file and using the supplied functions, you
* ensure greater compatibility in future versions and reduce the
* chance of error through omitted parameters. PLEASE USE THIS
* API FOR YOUR APPLICATIONS AS MUCH AS POSSIBLE, RATHER THAN THE
* THE MESSAGE PORT INTERFACE DIRECTLY!
*
* INSTRUCTIONS: In your project, include "kf-api.h" (which also
* includes "kf.h" for you) to define what is needed to interface
* with the KingFisher 2 Server. Compile the file "kf-api.c"
* into an object file (kf-api.o) and link it with your other
* objects.
*****************************************************************
* See kf-api.h for documentation on individual functions
*****************************************************************
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dos/dostags.h>
#include <exec/memory.h>
#include <libraries/dos.h>
#include <proto/exec.h>
#include <proto/dos.h>
#ifdef KFAPI_USE_INTUITION
#include <intuition/intuition.h> /* EasyRequest */
#include <proto/intuition.h> /* EasyRequest */
#endif
#include "kf-api.h"
#ifdef DEBUG
#define MALLOC(s) _MALLOC(s)
#define FREE(p) _FREE(p)
#define ALLOCMEM(s,t) _ALLOCMEM(s,t)
#define FREEMEM(p,t) _FREEMEM(p,t)
#define REALLOC(p,s) _REALLOC(p,s)
char Scrap[256];
static long fh = 0;
void *_MALLOC(ULONG size) {
void *p = malloc(size);
if(fh){sprintf(Scrap,"malloc(%d) = %08x\n",size,p);FPuts(fh,Scrap);Flush(fh);}
return p;
}
void _FREE(void *p) {
if(fh){sprintf(Scrap,"free(%08x)\n",p);FPuts(fh,Scrap);Flush(fh);}
free(p);
}
void *_ALLOCMEM(ULONG size, ULONG mask) {
char *p = AllocMem(size,mask);
if(fh){sprintf(Scrap,"AllocMem(%d,%d) = %08x\n",size,mask,p);FPuts(fh,Scrap);Flush(fh);}
return p;
}
void _FREEMEM(void *p, ULONG size) {
if(fh){sprintf(Scrap,"FreeMem(%08x,%d)\n",p,size);FPuts(fh,Scrap);Flush(fh);}
FreeMem(p,size);
}
void *_REALLOC(void *p, ULONG size) {
void *new;
if(fh){sprintf(Scrap,"realloc(%08x,%d) = ",p,size);FPuts(fh,Scrap);Flush(fh);}
new = realloc(p,size);
if(fh){sprintf(Scrap,"%08x\n",new);FPuts(fh,Scrap);Flush(fh);}
return new;
}
#else
#define MALLOC(s) malloc(s)
#define FREE(p) free(p)
#define ALLOCMEM(s,t) AllocMem(s,t)
#define FREEMEM(p,t) FreeMem(p,t)
#define REALLOC(p,s) realloc(p,s)
#endif
/*****************************************************************
* The client may modify the following variables:
*
* KFAPIServerName The complete name of the KFServer binary,
* used to auto-start the KFServer if its port
* cannot be found. KingFisher, for example,
* updates this with the value of the SERVERNAME
* tooltype/parameter.
* KFAPISilentRun Ordinarily the KF-API explicitly writes some
* status information to a stdout console window
* when the server needs to be started. This
* can be suppressed by setting this variable to
* a value of TRUE. KingFisher sets this value
* to TRUE if the NOOUTPUT tooltype/parameter
* is given.
* KFAPIVolumePrompts For this value to function, the DEFINE
* KFAPI_USE_INTUITION must also be activated.
* (see top of this file.) Setting this value
* to FALSE suppresses the API's ability to
* prompt the user to insert unmounted disk
* volumes. This capability is not made part
* of the server to enhance the server's ability
* to effectively multitask. Until the server
* becomes a multi-threaded application, the
* prompting must be done by the client process,
* not the server.
* For technophiles: the kfeFILEOPEN error is
* an indication that the server could not open
* the file whose exact name is then provided in
* the .RESERVED2 field.
* KFAPIApplicationWindow The window to which a requester is to be
* attached if KFAPIVolumePrompts is TRUE and a
* database access requires user-interaction.
* KFAPITimeout Number of seconds for the API to wait for
* the server's message port to appear. This
* defaults to 10 seconds but may be tuned to
* a lower number for harddisk systems to
* prevent a KFServer problem from "hanging"
* the client for as much as 10 seconds before
* giving up.
* KFAPIServerDebug Starts (if needed) the KFServer in debug mode.
*****************************************************************
*/
char KFAPIServerName[128] = "KFServer";
BOOL KFAPISilentRun = FALSE;
BOOL KFAPIVolumePrompts = TRUE;
BOOL KFAPIServerDebug = FALSE;
LONG KFAPITimeout = 10;
struct Window *KFAPIApplicationWindow = NULL;
/*****************************************************************
* The client may read the following variables
*****************************************************************
*/
/* When 'ExitRequested' becomes TRUE, the server has requested
* us to quit as swiftly as possible so it can shutdown. It is
* important to comply without much delay! Do not rely on this
* alone.
* NOTE: changes to the server make it now more accurate to listen
* to a ^C signal and shutdown when that is received. There exists
* no guarantee that the server remains available after a ^C is
* received.
*/
BOOL ExitRequested = FALSE;
int CallServerErr = 0;
int AsyncErr = kfeOK;
char AsyncMsg[512] = "";
/* We keep a list of all messages allocated with Login();
* Either the Logout() or the exit()-chain will free these for us.
* Each message is the sole provider of a pointer to the allocated
* reply port.
* In addition, we keep a list of messages we received that asked
* us to kfcEXIT (shutdown request.) These we will reply to when
* the program exits (via the _STD_KFAPI_Down() function.
* UPDATE for KF2.4: kfcEXIT messages are obsolete
*/
struct Messages {
struct Messages *NextMessage;
struct KFMsg *ThisMessage;
} *MessageList=NULL,*ReplyPending=NULL;
char KFAPIScratchBuffer[256]; /* used mostly internally */
#ifdef __SASC_650
#ifdef USEAUTO
/* This is a SAS/C AutoTermination function.
* By virtue of its name (starts with _STD) it will be called
* after the program exits. We use this to free all memory.
*/
void _STD_KFAPI_Down( void ) {
struct KFMsg *p;
#ifdef DEBUG
if( fh ) { /* the file handle is opened in the _STI_ function below */
FPuts(fh,"Closing down\n");
Flush(fh);
}
#endif
while( ReplyPending ) {
#ifdef DEBUG
if( fh ) {
FPuts(fh,"Freeing pending reply\n");
Flush(fh);
}
#endif
ReplyMsg( (struct Message *)ReplyPending->ThisMessage );
FREE( ReplyPending );
ReplyPending = ReplyPending->NextMessage;
} /* while */
while( MessageList ) {
#ifdef DEBUG
if( fh ) {
FPuts(fh,"Freeing login-related stuff\n");
Flush(fh);
}
#endif
p = MessageList->ThisMessage;
DeletePort( p->AmigaMsg.mn_ReplyPort );
if( p->Buffer != KFAPIScratchBuffer )
FREE( p->Buffer );
FREEMEM( p, sizeof(struct KFMsg) );
FREE( MessageList );
MessageList = MessageList->NextMessage;
} /* while */
#ifdef DEBUG
if( fh != 0 )
Close( fh );
#endif
} /* _STD_KFAPI_Down() */
#ifdef DEBUG
void _STI_KFAPI_Init( void ) {
fh = Open("CON:0/15/640/120/KingFisher API/AUTO/CLOSE/WAIT",MODE_NEWFILE);
if( fh ) {
FPuts(fh,"API Initialized\n");
Flush(fh);
/* yes, we leave the file handle open; the _STD_ function will close it */
}
} /* _STI_KFAPI_Init() */
#endif
#endif
#endif
/* it is not encouraged, but certainly permissible, to call this function with
* a pointer to a properly initialized KFMsg structure. See the kf.h file for
* details on what various server functions expect in parameters.
*/
BOOL CallServer( struct KFMsg *Msg ) {
struct MsgPort *PrimaryPort,*myPort=Msg->AmigaMsg.mn_ReplyPort;
struct KFMsg *reply;
static NoStart = FALSE;
BOOL result=TRUE,done=FALSE;
ULONG sigs;
short retry;
char SystemCmd[sizeof(KFAPIServerName)+24]; /* +24 for "run <nil: >nil: DEBUG " and NUL */
CallServerErr = 0;
AsyncErr = kfeOK;
/* It is possible to change this thing to a more-than-1 retry count
* for times when the system is HORRIBLY slow and waiting for the
* message port takes longer than a few seconds.
*/
for(retry=2;retry;retry--) {
Forbid();
if( PrimaryPort = FindPort( KFPortName ) )
PutMsg( PrimaryPort, (struct Message *)Msg );
Permit();
if( PrimaryPort || (retry == 1))
break; /* message sent; now go wait for a reply */
/* Can't find the server; let's try to start it up */
if( KFAPIServerName[0] == '\0' ) /* if no name, then don't even try */
break;
if( NoStart ) {
ExitRequested = TRUE;
break;
}
if( !KFAPISilentRun )
printf("\nKFAPI: Attempting to start \"%s\"...\n",KFAPIServerName);
/* create the command string, either
* run <nil: >nil: kfserver
* or
* run kfserver
*/
sprintf(SystemCmd,
"run %s%s%s",
(KFAPISilentRun?"<nil: >nil: ":""),
KFAPIServerName,
(KFAPIServerDebug?" DEBUG":""));
if( SystemTags(SystemCmd,
NP_StackSize, 8192, /* 8K stack */
TAG_DONE) == 0 ) {
short xyzzy; /* no, it's not really magic */
/* now wait up to 10 seconds for the server's message port to
* materialize before giving up; check once ever half second
* 10 seconds ought to be enough for the KFServer to startup
* even with a slow (floppy) systems (remember, it needs to
* load its .prefs file, too, and initialize a database...)
*/
for(xyzzy=2*KFAPITimeout;xyzzy;xyzzy--) {
Delay(25L); /* ½ second */
if( PrimaryPort = FindPort( KFPortName ) )
break; /* hooray! */
}
} else
break; /* failure of command; don't even retry ... */
} /* for */
if( PrimaryPort ) {
NoStart = TRUE;
while( !done ) {
sigs = Wait( (1L << myPort->mp_SigBit) | SIGBREAKF_CTRL_C );
if( sigs & (1L << myPort->mp_SigBit) )
while( reply = (struct KFMsg *)GetMsg( myPort ) ) {
if( reply == Msg ) {
#ifdef KFAPI_USE_INTUITION
if( (Msg->Error == kfeFILEOPEN) && (Msg->RESERVED != NULL) ) {
char tmp[312];
ULONG easyIDCMP;
struct EasyStruct APIRequester = {
sizeof(struct EasyStruct),
0,
"KFServer Request",
NULL,
"Retry|Cancel",
};
sprintf(tmp,
"Please insert volume for database file\n%s\nin any drive!",
Msg->RESERVED2);
APIRequester.es_TextFormat = tmp;
easyIDCMP = IDCMP_DISKINSERTED;
if( EasyRequest(KFAPIApplicationWindow,&APIRequester,&easyIDCMP) ) {
Forbid();
if( PrimaryPort = FindPort( KFPortName ) )
PutMsg( PrimaryPort, (struct Message *)Msg );
Permit();
if( PrimaryPort == NULL ) {
done = TRUE; /* error: must exit loop */
CallServerErr = kfeSERVERGONE;
}
} else {
done = TRUE; /* cancel */
result = FALSE;
}
} else
done = TRUE;
#else
done = TRUE;
#endif
} else {
if( reply->Command == kfcEXIT ) { /* kfcEXIT is obsolete */
struct Messages *NewMessage = MALLOC( sizeof(struct Messages) );
if( NewMessage ) {
NewMessage->ThisMessage = reply;
NewMessage->NextMessage = ReplyPending;
ReplyPending = NewMessage;
} else
ReplyMsg( (struct Message *)reply ); /* can't store; logout at once! */
ExitRequested = TRUE;
} else {
strncpy(AsyncMsg,Msg->Buffer,sizeof(AsyncMsg));
AsyncErr = Msg->Error;
ReplyMsg( (struct Message *)reply );
}
}
} /* while */
if( sigs & SIGBREAKF_CTRL_C ) {
SetSignal(0L,SIGBREAKF_CTRL_C);
ExitRequested = TRUE;
done = TRUE;
}
} /* while */
} else {
ExitRequested = TRUE;
CallServerErr = kfeNOSERVER;
result = FALSE;
}
return result;
}
/* Creates a new message node and attaches a new message to it, initializes it,
* with a reply port, and returns us this message. If the function returns
* NULL, then it failed one way or another (out of memory)
*/
struct KFMsg *KFLogin( char *Identifier ) {
struct Messages *NewMessage = MALLOC( sizeof(struct Messages) );
char *NewBuffer;
if( NewMessage ) {
if( NewMessage->ThisMessage = ALLOCMEM( sizeof(struct KFMsg), MEMF_PUBLIC|MEMF_CLEAR ) ) {
NewMessage->ThisMessage->AmigaMsg.mn_Node.ln_Type = NT_MESSAGE;
NewMessage->ThisMessage->AmigaMsg.mn_Length = sizeof(struct KFMsg);
if( NewMessage->ThisMessage->AmigaMsg.mn_ReplyPort = CreateMsgPort() ) {
NewMessage->ThisMessage->Command = kfcHELLO;
NewMessage->ThisMessage->Buffer = KFAPIScratchBuffer;
NewMessage->ThisMessage->BufferSize = sizeof(KFAPIScratchBuffer);
NewMessage->ThisMessage->BParam = (ULONG)FindTask(NULL);
NewMessage->ThisMessage->RESERVED2 = AsyncMsg; /* a 256+ byte buffer; yes, it's getting ugly! */
if( Identifier )
strncpy(KFAPIScratchBuffer,Identifier,sizeof(KFAPIScratchBuffer));
else
strcpy(KFAPIScratchBuffer,"(Unnamed Client)");
KFAPIScratchBuffer[sizeof(KFAPIScratchBuffer)-1] = '\0'; /* force termination */
if( CallServer( NewMessage->ThisMessage ) ) {
if( NewMessage->ThisMessage->VERSIONID >= KFAPIVER ) {
if( NewMessage->ThisMessage->Error != kfeOK )
strncpy(KFAPIScratchBuffer,NewMessage->ThisMessage->Buffer,sizeof(KFAPIScratchBuffer));
if( NewBuffer = MALLOC( NewMessage->ThisMessage->BParam ) ) {
NewMessage->ThisMessage->Buffer = NewBuffer;
NewMessage->ThisMessage->BufferSize = NewMessage->ThisMessage->BParam;
NewMessage->NextMessage = MessageList;
MessageList = NewMessage;
return NewMessage->ThisMessage;
} else
strcpy(KFAPIScratchBuffer,"No memory for buffer");
} else
sprintf(KFAPIScratchBuffer,
"Client-Server version mismatch! (S=%ld < C=%ld)",
NewMessage->ThisMessage->VERSIONID,KFAPIVER);
} else
strcpy(KFAPIScratchBuffer,"Unable to attach to the KFServer!\n"
"Does KFServer fail initialization?\n"
"(To test, try 'KFServer' from the CLI)");
} else
strcpy(KFAPIScratchBuffer,"Cannot create message port");
FREEMEM( NewMessage->ThisMessage, sizeof(struct KFMsg) );
} else
strcpy(KFAPIScratchBuffer,"No memory for login");
FREE( NewMessage );
} else
strcpy(KFAPIScratchBuffer,"No memory for message");
return NULL;
} /* KFLogin() */
/* Find the indicated message in our list of messages and remove it. Clears
* the message, frees the message port and all dynamic memory associated
* with it, and then logs us out of the server. The user must have cleared
* the Buffer pointer (it is assumed to be free) or else that memory will be
* lost. If the function returns FALSE, then the message could not be
* deallocated and its memory will be lost (along with the message port.)
*/
BOOL KFLogout( struct KFMsg *Msg ) {
struct Messages *CurMsg=MessageList,*PrevMsg=NULL;
if( Msg ) {
Msg->Command = kfcBYE;
Msg->Buffer = KFAPIScratchBuffer;
Msg->BufferSize = sizeof(KFAPIScratchBuffer);
CallServer( Msg );
while( CurMsg ) {
if( CurMsg->ThisMessage == Msg )
break;
PrevMsg = CurMsg;
CurMsg = CurMsg->NextMessage;
}
if( CurMsg ) {
if( PrevMsg )
PrevMsg->NextMessage = CurMsg->NextMessage;
else
MessageList = CurMsg->NextMessage;
DeletePort( Msg->AmigaMsg.mn_ReplyPort );
if( Msg->Buffer != KFAPIScratchBuffer )
FREE( Msg->Buffer );
FREEMEM( Msg, sizeof(struct KFMsg) );
FREE( CurMsg );
return TRUE;
}
}
return FALSE;
} /* KFLogout() */
BOOL KFStatus( struct KFMsg *Msg ) {
if( Msg ) {
Msg->Command = kfcSTATUS;
if( CallServer( Msg ) )
if( (Msg->Error == kfeOK) || (Msg->Error == kfeTRUNC) )
return TRUE;
}
return FALSE;
} /* KFStatus() */
ULONG KFMaxClients( struct KFMsg *Msg ) {
ULONG value = 0;
if( Msg ) {
Msg->Command = kfcMAXCLIENTS;
if( CallServer( Msg ) )
if( Msg->Error == kfeOK )
value = Msg->BParam;
} else {
/* NULL handle given; create a temporary and sub-functional handle that's just
* enough to get the job done (i.e. we don't even assign a text buffer!)
*/
struct KFMsg *TmpHandle = ALLOCMEM( sizeof(struct KFMsg), MEMF_PUBLIC|MEMF_CLEAR );
if( TmpHandle ) {
TmpHandle->AmigaMsg.mn_Node.ln_Type = NT_MESSAGE;
TmpHandle->AmigaMsg.mn_Length = sizeof(struct KFMsg);
if( TmpHandle->AmigaMsg.mn_ReplyPort = CreateMsgPort() ) {
value = KFMaxClients( TmpHandle ); /* To iterate is human, to recurse divine! */
DeletePort( TmpHandle->AmigaMsg.mn_ReplyPort );
}
FREEMEM( TmpHandle, sizeof(struct KFMsg) );
}
}
return value;
} /* KFMaxClients() */
ULONG KFCurFish( struct KFMsg *Msg ) {
if( Msg ) {
Msg->Command = kfcGETPOS;
if( CallServer( Msg ) )
if( Msg->Error == kfeOK )
return Msg->BParam;
}
return 0;
} /* KFCurFish() */
UWORD KFCurFlags( struct KFMsg *Msg ) {
if( Msg ) {
Msg->Command = kfcGETPOS;
if( CallServer( Msg ) )
if( Msg->Error == kfeOK )
return Msg->FParam;
}
return 0;
} /* KFCurFlags() */
ULONG KFCurDisk( struct KFMsg *Msg ) {
if( Msg ) {
Msg->Command = kfcGETDISKPOS;
if( CallServer( Msg ) )
if( Msg->Error == kfeOK )
return Msg->BParam;
}
return 0;
} /* KFCurDisk() */
char *KFCurDatabaseDescription( struct KFMsg *Msg ) {
if( Msg ) {
Msg->Command = kfcGETDBASEDESCRIPT;
if( CallServer( Msg ) )
if( Msg->Error == kfeOK )
return Msg->Buffer;
}
return NULL;
} /* KFCurDatabaseDescription() */
char *KFCurDatabaseName( struct KFMsg *Msg ) {
if( Msg ) {
Msg->Command = kfcGETDBASENAME;
if( CallServer( Msg ) )
if( Msg->Error == kfeOK )
return Msg->Buffer;
}
return NULL;
} /* KFCurDatabaseName */
ULONG KFCurDatabaseSize( struct KFMsg *Msg ) {
if( Msg ) {
Msg->Command = kfcGETDBASESIZE;
if( CallServer( Msg ) )
if( Msg->Error == kfeOK )
return Msg->BParam;
}
return 0;
} /* KFCurDatabaseSize() */
char *KFQuickIndex( struct KFMsg *Msg ) {
if( Msg ) {
Msg->Command = kfcGETQINDEX;
if( CallServer( Msg ) )
if( Msg->Error == kfeOK )
return (char *)Msg->BParam;
}
return NULL;
} /* KFQuickIndex() */
BOOL KFSelectFish( struct KFMsg *Msg, ULONG FishNumber ) {
if( Msg ) {
Msg->Command = kfcSETPOS;
Msg->BParam = FishNumber;
if( CallServer( Msg ) )
return TRUE;
}
return FALSE;
} /* KFSelectFish */
ULONG KFNextVersion( struct KFMsg *Msg ) {
if( Msg ) {
Msg->Command = kfcGETNEXTLINK;
if( CallServer( Msg ) )
return Msg->BParam;
}
return KF_NIL_FISH;
}
ULONG KFPrevVersion( struct KFMsg *Msg ) {
if( Msg ) {
Msg->Command = kfcGETPREVLINK;
if( CallServer( Msg ) )
return Msg->BParam;
}
return KF_NIL_FISH;
}
ULONG KFSetNextVersion( struct KFMsg *Msg, ULONG LinkValue ) {
if( Msg ) {
Msg->Command = kfcSETNEXTLINK;
Msg->BParam = LinkValue;
if( CallServer( Msg ) )
return Msg->BParam;
}
return -1L;
}
ULONG KFSetPrevVersion( struct KFMsg *Msg, ULONG LinkValue ) {
if( Msg ) {
Msg->Command = kfcSETPREVLINK;
Msg->BParam = LinkValue;
if( CallServer( Msg ) )
return Msg->BParam;
}
return -1L;
}
BOOL KFListDatabases( struct KFMsg *Msg ) {
if( Msg ) {
Msg->Command = kfcLISTDBASES;
if( CallServer( Msg ) )
if( (Msg->Error == kfeOK) || (Msg->Error == kfeTRUNC) )
return TRUE;
}
return FALSE;
} /* KFListDatabases() */
BOOL KFSelectDatabase( struct KFMsg *Msg, char *Filename ) {
if( Msg ) {
Msg->Command = kfcSELECTDBASE;
Msg->BParam = (ULONG)Filename;
if( CallServer( Msg ) ) {
if( Msg->Error == kfeOK ) {
if( Msg->BParam > Msg->BufferSize ) {
char *NewBuffer = REALLOC( Msg->Buffer, Msg->BParam );
if( NewBuffer ) {
if( Msg->Buffer != KFAPIScratchBuffer )
FREE( Msg->Buffer );
Msg->Buffer = NewBuffer;
Msg->BufferSize = Msg->BParam;
}
}
return TRUE;
}
}
}
return FALSE;
} /* KFSelectDatabase() */
BOOL KFGetFish( struct KFMsg *Msg, ULONG FishNumber ) {
if( Msg ) {
Msg->Command = kfcGETFISH;
Msg->BParam = FishNumber;
if( CallServer( Msg ) )
if( Msg->Error == kfeOK )
return TRUE;
}
return FALSE;
} /* KFGetFish() */
BOOL KFSetFlag( struct KFMsg *Msg, UWORD Mask ) {
if( Msg ) {
Msg->Command = kfcSETFLAG;
Msg->FParam = Mask;
if( CallServer( Msg ) )
if( Msg->Error == kfeOK )
return TRUE;
}
return FALSE;
} /* KFCurFlags() */
BOOL KFClrFlag( struct KFMsg *Msg, UWORD Mask ) {
if( Msg ) {
Msg->Command = kfcCLRFLAG;
Msg->FParam = Mask;
if( CallServer( Msg ) )
if( Msg->Error == kfeOK )
return TRUE;
}
return FALSE;
} /* KFCurFlags() */
BOOL KFFindFlag( struct KFMsg *Msg, BOOL Forward, UWORD MatchMask, UWORD AvoidMask ) {
if( Msg ) {
if( Forward )
Msg->Command = kfcFINDMASKFORWARD;
else
Msg->Command = kfcFINDMASKREVERSE;
Msg->FParam = MatchMask;
Msg->DParam = AvoidMask;
if( CallServer( Msg ) )
if( Msg->Error == kfeOK )
return TRUE;
}
return FALSE;
} /* KFFindFlag() */
ULONG KFFindNextUsedLink( struct KFMsg *Msg, ULONG FishNum ) {
if( Msg ) {
Msg->Command = kfcFINDNEXTUSEDLINK;
Msg->BParam = FishNum;
if( CallServer( Msg ) )
if( Msg->Error == kfeOK )
return Msg->BParam;
}
return 0L;
} /* KFFindNextUsedLink() */
BOOL KFGetDisk( struct KFMsg *Msg, ULONG DiskNumber ) {
if( Msg ) {
Msg->Command = kfcSETDISKPOS;
Msg->BParam = DiskNumber;
if( CallServer( Msg ) )
if( Msg->Error == kfeOK )
return KFGetFish( Msg, KF_CURRENT_FISH );
}
return FALSE;
} /* KFGetDisk() */
BOOL KFNextFish( struct KFMsg *Msg ) {
if( Msg ) {
Msg->Command = kfcNEXTFISH;
if( CallServer( Msg ) )
if( Msg->Error == kfeOK )
return TRUE;
}
return FALSE;
} /* KFNextFish() */
BOOL KFPrevFish( struct KFMsg *Msg ) {
if( Msg ) {
Msg->Command = kfcPREVFISH;
if( CallServer( Msg ) )
if( Msg->Error == kfeOK )
return TRUE;
}
return FALSE;
} /* KFPrevFish() */
BOOL KFAddFish( struct KFMsg *Msg, UWORD Disk, UWORD Flags, LONG PrevVersion, LONG NextVersion ) {
if( Msg ) {
Msg->Command = kfcADDFISH;
Msg->BParam = Disk;
Msg->FParam = Flags;
if( CallServer( Msg ) )
if( Msg->Error == kfeOK ) {
BOOL ok = TRUE;
if( PrevVersion > 0 ) {
Msg->Command = kfcSETPREVLINK;
Msg->BParam = PrevVersion;
if( !CallServer( Msg ) )
ok = FALSE;
else
if( Msg->Error != kfeOK )
ok = FALSE;
}
if( NextVersion > 0 ) {
Msg->Command = kfcSETNEXTLINK;
Msg->BParam = NextVersion;
if( !CallServer( Msg ) )
ok = FALSE;
else
if( Msg->Error != kfeOK )
ok = FALSE;
}
if( ok )
return TRUE;
}
}
return FALSE;
}/* KFAddFish() */
BOOL KFEndAdding( struct KFMsg *Msg ) {
if( Msg ) {
Msg->Command = kfcENDADDING;
if( CallServer( Msg ) )
if( Msg->Error == kfeOK )
return TRUE;
}
return FALSE;
} /* KFEndAdding() */
LONG KFTruncate( struct KFMsg *Msg ) {
if( Msg ) {
Msg->Command = kfcTRUNCATE;
if( CallServer( Msg ) )
if( Msg->Error == kfeOK )
return (LONG)Msg->BParam;
}
return -1;
} /* KFTruncate() */
BOOL KFParseFile( struct KFMsg *Msg, char *Filename ) {
if( Msg ) {
Msg->Command = kfcPARSEFILE;
Msg->BParam = (ULONG)Filename;
if( CallServer( Msg ) )
if( Msg->Error == kfeOK )
return TRUE;
}
return FALSE;
} /* KFParseFile() */
BOOL KFEndParsing( struct KFMsg *Msg ) {
if( Msg ) {
Msg->Command = kfcSTOPPARSE;
if( CallServer( Msg ) )
if( Msg->Error == kfeOK )
return TRUE;
}
return FALSE;
} /* KFEndParsing() */
/* This function performs one or more calls to the server,
* because the server will reindex only a portion of the
* database during any one call so as not to ignore requests
* by other clients for services.
*/
BOOL KFReindex( struct KFMsg *Msg ) {
if( Msg ) {
for(;;) {
Msg->Command = kfcREINDEX;
Msg->BParam = kfrREBUILDMAIN | kfrREBUILDQUICK;
if( CallServer( Msg ) )
if( Msg->Error == kfeOK )
continue;
break;
} /* for */
if( Msg->Error == kfeNOMORE )
return TRUE;
}
return FALSE;
} /* KFReindex() */
BOOL KFLockDB( struct KFMsg *Msg ) {
if( Msg ) {
Msg->Command = kfcLOCKDB;
if( CallServer( Msg ) )
if( Msg->Error == kfeOK )
return TRUE;
}
return FALSE;
} /* KFLockDB() */
BOOL KFUnlockDB( struct KFMsg *Msg ) {
if( Msg ) {
Msg->Command = kfcUNLOCKDB;
if( CallServer( Msg ) )
if( Msg->Error == kfeOK )
return TRUE;
}
return FALSE;
} /* KFUnlockDB() */
//End of File