home *** CD-ROM | disk | FTP | other *** search
Wrap
/* $Revision Header * Header built automatically - do not edit! ************* * * (C) Copyright 1990 by Olaf 'Olsen' Barthel & MXM * * Name .....: TermMain.c * Created ..: Monday 21-Jan-91 20:12 * Revision .: 0 * * Date Author Comment * ========= ======== ==================== * 21-Jan-91 Olsen Created this file! * * $Revision Header ********************************************************/ #include "TermGlobal.h" /* Argument vectors offsets. */ enum { ARG_KEEPIO,ARG_DONTPOP,ARG_DEBUGWINDOW,ARG_DEBUGFILE }; /* Some global variables for starters. */ STATIC BYTE Terminated = FALSE; #ifndef DONT_DEBUG /* My debug info - don't remove it! */ extern BPTR DebugConsole,DebugFile; BPTR TermHelp; #define ARGTEMPLATE "K=KEEPIO/S,D=DONTPOP/S,W=DEBUGWINDOW/S,F=DEBUGFILE/K" #define NUMARGS 4 #else #define ARGTEMPLATE "K=KEEPIO/S,D=DONTPOP/S" #define NUMARGS 2 #endif /* DONT_DEBUG */ /* main(): * * This is our main entry point, check for the right * Kickstart version and fire off the background task * if approritate. */ LONG __saveds main() { UBYTE *Result; /* Set up SysBase. */ SysBase = *(struct ExecBase **)4; /* Are we running as a child of Workbench? */ ThisProcess = (struct Process *)SysBase -> ThisTask; if(!ThisProcess -> pr_CLI) { WaitPort(&ThisProcess -> pr_MsgPort); WBenchMsg = (struct WBStartup *)GetMsg(&ThisProcess -> pr_MsgPort); } else WBenchMsg = NULL; /* Kickstart 2.0 or higher required, do you hear me? */ if(SysBase -> LibNode . lib_Version < 36) { if(ThisProcess -> pr_CLI) { if(DOSBase = (struct DosLibrary *)OpenLibrary("dos.library",0)) { Write(ThisProcess -> pr_COS,"Kickstart 2.0 or higher required.\a\n",35); ThisProcess -> pr_Result2 = ERROR_INVALID_RESIDENT_LIBRARY; CloseLibrary(DOSBase); } } else { if(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",0)) { STATIC struct IntuiText BodyText = {0,1,JAM1,5,3,&DefaultFont,(UBYTE *)"Kickstart 2.0 or higher required.", NULL}; STATIC struct IntuiText SorryText = {0,1,JAM1,6,3,&DefaultFont,(UBYTE *)"Sorry",NULL}; struct Window *Window; if(Window = (struct Window *)BuildSysRequest(NULL,&BodyText,NULL,&SorryText,GADGETUP,301,46)) { struct IntuiMessage *Message; ScreenToFront(Window -> WScreen); DisplayBeep(Window -> WScreen); WaitPort(Window -> UserPort); if(Message = (struct IntuiMessage *)GetMsg(Window -> UserPort)) ReplyMsg(Message); FreeSysRequest(Window); } CloseLibrary(IntuitionBase); } } if(WBenchMsg) { Forbid(); ReplyMsg((struct Message *)WBenchMsg); } return(RETURN_FAIL); } /* Now try to open dos.library and go on examining * our calling parameters. */ if(!(DOSBase = (struct DosLibrary *)OpenLibrary("dos.library",36))) { CloseAll(); return(RETURN_FAIL); } /* We were called from Shell. */ if(ThisProcess -> pr_CLI) { UBYTE **ArgArray; /* Use the cute ReadArgs parser, allocate the * argument vectors... */ if(ArgArray = (UBYTE **)AllocVec(sizeof(UBYTE *) * NUMARGS,MEMF_PUBLIC | MEMF_CLEAR)) { struct RDArgs *ArgsPtr; if(ArgsPtr = (struct RDArgs *)AllocVec(sizeof(struct RDArgs),MEMF_PUBLIC|MEMF_CLEAR)) { ArgsPtr -> RDA_ExtHelp = "\nUsage: \33[1mterm\33[0m [KeepIO] [DontPop]\n\n KeepIO ....: Keep links to the current Shell window.\n DontPop ...: Don't pop an already running term to the front.\n\n"; /* Parse the args (if any). */ if(ReadArgs(ARGTEMPLATE,(LONG *)ArgArray,ArgsPtr)) { #ifndef DONT_DEBUG { extern UBYTE DebugFileName[256]; extern BYTE DebugWindow; if(ArgArray[ARG_DEBUGWINDOW]) DebugWindow = TRUE; if(ArgArray[ARG_DEBUGFILE]) strcpy(DebugFileName,ArgArray[ARG_DEBUGFILE]); } #endif /* DONT_DEBUG */ /* Pop a running `term' to the front? */ if((TermPort = (struct TermPort *)FindPort("term Port")) && !ArgArray[ARG_DONTPOP]) { if(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",0)) { if(TermPort -> TopWindow) BumpWindow(TermPort -> TopWindow); CloseLibrary(IntuitionBase); } FreeArgs(ArgsPtr); FreeVec(ArgsPtr); FreeVec(ArgArray); return(RETURN_OK); } /* We are to keep our links to * the Shell. */ if(ArgArray[ARG_KEEPIO]) { /* Open our resources and * squeak after failure. */ if(Result = OpenAll()) { if(Result[0]) Printf("\33[1mterm:\33[0m %s!\a\n",Result); CloseAll(); FreeArgs(ArgsPtr); FreeVec(ArgsPtr); FreeVec(ArgArray); return(RETURN_FAIL); } /* Go into main input * loop. */ HandleInput(); /* Does anybody understand * this joke? */ Printf("You quit with 0 gold pieces\nTo play again, just type \"term\"\n"); /* Free the argument * data. */ FreeArgs(ArgsPtr); FreeVec(ArgsPtr); FreeVec(ArgArray); /* Mega-glitch: term used to * bolt and lock the door * before the last dos.library * functions were called! */ CloseAll(); return(RETURN_OK); } FreeArgs(ArgsPtr); } else { PrintFault(IoErr(),"term"); FreeVec(ArgsPtr); FreeVec(ArgArray); return(RETURN_ERROR); } FreeVec(ArgsPtr); } FreeVec(ArgArray); /* Clone the current directory of our * process before we detach ourselves * from the starting Shell. */ CurrentDir(RemoteCurrentDir = CurrentDir(NULL)); RemoteCurrentDir = DupLock(RemoteCurrentDir); /* Create a new process from our code. */ if(!Res("term Main Process",0,HandleInput,16384,FALSE)) { UnLock(RemoteCurrentDir); Printf("\33[1mterm:\33[0m Failed to create new process!\a\n"); CloseAll(); return(RETURN_FAIL); } } else { Printf("\33[1mterm:\33[0m Failed to allocate argument vectors!\a\n"); CloseLibrary(DOSBase); return(RETURN_FAIL); } } else { /* Initialize this, so OpenAll will work with * correct data. */ TermPort = (struct TermPort *)FindPort("term Port"); /* We were called from Workbench. */ if(Result = OpenAll()) { if(IntuitionBase && Result[0]) MyEasyRequest(NULL,"term has a problem:\n%s!","Continue",Result); CloseAll(); } else HandleInput(); } return(RETURN_OK); } /* HandleInput(): * * This is our main input loop (check window & serial). */ VOID HandleInput() { ULONG SignalSet,SavageSignals; ThisProcess = (struct Process *)SysBase -> ThisTask; /* Return to the previous current directory * (so that file requesters and the like * will know where to start). */ if(RemoteCurrentDir) { CurrentDir(RemoteCurrentDir); /* Oops, some data still remains and needs to * be cleared. */ ThisProcess -> pr_CIS = NULL; ThisProcess -> pr_COS = NULL; ThisProcess -> pr_ConsoleTask = NULL; ThisProcess -> pr_CLI = NULL; } /* Open the resources we need. */ if(!ThisProcess -> pr_CLI && !WBenchMsg) { UBYTE *Result; if(Result = OpenAll()) { if(IntuitionBase && Result[0]) MyEasyRequest(NULL,"term has a problem:\n%s!","Continue",Result); CloseAll(); return; } } BumpWindow(Window); /* Set up the public screen data. */ PubScreenStuff(); /* Show our business card. */ BlockWindows(); ShowInfo(TRUE); ReleaseWindows(); /* Initialize the modem. */ SerialCommand(Config . ModemInit); /* Execute the startup macro (if any). */ if(Config . StartupMacro[0]) SerialCommand(Config . StartupMacro); LogAction("Program started (%s %s).",TermName,TermDate); /* Go into input loop... */ Loop: while(!Terminated) { /* We did a file transfer (auto-download?) and * will need to close the transfer window. */ if(TransferWindow) { WakeUp(TransferWindow); DeleteTransferPanel(); ReleaseWindows(); Say("Transfer completed."); } /* For debugging purposes only: feed a file * to the `term' display. */ #ifndef DONT_DEBUG if(TermHelp && (DebugConsole || DebugFile)) { LONG HelpChar; while((HelpChar = FGetC(TermHelp)) != -1) { UBYTE Dummy = HelpChar; ConProcess(&Dummy,1); HandleWindow(); if(!TermHelp) break; } if(TermHelp) { Close(TermHelp); TermHelp = NULL; } } #endif /* DONT_DEBUG */ SavageSignals = NULL; /* The serial line is active. */ if(Status != STATUS_HOLDING && ReadPort) SavageSignals |= SIG_SERIAL; /* The packet window is still open. */ if(PacketWindow) SavageSignals |= SIG_PACKET; /* Wait for input events to occur. */ SignalSet = Wait(SIG_WINDOW | SIG_REXX | SIG_AUDIO | SavageSignals); /* Loop & check until the dust has settled. */ if(SignalSet & (SIG_WINDOW | SavageSignals)) while(HandleWindow() || HandleSerial() || HandlePacket()); /* Remove audio request. */ if(SignalSet & SIG_AUDIO) WaitIO(AudioBlock); /* Check if we are to prompt the user for * ZModem upload type. */ if(UsesZModem) { if(FlowInfo . ZModemUpload) { FlowInit(); BlockWindows(); if(UploadPanel() == 1) BinaryTransfer = FALSE; StartXprSend(BinaryTransfer ? TRANSFER_BINARY : TRANSFER_TEXT); ReleaseWindows(); } } /* Make the user notice not too obvious events. */ if((FlowInfo . Voice || FlowInfo . Ring) && Online) { BumpWindow(Window); if(FlowInfo . Voice) ConWrites("\r\nIncoming call!\r\n\r\n"); else ConWrites("\r\nIncoming voice call!\r\n\r\n"); Say("Incoming call."); FlowInit(); } /* Check for rexx messages to be processed. */ if(SignalSet & SIG_REXX) HandleRexx(); if(!Online && CurrentPay) { /* Display how much we expect * the user will have to pay for * this call. */ ConWrites("\r\nThis call will cost you %ld.%02ld.\r\n\r\n",CurrentPay / 100,CurrentPay % 100); CurrentPay = 0; } /* We did a file transfer (auto-download?) and * will need to close the transfer window. */ if(TransferWindow) { WakeUp(TransferWindow); DeleteTransferPanel(); ReleaseWindows(); Say("Transfer completed."); } if(ResetSerial) { FlushSerial(); DeleteSerial(); BlockWindows(); OpenLoop: if(!CreateSerial()) { APTR OldPtr = ThisProcess -> pr_WindowPtr; DeleteSerial(); ThisProcess -> pr_WindowPtr = (APTR)Window; switch(MyEasyRequest(Window,"term has a problem:\nFailed to open %s!","Retry|Ignore|Quit term",Config . SerialDevice)) { case 1: goto OpenLoop; case 2: break; case 0: Terminated = TRUE; } ThisProcess -> pr_WindowPtr = OldPtr; } else ResetSerial = TRUE; ReleaseWindows(); } /* We are to release the serial.device (or * whatever we are using) for some reason. */ if(ReleaseSerial) { APTR OldPtr = ThisProcess -> pr_WindowPtr; ThisProcess -> pr_WindowPtr = (APTR)Window; /* This might happen if an ARexx user * released the serial device and * failed to reopen it. */ if(!ReadPort) goto OpenIt; FlushSerial(); DeleteSerial(); BlockWindows(); if(MyEasyRequest(Window,"%s unit %ld has been reset and released.\nClick below to continue.","Continue|Quit term",Config . SerialDevice,Config . UnitNumber)) { OpenIt: if(!CreateSerial()) { DeleteSerial(); switch(MyEasyRequest(Window,"term has a problem:\nFailed to open %s!","Retry|Ignore|Quit term",Config . SerialDevice)) { case 1: goto OpenIt; case 2: break; case 0: Terminated = TRUE; } } } else Terminated = TRUE; ReleaseSerial = FALSE; ThisProcess -> pr_WindowPtr = OldPtr; ReleaseWindows(); } /* Somebody told us to re-open the display * (changed the terminal emulation/colour * mode). */ if(ResetDisplay) { UBYTE *Result; /* Delete the display (if possible). * This will go wrong if there * are any visitor windows on our * screen. */ if(DeleteDisplay()) { if(Result = CreateDisplay(FALSE)) { ThisProcess -> pr_WindowPtr = (APTR)Window; MyEasyRequest(NULL,"term has a problem:\n%s!","Continue",Result); Terminated = TRUE; } BumpWindow(Window); PubScreenStuff(); } else { CopyMem(&PrivateConfig,&Config,sizeof(struct Configuration)); BlockWindows(); MyEasyRequest(Window,"term has a problem:\nCannot close screen yet!","Continue"); ReleaseWindows(); } ResetDisplay = FALSE; } if(SendStartup && Online) { if(Config . StartupMacro[0]) SerialCommand(Config . StartupMacro); SendStartup = FALSE; } } /* User wants to quit term, so let's try to close * our magnificient screen and exit. */ if(Screen) { struct List *PubScreenList; struct PubScreenNode *ScreenNode; /* Lock the list of public screens. */ PubScreenList = LockPubScreenList(); /* Scan the list and try to find our * private node. */ for(ScreenNode = (struct PubScreenNode *)PubScreenList -> lh_Head ; ScreenNode -> psn_Node . ln_Succ ; ScreenNode = (struct PubScreenNode *)ScreenNode -> psn_Node . ln_Succ) { if(ScreenNode -> psn_Screen == Screen) break; } if(ScreenNode) { /* Okay, we know who and where we are, * check the number of visitor windows * currently open on our screen. */ if(ScreenNode -> psn_VisitorCount) { /* No chance, don't close * the screen now. */ UnlockPubScreenList(); BlockWindows(); MyEasyRequest(Window,"term has a problem:\nCannot close screen yet!","Continue"); ReleaseWindows(); Terminated = FALSE; goto Loop; } } UnlockPubScreenList(); } /* Send the modem exit command, shut down the * serial.device and close all resources. */ SerialCommand(Config . ModemExit); FlushSerial(); LogAction("Program terminated."); #ifndef DONT_DEBUG if(TermHelp) Close(TermHelp); #endif /* DONT_DEBUG */ Say("Bye bye."); if(!ThisProcess -> pr_CLI) CloseAll(); } /* HandleWindow(): * * This funny part checks the window(s) for incoming * user input. Menus are handled elsewhere. */ BYTE HandleWindow() { struct IntuiMessage *Massage; ULONG Class,Code,Qualifier; struct Gadget *Gadget; UBYTE Char,InputBuffer[257]; /* Any news in the mail? */ if(Massage = (struct IntuiMessage *)GetMsg(Window -> UserPort)) { /* Perform key conversion. */ Char = KeyConvert(Massage,InputBuffer); /* Pick up the pieces. */ Class = Massage -> Class; Code = Massage -> Code; Qualifier = Massage -> Qualifier; Gadget = (struct Gadget *)Massage -> IAddress; ReplyMsg(Massage); /* This looks like a raw key. */ if(Class == IDCMP_RAWKEY) { /* Make it a vanilla key if * possible. I didn't set * both VANILLAKEY & RAWKEY * since I prefer to convert * a few keys on my own and * I am not really sure whether * cooked key input includes * double-dead keys. */ if(Char) { /* VT100 prefers to handle * the numeric keypad differently * in applications mode. */ if(Qualifier & IEQUALIFIER_NUMERICPAD) { if(HandleCursor(Char)) goto SkipIt; } /* If input is not a control * character, such as F-keys, * cursor keys, etc. process * it as usual. */ if(!IsControl(Char)) { SHORT i; /* Run down the contents of * the key result string. */ for(i = 0 ; i < strlen(InputBuffer) ; i++) { /* Restart serial line * after XON. */ if(Status == STATUS_HOLDING) { if(InputBuffer[i] == XOF) { SerWrite(&InputBuffer[i],1); Status = STATUS_READY; } else DoSomeBeep(); } else { /* Convert chars * as approriate. */ if(InputBuffer[i] == '\n') { switch(Config . SendLF) { case LF_IGNORE: break; case LF_ASLF: goto SendIt; case LF_ASLFCR: SerWrite("\n\r",2); break; } continue; } if(InputBuffer[i] == '\r') { switch(Config . SendCR) { case CR_IGNORE: break; case CR_ASCR: goto SendIt; case CR_ASCRLF: SerWrite("\r\n",2); break; } continue; } /* Stop in/output. */ if(InputBuffer[i] == XON) { if(Config . Handshaking == HANDSHAKING_XONXOFF) Status = STATUS_HOLDING; } /* Convert special * Amiga characters into * alien IBM dialect. */ SendIt: if(Config . Font == FONT_IBM) { if(IBMConversion[InputBuffer[i]]) SerWrite(&IBMConversion[InputBuffer[i]],1); else SerWrite(&InputBuffer[i],1); } else SerWrite(&InputBuffer[i],1); } } } else { /* Send keyboard macro commands * or perform cursor functions. */ if(Char >= FN1 && Char <= F10) { if(Qualifier & IEQUALIFIER_CONTROL) SerialCommand(MacroKeys -> Keys[3][Char - FN1]); else { if(Qualifier & (IEQUALIFIER_LALT|IEQUALIFIER_RALT)) SerialCommand(MacroKeys -> Keys[2][Char - FN1]); else { if(Qualifier & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT)) SerialCommand(MacroKeys -> Keys[1][Char - FN1]); else SerialCommand(MacroKeys -> Keys[0][Char - FN1]); } } } else { #ifndef DONT_DEBUG if(Char == HLP && (DebugConsole || DebugFile)) { if(TermHelp) { Close(TermHelp); TermHelp = NULL; } else { struct FileRequester *FileRequest; UBYTE DummyBuffer[256]; BlockWindows(); if(FileRequest = GetFile("Load Test File...","","",DummyBuffer,"#?.ansi",FALSE,FALSE)) TermHelp = Open(DummyBuffer,MODE_OLDFILE); ReleaseWindows(); } } else #endif /* DONT_DEBUG */ HandleCursor(Char); } } } } /* Capture characters from the main * screen. */ if(Class == IDCMP_MOUSEBUTTONS && Code == SELECTDOWN) { BYTE SingleChar,Xerox; /* We want to know where the mouse * moves... */ ReportMouse(TRUE,Window); /* Pick a single character. */ if(Qualifier & IEQUALIFIER_CONTROL) SingleChar = TRUE; else SingleChar = FALSE; /* Xerox style snapping (feed into * input stream after selection). */ if(Qualifier & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT)) Xerox = TRUE; else Xerox = FALSE; RasterClip(SingleChar,Xerox); ReportMouse(FALSE,Window); } /* A menu item was selected. */ SkipIt: if(Class == IDCMP_MENUPICK) HandleMenu(Code); return(TRUE); } return(FALSE); } /* HandleSerial(): * * Handle the data coming in from the serial line. */ BYTE HandleSerial() { /* We are XON'ed or the serial line was shut down. */ if(Status != STATUS_HOLDING && ReadPort && !ReleaseSerial && !Terminated) { /* Any news? */ if(CheckIO(ReadRequest)) { LONG Length; if(WaitIO(ReadRequest)) return(FALSE); /* Process the data if necessary (XPR-function). */ if(TransferBits & XPRS_HOSTMON) if(!XProtocolHostMon(XprIO,ReadBuffer,1,1)) goto Loop; /* Send the byte to the console. */ ConProcess(ReadBuffer,1); /* Loop until all data has been processed. */ Loop: do { /* Check how many bytes are still in * the serial buffer. */ WriteRequest -> IOSer . io_Command = SDCMD_QUERY; DoIO(WriteRequest); if(Length = WriteRequest -> IOSer . io_Actual) { if(Length > 1024) Length = 1024; ReadRequest -> IOSer . io_Command = CMD_READ; ReadRequest -> IOSer . io_Data = ReadBuffer; ReadRequest -> IOSer . io_Length = Length; DoIO(ReadRequest); /* Process the serial data if * necessary (XPR-stuff). */ if(TransferBits & XPRS_HOSTMON) { if(!(Length = XProtocolHostMon(XprIO,ReadBuffer,Length,1024))) { Length = 1; continue; } } /* Send the data to the console. */ ConProcess(ReadBuffer,Length); } } while(Length); /* Ask for another byte. */ ReadRequest -> IOSer . io_Command = CMD_READ; ReadRequest -> IOSer . io_Data = ReadBuffer; ReadRequest -> IOSer . io_Length = 1; SendIO(ReadRequest); return(TRUE); } } return(FALSE); } /* HandleMenu(ULONG Code): * * Skip along the number of selected menu items and * handle the associated functions. */ VOID HandleMenu(ULONG Code) { STATIC UBYTE NumberBuffer[256]; struct MenuItem *MenuItem; struct FileRequester *FileRequest; UBYTE DummyBuffer[256],*DummyChar; BYTE OldStatus; struct List *DialList; LONG DialListNum; LONG Size; BPTR SomeFile; APTR OldPtr; /* Check until the last menuitem has been * processed. */ while(Code != MENUNULL) { /* Pick up the associated menu item. */ if(!(MenuItem = ItemAddress(Menu,Code))) break; OldStatus = Status; /* Now call the approriate routine. */ switch((ULONG)MENU_USERDATA(MenuItem)) { /* Say who we are. */ case MEN_ABOUT: BlockWindows(); ShowInfo(FALSE); ReleaseWindows(); break; /* Open the preferences settings. */ case MEN_OPEN: BlockWindows(); strcpy(DummyBuffer,LastConfig); DummyChar = PathPart(DummyBuffer); *DummyChar = 0; if(FileRequest = GetFile("Open Preferences...",DummyBuffer,FilePart(LastConfig),DummyBuffer,"#?.term",FALSE,FALSE)) { if(ReadIFFData(DummyBuffer,&PrivateConfig,sizeof(struct Configuration),'PREF')) { swmem(&PrivateConfig,&Config,sizeof(struct Configuration)); strcpy(DummyBuffer,LastConfig); ConfigSetup(); } else MyEasyRequest(Window,"Error opening file\n%s!","Continue",DummyBuffer); FreeAslRequest(FileRequest); } ReleaseWindows(); break; /* Save the terminal preferences. */ case MEN_SAVE: if(LastConfig[0]) { BlockWindows(); if(!WriteIFFData(LastConfig,&Config,sizeof(struct Configuration),'PREF')) MyEasyRequest(Window,"Error writing preferences to\nfile %s!","Continue",LastConfig); ReleaseWindows(); } break; /* Save the terminal preferences to a * given file name. */ case MEN_SAVEAS: BlockWindows(); strcpy(DummyBuffer,LastConfig); DummyChar = PathPart(DummyBuffer); *DummyChar = 0; if(FileRequest = GetFile("Save Preferences As...",DummyBuffer,FilePart(LastConfig),DummyBuffer,"#?.term",TRUE,FALSE)) { if(WriteIFFData(DummyBuffer,&Config,sizeof(struct Configuration),'PREF')) strcpy(LastConfig,DummyBuffer); else MyEasyRequest(Window,"Error writing preferences to\nfile %s!","Continue",DummyBuffer); FreeAslRequest(FileRequest); } ReleaseWindows(); break; /* Print the screen (pure ASCII). */ case MEN_PRINTSCREEN: BlockWindows(); if(SomeFile = Open("PRT:",MODE_NEWFILE)) { SHORT i; for(i = 0 ; i < RasterHeight ; i++) { if(!FWrite(SomeFile,&Raster[i * RasterWidth],RasterWidth,1)) break; if(!FWrite(SomeFile,"\n",1,1)) break; } Close(SomeFile); } else MyEasyRequest(Window,"Failed to open device PRT:!","Continue"); ReleaseWindows(); break; /* Terminate the program. */ case MEN_QUIT: BlockWindows(); OldPtr = ThisProcess -> pr_WindowPtr; ThisProcess -> pr_WindowPtr = (APTR)Window; if(MyEasyRequest(Window,"Do you really want to quit term?","Yes|No")) Terminated = TRUE; ThisProcess -> pr_WindowPtr = OldPtr; ReleaseWindows(); break; /* Set the name we will use to open the * default console output window for * AmigaDOS commands and ARexx scripts. */ case MEN_SETCONSOLE: BlockWindows(); if(xpr_gets("Set Console Window",WindowName)) SetEnvDOS("TERMWINDOW",WindowName); ReleaseWindows(); break; /* Execute an AmigaDOS command. */ case MEN_DOSCOMMAND: BlockWindows(); DummyBuffer[0] = 0; /* Enter the name of the command. */ if(GetString("Enter AmigaDOS Command",DummyBuffer)) SendAmigaDOSCommand(DummyBuffer); ReleaseWindows(); break; /* Execute an ARexx script command. */ case MEN_REXXCOMMAND: BlockWindows(); DummyBuffer[0] = 0; /* Get the rexx file name/program. */ if(GetString("Enter ARexx Command",DummyBuffer)) SendARexxCommand(DummyBuffer); ReleaseWindows(); break; /* Edit a file. */ case MEN_EDIT: BlockWindows(); if(!Config . Editor[0]) GetString("Enter Name Of Editor To Use",&Config . Editor[0]); if(Config . Editor[0]) { if(FileRequest = GetFile("Edit File...","","",DummyBuffer,NULL,FALSE,FALSE)) { UBYTE CompoundName[512]; ULONG TagEnd = TAG_END; strcpy(CompoundName,Config . Editor); strcat(CompoundName," "); strcat(CompoundName,DummyBuffer); System(CompoundName,&TagEnd); BumpWindow(Window); FreeAslRequest(FileRequest); } } ReleaseWindows(); break; /* Feed the contents of the clipboard * into the input stream. */ case MEN_PASTE: if(Size = LoadClip(SharedBuffer,256)) SerWrite(SharedBuffer,Size); break; /* Open the packet window if necessary, else * just activate it. */ case MEN_PACKET: if(!PacketWindow) CreatePacketWindow(); else ActivateWindow(PacketWindow); break; /* Clear the contents of the scrollback * buffer. */ case MEN_CLEARBUFFER: if(Lines) { BlockWindows(); if(MyEasyRequest(Window,"The buffer still holds %ld lines,\ndo you wish to discard them?","Yes|No",Lines)) ClearBuffer(); ReleaseWindows(); } break; /* Display the scrollback buffer. * Notify the scrollback task or * fire it off if approriate. */ case MEN_DISPLAYBUFFER: if(BufferProcess) Signal(BufferProcess,SIGBREAKF_CTRL_D); else { if(BufferProcess = (struct Process *)CreateNewProcTags( NP_Entry, BufferServer, NP_Name, "term Buffer Process", NP_Priority, 0, NP_StackSize, 8192, NP_WindowPtr, -1, TAG_END)) Wait(SIGBREAKF_CTRL_C); if(!BufferProcess) { BlockWindows(); MyEasyRequest(Window,"Unable to create buffer task!","Continue"); ReleaseWindows(); } } break; case MEN_CLOSEBUFFER: if(BufferProcess) Signal(BufferProcess,SIGBREAKF_CTRL_C); break; case MEN_LOADBUFFER: BlockWindows(); if(FileRequest = GetFile("Load Buffer...","","",DummyBuffer,NULL,FALSE,FALSE)) { if(GetFileSize(DummyBuffer)) { if(SomeFile = Open(DummyBuffer,MODE_OLDFILE)) { if(Lines) { switch(MyEasyRequest(Window,"The display buffer still holds %ld\nlines, do you wish to continue?","Discard Buffer|Append Buffer|Cancel",Lines)) { case 1: ClearBuffer(); break; case 2: break; case 0: Close(SomeFile); SomeFile = NULL; break; } } if(SomeFile) { LineRead(NULL,NULL,NULL); while(LineRead(SomeFile,DummyBuffer,80)) StoreBuffer(DummyBuffer,strlen(DummyBuffer)); Close(SomeFile); } } } FreeAslRequest(FileRequest); } ReleaseWindows(); break; /* Save the contents of the scrollback * buffer to a file (line by line). */ case MEN_SAVEBUFFER: BlockWindows(); if(!Lines) MyEasyRequest(Window,"There isn't anything in the\nbuffer right now.","Continue"); else { if(FileRequest = GetFile("Save Buffer...","","",DummyBuffer,NULL,TRUE,FALSE)) { SomeFile = NULL; /* If the file we are about * to create already exists, * ask the user whether we are * to create, append or skip * the file. */ if(GetFileSize(DummyBuffer)) { switch(MyEasyRequest(Window,"File %s already exists!","Create New File|Append Data|Cancel",DummyBuffer)) { case 1: SomeFile = Open(DummyBuffer,MODE_NEWFILE); break; case 2: if(SomeFile = Open(DummyBuffer,MODE_READWRITE)) { if(Seek(SomeFile,0,OFFSET_END) == -1) { Close(SomeFile); SomeFile = NULL; } } break; } } else SomeFile = Open(DummyBuffer,MODE_NEWFILE); if(!SomeFile) MyEasyRequest(Window,"Error opening file %s!","Continue",DummyBuffer); else { LONG i; /* Obtain the semaphore required * to gain access to the line buffer */ ObtainSemaphore(BufferSemaphore); for(i = 0 ; i < Lines ; i++) { if(FPrintf(SomeFile,"%s\n",BufferLines[i]) == -1) break; } ReleaseSemaphore(BufferSemaphore); Close(SomeFile); SetProtection(DummyBuffer,FIBF_EXECUTE); } FreeAslRequest(FileRequest); } } ReleaseWindows(); break; /* Open/close the terminal capture file. */ case MEN_CAPTUREDISK: if(FileCapture) { Close(FileCapture); MenuItem -> Flags &= ~CHECKED; FileCapture = NULL; if(!GetFileSize(CaptureName)) DeleteFile(CaptureName); else SetProtection(CaptureName,FIBF_EXECUTE); } else { BlockWindows(); strcpy(DummyBuffer,CaptureName); DummyChar = PathPart(DummyBuffer); *DummyChar = 0; if(FileRequest = GetFile("Capture To Disk...",DummyBuffer,FilePart(CaptureName),DummyBuffer,NULL,TRUE,FALSE)) { if(GetFileSize(DummyBuffer)) { switch(MyEasyRequest(Window,"File %s already exists!","Create New File|Append Data|Cancel",DummyBuffer)) { case 1: FileCapture = Open(DummyBuffer,MODE_NEWFILE); break; case 2: if(FileCapture = Open(DummyBuffer,MODE_READWRITE)) { if(Seek(FileCapture,0,OFFSET_END) == -1) { Close(FileCapture); FileCapture = NULL; } } break; case 0: MenuItem -> Flags &= ~CHECKED; goto CapSkip; } } else FileCapture = Open(DummyBuffer,MODE_NEWFILE); if(!FileCapture) { MyEasyRequest(Window,"Error opening file %s!","Continue",DummyBuffer); MenuItem -> Flags &= ~CHECKED; } else { strcpy(CaptureName,DummyBuffer); MenuItem -> Flags |= CHECKED; } FreeAslRequest(FileRequest); } else MenuItem -> Flags &= ~CHECKED; CapSkip: ReleaseWindows(); } break; /* Start/terminate the printer * capture. */ case MEN_CAPTUREPRINTER:if(PrinterCapture) { Close(PrinterCapture); MenuItem -> Flags &= ~CHECKED; PrinterCapture = NULL; } else { if(PrinterCapture = Open("PRT:",MODE_NEWFILE)) MenuItem -> Flags |= CHECKED; else { MenuItem -> Flags &= ~CHECKED; BlockWindows(); MyEasyRequest(Window,"Error opening PRT: device!","Continue"); ReleaseWindows(); } } break; /* This follows the upload routines. * Text upload makes the xpr_finfo function * identify any file as being a text * file (no voodoo magic yet). */ case MEN_UPLOADTEXT: BinaryTransfer = FALSE; /* The rest of the upload routines. */ case MEN_UPLOAD: BlockWindows(); StartXprSend(BinaryTransfer ? TRANSFER_BINARY : TRANSFER_TEXT); BinaryTransfer = TRUE; ReleaseWindows(); break; case MEN_DOWNLOADTEXT: BinaryTransfer = FALSE; /* Download some files. */ case MEN_DOWNLOAD: BlockWindows(); StartXprReceive(BinaryTransfer ? TRANSFER_BINARY : TRANSFER_TEXT); BinaryTransfer = TRUE; ReleaseWindows(); break; /* Set the file transfer options. */ case MEN_XFERPROTOCOL: BlockWindows(); for(;;) { XprIO -> xpr_filename = NULL; NewLibrary = FALSE; /* Set up the library options. */ if(XProtocolBase) { TransferBits = XProtocolSetup(XprIO); /* Successful? */ if(!(TransferBits & XPRS_SUCCESS)) { MyEasyRequest(Window,"Failed to set up protocol\n\"%s\"!","Continue",LastXprLibrary); CloseLibrary(XProtocolBase); XProtocolBase = NULL; LastXprLibrary[0] = 0; TransferBits = 0; break; } } else xpr_options(0,NULL); /* Save the options if necessary. */ SaveProtocolOpts(); if(NewLibrary) { if(!ProtocolSetup()) break; strcpy(Config . Protocol,LastXprLibrary); } else break; } ReleaseWindows(); break; /* Select the transfer protocol; I had hoped * to get rid of this option but xprascii and * the older pre-2.0 standard xpr-libraries * forced it back in. */ case MEN_SELECTXFER: BlockWindows(); NewLibrary = FALSE; xpr_options(0,NULL); if(NewLibrary) { if(ProtocolSetup()) strcpy(Config . Protocol,LastXprLibrary); } ReleaseWindows(); break; /* These routines simply switch the * transfer library (to xprascii.library) * and perform up/download. To lessen the * confusion both routines have been * implemented as single routines. * After the transfer the control is * returned to the previously selected * transfer library. */ case MEN_SEND: BlockWindows(); if(ASCIISetup()) { StartXprSend(TRANSFER_ASCII); ASCIIShutdown(); } ReleaseWindows(); break; case MEN_RECEIVE: BlockWindows(); if(ASCIISetup()) { StartXprReceive(TRANSFER_ASCII); ASCIIShutdown(); } ReleaseWindows(); break; /* Open the phonebook and dial the * list of entries the user will select. */ case MEN_PHONEBOOK: BlockWindows(); if(PhonePanel(&DialListNum)) { DialPanel(); Status = OldStatus; } ReleaseWindows(); break; /* Dial a single number. */ case MEN_DIAL: BlockWindows(); if(xpr_gets("Enter Phone Number",NumberBuffer)) { if(DialList = (struct List *)AllocMem(sizeof(struct List),MEMF_PUBLIC | MEMF_CLEAR)) { struct PhoneNode *DialNode; NewList(DialList); if(DialNode = (struct PhoneNode *)AllocMem(sizeof(struct PhoneNode),MEMF_PUBLIC|MEMF_CLEAR)) { DialNode -> VanillaNode . ln_Name = (UBYTE *)NumberBuffer; AddTail(DialList,&DialNode -> VanillaNode); FreeSubList(); SubList = DialList; SubListNum = 1; DialPanel(); Status = OldStatus; } else FreeMem(DialList,sizeof(struct List)); } } ReleaseWindows(); break; /* Redial those dial list entries which * we were unable to connect. */ case MEN_REDIAL: BlockWindows(); if(SubList) { DialPanel(); Status = OldStatus; } else MyEasyRequest(Window,"Current dialing list is empty.","Continue"); ReleaseWindows(); break; /* Play a touch-tone phone number. */ case MEN_PLAY: BlockWindows(); if(xpr_gets("Enter Phone Number To Play",NumberBuffer)) { if(!ToneDial(NumberBuffer)) MyEasyRequest(NULL,"term has a problem:\n%s!","Continue","Failed to allocate resources for playing."); else DeleteTone(); } ReleaseWindows(); break; /* Send a break across the serial line. */ case MEN_SENDBREAK: if(WriteRequest) { Status = STATUS_BREAKING; WriteRequest -> IOSer . io_Command = SDCMD_BREAK; DoIO(WriteRequest); Status = OldStatus; } break; /* Hang up the phone line. */ case MEN_HANGUP: Status = STATUS_HANGUP; SerialCommand(Config . ModemHangup); Status = OldStatus; Online = FALSE; Password[0] = 0; LogAction("Hang up line."); break; /* Release the serial device for other * applications. */ case MEN_RELEASE: ReleaseSerial = TRUE; break; /* Reset the display styles and restore * the colours. */ case MEN_RESETSTYLES: Escape = TRUE; ConProcess("\033[m",3); Config . FontScale = SCALE_NORMAL; switch(Config . ColourMode) { case COLOUR_EIGHT: FgPen = 7; break; case COLOUR_SIXTEEN: FgPen = 15; break; case COLOUR_AMIGA: default: FgPen = 1; break; } BgPen = 0; if(RPort -> FgPen != FgPen) SetAPen(RPort,FgPen); if(RPort -> BgPen != BgPen) SetBPen(RPort,BgPen); Escape = FALSE; break; /* Simply clear the screen and move the * cursor to its home position. */ case MEN_CLEARSCREEN: Escape = TRUE; ConProcess("\033[2J\033[H",7); Escape = FALSE; break; /* Save screen as IFF-ILBM file. */ case MEN_SAVEILBM: BlockWindows(); if(FileRequest = GetFile("Save Screen (IFF-ILBM)...","","",DummyBuffer,NULL,TRUE,FALSE)) { if(!SaveRPort(&Screen -> RastPort,VPort,0,Window -> TopEdge,Window -> Width,Window -> Height,Screen -> Width,Screen -> Height,FALSE,DummyBuffer)) MyEasyRequest(Window,"Failed to save screen to\nfile %s!","Continue",DummyBuffer); FreeAslRequest(FileRequest); } ReleaseWindows(); break; /* Save screen as ASCII file. */ case MEN_SAVEASCII: BlockWindows(); if(FileRequest = GetFile("Save Screen (ASCII)...","","",DummyBuffer,NULL,TRUE,FALSE)) { if(GetFileSize(DummyBuffer)) { switch(MyEasyRequest(Window,"File %s already exists!","Create New File|Append Data|Cancel",DummyBuffer)) { case 1: SomeFile = Open(DummyBuffer,MODE_NEWFILE); break; case 2: if(SomeFile = Open(DummyBuffer,MODE_READWRITE)) { if(Seek(SomeFile,0,OFFSET_END) == -1) { Close(SomeFile); SomeFile = NULL; } } break; case 0: SomeFile = ~0; break; } } else SomeFile = Open(DummyBuffer,MODE_NEWFILE); if(!SomeFile) MyEasyRequest(Window,"Failed to save screen to\nfile %s!","Continue",DummyBuffer); else { if(SomeFile != ~0) { SHORT i; for(i = 0 ; i < RasterHeight ; i++) { if(!FWrite(SomeFile,&Raster[i * RasterWidth],RasterWidth,1)) break; if(!FWrite(SomeFile,"\n",1,1)) break; } Close(SomeFile); SetProtection(DummyBuffer,FIBF_EXECUTE); } } FreeAslRequest(FileRequest); } ReleaseWindows(); break; /* Set the serial preferences. */ case MEN_SERIAL: BlockWindows(); if(SerialPanel(&Config)) { FlushSerial(); DeleteSerial(); if(!CreateSerial()) { OldPtr = ThisProcess -> pr_WindowPtr; DeleteSerial(); ThisProcess -> pr_WindowPtr = (APTR)Window; if(!MyEasyRequest(Window,"term has a problem:\nFailed to open %s!","Continue|Quit term",Config . SerialDevice)) { ThisProcess -> pr_WindowPtr = OldPtr; Terminated = TRUE; break; } ThisProcess -> pr_WindowPtr = OldPtr; } } ReleaseWindows(); break; /* Set the modem preferences. */ case MEN_MODEM: BlockWindows(); if(ModemPanel(&Config)) FlowInit(); ReleaseWindows(); break; /* Set the keyboard macros. */ case MEN_MACROS: BlockWindows(); MacroPanel(MacroKeys); ReleaseWindows(); break; /* Set the screen preferences. */ case MEN_SCREEN: BlockWindows(); if(ScreenPanel(&Config)) ResetDisplay = TRUE; else PubScreenStuff(); ReleaseWindows(); break; /* Set the terminal preferences. */ case MEN_TERMINAL: BlockWindows(); if(TerminalPanel(&Config)) { if(Config . Font != PrivateConfig . Font) { if(Config . Font == FONT_TOPAZ) SetFont(RPort,Topaz); else SetFont(RPort,IBM); } if(Config . Emulation != PrivateConfig . Emulation || Config . ColourMode != PrivateConfig . ColourMode) ResetDisplay = TRUE; } ReleaseWindows(); break; case MEN_STARTUP: BlockWindows(); GetString("Enter Startup Macro",&Config . StartupMacro[0]); ReleaseWindows(); break; case MEN_EMULATION: BlockWindows(); EmulationPanel(&Config); ReleaseWindows(); break; case MEN_PATH: BlockWindows(); if(PathPanel(&Config)) { DeleteBeep(); if(!OpenSound(Config . BeepSound)) MyEasyRequest(Window,"Failed to open sound \"%s\"!","Continue",Config . BeepSound); CreateBeep(); } ReleaseWindows(); break; case MEN_HOTKEYS: BlockWindows(); if(HotkeyPanel(&Hotkeys)) { if(!SetupCx()) MyEasyRequest(Window,"Failed to set up hotkeys (spelling mistake?).","Continue"); } ReleaseWindows(); break; case MEN_SPEECH: BlockWindows(); SpeechPanel(); ReleaseWindows(); break; /* Ignore the rest. */ default: break; } Code = MenuItem -> NextSelect; } }