
/*  Copyright (c) 1993 by Kenneth Duda <kkkken@athena.mit.edu>.  
 *  All rights reserved.
 *
 *  This program is distributed in the hope that it will be useful.
 *  Use and copying of this software and preparation of derivative works
 *  based upon this software are permitted, so long as the following
 *  conditions are met:
 *       o credit to the author is acknowledged 
 *       o no fees or compensation are charged for use, copies, or
 *         access to this software
 *       o this copyright notice is included intact.
 *  This software is made available AS IS, and no warranty is made about 
 *  the software or its performance. 
 * 
 *  Bug descriptions, use reports, comments or suggestions are welcome.
 *  Send them to <kkkken@athena.mit.edu>.
 */

#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/StringDefs.h>
#include <X11/IntrinsicP.h>
#include <X11/CoreP.h>
#include <X11/Xaw/XawInit.h>
#include <X11/Xaw/AsciiText.h>
#include "AsciiTtyP.h"
#include "kgo.h"


#define MINWIDTH 210
#define MINHEIGHT 210
#define DEFWIDTH 380
#define DEFHEIGHT 380

#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))
#define offset(field) XtOffset(AsciiTtyWidget,asciitty.field)

static void AsciiTtyInitialize(), AsciiTtyDestroy(), SendCmd();

static XtResource AsciiTtyResources[] = {
    { XtNtextLimit, XtCTextPosition, XtRInt, sizeof(int),
	  offset(textLimit), XtRString, "8192" },
};

static XtActionsRec actionsList[] = { 
  {"sendcmd",		SendCmd},
};
  
AsciiTtyClassRec asciiTtyClassRec = {
        { /* core fields */
    /* superclass		*/	(WidgetClass) &asciiTextClassRec,
    /* class_name		*/	"AsciiTty",
    /* widget_size		*/	sizeof(AsciiTtyRec),
    /* class_initialize		*/	XawInitializeWidgetSet,
    /* class_part_initialize	*/	NULL,
    /* class_inited		*/	FALSE,
    /* initialize		*/	AsciiTtyInitialize,
    /* initialize_hook		*/	NULL,
    /* realize			*/	XtInheritRealize,
    /* actions			*/	actionsList,
    /* num_actions		*/	XtNumber(actionsList),
    /* resources		*/	AsciiTtyResources,
    /* resource_count		*/	XtNumber(AsciiTtyResources),
    /* xrm_class		*/	NULLQUARK,
    /* compress_motion		*/	TRUE,
    /* compress_exposure	*/	TRUE,
    /* compress_enterleave	*/	TRUE,
    /* visible_interest		*/	FALSE,
    /* destroy			*/	AsciiTtyDestroy,
    /* resize			*/	XtInheritResize,
    /* expose			*/	XtInheritExpose,
    /* set_values		*/	NULL,
    /* set_values_hook		*/	NULL,
    /* set_values_almost	*/	XtInheritSetValuesAlmost,
    /* get_values_hook		*/	NULL,
    /* accept_focus		*/	XtInheritAcceptFocus,
    /* version			*/	XtVersion,
    /* callback_private		*/	NULL,
    /* tm_table			*/	XtInheritTranslations,
    /* query_geometry           */	XtInheritQueryGeometry,
    /* display_accelerator      */	XtInheritDisplayAccelerator,
    /* extension                */	NULL
    },
  { /* Simple fields */
    /* change_sensitive	*/	XtInheritChangeSensitive
  },
  { /* text fields */
    /* empty            */      0
  },
  { /* ascii fields */
    /* empty            */      0
  },
  { /* asciitty fields */
    /* empty            */      0
  }
};

WidgetClass asciiTtyWidgetClass = (WidgetClass) &asciiTtyClassRec;


static void SetEditType (text, type)
     Widget text;
     int type;
{
    Arg args[1];
    
    XtSetArg(args[0], XtNeditType, type); /* Hmmm */
    XtSetValues(text, args, 1);
}
     
static void AsciiTtyInitialize(request, new)
     Widget request;
     Widget new;
{
    AsciiTtyWidget atw = (AsciiTtyWidget) new;
    XtTranslations tr = XtParseTranslationTable("<Key>Return:   sendcmd()\n");

    XtOverrideTranslations (new, tr);
    atw->asciitty.userInputStart = 0;
    SetEditType (new, XawtextAppend);
    
}


static void AsciiTtyDestroy(w)
     Widget w;
{
}

XawTextPosition XawGetLastPos (w)
     Widget w;
{
    AsciiTtyWidget atw = (AsciiTtyWidget) w;

    return atw->text.lastPos;		/* Grab it right out of widget */
					/* I don't know how else to get this */
}

void XawAsciiTtyOutput (w, text, len)
     Widget w;
     char *text;
     int len;
{
    AsciiTtyWidget atw = (AsciiTtyWidget) w;
    XawTextBlock block;
    XawTextPosition end, del;
    XawTextPosition pos = atw->asciitty.userInputStart;
    
    if (len <= 0) return;
    block.firstPos = 0;
    block.length = len;
    block.ptr = text;
    block.format = XA_STRING;		/* What the hey ... */
    SetEditType (w, XawtextEdit);
    XawTextReplace (w, pos, pos, &block);
    atw->asciitty.userInputStart += len;
    end = XawGetLastPos(w);
    if (end > atw->asciitty.textLimit) {
	block.length = 0;
	del = atw->asciitty.textLimit / 2;
	XawTextReplace (w, 0, del, &block);
	end -= del;
	atw->asciitty.userInputStart -= del;
    }
    SetEditType (w, XawtextAppend);
    XawTextSetInsertionPoint (w, end);
}

void XawAsciiTtySimulateInput (w, txt, len)
     Widget w;
     char *txt;
     int len;
{
    XawTextBlock block;
    XawTextPosition pos = XawGetLastPos (w);
    
    if (len <= 0) return;
    block.firstPos = 0;
    block.length = len;
    block.ptr = txt;
    block.format = XA_STRING;		/* What the hey ... */
    XawTextReplace (w, pos, pos, &block);
}    

static void SendCmd(w, event, params, num_params)
     Widget w;
     XEvent *event;
     String *params;
     Cardinal *num_params;
{
    AsciiTtyWidget atw = (AsciiTtyWidget) w;
    XawTextPosition start;
    XawTextPosition end;
    char *txt;

    XawAsciiTtySimulateInput (w, "\n", 1);
    start = atw->asciitty.userInputStart;
    end = XawGetLastPos(w);
    atw->asciitty.userInputStart = end;
    if (start < end) {
	txt = (char *) _XawTextGetText (atw, start, end); /* Found this by using the force */
	
	SendServerNoEcho(txt);		/* Whee.. huge abstraction break */
	SetOutputSink (w);		/* a callback would be so much nicer */
					/* but I'm such a lazy bum */
	XtFree(txt);
    }
}
		    
