/*****************************************************************************
 * 
 * Nom                          : utils.c
 * desc                         : utilitaires projet
 *
 * version                      : $VER: utils.c 2.2 (11.04.98)
 *
 * ver 2.1: error handling
 * ver 2.2: some bug fixed
 *
 *****************************************************************************
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <exec/exec.h>
#include <exec/ports.h>
#include <exec/io.h>
#include <exec/tasks.h>
#include <exec/libraries.h>
#include <dos/datetime.h>
#include <dos/dosextens.h>
#include <workbench/workbench.h>
#include <libraries/notifyintuition.h>

#include <proto/exec.h>
#include <proto/intuition.h>
#include <proto/dos.h>
#include <proto/graphics.h>
#include <proto/gadtools.h>
#include <proto/icon.h>
#include "utils.h"
#include "timer.h"
#include "tracewin.h"
#include "notify.h"
#include "partial.h"
#include "conf.h"
#include "obp.h"

struct Library * NotifyIntuitionBase ;

char * ptrTime = NULL ;
struct DateTime * dt = NULL ;

idWin * init(WBArg * appName) {
  /* initalize the main window
   * and the project
   */
  struct Screen  * WBScreen = NULL ;                 // lock on WB
  idWin * prjWin = NULL ;                            // main prj
  
  if ((prjWin = AllocVec(sizeof(idWin), MEMF_PUBLIC|MEMF_CLEAR)) == NULL)
    return(NULL) ;
    
    
  if ((prjWin->date = AllocVec(sizeof(struct DateStamp), MEMF_PUBLIC)) == NULL) {
    close(prjWin) ;
    return(NULL) ;
  }
    
  if ((prjWin->Notify = AllocVec(sizeof(struct IntNotifyRequest), MEMF_PUBLIC|MEMF_CLEAR)) == NULL) {
    close(prjWin) ;
    return(NULL) ;
  }
  
  
  if ((NotifyIntuitionBase = OpenLibrary(NOTIFYINTUITIONNAME, NOTIFYINTUITION_VMIN)) != NULL) {
        /* open the window
         */
    LoadConf(prjWin) ;
    WBScreen = LockPubScreen("Workbench") ;
    top = WBScreen->BarHeight ; 
    prjWin->wb   = WBScreen ;
    init_bitmap(prjWin) ;
    prjWin->win = OpenWindowTags(NULL, WA_Left,   prjWin->backWin.posX,
                                       WA_Top,         prjWin->backWin.posY,
                                       WA_Width,       prjWin->backWin.width,
                                       WA_Height,      prjWin->backWin.height,
                                       WA_IDCMP,       IDCMP,
                                       WA_MinWidth,	 50,
                                       WA_MinHeight,   50,
                                       WA_MaxHeight,   200,
                                       WA_MaxWidth,    200,
                                       WA_Flags,       WFLG_BORDERLESS,
                                       WA_ScreenTitle, "BackClock", 
                                       WA_NewLookMenus, TRUE,
                                       WA_PubScreenName, "Workbench", TAG_DONE) ;
    
    szgdg.Height = top - 1 ;
    szgdg.NextGadget = &tagdg ;
    tagdg.LeftEdge  = prjWin->win->Width - 10 ;
    tagdg.TopEdge   = prjWin->win->Height - 10 ;
    tagdg.Width     = 10 ;
    tagdg.Height    = 10 ;
  
    AddGList(prjWin->win, &szgdg, 0, 2, NULL) ;
   
    RefreshGList(&szgdg, prjWin->win, NULL, -1) ;
                                                                                             
    if (prjWin->win == NULL)
      return(NULL) ;
    
    if (prjWin->win)
      WindowToBack(prjWin->win) ;
    if (prjWin->wb)
      UnlockPubScreen(NULL, WBScreen) ;
    
                                                                                                
          // initialisation ...  (fenetre...)
  }else {
    close(prjWin) ;
    return(NULL) ;
  }
  initwin(prjWin) ;
  if (!initTimer(prjWin))   { close(prjWin) ; return(NULL) ;}
  if (!startNotify(prjWin)) { close(prjWin) ; return(NULL) ;}
  if ((ptrTime = AllocVec(LEN_DATSTRING, MEMF_PUBLIC|MEMF_CLEAR)) == NULL) {close(prjWin) ; return(NULL) ;}
  if ((dt =      AllocVec(sizeof(struct DateTime),  MEMF_PUBLIC)) == NULL) {close(prjWin) ; return(NULL) ;}
  return prjWin ;
}

void close(idWin * prj) {
  int i;
  if (prj) {                              // struct prj existe (<>0) 
    endNotify(prj) ;
    if (prj->win) CloseWindow(prj->win) ; // ferme la fenetre
    free_twin(prj) ; 
    if (prj->date) FreeVec(prj->date) ;   // libere datestamp 
    if (prj->Notify) FreeVec(prj->Notify) ; // libere struct IntNotify
    closeTimer(prj) ;
    
    if (NotifyIntuitionBase) CloseLibrary(NotifyIntuitionBase) ;
    prj->wb = LockPubScreen("Workbench") ;
    for(i = 0; i<NUM_COLORS; i++)
      freePen(prj, prj->backWin.cmap[i].reg) ;
    if (prj->wb) UnlockPubScreen(NULL, prj->wb) ;
    FreeVec(prj) ;                        // libere la memoire
    if (ptrTime) FreeVec(ptrTime) ;
    free_bitmap(prj) ;
  }
}
void getDate(idWin * prj) {
  // remplit la structure (projet) avec la date
   
  DateStamp(prj->date) ;
  if (ptrTime) {  
    CopyMem(prj->date, &(dt->dat_Stamp), sizeof(struct DateStamp)) ;
    dt->dat_Format = FORMAT_DOS ;
    dt->dat_Flags = NULL ;
    dt->dat_StrDay  = NULL ;
    dt->dat_StrDate = NULL ;
    dt->dat_StrTime = ptrTime ;
    DateToStr(dt) ;
    //CopyMem(ptrTime, prj->datestr, LEN_DATSTRING) ;
    prj->oldH = prj->heu ;
    prj->oldM = prj->min ;
    prj->oldS = prj->sec ;
    DateToByte(ptrTime, prj) ;
  
  }
}

void processwin(idWin* prj) {
  /* variables
   */
  ULONG signals = NULL,                                                                          /* masque des signaux a attendre */
        mask,
        class,                                                                                                                   /* masque des signaux recus */
        sigtimer ;
        
  BOOL  stop    = FALSE ;                                                                                                                /* vrai si ctrl c */
  struct IntuiMessage * msg = NULL ;                     /* ptr sur message intuition */
  struct MsgPort      * extPort = NULL ;
  struct backMsg      * extmsg = NULL ;
  
  extPort = CreateMsgPort() ;
  extPort->mp_Node.ln_Name = AllocVec(10, MEMF_PUBLIC) ;
  CopyMem("backclock", extPort->mp_Node.ln_Name, 10) ;
  AddPort(extPort) ;
  
  sigtimer =  (1<<(prj->treq->tr_node.io_Message.mn_ReplyPort->mp_SigBit)) ; 
  /* signaux d'attentes
   */
  signals = SIGBREAKF_CTRL_C | 
            (1<<(prj->notifyPort->mp_SigBit)) | 
            (1<<(prj->win->UserPort->mp_SigBit)) | sigtimer|
            (1<<(extPort->mp_SigBit)) ;
  
  runtimer(prj) ;
  getDate(prj) ;
  retracer(prj) ;
  while(!stop) {
    mask = Wait(signals) ;
    if (mask & SIGBREAKF_CTRL_C) {
      /* recu le signal CTRL C
       */
      stop=TRUE;
    }
    if (mask & (1<<(extPort->mp_SigBit))) {
      // recu message prog externe
      extmsg = (struct backMsg *)GetMsg(extPort) ;
      if (extmsg->Class == BC_Quit) {
        // recu demande d'arret
        stop=TRUE ;
        extmsg->error = OK ;
      }
      if (extmsg->Class == BC_GetPrj) {
        // recu demande d'envoi du projet
        extmsg->ptrPrj = prj ;
        extmsg->error = OK ;
      }
      if (extmsg->Class == BC_RefreshColors) {
        setColors(prj) ;
      }
      if (extmsg->Class == BC_Refresh) {
        // refresh window (redraw)
        reinit_win(prj) ;
        getDate(prj) ;
        effacer(prj) ;
        retracer(prj) ;
        extmsg->error = OK ;
      }
      if (extmsg->Class == BC_SaveConf) {
        SaveEnv(prj, TRUE) ;
        if (prj->lastError) extmsg->error = prj->lastError ;
      }
      if (extmsg->Class == BC_UseConf) {
        SaveEnv(prj, FALSE) ;
        if (prj->lastError) extmsg->error = prj->lastError ;
      }
      if (extmsg->Class == BC_SetWindow) {
        setWindow(prj) ;
        extmsg->error = OK ;
      }
      if (extmsg) ReplyMsg((struct Message*)extmsg) ;
    }
    if (mask & (1<<(prj->notifyPort->mp_SigBit))) {
      // attention fermeture du WB
      if (partialClose(prj)) partialOpen(prj) ;
    }
    if (mask & 1<<(prj->win->UserPort->mp_SigBit)) {
      /* recu message d'intuition
       */
      while((msg = GT_GetIMsg(prj->win->UserPort)) != NULL) {
        /* retourne le message
         */
        class = msg->Class ;
        ReplyMsg((struct Message*)msg) ;
        if(class == IDCMP_CHANGEWINDOW) {
          
          RemoveGList(prj->win, &szgdg, 2) ;
          szgdg.Width = prj->win->Width ;
          tagdg.LeftEdge = prj->win->Width -10 ;
          tagdg.TopEdge = prj->win->Height -10 ;
          prj->backWin.width = prj->win->Width ;
          prj->backWin.height = prj->win->Height ;      
          prj->backWin.posX = prj->win->LeftEdge ;
          prj->backWin.posY = prj->win->TopEdge ;
          setWindow(prj) ;
          reinit_win(prj) ; 
          AddGList(prj->win, &szgdg, 0, 2, NULL) ;
          RefreshGList(&szgdg, prj->win, NULL, -1) ;

          SaveEnv(prj, TRUE) ;
        }  
      }          
    }
    if (CheckIO((struct IORequest*)prj->treq)) {
      WaitIO((struct IORequest*)prj->treq) ;
      AbortIO((struct IORequest*)prj->treq) ;
      WaitIO((struct IORequest*)prj->treq) ;
      runtimer(prj) ;
      getDate(prj) ;
      effacer(prj) ;
      retracer(prj) ;
      //WindowToBack(prj->win) ;
    }  
 
  }
  AbortIO((struct IORequest*)prj->treq) ;
  WaitIO((struct IORequest*)prj->treq) ;
  RemPort(extPort) ;
  FreeVec(extPort->mp_Node.ln_Name) ;
  DeleteMsgPort(extPort) ;
     
}

void ez_req(UBYTE * title, UBYTE * body, UBYTE * gadg, APTR arglist ) {
  struct EasyStruct * ez_rq ;
  
  if (ez_rq = AllocVec(sizeof(struct EasyStruct), MEMF_PUBLIC)) {
    if (ez_rq->es_Title = AllocVec(strlen(title)+1, MEMF_PUBLIC)) {
     strcpy(ez_rq->es_Title, title) ;
     if (ez_rq->es_TextFormat = AllocVec(strlen(body)+1, MEMF_PUBLIC)) {
      strcpy(ez_rq->es_TextFormat, body) ;
      if (ez_rq->es_GadgetFormat = AllocVec(strlen(gadg)+1, MEMF_PUBLIC)) {
       strcpy(ez_rq->es_GadgetFormat, gadg) ;
       ez_rq->es_StructSize = sizeof(EasyStruct) ;
       ez_rq->es_Flags = NULL ;
       EasyRequestArgs(NULL, ez_rq, NULL, arglist) ;
       FreeVec(ez_rq->es_GadgetFormat) ;
      }
      FreeVec(ez_rq->es_TextFormat) ;
     }
     FreeVec(ez_rq->es_Title) ;
    }
    FreeVec(ez_rq) ;
  }
}

