/***********************************************************
Copyright 1991 by the Massachusetts Institute of Technology

Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation, and that the name of M.I.T. not be used in advertising or
publicity pertaining to distribution of the software without specific,
written prior permission.  M.I.T. makes no representations about the
suitability of this software for any purpose.  It is provided "as is"
without express or implied warranty.


Author: Roman J. Budzianowski - Project Athena MIT

******************************************************************/

#include "WindowStream.h"
//#include <xt++/Xaw/AsciiText.h>
#include <X11/StringDefs.h>

static void InputDone(Core* , XEvent* , String* , Cardinal* );

static XtActionsRec actions[] =
{ 
   {"InputDone", InputDone},
};



void windowbuf::initialize()
{
   if(widget)
     widget->GetAppContext()->AddActions(actions, XtNumber(actions));
}

void windowbuf::print()
{
   int w = pptr() - pbase();
   dbp();
   cerr << "size= " << w << "\n";
   cerr << "In print: \n";
   cerr << pbase() << "\n";
   cerr << "Done.\n";
}
/*
streambuf* windowbuf::setbuf(char*  p, int len)
{
   cerr << "In windowbuf::setbuf.\n";
   return 0;
}
*/
int windowbuf::overflow(int c)
{
//   cerr << "In windowbuf::overflow. \n";

//   if(!(mode&ios::out)) return EOF;

   if(allocate()==EOF){
      cerr << "Not allocated.\n";
      return EOF;
   }
   
   if(gptr() && gptr() < egptr() ) {
      cerr << "Chars in get area: " << gptr() << "\n";
      return EOF;
   }

   setg(0,0,0);

   if(!widget){
      cerr << "%%WindowStream: widget not set.\n";
      setp(0,0);
      return EOF;
   }

   if(!pptr()) setp(base(),base());

   int w = pptr() - pbase();

   if(c!=EOF) {
      *pptr()=c;
      ++w;
   }

   // this should be a separate virtual method

   XawTextBlock text;
   text.firstPos = 0;
   text.length = w;
   text.ptr = pbase();
   text.format = FMT8BIT;

   XawTextPosition position = widget->GetInsertionPoint();

   if(XawEditDone == widget->Replace(position,
				 position,
				 &text)){
      widget->SetInsertionPoint(position+text.length);
      setp(base(),ebuf() -1);
//      cerr << "In windowbuf::overflow*** leaving \n";
      return zapeof(c);
   }
   else {
      cerr << "%%WindowStream: replace failed.\n";
      setp(0,0);
      return EOF;
   }

}


static void InputDone(Core* c, XEvent* , String* , Cardinal* )
{
   c->GetAppContext()->ExitLoop();
}

int windowbuf::underflow()
{
   // if(!(mode&ios::in)) return EOF;

   if(allocate()==EOF) return EOF;

   // flush output
   if(pptr() && pptr() > pbase()) overflow(EOF);

   setp(0,0);

   if(blen()>1) setg(base(),base()+1,ebuf());
   else         setg(base(),base(),ebuf());

   if(!widget){
      cerr << "%%WindowStream: widget not set.\n";
      setg(0,0,0);
      return EOF;
   }

   // this should be a separate virtual method

//   XawTextBlock text;
//   text.firstPos = 0;
//   text.length = 0;
//   text.ptr = pbase();
//   text.format = FMT8BIT;

   XawTextPosition position = widget->GetInsertionPoint();

/*********   
   /// XXX
//   cerr << "**Grabbing Keyboard!!!\n";
//   XSync(widget->XtDisplay(), False); // DDD debugging 

//   int retVal = widget->GrabPointer(False,
   int retVal = widget->GrabKeyboard(False,
//				    KeyPressMask|KeyReleaseMask|ButtonPressMask|ButtonReleaseMask,
//				    ButtonPressMask|ButtonReleaseMask,
				     GrabModeSync,GrabModeAsync,
//				     None,None,
				     CurrentTime);
   if(retVal != GrabSuccess)
     cerr << "WindowStream: cannot grab keyboard\n";
******/
   // XXX update Core.h to add the toolkit grab funs
   XtAddGrab(widget,True,False);
   widget->GetAppContext()->MainLoop();
   XtRemoveGrab(widget);
/********
//   widget->UngrabPointer(CurrentTime);			// remove grab
   widget->UngrabKeyboard(CurrentTime);			// remove grab
   XSync(widget->XtDisplay(), False); // DDD debugging 
**********/
//   No way to get a block of text !!!!!
//   TextSrcObject* src = widget->GetSource();
//   Is there a way to use our buffer  in TextWidget ?
//   we don't always want it 

   String in;

   ArgArray args;

   args(XtNstring)=XtArgVal(&in);
   widget->GetValues(args);

   // XXX long size ?
   int size= (int)(widget->GetInsertionPoint() - position);

   if(size){
      in = in + position;

//      cerr << "WS::underflow:  string= " << in << "$\n" << "blen= " << blen() << "\n";

      strncpy(base(),in,size);
      setg(base(),base(),base()+size);

      return zapeof(*gptr());
   }
   else{
      setg(0,0,0);
      return EOF;
   }

}


void windowbuf::clear()
{
   // flush output
   if(pptr() && pptr() > pbase()) overflow(EOF);
   widget->SetValues(XtNstring,(XtArgVal)"");
}

void windowbuf::top()
{
   // don't know how to scroll to the top
   // a little kludge for now

#define KLUDGE_COUNT 10
   int i=0;
   while(i++<KLUDGE_COUNT)
     sputc('\n');
   overflow(EOF);
}

/*
int windowbuf::sync()
{
   cerr << "In windowbuf::sync. \n";
   if(gptr() && egptr() > gptr())
     return EOF;

   if(pptr() && pptr() > pbase() ) 
     return overflow(EOF);

   return 0;
}

*/

owstream& clear(owstream& wo)
{
   wo.clear();
   return wo;
}

owstream& top(owstream& wo)
{
   wo.top();
   return wo;
}

