/* ** Bobi - The Ultimate Amiga Bob Manipulator ** ** ARexx.c - ARexx-Port für Bobi (created from TopScan/ARexx.c) ** ** COPYRIGHT (C) 1989-1993 BY CHRISTIAN A. WEBER, ZUERICH, SWITZERLAND. ** ALL RIGHTS RESERVED. NO PART OF THIS SOFTWARE MAY BE COPIED, REPRODUCED, ** OR TRANSMITTED IN ANY FORM OR BY ANY MEANS, WITHOUT THE PRIOR WRITTEN ** PERMISSION OF THE AUTHOR. NO WARRANTY. USE AT YOUR OWN RISK. */ #include #include #include #include #include #include #include #include #include #include "Bobi.h" #include "BobStructure.h" #define MYREXXPORTNAME "rexx_bobi" #define MYREXXSUFFIX "brx" /**************************************************************************** ** Globals */ BYTE arexxflag; /* TRUE wenn ein Kommando von ARexx am laufen ist */ char arexxfilename[200]; /* Filename z.B. für LoadBobs() */ BYTE debugflag; extern struct Screen *mainscreen; extern struct MyBob *BobTable[]; extern WORD numbobs,actbobnum,options,mainx0,mainy0; /**************************************************************************** ** Locals */ static struct Library *RexxSysBase; static struct MsgPort *myrexxport; /* TopScan's rexx port */ static LONG commandcounter; /* Zählt abgeschickte Kommandos */ static char resultstring[256]; /* Puffer für ARexx-Resultate */ /**************************************************************************** ** ASCII String holen, Anführungszeichen interpretieren. ** Der Char*-Zeiger wird auf den Text nach dem String gesetzt. */ static void GetRexxString(char **strptr,char *dest) { char *s=*strptr; /* ** Führende Spaces überlesen */ while(*s == ' ') s++; /* ** Text kopieren */ if(*s == '"') /* Anführungszeichen --> plain copy */ { s++; while(*s) { if(*s == '\\') /* Escape-Sequenz */ { switch(*++s) { case '\0': goto ende; case 'n': *dest++ = '\n'; break; default: *dest++ = *s; break; } s++; } else if(*s == '"') break; else *dest++ = *s++; } ende: ; } else /* Keine Anführungszeichen --> bis Space */ { while(*s) { if(*s == '\\') /* Escape-Sequenz */ { switch(*++s) { case '\0': goto ende2; case 'n': *dest++ = '\n'; break; default: *dest++ = *s; break; } s++; } else if(*s == ' ') break; else *dest++ = *s++; } ende2: ; } *dest = '\0'; /* ** Spaces am Schluss überlesen */ while(*s == ' ') s++; *strptr = s; } /**************************************************************************** ** ASCII nach Integer wandeln, Nachkommastellen werden unterdrückt. ** Der Char*-Zeiger wird auf den Text nach der Zahl gesetzt. */ static LONG GetRexxInteger(char **strptr) { char *s=*strptr; LONG zahl=0,sign=1; while(*s == ' ') s++; if(*s == '-') { sign=-1; s++; } else if(*s == '+') s++; while((*s >= '0') && (*s <= '9')) { zahl = zahl*10+(*s++-'0'); } while(*s == ' ') s++; *strptr = s; return zahl*sign; } /**************************************************************************** ** Die Interface-Routinen zu den ARexx-Kommandos */ static LONG RX_BobiToFrontFunc(char *args) { ScreenToFront(mainscreen); return RC_OK; } static LONG RX_BobiToBackFunc(char *args) { ScreenToBack(mainscreen); return RC_OK; } static LONG RX_ClearAllFunc(char *args) { ClearAll(); return RC_OK; } static LONG RX_LoadBobsFunc(char *args) { GetRexxString(&args,arexxfilename); LoadBobsFunc(); return RC_OK; } static LONG RX_InsertBobsFunc(char *args) { GetRexxString(&args,arexxfilename); InsertBobsFunc(); return RC_OK; } static LONG RX_SaveBobsFunc(char *args) { GetRexxString(&args,arexxfilename); SaveBobsFunc(); return RC_OK; } static LONG RX_GenerateCodeFunc(char *args) { GetRexxString(&args,arexxfilename); GenerateCodeFunc(); return RC_OK; } static LONG RX_LoadIFFFunc(char *args) { GetRexxString(&args,arexxfilename); LoadPicFunc(); return RC_OK; } static LONG RX_ClosePictureFunc(char *args) { CloseScreenFunc(); return RC_OK; } static LONG RX_GetBobFunc(char *args) { int x,y,w,h; x = GetRexxInteger(&args); y = GetRexxInteger(&args); w = GetRexxInteger(&args); h = GetRexxInteger(&args); if(GetBob(x,y,w,h)) { actbobnum++; return RC_OK; } else return RC_ERROR; } static LONG RX_InsertNewFunc(char *args) { InsertNewBobFunc(); return RC_OK; } static LONG RX_SetOrgFunc(char *args) { if((numbobs>0) && (numbobs!=actbobnum)) { BobTable[actbobnum]->X0 = GetRexxInteger(&args); BobTable[actbobnum]->Y0 = GetRexxInteger(&args); return RC_OK; } else return RC_ERROR; } #if 0 static LONG RX_DebugFunc(char *args) { debugflag=GetRexxInteger(&args); return RC_OK; } #endif /**************************************************************************** ** Ein Rexx-Kommando auswerten, geht auch wenn ARexx NICHT läuft */ LONG PerformRexxCommand(char *commandline) { static struct MyRexxCmd { char *Name; /* Name des Kommandos */ LONG (*Func)(char *); /* Aufzurufende Routine */ } rexxcmdtab[] = { "BOBITOFRONT", RX_BobiToFrontFunc, "BOBITOBACK", RX_BobiToBackFunc, "CLEARALL", RX_ClearAllFunc, "LOADBOBS", RX_LoadBobsFunc, "INSERTBOBS", RX_InsertBobsFunc, "SAVEBOBS", RX_SaveBobsFunc, "GENERATECODE", RX_GenerateCodeFunc, "LOADIFF", RX_LoadIFFFunc, "CLOSEPICTURE", RX_ClosePictureFunc, "GETBOB", RX_GetBobFunc, "INSERTNEW", RX_InsertNewFunc, "SETORG", RX_SetOrgFunc, #if 0 "DEFAULTORG", RX_DefaultOrgFunc, "SETCOLLISION", RX_SetCollisionFunc, "FLIPX", RX_FlipXFunc, "FLIPY", RX_FlipYFunc, "ROTATE", RX_RotateFunc, "ZOOM", RX_ZoomFunc, "DELETEBOB", RX_DeleteBobFunc, "LOADANIM", RX_LoadAnimFunc, "SAVEANIM", RX_SaveAnimFunc, "ANIMFIRST", RX_AnimFirstFunc, "ANIMLAST", RX_AnimLastFunc, "ANIMMODE", RX_AnimModeFunc, "STARTANIM", RX_StartAnimFunc, "STOPANIM", RX_StopAnimFunc, "TOOLWINDOW", RX_ToolWindowFunc, "LAYERMODE", RX_LayerModeFunc, "ORGGRID", RX_OrgGridFunc, "BOBBORDERS", RX_BobBordersFunc, "BOBCOLLISION", RX_BobCollisionFunc, "SETMAINORG", RX_SetMainOrgFunc, "LOADOFFSETS", RX_LoadOffsetsFunc, "SAVEOFFSETS", RX_SaveOffsetsFunc, "REMAKELABELS", RX_RemakeLabelsFunc, "REMAKECOLLISION", RX_RemakeCollisionFunc #endif NULL, NULL /* End-Markierung */ }; struct MyRexxCmd *cptr; *resultstring = '\0'; /* Resultat löschen */ for(cptr=rexxcmdtab; cptr->Name; cptr++) { char *s,*d; for(s=commandline,d=cptr->Name; *d; s++,d++) { if(*s != *d) break; } if(*s <= ' ') /* Kommandoname fertig <-> das richtige */ { LONG result; while(*s == ' ') s++; /* Spaces überhüpfen */ arexxflag = TRUE; result = cptr->Func(s); /* Funktion aufrufen */ arexxflag = FALSE; return result; } } return RC_ERROR; } /**************************************************************************** ** ARexx initialisieren, 1x gerufen bei Programmstart ** Öffnet rexxsyslib und erstellt rexx_topscan Port ** Resultat: 0 falls ARexx nicht läuft, sonst Signalmaske von neuem RexxPort */ ULONG InitARexx(void) { if(RexxSysBase=OpenLibrary(RXSNAME,0)) { if(myrexxport=CreatePort(MYREXXPORTNAME,0)) { return 1U<mp_SigBit; } } CloseARexx(); return 0; } /**************************************************************************** ** ARexx cleanup, 1x gerufen bei Programmende ** Zerstört den ARexx-Port und schliesst rexxsyslib, falls kein Kommando ** am Laufen ist, sonst wird FALSE zurückgegeben */ ULONG CloseARexx(void) { if(commandcounter) { ShowMonoReq2("Can't quit yet, there are\nARexx-Commands pending."); return FALSE; } if(myrexxport) { DeletePort(myrexxport); myrexxport = NULL; } if(RexxSysBase) { CloseLibrary(RexxSysBase); RexxSysBase = NULL; } return TRUE; } /**************************************************************************** ** RexxMessage holen und Kommando starten falls ARexx läuft */ void RexxMsgHandler(void) { struct RexxMsg *msg; if(!myrexxport) return; /* Sofort zurück falls ARexx nicht läuft */ while (msg = (struct RexxMsg *)GetMsg(myrexxport)) { if(msg->rm_Node.mn_Node.ln_Type != NT_REPLYMSG) /* ** Es ist eine gültige Message und keine Antwort. */ { if(IsRexxMsg(msg)) { /* Sollen wir ein Kommando auführen ? */ if((msg->rm_Action & RXCODEMASK) == RXCOMM) { msg->rm_Result1 = 0; msg->rm_Result2 = 0; if(msg->rm_Result1 = PerformRexxCommand(msg->rm_Args[0])) { /* Func returned an error */ } else if((*resultstring) && (msg->rm_Action & RXFF_RESULT)) { msg->rm_Result2 = (LONG) CreateArgstring(resultstring,strlen(resultstring)); } } // else INTERNAL_ERROR; } // else INTERNAL_ERROR; ReplyMsg(msg); } else /* ** Diese Message ist ein reply auf eine Message welche wir ** früher mal geschickt haben */ { DeleteArgstring(msg->rm_Args[0]); if(msg->rm_Stdin) Close(msg->rm_Stdin); DeleteRexxMsg(msg); commandcounter--; } } } /**************************************************************************** ** Eine RexxMessage schicken (Speicher wird von RexxMsgHandler freigegeben) ** Parameter: Kommando-String */ void SendRexxCommand(char *command) { BPTR window; if(window=Open("CON:0/20/600/160/Bobi ARexx Output Window/AUTO/CLOSE",MODE_OLDFILE)) { struct MsgPort *masterport; Forbid(); if(masterport=FindPort(RXSDIR)) { struct RexxMsg *msg; if(msg=CreateRexxMsg(myrexxport,MYREXXSUFFIX,MYREXXPORTNAME)) { if(msg->rm_Args[0] = CreateArgstring(command,strlen(command))) { msg->rm_Action = RXCOMM; msg->rm_Stdin = window; msg->rm_Stdout = window; window = NULL; commandcounter++; PutMsg(masterport,(struct Message *)msg); } } } Permit(); if(window) Close(window); /* Schliessen falls Error */ } }