/*
 * Copyright (c) 1995 Mark Brinicombe.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by Mark Brinicombe.
 * 4. The name of the company nor the name of the author may be used to
 *    endorse or promote products derived from this software without specific
 *    prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
 *
 * RiscBSD kernel project
 *
 * desktop.c
 *
 * Bootloader front end
 *
 * Created      : 26/04/95
 * Last updated : 13/07/96
 */

/* Include standard header files */

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

#include "wimp.h"
#include "Event.h"       /* Event despatcher                             */
#include "EventMsg.h"    /* Wimp Message event dispatcher                */
#include "Error.h"       /* Error despatcher                             */
#include "Resource.h"    /* Handles finding resource files in home dir.  */
#include "Template.h"    /* Template loading and cacheing                */
#include "Window.h"      /* Window handling automation                   */
#include "Icon.h"        /* Icon handling automation                     */
#include "Msgs.h"        /* Message translation code                     */
#include "Handler.h"     /* Default event handlers                       */
#include "WimpSWIs.h"    /* Default event handlers                       */
#include "Menu.h"        /* Menu handling                                */
#include "Screen.h"      /* Getting screen size info, etc   */
#include "Swi.h"
#include "swiv.h"
#include "dragaspr.h"

#include "prototypes.h"
#include "icons.h"
#include "config.h"

/* Define symbols */

#define MAX_FILENAME_LENGTH 255

/* Declare global variables */

menu_ptr main_menu;
icon_handle iconbar_icon = -1;
int iconboot = 0;

/* Declare external variabes */

extern window_handle config_window;
extern window_handle config_backing;
extern Config config;

/* Local function prototypes */

BOOL Iconbar_MenuSelect(event_pollblock *event, void *reference);
BOOL Iconbar_MenuSubWindow(event_pollblock *event, void *reference);
BOOL Iconbar_Click(event_pollblock *event, void *reference);
BOOL Message_Filename(event_pollblock *event, void *reference);
BOOL App_ModeChange(event_pollblock *event, void *reference);
void Exit_Handler(void);

/* Now for the main code */

int main(int argc, char *argv[])
  {
    char application_name[64];
    int loop;

/*
 *  Add exit handler
 */

    atexit(Exit_Handler);

/*
 *  Tell Resource (and thereby Template, Msgs, etc) where our resource
 *  directory is: "<Config$Dir>"
 */

    Resource_Initialise("BtRiscBSD");

/*
 *  Load and cache the messages. Find out the application name.
 */

    Msgs_LoadFile("messages");
    Msgs_Lookup("app.name:BtRiscBSD", application_name, 64);

/*
 *  Initialise the Wimp and Event Manager.
 *  The task name shown on the task display and error reports is set from
 *  the string "appname" fetched previously from the messages file.
 */

    Event_Initialise(application_name);
    EventMsg_Initialise();

/*
 *  Read and remember the current screen mode information
 *  (width and height, eig-factors, delta-x and delta-y, etc.)
 *  This is needed by the Menu code to get menu widths correct.
 */
 
    Screen_CacheModeInfo();

/*
 *  Add a handler function to a "screen mode changing" Wimp message, so
 *  that the information provided by the "Screen" functions is always
 *  correct.
 *  NOTE that the new Handler_ModeChange should also ensure that outline
 *  fonts will work if we change between lo-res and hi-res screen modes.
 */

    EventMsg_Claim(message_MODECHANGE, event_ANY, App_ModeChange, NULL);

/*
 *  Place the Handler_ module skeleton default handlers on all
 *  Redraw and Open-window request events (Application-wide defaults)
 */

/*    Event_Claim(event_REDRAW, event_ANY, event_ANY, Handler_NullRedraw, NULL);*/
    Event_Claim(event_OPEN, event_ANY, event_ANY, Handler_OpenWindow, NULL);

/*
 *  Load in and cache our window templates from the file
 *  "<Tester$Dir>.Templates" (Templates utilise the "Resource Directory")
 */

    Template_Initialise();
/*    Template_UseOutlineFonts();*/
    Template_LoadFile("Templates");

/*
 *  Claim window-close events
 *  Use the Window_Delete() handler rather than the Wimp_CloseWindow() one
 *  so that the window is closed and deleted and all memory and event
 *  claims are released whenever the user hits the close icon.
 */

/*    Event_Claim(event_CLOSE, event_ANY, event_ANY, Handler_DeleteWindow, NULL);*/

/*
 *  Claim DATALOAD and DATAOPEN messages
 */

    EventMsg_Claim(message_DATALOAD, event_ANY, Message_Filename, NULL);
    EventMsg_Claim(message_DATAOPEN, event_ANY, Message_Filename, NULL);

    Event_Claim(event_USERMESSAGEACK, event_ANY, event_ANY, Message_Ack, NULL);
    Event_Claim(event_KEY, event_ANY, event_ANY, Config_Keypress, NULL);

/*
 *  Add the Window_HelpHandler message handler so that help requests
 *  for the windows and the iconbar icon are automatically handled
 */

    Window_AutoHelp(event_ANY, event_ANY);

/*  Create main menu */

    main_menu = Menu_CreateMenu("Config", ">Info,Configuration,Quit");
    if (!main_menu) Msgs_ReportFatal(0x00000000, "err.0", "Main");

/* Initialise other modules */

    Desktop_CreateIcon();

    Config_Initialise();

    for (loop = 1; loop < argc; ++loop) {
      if (strcmp(argv[loop], "-open") == 0)
	    Config_OpenWindow();

      if (strcmp(argv[loop], "-iconboot") == 0)
	    iconboot = 1;
      if (strcmp(argv[loop], "-noiconboot") == 0)
	    iconboot = 0;
    }

/*  Main event handling loop. Let Event_ do all the work for us!
 */

    while (TRUE)
      Event_Poll();

    exit(0);
  }


void Exit_Handler(void)
  {
  }


/*
 *  Menu selection handler
 */

BOOL Iconbar_MenuSelect(event_pollblock *event, void *reference)
  {
    window_handle info_window;

    switch (event->data.words[0])
      {
        case MAIN_MENU_OPTION_INFO :
          info_window = Window_CreateAndShow("infowindow", 0,
            open_UNDERPOINTER);
          if (info_window)
            {
              Icon_SetText(info_window, INFO_WINDOW_ICON_VERSION,
                VERSION_STRING);
              Menu_HandleDbox(info_window);
              Window_Delete(info_window);
            }
          else
            Msgs_Report(0x00000000, "err.1", "info");
          break;

        case MAIN_MENU_OPTION_CONFIG :
          Config_OpenWindow();
          break;

        case MAIN_MENU_OPTION_QUIT :
          exit(0);
          break;
      }
    return(1);
  }


/*
 *  Menu Sub window handler
 */

BOOL Iconbar_MenuSubWindow(event_pollblock *event, void *reference)
  {
    window_handle info_window;

    switch (event->data.message.data.menuwarn.selection[0])
      {
        case MAIN_MENU_OPTION_INFO :
          info_window = Window_Create("infowindow", 0);
          if (info_window)
            {
              Icon_SetText(info_window, INFO_WINDOW_ICON_VERSION,
                VERSION_STRING);
              Wimp_CreateSubMenu((menu_block *)info_window,
                event->data.message.data.menuwarn.openpos.x,
                event->data.message.data.menuwarn.openpos.y);
              Menu_HandleDbox(info_window);
            }
          else
            Msgs_Report(0x00000000, "err.1", "info");
          break;
      }
    return(1);
  }


BOOL Iconbar_Click(event_pollblock *event, void *reference)
  {
    if (iconboot)
      Config_Confirm(NULL, (void *)0x01);
    else
      Config_OpenWindow();
    return(1);
  }


void Desktop_CreateIcon(void)
  {
/*
 *  Plonk an icon onto the iconbar
 */

    iconbar_icon = Icon_BarIcon("!BtRiscBSD", iconbar_RIGHT);

/*
 *  Claim mouse click events
 */
    Event_Claim(event_CLICK, iconbar_LEFT, iconbar_icon, Iconbar_Click, NULL);

    Menu_AttachMenu(main_menu, iconbar_LEFT, iconbar_icon, Iconbar_MenuSelect,
      Iconbar_MenuSubWindow, NULL, NULL);
  }


BOOL Close_Window(event_pollblock *event, void *reference)
  {
    window_handle *window = (window_handle *) reference;

    Window_Delete(*window);
    *window = NULL;
    return(1);
  }


BOOL App_ModeChange(event_pollblock *event, void *reference)
  {
    window_state wstate;
    event_pollblock ev;

    Handler_ModeChange(event, reference);
    
    if (config_backing)
      {
        Wimp_GetWindowState(config_backing, &wstate);
        ev.data.openblock = wstate.openblock;
        Config_PaneHandler(&ev, NULL);
      }
    
    return(0);
  }


BOOL Message_Filename(event_pollblock *event, void *reference)
  {
    message_block message;
    int filetype;
    char *filename;

/* Get the file type and filename from the message block */

    filetype = event->data.message.data.dataload.filetype;
    filename = (char *)&event->data.message.data.dataload.filename;

    if (event->data.message.header.action == message_DATAOPEN)
      {
        if (filetype != FILETYPE_UNIX)
          return(1);
        else
          {
            message.header.size = sizeof(message_header);
            message.header.yourref = event->data.message.header.myref;
            message.header.action = message_DATALOADACK;
            message.header.sender = event_taskhandle;

            Wimp_SendMessage(event_SEND, &message,
              event->data.message.header.sender, 0);
          }
      }

    if (filetype != FILETYPE_UNIX && filetype != FILETYPE_DATA
     && filetype != FILETYPE_DOS)
      {
        Msgs_Report(0x00000000, "err.3");
        return(1);
      }

/* Check the name */

    if (strlen(filename) > MAX_FILENAME_LENGTH)
      {
        Msgs_Report(0x00000000, "err.2");
        return(1);
      }
    else
      {
/* Ok we either have a a.out file to boot or a configuration file */

        if (Config_Load(filename) == 0)
          {
            if (config_window)
              Config_SetIcons();
          }
        else
          {
/*
 * Make sure the config structure is uptodate if the window is open as we
 * may be about to boot.
 */
            if (config_window)
              {
                Config_GetIcons();
                strcpy(config.kernel, filename);
                config.flags &= ~FLAG_NATIVE;
                Config_SetIcons();
              }
            else
              {
                strcpy(config.kernel, filename);
                config.flags &= ~FLAG_NATIVE;
               }
            
          }
      }

/*
 * If it was a DATAOPEN message or a DATALOAD to the iconbar
 * then we try booting the file
 */

    if (event->data.message.header.action == message_DATAOPEN
     || event->data.message.data.dataload.window == window_ICONBAR)
      Config_Confirm(NULL, (void *)0x01);

/* Indicate load is completed */

    return(1);
  }

/* End of desktop.c */
