/*
 * WebGet: Acorn Web Fetcher and rewriter
 * Wimp Interface Code
 *
 *  Joseph Heenan, 1996-8
 * All rights reserved.
 *
 * This source is not for release
 *
 * $Header: /home/cvs/webget/c/webget,v 1.36 2000/02/08 23:56:29 joseph Exp $
 *
 */

#include "defines.h"

#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "kernel.h"
#include "swis.h"
#include "wimplib.h"

#include "version.h"
#include "config.h"
#include "macros.h"
#include "url.h"
#include "status.h"
#include "addurl.h"
#include "fetchfile.h"
#include "ruleset.h"

#include "wimpclib.h"

#include "webget.h"

static int quit = 0;

const char frontend_taskname[] = TASK_NAME;

static const int wimp_messages [] = {
/* Get all messages */
       0};

static const int pollmask = (
/*     	   	        Wimp_Poll_NullMask |
                       Wimp_Poll_RedrawWindowRequestMask | */
                      Wimp_Poll_PointerLeavingWindowMask |
                      Wimp_Poll_PointerEnteringWindowMask |
/*                      Wimp_Poll_MouseClickMask | */
/*                      Wimp_Poll_KeyPressedMask | */
                      Wimp_Poll_LoseCaretMask |
                      Wimp_Poll_GainCaretMask |
                      Wimp_Poll_PollWordNonZeroMask |
/*                      Wimp_Poll_UserMessageMask |
                        Wimp_Poll_UserMessageRecordedMask |
                        Wimp_Poll_UserMessageAcknowledgeMask | */
/*                      Wimp_Poll_PollWord |
                      Wimp_Poll_PollWordHighPriority |
                      Wimp_Poll_SaveFPRegs | */
                      0);


static void frontend_initialise(void);
// static void frontend_configure(void);

static int frontend_errorwin = -1;
// static int frontend_noicon = 0;

static int frontend_infowin, frontend_statuswin, frontend_addurlwin;
static int frontend_iconbar;
static int frontend_fetchpending = 0;
static int frontend_dynamicareas = 0; /* don't use dynamic areas*/

static WimpMenu *frontend_mainmenu      = NULL;
static WimpMenu *frontend_fetchmenu     = NULL;
static WimpMenu *frontend_stopfetchmenu = NULL;

static enum frontend_menus { M_NONE, M_MAIN, M_INFO } frontend_openmenu = M_NONE;
static int frontend_menuopening = 0; /* set to true when we've opened a menu whilst another one of our menus is open */
static int frontend_catchurls = 0;
static int frontend_fetchmenuold = 0; /* set to true if the fetch menu is out of date. */
static int frontend_quitwhenidle = 0; /* set to true to quit at end of fetch */

typedef enum { START, START_FETCHONLY, FETCH, FETCH_FETCHONLY, REWRITE, DONE, IDLE } fetchstate_t;
static fetchstate_t frontend_fetchstate = IDLE;


#define MAINMENU ">Info,-Help...,>Start Fetch,!>Stop Fetch," \
                 "Configure...,Add URL...,>Launch URLs,>Open root,-Capture URLs,Quit", \
                 frontend_infowin, frontend_fetchmenu, frontend_stopfetchmenu, \
                 frontend_fetchmenu, frontend_fetchmenu

enum
{
  MAINMENU_INFO,
  MAINMENU_HELP,
  MAINMENU_STARTFETCH,
  MAINMENU_STOPFETCH,
  MAINMENU_CONFIGURE,
  MAINMENU_ADDURL,
  MAINMENU_LAUNCHURLS,
  MAINMENU_OPENROOT,
  MAINMENU_CATCHURLS,
  MAINMENU_QUIT
};

#define STOPFETCHMENU "Finish current pages & enter rewrite," \
                      "Abort current pages & enter rewrite,"  \
                      "Abort current pages & stop"

enum
{
  STOPFETCHMENU_FINISH,
  STOPFETCHMENU_ABORT,
  STOPFETCHMENU_ABORTSTOP
};

#define INFOWIN_AUTHOR        2
#define INFOWIN_WEBSITE       8
#define INFOWIN_VERSION       3

#define ERRORWIN_CANCEL       5
#define ERRORWIN_CONTINUE     1
#define ERRORWIN_MSG          0

#include "flex.h"

#include "url.h"
#include "rewrite.h"

#include "fetch.h"
#include "http.h"
#include "debug.h"

static int key_shift( void )
{
  int state;
  if ( _swix( OS_Byte, _INR(0,2) | _OUT(1), 202, 0, 255, &state ) ) return 0;
  return state & 1<<3;
}

static void webget_init( void )
{
/*  xflex_init( TASK_NAME, NULL, frontend_dynamicareas, 30 * 1024 * 1024 , 1  );  ?? what is this ??*/

  flex_init( TASK_NAME, NULL, 0); /* wimpslot */

  if ( config_load() < 0 )
  {
    E_REPORT("Could not load config file!");
  }

  if ( httpfetch_init( config_maxfetchers ) < 0)
  {
    E_REPORT("httpfetch initialisation failed - out of memory?");
    exit( 0 );
  }

  if ( url_init() < 0 )
  {
    E_REPORT("URL initialisation failed - out of memory?");
    exit( 0 );
  }

#if 0
  if ( mimetype_load(TASK_DIR".Resources.FileTypes") < 0 )
  {
    E_REPORT("Mimetype load failed - out of memory or FileTypes file missing?");
  }
#endif

  if ( ruleset_init() == -1 )
  {
    E_REPORT("Ruleset initialisation failed - out of memory?");
    exit( 0 );
  }

  status_init( frontend_statuswin );
}

static void webget_finalise( void )
{
  httpfetch_finalise();
}

static int frontend_createmenu( enum frontend_menus which, WimpMenu *menu, int x, int y )
{
  if ( frontend_openmenu != M_NONE && frontend_openmenu != which )
    frontend_menuopening = 1; /* if we're opening a menu whilst we have another open */

  E_CHECK_RETURN( -1, wimp_create_menu( menu, x, y ) );

  frontend_openmenu = which;
  return 0;
}

static void frontend_seticon( char which )
{
  static char last_which = 0;
  char icon[24] = "!" TASK_NAME;
  int  len = strlen( icon );

  if ( last_which == which || frontend_iconbar == -1 ) return;

  icon[ len++ ] = which; /* append 'which' to icon name */
  icon[ len   ] = 0;
  last_which    = which;

  wimpc_seticontext( -1, frontend_iconbar, icon );
}

static void do_icon( void )
{
  static int icon  = 0; /* icon in use */
  static int dir = 1; /* 1 = add, 0 = subtract */
  static unsigned int lasttime = 0;
  static fetchstate_t laststate = IDLE;
  unsigned int now;
  int change;

  if ( _swix( OS_ReadMonotonicTime, _OUT(0), &now ) ) return;

  change = now - (lasttime + 50) < 0x80000000;
  if ( !change && laststate == frontend_fetchstate && lasttime != 0 ) return;
  laststate = frontend_fetchstate;
  lasttime = now;

  switch( frontend_fetchstate )
  {
    case FETCH:
      if (dir)
      {
        icon++;
        if ( icon >= 4 )
          dir = 0;
      }
      else
      {
        icon--;
        if ( icon <= 0 )
          dir = 1;
      }
      frontend_seticon( '0' + icon );
      break;

    case REWRITE:
      icon++;
      if ( icon > 1 ) icon = 0;
      frontend_seticon( icon ? 'r' : '0' );
      break;

    default:
      /* replace original icon */
      icon  = 0;
      frontend_seticon( icon );
  }
}

static int frontend_makebusy( int busy )
{
  /* Fade Start Fetch */
  // if ( wimpc_menufadeitem( frontend_mainmenu, MAINMENU_STARTFETCH, busy ) < 0 ) return -1;
  if ( !busy )
    /* unfade entries in startfetch menu */
    wimpc_menufade( frontend_fetchmenu, 0 );

  /* unfade Stop Fetch, Abort Fetch */
  if ( wimpc_menufadeitem( frontend_mainmenu, MAINMENU_STOPFETCH , !busy ) < 0 ) return -1;

  if ( frontend_openmenu == M_MAIN )
    frontend_createmenu( M_MAIN, frontend_mainmenu, 0, 0 ); /* refresh menu if open */
  return 0;
}

static void webget_work( void )
{

  switch ( frontend_fetchstate )
  {
    case START:
    case START_FETCHONLY:
/*      if ( httpfetch_loadfetch () < 0 )
      {
        debug_printf(("Error reading fetch file!\n"));
        frontend_fetchstate = DONE;
        break;
      } */
      if ( http_openlog() < 0 )
      {
        debug_printf(("Error opening log file!\n"));
        frontend_fetchstate = DONE;
        break;
      }
      httpfetch_kick(0); /* kick all sessions */
      frontend_fetchstate = frontend_fetchstate == START ? FETCH : FETCH_FETCHONLY;
      frontend_makebusy( 1 );
      if ( config_openstatuswin )
        frontend_openstatus();
      break;

    case FETCH:
    case FETCH_FETCHONLY:
      if ( httpfetch_poll() == 0 )
      {
        debug_printf(("Fetching finished, starting rewrite:\n"));
        http_closelog();
        status_clearurls();
        if ( frontend_fetchstate == FETCH )
        {
          frontend_fetchstate = REWRITE;
          status_seturl(0, "Rewriting links...");
        }
        else
          frontend_fetchstate = DONE;
      }
      status_update(); /* update counts display */
      break;

    case REWRITE:
      if ( rewrite_poll( 0/*poll*/ ) > 0 )
        break;

      debug_printf(("Fetch/rewrite done!\n"));
      frontend_fetchstate = DONE;
      if ( frontend_fetchpending )
      {
        frontend_fetchpending = 0;
        frontend_fetchstate = START;
        break;
      }
      frontend_makebusy( 0 );
      {
        int delete_all_fetched_fetches_with_delete_set;
      }
      if (config_showlog)
      {
        char name[512];
        int len = sizeof(name) - sizeof("Filer_Run ");
        int spare;
        _kernel_oserror *e;
        strcpy( name, "Filer_Run " );
        e = _swix(OS_FSControl, _INR(0,2) | _IN(5) | _OUT(5), 37, LOG_DIR".Log", name+strlen(name), len, &spare);
        if ( e )
        {
          E_CHECK( e );
        }
        else
        {
          debug_printf(("Name = '%s'\n",name));
          E_CHECK( _swix( Wimp_StartTask, _IN(0), name ) );
        }
      }
      /* deliberate fall through */

    case DONE:
      if ( frontend_quitwhenidle )
        quit = 1;
      status_clearurls();
      status_seturl(0,"Fetch complete");
      status_update();
      frontend_fetchstate = IDLE;
      break;

    case IDLE:
    default:
      break;
  }

  do_icon();

  if ( frontend_fetchstate != FETCH )
  {
    httpfetch_poll();
  }
}



static void frontend_mouseclick( int window, int icon, int but, int x, int y )
{
  int handled = 1;
  y=y;

  if ( window == -2 )
  {
    /* iconbar */
    switch ( but )
    {
      case Wimp_MouseButtonSelect:
        frontend_openstatus();
        break;
      case Wimp_MouseButtonMenu:
        frontend_createmenu( M_MAIN, frontend_mainmenu, x-64, wimpc_menuheight(frontend_mainmenu) + 96 );
        break;
      case Wimp_MouseButtonAdjust:
#ifdef URLDUMP
        url_dump( FOUND, LOG_DIR".Found" );
        url_dump( PENDING, LOG_DIR".Pending" );
        url_dump( FETCHED, LOG_DIR".Fetched" );
/*        url_dump( MIMETYPES, LOG_DIR".MimeTypes" );*/
#endif
        break;
    }
  }
  else if ( window == frontend_infowin )
  {
    switch ( icon )
    {
      case INFOWIN_AUTHOR:
        url_launch( "mailto:webget@ping.demon.co.uk" );
        break;
      case INFOWIN_WEBSITE:
        url_launch( "http://www.ping.demon.co.uk/acorn/webget.html" );
        break;
    }
  }
  else if ( window == frontend_errorwin )
  {
    if ( icon == ERRORWIN_CANCEL || icon == ERRORWIN_CONTINUE )
      wimp_close_window( &frontend_errorwin );
  }
  else if ( window == frontend_addurlwin )
  {
    addurl_mouseclick( window, icon, but );
  }
  else if ( window == frontend_statuswin )
  {
    frontend_createmenu( M_MAIN, frontend_mainmenu, x-64, y );
  }
  else
  {
    handled = 0;
  }
  if ( handled ) return;

/*  {
    int x;
    for ( x = 0; *config_info[x].name; x++ )
    {
      if ( config_info[x].han == window )
        config_click( x, window, icon, but, x, y );
    }
  } */
}

static void frontend_wimpmessage_ack( WimpMessage * mess )
{
  if ( mess->hdr.action_code == Wimp_MOpenUrl )
    url_bounce( mess );
}


static void webget_startfetch( int fetchonly )
{
  switch ( frontend_fetchstate )
  {
    case FETCH:
      /* already fetching */
      httpfetch_kick( 0 );
      break;
    case REWRITE:
      frontend_fetchpending = 1;
      break;
    default:
      if ( fetchonly )
        frontend_fetchstate = START_FETCHONLY;
      else
        frontend_fetchstate = START;
  }
}


static int frontend_getfetchfrommenu( int sel, char *fname, int fnamesize )
{
  char *entry = wimpc_menuread( frontend_fetchmenu, sel );
  debug_printf(("getfetchfrommenu( %d, %p, %d ), entry = '%s'\n",sel,fname,fnamesize,entry));

  if ( !entry )
    return -1;

  entry = strchr( entry, '\r' );

  if ( !entry )
    return -1;

  if ( strlen(entry) + sizeof(WEBGET_FETCHDIR".") > fnamesize )
    return -1;

  strcpy( fname, WEBGET_FETCHDIR "." );

  entry++; /* skip \r */

  strcat( fname, entry );

  return 0;
}


static void frontend_menuselection(WimpMenuSelections sel, int adjust)
{
  if ( frontend_openmenu == M_MAIN )
  {
    switch ( sel[0] )
    {
      case MAINMENU_INFO:
//        frontend_createmenu( M_INFO, (WimpMenu *) frontend_infowin, x, y ); /* open infobox as transient */
//        wimpc_openwindow( frontend_statuswin );
        break;

      case MAINMENU_HELP:
      {
        static const char show_help_cmd[] = "Filer_Run "TASK_DIR".!Help";
        E_CHECK( _swix(OS_CLI, _IN(0), show_help_cmd) );
        break;
      }
      case MAINMENU_STARTFETCH:
      {
        int shift = key_shift();
        char fname[150];
        debug_printf(("sel[1] = '%d'\n", sel[1]));
        if ( sel[1] != -1 && frontend_getfetchfrommenu( sel[1], fname, sizeof fname ) != -1 )
        {
          debug_printf(("Loading file '%s'\n", fname ));
          if ( mimetype_init() != -1 )
            if ( fetchfile_load( fname, FETCHFILE_LOAD ) < 0 )
              break;
          webget_startfetch( shift );
          wimpc_menufadeitem( frontend_fetchmenu, sel[1], 1 );
        }
        else
        {
          int do_all_fetches;
        }
        break;
      }
      case MAINMENU_STOPFETCH:
      {
        if ( sel[1] == -1 || sel[1] == STOPFETCHMENU_FINISH )
        {
          /* stop, enter rewrite */
          if ( frontend_fetchstate == FETCH )
            httpfetch_stop();
        }
        else if ( sel[1] == STOPFETCHMENU_ABORT )
        {
          /* abort, enter rewrite */
          if ( frontend_fetchstate == FETCH )
          {
            httpfetch_abort();
            http_closelog();
            status_clearurls();
            frontend_fetchstate = REWRITE;
          }
        }
        else
        {
          /* abort & stop */
          if ( frontend_fetchstate == FETCH )
          {
            httpfetch_abort();
            http_closelog();
            status_clearurls();
          }
          else if ( frontend_fetchstate == REWRITE )
            rewrite_poll( 1/*abort*/ );
          frontend_fetchstate    = DONE;
          frontend_fetchpending  = 0;
          frontend_makebusy( 0 );
        }
        status_update(); /* update counts display */
        do_icon();

        /* if we're fetching, close fetch down nicely, otherwise do nothing */
        // wimpc_menufadeitem( frontend_mainmenu, MAINMENU_STOPFETCH , 1 ); /* fade 'stop fetch' */
        break;
      }

      case MAINMENU_CONFIGURE:
      {
        static const char show_help_cmd[] = "Filer_Run "TASK_DIR".Choices";
        E_CHECK( _swix(OS_CLI, _IN(0), show_help_cmd) );
        break;
      }
//        config_openwindow();
        break;

      case MAINMENU_ADDURL:
        addurl_open( NULL, 0 );
        break;

      case MAINMENU_LAUNCHURLS:
        if ( sel[1] != -1 )
        {
          char fname[150];
          if ( frontend_getfetchfrommenu( sel[1], fname, sizeof fname ) != -1 )
            fetchfile_load( fname, FETCHFILE_OPENURL );
        }
        break;

      case MAINMENU_OPENROOT:
        if ( sel[1] != -1 )
        {
          char fname[150];
          if ( frontend_getfetchfrommenu( sel[1], fname, sizeof fname ) != -1 )
            fetchfile_load( fname, FETCHFILE_OPENROOT );
        }
        break;

      case MAINMENU_CATCHURLS:
        frontend_catchurls = !frontend_catchurls;
        wimpc_menuflagitem( frontend_mainmenu, MAINMENU_CATCHURLS, WimpMenuItem_Ticked, frontend_catchurls );
        break;

      case MAINMENU_QUIT:
        quit = 1;
        break;
    }
    if ( adjust )
      frontend_createmenu( M_MAIN, frontend_mainmenu, 0, 0 ); /* redisplay menu */
  }
  if ( !adjust)
    frontend_openmenu = M_NONE;
}


static WimpMenu *frontend_buildmenu( void )
{
  const char sep[] = "\x01"; /* use CHR$(1) as the menu seperator */
  char buffer[60], *fname; /* buffer for filenames */
  int  count = 0, numread;
  char menuentry[60];
  char stack[2048], *menu = stack;
  int size = sizeof( stack );
  WimpMenu *ret;
  enum { STACK, BUFFER } where = STACK;
  int maxsize, avail;

  *menu = 0;

  /* copy directory into buffer, add '.' and set fname to the end of this */
  strcpy( buffer, WEBGET_FETCHDIR "." );
  maxsize = sizeof buffer - ( strlen(buffer) + 1 );
  fname = buffer + strlen( buffer );

  do
  {
    E_CHECK_RETURN( NULL, _swix( OS_GBPB, _INR(0,6) | _OUTR(3,4), 9,
                    WEBGET_FETCHDIR, fname, 1, count, maxsize, "*",
                    &numread, &count ) );

    if ( numread != 1 ) continue;

    avail = sizeof menuentry - ( strlen( fname ) + 1); /* +1 for the \r */
    if ( avail > 40 ) avail = 40;

    if ( fetchfile_readtag( buffer, "name", menuentry, avail ) < 0
      && fetchfile_readtag( buffer, "url",  menuentry, avail ) < 0 )
    {
      /* quite how there can be no name tag _and_ no url tag, I have no idea. Don't CAB, though */
      *menuentry = 0;
      strncat( menuentry, fname, avail - 1 );
    }
    /* strcat : we know we have enough space to do this */
    {
      char *ptr = menuentry;
      while ( ptr = strchr( ptr, *sep ), ptr )
        *ptr++='\x02'; /* shrug */
    }
    strcat( menuentry, "\r" );
    strcat( menuentry, fname );

    if ( strlen( menu ) + strlen( menuentry ) + 2 > size )
    {
      size *= 2;
      if ( where == STACK )
      {
        menu = malloc( size );
        memcpy( menu, stack, sizeof stack );
        if ( !menu ) return NULL;
        where = BUFFER;
      }
      else
      {
        char *tmp = realloc( menu, size );
        if ( !tmp )
        {
          free( menu );
          return NULL;
        }
        menu = tmp;
      }
    }
    strcat( menu, menuentry );
    strcat( menu, sep );
  } while ( count != -1 ); /* End of while loop */

  if ( strlen(menu) >= 1 )
    menu[ strlen(menu) - 1 ] = 0; /* remove final comma */

  ret = wimpc_createmenu( 1/*raw*/, *sep, "Fetches", menu );
  if ( where == BUFFER)
    free( menu );
  return ret;
}

void frontend_recreatefetchmenu( void )
{
  WimpMenu *new = NULL;

  if ( frontend_fetchstate != IDLE )
  {
    frontend_fetchmenuold = 1;
    return;
  }
  debug_printf(("Rebuilding fetch menu...\n"));

  new = frontend_buildmenu();
  if ( !new )
  {
    E_REPORT( "Out of memory - could not enlarge fetch menu!" );
    return;
  }

  free( frontend_fetchmenu );
  frontend_fetchmenu = new;

  wimpc_menuupdate( frontend_mainmenu, MAINMENU_STARTFETCH, frontend_fetchmenu );
  wimpc_menuupdate( frontend_mainmenu, MAINMENU_LAUNCHURLS, frontend_fetchmenu );
  wimpc_menuupdate( frontend_mainmenu, MAINMENU_OPENROOT, frontend_fetchmenu );
  frontend_fetchmenuold = 0;
}


/* picks out any -fetch's on the command line */
static void frontend_processcmdline( int argc, char *argv[] )
{
  int l;
  char err[256];
  char buffer[256];
  int type;
  int fetch = 0;

  if ( argc <= 1 )
    return; /* no options */

  *err = 0;

  for ( l = 1; l < argc; l++ )
  {
    if ( !strcmp( argv[l], "-fetch" ) )
    {
      l++;
      if ( l >= argc )
      {
        sprintf( err, "-fetch invalid without a filename / description\n"
                      "usage: webget [-fetch <fetchfile>|<desc>] [-quit]" );
      }
      else
      {
        /* try argv[1] as a fetchfile name, if not found search for matching description */
        strcpy( buffer, WEBGET_FETCHDIR "." );
        strncat( buffer, argv[l], sizeof(buffer) - sizeof(WEBGET_FETCHDIR".") );

        if ( (_swix( OS_File, _INR(0,1) | _OUT(0), 17, buffer, &type ) == NULL && type  == 1) ||
             fetchfile_searchfordesc( argv[l], buffer, sizeof buffer ) != -1 )
        {
          if ( mimetype_init() != -1 )
            fetchfile_load( buffer, FETCHFILE_LOAD );
        }
        else
          sprintf( err, "Could not find a fetch matching '%s'", argv[l] );
      }
      fetch = 1;
    }
    else if ( !strcmp( argv[l], "-quit" ) )
    {
      frontend_quitwhenidle = 1;
    }
    else if ( !strcmp( argv[l], "-noDA" ) && l == 1 )
    {
      /* already processed, as it needs to be read before the flex_initx call! */
    }
    else
      sprintf( err, "Option '%s' not recognised\nusage: webget [-fetch <fetchfile>|<desc>] [-quit]", argv[l] );

    if ( *err )
    {
      E_REPORT( err );
      exit( 1 );
    }
  }
  if ( fetch )
    webget_startfetch( 0 );
}

#define WORDALIGN(x) ( (x+3) & ~3 )

/* reference number for the last datasave message we sent out, so we know we have to delete the
 * file when we get back a dataload with that reference number */
static int last_datasave = 0;

static void frontend_datasave( WimpMessage *wimpmsg )
{
  WimpDataSaveMessage *msg = &wimpmsg->data.data_save;

  debug_printf(("Got datasave msg, there my_ref = %d\n", wimpmsg->hdr.my_ref));

  if ( msg->destination_window == frontend_statuswin || msg->destination_window == frontend_addurlwin ||
      (msg->destination_window == WimpWindow_Iconbar && msg->destination_icon == frontend_iconbar) )
  {
    /* check to see if it's a url drag we might like... */

    /* it is... send back a Message_DataSackAck */
    wimpmsg->hdr.your_ref    = wimpmsg->hdr.my_ref;
    wimpmsg->hdr.action_code = Wimp_MDataSaveAck;
    wimpmsg->hdr.size        = WORDALIGN( sizeof(WimpMessage) - sizeof(msg->leaf_name) + sizeof("<Wimp$Scrap>") );
    msg->estimated_size = -1; /* file is unsafe */
    strcpy( msg->leaf_name, "<Wimp$Scrap>" );
    E_CHECK( wimp_send_message( Wimp_EUserMessage, wimpmsg, wimpmsg->hdr.sender, 0, NULL ) );
    debug_printf(("Send datasave, my_ref = %d\n", wimpmsg->hdr.my_ref ));
    last_datasave = wimpmsg->hdr.my_ref;
    /* other app will now save it's data there, and send us a dataload msg */
  }

  return;
}

#define URI_FileType 0xf91

/* URI files have strange rules for lineterminators, so need a special fn to read them... */
static int uri_getnextline( FILE *f, char *buf, int bufsize )
{
  int c;
  char *ptr = buf;
  char *end = buf + bufsize - 1;

  do
  {
    c = fgetc( f );
    if ( c == EOF )
      break;
    if ( c < 32 )
    {
      while ( c = fgetc( f ), c < 32 && c != EOF );
      if ( c != EOF ) ungetc( c, f );
      break;
    }
    *ptr++ = c;
  } while ( ptr < end );

  *ptr = 0;
  if ( c == EOF && *buf == 0)
    return -1;

  if ( *buf == '#' )
    return uri_getnextline( f, buf, bufsize ); /* skip comments */

  return 0;
}

static void frontend_loadfile( const char *name, int ftype )
{
  char buf[256], *ptr;
  FILE *f = fopen( name, "r" );

  if ( !f )
    return;

  if ( ftype == URI_FileType )
  {
    debug_printf(("URI file (allegedly):\n"));
    if ( uri_getnextline( f, buf, sizeof buf ) != -1 && !strcmp( buf, "URI" ) )
    {
      char url[256];
      debug_printf(("/is/ a URI file:\n"));
       /* lines are: 'URI', <version>, <uri>, <desc> */
      if ( uri_getnextline( f, buf, sizeof buf ) == 0
        && uri_getnextline( f, url, sizeof url ) == 0 )
      {
        if ( uri_getnextline( f, buf, sizeof buf ) == 0 )
          /* there's a description */
          addurl_opendesc( url, buf );
        else
          addurl_opendesc( url, "" );
      }
    }
  }
  else
  {
    if ( fgets( buf, sizeof buf, f ) )
    {
      ptr = buf + strlen( buf ) - 1;
      while ( isspace( *ptr ) ) *ptr-- = 0;
      ptr = buf;
      while ( isspace( *ptr ) ) ptr++;
      debug_printf(("Got url : '%s'\n",ptr));
      addurl_opendesc( ptr, "" );
    }
  }
  fclose( f );
}

static void frontend_dataload( WimpMessage *wimpmsg )
{
  WimpDataLoadMessage *msg = &wimpmsg->data.data_load;

  debug_printf(("Got dataload msg, there my_ref = %d, our_ref = %d\n", wimpmsg->hdr.my_ref, wimpmsg->hdr.your_ref));

  if ( msg->destination_window == frontend_statuswin || msg->destination_window == frontend_addurlwin ||
      (msg->destination_window == WimpWindow_Iconbar && msg->destination_icon == frontend_iconbar) )
  {
    /* check to see if it's a file we might like... */

    frontend_loadfile( msg->leaf_name, msg->file_type );

    if ( wimpmsg->hdr.your_ref == last_datasave && last_datasave != 0 )
    {
      /* delete file when we're done */
      remove( msg->leaf_name );
    }

    /* acknowledge message */
    wimpmsg->hdr.your_ref = wimpmsg->hdr.my_ref;
    wimpmsg->hdr.action_code = Wimp_MDataLoadAck;
    E_CHECK( wimp_send_message( Wimp_EUserMessage, wimpmsg, wimpmsg->hdr.sender, 0, NULL ) );
  }

  return;
}

int main( int argc, char *argv[] )
{
  WimpPollBlock pollblock;
  int reason;

  if ( wimpc_taskpresent( TASK_NAME ) ) exit(0);

  E_CHECKABORT( _swix( OS_File, _INR(0,1), 8, WEBGET_FETCHDIR ) ); /* Make sure the fetch directory exists */
  E_CHECKABORT( _swix( OS_File, _INR(0,1), 8, LOG_DIR         ) ); /* Make sure the logs directory exists */

  frontend_initialise();

  if ( argc >= 2 && !strcmp( argv[1], "-noDA" ) )
    frontend_dynamicareas = 0;

  webget_init();

  http_zerocounts();

  frontend_fetchmenu = frontend_buildmenu();
  if ( !frontend_fetchmenu )
    E_ABORT("Could not build fetch menu!");

  frontend_stopfetchmenu = wimpc_createmenu( 0/*not raw*/, ',', TASK_NAME, STOPFETCHMENU );
  frontend_mainmenu = wimpc_createmenu( 0/*not raw*/, ',', TASK_NAME, MAINMENU );
  if ( !frontend_mainmenu || !frontend_stopfetchmenu )
    E_ABORT("Out of memory, could not create menus!\n");

  /* tick/untick catchs urls */
  wimpc_menuflagitem( frontend_mainmenu, MAINMENU_CATCHURLS, WimpIcon_Selected, frontend_catchurls );

  frontend_processcmdline( argc, argv );

  while(!quit)
  {

    if ( frontend_fetchstate == IDLE )
    {
      unsigned int time;
      if ( frontend_fetchmenuold )
        frontend_recreatefetchmenu();
      _swix(OS_ReadMonotonicTime, _OUT(0),&time); /* time in centiseconds. ie. 1500 -> 15 seconds */
      E_CHECK( wimp_pollidle(pollmask, &pollblock, time+1500, NULL, &reason) );
    }
    else
    {
      E_CHECK( wimp_poll(pollmask, &pollblock, NULL, &reason) );
    }

    if ( reason==Wimp_ENull || quit)
    {
      /* null poll - do some work */
      webget_work();
    }

    switch (reason) {

      case Wimp_ERedrawWindow:
        break;

      case Wimp_EOpenWindow:
          E_CHECK( wimp_open_window((WimpOpenWindowBlock *)&pollblock) );
        break;

      case Wimp_ECloseWindow:
        E_CHECK( wimp_close_window( &pollblock.close_window_request.window_handle ) );
        break;

      case Wimp_EMouseClick:
        frontend_mouseclick( pollblock.mouse_click.window_handle, pollblock.mouse_click.icon_handle,
                             pollblock.mouse_click.buttons,       pollblock.mouse_click.mouse_x,
                             pollblock.mouse_click.mouse_y);
        break;

      case Wimp_EKeyPressed:
        if ( pollblock.key_pressed.caret.window_handle == frontend_addurlwin &&
             addurl_keypress( pollblock.key_pressed.key_code ) )
        {
          /* key press handled elsewhere */
        }
        else
          wimp_process_key( pollblock.key_pressed.key_code );
        break;

      case Wimp_EMenuSelection:
      {
        WimpGetPointerInfoBlock pointer;
        wimp_get_pointer_info( &pointer );
        frontend_menuselection( pollblock.menu_selection, pointer.button_state & Wimp_MouseButtonAdjust );
      } break;

      case Wimp_EUserMessage:
      case Wimp_EUserMessageRecorded:
        debug_printf(("UserMessage%s of type 0x%x\n",
                      reason==Wimp_EUserMessage?"":"Recorded", pollblock.user_message.hdr.action_code));
        switch ( pollblock.user_message.hdr.action_code )
        {
          case Wimp_MDataSave:
            frontend_datasave( &pollblock.user_message );
            break;

          case Wimp_MDataLoad:
            frontend_dataload( &pollblock.user_message );
            break;

          case URI_MReturnResult:
            debug_printf(("URI bounce recv'ed\n"));
            url_bounce( &pollblock.user_message );
        }
        {
          int messno = pollblock.user_message.hdr.action_code;
          if (messno == Wimp_MQuit)
          {
            quit = 1;
          }
          else if ( messno == Wimp_MMenusDeleted )
          {
            if ( frontend_menuopening )
              frontend_menuopening = 0;
            else
              frontend_openmenu = M_NONE;
          }
          else if ( messno == Wimp_MModeChange )
          {
//            config_modechange = 1;
          }
          else if ( messno == Wimp_MOpenUrl && reason == Wimp_EUserMessageRecorded && frontend_catchurls )
          {
            /* Called when wantACK wimp message with type Wimp_MOpenUrl is received. */
            url_recvbroadcast( &pollblock.user_message, addurl_open );
          }
          else if ( messno == URI_MProcess && reason == Wimp_EUserMessageRecorded && frontend_catchurls )
          {
            /* Called when wantACK wimp message with type Wimp_MOpenUrl is received. */
            url_recvbroadcast( &pollblock.user_message, addurl_open );
          }
        } break;

      case Wimp_EUserMessageAcknowledge:
        debug_printf(("UserMessageAck of type 0x%x\n",pollblock.user_message.hdr.action_code));
        frontend_wimpmessage_ack( &pollblock.user_message );
        break;

    }
  } /* while ( !quit ) */

  webget_finalise();

  return 0;
}


static void frontend_initialise(void)
{
  E_CHECK_ABORT( wimp_initialise( 310, TASK_NAME, (int *) wimp_messages,
                                  NULL /* wimp version*/, NULL /* task handle */ ) );

  frontend_iconbar = wimpc_createiconbar( "!"TASK_NAME"0" );
  if ( frontend_iconbar < 0 )
    exit(1);

  E_CHECK_ABORT( wimp_open_template(TASK_DIR".Templates") );
  frontend_infowin    = wimpc_loadtemplate("info");
  frontend_statuswin  = wimpc_loadtemplate("status");
  frontend_errorwin   = wimpc_loadtemplate("error");
  frontend_addurlwin  = wimpc_loadtemplate("addurl");
  E_CHECK_ABORT( wimp_close_template() );
  if ( frontend_infowin<0 || frontend_statuswin<0 || frontend_errorwin<0 || frontend_addurlwin<0)
    exit(1);

  addurl_init( frontend_addurlwin );

  {
    char buffer[255];
    char *ptr, *date=__DATE__, *out = buffer;
    /* __DATE__ is MMM   DD   YYYY */
    strcpy( buffer, TASK_VERSION );
    strcat( buffer, " (" );
    out = buffer + strlen( buffer );
    ptr = strchr( date, ' ' );
    if ( ptr )
    {
      while ( *ptr == ' ' ) ptr++;
      while ( *ptr && *ptr != ' ' ) *out++ = *ptr++; /* copy day */
      *out++ = '-';
      while ( *ptr && *ptr == ' ' ) ptr++; /* move to start of year */
      while ( *date && *date != ' ' ) *out++ = *date++; /* copy month */
      *out++ = '-';
      if ( *ptr && *(ptr+1) ) ptr+=2; /* skip over century */
      while ( *ptr ) *out++ = *ptr++; /* copy year */
      *out++ = ')';
      *out = 0;
      wimpc_seticontext( frontend_infowin, INFOWIN_VERSION, buffer );
    }
  }

}


int frontend_warning( const char *name )
{
  if ( frontend_errorwin == -1) return -1;

  wimpc_settitle( frontend_errorwin, "Warning from "TASK_NAME );
  wimpc_deleteicon( frontend_errorwin, ERRORWIN_CANCEL, 1 ); /* delete cancel icon */
  wimpc_seticontext( frontend_errorwin, ERRORWIN_MSG, name );
  wimpc_openwindowcentre( frontend_errorwin, 0 );

  return 0;
}


int frontend_error( const char *name )
{
  if ( frontend_errorwin == -1) return -1;

  wimpc_settitle( frontend_errorwin, "Error from "TASK_NAME );
  wimpc_deleteicon( frontend_errorwin, ERRORWIN_CANCEL, 1 ); /* delete cancel icon */
  wimpc_seticontext( frontend_errorwin, ERRORWIN_MSG, name );
  wimpc_openwindowcentre( frontend_errorwin, 0 );

  return 0;
}


int frontend_openstatus( void )
{
  return wimpc_openwindow( frontend_statuswin );
}


