/*     
      SCOL ENVIRONMENT . Magma 1.0 . 1996 . Sylvain HUET

         hardload.c : chargement des packages systèmes
*/
// Modification history:
//
//$ FA(13/04/2001): Load base package
//$ FA(21/05/2001): Integrate debugger
//$ FA(10/07/2001): Load packages 3d registering and display packages
//$ FA(10/07/2001): Load packages 3d registering and display packages
//$ FA(03/08/2001): Add MMputs() function to echo strings of unrestricted length
//$ FA(26/10/2001): Recreate the base environment in a hash table
//$ FA(12/11/2001): Replace SCOL_DEBUGGER_AWARE by INCLUDE_DEBUGGER
//
//$ LB (13/06/2002) : added the OBJgetNewHandler function to the cbmachine
//



#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#include <windows.h>

#include "../kernel/include/kernel.h"
#include "../kernel/scol.h"
#include "../kernel/scolsys.h"
//$ FA(10/07/2001)
#include "../kernel/3d/display.h"
#include "../kernel/3d/register.h"
//
#include "winscol.h"
#include "listlab.h"
#include "macros.h"
#include "scolobj.h"



/* FONCTIONS DU KERNEL EXPORTEES VERS LE PLUGIN
  ----------------------------------------------*/

struct CBmachine
{
int (*MMpush)(mmachine m, int val);
int (*MMpushNoGC)(mmachine m, int val);
int (*MMpull)(mmachine m);
int (*MMgetPP)(mmachine m);
void (*MMsetPP)(mmachine m,int i);
int (*MMget)(mmachine m,int i);
void (*MMset)(mmachine m,int i,int v);
int (*MMgetglobal)(mmachine m,int i);
void (*MMsetglobal)(mmachine m,int i,int v);
int (*MMgetbase)(mmachine m,int b,int i);
void (*MMsetbase)(mmachine m,int b,int i,int v);
int (*MMfetch)(mmachine m,int s,int i);
void (*MMstore)(mmachine m,int s,int i,int v);
int* (*MMstart)(mmachine m,int s);
int (*MMsize)(mmachine m,int s);
int (*MMtype)(mmachine m,int s);
char* (*MMstartstr)(mmachine m,int s);
int (*MMsizestr)(mmachine m,int s);
void (*MMsetsizestr)(mmachine m,int s,int size);
int (*MMmalloc)(mmachine m, int size, int type);
int (*MMmallocCLR)(mmachine m, int size, int type);
int (*Mpushstrbloc)(mmachine m,char *buf);
int (*MBdeftab)(mmachine m);
int (*MBstrcat)(mmachine m);
int (*PKhardpak)(mmachine m, char *name,
              int n, char **namefun, int (**fun)(mmachine z)
              , int *nargfun, char **typfun);
int (*PKloader)(mmachine m,char *name,char *simplename);
int (*SPfindfile)(packdir p,char *sign,int *size,char *path);
int (*SPaddfile)(packdir p,char *sign,int size,char *path);
int (*SCgetsrvsocket)(mmachine m, int server);
int (*SCgetsocket)(mmachine m, int channel);
int (*Mcutting)(char *comm, char **argv);
void (*MMechostr)(int i,char *buf,...);
int (*fread)(char* buf,int i,int j,FILE *f);
packdir Firstpack;
int (*OBJcreate)(mmachine m,int typ,int handsys,int typpere,int handsyspere);
int (*OBJaddreflex)(mmachine m,int typ, int num);
int (*OBJbeginreflex)(mmachine m,int typ,int handsys,int num);
int (*OBJdel)(mmachine m,int p,int flag);
int (*OBJdestroy)(mmachine m, int typ,int handsys,int objm,int flag);
int (*OBJdelTH)(mmachine m,int typ,int handsys);
int (*OBJcallreflex)(mmachine m,int nbarg);
int (*OBJregister)(int nbrefl,int recrefl,int (*destroy)(mmachine m,int handsys,int objm),char *name);
int (*OBJtypebyname)(char *name);
int (*OBJdefEvent)(int event,int (*cbevent)(mmachine m,HWND hwnd, unsigned msg,
				UINT wParam,LONG lParam,int *ret));
int (*OBJgetUserEvent)();
void* (*SCgetExtra)(char *funcname);
char* (*stdloadJpg)(char *name,int *w,int *h);
int (*OBJdelTM)(mmachine m,int typ,int q);
int (*OBJfindTH)(mmachine m,int typ,int handsys);
int (*OBJfindTM)(mmachine m,int typ,int objm);
int (*Mpushstrblocn)(mmachine m,char *buf, int n);
int (*Minterpreter)(mmachine m);
int (*Msearchinsyspak)(mmachine m, char *name);
int (*MBstrcatn)(mmachine m);
int (*Buffer2texture)(mmachine m, char *buffer, int width, int height);
void (*MMputs)(int i, const char* text);

//$ LB (13/06/2002)
int (*OBJgetNewHandler)();
};
typedef struct CBmachine *cbmachine;

extern cbmachine ww;



extern char hardware3d[128];
extern void regX3D(char* name,void* address);
extern int mt_start(int per,int param,int (*fun)(int i,int param));
extern int mt_del(int i);
extern int MX3registerDevice(char *clearname,char *id);
extern int Minterpreter(mmachine m);
extern int Msearchinsyspak(mmachine m, char *name);
extern int tstscoldead(int i);
extern LRESULT CALLBACK WindowProc( HWND hwnd, unsigned msg, UINT wParam, LONG lParam ) ;
extern sysexe SCexeSearch(char *categ, char *name);
extern int SPstorepack(mmachine m);
extern HWND ActiveXhwnd;

void* SCgetExtra(char *funcname)
{
  if (!strcmp(funcname,"hscol")) return hscol;
  if (!strcmp(funcname,"this_inst")) return thisinst;
  if (!strcmp(funcname,"FirstPack")) return Firstpack;
  if (!strcmp(funcname,"free")) return free;
  if (!strcmp(funcname,"3dhardware")) return hardware3d;
  if (!strcmp(funcname,"regX3D")) return regX3D;
  if (!strcmp(funcname,"GRCreateBitmap")) return NULL;
  if (!strcmp(funcname,"GRCreateBitmap8")) return NULL;
  if (!strcmp(funcname,"GRDestroyBitmap")) return NULL;
  if (!strcmp(funcname,"GRGetBitmapSize")) return NULL;
  if (!strcmp(funcname,"GRCopyBitmap")) return NULL;
  if (!strcmp(funcname,"mt_start")) return mt_start;
  if (!strcmp(funcname,"mt_del")) return mt_del;
  if (!strcmp(funcname,"MX3registerDevice")) return MX3registerDevice;

  // added for exteriorisation of lib2d
  if (!strcmp(funcname,"tstscoldead")) return tstscoldead;
  if (!strcmp(funcname,"windowproc")) return WindowProc;
  if (!strcmp(funcname,"scexesearch")) return SCexeSearch;
  if (!strcmp(funcname,"SPstorepack")) return SPstorepack;

  if (!strcmp(funcname,"ActiveXhwnd")) return ActiveXhwnd;

  return NULL;
}

int SCinitCBm(cbmachine w)
{
	w->MMpush=MMpush;
    w->MMpushNoGC=MMpushNoGC;
    w->MMpull=MMpull;
    w->MMgetPP=MMgetPP;
    w->MMsetPP=MMsetPP;
    w->MMget=MMget;
    w->MMset=MMset;
    w->MMgetglobal=MMgetglobal;
    w->MMsetglobal=MMsetglobal;
    w->MMgetbase=MMgetbase;
    w->MMsetbase=MMsetbase;
    w->MMfetch=MMfetch;
    w->MMstore=MMstore;
    w->MMstart=MMstart;
    w->MMsize=MMsize;
    w->MMtype=MMtype;
    w->MMstartstr=MMstartstr;
    w->MMsizestr=MMsizestr;
    w->MMsetsizestr=MMsetsizestr;
    w->MMmalloc=MMmalloc;
    w->MMmallocCLR=MMmallocCLR;
    w->Mpushstrbloc=Mpushstrbloc;
    w->MBdeftab=MBdeftab;
    w->MBstrcat=MBstrcat;
    w->PKhardpak=PKhardpak;
    w->PKloader=PKloader;
    w->SPfindfile=SPfindfile;
    w->SPaddfile=SPaddfile;
    w->SCgetsrvsocket=SCgetsrvsocket;
    w->SCgetsocket=SCgetsocket;
    w->Mcutting=Mcutting;
    w->MMechostr=MMechostr;
    w->fread=fread;
    w->Firstpack=Firstpack;
    w->OBJcreate=OBJcreate;     
    w->OBJaddreflex=OBJaddreflex;  
    w->OBJbeginreflex=OBJbeginreflex;
    w->OBJdel=OBJdel;        
    w->OBJdestroy=OBJdestroy;    
    w->OBJdelTH=OBJdelTH;
    w->OBJcallreflex=OBJcallreflex;
    w->OBJregister=OBJregister;
    w->OBJtypebyname=OBJtypebyname;
	w->OBJdefEvent=OBJdefEvent;
	w->OBJgetUserEvent=OBJgetUserEvent;
	w->SCgetExtra=SCgetExtra;
//    w->stdloadJpg=stdloadJpg;
    w->OBJdelTM=OBJdelTM;
	w->OBJfindTH=OBJfindTH;
	w->OBJfindTM=OBJfindTM;
    w->Mpushstrblocn=Mpushstrblocn;
	w->Minterpreter=Minterpreter;
	w->Msearchinsyspak=Msearchinsyspak;
    w->MBstrcatn=MBstrcatn;
    w->Buffer2texture=NULL;
    w->MMputs=MMputs;

	//$ LB (13/06/2002)
	w->OBJgetNewHandler=OBJgetNewHandler;
    return 0;
}

typedef int (*FCM)(mmachine,cbmachine);
typedef int (*FCLOSECM)();

struct CBmachine wcb;

#define NBDLLMAX 32
char namedll[NBDLLMAX][128];
char fundll[NBDLLMAX][128];
char funclosedll[NBDLLMAX][128];
HANDLE hdll[NBDLLMAX];
int idll;

int SCregistDLL(char *name,char *fun,char *funclose)
{
	if (idll>=NBDLLMAX) return 0;
	strcpy(namedll[idll],name);
	fundll[idll][0]=0;
	funclosedll[idll][0]=0;
	if (fun) strcpy(fundll[idll],fun);
	if (funclose) strcpy(funclosedll[idll],funclose);
	idll++;
	return 0;
}

int SCloadDLLs(mmachine m)
{
    int i,k;
    HANDLE hLibrary;
    FCM SCOLloadDLL;

    SCinitCBm(&wcb);
	for(i=0;i<idll;i++)
	{
	    hLibrary=LoadLibrary(namedll[i]);
		hdll[i]=hLibrary;
		if (hLibrary)
		{
			if ((fundll[i][0])
				&&(SCOLloadDLL=(FCM)GetProcAddress(hLibrary,fundll[i])))
			{
				if (k=(*SCOLloadDLL)(m,&wcb)) return k;
			}
		}
	}
    return 0;
}

int SCOLendTimer();
int SCOLfreeHTTP();

int SCfreeDLLs()
{
    int i,k;
    HANDLE hLibrary;
	FCLOSECM SCOLcloseDLL;

	
    for(i=0;i<idll;i++)
	{
		hLibrary=hdll[i];
		if (hLibrary)
		{
			if ((funclosedll[i][0])
				&&(SCOLcloseDLL=(FCLOSECM)GetProcAddress(hLibrary,funclosedll[i])))
			{
				if (k=SCOLcloseDLL()) return k;
			}
            FreeLibrary(hLibrary);

        }
	}
	SCOLendTimer();
    SCOLfreeHTTP();
    idll=0;

    return 0;
}

int SCiniDLLs()
{
	idll=0;
	return 0;
}

int SCOLloadHTTP(mmachine m);
int SCOLloadHTTPserver(mmachine m);

//$LB (05/03/2002)
int SCOLloadINETCONNECT(mmachine m);

int IniTELNET(mmachine m);
int SCOLloadlogger(mmachine m);

int SCOLloadTimer(mmachine m);
int SCOLloadBOX(mmachine m);
int SCOLloadCOLL(mmachine m);

int SCOLloadBN(mmachine m);
int SCOLloadSYS(mmachine m);
//$ FA(01/11/2000)
int SCOLloadDebug(mmachine m);
//$ FA(13/04/2001): Declaration of base package loader
int SCOLloadBase(mmachine m);
//
int (*CBinit)(mmachine m);



int SCinitsyspack(mmachine m)
{
  int k;

  if (MMpush(m,NIL)) return MERRMEM;

  if (k=SCOLloadHTTP(m)) return k;
  if (k=SCOLloadHTTPserver(m)) return k;
  if (k=SCOLloadTimer(m)) return k;

  //$LB (05/03/2002)
  if (k=SCOLloadINETCONNECT(m)) return k;

  if (k=SCOLloadlogger(m)) return k;
  if (k=SCOLloadBN(m)) return k;

  if (k=IniTELNET(m)) return k;

//if (k=SCOLloadM3D(m)) return k;
  if (k=SCloadDLLs(m)) return k;


  if (k=SCOLloadSYS(m)) return k;
//$ FA(01/11/2000): Load debugger package
  if (k = SCOLloadDebug(m))
    return k;
//$ FA(13/04/2001): Load base package
  if (k = SCOLloadBase(m))
    return k;
//
//$ FA(10/07/2001)
  if (k = loadPackageDisplay(m))
    return k;
  if (k = loadPackageDevice3D(m))
    return k;
//
//$ FA(24/10/2001): Recreate the base environment in a hash table
#if !defined(INCLUDE_DEBUGGER)
  SECHECK(createInitialEnvironment(m));
//printInitialEnvironment(m);
#endif
  SECHECK(SEDUP(m));
//
  if (CBinit) if (k=CBinit(m)) return k;

  return 0;
}
