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

#include "os.h"
#include "flex.h"
#include "wimp.h"
#include "wimpt.h"
#include "win.h"
#include "res.h"
#include "template.h"
#include "baricon.h"
#include "event.h"
#include "menu.h"
#include "dbox.h"
#include "bbc.h"
#include "werr.h"
#include "xferrecv.h"
#include "drawfdiag.h"


#define UNUSED(x) x = x

#define menu_INFO 1
#define menu_QUIT 2

#define DRAWFILE 0xaff

#define MARGIN 16

/***************************************************************************/

typedef struct
{
  char       pathname[212];
  draw_diag  diag;
  wimp_w     han;
} viewer;


int cycle = 0;


/***************************************************************************/


void null_proc(wimp_i icon)
{
  UNUSED(icon);
}

void redraw_viewer(viewer *v)
{
wimp_redrawstr r;
BOOL more;
draw_error e;

  r.w = v->han;
  wimpt_noerr(wimp_redraw_wind(&r, &more));

  while (more)
  {
    if (!draw_render_diag(&v->diag, (draw_redrawstr *) &r, 1.0, &e))
      switch (e.type)
      {
      case DrawOSError:
        wimpt_noerr(&e.err.os);
        break;

      case DrawOwnError:
        werr(TRUE, "Draw error (code &%2x, location &%2x) in file %s",
                      e.err.draw.code,
                      e.err.draw.location,
                      v->pathname);
        break;
      }

    wimpt_noerr(wimp_get_rectangle(&r, &more));
  }
}

void close_viewer(viewer *v)
{
  if (v->han)
  {
    win_register_event_handler(v->han, 0, (void *) v);
    wimpt_noerr(wimp_delete_wind(v->han));
  }

  if (v->diag.data)
    flex_free((void *) &v->diag.data);

  free((void *) v);
}

void viewer_handler(wimp_eventstr *e, void *handle)
{
viewer *v = (viewer *) handle;

  switch(e->e)
  {
    case wimp_EREDRAW:
      redraw_viewer(v);
      break;

    case wimp_EOPEN:
      wimpt_noerr(wimp_open_wind(&e->data.o));
      break;

    case wimp_ECLOSE:
      close_viewer(v);
      break;

  }
}

BOOL new_viewer(char *pathname)
{
viewer *v;
os_filestr f;
wimp_wind *w;
wimp_wstate s;
draw_error e;

  f.action = 17;                                     /* find size of file */
  f.name = pathname;
  if (wimpt_complain(os_file(&f)))
    return FALSE;
  if (f.action != 1)
    return FALSE;

  if ((v = (viewer *) malloc(sizeof(viewer))) == 0)  /* create new struct */
    return FALSE;

  strncpy(v->pathname, pathname, 212);                   /* copy pathname */

  v->diag.data = NULL;
  v->diag.length = f.start;
                                              /* allocate memory for file */
  if (flex_alloc((flex_ptr) &v->diag.data, v->diag.length) == 0)
  {
    werr(FALSE, "flex_alloc failed");
    close_viewer(v);
    return FALSE;
  }

  f.action = 255;                                            /* load file */
  f.name = pathname;
  f.loadaddr = (int) v->diag.data;
  f.execaddr = 0;
  if (wimpt_complain(os_file(&f)))
  {
    close_viewer(v);
    return FALSE;
  }

  if (!draw_verify_diag(&v->diag, &e))
  {
    switch (e.type)
    {
    case DrawOSError:
      wimpt_complain(&e.err.os);
      break;

    case DrawOwnError:
      werr(FALSE, "Draw error (code &%2x, location &%2x) in file %s",
                    e.err.draw.code,
                    e.err.draw.location,
                    v->pathname);
      break;
    }

    return FALSE;
  }

  w = template_syshandle("Main");             /* create new viewer window */

  w->box.y1 = 800 - cycle * 48;                        /* window position */
  w->box.y0 = w->box.y1 - 480;

  w->title.indirecttext.buffer = v->pathname;             /* window title */

  draw_queryBox(&v->diag, (draw_box *) &w->ex, TRUE);    /* window extent */
  w->ex.x0 -= MARGIN;
  w->ex.y0 -= MARGIN;
  w->ex.x1 += MARGIN;
  w->ex.y1 += MARGIN;
  v->han = NULL;
  if (wimpt_complain(wimp_create_wind(w, &v->han)))
  {
    close_viewer(v);
    return FALSE;
  }


  wimpt_noerr(wimp_get_wind_state(v->han, &s));           /* open window */
  s.o.behind = (wimp_w) -1;
  wimpt_noerr(wimp_open_wind(&s.o));

  win_register_event_handler(v->han,                   /* install handler */
                             viewer_handler,
                             (void *) v);

  cycle = (++cycle & 3);                   /* update viewer positon cycle */

  return TRUE;
}

void iconbar_handler(wimp_eventstr *e, void *handle)
{
int filetype;
char *pathname;

  UNUSED(e);
  UNUSED(handle);

  switch(e->e)
  {
  case wimp_ESEND:
  case wimp_ESENDWANTACK:
    switch(e->data.msg.hdr.action)
    {
    case wimp_MDATALOAD:
    case wimp_MDATAOPEN:
      if ((filetype = xferrecv_checkinsert(&pathname)) != DRAWFILE)
        break;
      xferrecv_insertfileok();
      new_viewer(pathname);
      break;
    }
    break;
  }
}

void menu_handler(void *handle, char *hit)
{
  UNUSED(handle);

  switch(hit[0])
  {
    case menu_INFO:
    {
    dbox  d;

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

    case menu_QUIT:
      exit(0);
      break;
  }
}

void initialise(void)
{
menu m;

  wimpt_init("DrawView");
  res_init("DrawView");
  flex_init();
  template_init();

/*
  if (!drawfdiag_init())
    werr(TRUE, "DrawFDiag initialisation failure");
*/

  draw_registerMemoryFunctions(flex_alloc, flex_extend, flex_free);

  baricon("!drawview", 1, null_proc);
/*  win_register_event_handler(win_ICONBAR    , iconbar_handler, 0);*/
  win_register_event_handler(win_ICONBARLOAD, iconbar_handler, 0);
  win_claim_unknown_events(win_ICONBARLOAD);

  m = menu_new("DrawView", ">Info, Quit");
  event_attachmenu(win_ICONBAR, m, menu_handler, 0);
}

int main(int argc, char *argv[])
{
int i;

  initialise();

  for (i = 1; i < argc; i++)
    new_viewer(argv[i]);

  while(TRUE)
    event_process();

  return 0;
}
/*
bbc_vdu(4);
bbc_vdu(26);
printf("11111 \n");
bbc_vdu(5);
*/
