/************************************************************************
 *									*
 *			Copyright (c) 1982, Fred Fish			*
 *			    All Rights Reserved 			*
 *									*
 *	This software and/or documentation is released for public	*
 *	distribution for personal, non-commercial use only.		*
 *	Limited rights to use, modify, and redistribute are hereby	*
 *	granted for non-commercial purposes, provided that all		*
 *	copyright notices remain intact and all changes are clearly	*
 *	documented.  The author makes no warranty of any kind with	*
 *	respect to this product and explicitly disclaims any implied	*
 *	warranties of merchantability or fitness for any particular	*
 *	purpose.							*
 *									*
 ************************************************************************
 */
/* Modified:
 * 30-Apr-86 Mic Kaczmarczik
 *	     - Use ctype.h macros instead of the function isdigit().
 *	     - Use VMS speed value for ospeed -- in microEmacs
 *	       this is obtainted by ttinit().
 *	28-Jul-88 Tom Hageman
 *		padding code is not compiled in if symbol NOPAD is #defined.
 *		(NOPAD will be defined automatically for GEMDOS/MSDOS)
 *	(See Log at end)
 */

#ifdef RCS_ID
static const char rcsid[] =
	"$Id: tputs.c,v 1.6 1993/04/07 01:37:43 tom Exp tom $";
#endif

/*
 *  LIBRARY FUNCTION
 *
 *	tputs	  output string with appropriate padding
 *
 *  KEY WORDS
 *
 *	termcap
 *
 *  SYNOPSIS
 *
 *	tputs (cp,affcnt,outc)
 *	char *cp;
 *	int affcnt;
 *	int (*outc)();
 *
 *  DESCRIPTION
 *
 *	Outputs string pointed to by cp, using function outc, and
 *	following it with the appropriate number of padding characters.
 *	Affcnt contains the number of lines affected, which is used
 *	as a multiplier for the specified per line pad time.  If
 *	per line pad count is not applicable, affcnt should be 1,
 *	NOT zero.
 *
 *	The format of the string pointed to by cp is:
 *
 *		[pad time][*]<string to send>
 *
 *		where:	pad time => time to delay in milliseconds
 *			* => specifies that time is per line
 *
 *	The pad character is assumed to reside in the external
 *	variable "PC".	Also, the external variable "ospeed"
 *	should contain the output speed of the terminal as
 *	encoded in /usr/include/sgtty.h  (B0-B9600).
 *
 * SYSTEM DEPENDENCIES
 *
 *	On VMS, the external variable "ospeed" should contain the
 *	output speed of the terminal as obtained from byte 3 of
 *	the iosb status buffer, using the IO$_SENSEMODE QIO.
 *	The table times[] compiles into the correct values for VMS,
 *	and, happily, also handles 19200 baud.
 *
 *	On MS-DOS or GEMDOS padding makes no sense, so it is not
 *	compiled in.
 *
 * BUGS
 *
 *	Return type should be void.
 */



/*
 *	Miscellaneous stuff
 */

#include <stdio.h>
#include "_termcap.h"

#define isdigit(c)	('0' <= (c) && (c) <= '9')

#ifndef NOPAD
#   if (GEMDOS || MSDOS)
#	define NOPAD	1
#   endif
#endif


#if !NOPAD
extern char PC; 		/* Pad character to use */
extern short ospeed;		/* Encoding of output speed */

#if !(vms || GEMDOS || MSDOS)	/* i.e., unix or Minix */
#   if _I_TERMIOS
#	include <termios.h>
#   else
#	if _I_TERMIO
#	    include <termio.h>
#	else
#	    include <sgtty.h>
#	endif
#   endif
#endif

#define INFINITY    32767		/* Infinite enough to me. */

/* Minix (1.5) has a rather peculiar speed encoding (baud/100). */
#if (B9600 == 96 && B2400 == 24)
#   define OSPEED_TO_10th_ms(o)		((o) ? (1000 + (o)>>1) / (o) : INFINITY)
#endif

#ifndef OSPEED_TO_10th_ms

#   ifndef B0
#	define B0	0
#   endif
#   ifndef B50
#	define B50	1
#   endif
#   if (B50 - B0 == 1)
#	define OSPEED_TO_10th_ms(o)	(times[(o) - B0])
#   else
#	define OSPEED_TO_10th_ms(o)	((o)==B0 ? INFINITY : times[(o)-B50+1])
#   endif

/* This macro converts baud rate to tenths of milliseconds. */

#   define BAUD_TO_10th_ms(baud)	((int)((100000L + (baud)/2) / (baud)))

static int times[] = {
	INFINITY,		/* Tenths of ms per char     0 baud (bogus) */
	BAUD_TO_10th_ms(50),
	BAUD_TO_10th_ms(75),
	BAUD_TO_10th_ms(110),
	BAUD_TO_10th_ms(134),
	BAUD_TO_10th_ms(150),
#if !vms
	BAUD_TO_10th_ms(200),
#endif
	BAUD_TO_10th_ms(300),
	BAUD_TO_10th_ms(600),
#if (B900)
	BAUD_TO_10th_ms(900),
#endif
	BAUD_TO_10th_ms(1200),
	BAUD_TO_10th_ms(1800),
#if vms
	BAUD_TO_10th_ms(2000),
#endif
	BAUD_TO_10th_ms(2400),
#if (B3600 || vms)
	BAUD_TO_10th_ms(3600),
#endif
	BAUD_TO_10th_ms(4800),
#if (B7200 || vms)
	BAUD_TO_10th_ms(7200),
#endif
	BAUD_TO_10th_ms(9600),
	BAUD_TO_10th_ms(19200),
	BAUD_TO_10th_ms(38400),
	INFINITY,			/* for future extensions. */
	INFINITY
};
#endif /* !OSPEED_TO_10th_ms */
#endif /* !NOPAD */


/*
 *  PSEUDO CODE
 *
 *	Begin tputs
 *	    If string pointer is invalid then
 *		Return without doing anything.
 *	    Else
 *		For each pad digit (if any)
 *		    Accumulate the lower digit.
 *		    Do decimal left shift.
 *		End for
 *		If there is a fractional field
 *		    Skip the decimal point.
 *		    If there is a valid tenths digit
 *			Accumulate the tenths.
 *		    End if
 *		    Discard remaining digits.
 *		End if
 *		If per line is specified then
 *		    Adjust the pad time.
 *		    Discard the per line flag char.
 *		End if
 *		While there are any characters left
 *		    Send them out via output function.
 *		End while
 *		Transmit any padding required.
 *	    End if
 *	End tgoto
 *
 */

int
tputs(cap, affcnt, outc)
const char	*cap;
int		affcnt;
int		(*outc)__(( int ));
{
	register const char	*cp;
#if !NOPAD
	register int ptime = 0; 	/* Pad time in tenths of milliseconds */
#endif
	if ((cp = cap) == NULL || *cp == '\0')
		return;

	while (isdigit(*cp))
#if !NOPAD
		ptime = (ptime + (*cp++ - '0')) * 10;
#else
		cp++;
#endif
	if (*cp == '.') {
		cp++;
#if !NOPAD
		if (isdigit(*cp))
			ptime += (*cp++ - '0');
#endif
		while (isdigit(*cp))
			cp++;
	}
	if (*cp == '*') {
		cp++;
#if !NOPAD
		ptime *= affcnt;
#endif
	}
	while (*cp)
		(*outc)(*cp++);

#if !NOPAD
	if (ptime > 0) {
		register int	tpc = OSPEED_TO_10th_ms(ospeed);

		ptime = (ptime + (tpc >> 1)) / tpc;
		while (--ptime >= 0)
			(*outc)(PC);
	}
#endif
}

/*======================================================================*
 * $Log: tputs.c,v $
 * Revision 1.6  1993/04/07  01:37:43  tom
 * fix typo in RCS Log.
 *
 *======================================================================*/
