home *** CD-ROM | disk | FTP | other *** search
- /* $Revision Header * Header built automatically - do not edit! *************
- *
- * (C) Copyright 1990 by Olaf 'Olsen' Barthel & MXM
- *
- * Name .....: TermAux.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"
-
- /* The following static strings are displayed in the status
- * window.
- */
-
- STATIC UBYTE *ConfigFont[2] =
- {
- "Topaz",
- "IBM "
- };
-
- STATIC UBYTE *ConfigEmulation[3] =
- {
- "ANSI/VT",
- "Atomic ",
- "TTY "
- };
-
- STATIC UBYTE *ConfigParity[5] =
- {
- "None",
- "Even",
- "Odd ",
- "Mark",
- "Spac"
- };
-
- STATIC UBYTE *ConfigStatus[7] =
- {
- "Ready ",
- "Holding ",
- "Dialing ",
- "Upload ",
- "Download",
- "Breaking",
- "Hang Up "
- };
-
- /* Block window nest count. */
-
- STATIC SHORT BlockNestCount;
-
- /* GetConUnit():
- *
- * Extract the ConUnit pointer from the current output stream
- * console.
- */
-
- struct ConUnit *
- GetConUnit(struct MsgPort *ConsoleTask)
- {
- struct InfoData *InfoData;
- struct ConUnit *ConUnit = NULL;
-
- if(!ConsoleTask)
- ConsoleTask = (struct MsgPort *)((struct Process *)SysBase -> ThisTask) -> pr_ConsoleTask;
-
- if(InfoData = (struct InfoData *)AllocVec(sizeof(struct InfoData),MEMF_PUBLIC|MEMF_CLEAR))
- {
- /* Send the inquiry packet to the console task. */
-
- if(DoPkt1(ConsoleTask,ACTION_DISK_INFO,MKBADDR(InfoData)))
- ConUnit = (struct ConUnit *)((struct IOStdReq *)InfoData -> id_InUse) -> io_Unit;
-
- FreeVec(InfoData);
- }
-
- return(ConUnit);
- }
-
- /* AddDownloadObject(UBYTE *Line):
- *
- * Add another downloaded object to the list.
- */
-
- VOID
- AddDownloadObject(UBYTE *Line)
- {
- struct Node *SomeNode;
-
- /* Allocate space for the node itself and the
- * string to be put into the node name.
- */
-
- if(SomeNode = (struct Node *)AllocVec(sizeof(struct Node) + strlen(Line) + 1,MEMF_PUBLIC|MEMF_CLEAR))
- {
- /* Block list modification. */
-
- ObtainSemaphore(DownloadSemaphore);
-
- /* Enter the name. */
-
- SomeNode -> ln_Name = (UBYTE *)(SomeNode + 1);
-
- /* Copy the line over. */
-
- strcpy(SomeNode -> ln_Name,Line);
-
- /* Add it to the list. */
-
- AddTail(&DownloadList,SomeNode);
-
- /* Increment number of downloads. */
-
- DownloadLineCount++;
-
- ReleaseSemaphore(DownloadSemaphore);
- }
- }
-
- /* ClearDownloadObjects():
- *
- * Clear the list of downloaded objects.
- */
-
- VOID
- ClearDownloadObjects()
- {
- struct Node *SomeNode,*NextNode;
-
- ObtainSemaphore(DownloadSemaphore);
-
- SomeNode = DownloadList . lh_Head;
-
- while(SomeNode -> ln_Succ)
- {
- NextNode = SomeNode -> ln_Succ;
-
- Remove(SomeNode);
-
- FreeVec(SomeNode);
-
- SomeNode = NextNode;
- }
-
- DownloadNode = NULL;
-
- DownloadLineCount = 0;
-
- ReleaseSemaphore(DownloadSemaphore);
- }
-
- /* SequenceFilter(UBYTE Char):
- *
- * Yet another byte sequence filter, this time it's the
- * ARexx interface to make the call.
- */
-
- struct ScanNode *
- SequenceFilter(UBYTE Char)
- {
- struct ScanNode *SomeNode,*Matching = NULL;
- BYTE Matches = 0;
-
- /* Convert input character to upper case. */
-
- Char = ToUpper(Char);
-
- /* Get the first node in the list. */
-
- SomeNode = (struct ScanNode *)SequenceList . lh_Head;
-
- /* Scan until the last node is found. */
-
- while(SomeNode -> Node . mln_Succ)
- {
- /* This sequence had a couple of matches. */
-
- if(SomeNode -> Count == SequenceCount)
- {
- /* The next character in the sequence
- * still matches.
- */
-
- if(Char == SomeNode -> Sequence[SequenceCount])
- {
- /* Increase number of matching
- * characters.
- */
-
- SomeNode -> Count++;
-
- /* If there's another character
- * in the sequence, increase
- * the match counter.
- */
-
- if(SomeNode -> Sequence[SequenceCount + 1])
- Matches++;
- else
- {
- /* We were able to make
- * a perfect match.
- */
-
- Matches = 0;
-
- Matching = SomeNode;
- }
- }
- }
-
- /* Skip to the next node. */
-
- SomeNode = (struct ScanNode *)SomeNode -> Node . mln_Succ;
- }
-
- if(!Matches)
- {
- /* Clear the list entry counters. */
-
- if(SequenceCount)
- {
- SomeNode = (struct ScanNode *)SequenceList . lh_Head;
-
- while(SomeNode -> Node . mln_Succ)
- {
- SomeNode -> Count = 0;
-
- SomeNode = (struct ScanNode *)SomeNode -> Node . mln_Succ;
- }
-
- SequenceCount = 0;
- }
- }
- else
- SequenceCount++;
-
- return(Matching);
- }
-
- /* AddSequenceObject(UBYTE *Sequence):
- *
- * Add another sequence to the list of byte sequences
- * the routine above will look at whilst parsing.
- */
-
- VOID
- AddSequenceObject(UBYTE *Sequence)
- {
- struct ScanNode *SomeNode;
-
- if(SomeNode = AllocVec(sizeof(struct ScanNode) + strlen(Sequence) + 1,MEMF_PUBLIC|MEMF_CLEAR))
- {
- SHORT i;
-
- SomeNode -> Sequence = (UBYTE *)(SomeNode + 1);
-
- for(i = 0 ; i <= strlen(Sequence) ; i++)
- SomeNode -> Sequence[i] = ToUpper(Sequence[i]);
-
- AddTail(&SequenceList,(struct Node *)SomeNode);
- }
- }
-
- /* ClearSequenceObjects():
- *
- * Clear the list of scan sequences.
- */
-
- VOID
- ClearSequenceObjects()
- {
- struct Node *SomeNode,*NextNode;
-
- SomeNode = SequenceList . lh_Head;
-
- while(SomeNode -> ln_Succ)
- {
- NextNode = SomeNode -> ln_Succ;
-
- Remove(SomeNode);
-
- FreeVec(SomeNode);
-
- SomeNode = NextNode;
- }
- }
-
- /* LogAction(UBYTE *String,...):
- *
- * Write an action to the default log file.
- */
-
- VOID __stdargs
- LogAction(UBYTE *String,...)
- {
- if(Config . LogActions && Config . LogFile[0])
- {
- UBYTE DummyBuffer[256];
- BPTR File;
-
- va_list VarArgs;
-
- /* Build a valid string. */
-
- va_start(VarArgs,String);
- VSPrintf(DummyBuffer,String,VarArgs);
- va_end(VarArgs);
-
- /* Does the log file already exist? */
-
- if(GetFileSize(Config . LogFile))
- {
- /* It does, let's append the data. */
-
- if(File = Open(Config . LogFile,MODE_READWRITE))
- {
- if(Seek(File,0,OFFSET_END) == -1)
- {
- Close(File);
-
- File = NULL;
- }
- }
- }
- else
- {
- /* Create a new file. */
-
- if(File = Open(Config . LogFile,MODE_NEWFILE))
- FPrintf(File,"Date Time Action\n--------- -------- ----------------------------------------\n");
- }
-
- /* The file is open, build the date/time string and
- * write the log action.
- */
-
- if(File)
- {
- UBYTE TimeBuffer[20],DateBuffer[20];
- struct DateTime DateTime;
-
- /* Obtain current time. */
-
- DateStamp(&DateTime . dat_Stamp);
-
- /* Convert it to human readable form. */
-
- DateTime . dat_Format = FORMAT_DOS;
- DateTime . dat_Flags = 0;
- DateTime . dat_StrDay = NULL;
- DateTime . dat_StrDate = DateBuffer;
- DateTime . dat_StrTime = TimeBuffer;
-
- /* Conversion succeeded? */
-
- if(DateToStr(&DateTime))
- FPrintf(File,"%s %s %s\n",DateBuffer,TimeBuffer,DummyBuffer);
-
- /* Done! */
-
- Close(File);
- }
- }
- }
-
- /* FlushMsg(struct Window *Window):
- *
- * Cancel all pending messages of a window.
- */
-
- VOID
- FlushMsg(struct Window *Window)
- {
- struct IntuiMessage *Massage;
-
- while(Massage = (struct IntuiMessage *)GetMsg(Window -> UserPort))
- ReplyMsg(&Massage -> ExecMessage);
- }
-
- /* Local2Upper(UBYTE c):
- *
- * Very much the same as the macro expression ToUpper, but
- * more suitable for expressions such as `ToUpper(*a++)'.
- */
-
- UBYTE
- Local2Upper(UBYTE c)
- {
- return((UBYTE)((((c) >= 224 && (c) <= 254) || ((c) >= 'a' && (c) <= 'z')) ? (c) - 32 : (c)));
- }
-
- /* GetString(UBYTE *Prompt,UBYTE *Buffer):
- *
- * Get a string from the user, very much the same as xpr_gets,
- * but also including the `Load File' gadget.
- */
-
- BYTE
- GetString(UBYTE *Prompt,UBYTE *Buffer)
- {
- struct Gadget *GadgetList;
- struct Gadget *GadgetArray[4];
- struct Window *PanelWindow;
- struct Menu *PanelMenu;
- UBYTE DummyBuffer[256];
- struct FileRequester *FileRequest;
- LONG Width;
- BYTE Success = FALSE;
-
- STATIC struct NewMenu GetStringMenu[] =
- {
- { NM_TITLE, "Project", 0 , 0, 0, (APTR)0},
- { NM_ITEM, "Okay", "O", 0, 0, (APTR)1},
- { NM_ITEM, "Cancel", "C", 0, 0, (APTR)3},
- { NM_ITEM, NM_BARLABEL, 0 , 0, 0, (APTR)0},
- { NM_ITEM, "Load File...", "L", 0, 0, (APTR)2},
- { NM_ITEM, NM_BARLABEL, 0 , 0, 0, (APTR)0},
- { NM_ITEM, "Quit", "Q", 0, 0, (APTR)3},
- { NM_END, 0, 0 , 0, 0, (APTR)0}
- };
-
- if(CreateAllGetsGadgets(TRUE,Buffer,Prompt,&Width,&GadgetArray[0],&GadgetList,VisualInfo,Screen -> WBorTop + Screen -> Font -> ta_YSize + 1))
- {
- if(PanelMenu = CreateMenus(GetStringMenu,
- GTMN_FrontPen, 0,
- TAG_DONE))
- {
- if(LayoutMenus(PanelMenu,VisualInfo,
- GTMN_TextAttr,&DefaultFont,
- TAG_DONE))
- {
- if(PanelWindow = OpenWindowTags(NULL,
- WA_Width, Width,
- WA_Height, 56,
- WA_Left, (Screen -> Width - Width) >> 1,
- WA_Top, (Screen -> Height - 56) >> 1,
- WA_Activate, TRUE,
- WA_DragBar, TRUE,
- WA_DepthGadget, TRUE,
- WA_CloseGadget, TRUE,
- WA_RMBTrap, TRUE,
- WA_CustomScreen,Screen,
- WA_IDCMP, IDCMP_GADGETDOWN | IDCMP_ACTIVEWINDOW | IDCMP_CLOSEWINDOW | IDCMP_GADGETUP | IDCMP_MENUPICK | IDCMP_RAWKEY,
- WA_Title, "Enter A String",
- TAG_DONE))
- {
- struct IntuiMessage *Massage;
- ULONG Class,Code;
- struct Gadget *Gadget;
- BYTE Terminated = FALSE;
-
- PushWindow(PanelWindow);
-
- SetMenuStrip(PanelWindow,PanelMenu);
-
- PanelWindow -> Flags &= ~WFLG_RMBTRAP;
-
- AddGList(PanelWindow,GadgetList,(UWORD)-1,(UWORD)-1,NULL);
- RefreshGList(GadgetList,PanelWindow,NULL,(UWORD)-1);
- GT_RefreshWindow(PanelWindow,NULL);
-
- ActiveGadget = GadgetArray[0];
-
- ActivateGadget(GadgetArray[0],PanelWindow,NULL);
-
- while(!Terminated)
- {
- WaitPort(PanelWindow -> UserPort);
-
- while(!Terminated && (Massage = (struct IntuiMessage *)GT_GetIMsg(PanelWindow -> UserPort)))
- {
- Class = Massage -> Class;
- Code = Massage -> Code;
- Gadget = (struct Gadget *)Massage -> IAddress;
-
- GT_ReplyIMsg(Massage);
-
- if(Class == IDCMP_GADGETDOWN)
- {
- if((Gadget -> GadgetType & GTYP_GTYPEMASK) == STRGADGET)
- ActiveGadget = Gadget;
- }
-
- if(Class == IDCMP_RAWKEY)
- {
- if(Code == IECODE_UP_PREFIX|103 && CommandWindow == PanelWindow)
- ActivateGadget(CommandGadget,PanelWindow,NULL);
- }
-
- if(Class == IDCMP_ACTIVEWINDOW)
- ActivateGadget(GadgetArray[0],PanelWindow,NULL);
-
- if(Class == IDCMP_MENUPICK)
- {
- struct MenuItem *MenuItem;
-
- while(Code != MENUNULL)
- {
- MenuItem = ItemAddress(PanelMenu,Code);
-
- switch((ULONG)MENU_USERDATA(MenuItem))
- {
- case 3: Class = IDCMP_CLOSEWINDOW;
- break;
-
- case 1: strcpy(Buffer,((struct StringInfo *)GadgetArray[0] -> SpecialInfo) -> Buffer);
-
- Success = TRUE;
-
- Terminated = TRUE;
- break;
-
- case 2: GT_SetGadgetAttrs(GadgetArray[0],PanelWindow,NULL,
- GA_Disabled,TRUE,
- TAG_DONE);
-
- SetWait(PanelWindow);
-
- PanelWindow -> Flags |= WFLG_RMBTRAP;
-
- if(FileRequest = GetFile("Load File...","","",DummyBuffer,NULL,FALSE,FALSE))
- {
- GT_SetGadgetAttrs(GadgetArray[0],PanelWindow,NULL,
- GTST_String,DummyBuffer,
- TAG_DONE);
-
- RefreshGList(GadgetList,PanelWindow,NULL,(UWORD)-1);
-
- FreeAslRequest(FileRequest);
- }
-
- GT_SetGadgetAttrs(GadgetArray[0],PanelWindow,NULL,
- GA_Disabled,FALSE,
- TAG_DONE);
-
- ClearPointer(PanelWindow);
-
- PanelWindow -> Flags &= ~WFLG_RMBTRAP;
- break;
- }
-
- Code = MenuItem -> NextSelect;
- }
-
- if(ActiveGadget)
- ActivateGadget(ActiveGadget,PanelWindow,NULL);
- }
-
- if(Class == IDCMP_CLOSEWINDOW)
- Terminated = TRUE;
-
- if(Class == IDCMP_GADGETUP)
- {
- if(!DontActivate)
- {
- switch(Gadget -> GadgetID)
- {
- case 0:
- case 1: strcpy(Buffer,((struct StringInfo *)GadgetArray[0] -> SpecialInfo) -> Buffer);
-
- Success = TRUE;
-
- Terminated = TRUE;
- break;
-
- case 2: GT_SetGadgetAttrs(GadgetArray[0],PanelWindow,NULL,
- GA_Disabled,TRUE,
- TAG_DONE);
- SetWait(PanelWindow);
-
- PanelWindow -> Flags |= WFLG_RMBTRAP;
-
- if(FileRequest = GetFile("Load File...","","",DummyBuffer,NULL,FALSE,FALSE))
- {
- strcpy(((struct StringInfo *)GadgetArray[0] -> SpecialInfo) -> Buffer,DummyBuffer);
-
- RefreshGList(GadgetList,PanelWindow,NULL,(UWORD)-1);
-
- FreeAslRequest(FileRequest);
- }
-
- OnGadget(GadgetArray[0],PanelWindow,NULL);
- ClearPointer(PanelWindow);
-
- PanelWindow -> Flags &= ~WFLG_RMBTRAP;
- break;
-
- case 3: Terminated = TRUE;
- break;
- }
- }
- else
- DontActivate = FALSE;
- }
- }
- }
-
- PanelWindow -> Flags |= WFLG_RMBTRAP;
-
- ClearMenuStrip(PanelWindow);
-
- RemoveGList(PanelWindow,GadgetList,(UWORD)-1);
-
- PopWindow();
-
- CloseWindow(PanelWindow);
- }
-
- FreeGadgets(GadgetList);
- }
-
- FreeMenus(PanelMenu);
- }
- }
-
- return(Success);
- }
-
- /* WakeUp(struct Window *Window):
- *
- * Pop a window to the front and alert the user.
- */
-
- VOID
- WakeUp(struct Window *Window)
- {
- if(Window)
- BumpWindow(Window);
-
- Beep();
-
- WaitTime(2,0);
- /*
- Beep();
-
- WaitTime(0,MILLION / 4);
-
- Beep();
-
- WaitTime(0,MILLION / 4);*/
- }
-
- /* SendAmigaDOSCommand(UBYTE *Name):
- *
- * Let the current default Shell execute an AmigaDOS
- * command. Block until the command has returned.
- */
-
- VOID
- SendAmigaDOSCommand(UBYTE *Name)
- {
- BYTE DummyBuffer[2];
- BPTR File;
-
- /* Let the asynchronous Rexx server pick up and process
- * all incoming messages rather than sending them to the
- * main process (hopefully avoids deadlock situations).
- */
-
- BatchMode = TRUE;
-
- /* Open the console window or whatever the user
- * wants us to open here.
- */
-
- if(File = Open(WindowName,MODE_NEWFILE))
- {
- ULONG Tags[3];
- struct ConUnit *ConUnit = GetConUnit(((struct FileHandle *)BADDR(File)) -> fh_Type);
-
- Tags[0] = SYS_Output;
- Tags[1] = (ULONG)File;
- Tags[2] = TAG_DONE;
-
- if(ConUnit)
- {
- if(ConUnit -> cu_Window)
- BumpWindow(ConUnit -> cu_Window);
- }
-
- /* Make the Shell execute the command. */
-
- /* SystemTags(Name,SYS_Output,File,TAG_DONE);*/
-
- System(Name,(APTR)&Tags[0]);
-
- /* Wait for some impressive user action. */
-
- Write(File,"Press \33[1mRETURN\33[0m or close window to continue. ",51);
-
- Read(File,DummyBuffer,1);
-
- Close(File);
- }
-
- /* Bring the `term' main screen to the front and
- * fall back into asynchronous Rexx message processing.
- */
-
- BumpWindow(Window);
-
- BatchMode = FALSE;
- }
-
- /* RexxBackgroundServer():
- *
- * The background process to handle the rexx
- * massaging.
- */
-
- VOID __saveds
- RexxBackgroundServer()
- {
- BPTR OldCOS,OldCIS,NewCOS,NewCIS;
- struct MsgPort *OldConsoleTask,*ReplyPort;
-
- BYTE DummyBuffer[2];
-
- struct RexxMsg *RexxMsg;
-
- struct Process *BackgroundProcess;
- struct Message *SetupMsg;
-
- /* Look who we are. */
-
- BackgroundProcess = (struct Process *)SysBase -> ThisTask;
-
- /* Wait for startup message. */
-
- WaitPort(&BackgroundProcess -> pr_MsgPort);
-
- /* Pick the message up. */
-
- SetupMsg = GetMsg(&BackgroundProcess -> pr_MsgPort);
-
- /* Create a reply port the Rexx message is to
- * return to after processing.
- */
-
- if(ReplyPort = (struct MsgPort *)CreateMsgPort())
- {
- /* Remember previous I/O streams and
- * console handler.
- */
-
- OldCOS = BackgroundProcess -> pr_COS;
- OldCIS = BackgroundProcess -> pr_CIS;
-
- OldConsoleTask = BackgroundProcess -> pr_ConsoleTask;
-
- /* The following lines perform an `almost illegal'
- * action: new console I/O streams are opened for
- * the `term' main process. This is due to a rather
- * helpful Rexx server feature. Errors, messages
- * and other data are sent to the current output
- * stream.
- */
-
- if(NewCIS = Open(WindowName,MODE_NEWFILE))
- {
- struct FileHandle *FileHandle = (struct FileHandle *)BADDR(NewCIS);
- struct ConUnit *ConUnit = GetConUnit(((struct FileHandle *)BADDR(NewCIS)) -> fh_Type);
-
- /* Lock until we're done with the forgery. */
-
- Forbid();
-
- BackgroundProcess -> pr_ConsoleTask = (APTR)FileHandle -> fh_Type;
-
- BackgroundProcess -> pr_CIS = NewCIS;
- BackgroundProcess -> pr_COS = NewCOS = Open("*",MODE_NEWFILE);
-
- Permit();
-
- RexxWindow = NULL;
-
- if(ConUnit)
- {
- if(RexxWindow = ConUnit -> cu_Window)
- BumpWindow(RexxWindow);
- }
-
- /* Send the command and wait for a reply. */
-
- if(SendRexxCommand(ReplyPort,SetupMsg -> mn_Node . ln_Name,NULL,NULL))
- {
- ULONG SignalSet;
-
- SignalSet = Wait((1 << ReplyPort -> mp_SigBit) | SIGBREAKF_CTRL_C);
-
- if(SignalSet & SIGBREAKF_CTRL_C)
- Signal(ThisProcess,SIGBREAKF_CTRL_D);
-
- if(!(SignalSet & (1 << ReplyPort -> mp_SigBit)))
- Wait(1 << ReplyPort -> mp_SigBit);
-
- /* Pick up the RexxMsg (SendRexxCommand
- * had allocated it for us) and
- * examine the return codes.
- */
-
- if(RexxMsg = (struct RexxMsg *)GetMsg(ReplyPort))
- {
- if(!ExitQuietly)
- {
- /* This doesn't look too
- * good, does it?
- */
-
- if(RexxMsg -> rm_Result1)
- FPrintf(NewCIS,"\nCommand \"%s\" has terminated with code %ld, %ld.\n",SetupMsg -> mn_Node . ln_Name,RexxMsg -> rm_Result1,RexxMsg -> rm_Result2);
-
- /* Show our hand and return
- * to the usual business.
- */
-
- Write(BackgroundProcess -> pr_COS,"Press \33[1mRETURN\33[0m or close window to continue. ",51);
-
- Rexx2Front();
-
- Read(NewCIS,DummyBuffer,1);
-
- Term2Front();
- }
- else
- ExitQuietly = FALSE;
-
- /* Release the message. */
-
- FreeRexxCommand(RexxMsg);
- }
- }
-
- Forbid();
-
- RexxWindow = NULL;
-
- Permit();
-
- BumpWindow(Window);
-
- /* Close our fake I/O streams. */
-
- Forbid();
-
- Close(NewCIS);
- Close(NewCOS);
-
- /* And install the previous pointers. */
-
- BackgroundProcess -> pr_ConsoleTask = (APTR)OldConsoleTask;
-
- BackgroundProcess -> pr_CIS = OldCIS;
- BackgroundProcess -> pr_COS = OldCOS;
-
- Permit();
- }
-
- /* Remove the reply port. */
-
- DeleteMsgPort(ReplyPort);
- }
-
- /* We are done, lock and reply the message causing the
- * main process to return to the input loop.
- */
-
- Forbid();
-
- ReplyMsg(SetupMsg);
- }
-
- /* SendARexxCommand(UBYTE *Name):
- *
- * Let the ARexx server execute a command (or a script
- * file if necessary) and block until the command
- * has returned.
- */
-
- VOID
- SendARexxCommand(UBYTE *Name)
- {
- struct Process *BackgroundProcess;
- struct Message *SetupMsg;
- struct MsgPort *ReplyPort;
-
- ULONG SignalSet;
-
- /* Create a reply port for the info message. */
-
- if(ReplyPort = CreateMsgPort())
- {
- /* Allocate the message body. */
-
- if(SetupMsg = (struct Message *)AllocVec(sizeof(struct Message),MEMF_PUBLIC|MEMF_CLEAR))
- {
- /* Set up the message itself. */
-
- SetupMsg -> mn_Node . ln_Name = Name;
- SetupMsg -> mn_ReplyPort = ReplyPort;
- SetupMsg -> mn_Length = sizeof(struct Message);
-
- /* Create the background process which will
- * handle all the messy rexx message sending
- * for us.
- */
-
- if(BackgroundProcess = (struct Process *)CreateNewProcTags(
- NP_Entry, RexxBackgroundServer,
- NP_Name, "term Rexx Background Process",
- NP_StackSize, 16384,
- TAG_END))
- {
- SetSignal(0,SIGBREAKF_CTRL_D);
-
- /* Send the startup message. */
-
- PutMsg(&BackgroundProcess -> pr_MsgPort,SetupMsg);
-
- /* Go into loop and wait for the
- * background process to return.
- */
-
- FOREVER
- {
- SignalSet = Wait(SIG_REXX | (1 << ReplyPort -> mp_SigBit));
-
- /* Yet another rexx message. */
-
- if(SignalSet & SIG_REXX)
- HandleRexx();
-
- /* The background server has
- * finished.
- */
-
- if(SignalSet & (1 << ReplyPort -> mp_SigBit))
- break;
- }
-
- SetSignal(0,SIGBREAKF_CTRL_D);
- }
-
- /* Free the message. */
-
- FreeVec(SetupMsg);
- }
-
- /* Delete the reply port. */
-
- DeleteMsgPort(ReplyPort);
- }
- }
-
- /* ahtoi(UBYTE *String):
- *
- * Turn a hexadecimal string into an integer (borrowed from
- * Matt Dillon's dmouse.c).
- */
-
- LONG
- ahtoi(UBYTE *String)
- {
- LONG Value = 0;
- UBYTE c;
-
- while(c = *String)
- {
- Value <<= 4;
-
- if(c >= '0' && c <= '9')
- Value |= (c & 15);
- else
- Value |= (c & 15) + 9;
-
- ++String;
- }
-
- return(Value);
- }
-
- /* BlockWindows():
- *
- * Block the main window and the status window (i.e. disable
- * the menu and attach a wait pointer).
- */
-
- VOID
- BlockWindows()
- {
- if(!(BlockNestCount++))
- {
- SetWait(Window);
- SetWait(StatusWindow);
-
- if(PacketWindow)
- {
- SetWait(PacketWindow);
-
- PacketWindow -> Flags |= WFLG_RMBTRAP;
-
- GT_SetGadgetAttrs(PacketGadgetArray[0],PacketWindow,NULL,
- GA_Disabled,TRUE,
- TAG_DONE);
- }
-
- Window -> Flags |= WFLG_RMBTRAP;
- StatusWindow -> Flags |= WFLG_RMBTRAP;
-
- WeAreBlocking = TRUE;
- }
- }
-
- /* ReleaseWindows():
- *
- * Reenable the menus and clear the wait pointer.
- */
-
- VOID
- ReleaseWindows()
- {
- if(!(--BlockNestCount))
- {
- Window -> Flags &= ~WFLG_RMBTRAP;
- StatusWindow -> Flags &= ~WFLG_RMBTRAP;
-
- ClearPointer(Window);
- ClearPointer(StatusWindow);
-
- if(PacketWindow)
- {
- PacketWindow -> Flags &= ~WFLG_RMBTRAP;
-
- ClearPointer(PacketWindow);
-
- OnGadget(PacketGadgetArray[0],PacketWindow,NULL);
- }
-
- FlushMsg(Window);
-
- WeAreBlocking = FALSE;
- }
- }
-
- /* LineRead(BPTR File,UBYTE *Buffer,LONG MaxChars):
- *
- * Read a few bytes from a file (Ã la gets).
- */
-
- BYTE
- LineRead(BPTR File,UBYTE *Buffer,LONG MaxChars)
- {
- STATIC UBYTE Data[1024];
- STATIC LONG RIdx = 0,RLen = 0;
-
- LONG i;
-
- if(File)
- {
- for(i = 0 ; i < MaxChars ; i++)
- {
- if(RIdx >= RLen)
- {
- RLen = Read(File,Data,1024);
-
- RIdx = 0;
-
- if(RLen <= 0)
- {
- Buffer[i] = 0;
- return(FALSE);
- }
- }
-
- if((Buffer[i] = Data[RIdx]) != '\r')
- {
- if(Data[RIdx++] == '\n')
- {
- Buffer[i + 1] = 0;
- break;
- }
- }
- }
- }
- else
- RIdx = RLen = 0;
-
- return(TRUE);
- }
-
- /* FlowInit():
- *
- * Set up the data flow parser. The parser scans the serial
- * output data for more or less interesting modem output
- * (carrier lost, connect, etc.).
- */
-
- VOID
- FlowInit()
- {
- FlowInfo . Changed = FALSE;
-
- FlowInfo . NoCarrier = FlowInfo . ZModemUpload = FlowInfo . Connect = FlowInfo . Voice = FlowInfo . Ring = FlowInfo . Busy = FALSE;
-
- AttentionBuffers[0] = Config . NoCarrier;
- AttentionBuffers[1] = Config . Ring;
- AttentionBuffers[2] = Config . Voice;
- AttentionBuffers[3] = "*B01";
- AttentionBuffers[4] = "**B01";
- AttentionBuffers[5] = Config . Connect;
- AttentionBuffers[6] = Config . Busy;
-
- FlowCount = 0;
-
- memset(&AttentionCount[0],0,7);
-
- BaudPending = FALSE;
-
- FullCheck = FALSE;
- }
-
- /* FlowFilter(UBYTE Char):
- *
- * Send a character through the data flow parser and look
- * if it's part of a modem message.
- */
-
- VOID
- FlowFilter(UBYTE Char)
- {
- STATIC BYTE IgnoreChar;
- BYTE i,Matches = 0,Start,End,WasOnline = Online;
-
- /* Full data check is a lot slower than looking for
- * just a single sequence (such as the `CONNECT'
- * below). This mode is reserved for the dial panel.
- */
-
- if(FullCheck)
- {
- Start = 1;
- End = 7;
- }
- else
- {
- Start = 0;
-
- if(UsesZModem)
- End = 5;
- else
- End = 3;
- }
-
- /* We already got a `CONNECT' and the
- * `connect auto-baud' feature is enabled.
- * Continue scanning the serial output
- * data for the actual baud rate.
- */
-
- if(BaudPending)
- {
- if(Char >= '0' && Char <= '9')
- {
- BaudBuffer[BaudCount++] = Char;
-
- if(IgnoreChar)
- IgnoreChar = 0;
- }
- else
- {
- /* The scanner has found a
- * non-numerical character.
- * This is either a blank
- * space or something else.
- * The latter tells us
- * that the baud rate has
- * been identified and is
- * ready to be used.
- */
-
- if(Char != IgnoreChar)
- {
- BaudBuffer[BaudCount] = 0;
-
- BaudPending = FALSE;
- }
- }
- }
-
- if(!BaudPending)
- {
- /* Scan all ID strings for matches. */
-
- for(i = Start ; i < End ; i++)
- {
- /* This sequence is a probable
- * match.
- */
-
- if(AttentionCount[i] == FlowCount)
- {
- /* Does the character
- * fit into the sequence?
- */
-
- if(Char == AttentionBuffers[i][FlowCount])
- {
- /* Increment the
- * number of matching
- * characters in this
- * sequence.
- */
-
- AttentionCount[i]++;
-
- /* Did we hit the
- * last character
- * in the sequence?
- */
-
- if(AttentionBuffers[i][FlowCount + 1])
- Matches++;
- else
- {
- Matches = 0;
-
- /* We've got a valid
- * sequence, now look
- * which flags to change.
- */
-
- switch(i)
- {
- /* We got a `no carrier' message. */
-
- case 0: if(!FlowInfo . NoCarrier)
- {
- FlowInfo . NoCarrier = TRUE;
- FlowInfo . Changed = TRUE;
- }
-
- Online = FALSE;
-
- /* Clear the password. */
-
- Password[0] = 0;
-
- if(WasOnline)
- {
- if(CurrentPay)
- LogAction("Carrier lost (cost %ld.%02ld).",CurrentPay / 100,CurrentPay % 100);
- else
- LogAction("Carrier lost.");
-
- Say("Carrier lost.");
- }
- break;
-
- /* Got a voice call. */
-
- case 1: if(!FlowInfo . Voice)
- {
- FlowInfo . Voice = TRUE;
- FlowInfo . Changed = TRUE;
- }
- break;
-
- /* Got another call. */
-
- case 2: if(!FlowInfo . Ring)
- {
- FlowInfo . Ring = TRUE;
- FlowInfo . Changed = TRUE;
- }
- break;
-
- case 3:
- case 4: if(!FlowInfo . ZModemUpload)
- {
- FlowInfo . ZModemUpload = TRUE;
- FlowInfo . Changed = TRUE;
- }
- break;
-
- /* Got a connect message. */
-
- case 5: if(!FlowInfo . Connect)
- {
- FlowInfo . Connect = TRUE;
- FlowInfo . Changed = TRUE;
- }
-
- if(Config . ConnectAutoBaud)
- {
- BaudBuffer[0] = 0;
-
- BaudPending = TRUE;
- BaudCount = 0;
-
- IgnoreChar = ' ';
- }
-
- break;
-
- /* Line is busy. */
-
- case 6: if(!FlowInfo . Busy)
- {
- FlowInfo . Busy = TRUE;
- FlowInfo . Changed = TRUE;
- }
- break;
- }
- }
- }
- }
- }
-
- /* We've got a good match (recognized
- * a sequence, so reset the data flow
- * scanner.
- */
-
- if(!Matches)
- {
- if(FlowCount)
- {
- FlowCount = 0;
-
- memset(&AttentionCount[0],0,7);
- }
- }
- else
- FlowCount++;
- }
- else
- {
- /* This checks for just a single sequence:
- * the notorious `NO CARRIER'.
- */
-
- if(AttentionCount[0] == FlowCount)
- {
- if(Char == AttentionBuffers[0][FlowCount])
- {
- AttentionCount[0]++;
-
- if(AttentionBuffers[0][FlowCount + 1])
- Matches++;
- else
- {
- Matches = 0;
-
- if(!FlowInfo . NoCarrier)
- {
- FlowInfo . NoCarrier = TRUE;
- FlowInfo . Changed = TRUE;
- }
-
- Online = FALSE;
-
- /* Clear the password. */
-
- Password[0] = 0;
-
- if(WasOnline)
- {
- if(CurrentPay)
- LogAction("Carrier lost (cost %ld.%02ld).",CurrentPay / 100,CurrentPay % 100);
- else
- LogAction("Carrier lost.");
-
- Say("Carrier lost.");
- }
- }
- }
- }
-
- if(!Matches)
- {
- if(FlowCount)
- {
- FlowCount = 0;
-
- memset(&AttentionCount[0],0,7);
- }
- }
- else
- FlowCount++;
- }
- }
-
- /* LoadMacros(UBYTE *Name,struct MacroKeys *Keys):
- *
- * Load the keyboard macros from a file.
- */
-
- BYTE
- LoadMacros(UBYTE *Name,struct MacroKeys *Keys)
- {
- struct IFFHandle *Handle;
- BYTE Success = FALSE;
- struct StoredProperty *Prop;
- struct TermInfo *TermInfo;
-
- if(Handle = AllocIFF())
- {
- if(Handle -> iff_Stream = Open(Name,MODE_OLDFILE))
- {
- InitIFFasDOS(Handle);
-
- if(!OpenIFF(Handle,IFFF_READ))
- {
- /* Collect version number ID if
- * available.
- */
-
- if(!PropChunks(Handle,&VersionProps[0],1))
- {
- /* The following line tells iffparse to stop at the
- * very beginning of a `Type' chunk contained in a
- * `TERM' FORM chunk.
- */
-
- if(!StopChunk(Handle,'TERM','KEYS'))
- {
- /* Parse the file... */
-
- if(!ParseIFF(Handle,IFFPARSE_SCAN))
- {
- /* Did we get a version ID? */
-
- if(Prop = FindProp(Handle,'TERM','VERS'))
- {
- TermInfo = (struct TermInfo *)Prop -> sp_Data;
-
- /* Is it the file format we are able
- * to read?
- */
-
- if(TermInfo -> Version == TermVersion && TermInfo -> Revision <= TermRevision && TermInfo -> Revision >= 6)
- {
- /* The file read pointer is positioned
- * just in front of the first data
- * to be read, so let's don't disappoint
- * iffparse and read it.
- */
-
- if(ReadChunkBytes(Handle,Keys,sizeof(struct MacroKeys)) == sizeof(struct MacroKeys))
- Success = TRUE;
- }
- else
- {
- /* Probably an older revision. */
-
- if(TermInfo -> Version == 1 && TermInfo -> Revision < 6)
- {
- memset(Keys,0,sizeof(struct MacroKeys));
-
- if(ReadChunkBytes(Handle,Keys,10 * 256) == 10 * 256)
- Success = TRUE;
- }
- }
- }
- else
- {
- /* File was created by WriteIFFData previous
- * to revision 1.4.
- */
-
- memset(Keys,0,sizeof(struct MacroKeys));
-
- if(ReadChunkBytes(Handle,Keys,10 * 256) == 10 * 256)
- Success = TRUE;
- }
- }
- }
- }
-
- CloseIFF(Handle);
- }
-
- Close(Handle -> iff_Stream);
- }
-
- FreeIFF(Handle);
- }
-
- return(Success);
- }
-
- /* FindThisItem(ULONG MenuID):
- *
- * Scan the main menu for a menuitem associated with a
- * menu ID.
- */
-
- struct MenuItem *
- FindThisItem(ULONG MenuID)
- {
- struct Menu *FirstMenu;
- struct MenuItem *FirstItem;
-
- for(FirstMenu = Menu ; FirstMenu -> NextMenu ; FirstMenu = FirstMenu -> NextMenu)
- {
- for(FirstItem = FirstMenu -> FirstItem ; FirstItem -> NextItem ; FirstItem = FirstItem -> NextItem)
- {
- if((ULONG)GTMENUITEM_USERDATA(FirstItem) == MenuID)
- return(FirstItem);
- }
- }
-
- return(NULL);
- }
-
- /* GetFileSize(UBYTE *Name):
- *
- * Simple routine to return the size of a file in
- * bytes.
- */
-
- LONG
- GetFileSize(UBYTE *Name)
- {
- struct FileInfoBlock *FileInfo;
- BPTR FileLock;
- LONG FileSize = 0;
-
- if(FileInfo = (struct FileInfoBlock *)AllocMem(sizeof(struct FileInfoBlock),MEMF_PUBLIC))
- {
- if(FileLock = Lock(Name,ACCESS_READ))
- {
- if(Examine(FileLock,FileInfo))
- FileSize = FileInfo -> fib_Size;
-
- UnLock(FileLock);
- }
-
- FreeMem(FileInfo,sizeof(struct FileInfoBlock));
- }
-
- return(FileSize);
- }
-
- /* StrCmp(UBYTE *a,UBYTE *b):
- *
- * Perform case insensitive string comparison. I know
- * that Stricmp in utility.library handles the same
- * job, but by the time I had spread calls to this
- * routine across a number of modules I lost interest
- * in changing the call.
- */
-
- LONG
- StrCmp(UBYTE *a,UBYTE *b)
- {
- for( ; Local2Upper(*a) == Local2Upper(*b) ; a++, b++)
- {
- if(!(*a))
- return(0);
- }
-
- return((LONG)(Local2Upper(*a) - Local2Upper(*b)));
- }
-
- /* GetFile(UBYTE *Title,UBYTE *Directory,UBYTE *Name,UBYTE *Buffer,UBYTE *Pattern,BYTE SaveFlag,BYTE MultiSelect):
- *
- * Call the asl.library file requester to select a single or
- * a couple of files.
- */
-
- struct FileRequester *
- GetFile(UBYTE *Title,UBYTE *Directory,UBYTE *Name,UBYTE *Buffer,UBYTE *Pattern,BYTE SaveFlag,BYTE MultiSelect)
- {
- struct FileRequester *AslFileRequest;
- BYTE Result = FALSE;
- LONG Flags;
-
- STATIC UBYTE DirBuffer[256];
-
- /* We use this tag array to remember the size and
- * position of the asl requester window.
- */
-
- STATIC struct {
- ULONG Tag1, LeftEdge;
- ULONG Tag2, TopEdge;
- ULONG Tag3, Width;
- ULONG Tag4, Height;
- ULONG Tag5;
- } Dims = {
- ASL_LeftEdge, 0,
- ASL_TopEdge, 0,
- ASL_Width, 0,
- ASL_Height, 0,
- TAG_DONE
- };
-
- /* Empty directory string? Revert to the last directory
- * name.
- */
-
- if(!Directory[0])
- Directory = DirBuffer;
-
- /* If a wildcard pattern is required, add a gadget
- * to display it.
- */
-
- if(Pattern)
- {
- Flags = FILF_PATGAD;
-
- if(!Pattern[0])
- Pattern = "#?";
- }
- else
- {
- Flags = 0;
-
- Pattern = "#?";
- }
-
- /* Set the save flag if we are about to save something. */
-
- if(SaveFlag)
- Flags |= FILF_SAVE;
-
- /* Set the multiselect bit if multiple files are
- * to be selected (e.g. for batch file upload).
- */
-
- if(MultiSelect)
- Flags |= FILF_MULTISELECT;
-
- /* Allocate the asl.library directory requester
- * and display it.
- */
-
- if(AslFileRequest = (struct FileRequester *)AllocAslRequestTags(ASL_FileRequest,
- ASL_Window, Window,
- ASL_File, Name,
- ASL_Dir, Directory,
- ASL_Hail, Title,
- ASL_FuncFlags, Flags,
- ASL_Pattern, Pattern,
- ASL_OKText, SaveFlag ? "Save" : "Open",
- Dims . Width ? TAG_MORE : TAG_END,&Dims))
- {
- if(AslRequestTags(AslFileRequest,TAG_DONE))
- {
- Dims . LeftEdge = AslFileRequest -> rf_LeftEdge;
- Dims . TopEdge = AslFileRequest -> rf_TopEdge;
- Dims . Width = AslFileRequest -> rf_Width;
- Dims . Height = AslFileRequest -> rf_Height;
-
- /* Do we have a valid file name? */
-
- if(AslFileRequest -> rf_File[0])
- {
- /* Build a legal path/file string. */
-
- strcpy(Buffer,AslFileRequest -> rf_Dir);
-
- AddPart((UBYTE *)Buffer,(UBYTE *)AslFileRequest -> rf_File,256);
-
- Result = TRUE;
-
- strcpy(DirBuffer,AslFileRequest -> rf_Dir);
- }
- }
- }
-
- /* We didn't get a file, no need to keep the
- * file requester.
- */
-
- if(!Result && AslFileRequest)
- {
- FreeAslRequest(AslFileRequest);
- return(NULL);
- }
- else
- return(AslFileRequest);
- }
-
- /* MyEasyRequest(struct Window *Window,UBYTE *Text,UBYTE *Gadgets,...):
- *
- * Really quite simple varargs version of Intuition's
- * EasyRequest requester.
- */
-
- SHORT __stdargs
- MyEasyRequest(struct Window *Window,UBYTE *Text,UBYTE *Gadgets,...)
- {
- struct EasyStruct Easy;
- SHORT Result;
- ULONG IDCMP = NULL;
- va_list VarArgs;
-
- /* Standard data. */
-
- Easy . es_StructSize = sizeof(struct EasyStruct);
- Easy . es_Flags = NULL;
- Easy . es_Title = (UBYTE *)"term Request";
- Easy . es_TextFormat = (UBYTE *)Text;
- Easy . es_GadgetFormat = (UBYTE *)Gadgets;
-
- /* Use the argument array to build the
- * requester and display it.
- */
-
- va_start(VarArgs,Gadgets);
- Result = EasyRequestArgs(Window,&Easy,&IDCMP,VarArgs);
- va_end(VarArgs);
-
- return(Result);
- }
-
- /* A handy positioning macro. */
-
- #define MoveItem(X,Y) Move(RPort,((11 + X * 20) * 8) + ((Screen -> Width - 640) >> 1),2 + 6 + Y * 8)
-
- /* StatusServer():
- *
- * Asynchronous task to continuosly display the current
- * terminal settings.
- */
-
- VOID __saveds
- StatusServer()
- {
- struct RastPort *RPort = StatusWindow -> RPort;
- UBYTE Buffer[20];
-
- struct timerequest *TimeRequest;
- struct MsgPort *TimePort;
-
- struct timeval OnlineTime;
- BYTE GotOnline = FALSE;
-
- BYTE KeepGoing = TRUE;
-
- BYTE LastFont = -1;
- BYTE LastEmulation = -1;
-
- BYTE LastProtocol[40],ProtocolBuffer[10],i;
-
- LONG LastBaud = -1;
- BYTE LastBitsPerChar = -1;
- BYTE LastParity = -1;
- BYTE LastStopBits = -1;
-
- BYTE LastStatus = -1;
-
- LONG SecCount;
- BYTE FlagBit;
-
- LONG ThisHour,ThisMinute,TestTime;
-
- BYTE FlashIt = FALSE;
-
- LastProtocol[0] = 0;
-
- /* Create a timer device request. */
-
- if(TimePort = (struct MsgPort *)CreateMsgPort())
- {
- if(TimeRequest = (struct timerequest *)CreateIORequest(TimePort,sizeof(struct timerequest)))
- {
- if(!OpenDevice(TIMERNAME,UNIT_VBLANK,TimeRequest,0))
- {
- /* Signal our father process
- * that we're running.
- */
-
- Signal(ThisProcess,SIGBREAKF_CTRL_C);
-
- MoveItem(3,1);
- Print("00:00:00");
-
- /* Keep on displaying. */
-
- while(KeepGoing)
- {
- /* Are we to quit? */
-
- if(SetSignal(0,0) & SIGBREAKF_CTRL_C)
- {
- KeepGoing = FALSE;
-
- SetSignal(0,SIGBREAKF_CTRL_C);
- }
-
- /* Get the current time. */
-
- TimeRequest -> tr_node . io_Command = TR_GETSYSTIME;
- DoIO(TimeRequest);
-
- /* A connection has just
- * been established.
- */
-
- if(Online && !GotOnline)
- {
- OnlineTime = TimeRequest -> tr_time;
-
- GotOnline = TRUE;
-
- SecCount = 0;
-
- FlagBit = FALSE;
- }
-
- /* Print the current time. */
-
- ThisHour = (TimeRequest -> tr_time . tv_secs % 86400) / 3600;
- ThisMinute = (TimeRequest -> tr_time . tv_secs % 3600) / 60;
-
- SPrintf(Buffer,"%02ld:%02ld:%02ld",ThisHour,ThisMinute,TimeRequest -> tr_time . tv_secs % 60);
-
- MoveItem(3,0);
- Print(Buffer);
-
- if(Online)
- {
- struct timeval TempTime;
-
- if(PayPerUnit[0] || PayPerUnit[1])
- {
- TestTime = ThisHour * 6 + ThisMinute / 10;
-
- if(TestTime >= TimeOfDay[0] && TestTime <= TimeOfDay[1])
- PreferredTime = 0;
- else
- {
- if(TestTime >= TimeOfDay[1] && TestTime <= TimeOfDay[0])
- PreferredTime = 1;
- else
- {
- if(TestTime >= TimeOfDay[0] && TestTime >= TimeOfDay[1])
- {
- if(TimeOfDay[0] > TimeOfDay[1])
- PreferredTime = 0;
- else
- PreferredTime = 1;
- }
- else
- {
- if(TestTime <= TimeOfDay[0] && TestTime <= TimeOfDay[1])
- {
- if(TimeOfDay[0] > TimeOfDay[1])
- PreferredTime = 0;
- else
- PreferredTime = 1;
- }
- }
- }
- }
-
- if(!CurrentPay)
- CurrentPay = PayPerUnit[PreferredTime];
-
- FlagBit ^= TRUE;
-
- if(!FlagBit)
- {
- if((SecCount++) == SecPerUnit[PreferredTime])
- {
- SecCount = 0;
-
- CurrentPay += PayPerUnit[PreferredTime];
- }
- }
- }
-
- /* Show the time
- * we have been online
- * yet.
- */
-
- TempTime = TimeRequest -> tr_time;
-
- SubTime(&TempTime,&OnlineTime);
-
- SPrintf(Buffer,"%02ld:%02ld:%02ld",(TempTime . tv_secs % 86400) / 3600,(TempTime . tv_secs % 3600) / 60,TempTime . tv_secs % 60);
-
- MoveItem(3,1);
-
- Print(Buffer);
- }
- else
- {
- if(GotOnline)
- GotOnline = FALSE;
- }
-
- /* Display the current terminal
- * status.
- */
-
- if(LastStatus != Status)
- {
- LastStatus = Status;
-
- MoveItem(0,0);
- Print(ConfigStatus[LastStatus]);
- }
-
- /* Show the current transfer
- * protocol.
- */
-
- if(strcmp(LastProtocol,FilePart(Config . Protocol)))
- {
- strcpy(LastProtocol,FilePart(Config . Protocol));
-
- strcpy(ProtocolBuffer," ");
-
- for(i = 0 ; i < 8 ; i++)
- {
- if(!LastProtocol[i + 3] || LastProtocol[i + 3] == '.')
- break;
- else
- ProtocolBuffer[i] = LastProtocol[i + 3];
- }
-
- MoveItem(1,0);
- Print(ProtocolBuffer);
- }
-
- /* Show the current baud
- * rate.
- */
-
- if(LastBaud != Config . BaudRate)
- {
- LastBaud = Config . BaudRate;
-
- SPrintf(Buffer,"%ld ",LastBaud);
-
- Buffer[8] = 0;
-
- MoveItem(2,0);
- Print(Buffer);
- }
-
- /* Show the current
- * terminal font.
- */
-
- if(LastFont != Config . Font)
- {
- LastFont = Config . Font;
-
- MoveItem(0,1);
- Print(ConfigFont[LastFont]);
- }
-
- /* Show the current terminal
- * emulation.
- */
-
- if(LastEmulation != Config . Emulation)
- {
- LastEmulation = Config . Emulation;
-
- MoveItem(1,1);
- Print(ConfigEmulation[LastEmulation]);
- }
-
- /* Show the current serial
- * parameters (parity, etc).
- */
-
- if(LastBitsPerChar != Config . BitsPerChar || LastParity != Config . Parity || LastStopBits != Config . StopBits)
- {
- LastBitsPerChar = Config . BitsPerChar;
- LastParity = Config . Parity;
- LastStopBits = Config . StopBits;
-
- SPrintf(Buffer,"%ld-%s-%ld",LastBitsPerChar,ConfigParity[LastParity],LastStopBits);
-
- MoveItem(2,1);
- Print(Buffer);
- }
-
- /* Wait another half a second. */
-
- if(KeepGoing)
- {
- TimeRequest -> tr_node . io_Command = TR_ADDREQUEST;
- TimeRequest -> tr_time . tv_secs = 0;
- TimeRequest -> tr_time . tv_micro = MILLION / 2;
-
- DoIO(TimeRequest);
- }
-
- /* Make the colours blink. */
-
- if((Window -> Flags & WFLG_MENUSTATE) || (Window -> Pointer))
- {
- if(!FlashIt)
- {
- if(Screen == IntuitionBase -> FirstScreen)
- LoadRGB4(VPort,Config . Colours,16);
-
- FlashIt = TRUE;
- }
- }
- else
- {
- /* Are we to flash the display? */
-
- if(!Config . DisableBlinking)
- {
- if(Screen == IntuitionBase -> FirstScreen)
- {
- if(FlashIt)
- LoadRGB4(VPort,BlinkColours,16);
- else
- LoadRGB4(VPort,Config . Colours,16);
- }
-
- FlashIt ^= TRUE;
- }
- }
- }
-
- CloseDevice(TimeRequest);
- }
-
- DeleteIORequest(TimeRequest);
- }
-
- DeleteMsgPort(TimePort);
- }
-
- /* Signal the father process that we're done
- * and quietly remove ourselves.
- */
-
- Forbid();
-
- Signal(ThisProcess,SIGBREAKF_CTRL_C);
-
- StatusTask = NULL;
-
- RemTask(SysBase -> ThisTask);
- }
-
- /* CloseWindowSafely(struct Window *Window):
- *
- * Close a window freeing all messages pending at
- * its user port (taken from example source code
- * published once upon a time in Amiga Mail).
- */
-
- VOID
- CloseWindowSafely(struct Window *Window)
- {
- struct IntuiMessage *IntuiMessage;
- struct Node *Successor;
-
- Forbid();
-
- IntuiMessage = (struct IntuiMessage *)Window -> UserPort -> mp_MsgList . lh_Head;
-
- while(Successor = IntuiMessage -> ExecMessage . mn_Node . ln_Succ)
- {
- if(IntuiMessage -> IDCMPWindow == Window)
- {
- Remove(IntuiMessage);
-
- ReplyMsg((struct Message *)IntuiMessage);
- }
-
- IntuiMessage = (struct IntuiMessage *)Successor;
- }
-
- Window -> UserPort = NULL;
-
- ModifyIDCMP(Window,NULL);
- Permit();
-
- CloseWindow(Window);
- }
-
- /* WaitTime(LONG Secs,LONG Micros):
- *
- * Wait a given period of time.
- */
-
- VOID
- WaitTime(LONG Secs,LONG Micros)
- {
- TimeRequest -> tr_node . io_Command = TR_ADDREQUEST;
- TimeRequest -> tr_time . tv_secs = Secs;
- TimeRequest -> tr_time . tv_micro = Micros;
-
- DoIO(TimeRequest);
- }
-
- /* GetEnvDOS(UBYTE *Name,UBYTE *Buffer):
- *
- * Get the contents of a vanilla AmigaDOS environment
- * variable.
- */
-
- UBYTE *
- GetEnvDOS(UBYTE *Name,UBYTE *Buffer)
- {
- LONG Size;
- BPTR File,SomeLock;
-
- Buffer[0] = 0;
-
- /* Is ENV: present? */
-
- if(SomeLock = Lock("ENV:",ACCESS_READ))
- {
- UBYTE SomeBuffer[80];
-
- UnLock(SomeLock);
-
- strcpy(SomeBuffer,"ENV:");
- strcat(SomeBuffer,Name);
-
- /* Open the file. */
-
- if(File = Open(SomeBuffer,MODE_OLDFILE))
- {
- /* Read the contents. */
-
- Size = Read(File,Buffer,256);
-
- Close(File);
-
- if(Size > 0)
- {
- Buffer[Size] = 0;
-
- return(Buffer);
- }
- }
- }
-
- return(NULL);
- }
-
- /* SetEnvDOS(UBYTE *Name,UBYTE *Value):
- *
- * Set the contents of a vanilla AmigaDOS environment
- * variable.
- */
-
- BYTE
- SetEnvDOS(UBYTE *Name,UBYTE *Value)
- {
- UBYTE Buffer[80],*Destination;
- LONG Length = 0;
- BPTR File,FileLock;
- BYTE Success = FALSE;
- SHORT i;
-
- for(i = 0 ; i < 2 ; i++)
- {
- if(i)
- Destination = "ENVARC:";
- else
- Destination = "ENV:";
-
- /* Is ENV:/ENVARC: present? */
-
- if(FileLock = Lock(Destination,ACCESS_READ))
- {
- UnLock(FileLock);
-
- strcpy(Buffer,Destination);
- strcat(Buffer,Name);
-
- /* There already is a variable of that
- * name in the environment storage
- * directory.
- */
-
- if(FileLock = Lock(Buffer,ACCESS_WRITE))
- {
- UnLock(FileLock);
-
- /* Delete the variable. */
-
- if(!DeleteFile(Buffer))
- {
- Success = FALSE;
- continue;
- }
- }
-
- /* Set the new variable. */
-
- if(Length = strlen(Value))
- {
- if(File = Open(Buffer,MODE_NEWFILE))
- {
- if(Write(File,Value,Length) != Length)
- {
- Close(File);
- DeleteFile(Buffer);
-
- Success = FALSE;
- }
- else
- {
- Close(File);
- SetProtection(Buffer,FIBF_EXECUTE);
-
- Success = TRUE;
- }
- }
- else
- Success = FALSE;
- }
- else
- Success = TRUE;
- }
- else
- Success = FALSE;
- }
-
- return(Success);
- }
-
- /* BumpWindow(struct Window *SomeWindow):
- *
- * Bring a window to the front (and shift the screen
- * back to its initial position).
- */
-
- VOID
- BumpWindow(struct Window *SomeWindow)
- {
- MoveScreen(SomeWindow -> WScreen,-SomeWindow -> WScreen -> LeftEdge,-SomeWindow -> WScreen -> TopEdge);
-
- ScreenToFront(SomeWindow -> WScreen);
-
- ActivateWindow(SomeWindow);
- }
-
- /* BumpDefault():
- *
- * Bring the current default screen to the front.
- */
-
- VOID
- BumpDefault()
- {
- struct Screen *DefaultScreen;
-
- if(DefaultScreen = (struct Screen *)LockPubScreen(NULL))
- {
- MoveScreen(DefaultScreen,-DefaultScreen -> LeftEdge,-DefaultScreen -> TopEdge);
-
- ScreenToFront(DefaultScreen);
-
- UnlockPubScreen(NULL,DefaultScreen);
- }
- }
-
- /* WriteIFFData(UBYTE *Name,APTR Data,LONG Size,ULONG Type):
- *
- * Write data to an IFF file (via iffparse.library).
- */
-
- BYTE
- WriteIFFData(UBYTE *Name,APTR Data,LONG Size,ULONG Type)
- {
- struct IFFHandle *Handle;
- BYTE Success = FALSE;
-
- /* Allocate a handle. */
-
- if(Handle = AllocIFF())
- {
- /* Open an output stream. */
-
- if(Handle -> iff_Stream = Open(Name,MODE_NEWFILE))
- {
- /* Tell iffparse that this is
- * a DOS handle.
- */
-
- InitIFFasDOS(Handle);
-
- /* Open the handle for writing. */
-
- if(!OpenIFF(Handle,IFFF_WRITE))
- {
- /* Push outmost chunk onto stack. */
-
- if(!PushChunk(Handle,'TERM','FORM',IFFSIZE_UNKNOWN))
- {
- /* Add a version identifier. */
-
- if(!PushChunk(Handle,0,'VERS',IFFSIZE_UNKNOWN))
- {
- struct TermInfo TermInfo;
-
- TermInfo . Version = TermVersion;
- TermInfo . Revision = TermRevision;
-
- /* Write the version data. */
-
- if(WriteChunkBytes(Handle,&TermInfo,sizeof(struct TermInfo)) == sizeof(struct TermInfo))
- {
- /* Pop the version chunk, i.e. write it to the file. */
-
- if(PopChunk(Handle))
- Success = FALSE;
- else
- {
- /* Push the real data chunk on the stack. */
-
- if(!PushChunk(Handle,0,Type,IFFSIZE_UNKNOWN))
- {
- /* Write the data. */
-
- if(WriteChunkBytes(Handle,Data,Size) == Size)
- Success = TRUE;
-
- /* Pop the data chunk. */
-
- if(PopChunk(Handle))
- Success = FALSE;
- }
- else
- Success = FALSE;
- }
- }
- else
- Success = FALSE;
- }
-
- /* Seems that we're done, now try to pop the FORM chunk
- * and return.
- */
-
- if(PopChunk(Handle))
- Success = FALSE;
- }
-
- /* Close the handle (flush any pending data). */
-
- CloseIFF(Handle);
- }
-
- /* Close the DOS handle itself. */
-
- Close(Handle -> iff_Stream);
- }
-
- /* And free the IFF handle. */
-
- FreeIFF(Handle);
- }
-
- if(Success)
- SetProtection(Name,FIBF_EXECUTE);
-
- return(Success);
- }
-
- /* ReadIFFData(UBYTE *Name,APTR Data,LONG Size,ULONG Type):
- *
- * Read data from a `TERM' FORM chunk contained in an IFF file.
- */
-
- BYTE
- ReadIFFData(UBYTE *Name,APTR Data,LONG Size,ULONG Type)
- {
- struct IFFHandle *Handle;
- BYTE Success = FALSE;
- struct StoredProperty *Prop;
- struct TermInfo *TermInfo;
-
- if(Handle = AllocIFF())
- {
- if(Handle -> iff_Stream = Open(Name,MODE_OLDFILE))
- {
- InitIFFasDOS(Handle);
-
- if(!OpenIFF(Handle,IFFF_READ))
- {
- /* Collect version number ID if
- * available.
- */
-
- if(!PropChunks(Handle,&VersionProps[0],1))
- {
- /* The following line tells iffparse to stop at the
- * very beginning of a `Type' chunk contained in a
- * `TERM' FORM chunk.
- */
-
- if(!StopChunk(Handle,'TERM',Type))
- {
- /* Parse the file... */
-
- if(!ParseIFF(Handle,IFFPARSE_SCAN))
- {
- /* Did we get a version ID? */
-
- if(Prop = FindProp(Handle,'TERM','VERS'))
- {
- TermInfo = (struct TermInfo *)Prop -> sp_Data;
-
- /* Is it the file format we are able
- * to read?
- */
-
- if(TermInfo -> Version == TermVersion && TermInfo -> Revision <= TermRevision && TermInfo -> Revision >= 6)
- {
- /* The file read pointer is positioned
- * just in front of the first data
- * to be read, so let's don't disappoint
- * iffparse and read it.
- */
-
- if(ReadChunkBytes(Handle,Data,Size) == Size)
- Success = TRUE;
- }
- }
- }
- }
- }
-
- CloseIFF(Handle);
- }
-
- Close(Handle -> iff_Stream);
- }
-
- FreeIFF(Handle);
- }
-
- return(Success);
- }
-
- /* PushWindow(struct Window *Window):
- *
- * Push/PopWindow implement a single lifo window stack
- * which always updates the window to activate when
- * LSHIFT+RSHIFT+RETURN is pressed. This routine will
- * push a window on the stack.
- */
-
- VOID
- PushWindow(struct Window *Window)
- {
- if(WindowStackPtr < 5)
- {
- WindowStack[WindowStackPtr++] = Window;
-
- TopWindow = Window;
- }
- }
-
- /* PopWindow():
- *
- * Remove topmost window from window stack.
- */
-
- VOID
- PopWindow()
- {
- if(WindowStackPtr > 0)
- {
- WindowStackPtr--;
-
- if(WindowStackPtr)
- TopWindow = WindowStack[WindowStackPtr - 1];
- else
- TopWindow = Window;
- }
- }
-