/*
 * msg.c
 * 20/9/03
 * Anything to do with the Messages file
 */

#include "lib.h"
#include "main.h"
#include "msg.h"

static int msg_desc[5];
static char * msg_buf;

/*
 * msg_open
 * --------
 */
int msg_open(const char* name)
{
  _kernel_swi_regs regs;

  if(msg_desc[4])
    return 1; // already open

  regs.r[1] = (int)name;
  if(_kernel_swi(MessageTrans_FileInfo, &regs, &regs))
    return 0; // error opening file

  if(regs.r[0] & 1)
    return 0; // already in memory

  if((msg_buf = malloc(regs.r[2])) == NULL)
    return 0; // out of memory

  regs.r[0] = (int)&msg_desc;
  regs.r[1] = (int)name;
  regs.r[2] = (int)msg_buf;
  _kernel_swi(MessageTrans_OpenFile, &regs, &regs);
  msg_desc[4] = 1;

  return 1;
}

/*
 * msg_close
 * ---------
 */
void msg_close(void)
{
  _kernel_swi_regs regs;

  regs.r[0] = (int)&msg_desc;
  _kernel_swi(MessageTrans_CloseFile, &regs, &regs);
  msg_desc[4] = 0;

  if(msg_buf)
  {
    free(msg_buf);
    msg_buf = NULL;
  }
}

/*
 * msg_lookup
 * ----------
 * Converts a message token to text. Requires the base token string and
 * a numeric qualifier.
 * If qualifier is negative, uses token directly with no appended numeric.
 */
int msg_lookup(const char* token, int num, char* dest, int dstsize)
{
  _kernel_swi_regs regs;
  char tok[32];

  if(!msg_desc[4])
    return 0; // Messages file not opened

  regs.r[0] = (int)&msg_desc;
  if(num < 0)
    regs.r[1] = (int)token;
  else
  {
    snprintf(tok, sizeof(tok), "%s%d", token, num);
    regs.r[1] = (int)&tok;
  }
  regs.r[2] = (int)dest;
  regs.r[3] = dstsize;
  regs.r[4] = 0;
  regs.r[5] = 0;
  regs.r[6] = 0;
  regs.r[7] = 0;
  if(_kernel_swi(MessageTrans_Lookup, &regs, &regs))
    return 0;

  return 1;
}

/*
 * msg_load_menu
 * -------------
 * copies text from messages file to menu structures
 */
void msg_load_menu(const char* token, menu_block_t* blk)
{
  menu_item_t* item = (menu_item_t*) (blk + 1);
  char* str;
  _kernel_swi_regs regs;

  regs.r[0] = (int)&msg_desc;
  regs.r[1] = (int)token;
  regs.r[2] = 0;
  regs.r[3] = 0;
  regs.r[4] = 0;
  regs.r[5] = 0;
  regs.r[6] = 0;
  regs.r[7] = 0;
  if(_kernel_swi(MessageTrans_Lookup, &regs, &regs))
    return;

  if ((str = malloc(regs.r[3] + 1)) == NULL)
    return;

  memcpy(str, (char*) regs.r[2], regs.r[3]);
  str[regs.r[3]] = 0;

  // title
  blk->title = str;
  str = strchr(str, ',');
  if (str)
  {
    *str++ = 0;
    blk->len = str - blk->title;
  }
  else
  {
    blk->len = strlen(blk->title) + 1;
    return;
  }
  // Mark in first item that title is indirected
  item->item_flags |= 0x100;

  // items
  while(1)
  {
    item->text = str;
    str = strchr(str, ',');
    if (str)
    {
      *str++ = 0;
      item->len = str - item->text;
    }
    else
    {
      item->len = strlen(item->text) + 1;
      return;
    }
    // Do not go behind last item of menu
    if (item->item_flags & 0x80)
      return;
    item++;
  }
}

/*
 * msg_help
 * --------
 * Supplies help text. Requires the HelpRequest message block and current menu tag.
 */
void msg_help(int *b, int cur_menu)
{
  static const char const* tokens[WIN_MAX] =
  { "fe_filminfo_wh"
  , "fe_info_wh"
  , "fe_options_wh"
  , "fe_image_wh"
  , "fe_audio_wh"
  , "fe_auto_wh"
  , "fe_desktop_wh"
  , "fe_main_wh"
  , "fe_manual_wh"
  , "fe_multask_wh"
  , "fe_window_wh"
  , "fe_playlist_wh"
  };

  _kernel_swi_regs regs;
  int blk[10], ok = 0;
  char* dst = (char *)&b[5];
  int dstsize = 256 - 20;
  int id;

  for (id = 0; id < WIN_MAX; id++)
  {
    if (b[8] == win_data[id].win_handle)
      break;
  }

  if (id < WIN_MAX)
  {
    if ((ok = msg_lookup(tokens[id], b[9], dst, dstsize)) == 0)
      ok = msg_lookup(tokens[id], -1, dst, dstsize);
  }
  // unknown window, check for a menu
  else if(b[8] != -2)
  {
    regs.r[0] = 1;
    regs.r[1] = (int)blk;
    regs.r[2] = b[8]; // window handle
    regs.r[3] = b[9]; // icon handle
    _kernel_swi(Wimp_GetMenuState, &regs, &regs);
    switch(cur_menu)
    {
      case MENU_ICONBAR:
        ok = msg_lookup("fe_iconbar_mh", blk[0], dst, dstsize);
      break;

      case MENU_COLOURS:
        ok = msg_lookup("fe_colours_mh", -1, dst, dstsize);
      break;

      case MENU_RESOLUTION:
        ok = msg_lookup("fe_resolution_mh", -1, dst, dstsize);
      break;

      case MENU_ZOOM:
        ok = msg_lookup("fe_zoom_mh", -1, dst, dstsize);
      break;

      case MENU_SKIN:
        ok = msg_lookup("fe_skin_mh", -1, dst, dstsize);
      break;

      case MENU_AUDIOPLAYER:
        ok = msg_lookup("fe_audiomod_mh", -1, dst, dstsize);
      break;

      case MENU_SCALER:
        ok = msg_lookup("fe_scaler_mh", blk[0], dst, dstsize);
      break;

      case MENU_DEINTERLACE:
        ok = msg_lookup("deinterlace_mh", blk[0], dst, dstsize);
      break;

      case MENU_RESIZEMODE:
        ok = msg_lookup("resizemode_mh", blk[0], dst, dstsize);
      break;

      case MENU_RESIZETO:
        ok = msg_lookup("resizeto_mh", blk[0] ? 1 : 0, dst, dstsize);
      break;
    }
  }

  if(!ok)
    return; // no help available

  // send help text to Help application
  regs.r[0] = 17;     // User message
  regs.r[1] = (int)b;
  regs.r[2] = b[1];   // sender task handle
  b[0] = 256; // buffer length
  b[3] = b[2];
  b[4] = MESSAGE_HELPREPLY;
  _kernel_swi(Wimp_SendMessage, &regs, &regs);
}

