
/*                            FindDisk3.3

     Author      : Ross MacGregor
     Date        : 10/04/88
     Last Update : 20 Apr 91
     Comments    : This is a public domain program.                        */

/* Thanks must go to Radical Eye's dfc from which much of the following
   intuition stuff was ported */

#include <intuition/intuition.h>
#include <functions.h>
#include <exec/exec.h>
#include <exec/execbase.h>
#include <libraries/dosextens.h>

#define MAXSTRGADL 40
#define MAXPATHLEN 80  /*  *** ALSO DEFINED IN fd3.c *** */

#define TITLE "FindDisk3.3"
#define BLURB "   PDSoft 1991  Ross MacGregor"
/*
 *   These are the various globals this routine uses.
 */
struct StandardPacket *gpacket ;   /* packet to send various things */
struct IntuiMessage *message ;     /* the message we are working on */
struct Gadget *gadad ;             /* address of gadget from message */
struct Window *window ;            /* our window */
struct MsgPort *port ;             /* I/O port for dos communication */
struct IntuitionBase *IntuitionBase ;
                                   /* we need Intuition */
struct GfxBase *GfxBase ;          /* and graphics */

long output;
char strbuf[MAXSTRGADL+1] ;            /* this buffer holds fd input */
int  newcheck;
int  shdsp,subdir;

extern char *nullstr;
extern char dlpath[];

/*
 *   Always use topaz 80, and let's define an intuition buffer for our
 *   general string writing stuff.
 */
struct TextAttr myfont = {(STRPTR)"topaz.font", TOPAZ_EIGHTY, 0, 0 };
struct IntuiText intuitext = {1, 0, JAM2, 0, 0, &myfont} ;
/*
 *   Some defines setting the sizes of various things.  Play with these to
 *   resize things.  Too bad string gadgets still have problems with large
 *   fonts.
 */

#define WIDEGADG 85
#define SWITCHGADG 134
#define STRGADG 264
#define CURGADG 176
#define GADGHEIGHT 13

#define LINE1 13
#define LINE2 LINE1+13
#define LINE3 LINE2+16
#define LINE4 LINE3+GADGHEIGHT
#define LINE5 LINE4+GADGHEIGHT+6
#define LINE6 LINE5+GADGHEIGHT

#define COL1 8
#define COL2 COL1+WIDEGADG+10
#define COL3 COL2+WIDEGADG+10
#define MID  COL2+45

#define STRSTART COL1

#define WINDOWHEIGHT LINE6+GADGHEIGHT+4
#define WINDOWWIDTH COL3+WIDEGADG+10

/*
 *   Now, some defines to assist in declaring a few things, and
 *   centering strings, and the like.  These macros make the Intuition
 *   crap a lot easier to put together.
 */
#define makeintuitext(name,string,size) struct IntuiText name={1,0,JAM2,\
   (1+size-8*(sizeof(string)-1))/2,3,&myfont,(UBYTE*)string}

#define makebox(name,pname,width,height,x,y,pen1,pen2) \
    short pname[2][6]={0,height,0,0,width,0, \
                       width,0,width,height,0,height}; \
    struct Border name[2]= {x,y,pen1,0,JAM2,3,pname,&name[1], \
                            x,y,pen2,0,JAM2,3,pname[1],NULL }

#define makegadg(name,prev,xpos,ypos,text,ch) struct Gadget name={prev,\
   xpos,ypos,WIDEGADG,GADGHEIGHT,GADGHCOMP,RELVERIFY,BOOLGADGET,\
   (APTR)&widebox,NULL,&text,NULL,NULL,ch}

#define makeswgadg(name,prev,xpos,ypos,text,ch) struct Gadget name={prev,\
   xpos,ypos,SWITCHGADG,GADGHEIGHT,GADGHCOMP,RELVERIFY,BOOLGADGET,\
   (APTR)&swbox,NULL,&text,NULL,NULL,ch}

/*
 *   Now we declare all of our structures with the above macros.
 *   First, the text for our gadgets, and then the gadgets.  No sweat.
 */

makeintuitext(sdirtext,"SaveDir",WIDEGADG);
makeintuitext(updatetext,"UpdateDL",WIDEGADG);
makeintuitext(loadtext,"LoadDL",WIDEGADG);
makeintuitext(savetext,"SaveDL",WIDEGADG);
makeintuitext(newtext,"NewDL",WIDEGADG);
makeintuitext(deletetext,"RemDir",WIDEGADG);
makeintuitext(subdirtext, "Sub-Directories",SWITCHGADG);
makeintuitext(rootdirtext,"Root Directory ",SWITCHGADG);
makeintuitext(stddsptext,"Standard Display",SWITCHGADG);
makeintuitext(shdsptext, "   Short Form   ",SWITCHGADG);


makebox(swbox,tn4,SWITCHGADG-1,GADGHEIGHT-1,0,0,2,1);
makebox(widebox,tn2,WIDEGADG-1,GADGHEIGHT-1,0,0,2,1);
makebox(strbox,tn3,STRGADG+4,GADGHEIGHT-1,-2,-2,1,2);
makebox(curbox,tn1,CURGADG+6,GADGHEIGHT-2,-4,-2,1,2);

makeswgadg(dirgadg,NULL,COL1+1,LINE6,rootdirtext,'w');
makeswgadg(dspgadg,&dirgadg,MID,LINE6,stddsptext,'x');
makegadg(sdirgadg,&dspgadg,COL1,LINE3,sdirtext,'d');
makegadg(updategadg,&sdirgadg,COL1,LINE4,updatetext,'u');
makegadg(loadgadg,&updategadg,COL2,LINE3,loadtext,'l');
makegadg(savegadg,&loadgadg,COL2,LINE4,savetext,'s');
makegadg(newgadg,&savegadg,COL3,LINE3,newtext,'n');
makegadg(delgadg,&newgadg,COL3,LINE4,deletetext,'r');

/*
 *   We need two last gadgets, the string gadgets, and their associated
 *   special info structure.
 */
struct StringInfo strinfo={(UBYTE*)strbuf,NULL,0,MAXSTRGADL};
struct Gadget strgadg={&delgadg,STRSTART+6,LINE2,STRGADG,
   GADGHEIGHT-5,GADGHCOMP,STRINGCENTER|RELVERIFY,STRGADGET,(APTR)&strbox,
   NULL,NULL,NULL,(APTR)&strinfo,'f'};

struct StringInfo curinfo={(UBYTE*)dlpath,NULL,0,MAXPATHLEN};
struct Gadget curgadg={&strgadg,COL2+1,LINE5,CURGADG,
   GADGHEIGHT-5,GADGHCOMP,RELVERIFY,STRGADGET,(APTR)&curbox,
   NULL,NULL,NULL,(APTR)&curinfo,'c'};

/*
 *   Now we have our window structure.  Initially not resizeable.
 */
struct NewWindow newwindow = {200,20,WINDOWWIDTH,WINDOWHEIGHT,0,1,
   CLOSEWINDOW|ACTIVEWINDOW|GADGETDOWN|GADGETUP,
   WINDOWDEPTH|WINDOWCLOSE|WINDOWDRAG|SMART_REFRESH|ACTIVATE,
   &curgadg,NULL,(UBYTE *)TITLE,NULL,NULL,-1,-1,-1,-1,WBENCHSCREEN};


void cleanup(), setargs();

#define print(s) draw(to34(s,nullstr), COL1, LINE1)

void draw(s, x, y)
char *s ;
int x, y ;
{
   intuitext.IText = (UBYTE *)s ;
   PrintIText(window->RPort, &intuitext, (long)x, (long)y) ;
}

/*
 *   This routine looks at the global message and returns a character
 *   indicating the selected gadget.  This gives us easy equivalence
 *   of gadgets to vanillakeys, for instance.  This also replymsg()'s
 *   the message.
 */
int getop() {
   register long class ;
   register int op ;
   short code ;

   class = message->Class ;
   code = message->Code ;
   op = ' ' ;
   gadad = (struct Gadget *)(message->IAddress) ;
   ReplyMsg(message) ;
   message = NULL ;
   if (class == CLOSEWINDOW)
      op = 'q' ;
   else if (class == GADGETDOWN || class == GADGETUP)
      op = gadad->GadgetID ;
   else if (class == ACTIVEWINDOW)
   {
      op = 'a';
      gadad = NULL ;
   }
   return(op) ;
}

int disposemsgs() {
   register int op = 0 ;

   while (message = (struct IntuiMessage *)
                        GetMsg(window->UserPort))
      op = getop() ;
   return(op) ;
}


/*
 *   This routine pads 2 strings out to 34 characters.  Used to write to
 *   the top line of the window.
 */
static char ibuf[35] ;
char *to34(s1,s2)
register char *s1, *s2 ;
{
   register int i = 0 ;
   register char *p = ibuf ;

   while (*s1 != 0)
      p[i++] = *s1++ ;
   while (*s2 != 0)
      p[i++] = *s2++ ;
   while (i < 34)
      p[i++] = ' ' ;
   p[i]='\0';
   return(p) ;
}

extern char *errorstr;
void error(s)
register char *s;
{
   if (*s == '!' || !window) {
      if (output) {
         Write(output, errorstr, (long)strlen(errorstr)) ;
         Write(output, "\n",1L);
      }
      cleanup() ;
   }
   DisplayBeep(NULL) ;
   draw(to34(errorstr,s), COL1, LINE1) ;
   errorstr=nullstr;
}


/*
 *   This is our exit routine.  It frees the drives, deletes the ports,
 *   buffers, closes the window, and libraries.  Then it exits.
 */
void cleanup()
{
   register int i ;

   if (gpacket)
      FreeMem(gpacket, (long)sizeof(struct StandardPacket)) ;
   if (port)
      DeletePort(port) ;
   if (window)
      CloseWindow(window) ;
   if (GfxBase)
      CloseLibrary(GfxBase) ;
   if (IntuitionBase)
      CloseLibrary(IntuitionBase) ;
   exit(0) ;
}


/*
 *   This routine turns on a particular gadget.
 */
void turnon(g)
register struct Gadget *g ;
{
   if (g->Flags & GADGDISABLED) {
      SetAPen(window->RPort, 0L) ;
      RectFill(window->RPort, (long)g->LeftEdge, (long)g->TopEdge,
                              (long)g->LeftEdge+g->Width-1,
                              (long)g->TopEdge+g->Height-1) ;
      SetAPen(window->RPort, 1L) ;
      OnGadget(g, window, NULL) ;
   }
}

/*
 *   This routine turns off a particular gadget.
 */
void turnoff(g)
register struct Gadget *g ;
{
   if (!(g->Flags & GADGDISABLED))
      OffGadget(g, window, NULL) ;

}


/* Here at the main we pull in variables and call routines frow fd3.c */

extern char *dldisk, *dltemp, *sdir_pat;
extern char **glargv;
extern int  glargc, con_print_line;
char *yaargv[17];

char *getenv(), *strchr(), *firstchar();
struct DeviceNode *finddosnode();
void get_dlpath();

void main(argc, argv)
int argc ;
char *argv[] ;
{
  int op, rc ;
  char *p;

  output = (long)Output() ;
  errorstr=nullstr;

  glargv=argv;
  glargc=argc;

  if( finddosnode("ENV") )
  {
    dldisk=getenv("env:dldisk",dldisk);
    dltemp=getenv("env:dltemp",dltemp);
    sdir_pat=getenv("env:dldrive",sdir_pat);
  }
  get_dlpath();

  if( argc>1 )
  {
    if( finddisk() )
      error("!");
    return;
  }

/*
 *   We try and open things up!  First intuition, then graphics,
 *   then our window and an I/O port.  If any of these fail, we simply
 *   exit.
 */
  if( (IntuitionBase = (struct IntuitionBase *)OpenLibrary(
        "intuition.library",36L))==NULL )
  {
    if( (IntuitionBase = (struct IntuitionBase *)OpenLibrary(
         "intuition.library",33L))==NULL )
    {
      errorstr="Couldn't open window";
      error("!");
    }
    swbox[0].FrontPen=1;
    swbox[1].FrontPen=2;

    widebox[0].FrontPen=1;
    widebox[1].FrontPen=2;

    strbox[0].FrontPen=2;
    strbox[1].FrontPen=1;

    curbox[0].FrontPen=2;
    curbox[1].FrontPen=1;
  }

  if( (GfxBase = (struct GfxBase *)OpenLibrary(
        "graphics.library",0L))!=NULL &&
        (window=OpenWindow(&newwindow))!=NULL &&
      (port=CreatePort(0L, 0L)) &&
      (gpacket=(struct StandardPacket *)AllocMem(
              (long)sizeof(struct StandardPacket),MEMF_PUBLIC|MEMF_CLEAR)))
  {

    if( errorstr!=nullstr )
      error(nullstr);
    print(BLURB);
    draw("CurrentDL:",COL1+6,LINE5);
    if( !strcmp(dldisk,dlpath) )
      turnoff(&savegadg);
    if( tmpsize()<10 )
      turnoff(&updategadg);


/*
 *   Wait for a message.  After getting one,
 *   we drop into a case statement keying off what message it was.
 */
    while (1)
    {
       RefreshGList(&curgadg, window, NULL,2L) ;

       while ((message = (struct IntuiMessage *)
                      GetMsg(window->UserPort))==NULL)
          WaitPort(window->UserPort) ;
       op = getop() ;
       rc=1;
       switch(op)
       {
         case 'd' : if( rc=sdir() )
                      error(" SaveDir failed");
                    else
                      turnon(&updategadg);
                    break;

         case 'u' : if( rc=update() )
                      error(" Update failed");
                    else
                      turnoff(&updategadg);
                    break;

         case 'n': print(" NewDL: Are you sure (y/n) ?");
                   ActivateGadget(&strgadg, window, NULL) ;
                   newcheck=1;
                   break;

         case 'a' :  if (gadad == NULL )
                       ActivateGadget(&strgadg, window, NULL) ;
                     break ;

         case 'l' : if( rc=loaddl() )
                      error(" LoadDL failed");
                    else
                      turnon(&savegadg);
                    break;

         case 's' : if( rc=savedl() )
                    {
                      error(" SaveDL failed");
                      break;
                    }
                    turnoff(&updategadg);
                    turnoff(&savegadg);
                    break;

         case 'r' : if( rc=remove() )
                      if( rc==1)
                        error(" Specify volume to be removed:");
                      else
                        error(" RemDir failed");
                    break;

         case 'f' : if( newcheck )
                    {
                      rc=1;
                      newcheck=0;
                      if( *(firstchar(strbuf))=='y' )
                        if( newdl() )
                          print(" NewDL failed");
                        else
                          print(" Empty DiskList created.");
                      else
                        print(" NewDL aborted.");
                      break;
                    }

                    if( *(p=firstchar(strbuf)) )
                    {
                      print(" Searching...");
                      setargs(p);
                      if( rc=finddisk() )
                      {
                        error(nullstr);
                        break;
                      }
                      if( !con_print_line )
                      {
                        print(" Not found.");
                        rc=1;
                      }
                    }
                    else
                    {
                      error(" No search strings given.");
                      rc=1;
                    }
                    break;

         case 'w':  subdir=!subdir;
                    if( subdir )
                      dirgadg.GadgetText=&subdirtext;
                    else
                      dirgadg.GadgetText=&rootdirtext;
                    RefreshGList(&dirgadg, window, NULL,1L) ;
                    break;

         case 'x':  shdsp=!shdsp;
                    if( shdsp )
                      dspgadg.GadgetText=&shdsptext;
                    else
                      dspgadg.GadgetText=&stddsptext;
                    RefreshGList(&dspgadg, window, NULL,1L) ;
                    break;

       }

       if( !rc )
         print(BLURB);

       *strbuf='\0';
       if (op == 'q')
            break ;

    } /* while */

  }
  else
  {
    errorstr="Couldn't open window";
    error("!");
  }
  cleanup() ;
}

void setargs(s)
  char *s;
{
  char *p;

  for(glargc=1; glargc<=17; glargc++)
    if( p=strchr(s,' ') )
    {
      *p='\0';
      yaargv[glargc]=s;
      if( *(s=firstchar(p+1))=='\0' )
        break;
    }
    else
    {
      yaargv[glargc]=s;
      break;
    }
  glargv=yaargv;
  glargc++;
}

