/*
    ####             #    #     # #
    #   #            #    #       #          The FreeWare C library for 
    #   #  ##   ###  #  # #     # ###             RISC OS machines
    #   # #  # #     # #  #     # #  #   ___________________________________
    #   # ####  ###  ##   #     # #  #                                      
    #   # #        # # #  #     # #  #    Please refer to the accompanying
    ####   ### ####  #  # ##### # ###    documentation for conditions of use
    ________________________________________________________________________

    File:    Pane.c
    Author:  Copyright  1994 Ainsley Pereira. Major code rewrite by Keith Hall
    Version: 1.11 (30th March 94)
    Purpose: Handles windows with panes.
*/

#include <stdlib.h>

#include "Desk.Pane.h"
#include "Desk.DeskMem.h"

#include "PaneDefs.h"

Desk_pane_link *Desk_pane_root=NULL;
Desk_pane_link *curpane=NULL;


extern Desk_bool Desk_Pane_OpenEventHandler(Desk_event_pollblock *event,
                                  void *reference)
{
  Desk_window_state pstate;

  Desk_UNUSED( reference);
  
  curpane=Desk_pane_root;

  while(curpane)
  {
    if(event->data.openblock.window == curpane->panedata.master)
    {
      Desk_Wimp_GetWindowState(curpane->panedata.pane, &pstate);

      if(curpane->panedata.flags.data.fixed)
      {
        pstate.openblock.screenrect.max.y = event->data.openblock.screenrect.max.y - curpane->panedata.offset.y;
        pstate.openblock.screenrect.min.y = pstate.openblock.screenrect.max.y - curpane->panedata.size.y;
      }
      else
      {
        pstate.openblock.screenrect.min.y = event->data.openblock.screenrect.min.y +curpane->panedata.offset.y +42;
        pstate.openblock.screenrect.max.y = pstate.openblock.screenrect.min.y + curpane->panedata.size.y;
      }
      pstate.openblock.screenrect.min.x = event->data.openblock.screenrect.min.x + curpane->panedata.offset.x;

      if(curpane->panedata.flags.data.resize)
      {
        if(event->data.openblock.screenrect.max.x > pstate.openblock.screenrect.min.x + curpane->panedata.size.x)
          pstate.openblock.screenrect.max.x = pstate.openblock.screenrect.min.x + curpane->panedata.size.x;
        else
          pstate.openblock.screenrect.max.x = event->data.openblock.screenrect.max.x;
      }
      else
        pstate.openblock.screenrect.max.x = pstate.openblock.screenrect.min.x + curpane->panedata.size.x;
      pstate.openblock.behind = event->data.openblock.behind;
      Desk_Wimp_OpenWindow(&pstate.openblock);
      event->data.openblock.behind = curpane->panedata.pane;
      Desk_Wimp_OpenWindow(&event->data.openblock);
      return (Desk_bool_TRUE);
    }
    curpane=curpane->next;
  }
  return (Desk_bool_FALSE);
}

extern void Desk_Pane_Link(Desk_window_handle mast,
                      Desk_window_handle pane,
                      Desk_wimp_point   *offset,
                      Desk_wimp_point   *size,
                      int           flags)
{
  Desk_window_state maststate, panestate;

  Desk_Wimp_GetWindowState(mast, &maststate);
  Desk_Wimp_GetWindowState(pane, &panestate);

  if(Desk_pane_root == NULL)
  {
    curpane = Desk_pane_root = Desk_DeskMem_Calloc(1, sizeof(Desk_pane_link));
  }
  else
  {
    curpane->next = Desk_DeskMem_Calloc(1, sizeof(Desk_pane_link));
    curpane = curpane->next;
  }
  curpane->next = NULL;

  curpane->panedata.master = mast;
  curpane->panedata.pane = pane;
  curpane->panedata.flags.value = flags;
  curpane->panedata.flags.data.isopen = 0;

  if(offset)
    curpane->panedata.offset = *offset;
  else
  {
    curpane->panedata.offset.x = panestate.openblock.screenrect.min.x - maststate.openblock.screenrect.min.x;
    if(curpane->panedata.flags.data.fixed)
      curpane->panedata.offset.y = maststate.openblock.screenrect.max.y - panestate.openblock.screenrect.max.y;
    else
      curpane->panedata.offset.y = panestate.openblock.screenrect.min.y - maststate.openblock.screenrect.min.y -42;
  }

  if(size)
    curpane->panedata.size = *size;
  else
  {
    curpane->panedata.size.x = panestate.openblock.screenrect.max.x - panestate.openblock.screenrect.min.x;
    curpane->panedata.size.y = panestate.openblock.screenrect.max.y - panestate.openblock.screenrect.min.y;
  }
}

extern Desk_window_handle Desk_Pane_CreateAndLink(char        *mastname,
                                        char        *panename,
                                        int         mastmaxsize,
                                        int         panemaxsize,
                                        Desk_wimp_point *offset,
                                        Desk_wimp_point *size,
                                        int         flags)
{
  Desk_window_handle mast, pane;

  mast=Desk_Window_Create(mastname, mastmaxsize);
  pane=Desk_Window_Create(panename, panemaxsize);

  Desk_Pane_Link(mast, pane, offset, size, flags);

  return mast;
}

extern void Desk_Pane_Show(Desk_window_handle  window,
                      Desk_window_openpos openpos)
{
  Desk_window_state pstate;
  Desk_window_state mstate;
  curpane = Desk_pane_root;

  while(curpane)
  {
    if(curpane->panedata.master == window)
    {
      if(curpane->panedata.flags.data.isopen == 0)
      {
        Desk_Window_Show(curpane->panedata.master, openpos);
        Desk_Wimp_GetWindowState(curpane->panedata.master, &mstate);
        Desk_Wimp_GetWindowState(curpane->panedata.pane, &pstate);
  
        if(curpane->panedata.flags.data.fixed)
        {
          pstate.openblock.screenrect.max.y = mstate.openblock.screenrect.max.y - curpane->panedata.offset.y;
          pstate.openblock.screenrect.min.y = pstate.openblock.screenrect.max.y - curpane->panedata.size.y;
        }
        else
        {
          pstate.openblock.screenrect.min.y = mstate.openblock.screenrect.min.y +curpane->panedata.offset.y +42;
          pstate.openblock.screenrect.max.y = pstate.openblock.screenrect.min.y + curpane->panedata.size.y;
        }
        pstate.openblock.screenrect.min.x = mstate.openblock.screenrect.min.x + curpane->panedata.offset.x;
  
        if(curpane->panedata.flags.data.resize)
        {
          if(mstate.openblock.screenrect.max.x > pstate.openblock.screenrect.min.x + curpane->panedata.size.x)
            pstate.openblock.screenrect.max.x = pstate.openblock.screenrect.min.x + curpane->panedata.size.x;
          else
            pstate.openblock.screenrect.max.x = mstate.openblock.screenrect.max.x;
        }
        else
          pstate.openblock.screenrect.max.x = pstate.openblock.screenrect.min.x + curpane->panedata.size.x;
        pstate.openblock.behind = mstate.openblock.behind;
        Desk_Wimp_OpenWindow(&pstate.openblock);
        mstate.openblock.behind = curpane->panedata.pane;
        Desk_Wimp_OpenWindow(&mstate.openblock);

        curpane->panedata.flags.data.isopen = 1;
      }
    }
    curpane = curpane->next;
  }
}

extern void Desk_Pane_Hide(Desk_window_handle window)
{
  curpane = Desk_pane_root;

  while(curpane)
  {
    if(curpane->panedata.master == window)
    {
      if(curpane->panedata.flags.data.isopen == 1)
      {
        Desk_Window_Hide(curpane->panedata.master);
        Desk_Window_Hide(curpane->panedata.pane);
        curpane->panedata.flags.data.isopen = 0;
      }
    }
    curpane = curpane->next;
  }
}
