/**************************************************************************
*     M E N U   E X A M P L E    P R O G R A M   -   JOHN DRAPER
*   (originally it was anyway)
*
*  Modified (mangled) by Steve Berry 7/77/88
*
***************************************************************************/

#include <libraries/arpbase.h>
#include "flist.h"

void *OpenLibrary();
struct Window *OpenWindow();
struct IntuiMessage *GetMsg();
struct Window *BuildSysRequest();
extern void Cleanup(),scrprt(),getkey();
extern struct Gadget pg;
extern struct Window *winptr;

extern struct IntuiText TRUEtext;
extern struct Window *winptr;
extern struct Screen *scrptr;
extern struct RastPort *rp;
extern struct FileLock *lock, olddir;
extern long line, numfiles, collum, first;
extern char (*fname[MAXDIR])[FCHARS];
extern char (*finfo[MAXDIR])[4];
extern char conline[256];
long top;

/***************************************************************************
                     M E N U      D E F I N I T I O N S
***************************************************************************/

#define NUM_MENUS 3

/* Copies of this structure will get "stamped" into many more */
/* Allocated later */

struct IntuiText generic = {
  0, 1,                        /* Bluepen, Whitepen */
  JAM2, 5,                     /* mode,  LeftEdge */
  0, NL,                       /* Top (to be filled later), Font */
  NL,                          /* Name (to be filled later) */
  NL                           /* Next one */
};

/* Menu numbers */

#define PROJ_MENU 0
#define DIR_MENU  1
#define SORT_MENU 2

/* Menu Widths */

#define FIL_WIDTH   80
#define DIR_WIDTH   100
#define SORT_WIDTH  120
#define ITEM_WIDTH  150
#define REQ_WIDTH   100

int item_widths[ NUM_MENUS ] = {150,250,150};

/* All items in these menus has the following flags set */

#define BOX_FILL    ITEMTEXT | ITEMENABLED | HIGHBOX     
#define BLACK_FILL  COMMSEQ | ITEMTEXT | ITEMENABLED | HIGHCOMP
#define HAS_CHECKS  COMMSEQ | ITEMTEXT | ITEMENABLED | HIGHCOMP | CHECKIT

                            /** FILE MENU ITEMS  **/
#define NUM_FILE_ITEMS  4
#define DO_ITEM         0
#define ICON_ITEM       1
#define ABOUT_ITEM      2
#define QUIT_ITEM       3

struct MenuItem  file_items[NUM_FILE_ITEMS];
struct IntuiText file_names[NUM_FILE_ITEMS];

char  *filemenu_names[] = {
   "Execute REXX",
   "Iconify",
   "About",
   "Quit"
};

char *filemenu_short[] = {
    "E",
    "I",
    "B",
    "Q"
};

struct Menu fmenu = {
  NL,                        /* Pointer to next menu, fill in later */
  0, 0, FIL_WIDTH, 10,       /* LeftEdge, TopEdge, Width, Height */
  MENUENABLED,               /* FLAGS */
  "Project",                 /* Menu name */
  NL                         /* First item structure */
};

/************ Next menu ****************/

                            /** FILE MENU ITEMS  **/
#define NUM_DIR_ITEMS   7
#define PARENT_ITEM     0
#define CHANGE_ITEM     1
#define ARP_ITEM        2
#define REGET_ITEM      3
#define KILL_ITEM       4
#define RENAME_ITEM     5
#define MAKEDIR_ITEM    6

struct MenuItem  dir_items[NUM_DIR_ITEMS];
struct IntuiText dir_names[NUM_DIR_ITEMS];

char  *dirmenu_names[] = {
    "  Parent Directory",
    "  Change Directory",
    "  ARP Change to Volume",
    "  Get Directory",
    "  Kill File",
    "  Rename File",
    "  Make Dir"
};

char *dirmenu_short[] = {
    "P",
    "D",
    "A",
    "G",
    "K",
    "R",
    "N"
};

struct Menu dmenu = {
  NL,                        /* Pointer to next menu, fill in later */
  100, 0, DIR_WIDTH, 10,     /* LeftEdge, TopEdge, Width, Height */
  MENUENABLED,               /* FLAGS */
  "Directory",               /* Menu name */
  NL                         /* First item structure */
};

/************ Next menu ****************/

                            /** FILE MENU ITEMS  **/
#define NUM_SORT_ITEMS  5
#define ALPHABET_ITEM   0
#define SIZE_ITEM       1
#define TIME_ITEM       2
#define PATTERN_ITEM    3
#define DAY_ITEM        4

struct MenuItem  sort_items[NUM_SORT_ITEMS];
struct IntuiText sort_names[NUM_SORT_ITEMS];

char  *sortmenu_names[] = {
    "Alphabeticly",
    "By Size",
    "By Time",
    "By Pattern",
    "By Day"
};

char *sortmenu_short[] = {
    "S",
    "Z",
    "T",
    "O",
    "Y"
};

struct Menu smenu = {
  NL,                        /* Pointer to next menu, fill in later */
  200, 0, SORT_WIDTH, 10,    /* LeftEdge, TopEdge, Width, Height */
  MENUENABLED,               /* FLAGS */
  "Sort List",           /* Menu name */
  NL                         /* First item structure */
};

/***************************************************************************
                   AUTO REQUEST INTUITEXT STRUCTURES
***************************************************************************/

struct IntuiText Auto3 = {
   REDP,  WHTP,
   JAM1,  15,
   35,    NL,
   "Freely Redistributable for noncomercial purposes. ", NULL
};

struct IntuiText Auto2 = {
   REDP,  WHTP,
   JAM1,  15,
   17,    NL,
   " Inspired by the PD Flist on IBM mainframes ", &Auto3
};

struct IntuiText AboutText = {
   REDP,  WHTP,
   JAM1,  20,
   5,    NL,
   " Flist was written by Steve (Raz) Berry ", &Auto2  
};

/***************************************************************************
                  M A I N     P R O G R A M     M O D U L E
***************************************************************************/
long mousey, mousex;

menu()
{
    ULONG    class;     /* Message class from Intuition                  */
    USHORT   code;      /* Menu code info from Intuition                 */
    struct MenuItem *item;
    long     gadown=FALSE;
    struct IntuiMessage *message;
    struct Gadget *igad;
    register short  prevy=0;
    register int i,temp;
    char buf[256];

    mousey = 0;
    mousex = 0;

    fmenu.FirstItem = &file_items[0];
    fmenu.NextMenu = &dmenu;
    dmenu.NextMenu = &smenu;

    NewMenu( &fmenu, filemenu_names, filemenu_short, file_items, file_names,
            NUM_FILE_ITEMS, item_widths[0], BLACK_FILL);

    dmenu.FirstItem = &dir_items[0];

    NewMenu( &dmenu, dirmenu_names, dirmenu_short, dir_items, dir_names,
            NUM_DIR_ITEMS, item_widths[1], HAS_CHECKS);

    smenu.FirstItem = &sort_items[0];

    NewMenu( &smenu, sortmenu_names, sortmenu_short, sort_items, sort_names,
            NUM_SORT_ITEMS, item_widths[2], BLACK_FILL);

/*    sort_items[0].MutualExclude = 0xfffe; */

    top = 0;     /* this is the pointer to the first file on the screen */
  
    SetMenuStrip(winptr, &fmenu);      /* Set up the menu here */

    ShowTitle(scrptr,TRUE);      /* Do show the screen Title. */

    sort(0);                     /* sort the list alphabetically */
    refresh();
    drawcur();

    for (;;)
    {
      if ((message = (struct IntuiMessage *)GetMsg(winptr->UserPort)) == 0L)  {
          Wait(1L<<winptr->UserPort->mp_SigBit);
          continue;
      }

        class = message->Class;
        code = message->Code;
        igad = (struct Gadget *)message->IAddress;
        mousey = message->MouseY;
        mousex = message->MouseX;

        switch (class) {

            case RAWKEY:
                getkey(message);    /* message is replied to in routine */
                break;          

            case MOUSEMOVE: 
                ReplyMsg(message);
                if(gadown){
#ifdef KILLEXTRA
                        /* get rid of any extra messages */

                        while((message = (struct IntuiMessage *)GetMsg(winptr->UserPort)) != 0L) {
                                mousey = message->MouseY;
                                ReplyMsg(message);
                                if((prevy<mousey)&&(line<numfiles))
                                top++;
                                if((prevy>mousey)&&(top>0))
                                        top--;
                                prevy = mousey;  
                        } 
#endif
                        if((prevy<mousey)&&(line<numfiles-1)){
                                        line++;
                                        top++;
                        }
                        if((prevy>mousey)&&(top>0)){
                                if (line>0)
                                        line--;
                                top--;
                        }
                        prevy = mousey;    
                        temp = numfiles-top;
                        scrprt(temp,top);
                }
                break;
                
        case GADGETUP: 
                ReplyMsg(message);
                drawline(collum,TRUE);
                drawcur();
                gadown = FALSE;
                break;

        case GADGETDOWN:
                ReplyMsg(message);
                blankcur();
                switch ( i = igad->GadgetID) {
                    case FGAD: /* the prop gadget here... */
                        gadown = TRUE;
                        strcpy(buf,conline);
                        conline[first] = 0;
                        drawline(collum,TRUE);
                        strcpy(conline,buf);
                        drawline(collum,TRUE);
                        break;
                }
                break;

        case CLOSEWINDOW: 
                ReplyMsg(message);
                Cleanup();
                exit(0);
                break;

        case MENUPICK:
                ReplyMsg(message);
                blankcur();
                while (code != MENUNULL) {
#ifdef DEBUG
    sprintf(buf,"Code is %ld Menunum is %ld",code, MENUNUM(code));
    auto_req(buf);
#endif
                    domenu(MENUNUM(code), ITEMNUM(code),
                        SUBNUM(code));
                    item = ItemAddress(&fmenu, MENUNUM(code));
                    if (item->NextSelect == code)
                        break;
                    code = item->NextSelect;
                    item->NextSelect = MENUNULL;
                }
                drawcur();
                break;

        case MOUSEBUTTONS: 
                ReplyMsg(message);
                break;

        }   /* Case */
   }  /* for */
}   /* End of Main */

/***************************************************************************
                   C R E A T E    A    N E W    M E N U
***************************************************************************/
NewMenu ( menu, item_names,  item_short, menu_items, menu_text, 
        num_items, Mwidth, flag)

struct Menu      *menu;           /* Menu structure                       */
char             *item_names[];   /* Pointer to array of item names       */
char             *item_short[];   /* Pointer to array of shortcut char    */
struct MenuItem  menu_items[];    /* pointer to array of structures       */
struct IntuiText menu_text[];     /* Pointer to array of text structures  */
int               num_items;      /* Number of items                      */
int               Mwidth;         /* Menu Width */
long                flag;         /* Special Item flag for ALL items */
{
    int i;
    int height = 0;

    for (i=0; i< num_items; i++) {

        menu_text[i] = generic;              /* stamp generic template */
        menu_text[i].IText = item_names[i];          /* mv string ptrs */
        menu_items[i].NextItem = &menu_items[i+1];  /* Lnk to nxt item */
        menu_items[i].TopEdge = 10 * i;            /* Top rect of item */
        menu_items[i].LeftEdge = 2;
        menu_items[i].Height = 8;
        menu_items[i].ItemFill = (APTR)&menu_text[i];
        menu_items[i].Width = Mwidth;
        menu_items[i].MutualExclude = 0;
        menu_items[i].Command = item_short[i][0];
        menu_items[i].Flags = (USHORT)flag;
        menu_items[i].SubItem = NULL;
        menu_items[i].NextSelect = MENUNULL;
        height += 10;
    }
    menu_items[num_items-1].NextItem = NULL;
    menu->Height = height;
}

/* DO THE MENU SELECTIONS */

domenu(menu, item, subitem)
int  menu, item, subitem;
{
    char buf[256];
    int i;

    switch (menu) {

        case PROJ_MENU: 
            switch (item) {

               case  DO_ITEM: 
                    dorexx();
                    break;

               case  ICON_ITEM: 
                    tticon();
                    break;

               case  QUIT_ITEM:     
                    if(scrptr->FirstWindow->NextWindow != NULL) 
                        auto_req("Kill all other Applications first");
                    else {
                        Cleanup();
                        exit(0);
                    }
                    break;

               case  ABOUT_ITEM: 
                    AutoRequest(winptr, &AboutText, &TRUEtext, &TRUEtext, 
                                0L, 0L, 450L, 80L );
                    break;
            } 
            break;

        case DIR_MENU:

            for (i=0;i<NUM_DIR_ITEMS;i++)
                dir_items[i].Flags = HAS_CHECKS;

            switch (item) {

                case PARENT_ITEM:
                    parent();
                    refresh();
                    break;

                case CHANGE_ITEM:
                    if (*finfo[line][0] < 0){
                        sprintf(buf,"%s Not a directory",fname[line]);
                        auto_req(buf);
                    }else {
                        changedir(fname[line]);
                        refresh();
                    }
                    break;

                case ARP_ITEM:
                    if (Wbargs() == 0){
                        UnLock(olddir);
                        refresh();
                    }
                    break;

                case REGET_ITEM:
                    getdir();
                    refresh();
                    break;

                case KILL_ITEM:
                    kill(fname[line]);
                    refresh();
                    break;

                case RENAME_ITEM:
                    rename_file(fname[line]);
                    refresh();
                    break;

                case MAKEDIR_ITEM:
                    make_dir();
                    refresh();
                    break;
            }
            break;

        case SORT_MENU:
        
            switch (item) {

                case ALPHABET_ITEM:
                    sort(0);
                    refresh();
                    break;

                case SIZE_ITEM:
                    sort(1);
                    refresh();
                    break;

                case TIME_ITEM:
                    sort(2);
                    refresh();
                    break;

                case PATTERN_ITEM:
                    sort(3);
                    refresh();
                    break;

                case DAY_ITEM:
                    sort(4);
                    refresh();
                    break;

            }
            break;
    }
}

