/* $Id: TERMINAL.CPP 2.4 1995/07/20 11:24:33 leon Exp $
 *
 *      GISEL - G-CODE ISEL CNC driver
 *
 *      Copyright (c) 1994 LECAD
 *      All Rights Reserved.
 *
 */

#define Uses_TKeys

#define Uses_TRect

#define Uses_TEvent

#define Uses_TButton

#define Uses_TDialog

#define Uses_TMenuBar

#define Uses_TSubMenu

#define Uses_TMenuItem

#define Uses_TStaticText

#define Uses_TStreamableClass

#define Uses_TStreamable

#define Uses_TDeskTop

#define Uses_MsgBox

#define Uses_TApplication

#define Uses_TScroller

#define Uses_TTerminal


#include <tvision/tv.h>

__link( RView )
__link( RWindow )
__link(RScroller)
__link(RScrollBar)

#include <iostream.h>

#include <fstream.h>

#include <strstrea.h>

#include <string.h>

#include <ctype.h>

#pragma hdrstop


#include <conio.h>

#include <ctype.h>

#include <stdio.h> // sprintf()


#include "gisel.h"

#include "config.h"

#include "gadgets.h"

#include "terminal.h"

#include "comm.h"



/** Global Settings **/
extern SettingsRec *Settings;

const char * const TTermWindow::name = "TTermWindow";



#define INTRO "ISEL C-Series Terminal...\n" 

#define NOCOM "Error: Terminal port is not available\n\n"


/**
 **  TTermWindow constructor
 **/
TTermWindow::TTermWindow(const TRect& bounds, const char *aTitle, 
                         short aNumber) :
    TWindow( bounds, aTitle, aNumber ),
    TWindowInit( initFrame )
{
    TRect r( getExtent() );
    r.grow(-1, -1);
    options |= ofTileable;
    TTermView *t = new TTermView( r,
                         standardScrollBar(sbHorizontal | sbHandleKeyboard),
                         standardScrollBar(sbVertical   | sbHandleKeyboard)
                       );
    if( t != 0 )
        insert(t);
    else
        messageBox("Cannot enter terminal mode.", mfOKButton);
      
}

/** Reads window from the stream
 **/
void *TTermWindow::read(ipstream& is)
{
    TWindow::read(is);
    TRect r( getExtent() );
    r.grow(-1, -1);
    //options |= ofTileable;

#if 0

    TTermView *t = new TTermView( r,
                         standardScrr(sbHorizontal | sbHandleKeyboard ),
                         standardScrollBar(sbVertical   | sbHandleKeyboard )
                       );
    if( t != 0 )
        insert(t);
    else
        messageBox("Cannot enter terminal mode.", mfOKButton);
#endif


    return this;
}

/** {duh} **/
void TTermWindow::write(opstream& os)
{
    TWindow::write(os);
}

/** {duh} **/
TStreamable *TTermWindow::build()
{
    return new TTermWindow( streamableInit );
}


TStreamableClass RTermWindow( TTermWindow::name,
                              TTermWindow::build,
                              __DELTA(TTermWindow)
                            );

/**
 ** Constructor for terminal view
 **/
TTermView::TTermView( const TRect& bounds,
                      TScrollBar *aHScrollBar,
                      TScrollBar *aVScrollBar
                    ) :
    TTerminal( bounds, aHScrollBar, aVScrollBar, 8192U )
{
    do_sputn( INTRO, strlen(INTRO) );
    char buffer[10];
    sprintf(buffer, "\n%s%ld", PROMPT, Settings->device);
    prompt = strdup(buffer);
    do_sputn( prompt, strlen(prompt) );
}

/**
 ** Terminal destructor
 **/
TTermView::~TTermView()
{
  delete prompt;
}

/**
 ** Hanbdles terminal events
 **/
void TTermView::handleEvent( TEvent& event )
{
    TTerminal::handleEvent( event );

    ushort keyCode = event.keyDown.keyCode ;

    if( event.what == evKeyboard &&
        event.keyDown.charScan.charCode != 0 &&
        isascii( event.keyDown.charScan.charCode )
      )
    {
        if (keyCode == kbEnter)  // Send whole line at ENTER

          {
            if (comm->getReply() < 0)
              messageBox("You must wait for the acknowledge signal from the "
                         "controller before transmitting any additional information.",
                         mfOKButton | mfWarning);
            ushort start =  prevLines(queFront, 1);
// BUG: No buffer wrap checking

            comm->sendCommand(&buffer[start], queFront - start);
            do_sputn(prompt, strlen(prompt));
          }
        else
          do_sputc( keyCode );
        drawView();
        clearEvent( event );
    }
}

/**
 ** Draws terminal window
 **/
void TTermView::draw()
{
    short  i;
    ushort begLine, endLine;
    char s[256];
    ushort bottomLine;

    bottomLine = size.y + delta.y;
    if( limit.y > bottomLine )
    {
        endLine = prevLines( queFront, limit.y - bottomLine );
        bufDec( endLine );
    }
    else
        endLine = queFront;

    if( limit.y > size.y )
        i = size.y - 1;
    else
    {
        for( i = limit.y; i <= size.y - 1; i++ )
            writeChar(0, i, ' ', 1, size.x);
        i =  limit.y -  1;
    }

    for( ; i >= 0; i-- )
    {
        begLine = prevLines(endLine, 1);
        if (endLine >= begLine)
        {
            int T = (int) (endLine - begLine);
            memcpy( s, &buffer[begLine], T );
            s[T] = EOS;
        }
        else
        {
            int T = (int) (bufSize - begLine);
            memcpy( s, &buffer[begLine], T );
            memcpy( s+T, buffer, endLine );
            s[T+endLine] = EOS;
        }
        if( delta.x >= strlen(s) )
            *s = EOS;
        else
            strcpy( s, &s[delta.x] );

        writeStr( 0, i, s, 1 );
        writeChar( strlen(s), i, ' ', 1, size.x );
        endLine = begLine;
        bufDec( endLine );
    }
}


/**
 ** Inserts charcter into thw terminal window
 **/
void TTermView::do_sputc( const char c )
{
    ushort screenLines = limit.y;
    int i;

    if( c == '\n' )
        screenLines++;

    if( !canInsert( 1 ) )
    {
        queBack = nextLine( queBack );
        screenLines--;
    }

    if( c != '\x08' )
    {
        buffer[queFront++] = c;
        if( queFront == bufSize )
            queFront = 0;
    }
    else if( queFront != queBack )
    {
        --queFront;
        if( (int) queFront < 0 )
            queFront += bufSize;
        if( buffer[queFront] == '\n' )
            --screenLines;
    }

    ++drawLock;
    setLimit( limit.x, screenLines );
    scrollTo( 0, screenLines + 1 );
    --drawLock;

    i = prevLines( queFront, 1 );
    if( i <= queFront )
        i = queFront - i;
    else
        i = bufSize - (i - queFront);
    setCursor( i, screenLines - delta.y - 1 );
    return;
}


/**
 ** Inserts /count/ character into the terminal window
 **/
int TTermView::do_sputn( const char *s, int count )
{
    ushort screenLines = limit.y;
    for( ushort i = 0; i < count; i++ )
        if( s[i] == '\n' )
            screenLines++;

    while( !canInsert( count ) )  // purge last line(s) to make room

        {
        queBack = nextLine( queBack );
        screenLines--;
        }

    if( queFront + count >= bufSize ) // wrap around cyclic buffer

        {
        i = bufSize - queFront;
        memcpy( &buffer[queFront], s, i );
        memcpy( buffer, &s[i], count - i );
        queFront = count - i;
        }
    else                              // normal insert

        {
        memcpy( &buffer[queFront], s, count );
        queFront += count;
        }

    ++drawLock;
    setLimit( limit.x, screenLines );
    scrollTo( 0, screenLines + 1 );
    --drawLock;

    i = prevLines( queFront, 1 );
    if( i <= queFront )
        i = queFront - i;
    else
        i = bufSize - (i - queFront);
    setCursor( i, screenLines - delta.y - 1 );
    return count;
}



syntax highlighted by Code2HTML, v. 0.9.1