/*
 *  dialog_riscos.c -- dialog creation, RISC OS
 */

#include "gui.h"

/****************************************************************************************/
/*  Dialog creation functions                                                           */
/****************************************************************************************/

#define DIALOG_ICON_CHUNK 10
#define DIALOG_NONE 0xffffffff

static gui_window_id dialog_id = DIALOG_NONE;
static wimp_window *dialog_block;
static int dialog_block_icons;
static int dialog_icons;
static int dialog_y;
static int dialog_x;
static struct gui_dialog_icon *dialog_icon;

/*
 *  gui_start_dialog -- start creating a dialogue window
 *
 *  => title -- window title
 *
 *  <= nothing
 */

void gui_start_dialog(char *title, unsigned int width,
      bool close, const char *help)
{
  assert(dialog_id == DIALOG_NONE);

  #ifdef DEBUG
  printf("gui_start_dialog: title = '%s'\n", title);
  fflush(stdout);
  #endif

  dialog_id = gui_get_free_window_id();

  dialog_block_icons = DIALOG_ICON_CHUNK;
  dialog_icons = 0;
  dialog_y = 4;
  dialog_x = width;

  dialog_icon = malloc(dialog_block_icons * sizeof(struct gui_dialog_icon));
  if (!dialog_icon) gui_raise_error("memory");

  dialog_block = malloc(wimp_SIZEOF_WINDOW(dialog_block_icons));
  if (!dialog_block) gui_raise_error("memory");

  dialog_block->flags = wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW |
      wimp_WINDOW_NEW_FORMAT | wimp_WINDOW_BACK_ICON | wimp_WINDOW_TITLE_ICON |
      (close ? wimp_WINDOW_CLOSE_ICON : 0);
  dialog_block->title_fg = wimp_COLOUR_BLACK;
  dialog_block->title_bg = wimp_COLOUR_LIGHT_GREY;
  dialog_block->work_fg = wimp_COLOUR_BLACK;
  dialog_block->work_bg = wimp_COLOUR_VERY_LIGHT_GREY;
  dialog_block->highlight_bg = wimp_COLOUR_CREAM;
  dialog_block->extent.x0 = dialog_block->extent.y1 = 0;
  dialog_block->extent.x1 = width;
  dialog_block->title_flags = wimp_ICON_TEXT | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED |
      wimp_ICON_INDIRECTED;
  dialog_block->work_flags = 0;
  dialog_block->sprite_area = (osspriteop_area *) 1;
  dialog_block->xmin = dialog_block->ymin = 1;
  dialog_block->title_data.indirected_text.text = title;
  dialog_block->title_data.indirected_text.validation = 0;

  gui_window_list[dialog_id].title = title;
  gui_window_list[dialog_id].help = help;
}


/*
 *  gui_create_dialog -- finish creating and open a dialogue window
 *
 *  => nothing
 *
 *  <= window id
 */

gui_window_id gui_create_dialog()
{
  gui_window_id id = dialog_id;
  wimp_w handle;
  wimp_open open;

  assert(dialog_id != DIALOG_NONE);

  dialog_y += 4;

  dialog_block->extent.y0 = -dialog_y;
  dialog_block->icon_count = dialog_icons;

  gui_error = xwimp_create_window(dialog_block, &handle);
  gui_check_error();

  gui_window_list[dialog_id].used = DIALOG;
  gui_window_list[dialog_id].handle = handle;
  gui_window_list[dialog_id].close_fn = gui_remove_window;
  gui_window_list[dialog_id].redraw_fn = NULL;
  gui_window_list[dialog_id].click_fn = NULL;
  gui_window_list[dialog_id].resize_fn = NULL;
  gui_window_list[dialog_id].key_fn = NULL;
  gui_window_list[dialog_id].input_fn = NULL;
  gui_window_list[dialog_id].menu_fn = NULL;
  gui_window_list[dialog_id].width = dialog_block->extent.x1;
  gui_window_list[dialog_id].height = dialog_y;
  gui_window_list[dialog_id].menu = NULL;
  gui_window_list[dialog_id].icon = dialog_icon;

  free(dialog_block);

  open.w = handle;
  open.visible.x0 = open.visible.y0 = 300;
  open.visible.x1 = 300 + gui_window_list[dialog_id].width;
  open.visible.y1 = 300 + dialog_y;
  open.xscroll = open.yscroll = 0;
  open.next = wimp_TOP;
  gui_error = xwimp_open_window(&open);
  gui_check_error();

  dialog_id = DIALOG_NONE;

  #ifdef DEBUG
  printf("gui_create_dialog: id = 0x%x, handle = 0x%x\n", dialog_id,
        (unsigned int) handle);
  fflush(stdout);
  #endif

  return id;
}


/*
 *  ensure_dialog_space -- allocate memory for icons if necessary
 *
 *  => nothing
 *
 *  <= nothing
 */

void ensure_dialog_space(void)
{
  if (dialog_icons == dialog_block_icons)
  {
    dialog_block_icons += DIALOG_ICON_CHUNK;
    dialog_block = realloc(dialog_block, wimp_SIZEOF_WINDOW(dialog_block_icons));
    dialog_icon = realloc(dialog_icon, dialog_block_icons * sizeof(struct gui_dialog_icon));
    if (!dialog_block || !dialog_icon)
    {
/*      free(dialog_block);*/
      dialog_id = DIALOG_NONE;
      gui_raise_error("memory");
    }
  }
}


/*
 *  gui_create_label -- create a text label
 *
 *  => text -- label text
 *
 *  <= nothing
 */

void gui_create_label(char *text, const char *help)
{
  assert(dialog_id != DIALOG_NONE);

  #ifdef DEBUG
  printf("gui_create_label: text = '%s'\n", text);
  fflush(stdout);
  #endif

  ensure_dialog_space();

  dialog_block->icons[dialog_icons].extent.x0 = 0;
  dialog_block->icons[dialog_icons].extent.y0 = -(dialog_y + 52);
  dialog_block->icons[dialog_icons].extent.x1 = dialog_block->extent.x1;
  dialog_block->icons[dialog_icons].extent.y1 = -dialog_y;
  dialog_block->icons[dialog_icons].flags = wimp_ICON_TEXT | wimp_ICON_HCENTRED |
      wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED |
      wimp_BUTTON_NEVER << wimp_ICON_BUTTON_TYPE_SHIFT |
      wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT |
      wimp_COLOUR_VERY_LIGHT_GREY << wimp_ICON_BG_COLOUR_SHIFT;
  dialog_block->icons[dialog_icons].data.indirected_text.text = text;
  dialog_block->icons[dialog_icons].data.indirected_text.validation = 0;

  dialog_icon[dialog_icons].type = ICON_NONE;
  dialog_icon[dialog_icons].help = help;

  dialog_icons++;
  dialog_y += 52;
}


/*
 *  gui_create_text_box -- create a labelled writeable text box
 *
 *  => text -- label text
 *     mask -- entry mask (eg. '0-9' etc)
 *
 *  <= gadget id
 *     0 if an error occurred
 */

gui_gadget_id gui_create_text_box(char *text, const char *mask, const char *help)
{
  assert(dialog_id != DIALOG_NONE);

  #ifdef DEBUG
  printf("gui_create_text_box: text = '%s', mask = '%s'\n", text, mask);
  fflush(stdout);
  #endif

  ensure_dialog_space();

  dialog_block->icons[dialog_icons].extent.x0 = 0;
  dialog_block->icons[dialog_icons].extent.y0 = -(dialog_y + 60);
  dialog_block->icons[dialog_icons].extent.x1 = dialog_block->extent.x1 * 0.25;
  dialog_block->icons[dialog_icons].extent.y1 = -dialog_y;
  dialog_block->icons[dialog_icons].flags = wimp_ICON_TEXT | wimp_ICON_RJUSTIFIED |
       wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED |
       wimp_BUTTON_NEVER << wimp_ICON_BUTTON_TYPE_SHIFT |
       wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT |
       wimp_COLOUR_VERY_LIGHT_GREY << wimp_ICON_BG_COLOUR_SHIFT;
  dialog_block->icons[dialog_icons].data.indirected_text.text = text;
  dialog_block->icons[dialog_icons].data.indirected_text.validation = 0;

  dialog_icon[dialog_icons].type = ICON_NONE;
  dialog_icon[dialog_icons].help = help;

  dialog_icons++;

  ensure_dialog_space();

  dialog_block->icons[dialog_icons].extent.x0 = dialog_block->extent.x1 * 0.25;
  dialog_block->icons[dialog_icons].extent.y0 = -(dialog_y + 56);
  dialog_block->icons[dialog_icons].extent.x1 = dialog_block->extent.x1 - 8;
  dialog_block->icons[dialog_icons].extent.y1 = -(dialog_y + 4);
  dialog_block->icons[dialog_icons].flags = wimp_ICON_TEXT | wimp_ICON_VCENTRED |
      wimp_ICON_INDIRECTED | wimp_ICON_BORDER | wimp_ICON_FILLED |
      wimp_BUTTON_WRITABLE << wimp_ICON_BUTTON_TYPE_SHIFT |
      wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT |
      wimp_COLOUR_WHITE << wimp_ICON_BG_COLOUR_SHIFT;
  if (!(dialog_block->icons[dialog_icons].data.indirected_text.text = calloc(20, 1)))
  {
    free(dialog_block);
    dialog_id = DIALOG_NONE;
    gui_raise_error("memory");
  }
  dialog_block->icons[dialog_icons].data.indirected_text.validation = (char *) "kta;pptr_write,4,4";
  dialog_block->icons[dialog_icons].data.indirected_text.size = 20;

  dialog_icon[dialog_icons].type = ICON_NONE;
  dialog_icon[dialog_icons].help = help;

  dialog_icons++;
  dialog_y += 60;

  return (gui_gadget_id) dialog_icons - 1;
}


/*
 *  gui_create_text_box -- create a labelled display text box
 *
 *  => text -- label text
 *     value -- display text
 *
 *  <= gadget id
 *     0 if an error occurred
 */

gui_gadget_id gui_create_display_box(char *text, char *value, const char *help)
{
  assert(dialog_id != DIALOG_NONE);

  #ifdef DEBUG
  printf("gui_create_display_box: text = '%s'\n", text);
  fflush(stdout);
  #endif

  ensure_dialog_space();

  dialog_block->icons[dialog_icons].extent.x0 = 0;
  dialog_block->icons[dialog_icons].extent.y0 = -(dialog_y + 60);
  dialog_block->icons[dialog_icons].extent.x1 = dialog_block->extent.x1 * 0.25;
  dialog_block->icons[dialog_icons].extent.y1 = -dialog_y;
  dialog_block->icons[dialog_icons].flags = wimp_ICON_TEXT | wimp_ICON_RJUSTIFIED |
       wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED |
       wimp_BUTTON_NEVER << wimp_ICON_BUTTON_TYPE_SHIFT |
       wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT |
       wimp_COLOUR_VERY_LIGHT_GREY << wimp_ICON_BG_COLOUR_SHIFT;
  dialog_block->icons[dialog_icons].data.indirected_text.text = text;
  dialog_block->icons[dialog_icons].data.indirected_text.validation = 0;

  dialog_icon[dialog_icons].type = ICON_NONE;
  dialog_icon[dialog_icons].help = help;

  dialog_icons++;

  ensure_dialog_space();

  dialog_block->icons[dialog_icons].extent.x0 = dialog_block->extent.x1 * 0.25;
  dialog_block->icons[dialog_icons].extent.y0 = -(dialog_y + 56);
  dialog_block->icons[dialog_icons].extent.x1 = dialog_block->extent.x1 - 8;
  dialog_block->icons[dialog_icons].extent.y1 = -(dialog_y + 4);
  dialog_block->icons[dialog_icons].flags = wimp_ICON_TEXT | wimp_ICON_VCENTRED |
      wimp_ICON_INDIRECTED | wimp_ICON_BORDER | wimp_ICON_FILLED |
      wimp_BUTTON_NEVER << wimp_ICON_BUTTON_TYPE_SHIFT |
      wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT |
      wimp_COLOUR_VERY_LIGHT_GREY << wimp_ICON_BG_COLOUR_SHIFT;
  dialog_block->icons[dialog_icons].data.indirected_text.text = value;
  dialog_block->icons[dialog_icons].data.indirected_text.validation = (char *) "r2";
  dialog_block->icons[dialog_icons].data.indirected_text.size = 20;

  dialog_icon[dialog_icons].type = ICON_NONE;
  dialog_icon[dialog_icons].help = help;

  dialog_icons++;
  dialog_y += 60;

  return (gui_gadget_id) dialog_icons - 1;
}


/*
 *  gui_create_button -- create an action button
 *
 *  => text -- button text
 *     click_fn -- function called when button is clicked
 *
 *  <= nothing
 */

void gui_create_button(char *text, void (*click_fn)(gui_window_id window_id, gui_gadget_id gadget_id), const char *help)
{
  unsigned const int border = (dialog_x == dialog_block->extent.x1 ? 8 : 0);

  assert(dialog_id != DIALOG_NONE);

  #ifdef DEBUG
  printf("gui_create_button: text = '%s'\n", text);
  fflush(stdout);
  #endif

  ensure_dialog_space();

  if (dialog_x == dialog_block->extent.x1) dialog_y += 84;

  dialog_block->icons[dialog_icons].extent.x0 = dialog_x - 140 - border * 2;
  dialog_block->icons[dialog_icons].extent.y0 = -(dialog_y - 16 + border);
  dialog_block->icons[dialog_icons].extent.x1 = dialog_x - 8;
  dialog_block->icons[dialog_icons].extent.y1 = -(dialog_y - 68 - border);
  dialog_block->icons[dialog_icons].flags = wimp_ICON_TEXT | wimp_ICON_HCENTRED |
      wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_BORDER | wimp_ICON_FILLED |
      wimp_BUTTON_CLICK << wimp_ICON_BUTTON_TYPE_SHIFT |
      wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT |
      wimp_COLOUR_VERY_LIGHT_GREY << wimp_ICON_BG_COLOUR_SHIFT;
  dialog_block->icons[dialog_icons].data.indirected_text.text = text;
  dialog_block->icons[dialog_icons].data.indirected_text.validation =
      (dialog_x == dialog_block->extent.x1 ? (char *) "r6,3" : (char *) "r5,3");

  dialog_icon[dialog_icons].type = ICON_ACTION;
  dialog_icon[dialog_icons].click_fn = click_fn;
  dialog_icon[dialog_icons].help = help;

  dialog_icons++;
  dialog_x -= 140 + border * 2;
}
