/* lib.c */

/* adapted from Steve Mumford's AULib */

#include <stdarg.h>
#include "lib.h"
#include "main.h"
#include "msg.h"
#include "ka_error.h"

/**
 * Displays an error message then exits.
 *
 * @param  fatal   Positive if fatal error leading to program termination.
 *                 Negative if shouldn't look for format token in msg file.
 * @param  format  printf like format.
 * @param  ...     Additional parameters, format dependant.
 */
void report_error(int fatal, const char *format, ...)
{
  _kernel_oserror blk;
  _kernel_swi_regs regs;
  const char* app = "KinoAMP Player";
  char msg[240];

  blk.errnum = 0; // error number

  va_list arg;
  va_start(arg, format);

  if (fatal >= 0)
  {
    msg_lookup(format, -1, msg, sizeof(msg));
    vsnprintf(blk.errmess, sizeof(blk.errmess), msg, arg);
  }
  else
  {
    vsnprintf(blk.errmess, sizeof(blk.errmess), format, arg);
  }
  va_end(arg);

  regs.r[0] = (int) &blk;
  regs.r[1] = 8; // flags: bit3 = return immediately if full screen
  regs.r[2] = (int) app;
  _kernel_swi(Wimp_ReportError, &regs, &regs);

  if (fatal)
    exit(1);
}

/*
 * loadtemplate
 * ---------------
 */
int loadtemplate(const char* template_name, window_data* win_data, int entry)
{
  _kernel_swi_regs regs;
  int next_entry;

  regs.r[1] = 0;  // find size
  regs.r[5] = (int)template_name;
  regs.r[6] = entry;
  _kernel_swi(Wimp_LoadTemplate, &regs, &regs);
  win_data->buffer = malloc(regs.r[1]);
  win_data->workspace = malloc(regs.r[2]);

  // load template
  regs.r[1] = (int)win_data->buffer;
  regs.r[3] = (int)win_data->workspace + regs.r[2];
  regs.r[2] = (int)win_data->workspace;
  regs.r[4] = -1;
  regs.r[6] = entry;
  _kernel_swi(Wimp_LoadTemplate, &regs, &regs);
  next_entry = regs.r[6];

  // Create window
  regs.r[1] = (int)win_data->buffer;
  _kernel_swi(Wimp_CreateWindow, &regs, &regs);
  win_data->win_handle = regs.r[0];

  return next_entry;
}

/*
 * icon_text_change
 * -------------------
 */
void icon_text_change(int win_h, int icon_h, const char* text)
{
  int blk[16];

  // find address and length of icon buffer
  blk[0] = win_h;
  blk[1] = icon_h;
  _swi(Wimp_GetIconState, _IN(1), &blk[0]);

  // update only if indirect data
  if (blk[6] & 0x100)
  {
    snprintf((char*) blk[7], blk[9], "%s", text);

    // redraw icon
    blk[2] = 0;
    blk[3] = 0;
    _swi(Wimp_SetIconState, _IN(1), &blk[0]);
  }
}

/*
 * icon_text_format
 * -------------------
 */
void icon_text_format(int win_h, int icon_h, const char* format, ...)
{
  int blk[16];

  // find address and length of icon buffer
  blk[0] = win_h;
  blk[1] = icon_h;
  _swi(Wimp_GetIconState, _IN(1), &blk[0]);

  va_list arg;
  va_start(arg, format);

  // update only if indirect data
  if (blk[6] & 0x100)
  {
    vsnprintf((char*) blk[7], blk[9], format, arg);

    // redraw icon
    blk[2] = 0;
    blk[3] = 0;
    _swi(Wimp_SetIconState, _IN(1), &blk[0]);
  }
  va_end(arg);
}

/*
 * icon_gettext
 * ---------------
 */
const char* icon_gettext(int win_h, int icon_h)
{
	int blk[10];

	blk[0] = win_h;
	blk[1] = icon_h;
	if (_swix(Wimp_GetIconState, _IN(1), &blk[0]))
		return NULL;

	return (const char*) blk[7];
}

/*
 * icon_setselected
 * -------------------
 */
void icon_setselected(int win_h, int icon_h, int b)
{
  int blk[4];

  blk[0] = win_h;
  blk[1] = icon_h;
  blk[2] = b ? (1<<21) : 0;
  blk[3] = (1<<21);
  _swi(Wimp_SetIconState, _IN(1), &blk[0]);
}

/*
 * icon_setshaded
 * -------------------
 */
void icon_setshaded(int win_h, int icon_h, int b)
{
  int blk[4];

  blk[0] = win_h;
  blk[1] = icon_h;
  blk[2] = b ? (1<<22) : 0;
  blk[3] = (1<<22);
  _swi(Wimp_SetIconState, _IN(1), &blk[0]);
}
