/* * FTERM.C * * DNET (c)Copyright 1988, Matthew Dillon, All Rights Reserved. * * FTERM [-Nnet] [port] [-wcapturefile] [-c#] * * -c# = cooked mode. i.e. -c7 bit 0 convert CR's to LF's keyboard->remote * bit 1 echo chars locally (half duplex) * bit 2 received LF->CRLF */ #include "defs.h" #include short Deemu[] = { DMSTRT, 0, 0, DMNW , 0,10, 11, 11, -37, -28, 0xFFFF, DMTEXT, 0,30, 'FO','NT','\0t','op','az','.f','on','t.','8\0',0,0,0,0,0,0, DMEND , 0, 0 }; #define DMNWOFF 4 #define DMFONTSTR 17 TA Ta = { (ubyte *)"topaz.font", 8 }; ITEXT IText[] = { { 0, 1, JAM2, 0, 0, &Ta, (ubyte *)"Flush" }, { 0, 1, JAM2, 0, 0, &Ta, (ubyte *)"AppendCap" }, { 0, 1, JAM2, 0, 0, &Ta, (ubyte *)"NewCap" }, { 0, 1, JAM2, 0, 0, &Ta, (ubyte *)"CloseCap" }, { 0, 1, JAM2, 0, 0, &Ta, (ubyte *)"Paste" } }; ITEM Item[] = { { &Item[1], 0, 0, 100, 10, ITEMTEXT|COMMSEQ|ITEMENABLED|HIGHCOMP, 0, (APTR)&IText[0], NULL, 'o' }, { &Item[2], 0,10, 100, 10, ITEMTEXT|COMMSEQ|ITEMENABLED|HIGHCOMP, 0, (APTR)&IText[1], NULL, 'a' }, { &Item[3], 0,20, 100, 10, ITEMTEXT|COMMSEQ|ITEMENABLED|HIGHCOMP, 0, (APTR)&IText[2], NULL, 'n' }, { &Item[4], 0,30, 100, 10, ITEMTEXT|COMMSEQ|ITEMENABLED|HIGHCOMP, 0, (APTR)&IText[3], NULL, 'c' }, { NULL , 0,40, 100, 10, ITEMTEXT|COMMSEQ|ITEMENABLED|HIGHCOMP, 0, (APTR)&IText[4], NULL, 'p' } }; MENU Menu[] = { { NULL , 0, 0, 100, 10+40, MENUENABLED, "Control", &Item[0] } }; ubyte Title[80]; NW Nw = { 0, 0, 640, 200, -1, -1, NEWSIZE|CLOSEWINDOW|MENUPICK, WINDOWSIZING|WINDOWDRAG|WINDOWDEPTH|WINDOWCLOSE|NOCAREREFRESH|ACTIVATE, NULL, NULL, Title, NULL, NULL, 32, 32, -1, -1, WBENCHSCREEN }; WIN *Win; extern int Enable_Abort; char Buf[512]; char Term[64]; char Cc; char Cooked; /* bit 0 = cooked, bit 1 = local echo */ char IgnoreNS; struct IntuitionBase *IntuitionBase; struct GfxBase *GfxBase; void OpenConsole ARGS((WIN *, IOCON **, IOCON **)); void HandleIoctl ARGS((short, short, char, WIN *, IOCON *)); void CloseConsole ARGS((IOCON *, IOCON *)); void setsize ARGS((IOCON *, void *, WIN *)); void main ARGS((int, char **)); int brk() { return(0); } void main(ac, av) char *av[]; { void *chan; long imask, conmask, dmask, mask; IOCON *iocr, *iocw; char notdone = 1; char portspec = 0; char *host = NULL; char *capfile = NULL; FILE *capfi = NULL; uword port = PORT_IALPHATERM; FONT *font = NULL; onbreak(brk); sprintf(Title, "FTerm V%s%s", VERSION, FTERM_VERSION); strcpy(Term, Title); strcat(Title, " opening, wait ..."); { char *str = av[0]; for (str = str + strlen(str); str >= av[0]; --str) { if (*str == '/' || *str == ':') break; } ++str; if ((*str | 0x20) == 'b') /* bbsterm instead of fterm */ port = PORT_BBS; } { short i; for (i = 1; i < ac; ++i) { char *ptr = av[i]; if (*ptr == '-') { while (*++ptr) { switch(*ptr) { case 'N': host = ptr + 1; ptr = "\0"; break; case 'w': capfile = ptr + 1; ptr = "\0"; break; case 'c': Cooked = atoi(ptr + 1); ptr = "\0"; break; default: printf("Unknown option: '%c'\n", *ptr); break; } } } else { portspec = 1; port = atoi(ptr); } } } if (capfile) capfi = fopen(capfile, "a"); if (portspec) printf("Using port %ld\n", port); #ifndef LATTICE Enable_Abort = 0; #endif IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 0); GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 0); InitDeemuNW(Deemu+DMNWOFF, &Nw); { char *p1, *p2; p1 = (char *)(Deemu+DMFONTSTR) + strlen((char *)(Deemu+DMFONTSTR)) + 1; for (p2 = p1 + strlen(p1); p2 != p1 && *p2 != '.'; --p2); if (*p2 == '.') { *p2 = 0; font = (FONT *)GetFont(p1, (short)atoi(p2+1)); } } Win = OpenWindow(&Nw); if (Win == NULL) goto e1; if (font) { SetFont(Win->RPort, font); SetRast(Win->RPort, 0); RefreshWindowFrame(Win); } OpenConsole(Win, &iocr, &iocw); if (iocr == NULL || iocw == NULL) goto e3; /* * We delay here to allow DNET to go through its RESTART sequence * (when DNET automatically runs FTERM, it does so to quickly). * Such a hack! */ Delay(50 * 4); chan = DOpen(host, port, 20, 15); if (!chan) { puts("Unable to connect"); goto e3; } DQueue(chan, 32); SetMenuStrip(Win, Menu); SetWindowTitles(Win, Term, (char *)-1); imask = 1 << Win->UserPort->mp_SigBit; dmask = 1 << ((PORT *)chan)->mp_SigBit; conmask = 1 << iocr->io_Message.mn_ReplyPort->mp_SigBit; iocr->io_Data = (APTR)&Cc; iocr->io_Length = 1; SendIO(iocr); setsize(iocw, chan, Win); while (notdone) { mask = Wait(imask|dmask|conmask); if (mask & imask) { IMESS *im; while (im = (IMESS *)GetMsg(Win->UserPort)) { switch(im->Class) { case NEWSIZE: if (IgnoreNS) { --IgnoreNS; setsize(iocw, NULL, Win); } else { setsize(iocw, chan, Win); } break; case CLOSEWINDOW: notdone = 0; break; case MENUPICK: switch((uword)((MENUNUM(im->Code)<<8)|ITEMNUM(im->Code))) { case 0x0000: /* menu 0 item 0 */ DIoctl(chan, CIO_FLUSH, 0, 0); break; case 0x0001: /* menu 0 item 1 */ if (capfi) fclose(capfi); capfi = fopen("ram:capture", "a"); break; case 0x0002: if (capfi) fclose(capfi); capfi = fopen("ram:capture", "w"); break; case 0x0003: /* menu 0 item 2 */ if (capfi) fclose(capfi); capfi = NULL; break; case 0x0004: /* menu 0 item 3 */ { FILE *fi; long n; if (fi = fopen("ram:paste", "r")) { while ((n = fread(Buf, 1, sizeof(Buf), fi)) > 0) { DWrite(chan, Buf, n); } fclose(fi); } } break; case 0x0100: /* menu 1 item 0 */ break; } } ReplyMsg((MSG *)im); } } if (mask & dmask) { int n; if ((n = DNRead(chan, Buf, sizeof(Buf))) > 0) { iocw->io_Data = (APTR)Buf; iocw->io_Length = n; DoIO(iocw); if (capfi) fwrite(Buf, n, 1, capfi); } else if (n == -2) { short val; short cmd; char aux; cmd = DGetIoctl(chan, &val, &aux); HandleIoctl(cmd, val, aux, Win, iocw); if (cmd == CIO_MODE) { if (val) SetWindowTitles(Win, "(Cooked)", (char *)-1); else SetWindowTitles(Win, "(Raw)", (char *)-1); } } else if (n < 0) { notdone = 0; } } if (mask & conmask) { if (CheckIO(iocr)) { WaitIO(iocr); if (Cooked & 2) { /* Local Echo */ iocw->io_Data = (APTR)&Cc; iocw->io_Length = 1; DoIO(iocw); } if ((Cooked & 1) && Cc == 13) { Cc = 10; iocw->io_Data = (APTR)&Cc; iocw->io_Length = 1; DoIO(iocw); } DWrite(chan, &Cc, 1); iocr->io_Data = (APTR)&Cc; iocr->io_Length = 1; SendIO(iocr); } } } AbortIO(iocr); WaitIO(iocr); SetWindowTitles(Win, "Closing...", (char *)-1); DClose(chan); e3: CloseConsole(iocr,iocw); if (font) { SetFont(Win->RPort, Win->WScreen->RastPort.Font); CloseFont(font); } CloseWindow(Win); e1: CloseLibrary((LIB *)IntuitionBase); CloseLibrary((LIB *)GfxBase); if (capfi) fclose(capfi); } void OpenConsole(win, piocr, piocw) IOCON **piocr, **piocw; WIN *win; { PORT *port; static IOCON iocr, iocw; int error; port = CreatePort(NULL, 0); iocr.io_Command = CMD_READ; iocr.io_Data = (APTR)win; iocr.io_Message.mn_Node.ln_Type = NT_MESSAGE; iocr.io_Message.mn_ReplyPort = port; error = OpenDevice("console.device", 0, &iocr, 0); if (!error) { iocw = iocr; iocw.io_Command = CMD_WRITE; *piocr = &iocr; *piocw = &iocw; } else { *piocr = *piocw = NULL; } } void CloseConsole(iocr, iocw) IOCON *iocr; IOCON *iocw; { IOCON *tmp = (iocr) ? iocr : iocw; if (tmp) { CloseDevice(tmp); DeletePort(tmp->io_Message.mn_ReplyPort); } } void setsize(iocw, chan, win) IOCON *iocw; void *chan; WIN *win; { struct ConUnit *cu = (struct ConUnit *)iocw->io_Unit; static char IStr[] = { "\033c\23320l\233t\233u" }; if (Cooked & 4) IStr[5] = 'h'; else IStr[5] = 'l'; iocw->io_Data = (APTR)IStr; iocw->io_Length = sizeof(IStr) - 1; DoIO(iocw); if (chan) { DIoctl(chan, CIO_SETROWS, (uword)(cu->cu_YMax+1), 0); DIoctl(chan, CIO_SETCOLS, (uword)(cu->cu_XMax+1), 0); } sprintf(Term, "FTERM %ld x %ld", cu->cu_YMax+1, cu->cu_XMax+1); SetWindowTitles(win, Term, (char *)-1); } void HandleIoctl(cmd, val, aux, win, iocw) short cmd, val; char aux; WIN *win; IOCON *iocw; { static short saverows; short height, width; short dx, dy; switch(cmd) { case CIO_MODE: Cooked = val; break; case CIO_SETROWS: saverows = val; break; case CIO_SETCOLS: width = val * win->RPort->TxWidth + win->BorderLeft + win->BorderRight; height= saverows * win->RPort->TxHeight + win->BorderTop + win->BorderBottom; dx = win->WScreen->Width - (win->LeftEdge + width); if (dx > 0) dx = 0; if (-dx > win->LeftEdge) { dx = -win->LeftEdge; width = win->WScreen->Width; } dy = win->WScreen->Height - (win->TopEdge + height); if (dy > 0) dy = 0; if (-dy > win->TopEdge) { dy = -win->TopEdge; height = win->WScreen->Height; } if (dx || dy) { MoveWindow(win, dx, dy); } if (win->Width != width || win->Height != height) { SizeWindow(win, width - win->Width, height - win->Height); ++IgnoreNS; } break; } }