/**
 * Nettle Choices code
 * (C) Nettle developers 2000-2003
 *
 * $Id: choices,v 1.42 2010/04/11 21:39:02 archifishal Exp $
 */

#include "generic.h"
#include "globals.h"

#include "choices.h"
#include "hotlist.h"
#include "lineedit.h"
#include "messages.h"
#include "misc.h"
#include "templ.h"
#include "wimp.h"
#include "wimputil.h"
#include "zapredraw.h"

/* FIXME archifishal 11/04/2010: The version of errno.h I have doesn't build
 * with -c90 defined, for now just define 'errno' locally */
/*#include <errno.h>*/

#define errno __errno
extern int errno;

#include <time.h>

static colour_t get_colour_icon(int colour_handle, bool is_an_icon);

static void read_choice(char *variable, const char *line, const char *lookfor)
{
  int len=strlen(lookfor);

  if (strncmp(line,lookfor,len)==0)
  {
    strcpy(variable, line+len);
  }
}



static void read_boolean_choice(bool *var, const char *line, const char *lookfor)
{
  int len = strlen(lookfor);

  if (strncmp(line,lookfor,len)==0)
  {
    if (strncmp(line+len,"1",1) == 0)
    {
      *var=true;
    }
    else
    {
      *var=false;
    }
  }
}



static void read_integer_choice(int *var, const char *line, const char *lookfor)
{
  int len=strlen(lookfor);

  if (strncmp(line,lookfor,len)==0)
  {
    *var=atoi(line+len);
  }
}

static void read_terminal_choice(enum nettle_terminal *var, const char *line,const char *lookfor)
{
  int len=strlen(lookfor);

  if (strncmp(line,lookfor,len)==0)
  {
    *var=(enum nettle_terminal) atoi(line+len);
  }
}


static void read_character_choice(char *var, const char *line, const char *lookfor)
{
  int len=strlen(lookfor);

  if (strncmp(line,lookfor,len)==0)
  {
    *var=atoi(line+len);
  }
}


void load_choices(void)
{
  FILE *file_handle;
  char choices_path[256];
  char string[256];
  struct coords new_termsize = defaultsize;
  int new_scrollback = defaultscroll;
  int new_line_editor_size = line_editor_size;
  enum nettle_terminal new_default_terminal = default_terminal;
  colour_t new_palette[16];
  bool valid_palette=true;

  memcpy(new_palette, default_palette, sizeof(default_palette));

  get_system_variable(choices_path, "Choices$Write", sizeof(choices_path));

  if (choices_path[0]=='\0')
  {
    sprintf(string, "<%s$Dir>.Choices", application_name);
  }
  else
  {
    sprintf(string, "Choices:%s", application_name);
  }

  strcat(string, ".Choices");

  file_handle=fopen(string,"r");
  if (file_handle==NULL)
  {
    /* If the file doesn't exist, drop back to using default choices file */
    sprintf(string, "<%s$Dir>.Choices.Default", application_name);
    file_handle=fopen(string, "r");
    if (file_handle==NULL)
      return;
  }

  while (true)
  {
    char *str=fgets(string, sizeof(string), file_handle);
    int len;

    if (!str)
      break;

    len=strlen(string);
    if (string[len-1]=='\n')
      string[len-1]='\0';

    read_integer_choice(&choices_file_version_number, string, "Version:");
    if (choices_file_version_number>CHOICES_VERSION_KNOWN)
      break;

    read_choice(zap_font, string, "ZapFontHi:");
    read_choice(zap_lowres_font, string, "ZapFontLo:");

    read_boolean_choice(&logging, string, "Logging:");
    read_character_choice(&line_editor, string, "LineEditor:");
    read_boolean_choice(&pass_f12, string, "PassF12:");
    read_boolean_choice(&cursor_blink, string, "CursorBlink:");
    read_boolean_choice(&blinking, string, "Blinking:");
    read_boolean_choice(&dont_require_ctrl, string, "DontRequireCtrl:");
    read_boolean_choice(&scroll_on_keypress, string, "ScrollOnKeypress:");
    read_integer_choice((int*)&cursor_type, string, "CursorType:");

    read_terminal_choice(&new_default_terminal, string, "TerminalType:");
    read_integer_choice(&new_termsize.x, string, "TerminalWidth:");
    read_integer_choice(&new_termsize.y, string, "TerminalHeight:");
    read_integer_choice(&new_scrollback, string, "TerminalScroll:");
    read_integer_choice(&new_line_editor_size, string, "LineEditorSize:");

    if (!strncmp(string, "Palette:", 8))
    {
      int loop;
      str = string+8;
      for (loop=0; loop<16; loop++)
      {
        errno=0;
        new_palette[loop]=strtoul(str, &str, 16) << 8;
        if (errno)
        {
          valid_palette=false; /* invalid */
          break;
        }
      }
    }
  }

  if (choices_file_version_number>CHOICES_VERSION_KNOWN)
  {
    char buffer[4];
    sprintf(buffer, "%d", choices_file_version_number);

    generror(lookup_static_var("ChoicesNotKnown", 1, buffer), false);
  }
  else
  {
    switch (choices_file_version_number)
    {
      case 0:
        if (line_editor==LINEEDIT_CHECKBOX_OFF)
          line_editor=LINEEDIT_CHECKBOX_ON;
        else if (line_editor==LINEEDIT_CHECKBOX_ON)
          line_editor=LINEEDIT_ANTTERM;

        break;
    }

    fclose(file_handle);

    /* sanity checking in case of breakage through direct edit */
    /* May sanity check fonts, although if they're wrong, it'll default back to 08x16/08x08 */
    if (new_termsize.x >= MIN_TERMINAL_WIDTH && new_termsize.x <= MAX_TERMINAL_WIDTH)
      defaultsize.x = new_termsize.x;

    if (new_termsize.y >= MIN_TERMINAL_HEIGHT && new_termsize.y <= MAX_TERMINAL_HEIGHT)
      defaultsize.y = new_termsize.y;

    if (new_scrollback >= 0 && new_scrollback <= MAX_SCROLLBACK_SIZE)
      defaultscroll=new_scrollback;

    if (new_line_editor_size > 0 && new_line_editor_size <= MAX_LINE_EDITOR_SIZE)
      line_editor_size = new_line_editor_size;

    if (new_default_terminal >= 0 && new_default_terminal < NO_OF_TERMINAL_TYPES)
      default_terminal = new_default_terminal;

    /* Check that the cursor type is known */
    {
      char cstring[16];
      sprintf(cstring,"Cursor%d",cursor_type);
      if (lookup_inbuffer(cstring) == NULL)
        cursor_type = cursor_solid; /* Reset to solid, if invalid */
    }

    /* If palette is valid then copy it as the default */
    if (valid_palette)
      memcpy(palette, new_palette, sizeof(palette));
  }
}

bool save_choices(void)
{
  char choices_path[256];
  char string[512];

  get_system_variable(choices_path, "Choices$Write", sizeof(choices_path));

  if (choices_path[0]=='\0')
  {
    sprintf(string, "<%s$Dir>.Choices", application_name);
  }
  else
  {
    sprintf(string, "<Choices$Write>.%s", application_name);
  }

  _swi(OS_File, _INR(0,1)|_IN(4), 8, string, 0);
  strcat(string, ".Choices");

  _kernel_last_oserror();

  {
    bool error=false;
    FILE *file_handle=fopen(string, "w");

    if (file_handle==NULL)
    {
      /* Couldn't open the file for writing */
      error=true;
    }
    else
    {
      int loop;
      time_t current_time;

      time(&current_time);

      fprintf(file_handle, "# Nettle choices file\n");
      fprintf(file_handle, "# Created on %s\n", ctime(&current_time));
      fprintf(file_handle, "Version:1\n");
      fprintf(file_handle, "ZapFontHi:%s\n", zap_font);
      fprintf(file_handle, "ZapFontLo:%s\n", zap_lowres_font);

      fprintf(file_handle, "Logging:%d\n", (logging==true) ? 1 : 0);
      fprintf(file_handle, "PassF12:%d\n", (pass_f12==true) ? 1 : 0);
      fprintf(file_handle, "CursorBlink:%d\n", (cursor_blink==true) ? 1 : 0);
      fprintf(file_handle, "Blinking:%d\n", (blinking==true) ? 1 : 0);
      fprintf(file_handle, "DontRequireCtrl:%d\n", (dont_require_ctrl==true) ? 1 : 0);
      fprintf(file_handle, "ScrollOnKeypress:%d\n", (scroll_on_keypress==true) ? 1 : 0);
      fprintf(file_handle, "CursorType:%d\n", cursor_type);

      fprintf(file_handle, "TerminalType:%d\n", default_terminal);
      fprintf(file_handle, "TerminalWidth:%d\n", defaultsize.x);
      fprintf(file_handle, "TerminalHeight:%d\n", defaultsize.y);
      fprintf(file_handle, "TerminalScroll:%d\n", defaultscroll);
      fprintf(file_handle, "LineEditor:%d\n", line_editor);
      fprintf(file_handle, "LineEditorSize:%d\n", line_editor_size);

      fputs("Palette:", file_handle);

      for (loop=0; loop<16; loop++)
        fprintf(file_handle, "%06lX ", palette[loop] >> 8);

      fputc('\n', file_handle);

      if (!ferror(file_handle))
      {
        if (fclose(file_handle))
          error=true;

        file_handle=NULL;
      }
    }

    if (error)
    {
      gensaveerror(file_handle, "CantSaveChoices");
      return false;
    }

    return true;
  }
}




void close_choices_window(void)
{
  if (win_is_open(win_paneterm))
    close_window(win_paneterm);

  if (win_is_open(win_panecols))
    close_window(win_panecols);

  if (win_is_open(win_panehot))
    close_window(win_panehot);

  if (win_is_open(win_panemisc))
    close_window(win_panemisc);

  close_window(win_choices);
}


void open_choices_window(void)
{
  char string[32];

  /* Select paneterm */
  set_icon_state(win_choices, icon_choices_size, WIMP_ICON_SELECTED_BIT, WIMP_ICON_SELECTED_BIT);
  set_icon_state(win_choices, icon_choices_colour, 0, WIMP_ICON_SELECTED_BIT);
  set_icon_state(win_choices, icon_choices_hotlist, 0, WIMP_ICON_SELECTED_BIT);
  set_icon_state(win_choices, icon_choices_misc, 0, WIMP_ICON_SELECTED_BIT);

  /* Set paneterm type options */
  set_icon_data(win_paneterm, icon_paneterm_termtype, terminal_name[default_terminal]);
  set_termsize_icons(win_paneterm, icon_paneterm_termwidth, icon_paneterm_termheight, icon_paneterm_scrollback, defaultsize, defaultscroll);
  sprintf(string, "%d", line_editor_size);
  set_icon_data(win_paneterm, icon_paneterm_lineeditor, string);

  {
    char string_lineedit[32];

    sprintf(string_lineedit,"LineEd%d",line_editor);
    set_icon_data(win_paneterm, icon_paneterm_lineedittype, lookup(string_lineedit, string, sizeof(string)));
  }

  {
    char string_cursortype[32];

    sprintf(string_cursortype,"Cursor%d",cursor_type);
    set_icon_data(win_panemisc, icon_panemisc_cursortype, lookup(string_cursortype, string, sizeof(string)));
  }

  set_icon_data(win_paneterm, icon_paneterm_hifont, zap_font);
  set_icon_data(win_paneterm, icon_paneterm_lofont, zap_lowres_font);

  /* Set panecol type options */
  {
    int loop;

    for (loop = 15; loop >= 0; --loop)
      set_colour_icon (loop, palette[loop], false);
  }

  /* Set panemisc type options */
  set_icon_state(win_panemisc, icon_panemisc_passf12, (pass_f12==true) ? WIMP_ICON_SELECTED_BIT : 0, WIMP_ICON_SELECTED_BIT);
  set_icon_state(win_panemisc, icon_panemisc_blinking, (blinking==true) ? WIMP_ICON_SELECTED_BIT : 0, WIMP_ICON_SELECTED_BIT);
  set_icon_state(win_panemisc, icon_panemisc_cursorblink, (cursor_blink==true) ? WIMP_ICON_SELECTED_BIT : 0, WIMP_ICON_SELECTED_BIT);
  set_icon_state(win_panemisc, icon_panemisc_dontrequirectrl, (dont_require_ctrl==true) ? WIMP_ICON_SELECTED_BIT : 0, WIMP_ICON_SELECTED_BIT);
  set_icon_state(win_panemisc, icon_panemisc_scrollonkey, (scroll_on_keypress==true) ? WIMP_ICON_SELECTED_BIT : 0, WIMP_ICON_SELECTED_BIT);

  if (win_is_open(win_choices))
    open_window(NULL, win_choices);
  else
  {
    open_window_centred(win_choices);
    set_caret_position(win_paneterm, icon_paneterm_termwidth, -1, get_icon_data_length(win_paneterm, icon_paneterm_termwidth));
  }

  resize_hotpane();
  close_window(win_panehot);
  close_window(win_panecols);
  close_window(win_panemisc);
}


bool win_choices_read(int save)
{
  struct coords new_termsize;
  int new_scrollback;
  int new_line_editor_size;
  enum nettle_terminal new_default_terminal;
  char new_zap_font[256];
  char new_zap_lowres_font[256];
  char string[32];
  bool changed = false;
  int old_charw=redraw.r_charw;
  int old_charh=redraw.r_charh;

  /* Read paneterm type options */
  {
    char terminal_type_string[MESSAGE_MAX_TERMINAL];
    int counter=0;

    read_icon_data(win_paneterm, icon_paneterm_termtype, terminal_type_string,
                   MESSAGE_MAX_TERMINAL);

    while (counter<NO_OF_TERMINAL_TYPES &&
           strcmp(terminal_type_string, terminal_name[counter]))
    {
      counter++;
    }

    if (counter!=NO_OF_TERMINAL_TYPES)
    {
      new_default_terminal=(enum nettle_terminal) counter;
    }
    else
    {
      generror("BadTermType", true);
      return false;
    }
  }

  if (!read_termsize_icons (win_paneterm, icon_paneterm_termwidth, icon_paneterm_termheight,
                            icon_paneterm_scrollback, &new_termsize, &new_scrollback))
    return false;

  new_line_editor_size = atoi (read_icon_data (win_paneterm, icon_paneterm_lineeditor, string, sizeof (string)));


  if (new_line_editor_size < 1 || new_line_editor_size > MAX_LINE_EDITOR_SIZE)
  {
    generror ("BadLineEdSize", true);
    return false;
  }

  line_editor_size=new_line_editor_size;

  strcpy(new_zap_font, read_icon_data(win_paneterm, icon_paneterm_hifont, string, sizeof(string)));
  strcpy(new_zap_lowres_font, read_icon_data(win_paneterm, icon_paneterm_lofont, string, sizeof(string)));

  line_editor=read_lineeditor_type(win_paneterm, icon_paneterm_lineedittype);

  /* Read panecols type options */
  {
    int loop;
    for (loop=15; loop>=0; loop--)
    {
      colour_t colour = get_colour_icon (loop, false);
      if (colour != palette[loop])
      {
        palette[loop] = colour;
        changed=true;
      }
    }

  }

  /* Read panemisc type options */
  if (read_icon_ticked(win_panemisc, icon_panemisc_passf12))
    pass_f12=true;
  else
    pass_f12=false;

  if (read_icon_ticked(win_panemisc, icon_panemisc_blinking))
    blinking=true;
  else
    blinking=false;

  if (read_icon_ticked(win_panemisc, icon_panemisc_cursorblink))
    cursor_blink=true;
  else
    cursor_blink=false;

  if (read_icon_ticked(win_panemisc, icon_panemisc_dontrequirectrl))
    dont_require_ctrl=true;
  else
    dont_require_ctrl=false;

  if (read_icon_ticked(win_panemisc, icon_panemisc_scrollonkey))
    scroll_on_keypress=true;
  else
    scroll_on_keypress=false;

  /* Read the cursor type in use */
  {
    char cursor_type_string[32];
    int counter=0;

    read_icon_data(win_panemisc, icon_panemisc_cursortype, cursor_type_string,
                   sizeof(cursor_type_string));

    while (1)
    {
      char cursor_tok[32];
      char *name;
      int namelen;
      sprintf(cursor_tok,"Cursor%d",counter);
      name = lookup_inbuffer(cursor_tok);

      if (name == NULL)
      {
        counter=-1;
        break;
      }

      namelen = strchr(name, '\n') - name; /* inbuffer returns \n terminated */
      if (strncmp(cursor_type_string,name,namelen) == 0 &&
          cursor_type_string[namelen] == '\0')
        break;

      counter++;
    }

    if (counter==-1)
        counter=0; /* default to block cursor - should never happen */

    if (cursor_type != (cursor_t) counter)
    {
      changed = true;
      cursor_type = (cursor_t) counter;
      /* Updating the cursors here may result in the cursors being
       * written twice if the font is also changed; it's not a
       * stressful operation anyhow
       */
      update_cursors(zap_font_area);
      update_cursors(zap_lowres_font_area);
    }
  }

  /* make the choices in the new_* variables permanent */
  default_terminal = new_default_terminal;
  defaultsize = new_termsize;
  defaultscroll = new_scrollback;

  /* Load in new zap fonts */
  if (strcmp(zap_font, new_zap_font)!=0)
  {
    free(zap_font_area);
    strcpy(zap_font, new_zap_font);
    zap_font_area=load_font(zap_font);
    changed = true;
  }

  if (strcmp(zap_lowres_font, new_zap_lowres_font)!=0)
  {
    free(zap_lowres_font_area);
    strcpy(zap_lowres_font, new_zap_lowres_font);
    zap_lowres_font_area=load_font(zap_lowres_font);
    changed = true;
  }

  /* Resize & redraw; also updates the palette */
  if (changed)
  {
    struct session_struct *session = sessions;

    mode_change();
    while (session)
    {
      reopen_and_size_window(session, session->terminal_size.x, session->terminal_size.y,
                             session->scrollback, old_charw, old_charh, eig);
      session->window_needs_resized=false;
      session=session->next;
    }
  }

  if (save == false)
    return finish_hotlist_editing(1);

  /* if we're saving, save now */
  if (save_choices() == false)
    return false;

  return finish_hotlist_editing(2);
}

void set_colour_icon(int colour_handle, colour_t colour, bool is_an_icon)
{
  int icon_handle=-1;
  char *validation;

  if (is_an_icon)
  {
    icon_handle=colour_handle;
  }
  else
  {
    if (colour_handle>=0 && colour_handle<=7)
      icon_handle=colour_handle;

    if (colour_handle>=8 && colour_handle<=15)
      icon_handle=colour_handle-8+icon_panecols_bold0;
  }

  if (icon_handle==-1)
  {
    char string[128];

    sprintf(string,"Failed to set icon handle for set_colour_icon (colour_handle %d)",colour_handle);
    generror(string,false);
    return;
  }

  validation = get_icon_validation(win_panecols, icon_handle);

  sprintf(validation, "R2;C/%06X", ((unsigned int) colour) >> 8);

  set_icon_state (win_panecols, icon_handle, 0, 0);
}

static colour_t get_colour_icon(int colour_handle, bool is_an_icon)
{
  int icon_handle=-1;
  const char *validation;
  colour_t colour;

  if (is_an_icon)
  {
    icon_handle=colour_handle;
  }
  else
  {
    if (colour_handle>=0 && colour_handle<=7)
      icon_handle=colour_handle;

    if (colour_handle>=8 && colour_handle<=15)
      icon_handle=colour_handle-8+icon_panecols_bold0;
  }

  if (icon_handle==-1)
  {
    generror("Failed to set icon handle for get_colour_icon",false);
    return (colour_t) 0;
  }

  validation = get_icon_validation (win_panecols, icon_handle);

  colour = strtoul(validation + 5, NULL, 16);
  return (colour << 8);
}


void win_choices_click (int x, int y, int buttons, int icon_handle)
{
  close_window(win_hotedit);

  switch (icon_handle)
  {
    case icon_choices_size:
      if (win_is_open(win_panecols))
        close_window(win_panecols);

      if (win_is_open(win_panehot))
        close_window(win_panehot);

      if (win_is_open(win_panemisc))
        close_window(win_panemisc);

      set_icon_state(win_choices, icon_choices_size, WIMP_ICON_SELECTED_BIT, WIMP_ICON_SELECTED_BIT);
      set_icon_state(win_choices, icon_choices_colour, 0, WIMP_ICON_SELECTED_BIT);
      set_icon_state(win_choices, icon_choices_hotlist, 0, WIMP_ICON_SELECTED_BIT);
      set_icon_state(win_choices, icon_choices_misc, 0, WIMP_ICON_SELECTED_BIT);

      {
        struct wimp_getwindowstate_block block;

        block.window_handle=win_choices;
        _swi(Wimp_GetWindowState, _IN(1), &block);

        open_window((struct wimp_openwindow_block *) &block, win_choices);

        set_caret_position(win_paneterm, icon_paneterm_termwidth, -1, get_icon_data_length(win_paneterm, icon_paneterm_termwidth));
      }

      break;

    case icon_choices_colour:
      if (win_is_open(win_paneterm))
        close_window(win_paneterm);

      if (win_is_open(win_panehot))
        close_window(win_panehot);

      if (win_is_open(win_panemisc))
        close_window(win_panemisc);

      set_icon_state(win_choices, icon_choices_size, 0, WIMP_ICON_SELECTED_BIT);
      set_icon_state(win_choices, icon_choices_colour, WIMP_ICON_SELECTED_BIT, WIMP_ICON_SELECTED_BIT);
      set_icon_state(win_choices, icon_choices_hotlist, 0, WIMP_ICON_SELECTED_BIT);
      set_icon_state(win_choices, icon_choices_misc, 0, WIMP_ICON_SELECTED_BIT);

      {
        struct wimp_getwindowstate_block block;

        block.window_handle=win_choices;
        _swi(Wimp_GetWindowState, _IN(1), &block);

        open_window((struct wimp_openwindow_block *) &block, win_choices);
      }

      break;

    case icon_choices_hotlist:
      if (win_is_open(win_paneterm))
        close_window(win_paneterm);

      if (win_is_open(win_panecols))
        close_window(win_panecols);

      if (win_is_open(win_panemisc))
        close_window(win_panemisc);

      set_icon_state(win_choices, icon_choices_size, 0, WIMP_ICON_SELECTED_BIT);
      set_icon_state(win_choices, icon_choices_colour, 0, WIMP_ICON_SELECTED_BIT);
      set_icon_state(win_choices, icon_choices_hotlist, WIMP_ICON_SELECTED_BIT, WIMP_ICON_SELECTED_BIT);
      set_icon_state(win_choices, icon_choices_misc, 0, WIMP_ICON_SELECTED_BIT);

      {
        struct wimp_getwindowstate_block block;

        block.window_handle=win_choices;
        _swi(Wimp_GetWindowState, _IN(1), &block);

        open_window((struct wimp_openwindow_block *) &block, win_choices);
      }

      break;

    case icon_choices_misc:
      if (win_is_open(win_paneterm))
        close_window(win_paneterm);

      if (win_is_open(win_panecols))
        close_window(win_panecols);

      if (win_is_open(win_panehot))
        close_window(win_panehot);

      set_icon_state(win_choices, icon_choices_size, 0, WIMP_ICON_SELECTED_BIT);
      set_icon_state(win_choices, icon_choices_colour, 0, WIMP_ICON_SELECTED_BIT);
      set_icon_state(win_choices, icon_choices_hotlist, 0, WIMP_ICON_SELECTED_BIT);
      set_icon_state(win_choices, icon_choices_misc, WIMP_ICON_SELECTED_BIT, WIMP_ICON_SELECTED_BIT);

      {
        struct wimp_getwindowstate_block block;

        block.window_handle=win_choices;
        _swi(Wimp_GetWindowState, _IN(1), &block);

        open_window((struct wimp_openwindow_block *) &block, win_choices);
      }

      break;

    case icon_choices_save:
      if (win_choices_read(true) && save_choices() && (buttons & 1) == 0)
        close_choices_window();
      break;

    case icon_choices_cancel:
      if ((buttons & 1) == 0)
        close_choices_window();
      else
        open_choices_window();

      finish_hotlist_editing(0);
      break;

    case icon_choices_set:
      if (win_choices_read(false) && (buttons & 1) == 0)
        close_choices_window();
      break;
  }
}


void win_paneterm_click(int x, int y, int buttons, int icon_handle)
{
  switch (icon_handle)
  {
    case icon_paneterm_termtypebut:
      create_terminal_type_menu(win_paneterm, icon_paneterm_termtype, icon_paneterm_termtypebut);
      break;

    case icon_paneterm_lineeditbut:
      create_lineeditor_type_menu(win_paneterm, icon_paneterm_lineedittype, icon_paneterm_lineeditbut);
      break;

    case icon_paneterm_hifontbut:
    case icon_paneterm_lofontbut:
      if (create_zap_font_menu (win_paneterm, icon_handle))
      {
        menu_window = win_paneterm;

        if (icon_handle==icon_paneterm_hifontbut)
          menu_icon = icon_paneterm_hifont;
        else
          menu_icon = icon_paneterm_lofont;

        menu_open = MENU_ZAPFONTLIST;
      }
      break;
  }
}


void win_panecols_click(int x, int y, int buttons, int icon_handle)
{
  /* Not terribly optimal */
  if ((icon_handle>=icon_panecols_col0but  && icon_handle<=icon_panecols_col7but) ||
      (icon_handle>=icon_panecols_bold0but && icon_handle<=icon_panecols_bold7but))
  {
    /* open a ColourPicker window (as a menu) */
    static char title[64];
    struct colourpicker_block block;
    struct wimp_geticonstate_block icon;
    struct wimp_getwindowstate_block window;

    strcpy(title, lookup_static("SelColour"));

    window.window_handle = win_panecols;
    icon.window_handle = win_panecols;
    icon.icon_handle = icon_handle;
    _swi (Wimp_GetWindowState, _IN(1), &window);
    _swi (Wimp_GetIconState, _IN(1), &icon);

    block.flags = 0;
    block.title = title;
    block.bl.x = window.min.x + icon.max.x;
    block.bl.y = (int) 0x80000000;
    block.tr.x = (int) 0x7FFFFFFF;
    block.tr.y = window.max.y + icon.max.y;
    block.zero1 = block.zero0 = 0;
    block.colour = get_colour_icon(icon_handle-8, true);
    block.extsize = block.exttype = 0;
    colourpicker_handle = _swi (ColourPicker_OpenDialogue,
                          _INR(0,1) | _OUT(1), 1, &block, &menu_window);

    menu_icon = icon_handle-8; /* icon_handle-8 may change */
    menu_open = MENU_NONE;
  }

  if (icon_handle==icon_panecols_default)
  {
    int loop;
    for (loop=15; loop>=0; loop--)
    {
      set_colour_icon (loop, default_palette[loop], false);
    }
  }
  else if (icon_handle==icon_panecols_invertall)
  {
    int loop;
    for (loop=15; loop>=0; loop--)
    {
      /* It's important to invert the colour in the icon here, NOT the palette[] value */
      unsigned long colour = get_colour_icon(loop, false);
      set_colour_icon (loop, colour^0xffffff00, false);
    }
  }
}

void win_panemisc_click(int x, int y, int buttons, int icon_handle)
{
  switch (icon_handle)
  {
    case icon_panemisc_cursortypebut:
      create_cursor_type_menu(win_panemisc, icon_panemisc_cursortype, icon_panemisc_cursortypebut);
      break;
  }
}

