/*
 *  WICONIFYSCREEN  A companion utility to wIconify that allows you
 *                  to iconify any screen via a CLI command, and modify
 *                  its icon flags.
 *
 *  Copyright 1990 by Davide P. Cervone, all rights reserved.
 *  You may use this code, provided this copyright notice is kept intact.
 */

#define INTUITION_PREFERENCES_H             /* don't need 'em */
#include <intuition/intuitionbase.h>
#include "wIcon.h"

#define USAGE\
   "wIconifyScreen [screen] [[-]NOMOVE] [[-]NOSAVEPOS]\n   \
        [[-]NOMULTISELECT] [[-]LOCKED] [[-]NOORGANIZE]"

#define DEFAULTFLAGS    WI_NOCLOSE

static char *program = "wIconifyScreen";
static char *version = "v1.2";
static char *copyright =
   "Copyright (C) 1990 by Davide P. Cervone, all rights reserved.";


#define INTUITION_REV   0L
extern struct IntuitionBase *IntuitionBase;
extern struct IntuitionBase *OpenLibrary();

static WICON theIcon;               /* Definition of the icon to use */
static ULONG Flags = DEFAULTFLAGS;  /* The flags to use */
static ULONG NoFlags = 0;           /* Have flags been specified? */
static WORD  x,y;                   /* The icon's position */
static char *ScreenName = NULL;     /* the screen's name */


#define ARGMATCH(s)     (stricmp(*argv,s) == 0)
#define TOUPPER(c)      (((c)>='a'&&(c)<='z')?(c)-'a'+'A':c)
#define NOFLAGSYET\
   (Flags == DEFAULTFLAGS && NoFlags == 0 && x == 0 && y == 0)



/*
 *  Print()
 *
 *  Find the standard AmigaDOS output file and write the output string
 *  to the output file.  This is intended as a substitute for printf()
 *  when no formatting is required, and when you want a small executable.
 */

static void Print(s)
char *s;
{
   ULONG OutFile;
   extern ULONG Output();
   
   OutFile = Output();
   if (OutFile && s) Write(OutFile,s,strlen(s));
}


/*
 *  Error()
 *
 *  Print the character string, and up to two optional strings, then
 *  go to a new output line, close Intuition, and exit with an error.
 */

static void Error(s,x1,x2)
char *s,*x1,*x2;
{
   Print(s);
   if (x1) Print(x1);
   if (x2) Print(x2);
   Print("\n");
   if (IntuitionBase) CloseLibrary(IntuitionBase);
   _exit(10L);
}


/*
 *  ParseArguments()
 *
 *  While there are more arguments to consider,
 *    Move to the next one
 *    If it matches something we're looking for, then add the flag to
 *      the Flags or NoFlags masks.
 *    If the argument is "AT", then
 *      If the next arguement is an X,Y pair, save their values,
 *      Otherwise, give an error message.
 *      Skip the next argument in either case.
 *    If there were no flags and no screen title, then save the arguement
 *       as the screen title.
 *    Otherwise, report an error.
 *  Return TRUE if all parameters were OK, and FALSE otherwise.
 */

static int ParseArguments(argc,argv)
int argc;
char **argv;
{
   int status = TRUE;
   int X,Y;
   
   while (--argc)
   {
      argv++;
      if (ARGMATCH("NOMOVE"))        Flags |= WI_NOMOVE; else
      if (ARGMATCH("NOORGANIZE"))    Flags |= WI_NOORGANIZE; else
      if (ARGMATCH("NOSAVEPOS"))     Flags |= WI_NOSAVEPOS; else
      if (ARGMATCH("LOCKED"))        Flags |= WI_LOCKED; else
      if (ARGMATCH("NOMULTISELECT")) Flags |= WI_NOMULTISELECT; else

      if (ARGMATCH("-NOMOVE"))        NoFlags |= WI_NOMOVE; else
      if (ARGMATCH("-NOORGANIZE"))    NoFlags |= WI_NOORGANIZE; else
      if (ARGMATCH("-NOSAVEPOS"))     NoFlags |= WI_NOSAVEPOS; else
      if (ARGMATCH("-LOCKED"))        NoFlags |= WI_LOCKED; else
      if (ARGMATCH("-NOMULTISELECT")) NoFlags |= WI_NOMULTISELECT; else

      if (ARGMATCH("AT"))
      {
         if (argc > 1 && sscanf(*(argv+1),"%ld,%ld",&X,&Y) == 2)
             x = X, y = Y;
            else
             Print("The AT directive must be of the form 'AT x,y'\n"),
             status = FALSE;
         if (argc > 1) argc--, argv++;
      } else
      if (NOFLAGSYET && ScreenName == NULL) ScreenName = *argv;
      else
      {
         Print("Unrecognized flag '");
         Print(*argv);
         Print("'\n");
         status = FALSE;
      }
   }
   return(status);
}


/*
 *  PrefixMatch()
 *
 *  Case-insensitive prefix match.  NULL pointers and empty strings
 *  only match themselves, and are not considered prefixes to any string.
 *
 *  Return <0 if the first is smaller than the second,
 *         =0 if the first is a prefix of the second,
 *         >1 if the first is larger than the second.
 */

int PrefixMatch(s1,s2)
char *s1,*s2;
{
   int match = -1;
   
   if (s1 && *s1)
   {
      if (s2)
      {
         while (TOUPPER(*s1) == TOUPPER(*s2) && *s2 != 0) s1++,s2++;
         if (*s1 == 0) match = 0; else match = *s1 - *s2;
      } else match = 1;
   } else if (s2 == NULL || *s2 == 0) match = 0;
   return(match);
}


/*
 *  *FindScreen()
 *
 *  Lock IntuitionBase so nothing happens while we look.
 *  If there is a name to look for,
 *    Start at the first screen, and look for a screen whose title
 *      matches the given name.  If none, return NULL.
 *  Otherwise, use the active screen.
 *  Unlock Intuition.
 *  Return the screen pointer found, if any.
 */

static struct Screen *FindScreen(ScreenName)
char *ScreenName;
{
   struct Screen *theScreen;
   long ILock, LockIBase();

   ILock = LockIBase(0L);
   if (ScreenName)
   {
      theScreen = IntuitionBase->FirstScreen;
      while (theScreen && PrefixMatch(ScreenName,theScreen->Title))
         theScreen = theScreen->NextScreen;
   } else {
      theScreen = IntuitionBase->ActiveScreen;
   }
   UnlockIBase(ILock);
   return(theScreen);
}


/*
 *  main()
 *
 *  If all the parameters are OK,
 *  Open Intuition.
 *  Find the specified screen.
 *  If wIconify is runnging
 *    If the screen is iconified, de-iconify it,
 *    Otherwise
 *      Get the screen's icon's current values,
 *      Clear the NoFlags, and add the Flags specified by the user,
 *      If a position was given, set it
 *      Update the icon to the new values.
 *      Iconify the screen.
 *  Otherwise give appropriate errors.
 */

void main(argc,argv)
int argc;
char *argv[1];
{
   struct Screen *theScreen = NULL;
   WICONREF *wIconOfScreen();

   if (ParseArguments(argc,argv))
   {
      IntuitionBase = OpenLibrary("intuition.library",INTUITION_REV);
      if (IntuitionBase)
      {
         theScreen = FindScreen(ScreenName);
         if (theScreen)
         {
            if (wIconifyActive())
            {
               if (wIsScreenIconified(theScreen))
               {
                  wRestore(wIconOfScreen(theScreen));
               } else {
                  wGetIconData(&theIcon,wIconOfScreen(theScreen));
                  theIcon.Flags &= ~NoFlags;
                  theIcon.Flags |= Flags;
                  if (x || y)
                  {
                     theIcon.x = x;
                     theIcon.y = y;
                  }
                  wSetScreenIcon(theScreen,&theIcon);
                  wIconifyScreen(theScreen);
               }
            } else Error("wIconify not running or incompatible version",
                          NULL,NULL);
         } else Error("Can't find screen '",ScreenName,"'");
         CloseLibrary(IntuitionBase);
      } else Error("Can't Open Intuition Library!",NULL,NULL);
   } else Error("Usage:  ",USAGE);
}
