/* !DLibShell.c.Shell */

/* DeskLib programmer's shell. */

/* Must be linked with AppHooks file */

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

#include "DeskLib:Event.h"
#include "DeskLib:EventMsg.h"
#include "DeskLib:Wimp.h"
#include "DeskLib:WimpSWIs.h"
#include "DeskLib:Icon.h"
#include "DeskLib:Template.h"
#include "DeskLib:Window.h"
#include "DeskLib:Handler.h"
#include "DeskLib:Screen.h"
#include "DeskLib:Menu.h"
#include "DeskLib:Resource.h"
#include "DeskLib:Coord.h"
#include "DeskLib:GFX.h"
#include "DeskLib:SWI.h"
#include "DeskLib:File.h"
#include "DeskLib:Error.h"

#include "SaveBox.h"
#include "Customise.h"

BOOL Shell_Modified;
char Shell_Filename[212];

/* Shell specific global variables */

window_handle Shell_MainWindow;
window_handle Shell_SaveWindow;
window_handle Shell_Confirm;

BOOL WindowOpen;

/* Menu system */

#define menu_IBAR 1
#define menu_MAIN 2

int Shell_CurrentMenu;

menu_ptr Shell_IBarMenu;
menu_ptr Shell_MainMenu;

BOOL shell_PowerMenus;
 
/* Confirmations */

#define shell_query_CLOSE 1
#define shell_query_QUIT  2

int shell_CurrentQuery;                     

/* Shell function prototypes */

void Shell_Initialise(void);
void Shell_SetUpWindows(void);
void Shell_SetUpIBar(void);

BOOL Shell_LoadMessage(event_pollblock *,void *);

BOOL Shell_IBarClick(event_pollblock *,void *);
BOOL Shell_MenuSelection(event_pollblock *,void *);
BOOL Shell_MenuWarning(event_pollblock *,void *);

void Shell_IBarMenuSelect(int s[]);

void Shell_OpenWindow(void);
void Shell_CloseWindow(void);

BOOL Shell_CloseRequest(event_pollblock *,void *);
BOOL Shell_MouseClick(event_pollblock *,void *);
BOOL Shell_RedrawWindow(event_pollblock *,void *);

void Shell_ForceRedraw(void);

void Shell_StartSave(void);
BOOL Shell_SaveHand(char *,BOOL,void *);

void Shell_LoadFile(char *);

void Shell_AskQuery(char *text,int number);
BOOL Shell_ClickYes(event_pollblock *,void *);
BOOL Shell_ClickNo(event_pollblock *,void *);

void Application_Initialise(void);
menu_ptr Application_MakeMenu(void);
void Application_SetMenuFlags(void);
void Application_ClickSelect(int x,int y);
void Application_ClickAdjust(int x,int y);
void Application_DoubleSelect(int x,int y);
void Application_DoubleAdjust(int x,int y);
void Application_DrawWindowContents(int,int);
void Application_MenuSelect(int sel[]);
BOOL Application_SaveFile(char *);
void Application_NewFile(void);
void Application_LoadFile(char *);

/* Main program */

int main(int argc,char **argv) {
  
  Shell_Initialise(); 
  
  if(argc==2)
    Shell_LoadFile(argv[1]);
  
  for(;;) {
    Event_Poll();
  }
  
  return(0);
}

/* Initialise program */

void Shell_Initialise(void)
{
  Resource_Initialise(APPNAME);
  Event_Initialise(APPNAME); /* RISC OS 2 compatible */
  Template_Initialise();
  Template_LoadFile("Templates");
  EventMsg_Initialise();
  Screen_CacheModeInfo();

  Shell_SetUpWindows();
  Shell_SetUpIBar();
  
  SaveBox_Initialise();
  
  Event_Claim(event_MENU,event_ANY,event_ANY,Shell_MenuSelection,0);   
  EventMsg_Claim(message_MENUWARNING,event_ANY,Shell_MenuWarning,0);
  EventMsg_Claim(message_DATALOAD,-2,Shell_LoadMessage,(void *)1);
  EventMsg_Claim(message_DATAOPEN,event_ANY,Shell_LoadMessage,0); 
  
  Application_Initialise(); 
}

BOOL Shell_LoadMessage(event_pollblock *LoadData,void *ref)
{
  message_block Reply;
  int ft=LoadData->data.message.data.dataload.filetype;
  
  ref=ref;

  if(ft==FILETYPE) {
    if(!WindowOpen) {
      Reply=LoadData->data.message;
      Reply.header.yourref=Reply.header.myref;
      Wimp_SendMessage(17,&Reply,(message_destinee)Reply.header.sender,0);    
      Shell_LoadFile(LoadData->data.message.data.dataload.filename);
    }
  }
  
  return TRUE;
} 

void Shell_SetUpWindows(void)
{
  Shell_MainWindow=Window_Create("mainwind",255);
  
  Shell_MainMenu=Application_MakeMenu();
  if(Shell_MainMenu==NULL) {
    Shell_MainMenu=Menu_New(APPNAME,WINMENU);
    shell_PowerMenus=FALSE;
  }
  else
  {
    shell_PowerMenus=TRUE;
  }
  
  Event_Claim(event_OPEN,Shell_MainWindow,event_ANY,Handler_OpenWindow,0);
  Event_Claim(event_CLOSE,Shell_MainWindow,event_ANY,Shell_CloseRequest,0);
  Event_Claim(event_CLICK,Shell_MainWindow,event_ANY,Shell_MouseClick,0);
  Event_Claim(event_REDRAW,Shell_MainWindow,event_ANY,Shell_RedrawWindow,0);  
  
  WindowOpen=FALSE;    
  
  Shell_Confirm=Window_Create("confirm",0);
  Event_Claim(event_CLICK,Shell_Confirm,0,Shell_ClickYes,0);
  Event_Claim(event_CLICK,Shell_Confirm,2,Shell_ClickNo,0);
  Event_Claim(event_OPEN,Shell_Confirm,event_ANY,Handler_OpenWindow,0);
}

void Shell_SetUpIBar(void)
{
  window_handle progInfo = Window_Create("progInfo",-1);
  Event_Claim(event_OPEN,progInfo,event_ANY,Handler_OpenWindow,0);
  Icon_SetText(progInfo,2,VERSION" ("__DATE__")");
  
  Icon_BarIcon(IBARNAME,iconbar_RIGHT);        
  Event_Claim(event_CLICK,-2,event_ANY,Shell_IBarClick,0);
  
  Shell_IBarMenu=Menu_New(APPNAME,"Info,Quit");
  Menu_AddSubMenu(Shell_IBarMenu,0,(menu_ptr)progInfo);
}

BOOL Shell_IBarClick(event_pollblock *ClickData,void *ref)
{
  ref=ref;
  
  if (ClickData->data.mouse.button.data.menu) {
    Menu_Show(Shell_IBarMenu,ClickData->data.mouse.pos.x,-1);
    Shell_CurrentMenu=menu_IBAR;
  }
  else if (ClickData->data.mouse.button.data.select) {
    Shell_OpenWindow();
  }  
  
  return TRUE;
}

BOOL Shell_MenuSelection(event_pollblock *Selection,void *ref)
{
  mouse_block ClickData;
  
  ref=ref;
  
  switch(Shell_CurrentMenu) {
    case menu_IBAR:
      Shell_IBarMenuSelect(Selection->data.selection);
      break;
    case menu_MAIN:
      Application_MenuSelect(Selection->data.selection);
      Wimp_GetPointerInfo(&ClickData);
      if(ClickData.button.data.adjust) {
        if(shell_PowerMenus)
          Application_SetMenuFlags();
        Menu_ShowLast();
      }
      break;
  }
  
  return TRUE;
}

BOOL Shell_MenuWarning(event_pollblock *Warning,void *ref)
{
  ref=ref;
  
  switch(Shell_CurrentMenu) {
    case menu_IBAR:
      Shell_IBarMenuSelect(Warning->data.message.data.menuwarn.selection);
      break;
    case menu_MAIN:
      Application_MenuSelect(Warning->data.message.data.menuwarn.selection);
      break;
  }
  
  return TRUE;
}

void Shell_IBarMenuSelect(int sel[]) {
  if(sel[0]==1) {
    if(Shell_Modified)
      Shell_AskQuery("You have edited a file but not saved it. Are you sure you want to quit?",shell_query_QUIT);
    else
      exit(0);
  }
}

BOOL Shell_RedrawWindow(event_pollblock *RedrawData,void *pb)
{
  BOOL More;
  wimp_point Origin;
  window_redrawblock rBlock;
  convert_block ConvBlock;               
  
  RedrawData=RedrawData; pb=pb;
  
  rBlock.window=Shell_MainWindow;
  Wimp_RedrawWindow(&rBlock,&More);
  More=abs(More);
  
  while (More) {
    ConvBlock.screenrect=rBlock.rect;
    ConvBlock.scroll=rBlock.scroll;
    Coord_WindowOrigin(&Origin,&ConvBlock);
    Application_DrawWindowContents(Origin.x,Origin.y);
    Wimp_GetRectangle(&rBlock,&More);
    More=abs(More);
  }
  
  return TRUE;
}  

void Shell_ForceRedraw(void)
{
  window_redrawblock RedrawIt;
  
  RedrawIt.window=Shell_MainWindow;
  Wimp_GetWindowOutline((window_outline *)(&RedrawIt));
  RedrawIt.window=-1;
  Wimp_ForceRedraw(&RedrawIt);
}  

void Shell_AskQuery(char *text,int qnum)
{
  shell_CurrentQuery=qnum;
  
  Icon_SetText(Shell_Confirm,1,text);
  Menu_Show((menu_ptr)Shell_Confirm,200,500);
}

BOOL Shell_ClickYes(event_pollblock *pb,void *ref)
{
  pb=pb; ref=ref;
  
  switch(shell_CurrentQuery) {
    case shell_query_QUIT:
      exit(0);
      break;
    case shell_query_CLOSE:
      Shell_CloseWindow();
      break;
  }
  
  Menu_Show((menu_ptr)-1,0,0);
  
  return TRUE;
}

BOOL Shell_ClickNo(event_pollblock *pb,void *ref)
{
  pb=pb; ref=ref;
  
  Menu_Show((menu_ptr)-1,0,0);
  
  return TRUE;
}

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

void Shell_OpenWindow(void)
{
  if(!WindowOpen) {
    Window_SetTitle(Shell_MainWindow,"<Untitled>");
    Shell_Modified=FALSE;
    Shell_Filename[0]=0;
    Application_NewFile();
    Window_Show(Shell_MainWindow,open_CENTERED);
    WindowOpen=TRUE;
  }
}

BOOL Shell_CloseRequest(event_pollblock *pb,void *ref)
{
  pb=pb; ref=ref;

  if(Shell_Modified)
    Shell_AskQuery("You have not saved this modified file. Are you sure you want to close it?",shell_query_CLOSE);
  else
    Shell_CloseWindow();
  
  return TRUE;
}

void Shell_CloseWindow(void)
{
  Window_Hide(Shell_MainWindow);
  WindowOpen=FALSE;
  Shell_Modified=FALSE;
}  
                                                                           
wimp_point Shell_MainWindowOrigin(void)
{
  window_state CurState;
  convert_block ConvBlock;
  wimp_point Origin;
  
  Wimp_GetWindowState(Shell_MainWindow,&CurState);
  
  ConvBlock.screenrect=CurState.openblock.screenrect;
  ConvBlock.scroll=CurState.openblock.scroll;
  
  Coord_WindowOrigin(&Origin,&ConvBlock);
  
  return Origin;
}  

BOOL Shell_MouseClick(event_pollblock *ClickData,void *ref)
{
  wimp_point origin=Shell_MainWindowOrigin();
  int x=ClickData->data.mouse.pos.x-origin.x;
  int y=ClickData->data.mouse.pos.y-origin.y;
  
  ref=ref;
  
  if(ClickData->data.mouse.button.data.menu) {
    if(shell_PowerMenus)
      Application_SetMenuFlags();
      
    Menu_Show(Shell_MainMenu,ClickData->data.mouse.pos.x,ClickData->data.mouse.pos.y);
    Shell_CurrentMenu=menu_MAIN;
  }
  else if (ClickData->data.mouse.button.data.clickselect) {
    Application_ClickSelect(x,y);
  }
  else if(ClickData->data.mouse.button.data.clickadjust) {
    Application_ClickAdjust(x,y);
  }
  else if (ClickData->data.mouse.button.data.select) {
    Application_DoubleSelect(x,y);
  }
  else if(ClickData->data.mouse.button.data.adjust) {
    Application_DoubleAdjust(x,y);
  }
  
  /* Drags could be included here */
  
  return TRUE;
}  

void Shell_StartSave(void)
{
  SaveBox_PopUp(Shell_Filename[0]==0 ? DEFFILENAME : Shell_Filename,
                               FILETYPE,Shell_SaveHand,0);
}

BOOL Shell_SaveHand(char *name,BOOL safe,void *ref)
{
  BOOL ok;
  
  ref=ref;
              
  ok=Application_SaveFile(name);
  if(ok) {
    SWI(3,0,0x08,18,name,FILETYPE);  
    if(safe) {
      Shell_Modified=FALSE;
      strcpy(Shell_Filename,name);
      Window_SetTitle(Shell_MainWindow,name);
    }
  }
  
  return(ok);
}                                  

void Shell_SetModified(void)
{         
  char block[214];
  
  if(Shell_Modified==FALSE)
  {                                    
    if(Shell_Filename[0]==0) {
      Window_SetTitle(Shell_MainWindow,"<Untitled> *");
    }
    else 
    {               
      sprintf(block,"%s *",Shell_Filename);
      Window_SetTitle(Shell_MainWindow,block);
    }
    Shell_Modified=TRUE;
  }
}  

void Shell_LoadFile(char *fn)
{
  if(!WindowOpen) {            
    Shell_OpenWindow();
    Window_SetTitle(Shell_MainWindow,fn);
    strcpy(Shell_Filename,fn);
    Application_LoadFile(fn);
    Shell_ForceRedraw();
  }
}


