/* :ts=3
** nwb - NewWinBox: changes window size and position of active window
**
** written & © Ralph Reuchlein <amiga@rripley.de> 2000
*/

#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>

#include <exec/types.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/intuition.h>
#include <intuition/intuitionbase.h>
#include <exec/memory.h>

const UBYTE ver_string[] = "$VER: NewWinBox 1.0 (06.01.00)Copyright © 2000 by Ralph Reuchlein";


/* ReadArgs defines ----------------------------------------------- */
#define ARGS_TEMPLATE   "DELAY=D/N/K,"\
                        "WIDTH=W/N/K,"\
                        "HEIGHT=H/N/K,"\
                        "LEFT=X/N/K,"\
                        "TOP=Y/N/K,"\
                        "QUIET/S"

enum {
   OPT_DELAY = 0,
   OPT_WIDTH,
   OPT_HEIGHT,
   OPT_LEFT,
   OPT_TOP,
   OPT_QUIET,

   OPT_COUNT
};
static LONG args[OPT_COUNT];

#define ARG_DELAY    (*(ULONG *)args[OPT_DELAY])
#define ARG_WIDTH    (*(ULONG *)args[OPT_WIDTH])
#define ARG_HEIGHT   (*(ULONG *)args[OPT_HEIGHT])
#define ARG_LEFT     (*(ULONG *)args[OPT_LEFT])
#define ARG_TOP      (*(ULONG *)args[OPT_TOP])
#define ARG_QUIET    (args[OPT_QUIET]==-1)

#define IS_DELAY     (args[OPT_DELAY])
#define IS_WIDTH     (args[OPT_WIDTH])
#define IS_HEIGHT    (args[OPT_HEIGHT])
#define IS_LEFT      (args[OPT_LEFT])
#define IS_TOP       (args[OPT_TOP])
#define IS_QUIET     (args[OPT_QUIET]==-1)



/* Prototypes ----------------------------------------------------- */
void     error(STRPTR,...);
void     verbose(STRPTR,...);



/* Global variables ----------------------------------------------- */



/* ---------------------------------------------------------------- */
void main(UWORD argc,STRPTR argv[]) {
   struct RDArgs *rdargs;
   ULONG          ilock;
   struct Window *win;
   struct Screen *scr;
   WORD           width, height;
   WORD           leftEdge, topEdge;
   WORD           minWidth, minHeight;
   UWORD          maxWidth, maxHeight;
   WORD           scrWidth, scrHeight;
   UWORD          newWidth, newHeight;
   UWORD          newLeft, newTop;

   /* process arguments */
   if (rdargs=ReadArgs(ARGS_TEMPLATE,args,NULL)) {
      /* do we have a delay? */
      if ((IS_DELAY) && (ARG_DELAY>0))  Delay(TICKS_PER_SECOND*ARG_DELAY);

      /* Lock Intuition, get active window, grab information and UnLock */
      ilock=LockIBase(0);
      win=IntuitionBase->ActiveWindow;
      leftEdge=win->LeftEdge;
      topEdge=win->TopEdge;
      width=win->Width;
      height=win->Height;
      minWidth=win->MinWidth;
      minHeight=win->MinHeight;
      maxWidth=win->MaxWidth;
      maxHeight=win->MaxHeight;
      scr=win->WScreen;
      scrWidth=scr->Width;
      scrHeight=scr->Height;
      UnlockIBase(ilock);
      verbose("Original window dimensions:\n"
              "   Width: %5i,    Height: %5i, Left: %5i, Top: %5i\n"
              "MinWidth: %5i, MinHeight: %5i\n"
              "MaxWidth: %5i, MaxHeight: %5i\n"
              "ScrWidth: %5i, ScrHeight: %5i\n"
              "\n",
              width,height,leftEdge,topEdge,
              minWidth,minHeight,maxWidth,maxHeight,
              scrWidth,scrHeight);

      /* fill new box dimensions */
      newWidth  = (IS_WIDTH )?(ARG_WIDTH ):(width );
      newHeight = (IS_HEIGHT)?(ARG_HEIGHT):(height);
      newLeft   = (IS_LEFT  )?(ARG_LEFT  ):(leftEdge);
      newTop    = (IS_TOP   )?(ARG_TOP   ):(topEdge);

      if ((newLeft==leftEdge) && (newTop==topEdge) && (newWidth==width) && (newHeight==height)) {
         verbose("No window movement needed.\n");
      }
      else {
         verbose("Expected window dimensions:\n"
                 "   Width: %5i,    Height: %5i, Left: %5i, Top: %5i\n"
                 "\n",
                 newWidth,newHeight,newLeft,newTop);
         /* test if new window box would fit into min/max and screen */
         while(TRUE) {
            /* does the new window fit into its own limits? */
            if (newWidth<minWidth) { error("Width %i is too small, must be between %i and %i\n",newWidth,minWidth,maxWidth); break; }
            if (newWidth>maxWidth) { error("Width %i is too large, must be between %i and %i\n",newWidth,minWidth,maxWidth); break; }
            if (newHeight<minHeight) { error("Height %i is too small, must be between %i and %i\n",newHeight,minHeight,maxHeight); break; }
            if (newHeight>maxHeight) { error("Height %i is too large, must be between %i and %i\n",newHeight,minHeight,maxHeight); break; }
            /* does the new window fit into the screen? */
            if (newWidth>scrWidth) { error("Width %i is too large for screen, must be less equal %i\n",newWidth,scrWidth); break; }
            if (newHeight>scrHeight) { error("Height %i is too large for screen, must be less equal %i\n",newHeight,scrHeight); break; }
            /* does the new window position fit into the screen? */
            if ((newLeft+newWidth)>scrWidth) { error("Left %i plus Width %i is too large for screen, must be less equal %i\n",newLeft,newWidth,scrWidth); break; }
            if ((newTop+newHeight)>scrHeight) { error("Top %i plus Height %i is too large for screen, must be less equal %i\n",newTop,newHeight,scrHeight); break; }

            ChangeWindowBox(win,newLeft,newTop,newWidth,newHeight);

            verbose("New window box is set.\n");
            break;
         }
      }
      FreeArgs(rdargs);
   }
   else {
      error("Usage: %s %s\n",argv[0],ARGS_TEMPLATE);
   }
}



/* ---------------------------------------------------------------- */
void error(STRPTR fmt,...) {
   va_list a;
   va_start(a,fmt);
   vfprintf(stdout,fmt,a);
   va_end(a);
}

void verbose(STRPTR fmt,...) {
   va_list a;
   if (!ARG_QUIET) {
      va_start(a,fmt);
      vfprintf(stdout,fmt,a);
   }
   va_end(a);
}


