/************************************************************
**
** Application: Snapper
**
** Title:       c.main
**
*************************************************************/

/*
*
* Copyright (c) 2017, David Pilling and Chris Johnson
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*   * Redistributions of source code must retain the above copyright
*     notice, this list of conditions and the following disclaimer.
*   * Redistributions in binary form must reproduce the above
*     copyright notice, this list of conditions and the following
*     disclaimer in the documentation and/or other materials provided
*     with the distribution.
*   * Neither the name of the copyright holder nor the names of their
*     contributors may be used to endorse or promote products derived
*     from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/

/* Include files */

#include "debugDefs.h"
#include "revision.h"

#include "h.includes"


/* from TaskLib */

#include "TaskLib:h.wimpt"
#include "TaskLib:h.transform"
#include "TaskLib:h.bbc"
#include "TaskLib:h.task"
#include "TaskLib:h.poll"
#include "TaskLib:h.temp"
#include "TaskLib:h.scrap"
#include "TaskLib:h.fsx"
#include "TaskLib:h.etc"
#include "TaskLib:h.pane"
#include "TaskLib:h.font"
#include "TaskLib:h.bits"
#include "TaskLib:h.xhelp"
#include "TaskLib:h.mlo"
#include "TaskLib:h.mym"
#include "TaskLib:h.urllaunch"

/* from application */

#include "h.constants"
#include "h.reslink"
#include "h.config"
#include "h.xdeb"		/* for using debug */
#include "h.area"
#include "h.main"


static char   * versionstring = "1.34";

static char * datestring="13 May 2022";





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



mode_vars mode;

font fonthandle;


#define XEIGFACTOR 4
#define YEIGFACTOR 5
#define XWINDLIMIT 11
#define YWINDLIMIT 12

#define XOS_Bit                        0x020000
#define OS_ReadModeVariable            0x000035

#define WEB_BUTTON 8   /* web button icon ID in Info window */

/* paths for the help files */
#define HTML_HELP_FILE     "<SnapperRes$Dir>.Docs.help/html"
#define TEXT_HELP_FILE     "<SnapperRes$Dir>.Docs.help/txt"


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

void main_issuewarning (int tokennum)
{
  os_error   *warn;

  warn = geterror(tokennum);
  messagebox (warn->errmess);

  return;
}




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

/* readmodevars
 * to read eigen values and screen limits for the current mode
 * returns err
 */

static os_error * readmodevars(void)
{
  mode.xwindlimit = bbc_vduvar (bbc_XWindLimit);
  mode.xwindlimit1 = mode.xwindlimit + 1;
  mode.ywindlimit = bbc_vduvar (bbc_YWindLimit);
  mode.ywindlimit1 = mode.ywindlimit + 1;
  mode.xeig = bbc_vduvar (bbc_XEigFactor);
  mode.yeig = bbc_vduvar (bbc_YEigFactor);

  return (NULL);
}



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

/*   modechangemessage
 *   Required to reread the mode variables for the
 *   new mode
 */

static os_error * modechangemessage(wimp_msgstr * msg,int * ack)
{

  /* need to reread mode vars in case eigen values and/or
   * screen sizes have changed */
  readmodevars();

  area_update_on_mode_change ();

  return(NULL);

  USE(msg);
  USE(ack);
}



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

static os_error * uribouncemesage(wimp_msgstr * msg, int * ack)
{
  return(urllaunch_bounce(msg));
  USE(ack);
}



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

/* deal with click on web button in info window */

static os_error *infoicon(int handle, int userhandle, wimp_mousestr * m)
{
 os_error * err;

 err=NULL;

 switch(m->i)
 {
   case WEB_BUTTON:
     err = urllaunch_broadcast(WEB_URL);
     if (m->bbits != 1) zapmenu ();
     break;
 }

 return(err);

 USE(handle);
 USE(userhandle);
}






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

void terminate(void)

{
  if (!desktop_font_in_use && aopen) font_lose(fonthandle);
  if (!set_reset_suffix_at_start) config_save_suffixes ();
  event(EVENT_ENDPROGRAM,NULL,0);
  scrapfinit();
  exit(0);
}


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

static os_error * terminatemessage(wimp_msgstr * msg,int * ack)

{
 terminate();
 USE(msg);
 USE(ack);
 return(NULL);
}


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

static os_error * writebootfile(wimp_msgstr * msg,int * ack)

{
 char string[256];
 int  handle;

 handle=msg->data.savedesk.filehandle;
 sprintf(string,"Run %s\n",getenv("Snapper$Dir"));
 return(fs_write(handle,string,strlen(string)));
 USE(ack);
}



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

static os_error * addmessages(void)

{
 os_error * err;

          err=addmessage(writebootfile,wimp_SAVEDESK);
 if(!err) err=addmessage(terminatemessage,wimp_MCLOSEDOWN);
 if(!err) err=addmessage(modechangemessage,wimp_MMODECHANGE);   /* CJ: */
 if(!err) err=addmessage(uribouncemesage, wimp_MURI_RETURNRESULT);   /* CJ: */
 if(!err) err=addmessage(claim_entity, wimp_MCLAIMENTITY);
 if(!err) err=addmessage(data_request, wimp_MDATAREQUEST);

 return(err);
}



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

/* open info window and pass back pointer */

static os_error * infodynamic(int * menu,int * handle)

{
 os_error * err;
 static int infowhandle;

 err=NULL;

 if(menu[0]==0)
 {
  if(!infowhandle)
  {
    err=createwindow(TINFO,&infowhandle);
    if (!err)
    {
      addhelpevent(NULL,infowhandle,TINFO);
      addclickevent(infoicon,infowhandle,0);
    }
  }
  writeicon(infowhandle,1,wimpt_programname());

#ifdef PROD
  writeiconf (infowhandle, 7, "%s (%s)", versionstring,
              datestring);
#else
  writeiconf (infowhandle, 7, "Dev %s %s", REVISION, __DATE__);
#endif

  *handle=infowhandle;
 }

 return(err);
}


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

/*
  Following function tries to display the application help file.
  Either html or text, in that order.
  If neither is found - shows a warning message.
  The original method using a !Help file in the application
  directory which ran the html or text file, caused an
  error if itself or the files were not found
*/

static os_error *show_help_file (void)

{
  os_error   *err;
  char       cmd[256];
  char      *file;
  int        type = 0;

  err = NULL;
  file = NULL;

  /*
    Check that a browser has been seen by the filer.
    If so we can try to run the html help file.
    First check that it exists.
  */
  fs_exists (HTML_HELP_FILE, &type);
  if ((os_read_var_size ("Alias$@RunType_FAF")>0) && type)
  {
    file = HTML_HELP_FILE;
  }
  else
  {
    /* we can try to run the text help file instead */
    /* check that it exists */
    fs_exists (TEXT_HELP_FILE, &type);
    if (type)
    {
      file = TEXT_HELP_FILE;
    }
  }
  if (file)
  {
    /* run the file */
    sprintf(cmd,"Filer_Run %s",file);
    err = os_cli ( cmd ) ;
  }
  else
  {
    /* give user a warning message */
    main_issuewarning(WNOHELP);
  }
  return (err);
}




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

static os_error * infodecode(int * menu)

{
 os_error * err;

 err=NULL;


 switch(menu[0])
 {
  case 1:
     show_help_file ();
     break;

  case 2:
     err=configure();
     break;

   case 3:
     err = choice_open();
     break;

  case 4:
     err=configsave();
     break;

  case 5:
     terminate();
     break;
 }

 return(err);
}






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

static os_error * iconbar(int handle,int userhandle,wimp_mousestr * m)

{
 os_error * err;

 err=NULL;

 if(m->i==iconbaricon)
 {
  if(m->bbits==2)
  {
   err=openupmenu(MINFO);
  }
  else
  {
    if (m->bbits==4)
    {
      err=configure();
    }
    else
    {
      err = choice_open();
    }
  }
 }

 return(err);

 USE(userhandle);
 USE(handle);
}




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

static os_error * setupmenus(void)

{
 os_error * err;

 err=addclickevent(iconbar,-2,0);

 setmenufns(MINFO,infodecode,infodynamic);
 setmenudynamic(MINFO,0);
 setmenuflags(MINFO,MFINFO);

 return(err);
}




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

int main(int argc,char * argv[])

{
  os_error *err;
  int       handle = 0;

 setlocale(LC_ALL,"ISO8859-1");

  /*
    Should not run more than one instantiation of Snapper. Check if
    there is already a task running named "Snapper". If there is,
    then we should just quietly die

    HOWEVER - if Snapper is started with the parameter -multi in
    the command line as in
        Run "<Snapper$Dir>.!RunImage" %*0 -multi
    in the !Run file then more than one instance is allowed - this was done
    for a bit of fun for capturing Snapper's own area snapper and the code
    has been left in as an undocumented feature!
  */
  err = wos_tasknametohandle ("Snapper", &handle);
  if (handle)
  {
    if (argc > 1)
    {
      int i;
      int q = 0;

      for (i = 1; i < argc; i++)
      {
        if (!cstrcmp (argv[i], "-multi"))
        {
          q = 1;
          break;
        }
      }
      if (q == 0) exit (0);
    }
    else
    {
      exit (0);
    }
  }

 err=inittask("Snapper","Snapper","!Snapper","<SnapperRes$Dir>",NULL,NULL);
 if(err)
 {
  report(err);
  exit(0);
 }

#ifndef PROD
  debugenable (NULL);
#endif



 if(!err) err=seticonbar("!Snapper");

 if(!err) err=resinit("<SnapperRes$Dir>");

 if(!err) err=addmessages();

 if(!err) err=menulostart("<SnapperRes$Dir>","Menus");
 if(!err) err=setupmenus();

 if(!err) err=configinit();

 if(!err) err=addhelp ( "<SnapperRes$Dir>", "Help" );

 if(!err) readmodevars();
 if(!err) err=addhelpevent(NULL,-2,ICONBARTAG);
 event(EVENT_RUNPROGRAM,NULL,0);

 if(err)
 {
  report(err);
  terminate();
 }

  /* Do we open control window immediately? */
  if (set_open_control_at_start) configure();

 runtask();
}





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






/*************  End of c.main  ***********************/

