/* 
   win32-util.c, utitity routines for native win32 port of newLISP 

    Copyright (C) 2007 Lutz Mueller

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

//
// for function: gettimeofday() 
//
// Copyright (C) 1992-2002 Steve Adams
// 
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2, 1991,
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
*/

/*
//
// Copyright (c) 1992-2007 Lutz Mueller 
// 
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2, 1991,
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
*/


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <windows.h>
#include <io.h>

/* ------------------------  gettimeofday() ------------------------ */


struct timezone {
       int     tz_minuteswest;
       int     tz_dsttime;
};

int gettimeofday( struct timeval *tp, struct timezone *tzp )
{
  SYSTEMTIME lpt;
  TIME_ZONE_INFORMATION tzi;
  int result = 0;

  time_t        Now;
  Now         = time( NULL );
  tp->tv_sec  = Now;

  GetSystemTime(&lpt);
  tp->tv_usec = lpt.wMilliseconds * 1000;

  if(tzp != NULL)
  {
    result = GetTimeZoneInformation(&tzi);
    tzp->tz_minuteswest = tzi.Bias;
    tzp->tz_dsttime = tzi.DaylightBias;
  }

  return(result);
}

/* ---------------------------- pipes -------------------------------------- */

int winPipedProcess(char * cmd, int inpipe, int outpipe, int option)
{
STARTUPINFO si = { 0 };
PROCESS_INFORMATION process;
int result;
long fin, fout; 

/* GetStartupInfo(&si);  */
si.cb = sizeof(si);
si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
si.wShowWindow = option; /* SW_SHOW, SW_HIDE  get additional user option in Win32 versions */

fin = _get_osfhandle(inpipe);
fout = _get_osfhandle(outpipe);

si.hStdInput = (inpipe) ? (HANDLE)fin : GetStdHandle(STD_INPUT_HANDLE);
si.hStdOutput = (outpipe) ? (HANDLE)fout : GetStdHandle(STD_OUTPUT_HANDLE);
si.hStdError = (outpipe) ? (HANDLE)fout : GetStdHandle(STD_OUTPUT_HANDLE);

if((result = CreateProcess(NULL,cmd,NULL,NULL,TRUE,DETACHED_PROCESS,NULL,NULL,&si, &process)) == 0)
	return(0); 

/* let this be handled by parent process
CloseHandle((HANDLE)fin);
CloseHandle((HANDLE)fout);
*/

return(process.dwProcessId);
}

/*
typedef struct _PROCESS_INFORMATION { // pi  
    HANDLE hProcess; 
    HANDLE hThread; 
    DWORD dwProcessId; 
    DWORD dwThreadId; 
} PROCESS_INFORMATION; 
*/


int winPipe(UINT * inpipe, UINT * outpipe)
{
SECURITY_ATTRIBUTES sa = { 0 };
HANDLE pipe_r, pipe_w;

sa.nLength = sizeof(sa);
sa.bInheritHandle = TRUE;
sa.lpSecurityDescriptor = NULL;

if(!CreatePipe(&pipe_r, &pipe_w, &sa, 0))
	return(0);

*inpipe = _open_osfhandle((long) pipe_r, 0);
*outpipe = _open_osfhandle((long) pipe_w, 0);


return(1);
}


/* ---------------------------------- semaphores ---------------------------- */

UINT winCreateSemaphore(void)
{
SECURITY_ATTRIBUTES security = { 0 };
HANDLE hSemaphore;

security.nLength = sizeof(security);
security.bInheritHandle = TRUE;
security.lpSecurityDescriptor = NULL; /* default of caller */

hSemaphore = CreateSemaphore(&security, 0, 65536, NULL);

return((UINT)hSemaphore);
} 

UINT winWaitSemaphore(UINT hSemaphore)
{
DWORD dwWaitResult; 

dwWaitResult = WaitForSingleObject((HANDLE)hSemaphore, INFINITE);

if(dwWaitResult == WAIT_FAILED)
	return(FALSE);

return(TRUE);
}

UINT winSignalSemaphore(UINT hSemaphore, int count)
{
return(ReleaseSemaphore((HANDLE)hSemaphore, count, NULL));
}

int winDeleteSemaphore(UINT hSemaphore) 
{
return (CloseHandle((HANDLE)hSemaphore));
}

/*
See: http://www.codeguru.com/Cpp/W-P/win32/article.php/c1423/
QuerySemaphore() call
int winGetSemaphoreCount(UINT hSemaphore) {}
*/

/* ---------------------------- shared memory interface -------------------- */

UINT winSharedMemory(int size)
{
SECURITY_ATTRIBUTES sa = { 0 };
HANDLE hMemory;

sa.nLength = sizeof(sa);
sa.bInheritHandle = TRUE;
sa.lpSecurityDescriptor = NULL; /* default of caller */

hMemory = CreateFileMapping((HANDLE)0xFFFFFFFF, &sa, PAGE_READWRITE, 0, size, NULL);

return((UINT)hMemory);
}

UINT * winMapView(UINT hMemory, int size)
{
return((UINT*)MapViewOfFile((HANDLE)hMemory, FILE_MAP_WRITE, 0, 0, size));
}

/* ---------------------------- timer -------------------------------------- */


#include "newlisp.h"
#include "protos.h"

extern SYMBOL * timerEvent;
extern int milliSecTime(void);

/* 
UINT_PTR SetTimer(HWND hWnd, UINT_PTR nIDEvent, UINT uElapse, TIMERPROC lpTimerFunc);
BOOL KillTimer(HWND hWnd, UINT_PTR uIDEvent);
*/

void timerFunc(void * dummy);
int timerDuration = 0;
int rollover = 0;
int start;

CELL * p_timerEvent(CELL * params)
{
CELL * symCell;
double seconds;
int now;

if(params != nilCell) 
  {
  params = getSymbol(params, &timerEvent);

  if(params != nilCell)
	{
    getFloat(params, &seconds);
    timerDuration = 1000 * seconds;
	if(timerDuration > 0)
		{
    	start = milliSecTime();
    	_beginthread(timerFunc, 0, 0);
    	seconds = timerDuration/1000.0;
		}
	}
  else
    {
    /* return the elapsed time */
    seconds = ((now = milliSecTime()) < start ? 
			86400000 - start + now :
            now - start)/1000.0;  
    }
  return(stuffFloat(&seconds));    
  }
  
symCell = getCell(CELL_SYMBOL);
symCell->contents = (UINT)timerEvent;
return(symCell);
}


void timerFunc(void * dummy)
{
if(timerDuration == 0) return;

/* take care of midnight rollover */
if((rollover = start + timerDuration - 86400000) > 0)
    {
	while(milliSecTime() > start) mySleep(10); /* wait for rollover */
	while(milliSecTime() < rollover) mySleep(10);
	}
else
	while( milliSecTime() < (start + timerDuration) ) mySleep(10);

if(recursionCount)
  traceFlag |= TRACE_TIMER;
else /* if idle */
  executeSymbol(timerEvent, NULL);
}

/* eof */


syntax highlighted by Code2HTML, v. 0.9.1