home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga MA Magazine 1998 #3
/
amigamamagazinepolishissue1998.iso
/
bazy
/
db3.4
/
dbrexx.c
< prev
next >
Wrap
C/C++ Source or Header
|
1997-01-28
|
16KB
|
655 lines
/* Rexx support for db */
/**********************************************************************/
/* Includes */
/**********************************************************************/
#include <proto/rexxsyslib.h>
#include <proto/utility.h> /* Stricmp() */
#include <proto/exec.h>
#include <string.h>
#include <stdlib.h> /* atoi() */
/* Included for compatibility */
#include <libraries/gadtools.h>
#include <intuition/intuition.h> /* struct EasyStruct */
#include <proto/gadtools.h>
#include <proto/intuition.h>
#include <proto/dos.h> /* Unlock() */
#include "dbGUI.h"
#include "db.h"
#include "dbRexx.h"
// #include "dbParser.h"
/* Included for compatibility */
#include "dbtexts.h"
/**********************************************************************/
/* Defines */
/**********************************************************************/
#define REXXPORTNAMELENGTH 50
/**********************************************************************/
/* Globals */
/**********************************************************************/
/* ARexx specifics */
struct MsgPort *MyRexxPort = NULL;
char MyRexxPortName[REXXPORTNAMELENGTH] ="\0";
int OutstandingRexxCommands = 0;
/* End of Rexx specifics */
/**********************************************************************/
/* Prototypes */
/**********************************************************************/
extern int DB_SAVE( void ); /* I don't want to include dbGUI.h for this one liner */
typedef struct {
char *arg;
struct RexxMsg *rxmessage;
int RC;
char *Result;
char buf[10]; /* Sometimes Result points here */
} RXInfo;
/**********************************************************************/
/* Functions */
/**********************************************************************/
char *NextWord(const char *s)
{
/* Just steps forward all non space characters + one space character */
if (!s) return NULL;
while (*s && (*s++ != ' '));
return s;
}
int GetFldIndex(struct Pro *Pr, char *s)
{
/* Returns the fieldindex of the matching field or -1 if not found */
int i=0;
struct FldInfo *f = Pr->FirstFldInfo;
for (; f; f=f->Next, i++) if (!Stricmp(f->Name, s)) return i;
return -1;
}
Field RXGetFld(struct Pro *Pr, char *fieldname)
{
/* Returning NULL indicates an error */
int i;
if ((i = GetFldIndex(Pr, fieldname)) == -1) return NULL;
return GetFld(*Pr->Recpp, i);
}
LONG EasyRexxRequest(struct Window *w, struct EasyStruct *es, ULONG *idcmp,
char *string)
{
BOOL blocked;
/* Displays an EasyRequest where the strings are locale string-indexes */
LONG ret_val;
struct EasyStruct nes;
nes.es_StructSize = sizeof(struct EasyStruct);
nes.es_Flags = 0;
nes.es_Title = GetAppStr((LONG)es->es_Title);
nes.es_TextFormat = string;
nes.es_GadgetFormat = GetAppStr((LONG)es->es_GadgetFormat);
blocked = IsInputBlocked();
if (w) BlockInput(w, TRUE);
ret_val = EasyRequestArgs(w, &nes, idcmp, NULL);
if (w && !blocked) FreeInput(w);
return ret_val;
}
struct MsgPort *SetupRexxPort(char *basename)
{
struct MsgPort *port;
int num=1;
Forbid();
do { /* Make a unique portname db.<num> */
sprintf(MyRexxPortName, "%s.%d", basename, num++);
} while (FindPort(MyRexxPortName));
port = CreatePort(MyRexxPortName, 0L);
Permit();
return port;
}
void ReplyRexxCommand(struct RexxMsg *rxmessage, long rc, char *result)
{
long rc2 = 0;
if (!rc && (rxmessage->rm_Action & 1L<<RXFB_RESULT))
if (result) rc2 = (long)CreateArgstring(result, strlen(result));
rxmessage->rm_Result1 = rc;
rxmessage->rm_Result2 = rc2;
ReplyMsg((struct Message *)rxmessage);
}
/**********************************************************************/
/* ARexx command handlers */
/**********************************************************************/
static void Rx_Add(RXInfo *ri)
{
DB_ADD();
}
static void Rx_Kill(RXInfo *ri)
{
DB_KILL();
}
static void Rx_FirstRecord(RXInfo *ri)
{
UpdateRecord(CurrentPro);
if (CurrentPro->Mode == MODE_NORMAL) UpdateRecord(CurrentPro);
JumpList(CurrentPro, -CurrentPro->RecNum);
if (CurrentPro->Mode == MODE_NORMAL) {
UpdateWindow(CurrentPro);
UpdateDragBar(CurrentPro);
}
if (ReactivateGad) ActivateGadget(LastGad, CurrentPro->CurrentLayout->Window, NULL);
stci_d(ri->buf, CurrentPro->RecNum+1);
ri->Result = ri->buf;
}
static void Rx_NextRecord(RXInfo *ri)
{
if (CurrentPro->RecNum < (CurrentPro->RecSum-1)) {
if (CurrentPro->Mode == MODE_NORMAL) UpdateRecord(CurrentPro);
JumpList(CurrentPro, 1);
if (CurrentPro->Mode == MODE_NORMAL) {
UpdateWindow(CurrentPro);
UpdateDragBar(CurrentPro);
}
if (ReactivateGad) ActivateGadget(LastGad, CurrentPro->CurrentLayout->Window, NULL);
}
else ri->RC = RC_WARN;
stci_d(ri->buf, CurrentPro->RecNum+1);
ri->Result = ri->buf;
}
static void Rx_CurrentRecord(RXInfo *ri)
{
int recnum;
if (*ri->arg) {
recnum = atoi(ri->arg)-1;
if (recnum >= 0 && recnum < CurrentPro->RecSum) {
if (CurrentPro->Mode == MODE_NORMAL) UpdateRecord(CurrentPro);
JumpList(CurrentPro, -CurrentPro->RecNum+recnum);
if (CurrentPro->Mode == MODE_NORMAL) {
UpdateWindow(CurrentPro);
UpdateDragBar(CurrentPro);
}
if (ReactivateGad) ActivateGadget(LastGad, CurrentPro->CurrentLayout->Window, NULL);
}
else ri->RC = RC_WARN;
}
stci_d(ri->buf, CurrentPro->RecNum+1);
ri->Result = ri->buf;
}
static void Rx_RecordSum(RXInfo *ri)
{
stci_d(ri->buf, CurrentPro->RecSum);
ri->Result = ri->buf;
}
static void Rx_FindFirst(RXInfo *ri)
{
if (!FindRecord(CurrentPro,0,1)) ri->RC = RC_WARN;
stci_d(ri->buf, CurrentPro->RecNum+1);
ri->Result = ri->buf;
}
static void Rx_FindNext(RXInfo *ri)
{
if (!FindRecord(CurrentPro,CurrentPro->RecNum+1,1)) ri->RC = RC_WARN;
stci_d(ri->buf, CurrentPro->RecNum+1);
ri->Result = ri->buf;
}
static void Rx_Cut(RXInfo *ri)
{
DB_CUT();
}
static void Rx_Copy(RXInfo *ri)
{
DB_COPY();
}
static void Rx_Paste(RXInfo *ri)
{
DB_PASTE();
}
static void Rx_Merge(RXInfo *ri)
{
UpdateRecord(CurrentPro);
PasteFromClipboard(CurrentPro, *CurrentPro->Recpp);
CurrentPro->Modified |= PROMODIFIED;
UpdateGadgets(CurrentPro);
}
static void Rx_FirstField(RXInfo *ri)
{
struct FldInfo *fi;
if (fi = GetFldInfo(CurrentPro, 0)) {
CurrentPro->CurrentFldOffset = 0;
ri->Result = fi->Name;
}
else ri->RC = RC_WARN; /* No fields at all */
}
static void Rx_NextField(RXInfo *ri)
{
struct FldInfo *fi;
if (fi = GetFldInfo(CurrentPro, CurrentPro->CurrentFldOffset+1)) {
CurrentPro->CurrentFldOffset++;
ri->Result = fi->Name;
}
else ri->RC = RC_WARN;
}
static void Rx_CurrentField(RXInfo *ri)
{
int offset;
struct FldInfo *fi;
if (*ri->arg) {
if ((offset = GetFldIndex(CurrentPro, ri->arg)) == -1) {
ri->RC = RC_WARN;
return;
}
CurrentPro->CurrentFldOffset = offset;
}
if (fi = GetFldInfo(CurrentPro, CurrentPro->CurrentFldOffset)) ri->Result = fi->Name;
else ri->RC = RC_WARN; /* Should never happen */
}
static void Rx_GetField(RXInfo *ri) /* ri->arg is fieldname */
{
UpdateRecord(CurrentPro);
if (*ri->arg) ri->Result = RXGetFld(CurrentPro, ri->arg);
else ri->Result = GetFld(*CurrentPro->Recpp, CurrentPro->CurrentFldOffset);
if (!ri->Result) ri->RC = RC_WARN;
}
static void Rx_PutField(RXInfo *ri)
{
UpdateRecord(CurrentPro);
if (UpdateFld(*CurrentPro->Recpp, CurrentPro->CurrentFldOffset, ri->arg) &&
CurrentPro->Mode == MODE_NORMAL)
CurrentPro->Modified |= PROMODIFIED;
UpdateGadgets(CurrentPro);
}
static void Rx_Mode(RXInfo *ri)
{
if (*ri->arg) {
if (!Stricmp(ri->arg, "Normal")) SetProMode(CurrentPro, MODE_NORMAL);
else if (!Stricmp(ri->arg, "Find")) SetProMode(CurrentPro, MODE_FIND);
else if (!Stricmp(ri->arg, "Sort")) SetProMode(CurrentPro, MODE_SORT);
else ri->RC = RC_ERROR;
}
switch (CurrentPro->Mode) {
case MODE_NORMAL:
ri->Result = "Normal";
break;
case MODE_FIND:
ri->Result = "Find";
break;
case MODE_SORT:
ri->Result = "Sort";
break;
}
}
static void Rx_Save(RXInfo *ri)
{
DB_SAVE();
}
static void Rx_Sort(RXInfo *ri)
{
DoSort(CurrentPro, -1);
}
static void Rx_Quit(RXInfo *ri)
{
ReplyRexxCommand(ri->rxmessage, RC_OK, 0);
ByeBye();
}
static void Rx_UpdateGUI(RXInfo *ri)
{
BOOL save = CurrentPro->Quiet;
CurrentPro->Quiet = FALSE;
SetProMode(CurrentPro, CurrentPro->Mode);
CurrentPro->Quiet = save;
}
static void Rx_WindowToFront(RXInfo *ri)
{
if (CurrentPro->CurrentLayout->Window)
WindowToFront(CurrentPro->CurrentLayout->Window);
else ri->RC = RC_WARN;
}
static void Rx_ScreenToFront(RXInfo *ri)
{
ScreenToFront(Scr);
}
static void Rx_ActivateWindow(RXInfo *ri)
{
if (CurrentPro->CurrentLayout->Window)
ActivateWindow(CurrentPro->CurrentLayout->Window);
else ri->RC = RC_WARN;
}
static void Rx_BlockInput(RXInfo *ri)
{
BlockInput(CurrentPro->CurrentLayout->Window, TRUE);
UpdateRecord(CurrentPro);
CurrentPro->Quiet = TRUE; /* Don't do any GUI stuff from now on */
}
static void Rx_FreeInput(RXInfo *ri)
{
FreeInput(CurrentPro->CurrentLayout->Window);
CurrentPro->Quiet = FALSE; /* Release GUI now */
Rx_UpdateGUI(ri);
}
static void Rx_Dial(RXInfo *ri)
{
ri->RC = DoDial(ri->arg);
}
static void Rx_DisplayBeep(RXInfo *ri)
{
DisplayBeep(Scr);
}
static void Rx_Okay1(RXInfo *ri)
{
EasyRexxRequest(CurrentPro->CurrentLayout->Window, &ES_RexxOkay1, NULL, ri->arg);
}
static void Rx_Okay2(RXInfo *ri)
{
stci_d(ri->buf, EasyRexxRequest(CurrentPro->CurrentLayout->Window, &ES_RexxOkay2, NULL, ri->arg));
ri->Result = ri->buf;
}
static void Rx_CurrentGadget(RXInfo *ri)
{
int gadindex;
struct VisFldInfo *vf;
NextGad = NULL;
if (*ri->arg) {
gadindex = atoi(ri->arg);
if (!gadindex--) { /* string argument, not a number */
for(vf=CurrentPro->CurrentLayout->FirstVisFldInfo; vf; vf = vf->Next)
if (!Stricmp(ri->arg, vf->Name)) break;
}
else for (vf = CurrentPro->CurrentLayout->FirstVisFldInfo; vf && gadindex > 0; vf = vf->Next, gadindex--);
if (vf) LastGad = vf->Gadget;
}
if (LastGad) {
for(gadindex=1, vf=CurrentPro->CurrentLayout->FirstVisFldInfo; vf; vf = vf->Next, gadindex++)
if (vf->Gadget == LastGad) break;
stci_d(ri->buf, gadindex);
ri->Result = ri->buf;
}
else ri->RC = RC_WARN;
}
static void Rx_RetryInput(RXInfo *ri)
{
NextGad = NULL; /* Don't activate NextGad if tabcycling */
ActivateGadget(LastGad, CurrentPro->CurrentLayout->Window, NULL);
}
static void Rx_CurrentView(RXInfo *ri)
{
int viewindex;
struct Layout *lay = CurrentPro->FirstLayout;
if (*ri->arg) {
viewindex = atoi(ri->arg);
if (!viewindex--) { /* string argument, not a number */
for (; lay; lay = lay->NextLayout)
if (!Stricmp(ri->arg, lay->Name)) break;
} else for (; lay && viewindex; lay = lay->NextLayout, viewindex--);
ChangeView(lay);
}
else for (viewindex=1; lay != CurrentPro->CurrentLayout; lay = lay->NextLayout, viewindex++);
stci_d(ri->buf, viewindex);
ri->Result = ri->buf;
}
static void Rx_UndoBuffer(RXInfo *ri)
{
if (LastGad && LastGad->GadgetID == STRING_KIND)
ri->Result = ((struct StringInfo *)LastGad->SpecialInfo)->UndoBuffer;
else ri->RC = RC_WARN;
}
static void Rx_GetPortName(RXInfo *ri) /* Undocumented. The ARexx function Address() should do this job */
{
ri->Result = MyRexxPortName;
}
/**********************************************************************/
/* ARexx command dispatcher */
/**********************************************************************/
typedef struct {
char *name;
void (*cmd)(RXInfo *);
} Comm;
static Comm Commands[] = {
{ "Add", Rx_Add },
{ "Kill", Rx_Kill },
{ "FirstRecord", Rx_FirstRecord, },
{ "NextRecord", Rx_NextRecord },
{ "CurrentRecord", Rx_CurrentRecord },
{ "RecordSum", Rx_RecordSum },
{ "FindFirst", Rx_FindFirst },
{ "FindNext", Rx_FindNext },
{ "Cut", Rx_Cut },
{ "Copy", Rx_Copy },
{ "Paste", Rx_Paste },
{ "Merge", Rx_Merge },
{ "FirstField", Rx_FirstField },
{ "NextField", Rx_NextField },
{ "CurrentField", Rx_CurrentField },
{ "GetField", Rx_GetField },
{ "PutField", Rx_PutField },
{ "Mode", Rx_Mode },
{ "Save", Rx_Save },
{ "Sort", Rx_Sort },
{ "Quit", Rx_Quit },
{ "UpdateGUI", Rx_UpdateGUI },
{ "WindowToFront", Rx_WindowToFront },
{ "ScreenToFront", Rx_ScreenToFront },
{ "ActivateWindow", Rx_ActivateWindow },
{ "BlockInput", Rx_BlockInput },
{ "FreeInput", Rx_FreeInput },
{ "Dial", Rx_Dial },
{ "DisplayBeep", Rx_DisplayBeep },
{ "Okay1", Rx_Okay1 },
{ "Okay2", Rx_Okay2 },
{ "CurrentGadget", Rx_CurrentGadget },
{ "UndoBuffer", Rx_UndoBuffer },
{ "RetryInput", Rx_RetryInput },
{ "CurrentView", Rx_CurrentView },
{ "GetPortName", Rx_GetPortName },
{ NULL, NULL }
};
void HandleRexxCommand(struct RexxMsg *rxmessage)
{
int i, namelen;
char name[40];
char *cmdline = ARG0(rxmessage);
RXInfo ri;
ri.rxmessage = rxmessage; /* QUIT needs to answer itself */
ri.RC = RC_OK;
ri.Result = NULL;
/* Split cmdline into name and arg without affecting cmdline */
for (i=0; i<30 && cmdline[i] && cmdline[i] != ' '; i++)
name[i] = cmdline[i];
name[i] = '\0';
namelen = strlen(name);
ri.arg = NextWord(cmdline);
/* Do the dispatch */
for (i=0; Commands[i].name; i++) {
if (!Strnicmp(Commands[i].name, name, namelen)) {
Commands[i].cmd(&ri); /* Run this command */
ReplyRexxCommand(rxmessage, ri.RC, ri.Result);
return;
}
}
ReplyRexxCommand(rxmessage,RC_ERROR,NULL); /* Command not found */
}
void FreeRexxCommand(struct RexxMsg *rxmessage)
{
struct Window *win = (CurrentPro->CurrentLayout) ?
CurrentPro->CurrentLayout->Window : NULL;
if (rxmessage->rm_Result1) {
if (rxmessage->rm_Result2 == ERR10_001) /* Program not found */
EasyLocRequest(win, &ES_RexxProgNotFound, NULL, ARG0(rxmessage));
else EasyLocRequest(win, &ES_RexxError, NULL, ARG0(rxmessage), rxmessage->rm_Result2);
}
DeleteArgstring(rxmessage->rm_Args[0]); /* The command name */
/* In SendRexxCommand we cd to project's dir, cd back and unlock now */
UnLock(CurrentDir((BPTR)rxmessage->rm_Args[15]));
DeleteRexxMsg(rxmessage);
OutstandingRexxCommands--;
}
void CloseRexxPort(struct MsgPort *rexxport)
{
struct RexxMsg *rxmessage;
do {
while (rxmessage = (struct RexxMsg *)GetMsg(rexxport)) {
if (rxmessage->rm_Node.mn_Node.ln_Type == NT_REPLYMSG)
FreeRexxCommand(rxmessage); /* A command finished */
else ReplyRexxCommand(rxmessage, ERR10_013, NULL); /* 'Host not found' */
}
if (OutstandingRexxCommands) WaitPort(rexxport);
} while (OutstandingRexxCommands); /* Wait out all commands we've sent */
DeletePort(rexxport);
}
BOOL SendRexxCommand(char *name)
{
struct MsgPort *rexxport; /* System's Rexx port */
struct RexxMsg *rxmessage;
Forbid();
if (!(rexxport = FindPort(RXSDIR))) {
Permit();
return FALSE;
}
if (!(rxmessage = CreateRexxMsg(MyRexxPort,
NULL, MyRexxPort->mp_Node.ln_Name))) {
Permit();
return FALSE;
}
if (!(rxmessage->rm_Args[0] = CreateArgstring(name, strlen(name)))) {
Permit();
return FALSE;
}
rxmessage->rm_Action = RXCOMM | RXFB_NOIO; /* OR a stringcommand here */
/* Change to the directory of the project */
/* We put the old lock in Args[15] for FreeRexxCommand() */
rxmessage->rm_Args[15] =
(STRPTR)CurrentDir(Lock(CurrentPro->Drawer,ACCESS_READ));
PutMsg(rexxport, (struct Message *)rxmessage); /* Send it */
OutstandingRexxCommands++; /* For graceful cleanup */
Permit();
return TRUE;
}
BOOL SendRexxStrCommand(char *name)
{
char *str;
BOOL success;
int bufsize = strlen(name)+3;
if (!(str = AllocMem(bufsize, 0))) {
return FALSE;
}
sprintf(str,"\"%s\"", name);
success = SendRexxCommand(str);
FreeMem(str, bufsize);
return success;
}
BOOL HandleRexxMessage(struct MsgPort *rexxport)
{
BOOL finished = FALSE;
struct RexxMsg *rxmessage;
/* returns TRUE when command is finished */
/* Is this a reply? ie has a command finished? */
while (rxmessage = (struct RexxMsg *)GetMsg(rexxport)) {
if (rxmessage->rm_Node.mn_Node.ln_Type == NT_REPLYMSG) {
FreeRexxCommand(rxmessage);
finished = TRUE;
CurrentPro->Quiet = FALSE;
if (CurrentPro->CurrentLayout)
FreeInput(CurrentPro->CurrentLayout->Window);
}
else HandleRexxCommand(rxmessage);
}
return finished;
}