/*
 * Simple Toolbox application, showing how to DIY panes.
 */

#include <stdlib.h>
#include "wimp.h"
#include "toolbox.h"
#include "event.h"
#include "wimplib.h"
#include "window.h"
#include <string.h>

#define WimpVersion    310

#define E_CHECK(a) if((a) != NULL) { wimp_error(a); }
#define E_CHECK_ABORT(a) if((a) != NULL) { wimp_error(a);exit(0);}

static  WimpPollBlock  poll_block;
static  MessagesFD     messages;
static  IdBlock        id_block;
ObjectId	       MainWin;
ObjectId	       PaneWin;

void wimp_error(_kernel_oserror *er)
{
  /*
   * Generic routine to handle error reporting
   * through the wimp
   */

  _kernel_swi_regs regs;

  regs.r[0] = (int) er;
  regs.r[1] =       0;
  regs.r[2] = (int) "Pane";
  _kernel_swi(Wimp_ReportError, &regs, &regs);
}

/*
 * Open Pane Window
 */

void OpenPaneWindow(WimpOpenWindowBlock* parent, int panehandle)
{
  WindowShowObjectBlock o;

  o.visible_area.xmin = parent->visible_area.xmin + 100;
  o.visible_area.ymax = parent->visible_area.ymax - 100;
  o.visible_area.ymin = parent->visible_area.ymin + 100;
  o.visible_area.xmax = parent->visible_area.xmax - 100;
  //o.xscroll = 0;
  //o.yscroll = 0;
  o.behind = parent->behind;
  toolbox_show_object(0, PaneWin, 1, &o, 0, 0);
}

/*
 * Open main window
 */

void OpenMainWindow(WimpOpenWindowBlock* event)
{
  int paneh, mainh;
  WimpGetWindowStateBlock state;
  window_get_wimp_handle(0, PaneWin, &paneh);
  window_get_wimp_handle(0, MainWin, &mainh);
  OpenPaneWindow(event, paneh);

  if ((event->visible_area.xmax - event->visible_area.xmin) < 300)
    event->visible_area.xmax = event->visible_area.xmin + 300;
  if ((event->visible_area.ymax - event->visible_area.ymin) < 300)
    event->visible_area.ymin = event->visible_area.ymax - 300;

  event->behind = paneh;
  toolbox_show_object(0, MainWin, 1, &(event->visible_area), 0, 0); // Open window


  // now check to ensure that the parent window has been opened where
  // we expected.  i.e. has it been "forced on screen" by the wimp

  state.window_handle = mainh;
  wimp_get_window_state(&state);
  if((memcmp((void*) event, (void*) &state, 32)) != 0)
  {
    // if it's moved then re-open pane in correct place
    OpenPaneWindow((WimpOpenWindowBlock*) &state, paneh);
  }
}

/*
 * Call OpenMainWindow on a Wimp_OpenWindow request
 */

int OpenMainWindow_Callback(int x,WimpPollBlock* wpb,IdBlock* i,void* h)
{
  OpenMainWindow(&(wpb->open_window_request));
  return 1;
}

/*
 * Initiate the open window routine on an iconbar click
 * (Just sets up the window block for OpenMainWindow())
 */

int Initiate_OpenMainWindow(int x,ToolboxEvent* t,IdBlock* i,void* h)
{
  WimpGetWindowStateBlock block;
  int wh;
  window_get_wimp_handle(0, MainWin, &wh);
  block.window_handle = wh;
  wimp_get_window_state(&block);
  OpenMainWindow((WimpOpenWindowBlock*) &block);
  return 1;
}

/*
 * Close both windows on Wimp_CloseWindow event
 */

int MainW_Close(int event_code, WimpPollBlock* event, IdBlock* id_block, void* h)
{
  toolbox_hide_object(0, PaneWin);
  toolbox_hide_object(0, MainWin);
  return (1);
}


/*
 * Event handler to be called when toolbox event 1
 * is generated (by click on the 'Quit' entry of
 * the iconbar menu.
 */

int quit_event(int event_code, ToolboxEvent *event, IdBlock *id_block,void *handle)
{
  event_code = event_code;
  event = event;
  id_block = id_block;
  handle = handle;

  exit(0);
  return(1);
}


/*
 * Message handler to be called on receipt of a
 * Quit or PreQuit message from the Wimp.
 */


int quit_message(WimpMessage *message,void *handle)
{
  message = message;
  handle = handle;

  exit(0);
  return(1);
}

/*
 * Attach other handlers on object auto-creation.
 */

int attach_our_other_handlers(int event_code,ToolboxEvent *event,IdBlock *id_block, void *handle)
{
  _kernel_oserror *er;
  ObjectClass     obj_class;

  er = toolbox_get_object_class(0,id_block->self_id,&obj_class);

  switch(obj_class)
  {
    case Window_ObjectClass :
      if (strcmp(event->data.bytes,"Window") == 0)
      {
        MainWin = id_block->self_id;
        event_register_wimp_handler(MainWin, Wimp_EOpenWindow, OpenMainWindow_Callback,0);
        event_register_wimp_handler(MainWin, Wimp_ECloseWindow, MainW_Close,0);
        event_register_toolbox_handler(-1, 0x10, Initiate_OpenMainWindow, 0);
      }
      if (strcmp(event->data.bytes,"PaneWin") == 0)
      {
        PaneWin = id_block->self_id;
      }
      break;
  }
  return 0;
}

int main()
{
    int    toolbox_events = 0,
           wimp_messages = 0,
           event_code;

    /*
     * register ourselves with the Toolbox.
     */

    toolbox_initialise (0, WimpVersion, &wimp_messages, &toolbox_events, "<Pane$Dir>",
                        &messages, &id_block, 0, 0, 0);

    /*
     * initialise the event library.
     */

    event_initialise (&id_block);

    /*
     * register handler for toolbox event 1,
     * which is generated by the 'Quit' option on the
     * iconbar menu.  Also register message handlers
     * to quit properly when quit messages are
     * received from the wimp.
     */

    event_register_toolbox_handler(-1,1,quit_event,0);
    event_register_message_handler(Wimp_MQuit,quit_message,0);
    event_register_message_handler(Wimp_MPreQuit,quit_message,0);
    event_register_toolbox_handler(-1,Toolbox_ObjectAutoCreated,
                                    attach_our_other_handlers,NULL);

    /*
     * poll loop
     */

    while (TRUE)
    {
        event_poll (&event_code, &poll_block, 0);
    }
}
