/*
 * DeskFont, a simple example program using the Acorn Toolbox.
 * (c) Tony Howat / 20-20 Software, and RISC User 1995
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "kernel.h"
#include "swis.h"

#include "event.h"

#include "toolbox.h"
#include "iconbar.h"
#include "menu.h"
#include "fontmenu.h"
#include "wimplib.h"

#define MENU_FONTMENU    1
#define MENU_QUIT        2
#define MENU_SET         3

int message_list [] = {0};
int event_list   [] = {0};

MessagesFD    mfd;

IdBlock       id_blk;
WimpPollBlock poll_block;

void raise_error (_kernel_oserror *e);

void messages_lookup (MessagesFD messages_fd, char *token, char *buffer, int buffer_size, char *par1, char *par2, char *par3, char *par4, char **new_buffer, int *new_buffer_size) {

   /* Looks up token and passes back appropriate message */

   _kernel_oserror  *e;
   _kernel_swi_regs  regs;

   regs.r[0] = (int)  &messages_fd;
   regs.r[1] = (int)  token;
   regs.r[2] = (int)  buffer;
   regs.r[3] =        buffer_size;
   regs.r[4] = (int)  par1;
   regs.r[5] = (int)  par2;
   regs.r[6] = (int)  par3;
   regs.r[7] = (int)  par4;

   if ((e = _kernel_swi (MessageTrans_Lookup, &regs, &regs)) != NULL)
      raise_error (e);

   if (new_buffer) {
      *new_buffer      = (char *) regs.r[2];
   }
   if (new_buffer_size) {
      *new_buffer_size = regs.r[3];
   }
}

/* --- Given an error block, raise the error --- */

void raise_error (_kernel_oserror *e)
{
  _kernel_swi_regs regs;
  char *strng;
 
  /* Look up message tag '_TaskName' and point strng to it */
  messages_lookup (mfd, "_TaskName", NULL, 0, NULL, NULL, NULL, NULL,
                   &strng, NULL);
 
  /* Generate the error */
  regs.r[0] = (int) e;
  regs.r[1] = 16;
  regs.r[2] = (int) strng;
 
  _kernel_swi (Wimp_ReportError, &regs, &regs);
}

/* --- Good-bye! --- */

int wimp_quit (WimpMessage *message, void *h) {
  /* nothing to tidy up */
  exit(0);
  return(0); /* Keep the compiler happy */
}

/* --- This handles selections on the iconbar menu, the only item  --- */
/* --- we actually need to handle is quit, the rest are done by the --- */
/* --- toolbox according to the settings in our resources file --- */

int menu_selection (int event_code, ToolboxEvent *event_block,
                    IdBlock *id_blk, void *h)
{
  if (id_blk->self_component == MENU_QUIT) /* A click on Quit in the menu */
     wimp_quit(0,0);

  if (id_blk->self_component == MENU_SET) { 
     char buffer[40];

     if(_kernel_getenv("Wimp$Font", buffer, 40) == NULL) {
        FILE *out;
        _kernel_swi_regs  regs;
        
        if((out=fopen("Boot:Choices.Boot.PreDesk.DeskFont","wt")) != NULL) {
          fprintf(out,"Set Wimp$Font %s\n",buffer);
          fclose(out);

          regs.r[0] = 18;
          regs.r[1] = (int)"Boot:Choices.Boot.PreDesk.DeskFont";
          regs.r[2] = 0xfeb;
          _kernel_swi (OS_File, &regs, &regs);
        }
     }
  }

  return 1; /* Claim the event */
}

/* --- this is called just before the font menu opens so we can set --- */
/* --- which font to tick --- */

int setup_values (int event_code, ToolboxEvent *event_block,
                 IdBlock *id_blk, void *h)
{
  ObjectId fmid;
  char buffer[40];

  /** Now, find the object ID of the FontMenu **/
  menu_get_sub_menu_show(1,id_blk->self_id,MENU_FONTMENU,&fmid);

  if(_kernel_getenv("Wimp$Font", buffer, 40) == NULL)
    fontmenu_set_font(0, fmid, buffer);

  return 0;
}


/* --- the toolbox wants us to report an error --- */

int error_handler (int event_code, ToolboxEvent *event_block,
                   IdBlock *id_blk, void *h)
{
  raise_error ((_kernel_oserror *)event_block->data.bytes);
  return 1;
}

/* --- changes the desktop font by resetting wimp$font and sending a --- */
/* --- font_change WIMP message --- */

static void change_desktop_font(char *font)
{
  _kernel_swi_regs r;
  int msblock[20]={20,0,0,0,0x400cf}; /* our message */

  /* Set the variable to the font id the object sent us */

  r.r[0]=(int)"Wimp$Font";
  r.r[3]=0;
  r.r[4]=4;
    
  if (!strcmp(font,"SystemFont"))
  {
    r.r[1]=0;    /* with these settings we will delete the variable */
    r.r[2]=-1;  
  } else {
    r.r[1]=(int)font;
    r.r[2]=strlen(font);
  }

  _kernel_swi(OS_SetVarVal,&r,&r);

  /* now get the wimp to recognise the new font, send a fontchange message */

  wimp_send_message(17,msblock,0,0,msblock);
}

/* -- Called when there has been a click on an item in the Font Menu -- */

static int gotafont (int event_code, ToolboxEvent *event_block,
                    IdBlock *id_blk, void *h)
{
  /* obtain a pointer to a FontMenuSelectionEvent structure from the
   * event_block passed to us */
  FontMenuSelectionEvent *fmse=(FontMenuSelectionEvent *)event_block;

  /* Throw the font name to our font change procedure */
  change_desktop_font(fmse->font_id);

  return 1;
}

/* --- Called when a click event occurs --- */

int bar_click (int event_code, ToolboxEvent *event_block,
               IdBlock *id_blk, void *h)
{
  /* get a IconbarClickedEvent pointer from the ToolboxEvent pointer
   * supplied */
  IconbarClickedEvent *ibc=(IconbarClickedEvent *)event_block;

  if(ibc->hdr.flags & Iconbar_Clicked_Adjust)
    change_desktop_font("Homerton.Medium");
    
  return 1;
}

/* --- Initialise toolbox resources --- */
static void initialise (void)
{
  _kernel_oserror *e;

  if ((e = toolbox_initialise (0, 310, message_list, event_list,
       "<DeskFont$Dir>", &mfd, &id_blk, NULL, NULL, NULL)) != NULL) {
     raise_error (e);
     exit (1); /* Fatal */
  }

  event_initialise (&id_blk); /* this leaves us our id */
  event_set_mask (1+256);

  /* - register event handlers - */

  /* we catch Menu_AboutToBeShown so we can get the current Wimp$Font
   * ticked before the Font window appears - due to a bug in FontMenu
   * we can't catch FontMenu_AboutToBeShown
   */
  event_register_toolbox_handler(-1, Menu_AboutToBeShown,
                                 setup_values, NULL);

  /* catch iconbar clicks */
  event_register_toolbox_handler(-1, Iconbar_Clicked,
                                 bar_click, NULL);

  /* catch all selections from the font menu */
  event_register_toolbox_handler(-1, FontMenu_Selection, gotafont, NULL);

  /* catch all selections from all traditional menus (in this case there
   * is only our icon bar menu
   */
  event_register_toolbox_handler(-1, Menu_Selection, menu_selection, NULL);

  /* these two are self explanatory */
  event_register_toolbox_handler(-1, Toolbox_Error, error_handler, NULL);
  event_register_message_handler(Wimp_MQuit, wimp_quit, NULL);
}

/* --- main routine --- */

int main (void)
{
   int event_code;

   initialise();

   /* Poll loop - never catches anything because we rely on
      registered handlers */

   while (1)
      event_poll (&event_code, &poll_block, NULL);
}
