/**********************************************************************\
*                                                                      *
*  menu.c -- menu management functions                                 *
*                                                                      *
\**********************************************************************/

#include "defs.h"

CMD main_menu[] =
{
       submenu1, "File",             6,  71, 1, 5,
       submenu2, "Video",           72, 150, 2, 0,
       submenu3, "Fundamentals",   151, 285, 3, 1,
       submenu4, "Display",        286, 377, 4, 2,
       submenu5, "Miscellaneous",  378, 513, 5, 3,
       submenu6, "Utilities",      514, 605, 0, 4
};

CMD menu1[] =
{
       about_fg, "About Fastgraph   ", 7, 164, 1, 8,
     about_demo, "About This Demo   ", 7, 164, 2, 0,
     about_tech, "Technical Support ", 7, 164, 3, 1,
     about_docs, "Documentation     ", 7, 164, 4, 2,
     about_site, "Site Licenses     ", 7, 164, 5, 3,
    about_order, "Order By Phone    ", 7, 164, 6, 4,
     print_form, "Print Order Form  ", 7, 164, 7, 5,
          shell, "Shell to DOS      ", 7, 164, 8, 6,
   exit_program, "Exit              ", 7, 164, 0, 7
};

CMD menu2[] =
{
    about_modes, "Video Modes   ", 73, 210, 1, 4,
    auto_detect, "Autodetect    ", 73, 210, 2, 0,
 physical_pages, "Physical Pages", 73, 210, 3, 1,
  virtual_pages, "Virtual Pages ", 73, 210, 4, 2,
    coordinates, "Coordinates   ", 73, 210, 0, 3
};

CMD menu3[] =
{
      do_points, "Points     ", 152, 284, 1, 7,
       do_lines, "Lines      ", 152, 284, 2, 0,
       do_rects, "Rectangles ", 152, 284, 3, 1,
     do_circles, "Circles    ", 152, 284, 4, 2,
    do_ellipses, "Ellipses   ", 152, 284, 5, 3,
        do_text, "Text       ", 152, 284, 6, 4,
       do_paint, "Region Fill", 152, 284, 7, 5,
        do_clip, "Clipping   ", 152, 284, 0, 6
};

CMD menu4[] =
{
     do_bitmaps, "Bitmaps       ", 287, 434, 1, 3,
    do_transfer, "Transfer      ", 287, 434, 2, 0,
      do_scroll, "Scroll        ", 287, 434, 3, 1,
   view_graphic, "Display a File", 287, 434, 0, 2
};

CMD menu5[] =
{
       do_mouse, "Mouse    ", 379, 512, 1, 5,
    do_joystick, "Joystick ", 379, 512, 2, 0,
       do_sound, "Sound    ", 379, 512, 3, 1,
       do_music, "Music    ", 379, 512, 4, 2,
      do_editor, "Editor   ", 379, 512, 5, 3,
   do_histogram, "Histogram", 379, 512, 0, 4
};

CMD menu6[] =
{
 about_snapshot, "Snapshot ", 515, 604, 1, 2,
     about_clip, "Clip     ", 515, 604, 2, 0,
  about_convert, "Convert  ", 515, 604, 0, 1
};

int mouse_limits[] = {0,72,151,286,378,514,640};
int redraw = TRUE;
int selection = 0;

/**********************************************************************\
*                                                                      *
*  highlight option -- highlight an option on the main menu            *
*                                                                      *
\**********************************************************************/

void highlight_option(n)
{
   int y;

   y = menu_top + ptsize + 1;

   fg_setcolor(0);
   fg_rect(main_menu[n].x1,main_menu[n].x2,menu_top,menu_bottom-1);
   fg_setcolor(15);
   center_pstring(main_menu[n].menu_item,main_menu[n].x1,main_menu[n].x2,y);
}

/**********************************************************************\
*                                                                      *
*  horizontal_menu -- main menu containing submenus                    *
*                                                                      *
\**********************************************************************/

horizontal_menu(cmdtab,n,current,foregrnd,backgrnd,hilite_fgnd,hilite_bkgnd)
CMD cmdtab[];
int n, current;
int foregrnd, backgrnd;
int hilite_fgnd, hilite_bkgnd;
{
   register int i, k;
   int c;
   int found, new;
   int ymin, ymax;
   char l;

   if (current >= abs(n))
      return(ERR);

   ymin = menu_top;
   ymax = ymin + ptsize + 1;

   fg_mousevis(OFF);

   /* set up list of options */

   if (n < 0)
   {
      for (i = 0; i < abs(n); i++)
      {
         fg_setcolor(backgrnd);
         fg_rect(cmdtab[i].x1,cmdtab[i].x2,ymin,ymax);
         fg_setcolor(foregrnd);
         center_pstring(cmdtab[i].menu_item,cmdtab[i].x1,cmdtab[i].x2,ymax);
      }

      /* if we're just displaying the menu options, return */

      return(OK);
   }

   /* highlight current option */

   i = current;

   fg_setcolor(hilite_bkgnd);
   fg_rect(cmdtab[i].x1,cmdtab[i].x2,ymin,ymax);
   fg_setcolor(hilite_fgnd);
   center_pstring(cmdtab[i].menu_item,cmdtab[i].x1,cmdtab[i].x2,ymax);
   fg_mousevis(ON);

   /* choose an option */

   new = current;
   fg_setnum(OFF);
   flushkey();

   while (TRUE)
   {
      /* activate the corresponding vertical menu */

      c = (*cmdtab[i].menu_func)();

      /* cycle through choices */

      if (c == LEFT_ARROW || c == BS)
         new = cmdtab[i].prev;

      else if (c == RIGHT_ARROW || c == SPACEBAR)
         new = cmdtab[i].next;

      else if (c >= 0 && c <= n)
         new = c;

      else if (c == ESC)
      {
         exit_program();
         return(i);
      }

      else if (isalpha(c))
      {
          c = tolower(c);
          found = FALSE;
          for (k = i+1; k < n; k++)
          {
             l = first_nonblank(cmdtab[k].menu_item);
             if (c == tolower((int)l))
             {
                found = TRUE;
                break;
             }
          }
          if (!found)
          {
             for (k = 0; k <= i; k++)
             {
                l = first_nonblank(cmdtab[k].menu_item);
                if (c == (char)tolower((int)l))
                {
                   found = TRUE;
                   break;
                }
             }
         }
         if (found)
            new = k;
         else
            return(i);
      }
      else
         return(i);

      if (i != new)
      {

         /* unmark previous option */

         fg_mousevis(OFF);
         fg_setcolor(backgrnd);
         fg_rect(cmdtab[i].x1,cmdtab[i].x2,ymin,ymax);
         fg_setcolor(foregrnd);
         center_pstring(cmdtab[i].menu_item,cmdtab[i].x1,cmdtab[i].x2,ymax);

         /* mark new option */

         i = new;
         fg_setcolor(hilite_bkgnd);
         fg_rect(cmdtab[i].x1,cmdtab[i].x2,ymin,ymax);
         fg_setcolor(hilite_fgnd);
         center_pstring(cmdtab[i].menu_item,cmdtab[i].x1,cmdtab[i].x2,ymax);
         fg_mousevis(ON);
      }
   }
}

/**********************************************************************\
*                                                                      *
*  submenus                                                            *
*                                                                      *
\**********************************************************************/

submenu1()
{
   return(vertical_menu(menu1,0,9,0,15,15,0));
}
submenu2()
{
   return(vertical_menu(menu2,1,5,0,15,15,0));
}
submenu3()
{
   return(vertical_menu(menu3,2,8,0,15,15,0));
}
submenu4()
{
   return(vertical_menu(menu4,3,4,0,15,15,0));
}
submenu5()
{
   return(vertical_menu(menu5,4,6,0,15,15,0));
}
submenu6()
{
   return(vertical_menu(menu6,5,3,0,15,15,0));
}

/**********************************************************************\
*                                                                      *
*  vertical_menu -- submenu off main menu                              *
*                                                                      *
\**********************************************************************/

vertical_menu(cmdtab,index,n,foregrnd,backgrnd,hilite_fgnd,hilite_bkgnd)
CMD cmdtab[];
int index;
int n;
int foregrnd, backgrnd;
int hilite_fgnd, hilite_bkgnd;
{
   register int i, j, k;
   int found, new;
   int height;
   int left, right;
   int string_x;
   int x1, x2, y1, y2;
   int ymin, ymax;
   int count;
   char c, l;
   char key, aux;

   /* height in pixels of an individual menu item */

   height = ptsize + 2;

   /* the first menu item determines the x coordinate for the other items */

   string_x = get_center(cmdtab[0].menu_item,cmdtab[0].x1,cmdtab[0].x2);

   /* define the menu extremes */

   x1 = cmdtab[0].x1 - 1;
   x2 = cmdtab[0].x2 + 3;
   y1 = menu_bottom;
   y2 = menu_bottom + n*height + 1;

   /* define the associated horizontal mouse limits */

   if (mouse)
   {
      left  = mouse_limits[index];
      right = mouse_limits[index+1] - 2;
   }

   /* display the vertical menu if necessary */

   if (redraw)
   {
      /* do this stuff on the hidden page to make it look faster */

      fg_setpage(hidden);

      /* draw the menu outline and the shadow around it */

      fg_mousevis(OFF);
      fg_setcolor(backgrnd);
      draw_box(x1,x2-2,y1,y2-1);
      fg_setcolor(8);
      fg_rect(x1+2,x2,y2,y2);
      fg_rect(x2-1,x2,y1+scale(2),y2);
      fg_setcolor(foregrnd);
      draw_box(x1,x2-2,y1,y2-1);

      /* set up list of options */

      ymax = menu_bottom - 1;
      for (i = 0; i < n; i++)
      {
         ymin = ymax + 1;
         ymax = ymin + height - 1;
         fg_setcolor(backgrnd);
         fg_rect(cmdtab[i].x1,cmdtab[i].x2,ymin,ymax);
         fg_setcolor(foregrnd);
         put_pstring(cmdtab[i].menu_item,string_x,ymax);
      }

      /* highlight first or previously selected option */

      i = selection;
      ymin = menu_bottom + i*height;
      ymax = ymin + height - 1;
      fg_setcolor(hilite_bkgnd);
      fg_rect(cmdtab[i].x1,cmdtab[i].x2,ymin,ymax);
      fg_setcolor(hilite_fgnd);
      put_pstring(cmdtab[i].menu_item,string_x,ymax);

      /* restore the menu to the visual page */

      fg_setpage(visual);
      fg_restore(x1,x2,y1,y2);
      redraw = FALSE;
      fg_setpage(hidden);

      /* clear the hidden page under the menu */

      if (mode06 || mode11)
         fg_drect(x1,x2,y1,y2,matrix1);
      else
      {
         fg_setcolor(15);
         fg_rect(x1,x2,y1,y2);
         fg_setcolor(14);
         fg_drect(x1,x2,y1,y2,matrix2);
      }

      fg_setpage(visual);
      fg_mousevis(ON);
   }

   /* choose an option */

   i = selection;
   new = i;
   fg_setnum(OFF);
   flushkey();

   while (TRUE)
   {
      /* read a keystroke */

      fg_mousevis(ON);
      fg_waitfor(1);
      fg_intkey(&key,&aux);

      /* if using a mouse, check its position */

      if (mouse && key+aux == 0)
      {
         fg_mousebut(1,&count,&xmouse,&ymouse);

         if (count > 0)
         {
            if (BETWEEN(xmouse,x1,x2) && BETWEEN(ymouse,y1,y2-2))
            {
               new = (ymouse - y1) / height;

               /* check if this is the second click of a double click */

               if (i == new)
                  key = CR;
            }
            else if (!BETWEEN(xmouse,left,right) && BETWEEN(ymouse,menu_top,y1-1))
            {
               fg_mousevis(OFF);
               fg_restore(0,xlimit,menu_bottom,ylimit);
               redraw = TRUE;
               selection = 0;
               for (j = 0; j <= ITEMS; j++)
               {
                 if (BETWEEN(xmouse,mouse_limits[j],mouse_limits[j+1]))
                    return(j);
               }
            }
            else
            {
               fg_mousevis(OFF);
               fg_restore(0,xlimit,menu_bottom,ylimit);
               redraw = TRUE;
               selection = 0;
               return(-1);
            }
         }
      }

      /* cycle through choices */

      if (aux == UP_ARROW || key == BS)
         new = cmdtab[i].prev;
      else if (aux == DOWN_ARROW || key == SPACEBAR)
         new = cmdtab[i].next;

      else if (aux == HOME || aux == PAGE_UP)
         new = 0;

      else if (aux == END || aux == PAGE_DOWN)
         new = n - 1;

      else if (aux == LEFT_ARROW || aux == RIGHT_ARROW)
      {
         fg_mousevis(OFF);
         fg_restore(0,xlimit,menu_bottom,ylimit);
         redraw = TRUE;
         selection = 0;
         return((int)aux);
      }

      /* pick one choice */

      else if (key == CR)
      {
         (*cmdtab[i].menu_func)();
         wait_for_mouse_buttons();
         selection = i;
         return(index);
      }

      else if (key == ESC)
      {
         selection = 0;
         return(ESC);
      }
      else if (isalpha((int)key))
      {
          c = (char)tolower((int)key);
          found = FALSE;
          for (k = i+1; k < n; k++)
          {
             l = first_nonblank(cmdtab[k].menu_item);
             if (c == (char)tolower((int)l))
             {
                found = TRUE;
                break;
             }
          }
          if (!found)
          {
             for (k = 0; k <= i; k++)
             {
                l = first_nonblank(cmdtab[k].menu_item);
                if (c == (char)tolower((int)l))
                {
                   found = TRUE;
                   break;
                }
             }
         }
         if (found)
            new = k;
         else
         {
            redraw = TRUE;
            return(-1);
         }
      }
      else if (key+aux > 0) /* any other key */
      {
         redraw = TRUE;
         return(-1);
      }

      if (i != new)
      {
         /* unmark previous option */

         ymin = menu_bottom + i*height;
         ymax = ymin + height - 1;
         fg_mousevis(OFF);
         fg_setcolor(backgrnd);
         fg_rect(cmdtab[i].x1,cmdtab[i].x2,ymin,ymax);
         fg_setcolor(foregrnd);
         put_pstring(cmdtab[i].menu_item,string_x,ymax);

         /* mark new option */

         i = new;
         ymin = menu_bottom + i*height;
         ymax = ymin + height - 1;
         fg_setcolor(hilite_bkgnd);
         fg_rect(cmdtab[i].x1,cmdtab[i].x2,ymin,ymax);
         fg_setcolor(hilite_fgnd);
         put_pstring(cmdtab[i].menu_item,string_x,ymax);

         /* move mouse cursor to the new option */

         if (mouse)
         {
            fg_mousepos(&xmouse,&ymouse,&buttons);
            if (BETWEEN(xmouse,x1,x2)) fg_mousemov(xmouse,(ymin+ymax)/2);
            fg_mousevis(ON);
         }
      }
   }
}
