/***************************************************************************
 * 2.0 NewMenus demo program (requires WorkBench 2.0, v37 or greater)      *
 *    written by Paul Miller for AmigaWorld Tech Journal                   *
 ***************************************************************************/

#include <exec/types.h>
#include <intuition/intuition.h>
#include <libraries/gadtools.h>

#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include <clib/gadtools_protos.h>


struct GfxBase *GfxBase = NULL;
struct IntuitionBase *IntuitionBase = NULL;
struct Library *GadToolsBase = NULL;
struct Library *DiskfontBase = NULL;

struct Screen *screen = NULL;
struct Window *window = NULL;
struct Menu *menu = NULL;
struct TextAttr *textattr = NULL;
void *vi = NULL;


/* function prototypes for routines accessed with NewMenu UserData */
void NewProject(void);
void OpenProject(void);
void CloseProject(void);
void SaveProject(void);
void SaveAsProject(void);
void PrintProject(void);
void Quit(void);


/* NewMenu menu declaration */
struct NewMenu newmenu[] =
{
   {NM_TITLE, "Project",     0 , 0, 0, 0},
   {  NM_ITEM, "New...",    "N", 0, 0, NewProject},
   {  NM_ITEM, NM_BARLABEL,  0 , 0, 0, 0},
   {  NM_ITEM, "Open...",   "O", 0, 0, OpenProject},
   {  NM_ITEM, "Close",      0,  0, 0, CloseProject},
   {  NM_ITEM, NM_BARLABEL,  0 , 0, 0, 0},
   {  NM_ITEM, "Save",      "S", 0, 0, SaveProject},
   {  NM_ITEM, "Save As...","A", 0, 0, SaveAsProject},
   {  NM_ITEM, NM_BARLABEL,  0 , 0, 0, 0},
   {  NM_ITEM, "Print",     "P", 0, 0, PrintProject},
   {  NM_ITEM, NM_BARLABEL,  0 , 0, 0, 0},
   {  NM_ITEM, "Quit...",   "Q", 0, 0, Quit},

   {NM_TITLE, "Edit",        0 , 0, 0, 0},
   {  NM_ITEM, "Undo",      "Z", 0, 0, 0},
   {  NM_ITEM, NM_BARLABEL,  0 , 0, 0, 0},
   {  NM_ITEM, "Cut",       "X", 0, 0, 0},
   {  NM_ITEM, "Copy",      "C", 0, 0, 0},
   {  NM_ITEM, "Paste",     "V", 0, 0, 0},

   {NM_END, 0, 0, 0, 0, 0},
};


/* function prototypes */
void setup(void);
void closedown(void);
void open_libraries(void);
void close_libraries(void);
void abort(char *);
void handle_input(void);
void handle_menu(UWORD);

void main(argc, argv)
int argc;
char *argv[];
{
   setup();
   handle_input();
}

void setup()
{
   open_libraries();

   /* attempt to get access to the WorkBench screen */
   screen = LockPubScreen(NULL);
   if (!screen)
      abort("Couldn't get access to the WorkBench screen.");

   vi = GetVisualInfo(screen, TAG_DONE);
   if (!vi)
      abort("Couldn't get public screen VisualInfo.");

   /* use the Screen's default font for the menu text */
   textattr = screen->Font;

   /* build the menu-strip */
   menu = CreateMenus(newmenu, GTMN_FrontPen, 0, TAG_DONE);
   if (!menu)
      abort("Couldn't create the menu strip.");

   if (!LayoutMenus(menu, vi, GTMN_TextAttr, textattr, TAG_DONE))
      abort("Couldn't lay-out the menu stirp.");

   window = OpenWindowTags(NULL, WA_Width, 400,
                           WA_InnerHeight, 100,
                           WA_Activate, TRUE,
                           WA_DragBar, TRUE,
                           WA_CloseGadget, TRUE,
                           WA_DepthGadget, TRUE,
                           WA_SizeGadget, TRUE,
                           WA_SimpleRefresh, TRUE,
                           WA_IDCMP, CLOSEWINDOW | REFRESHWINDOW | MENUPICK,
                           WA_MinWidth, 50,
                           WA_MinHeight, 50,
                           WA_Title, "NewMenu Demo",
                           TAG_DONE);
   if (!window)
      abort("Couldn't open window.");

   SetMenuStrip(window, menu);
}

void open_libraries()
{
   GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 37L);
   if (!GfxBase)
      abort("Couldn't open graphics.library. 2.0 v37 or above required.");

   IntuitionBase = (struct IntuitionBase *)
                             OpenLibrary("intuition.library", 37L);
   if (!IntuitionBase)
      abort("Couldn't open intuition.library. 2.0 v37 or above required.");

   DiskfontBase = OpenLibrary("diskfont.library", 36L);
   if (!DiskfontBase)
      abort("Couldn't open diskfont.library. 2.0 v36 or above required.");

   GadToolsBase = OpenLibrary("gadtools.library", 37L);
   if (!GadToolsBase)
      abort("Couldn't open gadtools.library. 2.0 v37 or above required.");
}

void close_libraries()
{
   if (GadToolsBase) CloseLibrary(GadToolsBase);
   if (DiskfontBase) CloseLibrary(DiskfontBase);
   if (IntuitionBase) CloseLibrary((struct Library *)IntuitionBase);
   if (GfxBase) CloseLibrary((struct Library *)GfxBase);
}

void closedown()
{
   if (window)
   {
      ClearMenuStrip(window);
      CloseWindow(window);
   }
   if (GadToolsBase)
   {
      FreeMenus(menu);
      if (vi) FreeVisualInfo(vi);
   }
   if (screen) UnlockPubScreen(NULL, screen);

   close_libraries();
}

void abort(txt)
char *txt;
{
   closedown();
   if (txt)
      puts(txt);
   exit(0);
}

void handle_input()
{
   struct IntuiMessage *message;
   ULONG class;
   UWORD code;

   while (1)
   {
      WaitPort(window->UserPort);
      while (message = GT_GetIMsg(window->UserPort))
      {
         class = message->Class;
         code = message->Code;

         GT_ReplyIMsg(message);

         switch (class)
         {
            case CLOSEWINDOW:
               printf("CLOSEWINDOW.\n");
               abort(NULL);
               break;
            case MENUPICK:
               handle_menu(code);
               break;
            case REFRESHWINDOW:
               GT_BeginRefresh(window);
               GT_EndRefresh(window, TRUE);
               break;
         }
      }
   }
}

void handle_menu(code)
UWORD code;
{
   struct MenuItem *item;
   void (*funcptr)(void);

   printf("MENUPICK:  ");

   /* traverse the selected-item list, calling functions attached by item's
      UserData pointer (if available) */

   while (code != MENUNULL)
   {
      item = ItemAddress(menu, code);

      /* does item have a function pointer in the UserData field? */
      funcptr = GTMENUITEM_USERDATA(item);
      if (funcptr)
         funcptr();
      else
         printf("NO FUNCTION (id=%d)  ", ITEMNUM(code));

      code = item->NextSelect;
   }
   printf("\n");
}

/* NewMenu UserData functions */

void NewProject()
{
   printf("NEW  ");
}

void OpenProject()
{
   printf("OPEN  ");
}

void CloseProject()
{
   printf("CLOSE  ");
}

void SaveProject()
{
   printf("SAVE  ");
}

void SaveAsProject()
{
   printf("SAVEAS  ");
}

void PrintProject()
{
   printf("PRINT  ");
}

void Quit()
{
   printf("QUIT\n\n");
   abort("");
}
