/* $Revision Header * Header built automatically - do not edit! ************* * * (C) Copyright 1990 by Olaf 'Olsen' Barthel & MXM * * Name .....: termLite.c * Created ..: Saturday 8-Jun-91 12:32 * Revision .: 0 * * Date Author Comment * ========= ======== ==================== * 08-Jun-91 Olsen Created this file! * * $Revision Header ********************************************************/ /* System includes. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* A handy macro to access AbsExecBase. */ #define SysBase (*(struct ExecBase **)4L) /* The following pragmas provide the nessary support * for reentrancy: they permit to keep the library bases * defined locally. */ /* exec.library calls. */ #pragma libcall SysBase WaitPort 180 801 #pragma libcall SysBase GetMsg 174 801 #pragma libcall SysBase ReplyMsg 17a 901 #pragma libcall SysBase CloseLibrary 19e 901 #pragma libcall SysBase OpenLibrary 228 902 #pragma libcall SysBase AllocVec 2ac 1002 #pragma libcall SysBase FreeVec 2b2 901 #pragma libcall SysBase Forbid 84 0 #pragma libcall SysBase SendIO 1ce 901 #pragma libcall SysBase WaitIO 1da 901 #pragma libcall SysBase AbortIO 1e0 901 #pragma libcall SysBase Wait 13e 1 #pragma libcall SysBase DoIO 1c8 901 #pragma libcall SysBase OpenDevice 1bc 190804 #pragma libcall SysBase CloseDevice 1c2 901 #pragma libcall SysBase CreateIORequest 28e 802 #pragma libcall SysBase DeleteIORequest 294 801 #pragma libcall SysBase CreateMsgPort 29a 0 #pragma libcall SysBase DeleteMsgPort 2a0 801 #pragma libcall SysBase CopyMem 270 9803 /* dos.library calls. */ #pragma libcall DOSBase ReadArgs 31E 32103 #pragma libcall DOSBase FreeArgs 35A 101 #pragma libcall DOSBase StrToLong 330 2102 #pragma libcall DOSBase VPrintf 3BA 2102 /* icon.library calls. */ #pragma libcall IconBase GetDiskObject 4E 801 #pragma libcall IconBase FreeDiskObject 5A 801 #pragma libcall IconBase FindToolType 60 9802 /* intuition.library calls. */ #pragma libcall IntuitionBase LockPubScreen 1FE 801 #pragma libcall IntuitionBase UnlockPubScreen 204 9802 #pragma libcall IntuitionBase OpenWindowTagList 25E 9802 #pragma libcall IntuitionBase CloseWindow 48 801 #pragma libcall IntuitionBase EasyRequestArgs 24C BA9804 /* Signal bits to wait for. */ #define SIG_SERIAL (1 << SerReadPort -> mp_SigBit) #define SIG_CONSOLE (1 << ConReadPort -> mp_SigBit) #define SIG_WINDOW (1 << Window -> UserPort -> mp_SigBit) /* Size of the console read buffer and the serial read buffer. */ #define CON_READ_SIZE 256 #define SER_READ_SIZE 1024 /* Argument vector offsets. */ enum { ARG_DEVICE,ARG_UNIT }; /* termLite(): * * termLite main program, handles all those neat * IO functions in just a single routine. */ LONG __saveds termLite(VOID) { /* Window definitions, just a lookup table, will get * copied to local stack vars and modified lateron. * (to save the relocs). */ STATIC ULONG DefaultTags[20 * 2 + 1] = { WA_Top, NULL, WA_Width, NULL, WA_Height, NULL, WA_MinHeight, NULL, WA_Title, NULL, WA_MinWidth, NULL, WA_MaxWidth, ~0, WA_MaxHeight, ~0, WA_Left, 0, WA_SimpleRefresh, TRUE, WA_SizeGadget, TRUE, WA_DragBar, TRUE, WA_DepthGadget, TRUE, WA_CloseGadget, TRUE, WA_Activate, TRUE, WA_RMBTrap, TRUE, WA_SizeBBottom, TRUE, WA_AutoAdjust, TRUE, WA_RMBTrap, TRUE, WA_IDCMP, IDCMP_CLOSEWINDOW, TAG_DONE }; /* Library bases. */ struct DosLibrary *DOSBase; struct IntuitionBase *IntuitionBase; /* Workbench data. */ struct Process *ThisProcess; struct WBStartup *WBenchMsg; /* Our window. */ struct Window *Window; /* Serial IO data. */ struct IOExtSer *SerReadRequest; struct IOExtSer *SerWriteRequest; struct MsgPort *SerReadPort; struct MsgPort *SerWritePort; APTR SerReadBuffer; /* Console IO data. */ struct IOStdReq *ConReadRequest; struct IOStdReq *ConWriteRequest; struct MsgPort *ConReadPort; struct MsgPort *ConWritePort; APTR ConReadBuffer; /* Global result code. */ LONG Result = RETURN_FAIL; /* Set up the process pointer. */ ThisProcess = (struct Process *)SysBase -> ThisTask; /* Wait for Workbench startup packet. */ if(!ThisProcess -> pr_CLI) { WaitPort(&ThisProcess -> pr_MsgPort); WBenchMsg = (struct WBStartup *)GetMsg(&ThisProcess -> pr_MsgPort); } else WBenchMsg = NULL; /* Are we running under control of Kickstart 2.0? */ if(SysBase -> LibNode . lib_Version >= 37) { /* Open dos.library. */ if(DOSBase = (struct DosLibrary *)OpenLibrary("dos.library",37)) { /* Open intuition.library. */ if(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",37)) { UBYTE DeviceName[40]; LONG UnitNumber; /* Fill in the default serial device * name. */ strcpy(DeviceName,SERIALNAME); /* And set the default unit number * to zero. */ UnitNumber = 0; /* Take a look at the tool icon * if run from Workbench. */ if(WBenchMsg) { struct Library *IconBase; /* Open icon.library. */ if(IconBase = OpenLibrary("icon.library",0)) { struct DiskObject *DiskObject; /* Read the tool icon. */ if(DiskObject = GetDiskObject(WBenchMsg -> sm_ArgList -> wa_Name)) { UBYTE *Entry; /* Check for custom device name. */ if(Entry = FindToolType(DiskObject -> do_ToolTypes,"DEVICE")) strcpy(DeviceName,Entry); /* Check for custom device number. */ if(Entry = FindToolType(DiskObject -> do_ToolTypes,"UNIT")) StrToLong(Entry,&UnitNumber); /* Release the icon. */ FreeDiskObject(DiskObject); } /* Close the library. */ CloseLibrary(IconBase); } } else { UBYTE **ArgArray; /* Allocate argument array. */ if(ArgArray = (UBYTE **)AllocVec(sizeof(UBYTE *) * 2,MEMF_PUBLIC|MEMF_CLEAR)) { struct RDArgs *ArgsPtr; /* Read the startup args if any. */ if(ArgsPtr = (struct RDArgs *)ReadArgs("D=Device/K,U=Unit/N/K",(LONG *)ArgArray,NULL)) { /* Set custom device name. */ if(ArgArray[ARG_DEVICE]) strcpy(DeviceName,ArgArray[ARG_DEVICE]); /* Set custom unit number. */ if(ArgArray[ARG_UNIT]) UnitNumber = *(LONG *)ArgArray[ARG_UNIT]; /* Free the args. */ FreeArgs(ArgsPtr); } /* Free the argument array. */ FreeVec(ArgArray); } } /* Allocate the serial read buffer. */ if(SerReadBuffer = AllocVec(SER_READ_SIZE,MEMF_PUBLIC)) { /* Create the serial read port. */ if(SerReadPort = CreateMsgPort()) { /* Create the serial write port. */ if(SerWritePort = CreateMsgPort()) { /* Create the serial read request. */ if(SerReadRequest = (struct IOExtSer *)CreateIORequest(SerReadPort,sizeof(struct IOExtSer))) { /* Create the serial write request. */ if(SerWriteRequest = (struct IOExtSer *)AllocVec(sizeof(struct IOExtSer),MEMF_PUBLIC)) { /* Open the device in shared mode. */ SerReadRequest -> io_SerFlags |= SERF_SHARED; if(!OpenDevice(DeviceName,UnitNumber,&SerReadRequest -> IOSer,0)) { /* Clone the IORequest and fill in the * approriate reply port for the write * request. */ CopyMem(SerReadRequest,SerWriteRequest,sizeof(struct IOExtSer)); SerWriteRequest -> IOSer . io_Message . mn_ReplyPort = SerWritePort; /* Allocate the console read buffer. */ if(ConReadBuffer = AllocVec(CON_READ_SIZE,MEMF_PUBLIC)) { struct Screen *DefaultScreen; /* Lock the default public screen. */ if(DefaultScreen = LockPubScreen(NULL)) { ULONG StackTags[20 * 2 + 1]; /* Copy window sestup tags to local * stack array and initialize it * according to the size and * characteristics of the default * screen. */ CopyMem(DefaultTags,StackTags,sizeof(DefaultTags)); StackTags[ 1] = DefaultScreen -> BarHeight + 1; StackTags[ 3] = DefaultScreen -> Width; StackTags[ 5] = (DefaultScreen -> Font -> ta_YSize) * 17 + DefaultScreen -> WBorTop + DefaultScreen -> WBorBottom + 1; StackTags[ 7] = DefaultScreen -> Font -> ta_YSize + DefaultScreen -> WBorTop + DefaultScreen -> WBorBottom - 1; StackTags[ 9] = (ULONG)("termLite © Copyright 1991 by MXM"); StackTags[11] = DefaultScreen -> Width >> 1; /* Open the window. */ if(Window = OpenWindowTagList(NULL,(struct TagItem *)&StackTags[0])) { /* Create the console read port. */ if(ConReadPort = CreateMsgPort()) { /* Create the console write port. */ if(ConWritePort = CreateMsgPort()) { /* Create the console read * request. */ if(ConReadRequest = (struct IOStdReq *)CreateIORequest(ConReadPort,sizeof(struct IOStdReq))) { /* Create the console write request. */ if(ConWriteRequest = (struct IOStdReq *)AllocVec(sizeof(struct IOStdReq),MEMF_PUBLIC)) { /* Set up the console startup information and * open the approriate device. */ ConReadRequest -> io_Data = Window; ConReadRequest -> io_Length = sizeof(struct Window *); /* We want the character mapped simple refresh window * including cut & paste. */ if(!OpenDevice("console.device",CONU_SNIPMAP,ConReadRequest,0)) { BYTE Terminated = FALSE; ULONG SignalSet; /* Clone the IORequest and * fill in the console write * port. */ CopyMem(ConReadRequest,ConWriteRequest,sizeof(struct IOStdReq)); ConWriteRequest -> io_Message . mn_ReplyPort = ConWritePort; /* Unlock the default public * screen, there probably * is no need to keep * it open (our window * will keep it from * closing). */ UnlockPubScreen(NULL,DefaultScreen); DefaultScreen = NULL; /* Request characters from the console window. */ ConReadRequest -> io_Command = CMD_READ; ConReadRequest -> io_Length = CON_READ_SIZE - 1; ConReadRequest -> io_Data = ConReadBuffer; SendIO(ConReadRequest); /* Request a single byte from the * serial line. */ SerReadRequest -> IOSer . io_Command = CMD_READ; SerReadRequest -> IOSer . io_Length = 1; SerReadRequest -> IOSer . io_Data = SerReadBuffer; SendIO(&SerReadRequest -> IOSer); Result = RETURN_OK; /* Go into loop until the * user hits the close * gadget. */ while(!Terminated) { /* Wait for signals. */ SignalSet = Wait(SIG_SERIAL | SIG_CONSOLE | SIG_WINDOW); /* Did we get a message from the window? */ if(SignalSet & SIG_WINDOW) { struct IntuiMessage *Massage; /* Pick up the messages and reply them. The * only message type we expect is the * IDCMP_CLOSEWINDOW type. */ while(Massage = (struct IntuiMessage *)GetMsg(Window -> UserPort)) { ReplyMsg(&Massage -> ExecMessage); Terminated = TRUE; } } /* Did we get a message from the * console? */ if(SignalSet & SIG_CONSOLE) { /* Remove the IORequest from * the message list. */ WaitIO(ConReadRequest); /* Send the resulting characters to the * serial device. */ SerWriteRequest -> IOSer . io_Command = CMD_WRITE; SerWriteRequest -> IOSer . io_Data = ConReadBuffer; SerWriteRequest -> IOSer . io_Length = ConReadRequest -> io_Actual; DoIO(&SerWriteRequest -> IOSer); /* Post another request to the * console. */ ConReadRequest -> io_Command = CMD_READ; ConReadRequest -> io_Length = CON_READ_SIZE - 1; ConReadRequest -> io_Data = ConReadBuffer; SendIO(ConReadRequest); } /* Did we get a signal from * the serial line? */ if(SignalSet & SIG_SERIAL) { LONG Size; /* Remove IORequest from the * message list. */ WaitIO(&SerReadRequest -> IOSer); /* Echo the single character to * the console. */ ConWriteRequest -> io_Command = CMD_WRITE; ConWriteRequest -> io_Data = SerReadBuffer; ConWriteRequest -> io_Length = 1; DoIO(ConWriteRequest); /* Inquire how many characters * are still pending at the * serial port. */ SerReadRequest -> IOSer . io_Command = SDCMD_QUERY; DoIO(&SerReadRequest -> IOSer); /* If there are any, transfer them to * the serial line. */ if(Size = SerReadRequest -> IOSer . io_Actual) { LONG Frag; /* We need to transfer the block in small * fragments since the serial read buffer * may be smaller than the amount of data * to be read. */ while(Size) { /* Determine number of bytes to read. */ Frag = Size > SER_READ_SIZE ? SER_READ_SIZE : Size; /* Read the bytes. */ SerReadRequest -> IOSer . io_Command = CMD_READ; SerReadRequest -> IOSer . io_Data = SerReadBuffer; SerReadRequest -> IOSer . io_Length = Frag; DoIO(&SerReadRequest -> IOSer); /* Transfer them to the window. */ ConWriteRequest -> io_Command = CMD_WRITE; ConWriteRequest -> io_Data = SerReadBuffer; ConWriteRequest -> io_Length = Frag; DoIO(ConWriteRequest); Size -= Frag; } } /* Post a request for another byte. */ SerReadRequest -> IOSer . io_Command = CMD_READ; SerReadRequest -> IOSer . io_Data = SerReadBuffer; SerReadRequest -> IOSer . io_Length = 1; SendIO(&SerReadRequest -> IOSer); } } /* The program has been flagged to * to close down. Abort the pending * IORequestes and close the * console device. */ AbortIO(ConReadRequest); WaitIO(ConReadRequest); AbortIO(&SerReadRequest -> IOSer); WaitIO(&SerReadRequest -> IOSer); CloseDevice(ConReadRequest); } /* Free the console write request. */ FreeVec(ConWriteRequest); } /* Free the console read request. */ DeleteIORequest(ConReadRequest); } /* Delete the console write port. */ DeleteMsgPort(ConWritePort); } /* Delete the console read port. */ DeleteMsgPort(ConReadPort); } /* Close the window. */ CloseWindow(Window); } /* Unlock the default public screen * if necessary. */ if(DefaultScreen) UnlockPubScreen(NULL,DefaultScreen); } /* Free the console read buffer. */ FreeVec(ConReadBuffer); } /* Close the serial device. */ CloseDevice(&SerReadRequest -> IOSer); } /* Free the serial write request. */ FreeVec(SerWriteRequest); } /* Free the serial read request. */ DeleteIORequest(SerReadRequest); } /* Delete the serial write port. */ DeleteMsgPort(SerWritePort); } /* Delete the serial read port. */ DeleteMsgPort(SerReadPort); } /* Delete the serial read buffer. */ FreeVec(SerReadBuffer); } /* Close intuition.library. */ CloseLibrary(&IntuitionBase -> LibNode); } /* Close dos.library. */ CloseLibrary(&DOSBase -> dl_lib); } } /* Reply the startup packet if necessary. */ if(WBenchMsg) { Forbid(); ReplyMsg(&WBenchMsg -> sm_Message); } /* Return the result. */ return(Result); }