home *** CD-ROM | disk | FTP | other *** search
Wrap
/* ** $Id: termMain.c,v 1.16 92/08/18 16:12:39 olsen Sta Locker: olsen $ ** $Revision: 1.16 $ ** $Date: 92/08/18 16:12:39 $ ** ** Program main routines and event loop ** ** Copyright © 1990-1992 by Olaf `Olsen' Barthel & MXM ** All Rights Reserved */ #include "termGlobal.h" /* Argument vectors offsets. */ enum { ARG_KEEPIO,ARG_DONTPOP,ARG_SETTINGS,ARG_COUNT }; /* Argument template. */ #define ARGTEMPLATE "K=KEEPIO/S,D=DONTPOP/S,S=SETTINGS/K" /* Some global variables for starters. */ STATIC BYTE DoIconify = FALSE; /* Local config path variable. */ STATIC STRPTR ConfigPath; STATIC UBYTE ThePath[256]; /* 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 *) * (ARG_COUNT),MEMF_ANY|MEMF_CLEAR)) { struct RDArgs *ArgsPtr; if(ArgsPtr = (struct RDArgs *)AllocDosObject(DOS_RDARGS,TAG_DONE)) { ArgsPtr -> RDA_ExtHelp = "\nUsage: \33[1mterm\33[0m [KeepIO] [DontPop] [Settings <Path name>]\n\n KeepIO = Keep links to the current Shell window.\n DontPop = Do not pop an already running `term' to the front.\n Settings = Path to search for settings files.\n\n"; /* Parse the args (if any). */ if(ReadArgs(ARGTEMPLATE,(LONG *)ArgArray,ArgsPtr)) { /* 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); FreeDosObject(DOS_RDARGS,ArgsPtr); FreeVec(ArgArray); CloseLibrary(DOSBase); return(RETURN_OK); } /* Are we to use a special settings path? */ if(ArgArray[ARG_SETTINGS]) { ConfigPath = ThePath; strcpy(ThePath,ArgArray[ARG_SETTINGS]); } /* We are to keep our links to * the Shell. */ if(ArgArray[ARG_KEEPIO]) { BYTE OldPri = ThisProcess -> pr_Task . tc_Node . ln_Pri; /* Do we have enough stack space available? */ if(((struct CommandLineInterface *)BADDR(ThisProcess -> pr_CLI)) -> cli_DefaultStack < 4096) { Printf("\33[1mterm:\33[0m %s.\a\n","Sorry, the Shell stack must be at least 16384 bytes large"); FreeArgs(ArgsPtr); FreeDosObject(DOS_RDARGS,ArgsPtr); FreeVec(ArgArray); CloseLibrary(DOSBase); return(RETURN_FAIL); } /* Open our resources and * squeak on failure. */ if(Result = OpenAll(ConfigPath)) { if(Result[0]) Printf("\33[1mterm:\33[0m %s!\a\n",Result); CloseAll(); FreeArgs(ArgsPtr); FreeDosObject(DOS_RDARGS,ArgsPtr); FreeVec(ArgArray); CloseLibrary(DOSBase); 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); FreeDosObject(DOS_RDARGS,ArgsPtr); FreeVec(ArgArray); /* Restore old priority. */ SetTaskPri(ThisProcess,(LONG)OldPri); /* Terminate execution. */ CloseAll(); CloseLibrary(DOSBase); return(RETURN_OK); } FreeArgs(ArgsPtr); } else { PrintFault(IoErr(),"term"); FreeDosObject(DOS_RDARGS,ArgsPtr); FreeVec(ArgArray); CloseLibrary(DOSBase); return(RETURN_ERROR); } FreeDosObject(DOS_RDARGS,ArgsPtr); } FreeVec(ArgArray); /* Create a new process from our code. */ if(!SegmentSplit("term main process",0,16384,HandleInput)) { Printf("\33[1mterm:\33[0m Failed to create new process!\a\n"); CloseAll(); CloseLibrary(DOSBase); return(RETURN_FAIL); } } else { Printf("\33[1mterm:\33[0m Failed to allocate argument vectors!\a\n"); CloseLibrary(DOSBase); return(RETURN_FAIL); } } else { LONG StackSize; StackSize = (LONG)SysBase -> ThisTask -> tc_SPUpper - (LONG)SysBase -> ThisTask -> tc_SPLower; if(StackSize < 16384) { if(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",37)) { MyEasyRequest(NULL,"`term' has a problem:\nThe current stack size of %ld bytes is too low,\nplease edit the icon file to use at least\n16384 bytes and restart the proram.","Continue",StackSize); CloseLibrary(IntuitionBase); } if(DOSBase) CloseLibrary(DOSBase); Forbid(); ReplyMsg((struct Message *)WBenchMsg); return(RETURN_FAIL); } else { CurrentDir(WBenchMsg -> sm_ArgList -> wa_Lock); /* Open icon.library, we want to take a * look at the icon. */ if(IconBase = OpenLibrary("icon.library",0)) { struct DiskObject *Icon; /* Try to read the icon file. */ if(Icon = GetDiskObject(WBenchMsg -> sm_ArgList -> wa_Name)) { /* Look for a `Settings' tooltype. */ if(ConfigPath = FindToolType(Icon -> do_ToolTypes,"SETTINGS")) { /* Remember the path and continue. */ strcpy(ThePath,ConfigPath); ConfigPath = ThePath; } /* Free the icon. */ FreeDiskObject(Icon); } /* Close the library. */ CloseLibrary(IconBase); IconBase = NULL; } /* Initialize this, so OpenAll will work with * correct data. */ TermPort = (struct TermPort *)FindPort("term Port"); /* We were called from Workbench. */ if(Result = OpenAll(ConfigPath)) { if(IntuitionBase && Result[0]) MyEasyRequest(NULL,LocaleString(MSG_GLOBAL_TERM_HAS_A_PROBLEM_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT),Result); CloseAll(); } else HandleInput(); } } return(RETURN_OK); } /* HandleInput(): * * This is our main input loop (check window & serial). */ VOID __saveds HandleInput() { ULONG SignalSet = NULL,SavageSignals = NULL; ThisProcess = (struct Process *)SysBase -> ThisTask; /* Open the resources we need. */ if(!IntuitionBase) { UBYTE *Result; if(Result = OpenAll(ConfigPath)) { if(IntuitionBase && Result[0]) MyEasyRequest(NULL,LocaleString(MSG_GLOBAL_TERM_HAS_A_PROBLEM_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT),Result); CloseAll(); return; } } BumpWindow(Window); /* Set up the public screen data. */ PubScreenStuff(); /* Change program priority. */ SetTaskPri(ThisProcess,(LONG)Config . Priority); BlockWindows(); /* Load the phone book. */ LoadPhonebook(LastPhone); /* Show our business card. */ if(ShowInfo(TRUE)) SignalSet |= SIG_REXX; ReleaseWindows(); /* Initialize the modem. */ SerialCommand(Config . ModemInit); /* Execute the startup macro (if any). */ if(Config . StartupMacro[0]) SerialCommand(Config . StartupMacro); LogAction(LocaleString(MSG_TERMMAIN_LOGMSG_PROGRAM_STARTED_TXT),TermName,TermDate); /* Go into input loop... */ Loop: while(!MainTerminated) { /* Is the serial write request available? */ if((SignalSet & SIG_CHECK) && WriteRequest) { /* Query serial status. */ WriteRequest -> IOSer . io_Command = SDCMD_QUERY; DoIO(WriteRequest); /* Is the carrier detect signal * still present? */ if(WriteRequest -> io_Status & (1 << 5)) { WasOnline = TRUE; Online = FALSE; } } /* If no longer online, get back to the * previous configuration. */ if(!Online) { BYTE ShowRate = TRUE; if(WasOnline) { StopCall(FALSE); SetDialMenu(TRUE); /* Execute logoff macro. */ if(Config . LogoffMacro[0]) SerialCommand(Config . LogoffMacro); /* Clear the password. */ Password[0] = 0; UserName[0] = 0; WasOnline = FALSE; } ChosenEntry = NULL; /* Previous configuration available? */ if(BackupConfig) { /* Remember old configuration. */ PrivateConfig = Config; /* Copy configuration. */ memcpy(&Config,BackupConfig,sizeof(struct Configuration)); /* Set up new configuration. */ ConfigSetup(); /* Free old configuration. */ FreeVec(BackupConfig); BackupConfig = NULL; /* Don't show the rate yet. */ ShowRate = FALSE; } if(CurrentPay && ShowRate) { /* Display how much we expect * the user will have to pay for * this call. */ ConWrites(LocaleString(MSG_TERMMAIN_THIS_CALL_WILL_COST_YOU_TXT),CreateSum(CurrentPay,TRUE)); CurrentPay = 0; } } /* Take care of external terminal emulation library. */ if(SignalSet & XEM_Signal) { if(!XEmulatorSignal(XEM_IO,SignalSet)) { CloseEmulator(); ResetDisplay = TRUE; } } /* A SIG_CLIP will cause us to transmit the current contents of * the clipboard... */ if(SignalSet & SIG_CLIP) { if(!ClipInput) { if(!OpenClip()) ClipInput = ClipXerox = TRUE; else ClipInput = ClipXerox = FALSE; } } /* Loop & check until the dust has settled. */ if(SignalSet & (SIG_WINDOW | SavageSignals | SIG_CLIP)) while(HandleWindow() || HandleSerial() || HandlePacket() || HandleReview()); /* Remove audio request. */ if(SignalSet & SIG_AUDIO) ClearAudio(); /* Check if we are to prompt the user for * ZModem upload type. */ if(UsesZModem) { if(FlowInfo . ZModemUpload && XProtocolBase) { FlowInit(); if(Config . AutoUpload) { BlockWindows(); switch(UploadPanel()) { case UPLOAD_TEXT: BinaryTransfer = FALSE; if(!StartXprSend(TRANSFER_TEXT)) SerWrite(ZModemCancel,20); break; case UPLOAD_BINARY: BinaryTransfer = TRUE; if(!StartXprSend(TRANSFER_BINARY)) SerWrite(ZModemCancel,20); break; case UPLOAD_IGNORE: break; case UPLOAD_ABORT: SerWrite(ZModemCancel,20); break; } ReleaseWindows(); } } } /* Make the user notice not too obvious events. */ if(FlowInfo . Changed && (FlowInfo . Voice || FlowInfo . Ring || FlowInfo . Connect)) { if(!Online) { WakeUp(Window); if(FlowInfo . Voice) { ConWrites(LocaleString(MSG_TERMMAIN_INCOMING_VOIC_CALL_TXT)); Say(LocaleString(MSG_TERMMAIN_SAY_INCOMING_VOICE_CALL_TXT)); } if(FlowInfo . Ring) { ConWrites(LocaleString(MSG_TERMMAIN_INCOMING_CALL_TXT)); Say(LocaleString(MSG_GLOBAL_INCOMING_CALL_TXT)); } if(FlowInfo . Connect) { Online = TRUE; BaudPending = FALSE; SetDialMenu(FALSE); } } FlowInit(); } /* Check for rexx messages to be processed. */ if(SignalSet & SIG_REXX) { HandleRexx(); if(MainTerminated) break; } /* Iconify the program? */ if(DoIconify) { BYTE Released = FALSE; /* Set the wait mouse pointer... */ BlockWindows(); /* Open workbench.library. */ if(WorkbenchBase = OpenLibrary("workbench.library",0)) { /* Open icon.library. */ if(IconBase = OpenLibrary("icon.library",0)) { struct DiskObject *Icon = NULL; /* Get the program icon. */ if(WBenchMsg) { if(WBenchMsg -> sm_ArgList) { if(WBenchMsg -> sm_ArgList -> wa_Name) Icon = GetDiskObjectNew(WBenchMsg -> sm_ArgList -> wa_Name); } } /* No icon? Use the default name. */ if(!Icon) Icon = GetDiskObjectNew("term"); /* Did we get any icon? */ if(Icon) { /* Not a tool icon? */ if(Icon -> do_Type != WBTOOL) { /* Get rid of it... */ FreeDiskObject(Icon); /* Get the default tool icon. */ Icon = GetDefDiskObject(WBTOOL); } } else { /* Get the default tool icon. */ Icon = GetDefDiskObject(WBTOOL); } /* Did we get an icon? */ if(Icon) { struct MsgPort *IconPort; /* Default icon position. */ Icon -> do_CurrentX = NO_ICON_POSITION; Icon -> do_CurrentY = NO_ICON_POSITION; /* Create the Workbench reply port. */ if(IconPort = CreateMsgPort()) { struct AppIcon *AppIcon; /* Add the application icon. */ if(AppIcon = AddAppIcon(0,0,TermIDString,IconPort,NULL,Icon,NULL)) { BYTE IconTerminated = FALSE; struct AppMessage *AppMessage; BYTE HadBuffer = BufferProcess ? TRUE : FALSE; UBYTE *String,*Error; /* Release the window. */ Released = TRUE; ReleaseWindows(); /* Remove the display buffer. */ if(BufferProcess) { Signal(BufferProcess,SIGBREAKF_CTRL_C); Wait(SIGBREAKF_CTRL_C); } /* Reset and release the serial driver. */ ClearSerial(); DeleteSerial(); /* Close the display. full stop. */ DeleteDisplay(); /* Wait for double-click. */ IconLoop: while(!IconTerminated) { ULONG SignalSet = Wait((1 << IconPort -> mp_SigBit) | SIG_REXX); if(SignalSet & (1 << IconPort -> mp_SigBit)) { /* Pick up application messages. */ while(AppMessage = (struct AppMessage *)GetMsg(IconPort)) { /* Received a double-click? */ IconTerminated = TRUE; ReplyMsg(AppMessage); } } /* Wake up if ARexx command received. */ if(SignalSet & SIG_REXX) IconTerminated = TRUE; } /* The buffer process was running before we * went into iconified state, so let's try to * conjure it up again. */ if(HadBuffer) LaunchBuffer(); /* Open the serial driver. */ if(Error = CreateSerial()) { DeleteSerial(); switch(MyEasyRequest(NULL,LocaleString(MSG_GLOBAL_TERM_HAS_A_PROBLEM_TXT),LocaleString(MSG_TERMMAIN_ICONIFY_IGNORE_QUIT_TXT),Error)) { case 1: goto IconLoop; case 2: break; case 0: MainTerminated = TRUE; } } else { if(SerialMessage) { MyEasyRequest(Window,LocaleString(MSG_GLOBAL_TERM_HAS_A_PROBLEM_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT),SerialMessage); SerialMessage = NULL; } } /* Create the display. */ if(String = CreateDisplay(FALSE)) { if(MyEasyRequest(NULL,LocaleString(MSG_GLOBAL_TERM_HAS_A_PROBLEM_TXT),LocaleString(MSG_TERMMAIN_ICONIFY_QUIT_TXT),String)) { ClearSerial(); DeleteSerial(); IconTerminated = FALSE; goto IconLoop; } else MainTerminated = FALSE; } else { BumpWindow(Window); PubScreenStuff(); } /* Remove the application icon. */ RemoveAppIcon(AppIcon); /* Reply pending messages. */ while(AppMessage = (struct AppMessage *)GetMsg(IconPort)) ReplyMsg(AppMessage); } else MyEasyRequest(Window,LocaleString(MSG_TERMMAIN_FAILED_TO_ADD_APPLICATION_ICON_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT)); DeleteMsgPort(IconPort); } else MyEasyRequest(Window,LocaleString(MSG_GLOBAL_FAILED_TO_CREATE_MSGPORT_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT)); FreeDiskObject(Icon); } else MyEasyRequest(Window,LocaleString(MSG_TERMMAIN_FAILED_TO_OPEN_TOOL_ICON_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT)); CloseLibrary(IconBase); } else MyEasyRequest(Window,LocaleString(MSG_TERMMAIN_FAILED_TO_OPEN_ICON_LIBRARY_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT)); CloseLibrary(WorkbenchBase); } else MyEasyRequest(Window,LocaleString(MSG_TERMMAIN_FAILED_TO_OPEN_WORKBENCH_LIBRARY_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT)); if(!Released) ReleaseWindows(); /* Finished! */ DoIconify = FALSE; /* Just a check for safety. */ HandleRexx(); } /* Reset the serial driver? */ if(ResetSerial) { UBYTE *Error; ClearSerial(); DeleteSerial(); BlockWindows(); OpenLoop: if(Error = CreateSerial()) { APTR OldPtr = ThisProcess -> pr_WindowPtr; DeleteSerial(); ThisProcess -> pr_WindowPtr = (APTR)Window; switch(MyEasyRequest(Window,LocaleString(MSG_GLOBAL_TERM_HAS_A_PROBLEM_TXT),LocaleString(MSG_TERMMAIN_RETRY_IGNORE_QUIT_TXT),Error)) { case 1: goto OpenLoop; case 2: break; case 0: MainTerminated = TRUE; } ThisProcess -> pr_WindowPtr = OldPtr; } else { if(SerialMessage) { MyEasyRequest(Window,LocaleString(MSG_GLOBAL_TERM_HAS_A_PROBLEM_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT),SerialMessage); SerialMessage = NULL; } ResetSerial = FALSE; } 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; ClearSerial(); DeleteSerial(); BlockWindows(); if(MyEasyRequest(Window,LocaleString(MSG_TERMMAIN_UNIT_RESET_AND_RELEASED_TXT),LocaleString(MSG_TERMMAIN_RETURN_QUIT_TXT),Config . SerialDevice,Config . UnitNumber)) { UBYTE *Error; OpenIt: if(Error = CreateSerial()) { DeleteSerial(); switch(MyEasyRequest(Window,LocaleString(MSG_GLOBAL_TERM_HAS_A_PROBLEM_TXT),LocaleString(MSG_TERMMAIN_RETRY_IGNORE_QUIT_TXT),Error)) { case 1: goto OpenIt; case 2: break; case 0: MainTerminated = TRUE; } } else { if(SerialMessage) { MyEasyRequest(Window,LocaleString(MSG_GLOBAL_TERM_HAS_A_PROBLEM_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT),SerialMessage); SerialMessage = NULL; } } } else MainTerminated = TRUE; ReleaseSerial = FALSE; ThisProcess -> pr_WindowPtr = OldPtr; ReleaseWindows(); } /* Somebody told us to re-open the display * (changed the terminal emulation/colour * mode). */ if(ResetDisplay) { if(!DisplayReset()) MainTerminated = TRUE; } if(Blocking && !MainTerminated) { Blocking = FALSE; continue; } /* Set up the signal bits to wait for. */ SavageSignals = XEM_Signal; /* The serial line is active. */ if(Status != STATUS_HOLDING && ReadPort) SavageSignals |= SIG_SERIAL; /* The packet window is still open. */ if(PacketWindow) SavageSignals |= SIG_PACKET; /* The review buffer window is open. */ if(ReviewPort) SavageSignals |= SIG_REVIEW; /* Wait for input events to occur. */ SignalSet = Wait(SIG_WINDOW | SIG_REXX | SIG_AUDIO | SIG_CLIP | SIG_CHECK | SavageSignals); } /* Shut down the transfer panel if any. */ if(TransferWindow) { if(DidTransfer) { if(SendAbort && UsesZModem) SerWrite(ZModemCancel,20); } DeleteTransferPanel(); } /* 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,LocaleString(MSG_GLOBAL_TERM_HAS_A_PROBLEM_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT),LocaleString(MSG_TERMMAIN_CANNOT_CLOSE_SCREEN_YET_TXT)); ReleaseWindows(); MainTerminated = FALSE; goto Loop; } } UnlockPubScreenList(); } /* Send the modem exit command, shut down the * serial.device and close all resources. */ SerialCommand(Config . ModemExit); ClearSerial(); LogAction(LocaleString(MSG_TERMMAIN_LOGMSG_PROGRAM_TERMINATED_TXT)); Say(LocaleString(MSG_TERMMAIN_BYE_BYE_TXT)); 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; LONG MouseX,MouseY,Len; struct Gadget *Gadget; UBYTE Char,InputBuffer[257]; struct Window *IDCMPWindow; BYTE Result = FALSE; if(ClipInput) { WORD Len = GetClip(InputBuffer,256,FALSE); if(Len < 0) { CloseClip(); ClipInput = FALSE; if(ClipXerox) { switch(Config . SendCR) { case CR_IGNORE: break; case CR_ASCR: SerWrite("\r",1); break; case CR_ASCRLF: SerWrite("\r\n",2); break; } } ClipXerox = FALSE; } else { if(Len > 0) { /* Is a send-delay enabled? */ if(Config . CharDelay || Config . LineDelay) { WORD i; /* Run down the buffer... */ for(i = 0 ; i < Len ; i++) { /* What kind of delay * are we to provide? */ switch(InputBuffer[i]) { case '\r': if(Config . LineDelay) WaitTime(Config . LineDelay / 100,(Config . LineDelay % 100) * 10000); break; default: if(Config . CharDelay) WaitTime(Config . CharDelay / 100,(Config . CharDelay % 100) * 10000); break; } SerWrite(&InputBuffer[i],1); } } else SerWrite(InputBuffer,Len); } Result = TRUE; } } /* Any news in the mail? */ if(Massage = (struct IntuiMessage *)GT_GetIMsg(Window -> UserPort)) { /* Pick up the pieces. */ Class = Massage -> Class; Code = Massage -> Code; Qualifier = Massage -> Qualifier; MouseX = Massage -> MouseX; MouseY = Massage -> MouseY; Gadget = (struct Gadget *)Massage -> IAddress; IDCMPWindow = Massage -> IDCMPWindow; if(Class == IDCMP_RAWKEY) { /* Perform key conversion. */ if(XEmulatorBase) { if(Len = XEmulatorUserMon(XEM_IO,InputBuffer,256,Massage)) Char = InputBuffer[0]; } else Char = KeyConvert(Massage,InputBuffer,&Len); } GT_ReplyIMsg(Massage); if(IDCMPWindow == InfoWindow) { switch(Class) { case IDCMP_CLOSEWINDOW: CloseInfoWindow(); return(Result); case IDCMP_MOUSEBUTTONS:if(!(Code & IECODE_UP_PREFIX)) RefreshInfoWindow(); return(Result); default: break; } } /* The following messages probably * originate from the fast! macro * panel. */ if(IDCMPWindow == FastWindow) { struct MacroNode *Node; switch(Class) { /* Close the window. */ case IDCMP_CLOSEWINDOW: CloseFastWindow(); return(Result); /* Window size has changed for some reason. */ case IDCMP_NEWSIZE: if(FastWindow -> Height != Screen -> WBorTop + Screen -> Font -> ta_YSize + 1) { RefreshFastWindow(FastWindow -> Height); RefreshWindowFrame(FastWindow); } return(Result); case IDCMP_GADGETUP: if(Node = GetFastMacro(Code)) { if(Node -> mn_Code[0]) SerialCommand(Node -> mn_Code); } return(Result); case IDCMP_MOUSEBUTTONS:return(Result); default: break; } } /* This looks like a raw, or better, now cooked key. */ if(Class == IDCMP_RAWKEY && Len) { if(ClipInput) { CloseClip(); ClipInput = ClipXerox = FALSE; } /* 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(!IsBlank(Char)) { WORD i; UBYTE c; /* Run down the contents of * the key result string. */ for(i = 0 ; i < Len ; i++) { if(Config . StripBit8) c = InputBuffer[i] & 0x7F; else c = InputBuffer[i]; /* Restart serial line * after XON. */ if(Status == STATUS_HOLDING) { if(c == XOF) { SerWrite(&c,1); Status = STATUS_READY; } else DoBeep(); } else { /* Convert chars * as approriate. */ if(c == '\n') { switch(Config . SendLF) { case LF_IGNORE: break; case LF_ASLF: goto SendIt; case LF_ASLFCR: SerWrite("\n\r",2); break; } continue; } if(c == '\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(c == XON) { if(Config . PassThrough) { SerWrite(&c,1); continue; } else { if(Config . xONxOFF) Status = STATUS_HOLDING; } } /* Restart in/output. */ if(c == XOF) { if(Config . PassThrough) { SerWrite(&c,1); continue; } } /* Convert special * Amiga characters into * alien IBM dialect. */ SendIt: if(Config . Font == FONT_IBM) { if(IBMConversion[c]) SerWrite(&IBMConversion[c],1); else SerWrite(&c,1); } else SerWrite(&c,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 HandleCursor(Char); } } /* Capture characters from the main * screen. */ if(Class == IDCMP_MOUSEBUTTONS && !(Code & IECODE_UP_PREFIX)) { if(Code == SELECTDOWN && (Qualifier & (IEQUALIFIER_LALT|IEQUALIFIER_RALT)) && (Qualifier & IEQUALIFIER_LEFTBUTTON)) { WORD DeltaX = MouseX / TextFontWidth - CursorX, DeltaY = MouseY / TextFontHeight - CursorY; if(DeltaX || DeltaY) { if(DeltaX > 0) { DeltaX++; while(DeltaX--) SerWrite("\33[C",3); } if(DeltaX < 0) { while(DeltaX++) SerWrite("\33[D",3); } if(DeltaY > 0) { DeltaY++; while(DeltaY--) SerWrite("\33[B",3); } if(DeltaY < 0) { while(DeltaY++) SerWrite("\33[A",3); } } } else { if(!XEmulatorBase || Config . Emulation != EMULATION_EXTERNAL) { BYTE SingleChar,Xerox; Marking = TRUE; /* 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(Code == MIDDLEDOWN || (Qualifier & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT))) Xerox = TRUE; else Xerox = FALSE; MarkClip(SingleChar,Xerox); ReportMouse(FALSE,Window); while(Massage = (struct IntuiMessage *)GT_GetIMsg(Window -> UserPort)) GT_ReplyIMsg(Massage); Marking = FALSE; return(Result); } } } /* A menu item was selected. */ SkipIt: if(Class == IDCMP_MENUPICK) HandleMenu(Code,Qualifier); return(TRUE); } return(Result); } /* TransferCleanup(): * * We did a file transfer (auto-download?) and * will need to close the transfer window. */ VOID TransferCleanup() { if(DidTransfer) { WakeUp(TransferWindow); WaitTime(2,0); DeleteTransferPanel(); if(SendAbort && UsesZModem) SerWrite(ZModemCancel,20); SendAbort = FALSE; if(Config . DownloadMacro[0]) SerialCommand(Config . DownloadMacro); Say(LocaleString(MSG_GLOBAL_TRANSFER_COMPLETED_TXT)); DidTransfer = FALSE; } else { WaitTime(3,0); DeleteTransferPanel(); } ReleaseWindows(); } /* HandleSerial(): * * Handle the data coming in from the serial line. */ BYTE HandleSerial() { if(ReadPort && !ReleaseSerial && !MainTerminated) { BYTE Return = FALSE; if(HostReadBuffer) { LONG Length; if(Length = XProtocolHostMon(XprIO,HostReadBuffer,0,Config . SerBuffSize)) { ConProcess(ReadBuffer,Length); Return = TRUE; } } /* We are XON'ed or the serial line was shut down. */ if(Status != STATUS_HOLDING && !Blocking) { register ULONG MaxReadSize = Config . SerBuffSize; if(MaxReadSize > ReadRequest -> io_Baud / 4) MaxReadSize = ReadRequest -> io_Baud / 4; /* Any news? */ if(CheckIO(ReadRequest)) { LONG Length; if(WaitIO(ReadRequest)) { ReadRequest -> IOSer . io_Command = CMD_READ; ReadRequest -> IOSer . io_Data = ReadBuffer; ReadRequest -> IOSer . io_Length = 1; SetSignal(0,SIG_SERIAL); SendIO(ReadRequest); return(Return); } BytesIn++; if(XProtocolBase) { /* Process the data if necessary (XPR-function). */ if(TransferBits & XPRS_HOSTMON) { LONG Result = XProtocolHostMon(XprIO,ReadBuffer,1,1); if(TransferWindow) TransferCleanup(); if(!Result) 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 > MaxReadSize) Length = MaxReadSize; ReadRequest -> IOSer . io_Command = CMD_READ; ReadRequest -> IOSer . io_Data = ReadBuffer; ReadRequest -> IOSer . io_Length = Length; if(!DoIO(ReadRequest)) { BytesIn += ReadRequest -> IOSer . io_Actual; if(XProtocolBase) { /* Process the serial data if * necessary (XPR-stuff). */ if(TransferBits & XPRS_HOSTMON) { Length = XProtocolHostMon(XprIO,ReadBuffer,Length,Config . SerBuffSize); if(TransferWindow) TransferCleanup(); if(!Length) { 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; SetSignal(0,SIG_SERIAL); SendIO(ReadRequest); return(TRUE); } } return(Return); } return(FALSE); } /* HandleCode(ULONG Code,ULONG Qualifier,struct MenuItem *MenuItem): * * Handle each function associated with a menu code. */ VOID HandleCode(ULONG Code,ULONG Qualifier,struct MenuItem *MenuItem) { STATIC UBYTE NumberBuffer[256]; struct FileRequester *FileRequest; UBYTE DummyBuffer[256], *DummyChar; BYTE OldStatus = Status; BPTR SomeFile; APTR OldPtr; switch(Code) { /* Save screen as IFF-ILBM file. */ case MEN_SAVE_AS_PICTURE: BlockWindows(); if(FileRequest = GetFile(LocaleString(MSG_TERMMAIN_SAVE_SCREEN_IFF_TXT),"","",DummyBuffer,NULL,TRUE,FALSE,FALSE,LocaleString(MSG_GLOBAL_SAVE_TXT))) { if(!SaveRPort(&Screen -> RastPort,VPort,0,Window -> TopEdge,Window -> Width,Window -> Height,Screen -> Width,Screen -> Height,FALSE,DummyBuffer)) MyEasyRequest(Window,LocaleString(MSG_GLOBAL_FAILED_TO_SAVE_SCREEN_TO_FILE_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT),DummyBuffer); FreeAslRequest(FileRequest); } ReleaseWindows(); break; /* Save screen as ASCII file. */ case MEN_SAVE_AS_TEXT: BlockWindows(); if(FileRequest = GetFile(LocaleString(MSG_TERMMAIN_SAVE_SCREEN_ASCII_TXT),"","",DummyBuffer,NULL,TRUE,FALSE,FALSE,LocaleString(MSG_GLOBAL_SAVE_TXT))) { if(GetFileSize(DummyBuffer)) { switch(MyEasyRequest(Window,LocaleString(MSG_GLOBAL_FILE_ALREADY_EXISTS_TXT),LocaleString(MSG_GLOBAL_CREATE_APPEND_CANCEL_TXT),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,LocaleString(MSG_GLOBAL_FAILED_TO_SAVE_SCREEN_TO_FILE_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT),DummyBuffer); else { if(SomeFile != ~0) { WORD i,j; UBYTE *Buffer; for(i = 0 ; i < RasterHeight ; i++) { Buffer = &Raster[i * RasterWidth]; j = LastColumn; while(j >= 0 && Buffer[j] == ' ') j--; if(j >= 0) { if(!FWrite(SomeFile,Buffer,j + 1,1)) break; } if(!FWrite(SomeFile,"\n",1,1)) break; } Close(SomeFile); SetProtection(DummyBuffer,FIBF_EXECUTE); } } FreeAslRequest(FileRequest); } ReleaseWindows(); break; /* Print the screen (pure ASCII). */ case MEN_PRINT_SCREEN: BlockWindows(); if(!XEmulatorBase || Config . Emulation != EMULATION_EXTERNAL) PrintSomething(PRINT_SCREEN); else MyEasyRequest(Window,LocaleString(MSG_TERMMAIN_NO_DATA_TO_PRINT_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT)); ReleaseWindows(); break; /* Print the clipboard contents. */ case MEN_PRINT_CLIP: BlockWindows(); PrintSomething(PRINT_CLIP); ReleaseWindows(); break; /* Open/close the terminal capture file. */ case MEN_CAPTURE_TO_FILE: if(FileCapture) { BufferClose(FileCapture); MenuItem -> Flags &= ~CHECKED; FileCapture = NULL; if(!GetFileSize(CaptureName)) DeleteFile(CaptureName); else SetProtection(CaptureName,FIBF_EXECUTE); } else { BlockWindows(); if(!CaptureName[0]) { strcpy(CaptureName,Config . CapturePath); if(!AddPart(CaptureName,LocaleString(MSG_DIALPANEL_CAPTURE_NAME_TXT),256)) CaptureName[0] = 0; } strcpy(DummyBuffer,CaptureName); DummyChar = PathPart(DummyBuffer); *DummyChar = 0; if(FileRequest = GetFile(LocaleString(MSG_TERMMAIN_CAPTURE_TO_DISK_TXT),DummyBuffer,FilePart(CaptureName),DummyBuffer,NULL,TRUE,FALSE,FALSE,LocaleString(MSG_GLOBAL_OPEN_TXT))) { if(GetFileSize(DummyBuffer)) { switch(MyEasyRequest(Window,LocaleString(MSG_GLOBAL_FILE_ALREADY_EXISTS_TXT),LocaleString(MSG_GLOBAL_CREATE_APPEND_CANCEL_TXT),DummyBuffer)) { case 1: FileCapture = BufferOpen(DummyBuffer,"w"); break; case 2: FileCapture = BufferOpen(DummyBuffer,"a"); break; case 0: MenuItem -> Flags &= ~CHECKED; goto CapSkip; } } else FileCapture = BufferOpen(DummyBuffer,"w"); if(!FileCapture) { MyEasyRequest(Window,LocaleString(MSG_GLOBAL_ERROR_OPENING_FILE_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT),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_CAPTURE_TO_PRINTER: if(PrinterCapture) ClosePrinterCapture(TRUE); else OpenPrinterCapture(FALSE); break; /* Iconify the program. */ case MEN_ICONIFY: DoIconify = TRUE; break; /* Say who we are. */ case MEN_ABOUT: BlockWindows(); ShowInfo(FALSE); ReleaseWindows(); break; /* Terminate the program. */ case MEN_QUIT: if(Qualifier & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT)) MainTerminated = TRUE; else { BlockWindows(); OldPtr = ThisProcess -> pr_WindowPtr; ThisProcess -> pr_WindowPtr = (APTR)Window; if(MyEasyRequest(Window,LocaleString(MSG_TERMMAIN_REALLY_QUIT_TXT),LocaleString(MSG_GLOBAL_YES_NO_TXT))) MainTerminated = TRUE; ThisProcess -> pr_WindowPtr = OldPtr; ReleaseWindows(); } break; /* Feed the contents of the clipboard * into the input stream. */ case MEN_PASTE: if(!OpenClip()) ClipInput = TRUE; else ClipInput = FALSE; break; /* Execute an AmigaDOS command. */ case MEN_EXECUTE_DOS_COMMAND: BlockWindows(); DummyBuffer[0] = 0; /* Enter the name of the command. */ if(GetString(LocaleString(MSG_TERMMAIN_ENTER_AMIGADOS_COMMAND_TXT),DummyBuffer)) SendAmigaDOSCommand(DummyBuffer); ReleaseWindows(); break; /* Execute an ARexx script command. */ case MEN_EXECUTE_REXX_COMMAND: BlockWindows(); DummyBuffer[0] = 0; /* Get the rexx file name/program. */ if(GetString(LocaleString(MSG_TERMMAIN_ENTER_AREXX_COMMAND_TXT),DummyBuffer)) SendARexxCommand(DummyBuffer); ReleaseWindows(); break; /* Set the name we will use to open the * default console output window for * AmigaDOS commands and ARexx scripts. */ case MEN_SET_CONSOLE: BlockWindows(); if(xpr_gets(LocaleString(MSG_TERMMAIN_SET_CONSOLE_WINDOW_TXT),WindowName)) SetEnvDOS("TERMWINDOW",WindowName); ReleaseWindows(); break; /* Open the phonebook and dial the * list of entries the user will select. */ case MEN_PHONEBOOK: BlockWindows(); while(PhonePanel()) { if(!DialPanel()) { Status = OldStatus; break; } Status = OldStatus; } ReleaseWindows(); break; /* Redial those dial list entries which * we were unable to connect. */ case MEN_REDIAL: BlockWindows(); if(DialList) { if(DialList -> lh_Head -> ln_Succ) { DialPanel(); Status = OldStatus; } else MyEasyRequest(Window,LocaleString(MSG_TERMMAIN_CURRENT_DIALING_LIST_IS_EMPTY_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT)); } else MyEasyRequest(Window,LocaleString(MSG_TERMMAIN_CURRENT_DIALING_LIST_IS_EMPTY_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT)); ReleaseWindows(); break; /* Dial a single number. */ case MEN_DIAL_NUMBER: BlockWindows(); if(xpr_gets(LocaleString(MSG_TERMMAIN_ENTER_PHONE_NUMBER_TXT),NumberBuffer)) { if(NumberBuffer[0]) { struct List *LocalList; if(LocalList = (struct List *)AllocVec(sizeof(struct List),MEMF_ANY|MEMF_CLEAR)) { struct PhoneNode *DialNode; NewList(LocalList); if(DialNode = (struct PhoneNode *)AllocVec(sizeof(struct PhoneNode),MEMF_ANY|MEMF_CLEAR)) { DialNode -> VanillaNode . ln_Name = (UBYTE *)NumberBuffer; AddTail(LocalList,&DialNode -> VanillaNode); FreeDialList(); DialList = LocalList; DialPanel(); Status = OldStatus; } else FreeVec(LocalList); } } } ReleaseWindows(); break; /* Play a touch-tone phone number. */ case MEN_PLAY_NUMBER: BlockWindows(); if(xpr_gets(LocaleString(MSG_TERMMAIN_ENTER_PHONE_NUMBER_TO_PLAY_TXT),NumberBuffer)) { if(!ToneDial(NumberBuffer)) MyEasyRequest(NULL,LocaleString(MSG_GLOBAL_TERM_HAS_A_PROBLEM_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT),LocaleString(MSG_GLOBAL_FAILED_TO_ALLOCATE_RESOURCES_FOR_PLAYING_TXT)); else DeleteTone(); } ReleaseWindows(); break; /* Send a break across the serial line. */ case MEN_SEND_BREAK: if(WriteRequest) { Status = STATUS_BREAKING; WriteRequest -> IOSer . io_Command = SDCMD_BREAK; DoIO(WriteRequest); Status = OldStatus; } break; /* Hang up the phone line. */ case MEN_HANG_UP: BlockWindows(); Status = STATUS_HANGUP; /* Are we to drop the DTR line * before sending the hangup * string? */ if(Config . DropDTR) { /* Let's be nice and try to transmit the * `drop the line' command before * trying to close and reopen the driver. */ WriteRequest -> IOSer . io_Command = SIOCMD_SETCTRLLINES; WriteRequest -> IOSer . io_Offset = SIOB_DTRF; WriteRequest -> IOSer . io_Length = 0; /* Transmit the command. */ if(!DoIO(WriteRequest)) { /* Wait a bit... */ WaitTime(1,0); /* Raise the line again. */ WriteRequest -> IOSer . io_Command = SIOCMD_SETCTRLLINES; WriteRequest -> IOSer . io_Offset = SIOB_DTRF; WriteRequest -> IOSer . io_Length = SIOB_DTRF; DoIO(WriteRequest); } else { /* Do it the standard way: close and reopen * the serial driver (the serial.device is * supposed to drop the DTR line when closed). */ if(!DropDTR()) { if(!MyEasyRequest(Window,LocaleString(MSG_TERMMAIN_FAILED_TO_REOPEN_UNIT_TXT),LocaleString(MSG_TERMMAIN_IGNORE_QUIT_TXT),Config . SerialDevice,Config . UnitNumber)) MainTerminated = TRUE; } } } /* Transmit the hangup command. */ SerialCommand(Config . ModemHangup); /* Reset to old status. */ Status = OldStatus; /* We are no longer online. */ Online = FALSE; /* Clear the password. */ Password[0] = 0; /* Clear the user name as well. */ UserName[0] = 0; /* Note the last action. */ LogAction(LocaleString(MSG_TERMMAIN_LOGMSG_HANG_UP_TXT)); ReleaseWindows(); /* Execute logoff macro. */ if(Config . LogoffMacro[0] && WasOnline) SerialCommand(Config . LogoffMacro); /* Update the logfile. */ StopCall(FALSE); /* Don't execute the logoff macro twice. */ WasOnline = FALSE; /* Enable the dialing functions. */ SetDialMenu(TRUE); break; /* Flush the serial buffers. */ case MEN_FLUSH_BUFFER: ClearSerial(); if(ReadRequest) { ReadRequest -> IOSer . io_Command = CMD_READ; ReadRequest -> IOSer . io_Data = ReadBuffer; ReadRequest -> IOSer . io_Length = 1; SetSignal(0,SIG_SERIAL); SendIO(ReadRequest); } break; /* Release the serial device for other * applications. */ case MEN_RELEASE_DEVICE: ReleaseSerial = TRUE; break; case MEN_UPLOAD_ASCII: BlockWindows(); if(ASCIISetup()) { StartXprSend(TRANSFER_ASCII); ASCIIShutdown(); } ReleaseWindows(); break; case MEN_DOWNLOAD_ASCII: BlockWindows(); if(ASCIISetup()) { StartXprReceive(TRANSFER_ASCII); ASCIIShutdown(); } ReleaseWindows(); break; case MEN_UPLOAD_TEXT: BlockWindows(); BinaryTransfer = FALSE; StartXprSend(TRANSFER_TEXT); BinaryTransfer = TRUE; ReleaseWindows(); break; case MEN_DOWNLOAD_TEXT: BlockWindows(); BinaryTransfer = FALSE; StartXprReceive(TRANSFER_TEXT); BinaryTransfer = TRUE; ReleaseWindows(); break; /* Edit and transfer a file. */ case MEN_EDIT_AND_UPLOAD_TEXT: BlockWindows(); if(!Config . Editor[0]) GetString(LocaleString(MSG_TERMMAIN_ENTER_NAME_OF_EDITOR_TO_USE_TXT),&Config . Editor[0]); if(Config . Editor[0]) { if(FileRequest = GetFile(LocaleString(MSG_TERMMAIN_EDIT_AND_TRANSFER_FILE_TXT),"","",DummyBuffer,NULL,FALSE,FALSE,FALSE,LocaleString(MSG_TERMMAIN_EDIT_TXT))) { UBYTE CompoundName[512]; strcpy(CompoundName,Config . Editor); strcat(CompoundName," "); strcat(CompoundName,DummyBuffer); SystemTags(CompoundName,TAG_DONE); BumpWindow(Window); FreeAslRequest(FileRequest); if(GetFileSize(DummyBuffer)) { BinaryTransfer = FALSE; switch(MyEasyRequest(Window,LocaleString(MSG_TERMMAIN_TRANSFER_FILE_AS_TXT),LocaleString(MSG_TERMMAIN_ASCII_UPLOAD_CANCEL_TXT),FilePart(DummyBuffer))) { case 1: if(ASCIISetup()) { SendTextFile(DummyBuffer); ASCIIShutdown(); } break; case 2: SendTextFile(DummyBuffer); break; case 0: break; } BinaryTransfer = TRUE; } } } ReleaseWindows(); break; case MEN_UPLOAD_BINARY: BlockWindows(); BinaryTransfer = TRUE; StartXprSend(TRANSFER_BINARY); ReleaseWindows(); break; /* Download some files. */ case MEN_DOWNLOAD_BINARY: BlockWindows(); BinaryTransfer = TRUE; StartXprReceive(TRANSFER_BINARY); ReleaseWindows(); break; /* Clear the contents of the scrollback * buffer. */ case MEN_CLEAR_BUFFER: if(Lines) { BlockWindows(); if(Qualifier & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT)) ClearBuffer(); else { if(MyEasyRequest(Window,LocaleString(MSG_TERMMAIN_BUFFER_STILL_HOLDS_LINES_TXT),LocaleString(MSG_GLOBAL_YES_NO_TXT),Lines)) ClearBuffer(); } UpdateReview(TRUE); ReleaseWindows(); } break; /* Display the scrollback buffer. * Notify the scrollback task or * fire it off if approriate. */ case MEN_DISPLAY_BUFFER: if(!LaunchBuffer()) { BlockWindows(); MyEasyRequest(Window,LocaleString(MSG_TERMMAIN_UNABLE_TO_CREATE_BUFFER_TASK_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT)); ReleaseWindows(); } break; /* Close the buffer display. */ case MEN_CLOSE_BUFFER: if(BufferProcess) { Signal(BufferProcess,SIGBREAKF_CTRL_C); Wait(SIGBREAKF_CTRL_C); } break; /* Is the buffer to be frozen? */ case MEN_FREEZE_BUFFER: if(MenuItem -> Flags & CHECKED) BufferFrozen = TRUE; else BufferFrozen = FALSE; break; /* Load the buffer contents from a file. */ case MEN_OPEN_BUFFER: BlockWindows(); if(FileRequest = GetFile(LocaleString(MSG_TERMMAIN_LOAD_BUFFER_TXT),"","",DummyBuffer,NULL,FALSE,FALSE,FALSE,LocaleString(MSG_GLOBAL_LOAD_TXT))) { if(GetFileSize(DummyBuffer)) { if(SomeFile = Open(DummyBuffer,MODE_OLDFILE)) { if(Lines) { switch(MyEasyRequest(Window,LocaleString(MSG_TERMMAIN_BUFFER_STILL_HOLDS_LINES_TXT),LocaleString(MSG_TERMMAIN_DISCARD_APPPEND_CANCEL_TXT),Lines)) { case 1: ClearBuffer(); break; case 2: break; case 0: Close(SomeFile); SomeFile = NULL; break; } } if(SomeFile) { LONG Len; LineRead(NULL,NULL,NULL); while(Len = LineRead(SomeFile,DummyBuffer,80)) StoreBuffer(DummyBuffer,Len); Close(SomeFile); } } } FreeAslRequest(FileRequest); } ReleaseWindows(); break; /* Save the contents of the scrollback * buffer to a file (line by line). */ case MEN_SAVE_BUFFER_AS: BlockWindows(); if(!Lines) MyEasyRequest(Window,LocaleString(MSG_GLOBAL_NOTHING_IN_THE_BUFFER_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT)); else { if(FileRequest = GetFile(LocaleString(MSG_TERMMAIN_SAVE_BUFFER_TXT),"","",DummyBuffer,NULL,TRUE,FALSE,FALSE,LocaleString(MSG_GLOBAL_SAVE_TXT))) { 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,LocaleString(MSG_GLOBAL_FILE_ALREADY_EXISTS_TXT),LocaleString(MSG_GLOBAL_CREATE_APPEND_CANCEL_TXT),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,LocaleString(MSG_GLOBAL_ERROR_OPENING_FILE_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT),DummyBuffer); else { LONG i,Len; /* Obtain the semaphore required * to gain access to the line buffer */ ObtainSemaphore(BufferSemaphore); for(i = 0 ; i < Lines ; i++) { Len = ((ULONG *)BufferLines[i])[-1]; if(Len) { if(FWrite(SomeFile,BufferLines[i],Len,1) != 1) break; } if(FPrintf(SomeFile,"\n") < 1) break; } ReleaseSemaphore(BufferSemaphore); Close(SomeFile); SetProtection(DummyBuffer,FIBF_EXECUTE); } FreeAslRequest(FileRequest); } } ReleaseWindows(); break; /* Simply clear the screen and move the * cursor to its home position. */ case MEN_CLEAR_SCREEN: if(XEmulatorBase && Config . Emulation == EMULATION_EXTERNAL) XEmulatorClearConsole(XEM_IO); else { EraseScreen("2J"); SetAbsolutePosition("H"); } break; /* Reset the current text rendering font. */ case MEN_RESET_FONT: if(XEmulatorBase && Config . Emulation == EMULATION_EXTERNAL) XEmulatorResetCharset(XEM_IO); else { CurrentFont = TextFont; SetFont(RPort,CurrentFont); } break; /* Reset the display styles and restore * the colours. */ case MEN_RESET_STYLES: if(XEmulatorBase && Config . Emulation == EMULATION_EXTERNAL) XEmulatorResetTextStyles(XEM_IO); else { SetAttributes("0m"); 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); SetWrMsk(RPort,0xFF); } break; /* Reset the whole terminal. */ case MEN_RESET_TERMINAL: if(XEmulatorBase && Config . Emulation == EMULATION_EXTERNAL) XEmulatorResetConsole(XEM_IO); else { DoCancel(); Reset(); } break; case MEN_SET_EMULATION: BlockWindows(); if(XEmulatorBase && Config . Emulation == EMULATION_EXTERNAL) { OptionTitle = LocaleString(MSG_TERMMAIN_EMULATION_PREFERENCES_TXT); XEmulatorOptions(XEM_IO); if(NewOptions) { SetEmulatorOptions(XEM_PREFS_SAVE); NewOptions = FALSE; } OptionTitle = NULL; } else EmulationPanel(&Config); ReleaseWindows(); break; /* Set the serial preferences. */ case MEN_SERIAL: BlockWindows(); if(SerialPanel(&Config)) ConfigSetup(); ReleaseWindows(); break; /* Set the modem preferences. */ case MEN_MODEM: BlockWindows(); if(ModemPanel(&Config)) FlowInit(); ReleaseWindows(); break; /* Set the screen preferences. */ case MEN_SCREEN: BlockWindows(); if(ScreenPanel(&Config)) ResetDisplay = TRUE; else PubScreenStuff(); if(memcmp(&PrivateConfig . Colours[0],&Config . Colours[0],sizeof(UWORD) * 16)) { switch(Config . ColourMode) { case COLOUR_EIGHT: CopyMem(&Config . Colours[0],&ANSIColours[0],16 * sizeof(UWORD)); break; case COLOUR_SIXTEEN: CopyMem(&Config . Colours[0],&EGAColours[0],16 * sizeof(UWORD)); break; case COLOUR_AMIGA: CopyMem(&Config . Colours[0],&DefaultColours[0],16 * sizeof(UWORD)); break; case COLOUR_MONO: CopyMem(&Config . Colours[0],&AtomicColours[0],16 * sizeof(UWORD)); break; } } ReleaseWindows(); break; /* Set the terminal preferences. */ case MEN_TERMINAL: BlockWindows(); TerminalPanel(&Config); ConfigSetup(); ReleaseWindows(); break; case MEN_COMMANDS: BlockWindows(); CommandPanel(&Config); ReleaseWindows(); break; case MEN_MISC: BlockWindows(); MiscPanel(&Config); ConfigSetup(); ReleaseWindows(); break; case MEN_PATH: BlockWindows(); if(PathPanel(&Config)) { DeleteBeep(); if(Config . BeepSound[0]) { if(!OpenSound(Config . BeepSound)) MyEasyRequest(Window,LocaleString(MSG_TERMMAIN_FAILED_TO_OPEN_SOUND_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT),Config . BeepSound); } CreateBeep(); } ReleaseWindows(); break; /* Set the file transfer options. */ case MEN_TRANSFER: 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,LocaleString(MSG_GLOBAL_FAILED_TO_SET_UP_PROTOCOL_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT),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()) SetTransferMenu(FALSE); else SetTransferMenu(TRUE); if(strlen(LastXprLibrary) > 39) { MyEasyRequest(Window,LocaleString(MSG_TERMMAIN_NAME_TOO_LONG_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT)); strcpy(Config . Protocol,FilePart(LastXprLibrary)); } else 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_TRANSFER_PROTOCOL: BlockWindows(); if(SelectProtocol(LastXprLibrary,Window)) { if(ProtocolSetup()) { if(strlen(LastXprLibrary) > 39) { MyEasyRequest(Window,LocaleString(MSG_TERMMAIN_NAME_TOO_LONG_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT)); strcpy(Config . Protocol,FilePart(LastXprLibrary)); } else strcpy(Config . Protocol,LastXprLibrary); } else { strcpy(LastXprLibrary,Config . Protocol); ProtocolSetup(); } if(!XProtocolBase) SetTransferMenu(FALSE); else SetTransferMenu(TRUE); } ReleaseWindows(); break; /* Set the keyboard macros. */ case MEN_MACROS: BlockWindows(); if(XEmulatorBase && Config . Emulation == EMULATION_EXTERNAL) { XEmulatorMacroKeyFilter(XEM_IO,NULL); MacroPanel(MacroKeys); SetupXEM_MacroKeys(MacroKeys); } else MacroPanel(MacroKeys); ReleaseWindows(); break; /* Set the fast macros. */ case MEN_FAST_MACROS: BlockWindows(); FastMacroPanel(); ReleaseWindows(); break; case MEN_HOTKEYS: BlockWindows(); if(HotkeyPanel(&Hotkeys)) { if(!SetupCx()) MyEasyRequest(Window,LocaleString(MSG_TERMMAIN_FAILED_TO_SET_UP_HOTKEYS_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT)); } ReleaseWindows(); break; case MEN_SPEECH: BlockWindows(); SpeechPanel(); ReleaseWindows(); break; /* Open the preferences settings. */ case MEN_OPEN_SETTINGS: BlockWindows(); strcpy(DummyBuffer,LastConfig); DummyChar = PathPart(DummyBuffer); *DummyChar = 0; if(FileRequest = GetFile(LocaleString(MSG_TERMMAIN_OPEN_PREFERENCES_TXT),DummyBuffer,FilePart(LastConfig),DummyBuffer,"#?.prefs",FALSE,FALSE,FALSE,NULL)) { if(ReadIFFData(DummyBuffer,&PrivateConfig,sizeof(struct Configuration),'PREF')) { swmem(&PrivateConfig,&Config,sizeof(struct Configuration)); strcpy(DummyBuffer,LastConfig); UpdatePrefs(&Config); ConfigSetup(); } else MyEasyRequest(Window,LocaleString(MSG_GLOBAL_ERROR_OPENING_FILE_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT),DummyBuffer); FreeAslRequest(FileRequest); } ReleaseWindows(); break; /* Save the terminal preferences. */ case MEN_SAVE_SETTINGS: if(LastConfig[0]) { BlockWindows(); if(!WriteIFFData(LastConfig,&Config,sizeof(struct Configuration),'PREF')) MyEasyRequest(Window,LocaleString(MSG_TERMMAIN_ERROR_WRITING_PREFERENCES_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT),LastConfig); ReleaseWindows(); break; } /* Save the terminal preferences to a * given file name. */ case MEN_SAVE_SETTINGS_AS: BlockWindows(); strcpy(DummyBuffer,LastConfig); DummyChar = PathPart(DummyBuffer); *DummyChar = 0; if(FileRequest = GetFile(LocaleString(MSG_TERMMAIN_SAVE_PREFERENCES_AS_TXT),DummyBuffer,FilePart(LastConfig),DummyBuffer,"#?.prefs",TRUE,FALSE,FALSE,NULL)) { if(WriteIFFData(DummyBuffer,&Config,sizeof(struct Configuration),'PREF')) strcpy(LastConfig,DummyBuffer); else MyEasyRequest(Window,LocaleString(MSG_TERMMAIN_ERROR_WRITING_PREFERENCES_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT),DummyBuffer); FreeAslRequest(FileRequest); } ReleaseWindows(); break; /* Show terminal information window. */ case MEN_STATUS_WINDOW: if(InfoWindow) CloseInfoWindow(); else OpenInfoWindow(); break; case MEN_REVIEW_WINDOW: if(ReviewWindow) DeleteReview(); else CreateReview(); break; /* Open the packet window if necessary, else * just activate it. */ case MEN_PACKET_WINDOW: if(!PacketWindow) CreatePacketWindow(); else { ActivateWindow(PacketWindow); MenuItem -> Flags |= CHECKED; } break; /* Toggle the presence of the fast! macro panel. */ case MEN_FAST_MACROS_WINDOW: if(FastWindow) CloseFastWindow(); else OpenFastWindow(); break; /* Ignore the rest. */ default: break; } } /* HandleMenu(ULONG Code,ULONG Qualifier): * * Skip along the number of selected menu items and * handle the associated functions. */ VOID HandleMenu(ULONG Code,ULONG Qualifier) { struct MenuItem *MenuItem; DisplayReopened = FALSE; /* Check until the last menuitem has been * processed. */ while(Code != MENUNULL) { /* Pick up the associated menu item. */ if(MenuItem = ItemAddress(Menu,Code)) { HandleCode((ULONG)GTMENUITEM_USERDATA(MenuItem),Qualifier,MenuItem); if(DisplayReopened) { DisplayReopened = FALSE; break; } Code = MenuItem -> NextSelect; } else break; } }