/* Simple BBC News ticker client
 * (c) Darren Salt
 * GPL applies
 * $Id: wimpmenu.c,v 1.5 2007/04/25 14:11:16 ds Exp $
 */

/* System includes */

#include <string.h>

/* Program includes */

#include "globals.h"

#include "configure.h"
#include "fetch.h"
#include "wimp.h"
#include "wimpmenu.h"
#include "wimpticker.h"


base_menu2_type url_menu_bbc =
{
  "Go to", 0x70207, 0, 44, 0,
  {
    {
      0, -1, 0x7000121,.text.it =
      {
      "BBC Online\0http://www.bbc.co.uk/", "", 11}
    }
    ,
    {
      128, -1, 0x7000121,.text.it =
      {
      "BBC News\0http://news.bbc.co.uk/", "", 9}
    }
  }
};

base_menu_type *servers_menu = 0, *servers_submenu = 0, *resources_menu = 0;

base_menu1_type null_goto_menu =
{
  "Go to", 0x70207, 0, 0, 0,
  {
    {
    128, -1, 0, ""}
  }
};


base_menu6_type iconbar_menu =
{
  "Ticker", 0x70207, 160, 44, 0,
  {
    {
    0, -1, 0x7000021, "Info"}
    ,
    {
    24, 0, 0x7000021, "Ticker..."}
    ,
    {
    0, -1, 0x7000021, "Choices..."}
    ,
    {
    0, -1, 0x7000021, "Tickers..."}
    ,
    {
    24, 1, 0x7400021, "Go to"}
    ,
    {
    128, -1, 0x7000021, "Quit"}
  }
};


base_menu6_type ticker_control_menu =
{
  "Control", 0x70207, 160, 44, 0,
  {
    {
    0, -1, 0x7000021, "Update"}
    ,
    {
    24, 0, 0x7000021, "Ticker"}
    ,
    {
    0, -1, 0x7000021, "Abort"}
    ,
    {
    0, -1, 0x7000021, "Restart"}
    ,
    {
    0, -1, 0x7000021, ""}
    ,
    {
    128, -1, 0x7000021, "Reposition"}
  }
};


base_menu6_type ticker_menu =
{
  "Ticker", 0x70207, 160, 44, 0,
  {
    {
    0, -1, 0x7000021, "Control"}
    ,
    {
    8, -1, 0x7000021, "Save link"}
    ,
    {
    8, -1, 0x7000021, "Save text"}
    ,
    {
    0, -1, 0x7000021, "Choices..."}
    ,
    {
    0, -1, 0x7000021, "Tickers..."}
    ,
    {
    152, 1, 0x7400021, "Go to"}
  }
};


base_menu8_type ticker_menu_no_ibar =
{
  "Ticker", 0x70207, 160, 44, 0,
  {
    {
    0, -1, 0x7000021, "Control"}
    ,
    {
    8, -1, 0x7000021, "Save link"}
    ,
    {
    8, -1, 0x7000021, "Save text"}
    ,
    {
    0, -1, 0x7000021, "Choices..."}
    ,
    {
    0, -1, 0x7000021, "Tickers..."}
    ,
    {
    24, 1, 0x7400021, "Go to"}
    ,
    {
    0, -1, 0x7000021, "Info"}
    ,
    {
    128, -1, 0x7000021, "Quit"}
  }
};


/* The currently open menu */
struct current_menu_t current_menu = {0};

/* Do we reopen the current menu? */
int force_reopen_menu = 0;


/*************
 * Menu open *
 *************/


/* Updates the state of menu entries in the given menu (and submenus)
 * according to the current program state.
 * (If menu == current_menu.handle, we're reopening this menu.)
 */

void
update_menu (void *menu)
{
  struct menu_entry *item = (struct menu_entry *) ((char *) menu + 28);
  int f;

  if ((int) menu < 0x8000 || (int) menu & 1)
    return;

  if (menu == &ticker_menu || menu == &ticker_menu_no_ibar)
  {
    struct wimp_getpointerinfo_block pointer;
    wimp_get_pointer_info (&pointer);
    current_menu.story = which_story (&pointer);
    set_menu_shade (&ticker_menu, 1, f =
		    (current_menu.story && current_menu.story->url));
    set_menu_shade (&ticker_menu_no_ibar, 1, f);
    set_menu_shade (&ticker_menu, 2, f = ticker_data.stories != 0);
    set_menu_shade (&ticker_menu_no_ibar, 2, f);
    set_menu_shade (&ticker_menu, 5, f = (find_goto_menu (0) != 0));
    set_menu_shade (&ticker_menu_no_ibar, 5, f);
  }
  else if (menu == &ticker_control_menu)
  {
    f = ticker_data.state != state_LOADING || is_fetch_allowed ();
    set_menu_shade (menu, 0, f);
    set_menu_shade (menu, 1, f);
    set_menu_shade (menu, 2, ticker_data.state == state_LOADING);
    set_menu_shade (menu, 3, ticker_data.state == state_ACTIVE);
    strcpy (item[4].text.t.text,
	    ticker.state == is_MINIMISED ? "Maximise" : "Minimise");
  }
  else if (menu == &iconbar_menu)
    set_menu_shade (menu, 4, find_goto_menu (0) != 0);

  do
  {
    if (item->submenu)
      update_menu ((void *) item->submenu);
  }
  while (((++item)->menuflags & 128) == 0);
}


void
mark_menu_closed (void)
{
  if (current_menu.handle == &ticker_menu
      || current_menu.handle == &ticker_menu_no_ibar)
    next_scroll_time = read_monotonic_time ();
  force_reopen_menu = 0;
  current_menu.handle = 0;
}


void
close_menu (void)
{
  wimp_create_menu ((const void *) -1, 0, 0);
  mark_menu_closed ();
}


void
open_menu (void *menu, int x, int y)
{
  if (!menu)
    return;

  update_menu (menu);

  if (x >= 0x8000)
  {
    /* It's not a coordinate pair but a window/icon pair */
    union
    {
      struct wimp_getwindowinfo_block w;
      struct wimp_geticonstate_block i;
    }
    block;
    current_menu.window = x;
    current_menu.icon = y;
    wimp_get_icon_state (x, y, &block.i);
    x = block.i.max.x;
    y = block.i.max.y;
    wimp_get_window_info (&block.w, 0);
    x +=
      block.w.data.min.x + block.w.data.scroll.x -
      2 * block.w.data.work_min.x;
    y +=
      block.w.data.max.y + block.w.data.scroll.y -
      2 * block.w.data.work_max.y;
  }
  else
    current_menu.window = 0;

  if (!wimp_create_menu (menu, x, y))
  {
    current_menu.handle = menu;
    current_menu.pos.x = x;
    current_menu.pos.y = y;
    wimp_close_window (&wind.ticker_desc);
  }
}


base_menu_type *
find_goto_menu (int use_null)
{
  void *m;
  if (resources_menu && resources_menu->width)
    m = resources_menu;
  else if (fetcher.format == format_BBC && ticker_data.state == state_ACTIVE)
    m = &url_menu_bbc;
  else
    m = use_null ? &null_goto_menu : 0;
  return m;
}


static void
menu_launch_url (int sel)
{
  unsigned int num = 0;
  const struct menu_entry *items = find_goto_menu (1)->items;
  while ((items[num++].menuflags & 128) == 0)
    ;
  if ((unsigned int) sel < num)
  {
    const char *url = items[sel].text.it.text;
    launch_url (url + strlen (url) + 1, 1);
  }
}


int
menu_click (void)
{
  struct wimp_getpointerinfo_block block;
  const void *handle = current_menu.handle;

  wimp_get_pointer_info (&block);
  if (block.buttons & 1)
  {
    force_reopen_menu = 1;
    update_menu (current_menu.handle);
    wimp_create_menu (current_menu.handle, current_menu.pos.x,
		      current_menu.pos.y);
  }
  else
    mark_menu_closed ();

  if (handle == &iconbar_menu)
    switch (poll_block.menu_selection.menu[0])
    {
    case 1:			/* open ticker */
      if (poll_block.menu_selection.menu[1] != -1)
      {
	int i = find_server_from_menu (&poll_block.menu_selection.menu[1]);
	if (i != -1)
	{
	  set_fetcher (&servers[i]);
	  go_fetch_ticker (1);
	}
      }
      else
	reopen_ticker_window (0, 2);
      break;
    case 2:			/* open options */
      open_config_window (1);
      break;
    case 3:			/* open servers config */
      open_servers_window (1, 0, 0);
      break;
    case 4:			/* URLs */
      menu_launch_url (poll_block.menu_selection.menu[1]);
      break;
    case 5:			/* quit */
      return 1;
    }
  else if (handle == &ticker_menu || handle == &ticker_menu_no_ibar)
    switch (poll_block.menu_selection.menu[0])
    {
    case 0:
      switch (poll_block.menu_selection.menu[1])
      {
      case 0:			/* refresh ticker */
	if (ticker_data.state != state_LOADING && !is_save_window_open ())
	  go_fetch_ticker (1);
	break;
      case 1:
	if (poll_block.menu_selection.menu[2] != -1)
	{
	  int i = find_server_from_menu (&poll_block.menu_selection.menu[2]);
	  if (i != -1)
	  {
	    set_fetcher (&servers[i]);
	    go_fetch_ticker (1);
	  }
	}
	break;
      case 2:			/* abort */
	if (ticker_data.state == state_LOADING)
	  abort_fetch ();
	break;
      case 3:			/* restart ticker */
	if (ticker_data.state == state_ACTIVE)
	{
	  process_stories ();
	  reopen_ticker_window (1, 0);
	}
	break;
      case 4:			/* (de)minimise */
	toggle_ticker_minimise ();
	break;
      case 5:			/* restore configured position */
	wimp_get_window_state (&poll_block.open_window, wind.ticker_tbar);
	set_ticker_width (&poll_block.open_window);
	set_ticker_align (&poll_block.open_window);
	open_ticker_window_current (&poll_block.open_window, 0, 0);
	break;
      }
      break;
    case 3:			/* open options */
      open_config_window (1);
      break;
    case 4:			/* open servers config */
      open_servers_window (1, 0, 0);
      break;
    case 5:			/* URLs */
      menu_launch_url (poll_block.menu_selection.menu[1]);
      break;
    case 7:			/* quit */
      return 1;
    }
  else if (handle == servers_menu)
    click_servers_menu (poll_block.menu_selection.menu,
			current_menu.window, current_menu.icon);
  else
    click_config_menu (handle, poll_block.menu_selection.menu,
		       current_menu.window, current_menu.icon);

  return 0;
}
