/*  usercomg.C   */
/*  Copyright 1990 Mountain Math Software  */
/*  All Rights Reserved                    */

#include <stream.h>
#include <ctype.h>
#include "usercom.h"
#include "cgidbg.h"
#include "grphio.h"
#include "portable.h"
#include "basicio.h"
#include "xdrv.h"
#include "dsp_app.h"


typedef void (RootMenuView::*root_scroll)(const char *);

struct X_WindowBuf {
	char * buffer ;
	char * buffer_end ;
	char * next ;
	void write(int c);
	root_scroll scroll ;
	void init(root_scroll scr);
	void flush();
};

void X_WindowBuf::flush()
{
	if (next == buffer) return ;
	*next++ = '\0' ;
	RootMenuView& gbg = *(DspApplication::root_window());
	(gbg.*scroll)(buffer);
	next = buffer ;
}

void X_WindowBuf::write(int c)
{
	if (c == '\n' || c == '\r') {
		flush();
		return ;
	}
	if (next >= buffer_end) flush();
	*next++ = c;
}

void X_WindowBuf::init(root_scroll scr)
{
	buffer = new char[DspApplication::spacer_length()+1] ;
	buffer_end = buffer + DspApplication::spacer_length() ;
	next = buffer ;
	scroll = scr ;
}

const NumberBuffers = 3 ;
class X_WindowBuffers {
	X_WindowBuf buffer[NumberBuffers];
	X_WindowBuf * buf_from_type(OutputType);
public:
	X_WindowBuffers();
	void write(OutputType win, int c);
	void flush(OutputType win);
	void flush();
};


void X_WindowBuffers::flush()
{
	for (int i = 0 ; i < NumberBuffers ;i++) buffer[i].flush();
}

void X_WindowBuffers::flush(OutputType win)
{
	X_WindowBuf * buf = buf_from_type(win);
	if (!buf) return ;
	buf->flush();
}

void X_WindowBuffers::write(OutputType win, int c)
{
	X_WindowBuf * buf = buf_from_type(win);
	if (!buf) return ;
	buf->write(c);
}

X_WindowBuf * X_WindowBuffers::buf_from_type(OutputType type)
{
    switch (type) {
case OutputCppEntry:
case OutputCppHelp:
	return buffer + 1 ;
case OutputMenu:
case OutputHelp:
	return buffer ;
case OutputPrompt:
case OutputPlot:
case OutputAcknowledge:
	// cerr << "X_WindowsBuffer::buf_from_type - type " << type << "\n" ;
	return 0 ;
case OutputInfo:
	return buffer + 2 ;
default:
case OutputUndefined:
case OutputEndOfOutputTypes:
case OutputNotInitialized:
        DbgError("RootMenuView::RemoteServer","bad type");
    }
	return 0 ;
}

X_WindowBuffers::X_WindowBuffers()
{
	buffer[0].init(&(RootMenuView::scroll));
	buffer[1].init(&(RootMenuView::cpp_scroll));
	buffer[2].init(&(RootMenuView::help_info_string));
}


static X_WindowBuffers * TheX_Buffers = 0 ;

int WindowBuf::overflow(int c)
{
	if (!GraphicsMode) return 0 ;
	if (!TheX_Buffers) TheX_Buffers = new X_WindowBuffers ;
	TheX_Buffers->write((OutputType) PortIndex, c);
	return 0 ;
}

ostream& OutCon::operator+(int TheType)
{
    return Basic->SetWindow(TheType);
}



void OutCon::Flush()
{
	if (GraphicsMode) return ;
	cout.flush();
}
