/* outtext.c  94.12.13
 * Copyright 1983-1992   Albert Davis
 * output text to files, devices, or whatever
 * m???? = multiple output to a bunch of io devices.
 *	    with character count (so tab will work)
 * Will start a new line first if the entire output will not fit.
 * so wrap will not break a word or number.
 * Where is a bit mask of places to send the output.
 * A possible portability problem exists with the handle numbers.
 * It assumes they start at 0, and count up, and that there are no more than
 * the number of bits in an integer (MAXHANDLE).
 * but I have yet to find a system that did not meet this form.
 */
#include "ecah.h"
#include "io.h"
#include "options.h"
#include "declare.h"
/*--------------------------------------------------------------------------*/
	void mtab(int,int);
	void mprintf(int,const char*,...);
	void mputs(const char*,int);
	void mputc(int,int);
/*--------------------------------------------------------------------------*/
extern const struct ioctrl io;
extern const struct options opt;
static int cpos[MAXHANDLE+1];		/* character counter    */
extern FILE *stream[];			/* reverse of fileno()  */
/*--------------------------------------------------------------------------*/
/* mtab: tab to column "count" on output devices "where"
 * by outputting spaces.
 * If already beyond, start new line, then tab to column.
 */
void mtab(int count, int where)
{
 int ii,mm;
 for (ii=0, mm=1;   ii<=MAXHANDLE;   ++ii, mm<<=1){
    if (where & mm){
       if (cpos[ii] > count)
	  mputc('\n',mm);
       while (cpos[ii]<count)
	  mputc(' ',mm);
    }
 }
}
/*--------------------------------------------------------------------------*/
/* mprintf: multiple printf
 * printf to "m" style files.
 */
void mprintf(int where, const char *fmt, ...)
{
 char buffer[BIGBUFLEN];
 va_list arg_ptr;

 va_start(arg_ptr,fmt);
 vsprintf(buffer,fmt,arg_ptr);
 va_end(arg_ptr);

 mputs(buffer,where);
}
/*--------------------------------------------------------------------------*/
/* mputs: multiple puts.
 * puts to "m" style files.
 * also....
 * starts new line, prefixes it with + if it would exceed width
 * width is handled separately for each file to support different widths
 * (which are not currently handled by .options)
 * and it is possible that current contents of lines may be different
 */
void mputs(const char *str, int where)
{
 int ii;	/* file counter */
 int mm;	/* file counter mask */
 int sl;	/* length of output string */
 int newline;	/* true if any destination is at beginning of line */

 newline = NO;
 sl = strlen(str);
 for (ii=0, mm=1;   ii<=MAXHANDLE;   ++ii, mm<<=1){
    if (where & mm   &&   (sl+cpos[ii]) >= opt.outwidth){
       mputc('\n',mm);
       mputc('+',mm);
    }
    if (cpos[ii]==0)
       newline = YES;
 }
 if (io.outcipher && newline)
    mputc('\t',where);
 while (*str)
    mputc(*str++,where);
}
/*--------------------------------------------------------------------------*/
/* mputc: multiple putc
 * multiple putc
 * also....
 * crunch spaces, if selected
 * encripts, if selected
 * keeps track of character count
 */
void mputc(int chr, int where)
{
 int ii,mm,suppress,count;
 static int old = '\0';
 static int cchr = 'w';			/* starting encryption seed	    */
					/* arbitrary printable character    */
 if (chr=='\t'){
    chr = ' ';
    count = NO;
 }else{
    count = YES;
 }

 suppress = (io.pack && old==' ' && chr==' ');
 old = chr;
 if (io.outcipher && !suppress && isprint(chr)){
    cchr += (unsigned int)chr;
    while (!isascii(cchr)  ||  !isprint(cchr))
	cchr -= (0x7f-0x20);
    chr = (char)cchr;
 }

 for (ii=0, mm=1;   ii<=MAXHANDLE;   ++ii, mm<<=1){
    if (where & mm){
       if (chr=='\b'){
	  --cpos[ii];
	  (void)fflush(stream[ii]);
       }else if (count){
	  ++cpos[ii];
       }
       if (chr=='\n'){
	  cpos[ii] = 0;
	  (void)fflush(stream[ii]);
#ifdef CRLF_FIX
	  (void)fputc('\r',stream[ii]);
#endif
       }else if (chr=='\r'){
	  if (cpos[ii] == 0){
	     suppress = YES;
	  }else{
	     cpos[ii] = 0;
	     (void)fflush(stream[ii]);
	  }
       }
       if (!suppress)
	  (void)fputc(chr,stream[ii]);
    }
 }
}
/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/
