/******************************************************************************
*   "Irit" - the 3d polygonal solid modeller.				      *
*									      *
* Written by:  Gershon Elber				 Ver 0.2, Mar. 1990   *
*******************************************************************************
* Procedures to handle the dos interface - print/change the current dir. etc. *
******************************************************************************/

#ifdef __MSDOS__
#include <stdlib.h>
#include <dir.h>
#include <dos.h>
#include <time.h>
#include <float.h>
#include <process.h>
#include <graphics.h>
#else
#include <sys/types.h>
#include <sys/times.h>
#include <sys/param.h>
#ifndef HZ
#define HZ 60
#endif  /* HZ */
#endif /* __MSDOS__ */

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include "program.h"

#ifdef __MSDOS__
#include "mousedrv.h"
#endif /* __MSDOS__ */

#include <stdio.h>
#include "dosintrl.h"
#include "dosintrg.h"
#include "ctrl-brk.h"

#ifndef __MSDOS__
#include "xgraphic.h"
#endif /* __MSDOS__ */

#include "graphgng.h"
#include "windowsg.h"

/******************************************************************************
* Procedure to print the current directory content in menu area:	      *
* Print file name and size in k bytes one per line. if page is full	      *
* (> ~20 lines) it pause and continue in next page. No sort is perform.       *
******************************************************************************/
void DosPrintDir(char *Match)
{
#ifdef __MSDOS__
    int StrCount, Reset = TRUE;
    char s[LINE_LEN];
    struct ffblk ffblk;

    getcwd(s, LINE_LEN-1);		   /* Might be 64 chars at the most. */
    WndwInputWindowPutStr(s, NO_COLOR);

    if (Match == NULL || strlen(Match) == 0) Match = "*.*";

    StrCount = 0;     /* Count number of file names written allready into s. */
    s[0] = 0;
    if (!findfirst(Match, &ffblk, FA_DIREC))
	do {
	    switch (ffblk.ff_attrib) {
		case FA_DIREC: /* Directory */
		    sprintf(&s[strlen(s)], "<DIR> %-13s", ffblk.ff_name);
		    break;
		default: /* regular file */
		    sprintf(&s[strlen(s)], " %3dk %-13s",
			(int) ((ffblk.ff_fsize+1023)/1024), ffblk.ff_name);
		    break;
	    }
	    if (++StrCount == 4) {			/* Print the string: */
		WndwInputWindowPutStrFS(s, NO_COLOR, Reset);
		Reset = FALSE;
		StrCount = 0;
		s[0] = 0;
	    }
	}
	while (!findnext(&ffblk));

    if (StrCount > 0)					/* Print the string: */
	WndwInputWindowPutStrFS(s, NO_COLOR, Reset);
#else
    fprintf(stderr, "Not implemented on this system.\n");
#endif /* __MSDOS__ */
}

/*****************************************************************************
*   Routine to change current directory					     *
*****************************************************************************/
void DosChangeDir(char *s)
{
#ifdef __MSDOS__
    char cwd[LINE_LEN], *sptr;

    getcwd(cwd, LINE_LEN-1);			   /* Save current position. */

    if (s[1] == ':') sptr = &s[2];	    /* Sptr points on the path only. */
    else sptr = s;

    if (strlen(sptr) != 0 && chdir(s))
	WndwInputWindowPutStr("CHDIR: No Such Dir!", RED);
    else if (s[1] == ':') {
	if (islower(s[0])) s[0] = toupper(s[0]);
	setdisk(s[0] - 'A');			    /* Move to the new disk. */
	if (getdisk() != s[0] - 'A')
	    WndwInputWindowPutStr("CHDIR: No Such Disk!", RED);

    }

    if (getcwd(s, LINE_LEN-1) == NULL) {      /* Test if directory is valid! */
	WndwInputWindowPutStr("CHDIR: hardware (!?) error - ignored", RED);
	/* Restore old working directory: */
	if (strlen(&cwd[2]) != 0) chdir(cwd); /* If directory is not root... */
	if (islower(cwd[0])) cwd[0] = toupper(cwd[0]);
	setdisk(cwd[0] - 'A');		       /* Move to the original disk. */
    }
#else
    fprintf(stderr, "Not implemented on this system.\n");
#endif /* __MSDOS__ */
}

/******************************************************************************
* Procedure to return current time from last time, time was reset.	      *
* Time is reset if the given parameter is non zero. Time is returned in       *
* seconds. This routine should be called at the beginning of the program to   *
* reset it time.							      *
* As we return only one parameter, on unix systems - the sum. of the user and *
* system time is returned, which is all the time used for this process.	      *
******************************************************************************/
double DosGetTime(double ResetTime)
{
#ifdef __MSDOS__
    double t;
    static time_t LastTime;
    time_t CurrentTime;

    time(&CurrentTime);

    t = difftime(CurrentTime, LastTime);

    if (!APX_EQ(ResetTime, 0.0)) {			  /* Reset the time! */
	time(&LastTime);
    }

    return t;
#else
    static double LastTime = 0.0;
    double t, NewTime;
    struct tms TimeBuffer;

    times(&TimeBuffer);

    NewTime = ((double) TimeBuffer.tms_utime) / HZ +
	      ((double) TimeBuffer.tms_stime) / HZ;

    t = NewTime - LastTime;

    if (!APX_EQ(ResetTime, 0.0)) {			  /* Reset the time! */
	LastTime = NewTime;
    }

    return t;
#endif /* __MSDOS__ */
}

/******************************************************************************
* Procedure to execute the editor as defined by the global variable EditPrgm  *
* as a child process, and wait for its completion.			      *
* The routine release all resources before and reclaim them after.	      *
******************************************************************************/
void DosEditFile(char *Str)
{
#ifdef __MSDOS__
    char *Err = NULL;

    DosReleaseResources();

    if (spawnl(P_WAIT, EditPrgm, EditPrgm, Str, NULL) == -1) {	   /* Do it! */
	/* Error had occured - trace it: */
	switch(errno) {
	    case ENOENT:
		Err = "Editor not found in path specified";
		break;
	    case ENOMEM:
		Err = "Not enough memory to run editor";
		break;
	    default:
		Err = "Undefined error in attempt to run editor";
	}
    }

    DosReclaimResources();

    if (Err != NULL) WndwInputWindowPutStr(Err, RED);
#else
    fprintf(stderr, "Not implemented on this system.\n");
#endif /* __MSDOS__ */
}

/******************************************************************************
* Procedure to execute the command processor as defined by COMSPEC	      *
* environment variable and enter it as a child process.			      *
******************************************************************************/
void DosSystem(void)
{
#ifdef __MSDOS__
    char *FullPath, *Err = NULL;

    if ((FullPath = getenv("COMSPEC")) == NULL) {
	WndwInputWindowPutStr("No COMSPEC environment variable, cannt escape to system",
		RED);
	return;
    }

    DosReleaseResources();

    if (spawnl(P_WAIT, FullPath, FullPath, NULL) == -1) {	   /* Do it! */
	/* Error had occured - trace it: */
	switch(errno) {
	    case ENOENT:
		Err = "No command processor found in COMSPEC path specified";
		break;
	    case ENOMEM:
		Err = "Not enough memory to escape to system";
		break;
	    default:
		Err = "Undefined error in attempt to escape to system";
	}
    }

    DosReclaimResources();

    if (Err != NULL) WndwInputWindowPutStr(Err, RED);
#else
    fprintf(stderr, "Not implemented on this system.\n");
#endif /* __MSDOS__ */
}

#ifdef __MSDOS__

/******************************************************************************
* Procedure to release all resources used by the program.		      *
******************************************************************************/
static void DosReleaseResources(void)
{
    WndwClaimStatus();		/* Disable status printing on status window. */
    GGCloseGraph();				/* Close the graphic driver. */
    if (MouseExists) MouseClose();		/* Disable mouse interrupts. */
    RestoreCtrlBrk();			      /* Restore ctrl-brk interrupt. */
}

/******************************************************************************
* Procedure to reclaim all resources used by the program.		      *
******************************************************************************/
static void DosReclaimResources(void)
{
    GGInitGraph(); 			     /* Initiate the graphic driver. */
    GGClearAllScreen();
    WndwDrawAllWndwFrames();			 /* Draw the windows frames. */

    if (MouseExists) MouseInit();

    WndwStatusWindowDraw();  /* Update the status window - beginning status. */
    WndwInputWindowPutStr("Back to IRIT...", YELLOW);/* Refresh input window.*/

    _fpreset();	       /* Reset the floating point package to a known state. */

    WndwReclaimStatus();	 /* Enable status printing on status window. */
    WndwStatusWindowDraw();    /* Update the status window - current status. */
}

#endif /* __MSDOS__ */
