#include "wimp.h"
#include "wimpt.h"
#include "win.h"
#include "event.h"
#include "baricon.h"
#include "res.h"
#include "menu.h"
#include "template.h"
#include "dbox.h"
#include "werr.h"
#include "bbc.h"
#include "colourmenu.h"
#include "coords.h"
#include "akbd.h"
#include "xfersend.h"
#include "resspr.h"
#include "flex.h"
#include "heap.h"

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


#define bd_menu_REMOVE   1
#define bd_menu_OBCOL    2
#define bd_menu_OTCOL    3
#define bd_menu_OSMALL   4
#define bd_menu_FILE     5
#define bd_menu_SAVE     6
#define bd_menu_RENAME   7
#define bd_menu_BCOL     8
#define bd_menu_TCOL     9
#define bd_menu_SMALL   10

#define file_menu_COUNT  1
#define file_menu_INFO   2
#define file_menu_UNLOCK 3
#define file_menu_CAT    4
#define file_menu_EX     5
#define file_menu_DIR    6

#define icon_menu_INFO   1
#define icon_menu_QUIT   2


#define FLAGS       (wimp_ITEXT | wimp_ISPRITE | wimp_INDIRECT | (wimp_IBTYPE * wimp_BCLICKDRAGDOUBLE))
#define FLAGS_large (wimp_IHCENTRE)
#define FLAGS_small (wimp_IVCENTRE | wimp_IHALVESPRITE)


#define iconbar_height 144


#define OS_FSControl 0x00000029

/******************************* DATA TYPES ********************************/
typedef struct object__str
{
  int x, y;
  char *pathname;
  char leaf[11];
  unsigned int type;
  unsigned char bcol, tcol;
  BOOL small;
  wimp_i icon;
  struct object__str *next;
} object;

/******************************* GLOBAL DATA *******************************/

static wimp_dragstr drag;                           /* data for user drag */
static coords_cvtstr c;

static char buff[512];                   /* general purpose string buffer */

static object *objects = NULL;          /* head of linked list of objects */

static object *current = NULL;         /* object being dragged or in menu */

static int bcol = 4;                    /* default values for new objects */
static int tcol = 0;
static BOOL small = FALSE;

static menu bd_menu;                                     /* backdrop menu */
static menu file_menu;                               /* backdrop submenus */
static menu obcol_menu, otcol_menu;
static menu bcol_menu, tcol_menu;

static char *cmd[6] = {"Count %s",                  /* file menu commands */
                       "Info %s",
                       "Access %s WR/wr",
                       "Cat %s",
                       "Ex %s",
                       "Dir %s"};

static wimp_w bd_handle;              /* window handle of backdrop window */

static wimp_i baricon_handle;             /* icon handle of icon bar icon */
static menu icon_menu;                                   /* icon bar menu */


/******************************** FUNCTIONS ********************************/

int greater(int a, int b)
{
  return((a > b) ? a : b);
}

char *leafname(char *path)                 /* find leafname from pathname */
{                                        /* result is within input string */
char *p;

  p = strrchr(path, '.');

  if (p != NULL)
    p++;

  return p;
}

char *new_string(char *string)    /* makes a (permanent) copy of a string */
{
char *new;

  new = (char *) heap_alloc(strlen(string) + 1);
  if (new == NULL)
    werr(TRUE, "heap_alloc failed");
  strcpy(new, string);
  return new;
}

object *find_object(wimp_i i)
{
object *o;

  for (o = objects; o; o = o->next)
    if (o->icon == i)
      return o;

  return NULL;
}

void null_proc(wimp_i icon)                   /* dummy icon click handler */
{
  icon = icon;                                                   /* Dummy */
}

menu bd_menu_maker(void *handle)                    /* make backdrop menu */
{
int i;
char *leaf = "", *type = "File";
wimp_menuitem *p;
void *q;

  handle = handle;                                               /* Dummy */

  if (!event_is_menu_being_recreated())
  {
  wimp_mousestr m;

    wimpt_noerr(wimp_get_point_info(&m));
    current = find_object(m.i);
  }

  if (current)                          /* if pointer is/was over an icon */
  {
    leaf = current->leaf;                                 /* get leafname */

    switch(current->type)
    {
    case 0x1000:
      type = "Dir.";
      break;

    case 0x2000:
      type = "App.";
      break;

    default:
      type = "File";
      break;
    }

    menu_setflags(file_menu, file_menu_CAT, 0, type == "File");
    menu_setflags(file_menu, file_menu_EX , 0, type == "File");
    menu_setflags(file_menu, file_menu_DIR, 0, type == "File");

    for (i = 1; i <= 16; i++)
    {
      menu_setflags(obcol_menu, i, i == current->bcol+1, 0);
      menu_setflags(otcol_menu, i, i == current->tcol+1, 0);
    }

    menu_setflags(bd_menu, bd_menu_REMOVE, 0, 0);
    menu_setflags(bd_menu, bd_menu_OBCOL,  0, 0);
    menu_setflags(bd_menu, bd_menu_OTCOL,  0, 0);
    menu_setflags(bd_menu, bd_menu_OSMALL, current->small, 0);
    menu_setflags(bd_menu, bd_menu_FILE,   0, 0);
  }
  else
  {
    menu_setflags(bd_menu, bd_menu_FILE,   0, 1);
    menu_setflags(bd_menu, bd_menu_OBCOL,  0, 1);
    menu_setflags(bd_menu, bd_menu_OTCOL,  0, 1);
    menu_setflags(bd_menu, bd_menu_OSMALL, 0, 1);
    menu_setflags(bd_menu, bd_menu_REMOVE, 0, 1);
  }

  for (i = 1; i <= 16; i++)
  {
    menu_setflags(tcol_menu, i, i == tcol+1, 0);
    menu_setflags(bcol_menu, i, i == bcol+1, 0);
  }

  menu_setflags(bd_menu, bd_menu_SMALL, small, 0);

  q = menu_syshandle(bd_menu);

  i = 128 + (16 * strlen(leaf));                /* set correct menu width */
  ((wimp_menuhdr *) q)->width = greater(i, 192);

          /* write type and filename into File/Dir./App. 'xxx' menu entry */
  p = ((wimp_menuitem *) ((int) q + sizeof(wimp_menuhdr)))+bd_menu_FILE-1;
  sprintf(p->data.indirecttext.buffer, "%s '%s'", type, leaf);


  return bd_menu;
}

void ensure_sprite(char *pathname)
{
os_filestr f = {17, buff};

  f.action = 17;                              /* see if !Boot file exists */
  sprintf(buff, "%s.!Boot", pathname);
  wimpt_complain(os_file(&f));
  if (f.action == 1)                               /* if it does, *Run it */
  {
    sprintf(buff, "Run %s.!Boot", pathname);
    wimpt_complain(os_cli(buff));
    return;
  }

  f.action = 17;                /* otherwise, see if !Sprites file exists */
  sprintf(buff, "%s.!Sprites", pathname);
  wimpt_complain(os_file(&f));
  if (f.action == 1)                       /* if it does, *IconSprites it */
  {
    sprintf(buff, "IconSprites %s.!Sprites", pathname);
    wimpt_complain(os_cli(buff));
  }
}

char *find_sprite(char *pathname, BOOL ensure)
{
char *leaf = leafname(pathname);

  if (ensure)
    if (wimp_spriteop(24, leaf))  /* see if sprite is in Wimp sprite pool */
      ensure_sprite(pathname);          /* if not, initialise application */

  return (wimp_spriteop(24, leaf) ? "application" : leaf);
}

void make_icon(object *o, BOOL ensure)/* generate Wimp icon for an object */
{
wimp_icreate ic;
wimp_i i;
char sprite[16];

  if (o->icon != NULL)
    werr(TRUE, "Object already has an icon");

  ic.w = bd_handle;
  if (o->small)
  {
    ic.i.box.x0 = o->x - 104;
    ic.i.box.x1 = o->x + 104;
    ic.i.box.y0 = o->y - 20;
    ic.i.box.y1 = o->y + 20;
  }
  else
  {
    ic.i.box.x0 = o->x - 80;
    ic.i.box.x1 = o->x + 80;
    ic.i.box.y0 = o->y - 54;
    ic.i.box.y1 = o->y + 54;
  }

  ic.i.flags = FLAGS
             |(wimp_IFORECOL * o->tcol)
             |(wimp_IBACKCOL * o->bcol)
             |(o->small ? FLAGS_small : FLAGS_large);

  switch(o->type)
  {
  case 0x1000:                                               /* Directory */
    sprintf(sprite, "Sdirectory");
    break;

  case 0x2000:                                             /* Application */
    sprintf(sprite, "S%s", find_sprite(o->pathname, ensure));
    break;

  case 0x3000:                                            /* Untyped file */
    sprintf(sprite, "Sfile_xxx");
    break;

  default:                                                  /* Typed file */
    sprintf(sprite, "Sfile_%3.3x", o->type);
    break;
  }

  ic.i.data.indirecttext.buffer = (o->leaf);
  ic.i.data.indirecttext.validstring = new_string(sprite);
  ic.i.data.indirecttext.bufflen = 1;

  if(wimpt_complain(wimp_create_icon(&ic, &i)) == 0)
  {
  wimp_redrawstr r;

    o->icon = i;

    r.w = bd_handle;
    r.box = ic.i.box;
    wimpt_noerr(wimp_force_redraw(&r));
  }
  else
    heap_free((void *) ic.i.data.indirecttext.validstring);
}

void delete_icon(object *o)             /* delete Wimp icon for an object */
{
wimp_icon i;
wimp_redrawstr r;

  wimpt_noerr(wimp_get_icon_info(bd_handle, o->icon, &i));
  heap_free((void *) i.data.indirecttext.validstring);
  wimpt_noerr(wimp_delete_icon(bd_handle, o->icon));

  r.w   = bd_handle;
  r.box = i.box;
  wimpt_noerr(wimp_force_redraw(&r));

  o->icon = NULL;
}

void add_object(char *name, int type, int x, int y)         /* new object */
{
object *o;

  o = (object *) heap_alloc(sizeof(object));    /* claim space for new object */
  if (o == NULL)
    werr(TRUE, "heap_alloc failed");

  o->x = x;                                     /* initialise object data */
  o->y = y;
  o->pathname = new_string(name);
  strncpy(o->leaf, leafname(o->pathname), 11);
  o->type  = type;
  o->bcol  = bcol;
  o->tcol  = tcol;
  o->small = small;

  o->icon = NULL;
  make_icon(o, TRUE);                                    /* generate icon */

  o->next = objects;                            /* link object into chain */
  objects = o;
}

void remove_object(object *o)                            /* delete object */
{
object **p = &objects;

  delete_icon(o);                                 /* delete object's icon */

  for( ; *p; p = &(*p)->next)                     /* find previous object */
    if (*p == o)
    {
      *p = o->next;                                   /* unlink from list */
      heap_free((void *) o->pathname);  /* free space in 'pathname' field */
      heap_free((void *) o);             /* free space occupied by object */

      return;
    }

  werr(TRUE, "Object not found in chain");       /* complain if not found */
}

void move_icon(object *o, wimp_box *box)
{
  delete_icon(o);                                      /* delete old icon */
  coords_box_toworkarea(box, &c);               /* calculate new position */
  o->x = (box->x0 + box->x1)/2;                          /* from drag box */
  o->y = (box->y0 + box->y1)/2;
  make_icon(o, FALSE);                                   /* make new icon */
  wimpt_noerr(wimp_set_icon_state(bd_handle, o->icon, 0, 0));   /* redraw */
}

void bd_event_handler(wimp_eventstr *e, void *handle)    /* event handler */
{
object *o;

  handle = handle;

  switch (e->e)
  {
  case wimp_EOPEN:
    wimpt_complain(wimp_open_wind(&e->data.o));
    break;

  case wimp_EBUT:
    if (e->data.but.m.i == -1)
      break;

    o = find_object(e->data.but.m.i);

    switch (e->data.but.m.bbits)
    {
    wimp_msgstr m;
    wimp_icon i;

    case wimp_BLEFT:
    case wimp_BRIGHT:
      m.hdr.size = 256;
      m.hdr.your_ref = 0;
      m.hdr.action = wimp_MDATAOPEN;
      m.data.dataload.w = bd_handle;
      m.data.dataload.x = o->x;
      m.data.dataload.y = o->y;
      m.data.dataload.size = 0;
      m.data.dataload.type = (o->type == 0x2000)
                           ? (akbd_pollsh() ? 0x1000 : 0x2000)
                           : (o->type);
      strncpy(m.data.dataload.name, o->pathname, sizeof(m.data.dataload.name));
      wimpt_noerr(wimp_sendmessage(wimp_ESENDWANTACK, &m, (wimp_t) 0));
      break;

    case wimp_BDRAGLEFT:
    case wimp_BDRAGRIGHT:
      current = o;

      wimpt_noerr(wimp_get_icon_info(bd_handle, o->icon, &i));
      coords_box_toscreen(&i.box, &c);

      drag.type = wimp_USER_FIXED;
      drag.box = i.box;
      drag.parent.x0 = INT_MIN;
      drag.parent.y0 = INT_MIN;
      drag.parent.x1 = INT_MAX;
      drag.parent.y1 = INT_MAX;
      wimpt_noerr(wimp_drag_box(&drag));

      break;
    }
    break;

  case wimp_EUSERDRAG:
    {
    wimp_mousestr ms;
    wimp_msgstr m;
    coords_pointstr p;

      wimpt_noerr(wimp_get_point_info(&ms));
      if (ms.w == -1)
        break;

      if (ms.w == bd_handle)                          /* drag on backdrop */
        move_icon(current, &e->data.dragbox);
      else                                           /* drag off backdrop */
      {
        p.x = current->x;
        p.y = current->y;
        coords_point_toscreen(&p, &c);

        m.hdr.size = 256;
        m.hdr.your_ref = 0;
        m.hdr.action = wimp_MDATASAVE;
        m.data.datasave.w = ms.w;
        m.data.datasave.i = ms.i;
        m.data.datasave.x = p.x;
        m.data.datasave.y = p.y;
        m.data.datasave.estsize = 0;
        m.data.datasave.type = current->type;
        strcpy(m.data.datasave.leaf, current->leaf);
        wimpt_noerr(wimp_sendwmessage(wimp_ESEND, &m, ms.w, ms.i));

        m.hdr.action = wimp_MDATALOAD;
        strcpy(m.data.dataload.name, current->pathname);
        wimpt_noerr(wimp_sendwmessage(wimp_ESEND, &m, ms.w, ms.i));
      }
    }
    break;

  case wimp_EKEY:
    {
    wimp_wstate s;

      wimpt_noerr(wimp_get_wind_state(bd_handle, &s));

      switch (e->data.key.chcode)
      {
      case akbd_Fn10:                              /* bring window to front */
      s.o.behind = -1;
      wimpt_complain(wimp_open_wind(&s.o));
        break;

      case akbd_Fn11:                                /* send window to back */
      s.o.behind = -2;
      wimpt_complain(wimp_open_wind(&s.o));
        break;

      default:
        wimp_processkey(e->data.key.chcode);
      }
    }
    break;

  case wimp_ESEND:
  case wimp_ESENDWANTACK:

    switch (e->data.msg.hdr.action)
    {
    coords_pointstr p;

    case wimp_MDATASAVEOK:
      sprintf(buff, "Copy %s %s A~C~D~F~L~N~P~QR~S~T~V",
                        current->pathname,
                        e->data.msg.data.datasaveok.name);
      wimpt_complain(os_cli(buff));
      break;

    case wimp_MDATALOAD:
      p.x = e->data.msg.data.dataload.x;
      p.y = e->data.msg.data.dataload.y;
      coords_point_toworkarea(&p, &c);
      add_object(e->data.msg.data.dataload.name,
                 e->data.msg.data.dataload.type,
                 p.x, p.y);
      break;
    }
    break;

  case wimp_EACK:
    switch (e->data.msg.hdr.action)
    {
    case wimp_MDATAOPEN:
      sprintf(buff, (e->data.msg.data.dataload.type == 0x1000)
                       ? "Filer_OpenDir "
                       : "Run ");
      strcat(buff, e->data.msg.data.dataload.name);
      wimpt_complain(wimp_starttask(buff));

      break;
    }
    break;
  }
}

void infobox(void)                   /* 'About this program' dialogue box */
{
dbox  d;

  if ((d = dbox_new("ProgInfo")) != NULL)
  {
    dbox_show(d);
    dbox_fillin(d);
    dbox_dispose(&d);
  }
}

void save_backdrop(void)
{
object *o;
FILE *statesave = res_openfile("!StateSave", "wb");

  fputc(bcol, statesave);
  fputc(tcol, statesave);
  fputc(small, statesave);

  for(o = objects; o!=NULL; o = o->next)
  {
    fputs(o->pathname, statesave);
    fputc(0, statesave);
    fwrite((void *) o, sizeof(object), 1, statesave);
  }

  fclose(statesave);
}

void load_backdrop(void)
{
object *o;
FILE *statesave = res_openfile("!StateSave", "rb");
int i,c;

  if (!statesave)
    return;

  bcol = fgetc(statesave);
  tcol = fgetc(statesave);
  small= fgetc(statesave);

  while (!feof(statesave))
  {
    o = (object *) heap_alloc(sizeof(object));  /* claim space for new object */
    if (o)
    {
      i = 0;
      do
      {
        if (feof(statesave) || i > 255)
        {
          fclose(statesave);
          return;
        }

        c = fgetc(statesave);
        buff[i++] = c;

      } while (c != 0);

      fread((void *) o, sizeof(object), 1, statesave);     /* read object */

      o->pathname = new_string(buff);

      o->icon = NULL;
      make_icon(o, TRUE);                                /* generate icon */

      o->next = objects;                        /* link object into chain */
      objects = o;

    }
  }

  fclose(statesave);

  return;
}

BOOL rename_handler(dbox d, void *event, void *handle)
{
wimp_eventstr *e = (wimp_eventstr *) event;
wimp_i i;
wimp_caretstr c;

  handle = handle;                                               /* Dummy */

  if (e->e != wimp_ESEND && e->e != wimp_ESENDWANTACK)
    return FALSE;

  if (e->data.msg.hdr.action != wimp_MDATALOAD)
    return FALSE;

  if (i = e->data.msg.data.dataload.i, i != 1 && i != 2)
    return FALSE;

  dbox_setfield(d, i, e->data.msg.data.dataload.name);

  c.w = dbox_syshandle(d);
  c.i = i;
  c.height = -1;
  c.index = strlen(e->data.msg.data.dataload.name);
  wimpt_complain(wimp_set_caret_pos(&c));

  return TRUE;
}

void rename_dbox(void)                         /* dialogue box for Rename */
{
dbox  d;

  if ((d = dbox_new("Rename")) != NULL)
  {
    dbox_raw_eventhandler(d, rename_handler, 0);
    dbox_showstatic(d);
    do
    {
      if (dbox_fillin(d) == 0)
      {
#define buffsize 256

      static char buff1[buffsize], buff2[buffsize];
      object *o;
      int i;

        dbox_getfield(d, 1, buff1, buffsize);
        dbox_getfield(d, 2, buff2, buffsize);

        for (o = objects; o; o = o->next)
        {
          i = 0;

          while (buff1[i] && (buff1[i] == o->pathname[i]))
            i++;

          if (buff1[i] || (o->pathname[i] != '.' && o->pathname[i] != '\0'))
            continue;

          sprintf(buff, "%s%s", buff2, o->pathname + i);

          if (o->pathname[i] == '\0')
          {                                   /* make new object from old */
            add_object(buff2, o->type, o->x, o->y);
            remove_object(o);
          }
          else
          {                                       /* just change pathname */
            heap_free((void *) o->pathname);
            o->pathname = new_string(buff);
          }
        }

        save_backdrop();

      }
    } while (dbox_persist());

    dbox_dispose(&d);
  }
}

void bd_menuproc(void *handle, char *hit)             /* menu hit handler */
{
object *o = current;

  handle = handle;

  switch (hit[0])
  {
  case bd_menu_REMOVE:
    remove_object(o);
    current = NULL;
    break;

  case bd_menu_OBCOL:
    if (hit[1] == 0)
      break;
    o->bcol = hit[1] - 1;
    wimpt_noerr(wimp_set_icon_state(bd_handle, o->icon, wimp_IBACKCOL * o->bcol, wimp_IBACKCOL * 0xfU));
    break;

  case bd_menu_OTCOL:
    if (hit[1] == 0)
      break;
    o->tcol = hit[1] - 1;
    wimpt_noerr(wimp_set_icon_state(bd_handle, o->icon, wimp_IFORECOL * o->tcol, wimp_IFORECOL * 0xf));
    break;

  case bd_menu_OSMALL:
    o->small = !o->small;
    delete_icon(o);
    make_icon(o, FALSE);
    break;

  case bd_menu_FILE:
    if (hit[1] == 0)
      return;
    sprintf(buff, cmd[hit[1] - 1], o->pathname);
    wimp_starttask(buff);
    break;

  case bd_menu_SAVE:
    save_backdrop();
    break;

  case bd_menu_RENAME:
    rename_dbox();
    break;

  case bd_menu_BCOL:
    if (hit[1])
      bcol = hit[1] - 1;
    break;

  case bd_menu_TCOL:
    if (hit[1])
      tcol = hit[1] - 1;
    break;

  case bd_menu_SMALL:
    small = !small;
    break;
  }
}

void icon_menuproc(void *handle, char *hit)  /* icon bar menu hit handler */
{
  handle = handle;

  switch (hit[0])
  {
  case icon_menu_INFO:
    infobox();
    break;

  case icon_menu_QUIT:
    exit(0);
  }
}

BOOL create_menus(void)                    /* generate backdrop menu tree */
{
                                         /* object background colour menu */
  obcol_menu = colourmenu_make("Colour", FALSE);
  if (obcol_menu == NULL)
    return FALSE;
                                               /* object text colour menu */
  otcol_menu = colourmenu_make("Colour", FALSE);
  if (otcol_menu == NULL)
    return FALSE;
                                                             /* file menu */
  file_menu = menu_new("File", "Count, Info, Unlock, Cat, Ex, Dir");
  if (file_menu == NULL)
    return FALSE;
                                                /* background colour menu */
  bcol_menu = colourmenu_make("Colour", FALSE);
  if (bcol_menu == NULL)
    return FALSE;
                                                      /* text colour menu */
  tcol_menu = colourmenu_make("Colour", FALSE);
  if (tcol_menu == NULL)
    return FALSE;

                                                             /* main menu */
  bd_menu = menu_new("BackDrop", "Remove Icon| Background, Text, Small icon| File '0123456789', Save, Rename| Background, Text, Small icons");
  if (bd_menu == NULL)
    return FALSE;
  menu_submenu(bd_menu, bd_menu_OTCOL, otcol_menu);
  menu_submenu(bd_menu, bd_menu_OBCOL, obcol_menu);
  menu_submenu(bd_menu, bd_menu_FILE,  file_menu);
  menu_submenu(bd_menu, bd_menu_TCOL,  tcol_menu);
  menu_submenu(bd_menu, bd_menu_BCOL,  bcol_menu);


  return TRUE;
}

BOOL bd_create(void)                            /* create backdrop window */
{
wimp_wind *w;
wimp_icon *i;
sprite_area *a = resspr_area();
wimp_wstate s;

  if ((w = template_syshandle("Main")) == 0)
    return FALSE;
  i = (wimp_icon *) ((void*) (w+1));

  w->box.x0 = 0;
  w->box.y0 = iconbar_height;
  w->box.x1 = (1+bbc_vduvar(bbc_XWindLimit)) * (1 << bbc_vduvar(bbc_XEigFactor));
  w->box.y1 = (1+bbc_vduvar(bbc_YWindLimit)) * (1 << bbc_vduvar(bbc_YEigFactor));

  w->scx = 0;
  w->scy = 0;

  w->behind = -2;

  c.box = w->box;
  c.scx = w->scx;
  c.scy = w->scy;

  w->ex.x0 =   0;
  w->ex.y0 = - w->box.y1;
  w->ex.x1 =   w->box.x1;
  w->ex.y1 =   0;

  w->spritearea = (void *) 1;

  if ((int) a == 1)
    w->nicons = 0;
  else
  {
    i->box = w->ex;
    i->data.indirectsprite.name = (char *) ((int) a + a->sproff);
    i->data.indirectsprite.spritearea = (void *) a;
    i->data.indirectsprite.nameisname = FALSE;
  }

  wimpt_noerr(wimp_create_wind(w, &bd_handle));
  win_register_event_handler(bd_handle, bd_event_handler, 0);
  if (!event_attachmenumaker(bd_handle, bd_menu_maker, bd_menuproc, 0))
    return FALSE;
  win_claim_unknown_events(bd_handle);

  wimpt_noerr(wimp_get_wind_state(bd_handle, &s));
  s.o.behind = -2;
  wimpt_noerr(wimp_open_wind(&s.o));


  return TRUE;
}

BOOL initialise(void)
{
  wimpt_init("Sticky BackDrop");
  res_init("BackDrop");
  resspr_init();
  template_init();
  dbox_init();

  flex_init();
  heap_init(TRUE);

  if (!create_menus())
    return FALSE;

  if (!bd_create())
    return FALSE;

  icon_menu = menu_new("BackDrop", ">Info, Quit");
  if (!icon_menu)
    return FALSE;

  baricon_handle = baricon("!backdrop", 1, null_proc);
  if (!event_attachmenu(win_ICONBAR, icon_menu, icon_menuproc, 0))
    return FALSE;

  load_backdrop();


  return TRUE;
}

/****************************** MAIN PROGRAM *******************************/

int main(void)                                            /* main program */
{
  if (!initialise())
    return 1;

  while (TRUE)
    event_process();

  return 0;
}
