/*
(overscan.c)

   overscan
  ----------

  By Ari & Dov Freund - 20/11/87

Patches up the Intuition library so that sizable windows with MaxHeight = 200
(or 400 in lace), and screens with Height = 200 (or 400 in lace) will take
advantage of the overscan capability of Intuition V1.2.

To install the patch: overscan
To remove it:         overscan delete

Compile and assemble using Aztec C V3.4a:  cc overscan.c +C +D
                                           as overscan_lib.asm
Create a library file using the librarian: lb overscan.lib overscan_lib.o
Link using Aztec C V3.4a:                  ln +S overscan.o overscan.lib c.lib

You may also execute the overscan.make file.

See overscan.doc for more information.

*/

#undef ERROR
#ifdef AZTEC_C
   #ifndef _LARGE_DATA
      #define ERROR
   #else
      #ifndef _LARGE_CODE
         #define ERROR
      #endif
   #endif
   #ifdef ERROR

   /*
      If compiled with aztec and without the +C +D (large code and data)
      options, generate an error to alert the user and don't compile.
   */

   )Compile me with the +C +D options.
   )Compile me with the +C +D options.
   )Compile me with the +C +D options.
   )Compile me with the +C +D options.
   )Compile me with the +C +D options.
   )Compile me with the +C +D options.

   #endif
#endif

#ifndef ERROR

#include <libraries/dosextens.h>

#define OPENSCREEN -198L /* OpenScreen()'s vecter offset from IntuitionBase */
#define OPENWINDOW -204L /* OpenWindow()'s vector offset from IntuitionBase */

main(argc,argv)
int argc;
char *argv[];
{
   /* These externals belong to overscan.lib. */
   extern struct myvars{
      struct MsgPort port;    /* a message port left behind for subsequent
                                 invocations of overscan */
      BPTR myseg;             /* pointer to segment containing the patch */
      ULONG oldscreen;        /* pointer to Intuition's OpenScreen() */
      ULONG oldwindow;        /* pointer to Intuition's OpenWindow() */
      ULONG in_use;           /* flag indicating patch is/isn't in use */
   } data;
   extern UBYTE *IntuitionBase;
   extern char myname[];                     /* name of message port above */
   extern void screenpatch(), windowpatch(); /* See overscan_lib.asm. */

   UBYTE *OpenLibrary();
   struct Process *me, *FindTask();
   struct myvars *mydata, *FindPort();
   ULONG *seg, *prev;                        /* pointers to my segments */
   BPTR *mylast;                             /* the same */
   int install, err=0;                       /* flags */
   int count;                                /* count of disconnected segs */
   static   char delstrng[]="delete";
   char *rem=delstrng;

   printf(
"\nCopyright (c) 1987, by Ari & Dov Freund.\
\n\
\nThis program patchs the system so that most American programs\
\nwill use the extra lines on European (PAL) machines.\
\nTo install patch type: \"overscan\"\
\nTo delete  patch type: \"overscan delete\"\
\n\
\nThis program is shareware, if you like it send $5 to the authors at:\
\nAri Freund\
\n20 Yahalom st.\
\nPetach-Tikva\
\nISRAEL\n");

   /* Check for presence of "delete". */
   if(argc==2)
      do
         if(tolower(*rem)!=tolower(*argv[1]))
            err=1;
      while(argv[1]++,*rem++);

   if(argc>2||err){
      printf("\nUsage: %s [%s]\n",argv[0],delstrng);
      return;
   }

   /* Decide whether to install or remove. */
   install=argc==1;

   /* Get pointer to intuition library. */
   if(!(IntuitionBase=OpenLibrary("intuition.library",LIBRARY_VERSION))){
      printf("\nIntuition V1.2 required\n");
      return;
   }

   /* Look for my message port (if found, overscan is already installed). */
   mydata=FindPort(myname);

   /* If I should install but am already installed do nothing. */
   if(mydata&&install){
      printf("\nOverscan patch already installed.\n");
      goto exit;
   }
   /* If I should remove but am not installed do nothing. */
   else if(!install&&!mydata){
      printf("\nOverscan patch already removed.\n");
      goto exit;
   }

   /* Get pointer to my Process structure. */
   me=FindTask(NULL);

   /*
      Walk through my own SegList and disconnect (if needed) the segment
      containing the patch. This is done so that when I exit,
      the patch will not be unloaded. The external 'data.myseg' is set as
      a BPTR to this segment.
   */
   for(
    prev=
     (ULONG *)(&(*(struct CommandLineInterface *)(me->pr_CLI<<2)).cli_Module),
    seg=(ULONG *)(*prev<<2),
    *(mylast=&data.myseg)=NULL,
    count=0
   ;
    seg
   ;
    prev=seg,
    seg=(ULONG *)(*seg<<2)
   )
      if(       /* Should I disconnect any segments at all? */
       install                                         &&
                /* Is this the segment with the patch? */
       (ULONG)screenpatch<(ULONG)seg+*(seg-1)-4       &&
       (ULONG)screenpatch>(ULONG)seg
      ){
         count++;
               /* Disconnect the segment from the list */
         *prev=*seg;
               /* and chain it to the 'disconnected' list. */
         *mylast=(BPTR)((ULONG)seg>>2);
         *(mylast=(BPTR *)seg)=NULL;
               /* Allow loop to continue, skiping over the disconnected seg. */
         seg=prev;
      }

   if(install){            /* --> Install the patch. <-- */
      /*
         An incorrect number of disconnected segments
         means something is terribly wrong.
      */
      if(count!=1){
         printf("\ninternal fatal error\n");
         if(count>0)
                           /* Reconnect the disconnected segments and exit. */
            *prev=(ULONG)data.myseg;
      }
      else{                /* Save the old vectors and patch up Intuition. */
         Forbid();
         data.oldscreen=*(ULONG *)(IntuitionBase+OPENSCREEN+2);
         data.oldwindow=*(ULONG *)(IntuitionBase+OPENWINDOW+2);
         SetFunction(IntuitionBase,OPENSCREEN,screenpatch);
         SetFunction(IntuitionBase,OPENWINDOW,windowpatch);
         Permit();
         /*
            Link in the message port so it can be found later when we may
            want to remove the patch.
         */
         AddPort(&data.port);
         printf("\nOverscan patch installed.\n");
      }
   }
   else{                          /* --> Remove the patch. <-- */
      /*
         Connect the segment used by the existing patch to myself.
         This way, when I exit it will be unloaded together with me.
      */
      Forbid();
      /* If patch is in use don't remove it. */
      if(mydata->in_use){
         Permit();
         printf("\nOverscan patch in use, cannot remove it.\n");
         goto exit;
      }
      *prev=(ULONG)mydata->myseg;    /* Connect the segment to myself,  */
      RemPort(mydata);               /* unlink the message port,        */
                                     /* and restore the vectors.        */
      SetFunction(IntuitionBase,OPENSCREEN,mydata->oldscreen);
      SetFunction(IntuitionBase,OPENWINDOW,mydata->oldwindow);
      Permit();
      printf("\nOverscan patch deleted.\n");
   }

   /* Exit gracefully. */
exit:
   CloseLibrary(IntuitionBase);
}

#endif
