[comp.sources.amiga] unix windows client

ain@j.cc.purdue.edu (Patrick White) (01/25/88)

Program Name:	uw  (unix window client)
Submitted By:	denbeste@cc5.bbn.com
Summary:	This is a unix window client.  Allows up to 7 windows into
		unix -- each with its own shell.
Poster Boy:  Pat White  (ain@j.cc.purdue.edu)
Tested.

NOTES:
   I will be posting the unix server source, but I'm not sure if we will be
archiving it.
   I've included terminal.diff even though I'm pretty sure the diffs have
already been installed in terminal.c.


-- Pat White   (co-moderator comp.sources/binaries.amiga)
UUCP: j.cc.purdue.edu!ain  BITNET: PATWHITE@PURCCVM   PHONE: (317) 743-8421
U.S.  Mail:  320 Brown St. apt. 406,    West Lafayette, IN 47906

========================================


#	This is a shell archive.
#	Remove everything above and including the cut line.
#	Then run the rest of the file through sh.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar:	Shell Archiver
#	Run the following text with /bin/sh to create:
#	README
#	amterm
#	terminal.c
#	terminal.diff
# This archive created: Mon Jan 25 09:25:07 1988
# By:	Patrick White (PUCC Land, USA)
echo shar: extracting README '(1376 characters)'
cat << \SHAR_EOF > README
Enclosed here are the following files:
   <amterm> contains a termcap entry for the UW program's default window size.
      If you resize the window it won't work!
   <terminal.diff> contains the differences to 'terminal.c' to fix a bug
   <terminal.c> is the new version of the file
   <uw.uue> is an executable with the fix

To use 'amterm', put it in a file in your home directory. After you log in,
type:
. amterm

THEN run the uw-server on UNIX and carry on from there. [HOWEVER, comma, that
worked just now with our current version of ULTRIX. When I was messing with
this last summer, I had to run it with each window after it had been opened,
when we were using a previous version of ULTRIX. Give it a try and check to
see if it got exported and inherited correctly before you believe anything.]

The original released version of UW has a bug in handling received linefeeds.
On the screen, they show up as newlines, but certain programs which use CURSES
try to use a linefeed to move the cursor straight down. As a result, the
unmodified UW couldn't be used with VI or anything else that was screen
oriented.

This change fixes that, but unfortunately I don't remember precisely how,
since I fixed it about 5 months ago. I seem to remember something about
sending a special character sequence to the terminal handler to make a
line-feed no longer treated as a newline.
SHAR_EOF
if test 1376 -ne "`wc -c README`"
then
echo shar: error transmitting README '(should have been 1376 characters)'
fi
echo shar: extracting amterm '(501 characters)'
cat << \SHAR_EOF > amterm
TERMCAP="sz|amiga|amiga-ansi:\
	:ae=\017:as=\016:bw:mi:ms:sf=\E[S:sr=\E[T:te=\E[S\E23;H:vb=\007:\
	:cr=^M:do=\ED:nl=^J:bl=^G:co#77:li#23:cl=\014:\
	:le=^H:bs:am:cm=\E[%i%d;%dH:nd=\E[C:up=\E[A:\
	:ce=\E[K:cd=\E[J:so=\E[3;7m:se=\E[m:us=\E[4m:ue=\E[m:\
	:md=\E[1m:mr=\E[7m:mb=\E[2m:me=\E[m:is=\E[23t\E[79u\E[23;H:\
	:ku=\EA:kd=\EB:kr=\EC:kl=\ED:kb=^H:kh=\E?~\
	:ho=\E[H:k1=\E0~:k2=\E1~:k3=\E2~:k4=\E3~:ta=^I:pt:sr=\EM:\
	:al=\E[L:dl=\E[M:dc=\E[P:ic=\E[@:im=:ei=:ed=:xn:"
TERM="amiga"
export TERM TERMCAP
SHAR_EOF
if test 501 -ne "`wc -c amterm`"
then
echo shar: error transmitting amterm '(should have been 501 characters)'
fi
echo shar: extracting terminal.c '(8109 characters)'
cat << \SHAR_EOF > terminal.c

/*  Unix Windows Client for the Amiga (ANSI Terminal Emulation only)

    ) 1987 by  Michael J. McInerny   12-May-87 version 1.00

*/

#define INTUITION_MESSAGE(x) (1<<uw[x].winsig)
#define TYPED_CHARACTER(x) (1<<uw[x].consig)
#define INPUT_CHARACTER (1<<serReadBit)

#define CloseConsole(x) CloseDevice(x)

#include "term.h"
#include "devices/serial.h"

/* GLOBALS ****************************************************** */
extern long IntuitionBase;
extern long GfxBase;

extern UWwrite();

struct uw_struct uw[8];
int uw_read, uw_write, uw_count = 0;

extern struct Window *NewTermWin();
extern struct Menu *MenuHead;

int waitmask;    /* what are we waiting for? */
struct MsgPort *serReadPort = NULL;
struct MsgPort *serWritePort = NULL;
struct IOExtSer *SerReadReq = NULL;
struct IOExtSer *SerWriteReq = NULL;

char letter[8];            /* one letter at a time from console */
char serin;             /* one letter at a time from serial  */
char serbuf[4096]; /* as much as we can get! */
int sercount;    /* how many to get */
int FullDuplex = TRUE;  /* flag for local echo  */

static   char reset_mode[] = {0x9B, 0x32, 0x30, 0x6C};

AllocTerm(slot)
int slot;
{
   char *s = "xxuw.con";

   uw_count += 1;
   uw[slot].free = FALSE;
   uw[slot].win = NewTermWin();
   SetMenuStrip(uw[slot].win, MenuHead);
   *s = (char)slot + 'a';
   *(s+1) = 'w';
   uw[slot].ConWritePort = CreatePort(s,0);
    if(uw[slot].ConWritePort == 0) Cleanup();
   uw[slot].ConWriteReq = CreateStdIO(uw[slot].ConWritePort);
    if(uw[slot].ConWriteReq == 0) Cleanup();
   *(s+1) = 'r';
   uw[slot].ConReadPort = CreatePort(s,0);
    if(uw[slot].ConReadPort == 0) Cleanup();
   uw[slot].ConReadReq =  CreateStdIO(uw[slot].ConReadPort);
    if(uw[slot].ConReadReq == 0) Cleanup();
   if((OpenConsole(uw[slot].ConWriteReq,
   uw[slot].ConReadReq,
   uw[slot].win)) != 0)
      Cleanup();
   uw[slot].consig = uw[slot].ConReadReq->io_Message.mn_ReplyPort->mp_SigBit;
   uw[slot].winsig = uw[slot].win->UserPort->mp_SigBit;
   waitmask |= INTUITION_MESSAGE(slot) | TYPED_CHARACTER(slot) ;
   QueueRead(uw[slot].ConReadReq, &letter[slot]);

   uw[slot].ConWriteReq->io_Command = CMD_WRITE;
   uw[slot].ConWriteReq->io_Length = sizeof(reset_mode);
   uw[slot].ConWriteReq->io_Data = (APTR)(reset_mode);

   if(DoIO(uw[slot].ConWriteReq) != 0) {
      Notify(uw[uw_write].win, "Console write error.");
   }
} /* end of AllocTerm */

ZeroTerm(slot)
int slot;
{
 uw[slot].free = TRUE;
 uw[slot].ConReadPort = NULL;
 uw[slot].ConWritePort = NULL;
 uw[slot].ConReadReq = NULL;
 uw[slot].ConWriteReq = NULL;
 uw[slot].win = NULL;
 uw[slot].winsig = 0;
 uw[slot].consig = 0;
} /* end of ZeroTerm */

DeallocTerm(slot)
int slot;
{
   waitmask &= ~(INTUITION_MESSAGE(slot) | TYPED_CHARACTER(slot)) ;
   if (uw[slot].free == FALSE) {
 AbortIO(uw[slot].ConReadReq);  /* cancel the last queued read */
 uw_count -= 1;
 if (uw[slot].ConWriteReq) CloseConsole(uw[slot].ConWriteReq);
 if (uw[slot].ConReadReq) DeleteStdIO(uw[slot].ConReadReq);
 if (uw[slot].ConReadPort) DeletePort(uw[slot].ConReadPort);
 if (uw[slot].ConWriteReq) DeleteStdIO(uw[slot].ConWriteReq);
 if (uw[slot].ConWritePort) DeletePort(uw[slot].ConWritePort);
 if (uw[slot].win) {
    ClearMenuStrip(uw[slot].win);
    CloseWindow(uw[slot].win);
 }
 ZeroTerm(slot);
   } /* end if uw.free */
} /* end of DeallocTerm */

InitSerReqs()
{
   serReadPort = CreatePort("uw.ser.read",0);
   if (serReadPort == NULL) Cleanup();
   SerReadReq = (struct IOExtSer *)CreateExtIO(serReadPort,
                                               sizeof(struct IOExtSer));
   if (SerReadReq == NULL) Cleanup();
   serWritePort = CreatePort("uw.ser.write",0);
   if (serWritePort == NULL) Cleanup();
   SerWriteReq = (struct IOExtSer *)CreateExtIO(serWritePort,
                                               sizeof(struct IOExtSer));
   if (SerWriteReq == NULL) Cleanup();
   if ((OpenSerial(SerReadReq, SerWriteReq)) != 0) Cleanup();
   if ((SetParams( SerReadReq, 4096, 0x07, 0x07, 750000,
                           9600, 0x00, 
      0x51040303, 0x03030303)) != 0)
      Cleanup();
}

main()
{
   USHORT class, code, qualifier;
   int problem, i, serReadBit;
   struct IntuiMessage *message; /* the message the IDCMP sends us */

   IntuitionBase = 0L;
   GfxBase = 0L;
   MenuHead = NULL;

   for(i = 0; i < 8; ++i) ZeroTerm(i);

   InitLibs();
   InitSerReqs();
   serReadBit = SerReadReq->IOSer.io_Message.mn_ReplyPort->mp_SigBit;
   waitmask = INPUT_CHARACTER;

   if (!InitMenus()) Cleanup();

   AllocTerm(1);
   uw_read = 1;
   uw_write = 1;

   sercount = 1;
   ReadSer(serbuf, sercount);

/*   UWExit(); */

   problem = TRUE;
   do {
 Wait(waitmask);
 if(CheckIO(SerReadReq))
 {
  WaitIO(SerReadReq);
  UWwrite(serbuf, sercount);
  sercount = QuerySer(SerReadReq);
  if (sercount < 1) sercount = 1;
  ReadSer(serbuf, sercount);
 } /* end if(CheckIO(SerRead)) */
      for (i = 0; i < 8; ++i) {
 if (!uw[i].free) {
  while((!uw[i].free) &&
   ((message = (struct IntuiMessage *)
    GetMsg(uw[i].win->UserPort) ) != NULL)) {
    class     = message->Class;
    code      = message->Code;
    qualifier = message->Qualifier;
    ReplyMsg(message);
    problem &= HandleEvent(i,class,code,qualifier);
/*    if(problem == FALSE) break; */
   } /* end while(mess... */

  if((!uw[i].free) && CheckIO(uw[i].ConReadReq))
  {
   WaitIO(uw[i].ConReadReq);
   if (uw_read != i) SelInput(i);
 /* is this is current input window?  if not, send note off ... */
   UWWriteChar(letter[i]);
/*   SerPutChar(SerWriteReq, letter[i]); */
   if (!FullDuplex)
    ConPutChar(uw[uw_write].ConWriteReq, letter[i]);
   QueueRead(uw[i].ConReadReq, &letter[i]);
  } /* end if(CheckIO(ConRead)) */
 } /* end if(!uw[i].free) */
      } /* end for i */
   } while (problem); /* keep going as long as HandleEvent returns nonzero */

   AbortIO(SerReadReq);
   Cleanup();
}

Cleanup()
{
   int i;

   for (i = 0; i < 8; ++i)
 if (!uw[i].free) DeallocTerm(i);
   if (SerReadReq) CloseDevice(SerReadReq);
   if (SerWriteReq) DeleteExtIO(SerWriteReq,sizeof(struct IOExtSer));
   if (serWritePort) DeletePort(serWritePort);
   if (SerReadReq) DeleteExtIO(SerReadReq,sizeof(struct IOExtSer));
   if (serReadPort) DeletePort(serReadPort);
   if (MenuHead) DisposeMenus(MenuHead);
   if (IntuitionBase) CloseLibrary(IntuitionBase);
   if (GfxBase) CloseLibrary(GfxBase);
   exit(0);
} /* end of Cleanup */

HandleEvent(term,class,code,qualifier)
int term;
USHORT class;
USHORT code;
USHORT qualifier;
{
      switch( class ) {
  case CLOSEWINDOW:
     return(CloseWin(term));
     break;
         case MENUPICK:
            return(MenuSwitch(code));
            break;
      } /* end of switch( class ) */
      return(TRUE);
} /* end of HandleEvent */

/*      R e a d S e r
 *
 *      Read characters from the serial.device
 *
 */

ReadSer(data,length)
char *data;
int length;
{
  SerReadReq->IOSer.io_Command = CMD_READ;
  SerReadReq->IOSer.io_Length = length;
  SerReadReq->IOSer.io_Data = (APTR)(data);

   BeginIO(SerReadReq);
}

/*      W r i t e S e r
 *
 *      Write characters to the serial.device
 *
 */

WriteSer(data,length)
char *data;
int length;
{
/*  int i; */

  SerWriteReq->IOSer.io_Command = CMD_WRITE;
  SerWriteReq->IOSer.io_Length = length;
/*  SerWriteReq->IOSer.io_Length = 1; 
  for(i = 0; i < length; ++i) {
 SerWriteReq->IOSer.io_Data = (APTR)(data + i);
 DoIO(SerWriteReq);
  }
*/
  SerWriteReq->IOSer.io_Data = (APTR)(data);

  if(DoIO(SerWriteReq) != 0)
  {
      Notify(uw[uw_write].win, "Serial write error.");
  }
}

extern int uwflag;
sputc(c)
char c;
{
/* printf(">0%o ",c); */
 if (uwflag) Delay(1); /* Why is this necessary????? */
 SerPutChar(SerWriteReq, c);
}

/*      W r i t e C o n
 *
 *      Write characters to the console.device
 *
 */

WriteCon(data,length)
char *data;
int length;
{
  uw[uw_write].ConWriteReq->io_Command = CMD_WRITE;
  uw[uw_write].ConWriteReq->io_Length = length;
  uw[uw_write].ConWriteReq->io_Data = (APTR)(data);

if(!uw[uw_write].free)
  if(DoIO(uw[uw_write].ConWriteReq) != 0)
  {
      Notify(uw[uw_write].win, "Console write error.");
  }
}

SHAR_EOF
if test 8109 -ne "`wc -c terminal.c`"
then
echo shar: error transmitting terminal.c '(should have been 8109 characters)'
fi
echo shar: extracting terminal.diff '(359 characters)'
cat << \SHAR_EOF > terminal.diff
40a41,42
> static   char reset_mode[] = {0x9B, 0x32, 0x30, 0x6C};
> 
68a71,78
> 
>    uw[slot].ConWriteReq->io_Command = CMD_WRITE;
>    uw[slot].ConWriteReq->io_Length = sizeof(reset_mode);
>    uw[slot].ConWriteReq->io_Data = (APTR)(reset_mode);
> 
>    if(DoIO(uw[slot].ConWriteReq) != 0) {
>       Notify(uw[uw_write].win, "Console write error.");
>    }
SHAR_EOF
if test 359 -ne "`wc -c terminal.diff`"
then
echo shar: error transmitting terminal.diff '(should have been 359 characters)'
fi
#	End of shell archive
exit 0