Listing 4 von query.c (rexxalert.library)

/*--------------------------------------------------------*/
/*    query.c -- v. Bob Malzan                            */
/*                                                        */
/*  hier steht die Funktion, die vom REXXMAST aufgerufen  */
/*  wird, sowie die Anwendungen, die wiederum von Query   */
/*  aufgerufen werden...                                  */
/*--------------------------------------------------------*/
#include <exec/memory.h>
#include <functions.h>
#include <intuition/intuitionbase.h>

/*                   globale Variablen                    */
struct Library *RexxSysBase = NULL;
struct IntuitionBase *IntuitionBase = NULL;
struct Library *DosBase = NULL;

/*                   externe Funktionen                   */
extern char *CreateArgstring(char *arg,long len);

/*  mit diesem PRAGMA rufe ich die rexxsyslib direkt auf  */
#pragma amicall(RexxSysBase, 0x7E, CreateArgstring(a0,d0))

/*          so sieht die RexxMsg-Struktur aus...          */
struct RexxMsg {
  struct Message rm_Node;
  APTR           rm_TaskBlock;
  APTR           rm_LibBase;
  LONG           rm_Action;
  LONG           rm_Result1;
  LONG           rm_Result2;
  STRPTR         rm_Args[16];
  struct MsgPort *rm_PassPort;
  STRPTR         rm_CommAddr;
  STRPTR         rm_FileExt;
  LONG           rm_Stdin;
  LONG           rm_Stdout;
  LONG           rm_avail;
};

/*      eine "Musterstruktur" für die Requestertexte      */
struct IntuiText ISample =
{
  0,1,     /* Left, Top; */
  JAM1,    /* DrawMode */
  8,4,     /* SHORT LeftEdge; SHORT TopEdge; */
  NULL,    /* struct TextAttr *ITextFont; */
  (UBYTE *)NULL, /* TextFont */
  NULL     /* NextText */
};

/*--------------------------------------------------------*/
/*    Es folgen zwei Routinen, 'MyOpen' und 'MyClose',    */
/*     die beim ersten Starten und beim Entfernen der     */
/*     Library aufgerufen werden. Hier müssen eigene      */
/*         Initialisierungen eingetragen werden.          */
/*--------------------------------------------------------*/
void MyOpen(struct RXALBase *base)
{
  DosBase       = OpenLibrary("dos.library", 0L);
  IntuitionBase = OpenLibrary("intuition.library", 0L);
  RexxSysBase   = OpenLibrary("rexxsyslib.library", 0L);
}

void MyClose(struct RXALBase *base)
{
  if (RexxSysBase)   CloseLibrary(RexxSysBase);
  if (IntuitionBase) CloseLibrary(IntuitionBase);
  if (DosBase)       CloseLibrary(DosBase);
}

/*--------------------------------------------------------*/
/*  Eine kleine Hilfsroutine, um die IDCMP's auszuwerten. */
/* Hier können weitere IDCMP-Events eingeführt werden...  */
/*--------------------------------------------------------*/
long EvalIDCMP(char *str)
{
  long idcmp = 0;
  char buf[20];
  int  I=0;

  while(*str)
  {
    while (*str && *str!='+') buf[I++] = *str++;
    buf[I]='\0';
    if (strcmp(buf,"DISKINSERTED")==0) idcmp |= DISKINSERTED;
    else if (strcmp(buf,"DISKREMOVED")==0) idcmp |= DISKREMOVED;
    else return(-1);
    I=0;
    if (*str) str++;
  }
  return(idcmp);
}

/*--------------------------------------------------------*/
/*          ARequest erzeugt einen Auto-Requester         */
/*       Wenn der Window-Zeiger == NULL, dann wird        */
/*   auto(reques)tomatisch ein System-Request erzeugt.    */
/* wenn eine unmögliche Höhe angegeben wird, wandelt das  */
/*       System das Ganze in einen User-Alert um!         */
/*--------------------------------------------------------*/
int ARequest(
  struct Window *W,
  int NumArgs,
  char **Args,
  char **ResP)
{
  char *PText;
  char *NText = "CANCEL";
  long Width,Height,BNumChars,BNumLines;
  long Pidcmp = 0;
  long Nidcmp = 0;
  BOOL res;
  int Rc = 0;

  struct IntuiText IBText1;
  struct IntuiText IBText2;
  struct IntuiText IBText3;
  struct IntuiText IPText;
  struct IntuiText INText;

  register char *Arg;

/*         Grundeinstellung der Text-Struktur aus         */
/*                 dem Muster übernehmen                  */
  memcpy(&IBText1,&ISample,sizeof(ISample));
  memcpy(&IBText2,&ISample,sizeof(ISample));
  memcpy(&IBText3,&ISample,sizeof(ISample));
  memcpy(&IPText,&ISample,sizeof(ISample));
  memcpy(&INText,&ISample,sizeof(ISample));

/*--------------------------------------------------------*/
/*                  Parameter auswerten                   */
  if (NumArgs-- > 0)
  {
    Arg = Args[1];
    if (Arg) /* BText = "Body Text" zerlegen */
    {
      char *strb = Arg;
      char *strc = Arg;

      while (*strc && *strc != '\\') strc++;
      IBText1.IText = (UBYTE *)strb;
      BNumChars = strc-strb;
      BNumLines = 1;
      if (*strc)
      {
        *strc++ = '\0';
        strb = strc;
        while (*strc && *strc != '\\') strc++;
        IBText2.IText = (UBYTE *)strb;
        IBText1.NextText = &IBText2;
        IBText2.TopEdge = 4+9;
        if (strc-strb > BNumChars) BNumChars = strc-strb;
        BNumLines++;
      }
      if (*strc)
      {
        *strc++ = '\0';
        IBText3.IText = (UBYTE *)strc;
        IBText2.NextText = &IBText3;
        IBText3.TopEdge = 4+18;
        if (strlen(strc) > BNumChars) BNumChars = strlen(strc);
        BNumLines++;
      }
    }
    else Rc = 18; /* ungültiges (kein) Argument */
  }
  else Rc = 17; /* falsche Anzahl von Parametern (gar keine) */

  if (NumArgs-- > 0) PText = Args[2]; /* positiver Text */
  else PText = NULL;

  if (NumArgs-- > 0 && Args[3]) NText = Args[3]; /* neg. Text */
  else Rc = 17; /* falsche Anzahl von Parametern (min. 2) */

  if (NumArgs-- > 0) /* positive IDCMPs */
  {
    Arg = Args[4];
    if (Arg)
    {
      Pidcmp = EvalIDCMP(Arg);
      if (Pidcmp == -1) Rc = 18; /* ungültiges Argument */
    }
  }

  if (NumArgs-- > 0) /* negative IDCMPs */
  {
    Arg = Args[5];
    if (Arg)
    {
      Nidcmp = EvalIDCMP(Arg);
      if (Nidcmp == -1) Rc = 18;
    }
  }

  if (NumArgs-- > 0 && Args[6]) /* Requesterbreite */
  {
    Arg = Args[6];
    Width = atoi(Arg);
  }
  else /* sonst automatische Breite */
  {
    int Wpn = (strlen(PText)+strlen(NText)+10)*8;
    int Wb  = (BNumChars+3)*8;

    Width = (Wpn > Wb ? Wpn : Wb);
  }

  if (NumArgs-- > 0 && Args[7]) /* Requesterhöhe */
  {
    Arg = Args[7];
    Height = atoi(Arg);
  }
  else Height = (BNumLines+5)*9; /* sonst automatisch */

/*               Ende Parameter-Auswertung                */
/*--------------------------------------------------------*/

/*    wenn so weit alles klar ist, Requester aufbauen     */
  if (Rc == 0)
  {
    IPText.IText = (UBYTE *)PText;
    INText.IText = (UBYTE *)NText;
    if (PText) /* Fall mit positivem Text */
    {
      res = AutoRequest(W,&IBText1,&IPText,&INText,
                        Pidcmp,Nidcmp,Width,Height);
    }
    else /* Fall ohne positiven Text */
    {
      res = AutoRequest(W,&IBText1,NULL,&INText,
                        Pidcmp,Nidcmp,Width,Height);
    }
/*  praktischerweise gibt ARequest() nur die boole'schen  */
/*      Werte '0' oder '1' zurück, wie sie von ARexx      */
/*               auch verarbeitet werden...               */
    *ResP=(res ? "1" : "0");
  }
  return(Rc);
}

/* zwei kleine Hilfsdefinitionen zum Zerlegen eines UWORD */
#define HIBYTE(x) (( (x) >> 8 ) & 0xFF)
#define LOBYTE(x) ( (x) & 0xFF)

/*--------------------------------------------------------*/
/*           DAlert erzeugt einen DisplayAlert            */
/*--------------------------------------------------------*/
long DAlert(int NumArgs,char **Args,char **ResP)
{
  int            res,lines=0;
  int            Spacing = 10;
  register UBYTE *p1,*p2;
  UBYTE          AlsList[1024];
  UWORD          LeftOffset = 10;
  UBYTE          TopOffset = 15;

/*                   Parameter einlesen                   */
  if (NumArgs-- < 1) return(17L); /* falsche Anz. v. Parametern */
  p1 = (UBYTE *)Args[1];
  if (!p1) return(18L); /* ungültiger Wert (kein Text) */

  if (NumArgs-- > 0 && Args[2]) LeftOffset = atoi(Args[2]);
  if (NumArgs-- > 0 && Args[3]) TopOffset = atoi(Args[3]);
  if (NumArgs-- > 0 && Args[4]) Spacing = atoi(Args[4]);

/*--------------------------------------------------------
 Format einer Textzeile für Alerts:

 1. & 2. Byte      Abstand vom linken Rand als UWORD
 3. Byte           Abstand von oberen Rand als UBYTE
 4. ... n. Byte    der Textstring
 n+1. Byte         0 (wie immer am Ende eines Strings)
 n+2. Byte         1, wenn eine weitere Zeile folgt und
                   0, wenn keine weitere Zeile folgt
--------------------------------------------------------*/

  p2 = AlsList; /* unser Puffer für die Textzeilen */

/*              erste Textzeile vorbereiten               */
  *p2++ = HIBYTE(LeftOffset); /* x-Offset high */
  *p2++ = LOBYTE(LeftOffset); /* x-Offset low  */
  *p2++ = TopOffset; /* y-Offset */

  while (*p1)
  {
    if (*p1 == '\\') /* Zeilenende */
    {
      lines++;
      *p2++ = 0; /* Zeilenende eintragen */
      p1++;
      if (*p1) /* Folgezeile aufbauen */
      {
        *p2++ = 1;
        *p2++ = HIBYTE(LeftOffset);
        *p2++ = LOBYTE(LeftOffset);
        *p2++ = TopOffset+lines*Spacing;
      }
    }
    else *p2++ = *p1++; /* Zeichen in den Puffer kopieren */
  }
  *p2++ = 0; /* Zeilenende */
  *p2++ = 0; /* keine weiteren Zeilen */

/*--------------------------------------------------------*/

  res = DisplayAlert(
          RECOVERY_ALERT,
          (char *)AlsList,
          TopOffset+10+lines*Spacing);

/*   praktischerweise gibt DAlert() nur die boole'schen   */
/*      Werte '0' oder '1' zurück, wie sie von ARexx      */
/*               auch verarbeitet werden...               */
  *ResP=(res ? "1" : "0");
  return(0L);
}

/*--------------------------------------------------------*/
/* Es folgt die Query-Routine. Sie wird immer aufgerufen, */
/*         wenn der REXXMAST eine Funktion sucht.         */
/*--------------------------------------------------------*/
LONG Query(struct RexxMsg *RxMsg,char **ResultP)
{
  char  *Result;
  int   ReturnCode=0;
  int   NumArgs;

  register char *FName,*Arg;

  NumArgs = RxMsg->rm_Action & 0x0F;
  FName = (char *)RxMsg->rm_Args[0];
  if (strcmp(FName,"AUTOREQUEST")==0)
  {
    ReturnCode = ARequest(
                   IntuitionBase->ActiveWindow,
                   NumArgs,
                   (char **)RxMsg->rm_Args,
                   &Result);
  }
  else if (strcmp(FName,"SYSREQUEST")==0)
  {
    ReturnCode = ARequest(
                   NULL,
                   NumArgs,
                   (char **)RxMsg->rm_Args,
                   &Result);
  }
  else if (strcmp(FName,"DALERT")==0)
  {
    ReturnCode = DAlert(
                   NumArgs,
                   (char **)RxMsg->rm_Args,
                   &Result);
  }
  else ReturnCode = 1; /* "Funktion nicht gefunden" */

/*--------------------------------------------------------*/
/*                      Query()-ENDE                      */
/*      Nur, wenn kein Fehler aufgetreten ist, dann       */
/*               RESULT-ArgString erzeugen                */
  if (ReturnCode==0)
    *ResultP = CreateArgstring(Result,strlen(Result));
/*                        fertig!                         */
  return(ReturnCode);
}
