// -*- C++ -*-
/*
 *  This file is part of LyX, the High Level Word Processor
 *
 *  GNU Copyleft (C) 1996   LyX Team. 
 *
 *  Created: 15/05/96 Alejandro Aguilar Sierra <asierra@servidor.unam.mx>
 * 
 *  Dependencies:  Only XFoms, but designed to be easyly used by LyX.
 * 
 *  Description:  A Menu class encapsulates standard text menus.
 *                You can use Menu to construct, modify, display and 
 *                query menu objects. A Menu can also include
 *                submenus, short cuts, binary items, etc.
 * 
 */ 

/* Change log:
 *  
 *  15/05/1996,   Alejandro Aguilar Sierra 
 *    Created and tested the class Menu. It can handle short cuts
 *    and submenus in a very easy way. Binary and disabled items not
 *    yet implemented, but this could be done externally on the
 *    tables using XForms syntax.
 * 
 */  

//#include "config.h"   // Uncoment when this file be integrated to lyx.
#include "Menu.h"
#include <string.h>

///
Menu::Menu()
{
   title = NULL;
   popup = -1;
   isbm = 1;
   nsm = 0;
   table = NULL;
   submenu = NULL;
   nitems = 0;
   mode = FL_PUP_NONE;
}

///
Menu::Menu(menu_table_item* t, int n)
{
   title = NULL;
   submenu = NULL;
   popup = -1;
   isbm = 1;
   nsm = 0;
   mode = FL_PUP_NONE;
   setTable(t, n);
}

///
Menu::~Menu()
{
   if (nsm) delete[] submenu;
   if (title) delete[] title;
}

   
///
void Menu::setTable(menu_table_item* t, int n)
{ 
   table = t; 
   nitems = n;
   for (int i=0; i<nitems; i++) {
      if (table[i].action==MENU_SUBMENU) nsm++;
   }
   if (submenu) delete[] submenu;
   
   if (nsm>0) {
      submenu = new MenuPtr[nsm];
      isbm = 0;
   }
}

///
void Menu::setName(const char* t) 
{
   title = new char[strlen(t)+1];
   strcpy(title, t);
}

///
void Menu::addSubmenu(Menu* m) 
{
   if (isbm<nsm) 
     submenu[isbm++] = m;
   else
     fprintf(stderr, "Menu error: No more submenus allowed.\n");
}

///
void Menu::setSubmenu(Menu* m, int i)
{
   if (i>=0 && i<nsm) 
     submenu[i] = m;
   else
     fprintf(stderr, "Menu error: Invalid submenu number.\n");
}

///
void Menu::setParent(Window w) 
{ 
   parent = w;
   for (int i=0; i<nsm; i++)
     submenu[i]->setParent(parent);
}

///
int Menu::getpup() 
{  
   int sm = 0;
   char s[80];
 
   popup =fl_newpup(parent);  
   for (int i=0; i<nitems; i++) {
      switch (table[i].action) {
       case MENU_SEPARATOR: break;
       case MENU_SUBMENU: 
	   {
	      int p = submenu[sm++]->getpup();
	      sprintf(s, "%s%%m", table[i].label); 
	      if (table[i].keyb && table[i].keyb[0] > ' ') {
		 strcat(s, "%h");
		 fl_addtopup(popup, s, p, table[i].keyb); 
	      } else 
		fl_addtopup(popup, s, p);
	      break;
	   }
       default:
	 sprintf(s, "%s%%x%d", table[i].label, table[i].action);
	 if (i<nitems-1 && table[i+1].action==MENU_SEPARATOR)
	    strcat(s, "%l");
         if (table[i].keyb && table[i].keyb[0] > ' ') {
	    strcat(s, "%h");
	    fl_addtopup(popup, s, table[i].keyb); 
	 } else 
	   fl_addtopup(popup, s);
	 break;
      }
   }
   return popup;
}

///
int Menu::show(int x, int y) 
{
   if (popup<0) getpup();
   fl_setpup_position(x, y);
   int k = fl_dopup(popup);
//   if (k>0) {
//      mode = fl_getpup_mode(popup, k);
//   }
   freepup();
   
   return k;
}


///
void Menu::freepup() 
{       
   for (int i=0; i<nsm; i++)
     submenu[i]->freepup();
   fl_freepup(popup); 
   popup = -1; 
}


#ifdef TEST_MENU     

///
typedef struct {
	FL_FORM *test;
	FL_OBJECT *bar;
	FL_OBJECT *menu1;
	FL_OBJECT *menu2;
	FL_OBJECT *menu3;
	void *vdata;
	long ldata;
} ///
 FD_test;

///
FD_test *fd_test;

///
menu_table_item t1[] = {
   { 0, "Hola", "H"},
   { 1, "Hello", "e"},
   { 2, "Alo%l", "o"},
   { MENU_SUBMENU, "Bad words", "w"},
};

///
menu_table_item t2[] = {
   { 5, "Bye%b", "B"},
   { 6, "Adios%b", "d"},
   { MENU_SEPARATOR, "", ""},
   { 7, "Au revoir", "A"},
   { 8, "Lebewohl", "w"},
};

///
menu_table_item t3[] = {
   { 9, "merde%r1", "m"},
   { 10, "fuck%r1", "f"},
   { 12, "carajo%r1", "j"},
};

///
Menu menu1, menu2, menu3, menu4;

///
void
do_menu(FL_OBJECT *ob, long q)
{
   Menu* menu;
   int x = ob->x + ob->form->x;
   int y = ob->y + ob->form->y + ob->h + 10;
   switch (q) {
    case 0: menu = &menu1; break;
    case 1: menu = &menu2; break;
    case 2: menu = &menu3; break;
   }
   fprintf(stderr, "POP %ld ", q);
   menu->setParent(FL_ObjWin(ob));
   fprintf(stderr, "Menu [%s] %d ", menu->getName(), menu->show(x, y));
}
   
///
FD_test *create_form_test(void)
{
   FL_OBJECT *obj;
   FD_test *fdui = (FD_test *) fl_calloc(1, sizeof(*fdui));

   fdui->test = fl_bgn_form(FL_NO_BOX, 320, 190);
   obj = fl_add_box(FL_UP_BOX,0,0,320,190,"");

   fdui->bar = fl_bgn_group();
   fdui->menu1 = obj = fl_add_button(FL_NORMAL_BUTTON,20,20,50,20,"Hellos");
     fl_set_object_callback(obj,do_menu,0);
   fdui->menu2 = obj = fl_add_button(FL_NORMAL_BUTTON,90,20,50,20,"Byes");
     fl_set_object_callback(obj,do_menu,1);
   fdui->menu3 = obj = fl_add_button(FL_NORMAL_BUTTON,160,20,50,20,"Bad words");
     fl_set_object_callback(obj,do_menu,2);
   fl_end_group();
   
  fl_end_form();

  return fdui;
}

///
int main(int argc, char *argv[])
{
   int n1;
   fl_initialize(&argc, argv, 0, 0, 0);
   
   fd_test = create_form_test();

   /* fill-in form initialization code */
   menu1.setTable(t1, 4);
   menu2.setTable(t2, 5);
   menu3.setTable(t3, 3);
   menu4.setTable(t3, 3);
   menu1.addSubmenu(&menu4);

   menu1.setName("Hellos");
   menu2.setName("Byes");
   menu3.setName("Bad words");   
   
   /* show the first form */
   fl_show_form(fd_test->test,FL_PLACE_CENTER,FL_FULLBORDER,"test");
   fl_do_forms();
   return 0;
}

#endif
