#include "fido.h"
#include <ascii.h>
#include "fidomem.h"
#include "proto.h"

/*
	Modem & other I/O for fido. These enforce time limits
	only if hlimit is set.

modin(n)	Returns a character available, else -1 if more that N
		times 10 milliseconds.

modout(c)	Outputs C to the modem.

modstat()	Returns true if a modem character available.

mbreak()	Generates a 1/2 second break signal.

limitchk()	Checks the set time limit, and logs off if exceeded.

flush(n)	Flush the modem until it is clear for n centiseconds.

cd()		Returns true if Carrier Detect is true or CD_FLAG
		is true.

idle()		Call this whenever there is nothing to do except
		spin in a loop waiting for something, like keyboard
		or modem input, etc. Potentially does somethign useful
		with the wasted time.

	The above all watch the modem via cd(), and if it goes false,
logs the caller off by calling logoff(0,1). (Closes the file, exits to DOS.)

*/

/* If doubleDOS is enabled, pass idle time to the other task. */

void idle() {

	switch (fido.mtasker) {
		case 1: dbldos(); break;	/* Double DOS */
		case 2: desqview(); break;	/* DESQview */
	}
}

/* Check the time limit, and if over, bump the guy off. */

void limitchk() {

	if (limit && (minutes >= limit)) logoff(0,1);
}

/* Generate a 1/2 second break signal. */

void mbreak() {
	_mbreak(1);			/* start a break, */
	delay(50);			/* 1/2 sec delay */
	_mbreak(0);			/* break off */
}

/* Return true if a modem character is available. */

int modstat() {

	if (test) return(0);
	carrierchk();			/* watch carrier, */
	if (hlimit) limitchk();		/* watch time limits */
	return(_mconstat());
}

/* Output to the modem. */

void modout(c)
char c;
{
	if (test) return;

	while (! _mconostat()) {		/* while not ready, */
		carrierchk();			/* watch carrier */
		if (hlimit) limitchk();		/* watch time limits */
		if (datarate < 2400) idle();	/* idle at  l o w  baud rates */
	}
	carrierchk();				/* always watch this */
	_mconout(c);				/* limit will get checked eventually */
}
/* Get a character from the modem, with a maximum wait time, in
centiseconds. Returns -1 if timeout. */

int modin(n)
unsigned n;
{
long til;

	if (test) return(-1);		/* cant in test mode */
	if (hlimit) limitchk();		/* watch time limits */
	carrierchk();			/* watch disconnect, */
	if (_mconstat()) return(_mconin()); /* why wait? */

	til= (n * 10L) + millis2;	/* time we stop */
	while (millis2 < til) {
		carrierchk();		/* watch disconnect, */
		if (hlimit) limitchk();	/* watch time limits */
		if (_mconstat()) 	/* if a char avail, return it. */
			return(_mconin());
		if (n > 10) idle();	/* nothing ready yet */
	}
	return(-1);			/* timeout */
}

/* Flush modem in & out buffers. */

void mflush() {

	if (! test) _mflush();
}

/* Delay N centiseconds. Do nothing in the mean time. */

void delay(n)
int n;
{
long til;

	til= (n * 10L) + millis2;		/* time we stop */
	while (millis2 < til) {
		if (n > 10) idle();		/* idle() if coarse delay */
	}
}
/* Logoff if carrier is lost. */

void carrierchk() {

	if (! cd()) {
		logoff(0,1);
	}
}

/* Return true if carrier detect is true or "ignore CD" is true. */

int cd() {

int n;

	if (_cd()) return(1);		/* be fast for normal operation */

	for (n= 50; n--;)
		if (_cd() || cd_flag || test) return(1);
	return(0);
}

/* Flush the modem until its quiet for N centiseconds or just flush
whatever is there if n == 0. */

void flush(n)
int n;
{
	if (n) while (modin(n) != -1);
	else while (_mconstat()) _mconin();
}
