home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / amiga / comms / comprgs / term232.lha / Source_Code / termSource / termAux.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-18  |  71.8 KB  |  3,704 lines

  1. /*
  2. **    $Id: termAux.c,v 1.18 92/08/18 16:11:50 olsen Sta Locker: olsen $
  3. **    $Revision: 1.18 $
  4. **    $Date: 92/08/18 16:11:50 $
  5. **
  6. **    Miscellaneous support routines
  7. **
  8. **    Copyright ⌐ 1990-1992 by Olaf `Olsen' Barthel & MXM
  9. **        All Rights Reserved
  10. */
  11.  
  12. #include "termGlobal.h"
  13.  
  14. enum    {    STATUSBOX_STATUS_FONT,STATUSBOX_PROTOCOL_TERMINAL,
  15.         STATUSBOX_RATE_PARAMETERS,STATUSBOX_TIME_ONLINE };
  16.  
  17.     /* The following static strings are displayed in the status
  18.      * window.
  19.      */
  20.  
  21. STATIC UBYTE *ConfigFont[2] =
  22. {
  23.     NULL,
  24.     NULL
  25. };
  26.  
  27. STATIC UBYTE *ConfigEmulation[4] =
  28. {
  29.     NULL,
  30.     NULL,
  31.     NULL,
  32.     NULL
  33. };
  34.  
  35. STATIC UBYTE *ConfigParity[5] =
  36. {
  37.     NULL,
  38.     NULL,
  39.     NULL,
  40.     NULL,
  41.     NULL
  42. };
  43.  
  44. STATIC UBYTE *ConfigStatus[7] =
  45. {
  46.     NULL,
  47.     NULL,
  48.     NULL,
  49.     NULL,
  50.     NULL,
  51.     NULL,
  52.     NULL
  53. };
  54.  
  55.     /* Block window nest count. */
  56.  
  57. STATIC WORD BlockNestCount;
  58.  
  59.     /* SetDialMenu(BYTE Mode):
  60.      *
  61.      *    Block or enable the dialing menu.
  62.      */
  63.  
  64. VOID
  65. SetDialMenu(BYTE Mode)
  66. {
  67.     if(Mode)
  68.     {
  69.         OnMenu(Window,FULLMENUNUM(3, 1,NOSUB));
  70.         OnMenu(Window,FULLMENUNUM(3, 2,NOSUB));
  71.     }
  72.     else
  73.     {
  74.         OffMenu(Window,FULLMENUNUM(3, 1,NOSUB));
  75.         OffMenu(Window,FULLMENUNUM(3, 2,NOSUB));
  76.     }
  77. }
  78.  
  79.     /* SetTransferMenu(BYTE Mode):
  80.      *
  81.      *    Block or enable the transfer menu.
  82.      */
  83.  
  84. VOID
  85. SetTransferMenu(BYTE Mode)
  86. {
  87.     if(Mode)
  88.     {
  89.         OnMenu(Window,FULLMENUNUM(4,NOITEM,NOSUB));
  90.         OnMenu(Window,FULLMENUNUM(7,9,NOSUB));
  91.     }
  92.     else
  93.     {
  94.         OffMenu(Window,FULLMENUNUM(4,NOITEM,NOSUB));
  95.         OffMenu(Window,FULLMENUNUM(7,9,NOSUB));
  96.     }
  97. }
  98.  
  99.     /* PickFont(struct Window *Window,STRPTR Name,WORD *Height,BYTE MonoSpaced):
  100.      *
  101.      *    Pick a font using asl.library
  102.      */
  103.  
  104. BYTE
  105. PickFont(struct Window *Window,STRPTR Name,WORD *Height,BYTE MonoSpaced)
  106. {
  107.     struct FontRequester    *Requester;
  108.     BYTE             Result = FALSE;
  109.  
  110.     if(Requester = (struct FontRequester *)AllocAslRequestTags(ASL_FontRequest,
  111.         ASL_Window,                    Window,
  112.         MonoSpaced ? ASL_FuncFlags : TAG_IGNORE,    FONF_FIXEDWIDTH,
  113.         ASL_MinHeight,                    8,
  114.     TAG_DONE))
  115.     {
  116.         if(AslRequestTags(Requester,
  117.             ASLFO_InitialName,    Name,
  118.             ASLFO_InitialSize,    *Height,
  119.         TAG_DONE))
  120.         {
  121.             strcpy(Name,Requester -> fo_Attr . ta_Name);
  122.  
  123.             *Height = Requester -> fo_Attr . ta_YSize;
  124.  
  125.             Result = TRUE;
  126.         }
  127.  
  128.         FreeAslRequest(Requester);
  129.     }
  130.  
  131.     return(Result);
  132. }
  133.  
  134.     /* ExtractString():
  135.      *
  136.      *    Extracts a string from a list separated by `|' characters.
  137.      */
  138.  
  139. UBYTE * __regargs
  140. ExtractString(UBYTE *String,UBYTE *Destination,BYTE ReturnEnd)
  141. {
  142.     UBYTE *OldString;
  143.  
  144.     if(ReturnEnd)
  145.         OldString = NULL;
  146.     else
  147.         OldString = String;
  148.  
  149.     while(*String)
  150.     {
  151.         if(*String == '|')
  152.         {
  153.             *Destination = 0;
  154.  
  155.             String++;
  156.  
  157.             if(*String)
  158.                 return(String);
  159.             else
  160.                 return(OldString);
  161.         }
  162.         else
  163.             *Destination++ = *String++;
  164.     }
  165.  
  166.     *Destination = 0;
  167.  
  168.     return(OldString);
  169. }
  170.  
  171.     /* DeleteInterleavedBitMap():
  172.      *
  173.      *    Delete an interleaved bitmap as allocated by
  174.      *    CreateInterleavedBitMap().
  175.      */
  176.  
  177. VOID __regargs
  178. DeleteInterleavedBitMap(struct BitMap *SomeBitMap)
  179. {
  180.     FreeVec(SomeBitMap -> Planes[0]);
  181.  
  182.     FreeVec(SomeBitMap);
  183. }
  184.  
  185.     /* CreateInterleavedBitMap():
  186.      *
  187.      *    With special thanks to Leo Schwab, this routine will create an
  188.      *    interleaved BitMap structure suitable for optimized blitter
  189.      *    access.
  190.      */
  191.  
  192. struct BitMap * __regargs
  193. CreateInterleavedBitMap(LONG Width,LONG Height,WORD Depth)
  194. {
  195.         /* A single plane BitMap cannot be interleaved. */
  196.  
  197.     if(Depth > 1)
  198.     {
  199.         struct BitMap *SomeBitMap;
  200.  
  201.             /* Allocate space for the bitmap structure. */
  202.  
  203.         if(SomeBitMap = (struct BitMap *)AllocVec(sizeof(struct BitMap),MEMF_ANY))
  204.         {
  205.                 /* Initialize with standard values, so we can check
  206.                  * whether the current system will be able to handle
  207.                  * an interleaved bitmap of the expected size.
  208.                  */
  209.  
  210.             InitBitMap(SomeBitMap,Depth,Width,Height);
  211.  
  212.                 /* Check for old standard blitter limits. */
  213.  
  214.             if(Height * Depth > 1024 || SomeBitMap -> BytesPerRow * Depth > 126)
  215.             {
  216.                     /* The current space requirements will operate
  217.                      * correctly only on a system equipped with a
  218.                      * Fat Agnus (or successor) chip, let's see
  219.                      * if we can find one.
  220.                      */
  221.  
  222.                 if(!(GfxBase -> ChipRevBits0 & GFXF_BIG_BLITS))
  223.                 {
  224.                         /* Looks like a Big or old (A1000)
  225.                          * Agnus chip.
  226.                          */
  227.  
  228.                     FreeVec(SomeBitMap);
  229.  
  230.                     return(NULL);
  231.                 }
  232.                 else
  233.                 {
  234.                         /* Unlikely, put still not impossible: check for
  235.                          * Fat Agnus size limits...
  236.                          */
  237.  
  238.                     if(Height * Depth > 32768 || SomeBitMap -> BytesPerRow * Depth > 4096)
  239.                     {
  240.                         FreeVec(SomeBitMap);
  241.  
  242.                         return(NULL);
  243.                     }
  244.                 }
  245.             }
  246.  
  247.                 /* Initialize to interleaved BitMap values. */
  248.  
  249.             InitBitMap(SomeBitMap,1,Width,Height * Depth);
  250.  
  251.                 /* Allocate plane data. */
  252.  
  253.             if(SomeBitMap -> Planes[0] = (PLANEPTR)AllocVec(SomeBitMap -> BytesPerRow * SomeBitMap -> Rows,MEMF_CHIP))
  254.             {
  255.                 PLANEPTR    Base;
  256.                 WORD        i,
  257.                         Size;
  258.  
  259.                     /* Remember previous data. */
  260.  
  261.                 Base = SomeBitMap -> Planes[0];
  262.                 Size = SomeBitMap -> BytesPerRow;
  263.  
  264.                     /* Clear the bitmap. */
  265.  
  266.                 BltBitMap(SomeBitMap,0,0,SomeBitMap,0,0,Width,Height,0,~0,NULL);
  267.  
  268.                     /* Reinitialize. */
  269.  
  270.                 InitBitMap(SomeBitMap,Depth,Width,Height);
  271.  
  272.                     /* Modify for interleaved look. */
  273.  
  274.                 SomeBitMap -> BytesPerRow *= Depth;
  275.  
  276.                     /* Initialize the single planes. */
  277.  
  278.                 for(i = 0 ; i < Depth ; i++)
  279.                 {
  280.                     SomeBitMap -> Planes[i] = Base;
  281.  
  282.                     Base += Size;
  283.                 }
  284.  
  285.                     /* Return the ready bitmap. */
  286.  
  287.                 return(SomeBitMap);
  288.             }
  289.  
  290.                 /* Deallocate memory. */
  291.  
  292.             FreeVec(SomeBitMap);
  293.         }
  294.     }
  295.  
  296.         /* Return failure. */
  297.  
  298.     return(NULL);
  299. }
  300.  
  301.     /* GetListNode(LONG Offset,struct List *List):
  302.      *
  303.      *    Return the n-th Node entry in a standard exec list.
  304.      */
  305.  
  306. struct Node *
  307. GetListNode(LONG Offset,struct List *List)
  308. {
  309.     struct Node    *Node;
  310.     LONG         i;
  311.  
  312.     Node = List -> lh_Head;
  313.  
  314.     for(i = 0 ; i < Offset ; i++)
  315.     {
  316.         if(!Node -> ln_Succ -> ln_Succ)
  317.             return(NULL);
  318.  
  319.         Node = Node -> ln_Succ;
  320.     }
  321.  
  322.     return(Node);
  323. }
  324.  
  325.     /* GetConUnit():
  326.      *
  327.      *    Extract the ConUnit pointer from the current output stream
  328.      *    console.
  329.      */
  330.  
  331. struct ConUnit *
  332. GetConUnit(struct MsgPort *ConsoleTask)
  333. {
  334.     struct InfoData    *InfoData;
  335.     struct ConUnit    *ConUnit = NULL;
  336.  
  337.     if(!ConsoleTask)
  338.     {
  339.         ConsoleTask = (struct MsgPort *)((struct Process *)SysBase -> ThisTask) -> pr_ConsoleTask;
  340.  
  341.         if(!TypeOfMem(ConsoleTask))
  342.             return(NULL);
  343.     }
  344.  
  345.     if(InfoData = (struct InfoData *)AllocVec(sizeof(struct InfoData),MEMF_ANY|MEMF_CLEAR))
  346.     {
  347.             /* Send the inquiry packet to the console task. */
  348.  
  349.         if(DoPkt1(ConsoleTask,ACTION_DISK_INFO,MKBADDR(InfoData)))
  350.             ConUnit = (struct ConUnit *)((struct IOStdReq *)InfoData -> id_InUse) -> io_Unit;
  351.  
  352.         FreeVec(InfoData);
  353.     }
  354.  
  355.     return(ConUnit);
  356. }
  357.  
  358.     /* AddDownloadObject(UBYTE *Line):
  359.      *
  360.      *    Add another downloaded object to the list.
  361.      */
  362.  
  363. VOID
  364. AddDownloadObject(UBYTE *Line)
  365. {
  366.     struct Node *SomeNode;
  367.  
  368.         /* Allocate space for the node itself and the
  369.          * string to be put into the node name.
  370.          */
  371.  
  372.     if(SomeNode = (struct Node *)AllocVec(sizeof(struct Node) + strlen(Line) + 1,MEMF_ANY|MEMF_CLEAR))
  373.     {
  374.             /* Block list modification. */
  375.  
  376.         ObtainSemaphore(DownloadSemaphore);
  377.  
  378.             /* Enter the name. */
  379.  
  380.         SomeNode -> ln_Name = (UBYTE *)(SomeNode + 1);
  381.  
  382.             /* Copy the line over. */
  383.  
  384.         strcpy(SomeNode -> ln_Name,Line);
  385.  
  386.             /* Add it to the list. */
  387.  
  388.         AddTail(&DownloadList,SomeNode);
  389.  
  390.             /* Increment number of downloads. */
  391.  
  392.         DownloadLineCount++;
  393.  
  394.         ReleaseSemaphore(DownloadSemaphore);
  395.     }
  396. }
  397.  
  398.     /* ClearDownloadObjects():
  399.      *
  400.      *    Clear the list of downloaded objects.
  401.      */
  402.  
  403. VOID
  404. ClearDownloadObjects()
  405. {
  406.     struct Node *SomeNode,*NextNode;
  407.  
  408.     ObtainSemaphore(DownloadSemaphore);
  409.  
  410.     SomeNode = DownloadList . lh_Head;
  411.  
  412.     while(SomeNode -> ln_Succ)
  413.     {
  414.         NextNode = SomeNode -> ln_Succ;
  415.  
  416.         Remove(SomeNode);
  417.  
  418.         FreeVec(SomeNode);
  419.  
  420.         SomeNode = NextNode;
  421.     }
  422.  
  423.     DownloadNode = NULL;
  424.  
  425.     DownloadLineCount = 0;
  426.  
  427.     ReleaseSemaphore(DownloadSemaphore);
  428. }
  429.  
  430.     /* SequenceFilter(UBYTE Char):
  431.      *
  432.      *    Yet another byte sequence filter, this time it's the
  433.      *    ARexx interface to make the call.
  434.      */
  435.  
  436. struct ScanNode *
  437. SequenceFilter(UBYTE Char)
  438. {
  439.     struct ScanNode    *SomeNode,*Matching = NULL;
  440.     BYTE         Matches = 0;
  441.  
  442.         /* Convert input character to upper case. */
  443.  
  444.     Char = ToUpper(Char);
  445.  
  446.         /* Get the first node in the list. */
  447.  
  448.     SomeNode = (struct ScanNode *)SequenceList . lh_Head;
  449.  
  450.         /* Scan until the last node is found. */
  451.  
  452.     while(SomeNode -> Node . mln_Succ)
  453.     {
  454.             /* This sequence had a couple of matches. */
  455.  
  456.         if(SomeNode -> Count == SequenceCount)
  457.         {
  458.                 /* The next character in the sequence
  459.                  * still matches.
  460.                  */
  461.  
  462.             if(Char == SomeNode -> Sequence[SequenceCount])
  463.             {
  464.                     /* Increase number of matching
  465.                      * characters.
  466.                      */
  467.  
  468.                 SomeNode -> Count++;
  469.  
  470.                     /* If there's another character
  471.                      * in the sequence, increase
  472.                      * the match counter.
  473.                      */
  474.  
  475.                 if(SomeNode -> Sequence[SequenceCount + 1])
  476.                     Matches++;
  477.                 else
  478.                 {
  479.                         /* We were able to make
  480.                          * a perfect match.
  481.                          */
  482.  
  483.                     Matches = 0;
  484.  
  485.                     Matching = SomeNode;
  486.                 }
  487.             }
  488.         }
  489.  
  490.             /* Skip to the next node. */
  491.  
  492.         SomeNode = (struct ScanNode *)SomeNode -> Node . mln_Succ;
  493.     }
  494.  
  495.     if(!Matches)
  496.     {
  497.             /* Clear the list entry counters. */
  498.  
  499.         if(SequenceCount)
  500.         {
  501.             SomeNode = (struct ScanNode *)SequenceList . lh_Head;
  502.  
  503.             while(SomeNode -> Node . mln_Succ)
  504.             {
  505.                 SomeNode -> Count = 0;
  506.  
  507.                 SomeNode = (struct ScanNode *)SomeNode -> Node . mln_Succ;
  508.             }
  509.  
  510.             SequenceCount = 0;
  511.         }
  512.     }
  513.     else
  514.         SequenceCount++;
  515.  
  516.     return(Matching);
  517. }
  518.  
  519.     /* AddSequenceObject(UBYTE *Sequence):
  520.      *
  521.      *    Add another sequence to the list of byte sequences
  522.      *    the routine above will look at whilst parsing.
  523.      */
  524.  
  525. VOID
  526. AddSequenceObject(UBYTE *Sequence)
  527. {
  528.     struct ScanNode *SomeNode;
  529.  
  530.     if(SomeNode = AllocVec(sizeof(struct ScanNode) + strlen(Sequence) + 1,MEMF_ANY|MEMF_CLEAR))
  531.     {
  532.         WORD i;
  533.  
  534.         SomeNode -> Sequence = (UBYTE *)(SomeNode + 1);
  535.  
  536.         for(i = 0 ; i <= strlen(Sequence) ; i++)
  537.             SomeNode -> Sequence[i] = ToUpper(Sequence[i]);
  538.  
  539.         AddTail(&SequenceList,(struct Node *)SomeNode);
  540.     }
  541. }
  542.  
  543.     /* ClearSequenceObjects():
  544.      *
  545.      *    Clear the list of scan sequences.
  546.      */
  547.  
  548. VOID
  549. ClearSequenceObjects()
  550. {
  551.     struct Node *SomeNode,*NextNode;
  552.  
  553.     SomeNode = SequenceList . lh_Head;
  554.  
  555.     while(SomeNode -> ln_Succ)
  556.     {
  557.         NextNode = SomeNode -> ln_Succ;
  558.  
  559.         Remove(SomeNode);
  560.  
  561.         FreeVec(SomeNode);
  562.  
  563.         SomeNode = NextNode;
  564.     }
  565. }
  566.  
  567.     /* LogAction(UBYTE *String,...):
  568.      *
  569.      *    Write an action to the default log file.
  570.      */
  571.  
  572. VOID __stdargs
  573. LogAction(UBYTE *String,...)
  574. {
  575.     if(Config . LogActions && Config . LogFile[0])
  576.     {
  577.         UBYTE    DummyBuffer[512];
  578.         BPTR    File;
  579.  
  580.         va_list    VarArgs;
  581.  
  582.             /* Build a valid string. */
  583.  
  584.         va_start(VarArgs,String);
  585.         VSPrintf(DummyBuffer,String,VarArgs);
  586.         va_end(VarArgs);
  587.  
  588.             /* Does the log file already exist? */
  589.  
  590.         if(GetFileSize(Config . LogFile))
  591.         {
  592.                 /* It does, let's append the data. */
  593.  
  594.             if(File = Open(Config . LogFile,MODE_READWRITE))
  595.             {
  596.                 if(Seek(File,0,OFFSET_END) == -1)
  597.                 {
  598.                     Close(File);
  599.  
  600.                     File = NULL;
  601.                 }
  602.             }
  603.         }
  604.         else
  605.         {
  606.                 /* Create a new file. */
  607.  
  608.             if(File = Open(Config . LogFile,MODE_NEWFILE))
  609.                 FPrintf(File,LocaleString(MSG_TERMAUX_DATE_TIME_ACTION_TXT));
  610.         }
  611.  
  612.             /* The file is open, build the date/time string and
  613.              * write the log action.
  614.              */
  615.  
  616.         if(File)
  617.         {
  618.             UBYTE        TimeBuffer[20],DateBuffer[20];
  619.             struct DateTime    DateTime;
  620.  
  621.                 /* Obtain current time. */
  622.  
  623.             DateStamp(&DateTime . dat_Stamp);
  624.  
  625.                 /* Convert it to human readable form. */
  626.  
  627.             DateTime . dat_Format    = FORMAT_DOS;
  628.             DateTime . dat_Flags    = 0;
  629.             DateTime . dat_StrDay    = NULL;
  630.             DateTime . dat_StrDate    = DateBuffer;
  631.             DateTime . dat_StrTime    = TimeBuffer;
  632.  
  633.                 /* Conversion succeeded? */
  634.  
  635.             if(DateToStr(&DateTime))
  636.                 FPrintf(File,"%s %s %s\n",DateBuffer,TimeBuffer,DummyBuffer);
  637.  
  638.                 /* Done! */
  639.  
  640.             Close(File);
  641.         }
  642.     }
  643. }
  644.  
  645.     /* FlushMsg(struct Window *Window):
  646.      *
  647.      *    Cancel all pending messages of a window.
  648.      */
  649.  
  650. VOID
  651. FlushMsg(struct Window *Window)
  652. {
  653.     struct IntuiMessage *Massage;
  654.  
  655.     while(Massage = (struct IntuiMessage *)GetMsg(Window -> UserPort))
  656.         ReplyMsg(&Massage -> ExecMessage);
  657. }
  658.  
  659.     /* GetString(UBYTE *Prompt,UBYTE *Buffer):
  660.      *
  661.      *    Get a string from the user, very much the same as xpr_gets,
  662.      *    but also including the `Load File' gadget.
  663.      */
  664.  
  665. BYTE
  666. GetString(UBYTE *Prompt,UBYTE *Buffer)
  667. {
  668.     struct Gadget        *GadgetList = NULL;
  669.     struct Gadget        *GadgetArray[4];
  670.     struct Window        *PanelWindow;
  671.     UBYTE             DummyBuffer[256];
  672.     struct FileRequester    *FileRequest;
  673.     BYTE             Success = FALSE;
  674.  
  675.     if(CreateAllGetsGadgets(TRUE,Buffer,Prompt,&GadgetArray[0],&GadgetList,VisualInfo,Screen -> WBorTop + Screen -> Font -> ta_YSize + 1,Screen))
  676.     {
  677.         if(PanelWindow = OpenWindowTags(NULL,
  678.             WA_Left,    (Screen -> Width    - SZ_GetWindowWidth())    / 2,
  679.             WA_Top,        (Screen -> Height    - SZ_GetWindowHeight())    / 2,
  680.             WA_Width,    SZ_GetWindowWidth(),
  681.             WA_Height,    SZ_GetWindowHeight(),
  682.  
  683.             WA_Activate,    TRUE,
  684.             WA_DragBar,    TRUE,
  685.             WA_DepthGadget,    TRUE,
  686.             WA_CloseGadget,    TRUE,
  687.             WA_RMBTrap,    TRUE,
  688.             WA_CustomScreen,Screen,
  689.             WA_IDCMP,    IDCMP_GADGETDOWN | IDCMP_ACTIVEWINDOW | IDCMP_CLOSEWINDOW | IDCMP_GADGETUP | IDCMP_VANILLAKEY | BUTTONIDCMP | STRINGIDCMP,
  690.             WA_Title,    LocaleString(MSG_GLOBAL_ENTER_TEXT_TXT),
  691.         TAG_DONE))
  692.         {
  693.             struct IntuiMessage    *Massage;
  694.             ULONG             Class,Code;
  695.             struct Gadget        *Gadget;
  696.             BYTE             Terminated = FALSE;
  697.  
  698.             PushWindow(PanelWindow);
  699.  
  700.             AddGList(PanelWindow,GadgetList,(UWORD)-1,(UWORD)-1,NULL);
  701.             RefreshGList(GadgetList,PanelWindow,NULL,(UWORD)-1);
  702.             GT_RefreshWindow(PanelWindow,NULL);
  703.  
  704.             ActiveGadget = NULL;
  705.  
  706.             while(!Terminated)
  707.             {
  708.                 WaitPort(PanelWindow -> UserPort);
  709.  
  710.                 while(!Terminated && (Massage = (struct IntuiMessage *)GT_GetIMsg(PanelWindow -> UserPort)))
  711.                 {
  712.                     Class    = Massage -> Class;
  713.                     Code    = Massage -> Code;
  714.                     Gadget    = (struct Gadget *)Massage -> IAddress;
  715.  
  716.                     GT_ReplyIMsg(Massage);
  717.  
  718.                     if(Class == IDCMP_VANILLAKEY)
  719.                         KeySelect(GadgetArray,3,Code,PanelWindow,&Gadget,&Class,&Code);
  720.  
  721.                     if(Class == IDCMP_GADGETDOWN)
  722.                     {
  723.                         if((Gadget -> GadgetType & GTYP_GTYPEMASK) == GTYP_STRGADGET)
  724.                             ActiveGadget = Gadget;
  725.                     }
  726.  
  727.                     if(Class == IDCMP_ACTIVEWINDOW && ActiveGadget)
  728.                         ActivateGadget(ActiveGadget,PanelWindow,NULL);
  729.  
  730.                     if(Class == IDCMP_CLOSEWINDOW)
  731.                         Terminated = TRUE;
  732.  
  733.                     if(Class == IDCMP_GADGETUP)
  734.                     {
  735.                         switch(Gadget -> GadgetID)
  736.                         {
  737.                             case 0: if(Code != '\t')
  738.                                 {
  739.                                     strcpy(Buffer,GT_STRING(GadgetArray[0]));
  740.  
  741.                                     Success = TRUE;
  742.  
  743.                                     Terminated = TRUE;
  744.                                 }
  745.  
  746.                                 break;
  747.  
  748.                             case 1:    strcpy(Buffer,GT_STRING(GadgetArray[0]));
  749.  
  750.                                 Success = TRUE;
  751.  
  752.                                 Terminated = TRUE;
  753.                                 break;
  754.  
  755.                             case 2:    BlockWindow(PanelWindow);
  756.  
  757.                                 if(FileRequest = GetFile(LocaleString(MSG_TERMAUX_LOAD_FILE_TXT),"","",DummyBuffer,NULL,FALSE,FALSE,FALSE,LocaleString(MSG_GLOBAL_LOAD_TXT)))
  758.                                 {
  759.                                     GT_SetGadgetAttrs(GadgetArray[0],PanelWindow,NULL,
  760.                                         GTST_String,DummyBuffer,
  761.                                     TAG_DONE);
  762.  
  763.                                     FreeAslRequest(FileRequest);
  764.                                 }
  765.  
  766.                                 ReleaseWindow(PanelWindow);
  767.  
  768.                                 break;
  769.  
  770.                             case 3:    Terminated = TRUE;
  771.                                 break;
  772.                         }
  773.                     }
  774.                 }
  775.             }
  776.  
  777.             ActiveGadget = NULL;
  778.  
  779.             RemoveGList(PanelWindow,GadgetList,(UWORD)-1);
  780.  
  781.             PopWindow();
  782.  
  783.             CloseWindow(PanelWindow);
  784.         }
  785.     }
  786.  
  787.     FreeGadgets(GadgetList);
  788.  
  789.     return(Success);
  790. }
  791.  
  792.     /* WakeUp(struct Window *Window):
  793.      *
  794.      *    Pop a window to the front and alert the user.
  795.      */
  796.  
  797. VOID __regargs
  798. WakeUp(struct Window *Window)
  799. {
  800.     if(Window)
  801.     {
  802.         if(Config . Alert == ALERT_SCREEN || Config . Alert == ALERT_BEEP_SCREEN)
  803.         {
  804.             if(Window -> WScreen -> LeftEdge > 0)
  805.             {
  806.                 if(Window -> WScreen -> TopEdge > 0)
  807.                     MoveScreen(Window -> WScreen,-Window -> WScreen -> LeftEdge,-Window -> WScreen -> TopEdge);
  808.                 else
  809.                     MoveScreen(Window -> WScreen,-Window -> WScreen -> LeftEdge,0);
  810.             }
  811.             else
  812.             {
  813.                 if(Window -> WScreen -> TopEdge > 0)
  814.                     MoveScreen(Window -> WScreen,0,-Window -> WScreen -> TopEdge);
  815.             }
  816.  
  817.             WindowToFront(Window);
  818.  
  819.             ScreenToFront(Window -> WScreen);
  820.         }
  821.     }
  822.  
  823.     if(Config . Alert == ALERT_BEEP || Config . Alert == ALERT_BEEP_SCREEN)
  824.         Beep();
  825. }
  826.  
  827.     /* SendAmigaDOSCommand(UBYTE *Name):
  828.      *
  829.      *    Let the current default Shell execute an AmigaDOS
  830.      *    command. Block until the command has returned.
  831.      */
  832.  
  833. VOID
  834. SendAmigaDOSCommand(UBYTE *Name)
  835. {
  836.     BYTE DummyBuffer[2];
  837.     BPTR File;
  838.  
  839.         /* Let the asynchronous Rexx server pick up and process
  840.          * all incoming messages rather than sending them to the
  841.          * main process (hopefully avoids deadlock situations).
  842.          */
  843.  
  844.     BatchMode = TRUE;
  845.  
  846.         /* Open the console window or whatever the user
  847.          * wants us to open here.
  848.          */
  849.  
  850.     if(File = Open(WindowName,MODE_NEWFILE))
  851.     {
  852.         struct ConUnit    *ConUnit = GetConUnit(((struct FileHandle *)BADDR(File)) -> fh_Type);
  853.         STRPTR         WindowSpec;
  854.  
  855.         if(ConUnit)
  856.         {
  857.             if(ConUnit -> cu_Window)
  858.                 BumpWindow(ConUnit -> cu_Window);
  859.         }
  860.  
  861.             /* Make the Shell execute the command. */
  862.  
  863.         SystemTags(Name,SYS_Output,File,TAG_DONE);
  864.  
  865.             /* Wait for some impressive user action. */
  866.  
  867.         if(IsInteractive(File) && (WindowSpec = FilePart(WindowName)))
  868.         {
  869.             BYTE IsAuto = FALSE;
  870.             WORD i;
  871.  
  872.             for(i = 0 ; i < strlen(WindowSpec) - 3 ; i++)
  873.             {
  874.                 if(!Strnicmp(&WindowSpec[i],"WAIT",4))
  875.                 {
  876.                     IsAuto = TRUE;
  877.  
  878.                     break;
  879.                 }
  880.             }
  881.  
  882.             if(!IsAuto)
  883.             {
  884.                 Write(File,LocaleString(MSG_TERMAUX_PRESS_RETURN_TO_CONTINUE_TXT),strlen(LocaleString(MSG_TERMAUX_PRESS_RETURN_TO_CONTINUE_TXT)));
  885.  
  886.                 Read(File,DummyBuffer,1);
  887.             }
  888.         }
  889.  
  890.         Close(File);
  891.     }
  892.  
  893.         /* Bring the `term' main screen to the front and
  894.          * fall back into asynchronous Rexx message processing.
  895.          */
  896.  
  897.     BumpWindow(Window);
  898.  
  899.     BatchMode = FALSE;
  900. }
  901.  
  902.     /* RexxBackgroundServer():
  903.      *
  904.      *    The background process to handle the rexx
  905.      *    massaging.
  906.      */
  907.  
  908. VOID __saveds
  909. RexxBackgroundServer()
  910. {
  911.     BPTR         OldCOS,OldCIS,NewCOS,NewCIS;
  912.     struct MsgPort    *OldConsoleTask,*ReplyPort;
  913.  
  914.     BYTE         DummyBuffer[2];
  915.  
  916.     struct RexxMsg    *RexxMsg;
  917.     struct Message    *SetupMsg;
  918.  
  919.         /* Look who we are. */
  920.  
  921.     RexxBackgroundProcess = (struct Process *)SysBase -> ThisTask;
  922.  
  923.         /* Wait for startup message. */
  924.  
  925.     WaitPort(&RexxBackgroundProcess -> pr_MsgPort);
  926.  
  927.         /* Pick the message up. */
  928.  
  929.     SetupMsg = GetMsg(&RexxBackgroundProcess -> pr_MsgPort);
  930.  
  931.         /* Create a reply port the Rexx message is to
  932.          * return to after processing.
  933.          */
  934.  
  935.     if(ReplyPort = (struct MsgPort *)CreateMsgPort())
  936.     {
  937.             /* Remember previous I/O streams and
  938.              * console handler.
  939.              */
  940.  
  941.         OldCOS        = RexxBackgroundProcess -> pr_COS;
  942.         OldCIS        = RexxBackgroundProcess -> pr_CIS;
  943.  
  944.         OldConsoleTask    = RexxBackgroundProcess -> pr_ConsoleTask;
  945.  
  946.             /* The following lines perform an `almost illegal'
  947.              * action: new console I/O streams are opened for
  948.              * the `term' main process. This is due to a rather
  949.              * helpful Rexx server feature. Errors, messages
  950.              * and other data are sent to the current output
  951.              * stream.
  952.              */
  953.  
  954.         if(NewCIS = Open(WindowName,MODE_NEWFILE))
  955.         {
  956.             struct FileHandle    *FileHandle = (struct FileHandle *)BADDR(NewCIS);
  957.             struct ConUnit        *ConUnit = GetConUnit(((struct FileHandle *)BADDR(NewCIS)) -> fh_Type);
  958.  
  959.                 /* Lock until we're done with the forgery. */
  960.  
  961.             Forbid();
  962.  
  963.             RexxBackgroundProcess -> pr_ConsoleTask    = (APTR)FileHandle -> fh_Type;
  964.  
  965.             RexxBackgroundProcess -> pr_CIS        = NewCIS;
  966.             RexxBackgroundProcess -> pr_COS        = NewCOS = Open("*",MODE_NEWFILE);
  967.  
  968.             Permit();
  969.  
  970.             RexxWindow = NULL;
  971.  
  972.             if(ConUnit)
  973.             {
  974.                 if(RexxWindow = ConUnit -> cu_Window)
  975.                     BumpWindow(RexxWindow);
  976.             }
  977.  
  978.                 /* Send the command and wait for a reply. */
  979.  
  980.             if(SendRexxCommand(ReplyPort,SetupMsg -> mn_Node . ln_Name,"term",TermIDString))
  981.             {
  982.                 ULONG SignalSet;
  983.  
  984.                 do
  985.                 {
  986.                     SignalSet = Wait((1 << ReplyPort -> mp_SigBit) | SIGBREAKF_CTRL_C);
  987.  
  988.                     if(SignalSet & SIGBREAKF_CTRL_C)
  989.                         Signal(ThisProcess,SIGBREAKF_CTRL_D);
  990.                 }
  991.                 while(!(SignalSet & (1 << ReplyPort -> mp_SigBit)));
  992.  
  993.                     /* Pick up the RexxMsg (SendRexxCommand
  994.                      * had allocated it for us) and
  995.                      * examine the return codes.
  996.                      */
  997.  
  998.                 if(RexxMsg = (struct RexxMsg *)GetMsg(ReplyPort))
  999.                 {
  1000.                     if(!ExitQuietly)
  1001.                     {
  1002.                         STRPTR WindowSpec;
  1003.  
  1004.                         /* This doesn't look too
  1005.                          * good, does it?
  1006.                          */
  1007.  
  1008.                         if(RexxMsg -> rm_Result1)
  1009.                             FPrintf(NewCIS,LocaleString(MSG_TERMAUX_COMMAND_HAS_TERMINATED_TXT),SetupMsg -> mn_Node . ln_Name,RexxMsg -> rm_Result1,RexxMsg -> rm_Result2);
  1010.  
  1011.                         /* Show our hand and return
  1012.                          * to the usual business.
  1013.                          */
  1014.  
  1015.                         if(IsInteractive(NewCIS) && (WindowSpec = FilePart(WindowName)))
  1016.                         {
  1017.                             BYTE IsAuto = FALSE;
  1018.                             WORD i;
  1019.  
  1020.                             for(i = 0 ; i < strlen(WindowSpec) - 3 ; i++)
  1021.                             {
  1022.                                 if(!Strnicmp(&WindowSpec[i],"WAIT",4))
  1023.                                 {
  1024.                                     IsAuto = TRUE;
  1025.  
  1026.                                     break;
  1027.                                 }
  1028.                             }
  1029.  
  1030.                             if(!IsAuto)
  1031.                             {
  1032.                                 Write(NewCIS,LocaleString(MSG_TERMAUX_PRESS_RETURN_TO_CONTINUE_TXT),strlen(LocaleString(MSG_TERMAUX_PRESS_RETURN_TO_CONTINUE_TXT)));
  1033.  
  1034.                                 Read(NewCIS,DummyBuffer,1);
  1035.                             }
  1036.                         }
  1037.  
  1038.                         Term2Front();
  1039.                     }
  1040.                     else
  1041.                         ExitQuietly = FALSE;
  1042.  
  1043.                         /* Release the message. */
  1044.  
  1045.                     FreeRexxCommand(RexxMsg);
  1046.                 }
  1047.             }
  1048.  
  1049.             Forbid();
  1050.  
  1051.             RexxWindow = NULL;
  1052.  
  1053.             Permit();
  1054.  
  1055.             BumpWindow(Window);
  1056.  
  1057.                 /* Close our fake I/O streams. */
  1058.  
  1059.             Forbid();
  1060.  
  1061.             Close(NewCIS);
  1062.             Close(NewCOS);
  1063.  
  1064.                 /* And install the previous pointers. */
  1065.  
  1066.             RexxBackgroundProcess -> pr_ConsoleTask    = (APTR)OldConsoleTask;
  1067.  
  1068.             RexxBackgroundProcess -> pr_CIS        = OldCIS;
  1069.             RexxBackgroundProcess -> pr_COS        = OldCOS;
  1070.  
  1071.             Permit();
  1072.         }
  1073.  
  1074.             /* Remove the reply port. */
  1075.  
  1076.         DeleteMsgPort(ReplyPort);
  1077.     }
  1078.  
  1079.         /* We are done, lock and reply the message causing the
  1080.          * main process to return to the input loop.
  1081.          */
  1082.  
  1083.     Forbid();
  1084.  
  1085.     ReplyMsg(SetupMsg);
  1086.  
  1087.     RexxBackgroundProcess = NULL;
  1088. }
  1089.  
  1090.     /* SendARexxCommand(UBYTE *Name):
  1091.      *
  1092.      *    Let the ARexx server execute a command (or a script
  1093.      *    file if necessary) and block until the command
  1094.      *    has returned.
  1095.      */
  1096.  
  1097. VOID
  1098. SendARexxCommand(UBYTE *Name)
  1099. {
  1100.     struct Process    *BackgroundProcess;
  1101.     struct Message    *SetupMsg;
  1102.     struct MsgPort    *ReplyPort;
  1103.  
  1104.     ULONG         SignalSet;
  1105.  
  1106.         /* Create a reply port for the info message. */
  1107.  
  1108.     if(ReplyPort = CreateMsgPort())
  1109.     {
  1110.             /* Allocate the message body. */
  1111.  
  1112.         if(SetupMsg = (struct Message *)AllocVec(sizeof(struct Message),MEMF_ANY|MEMF_CLEAR))
  1113.         {
  1114.                 /* Set up the message itself. */
  1115.  
  1116.             SetupMsg -> mn_Node . ln_Name    = Name;
  1117.             SetupMsg -> mn_ReplyPort    = ReplyPort;
  1118.             SetupMsg -> mn_Length        = sizeof(struct Message);
  1119.  
  1120.                 /* Create the background process which will
  1121.                  * handle all the messy rexx message sending
  1122.                  * for us.
  1123.                  */
  1124.  
  1125.             if(BackgroundProcess = (struct Process *)CreateNewProcTags(
  1126.                 NP_Entry,    RexxBackgroundServer,
  1127.                 NP_Name,    "term ARexx background process",
  1128.                 NP_StackSize,    16384,
  1129.             TAG_END))
  1130.             {
  1131.                 SetSignal(0,SIGBREAKF_CTRL_D);
  1132.  
  1133.                     /* Send the startup message. */
  1134.  
  1135.                 PutMsg(&BackgroundProcess -> pr_MsgPort,SetupMsg);
  1136.  
  1137.                     /* Go into loop and wait for the
  1138.                      * background process to return.
  1139.                      */
  1140.  
  1141.                 FOREVER
  1142.                 {
  1143.                     SignalSet = Wait(SIG_REXX | (1 << ReplyPort -> mp_SigBit));
  1144.  
  1145.                         /* Yet another rexx message. */
  1146.  
  1147.                     if(SignalSet & SIG_REXX)
  1148.                         HandleRexx();
  1149.  
  1150.                         /* The background server has
  1151.                          * finished.
  1152.                          */
  1153.  
  1154.                     if(SignalSet & (1 << ReplyPort -> mp_SigBit))
  1155.                         break;
  1156.                 }
  1157.  
  1158.                 SetSignal(0,SIGBREAKF_CTRL_D);
  1159.             }
  1160.  
  1161.                 /* Free the message. */
  1162.  
  1163.             FreeVec(SetupMsg);
  1164.         }
  1165.  
  1166.             /* Delete the reply port. */
  1167.  
  1168.         DeleteMsgPort(ReplyPort);
  1169.     }
  1170. }
  1171.  
  1172.     /* ahtoi(UBYTE *String):
  1173.      *
  1174.      *    Turn a hexadecimal string into an integer (borrowed from
  1175.      *    Matt Dillon's dmouse.c).
  1176.      */
  1177.  
  1178. LONG
  1179. ahtoi(UBYTE *String)
  1180. {
  1181.     LONG Value = 0;
  1182.     UBYTE c;
  1183.  
  1184.     while(c = *String)
  1185.     {
  1186.         Value <<= 4;
  1187.  
  1188.         if(c >= '0' && c <= '9')
  1189.             Value |= (c & 15);
  1190.         else
  1191.             Value |= (c & 15) + 9;
  1192.  
  1193.         ++String;
  1194.     }
  1195.  
  1196.     return(Value);
  1197. }
  1198.  
  1199.     /* BlockWindow(struct Window *Window):
  1200.      *
  1201.      *    Block a window (show a wait mouse pointer, block
  1202.      *    windows, custom and system gadgets) by adding
  1203.      *    an invisible requester to it.
  1204.      */
  1205.  
  1206. VOID __regargs
  1207. BlockWindow(struct Window *Window)
  1208. {
  1209.     if(Window)
  1210.     {
  1211.         struct Requester    *InvisibleRequest = NULL;
  1212.         WORD             i;
  1213.  
  1214.         Forbid();
  1215.  
  1216.             /* Is this window already on the list? */
  1217.  
  1218.         for(i = 0 ; i < 10 ; i++)
  1219.         {
  1220.             if(RequesterList[i] . RWindow == Window)
  1221.             {
  1222.                 Permit();
  1223.  
  1224.                 return;
  1225.             }
  1226.         }
  1227.  
  1228.             /* Look for an empty slot. */
  1229.  
  1230.         for(i = 0 ; i < 10 ; i++)
  1231.         {
  1232.             if(!RequesterList[i] . RWindow)
  1233.             {
  1234.                 InvisibleRequest = &RequesterList[i];
  1235.  
  1236.                 InvisibleRequest -> RWindow = (struct Window *)~0;
  1237.  
  1238.                 break;
  1239.             }
  1240.         }
  1241.  
  1242.         Permit();
  1243.  
  1244.             /* Install the wait mouse pointer. */
  1245.  
  1246.         SetWait(Window);
  1247.  
  1248.             /* Install the requester if possible. */
  1249.  
  1250.         if(InvisibleRequest)
  1251.             Request(InvisibleRequest,Window);
  1252.     }
  1253. }
  1254.  
  1255.     /* ReleaseWindow(struct Window *Window):
  1256.      *
  1257.      *    Release a window blocked by `BlockWindow()'.
  1258.      */
  1259.  
  1260. VOID __regargs
  1261. ReleaseWindow(struct Window *Window)
  1262. {
  1263.     if(Window)
  1264.     {
  1265.         struct Requester    *InvisibleRequest = NULL;
  1266.         WORD             i;
  1267.  
  1268.             /* Search all slots for the requester to block this window. */
  1269.  
  1270.         for(i = 0 ; i < 10 ; i++)
  1271.         {
  1272.             if(RequesterList[i] . RWindow == Window)
  1273.             {
  1274.                 InvisibleRequest = &RequesterList[i];
  1275.  
  1276.                 break;
  1277.             }
  1278.         }
  1279.  
  1280.             /* Restore the mouse pointer. */
  1281.  
  1282.         ClearPointer(Window);
  1283.  
  1284.             /* If disabled, restore the window. */
  1285.  
  1286.         if(InvisibleRequest)
  1287.         {
  1288.                 /* End the requester activity. */
  1289.  
  1290.             EndRequest(InvisibleRequest,Window);
  1291.  
  1292.                 /* Reset it to zeroes. */
  1293.  
  1294.             memset(InvisibleRequest,0,sizeof(struct Requester));
  1295.         }
  1296.     }
  1297. }
  1298.  
  1299.     /* BlockWindows():
  1300.      *
  1301.      *    Block the main window and the status window (i.e. disable
  1302.      *    the menu and attach a wait pointer).
  1303.      */
  1304.  
  1305. VOID
  1306. BlockWindows()
  1307. {
  1308.     if(!(BlockNestCount++))
  1309.     {
  1310.         BlockWindow(Window);
  1311.         BlockWindow(StatusWindow);
  1312.         BlockWindow(PacketWindow);
  1313.         BlockWindow(FastWindow);
  1314.         BlockWindow(ReviewWindow);
  1315.         BlockWindow(InfoWindow);
  1316.  
  1317.         WeAreBlocking = TRUE;
  1318.     }
  1319. }
  1320.  
  1321.     /* ReleaseWindows():
  1322.      *
  1323.      *    Reenable the menus and clear the wait pointer.
  1324.      */
  1325.  
  1326. VOID
  1327. ReleaseWindows()
  1328. {
  1329.     if(!(--BlockNestCount))
  1330.     {
  1331.         ReleaseWindow(Window);
  1332.         ReleaseWindow(StatusWindow);
  1333.         ReleaseWindow(PacketWindow);
  1334.         ReleaseWindow(FastWindow);
  1335.         ReleaseWindow(ReviewWindow);
  1336.         ReleaseWindow(InfoWindow);
  1337.  
  1338.         WeAreBlocking = FALSE;
  1339.     }
  1340. }
  1341.  
  1342.     /* LineRead(BPTR File,UBYTE *Buffer,LONG MaxChars):
  1343.      *
  1344.      *    Read a few bytes from a file (α la gets).
  1345.      */
  1346.  
  1347. LONG
  1348. LineRead(BPTR File,UBYTE *Buffer,LONG MaxChars)
  1349. {
  1350.     STATIC    UBYTE    Data[1024];
  1351.  
  1352.     STATIC    LONG    RIdx = 0,
  1353.             RLen = 0;
  1354.  
  1355.         LONG    BytesRead = 0,
  1356.             i;
  1357.  
  1358.     if(File)
  1359.     {
  1360.         for(i = 0 ; i < MaxChars ; i++)
  1361.         {
  1362.             if(RIdx >= RLen)
  1363.             {
  1364.                 RLen = Read(File,Data,1024);
  1365.  
  1366.                 RIdx = 0;
  1367.  
  1368.                 if(RLen <= 0)
  1369.                 {
  1370.                     Buffer[i] = 0;
  1371.  
  1372.                     return(BytesRead);
  1373.                 }
  1374.             }
  1375.  
  1376.             BytesRead++;
  1377.  
  1378.             if((Buffer[i] = Data[RIdx++]) == '\n')
  1379.             {
  1380.                 Buffer[i + 1] = 0;
  1381.  
  1382.                 return(BytesRead);
  1383.             }
  1384.         }
  1385.  
  1386.         return(BytesRead);
  1387.     }
  1388.     else
  1389.         RIdx = RLen = 0;
  1390. }
  1391.  
  1392.     /* FlowInit():
  1393.      *
  1394.      *    Set up the data flow parser. The parser scans the serial
  1395.      *    output data for more or less interesting modem output
  1396.      *    (carrier lost, connect, etc.).
  1397.      */
  1398.  
  1399. VOID
  1400. FlowInit()
  1401. {
  1402.     FlowInfo . Changed = FALSE;
  1403.  
  1404.     FlowInfo . NoCarrier = FlowInfo . ZModemUpload = FlowInfo . Connect = FlowInfo . Voice = FlowInfo . Ring = FlowInfo . Busy = FlowInfo . NoDialTone = FALSE;
  1405.  
  1406.     if(Config . NoCarrier[0])
  1407.         SPrintf(AttentionBuffers[0],"%s\r",Config . NoCarrier);
  1408.     else
  1409.         AttentionBuffers[0][0] = 0;
  1410.  
  1411.     if(Config . Ring[0])
  1412.         SPrintf(AttentionBuffers[1],"%s\r",Config . Ring);
  1413.     else
  1414.         AttentionBuffers[1][0] = 0;
  1415.  
  1416.     if(Config . Voice[0])
  1417.         SPrintf(AttentionBuffers[2],"%s\r",Config . Voice);
  1418.     else
  1419.         AttentionBuffers[2][0] = 0;
  1420.  
  1421.     if(Config . Busy[0])
  1422.         SPrintf(AttentionBuffers[6],"%s\r",Config . Busy);
  1423.     else
  1424.         AttentionBuffers[6][0] = 0;
  1425.  
  1426.     if(Config . NoDialTone[0])
  1427.         SPrintf(AttentionBuffers[7],"%s\r",Config . NoDialTone);
  1428.     else
  1429.         AttentionBuffers[7][0] = 0;
  1430.  
  1431.     strcpy(AttentionBuffers[3],Config . Connect);
  1432.  
  1433.     strcpy(AttentionBuffers[4],"*\030B01");
  1434.     strcpy(AttentionBuffers[5],"**\030B01");
  1435.  
  1436.     FlowCount = 0;
  1437.  
  1438.     memset(&AttentionCount[0],0,8);
  1439.  
  1440.     BaudPending = FALSE;
  1441.  
  1442.     FullCheck = FALSE;
  1443. }
  1444.  
  1445.     /* FlowFilter(UBYTE Char):
  1446.      *
  1447.      *    Send a character through the data flow parser and look
  1448.      *    if it's part of a modem message.
  1449.      */
  1450.  
  1451. VOID
  1452. FlowFilter(UBYTE Char)
  1453. {
  1454.     if(Char)
  1455.     {
  1456.         BYTE i,Matches = 0,Start,End;
  1457.  
  1458.             /* Remember previous online state. */
  1459.  
  1460.         WasOnline = Online;
  1461.  
  1462.             /* Full data check is a lot slower than looking for
  1463.              * just a single sequence (such as the `CONNECT'
  1464.              * below). This mode is reserved for the dial panel.
  1465.              */
  1466.  
  1467.         if(FullCheck)
  1468.         {
  1469.             Start    = 0;
  1470.             End    = 8;
  1471.         }
  1472.         else
  1473.         {
  1474.             Start    = 0;
  1475.  
  1476.             if(UsesZModem)
  1477.                 End = 6;
  1478.             else
  1479.                 End = 4;
  1480.         }
  1481.  
  1482.             /* We already got a `CONNECT' and the
  1483.              * `connect auto-baud' feature is enabled.
  1484.              * Continue scanning the serial output
  1485.              * data for the actual baud rate.
  1486.              */
  1487.  
  1488.         if(BaudPending)
  1489.         {
  1490.             if(Char < ' ')
  1491.             {
  1492.                 if(BaudCount)
  1493.                     BaudCount--;
  1494.  
  1495.                 while(BaudCount > 0 && BaudBuffer[BaudCount] == ' ')
  1496.                     BaudCount--;
  1497.  
  1498.                 BaudBuffer[BaudCount + 1] = 0;
  1499.  
  1500.                 FlowInfo . Connect = TRUE;
  1501.                 FlowInfo . Changed = TRUE;
  1502.  
  1503.                 BaudPending = FALSE;
  1504.             }
  1505.             else
  1506.             {
  1507.                 if(Char != ' ' || BaudCount)
  1508.                 {
  1509.                     BaudBuffer[BaudCount++] = Char;
  1510.  
  1511.                     if(BaudCount == 79)
  1512.                     {
  1513.                         BaudCount--;
  1514.  
  1515.                         while(BaudCount > 0 && BaudBuffer[BaudCount] == ' ')
  1516.                             BaudCount--;
  1517.  
  1518.                         BaudBuffer[BaudCount + 1] = 0;
  1519.  
  1520.                         FlowInfo . Connect = TRUE;
  1521.                         FlowInfo . Changed = TRUE;
  1522.  
  1523.                         BaudPending = FALSE;
  1524.                     }
  1525.                 }
  1526.             }
  1527.         }
  1528.         else
  1529.         {
  1530.                 /* Scan all ID strings for matches. */
  1531.  
  1532. Rescan1:        for(i = Start ; i < End ; i++)
  1533.             {
  1534.                     /* This sequence is a probable
  1535.                      * match.
  1536.                      */
  1537.  
  1538.                 if(AttentionCount[i] == FlowCount)
  1539.                 {
  1540.                         /* Does the character
  1541.                          * fit into the sequence?
  1542.                          */
  1543.  
  1544.                     if(Char == AttentionBuffers[i][FlowCount])
  1545.                     {
  1546.                             /* Increment the
  1547.                              * number of matching
  1548.                              * characters in this
  1549.                              * sequence.
  1550.                              */
  1551.  
  1552.                         AttentionCount[i]++;
  1553.  
  1554.                             /* Did we hit the
  1555.                              * last character
  1556.                              * in the sequence?
  1557.                              */
  1558.  
  1559.                         if(AttentionBuffers[i][FlowCount + 1])
  1560.                             Matches++;
  1561.                         else
  1562.                         {
  1563.                             Matches = 0;
  1564.  
  1565.                                 /* We've got a valid
  1566.                                  * sequence, now look
  1567.                                  * which flags to change.
  1568.                                  */
  1569.  
  1570.                             switch(i)
  1571.                             {
  1572.                                     /* We got a `no carrier' message. */
  1573.  
  1574.                                 case 0:    if(Config . CheckCarrier)
  1575.                                     {
  1576.                                         WriteRequest -> IOSer . io_Command = SDCMD_QUERY;
  1577.  
  1578.                                         DoIO(WriteRequest);
  1579.  
  1580.                                             /* Are we to take a look at the carrier bit
  1581.                                              * and if so, is the carrier still
  1582.                                              * present?
  1583.                                              */
  1584.  
  1585.                                         if(!(WriteRequest -> io_Status & (1 << 5)))
  1586.                                             break;
  1587.                                     }
  1588.  
  1589.                                     if(!FlowInfo . NoCarrier)
  1590.                                     {
  1591.                                         FlowInfo . NoCarrier    = TRUE;
  1592.                                         FlowInfo . Changed    = TRUE;
  1593.                                     }
  1594.  
  1595.                                     Online = FALSE;
  1596.  
  1597.                                         /* Clear the password. */
  1598.  
  1599.                                     Password[0] = 0;
  1600.                                     UserName[0] = 0;
  1601.  
  1602.                                     if(WasOnline)
  1603.                                     {
  1604.                                         StopCall(FALSE);
  1605.  
  1606.                                         if(CurrentPay && ChosenEntry)
  1607.                                             LogAction(LocaleString(MSG_TERMAUX_CARRIER_LOST_COST_TXT),CreateSum(CurrentPay,TRUE));
  1608.                                         else
  1609.                                             LogAction(LocaleString(MSG_TERMAUX_CARRIER_LOST_TXT));
  1610.  
  1611.                                         Say(LocaleString(MSG_TERMAUX_CARRIER_LOST_TXT));
  1612.  
  1613.                                         SetDialMenu(TRUE);
  1614.                                     }
  1615.  
  1616.                                     break;
  1617.  
  1618.                                     /* Got another call. */
  1619.  
  1620.                                 case 1:    if(!FlowInfo . Ring)
  1621.                                     {
  1622.                                         FlowInfo . Ring        = TRUE;
  1623.                                         FlowInfo . Changed    = TRUE;
  1624.                                     }
  1625.  
  1626.                                     break;
  1627.  
  1628.                                     /* Got a voice call. */
  1629.  
  1630.                                 case 2:    if(!FlowInfo . Voice)
  1631.                                     {
  1632.                                         FlowInfo . Voice    = TRUE;
  1633.                                         FlowInfo . Changed    = TRUE;
  1634.                                     }
  1635.  
  1636.                                     break;
  1637.  
  1638.                                     /* Got a connect message. */
  1639.  
  1640.                                 case 3:    if(!Online)
  1641.                                     {
  1642.                                         BaudBuffer[0]    = 0;
  1643.  
  1644.                                         BaudPending    = TRUE;
  1645.                                         BaudCount    = 0;
  1646.                                     }
  1647.  
  1648.                                     break;
  1649.  
  1650.                                     /* Got the ZModem inquiry sequence. */
  1651.  
  1652.                                 case 4:
  1653.                                 case 5:    if(!FlowInfo . ZModemUpload)
  1654.                                     {
  1655.                                         FlowInfo . ZModemUpload    = TRUE;
  1656.                                         FlowInfo . Changed    = TRUE;
  1657.                                     }
  1658.  
  1659.                                     break;
  1660.  
  1661.                                     /* Line is busy. */
  1662.  
  1663.                                 case 6:    if(!FlowInfo . Busy)
  1664.                                     {
  1665.                                         FlowInfo . Busy        = TRUE;
  1666.                                         FlowInfo . Changed    = TRUE;
  1667.                                     }
  1668.  
  1669.                                     break;
  1670.  
  1671.                                 case 7:    if(!FlowInfo . NoDialTone)
  1672.                                     {
  1673.                                         FlowInfo . NoDialTone    = TRUE;
  1674.                                         FlowInfo . Changed    = TRUE;
  1675.                                     }
  1676.  
  1677.                                     break;
  1678.                             }
  1679.                         }
  1680.                     }
  1681.                 }
  1682.             }
  1683.  
  1684.                 /* We've got a good match (recognized
  1685.                  * a sequence, so reset the data flow
  1686.                  * scanner.
  1687.                  */
  1688.  
  1689.             if(!Matches)
  1690.             {
  1691.                 if(FlowCount)
  1692.                 {
  1693.                     FlowCount = 0;
  1694.  
  1695.                     memset(&AttentionCount[0],0,8);
  1696.  
  1697.                     goto Rescan1;
  1698.                 }
  1699.             }
  1700.             else
  1701.                 FlowCount++;
  1702.         }
  1703.     }
  1704. }
  1705.  
  1706.     /* LoadMacros(UBYTE *Name,struct MacroKeys *Keys):
  1707.      *
  1708.      *    Load the keyboard macros from a file.
  1709.      */
  1710.  
  1711. BYTE
  1712. LoadMacros(UBYTE *Name,struct MacroKeys *Keys)
  1713. {
  1714.     struct IFFHandle    *Handle;
  1715.     BYTE             Success = FALSE;
  1716.     struct StoredProperty    *Prop;
  1717.     struct TermInfo        *TermInfo;
  1718.  
  1719.     if(Handle = AllocIFF())
  1720.     {
  1721.         if(Handle -> iff_Stream = Open(Name,MODE_OLDFILE))
  1722.         {
  1723.             InitIFFasDOS(Handle);
  1724.  
  1725.             if(!OpenIFF(Handle,IFFF_READ))
  1726.             {
  1727.                 /* Collect version number ID if
  1728.                  * available.
  1729.                  */
  1730.  
  1731.                 if(!PropChunks(Handle,&VersionProps[0],1))
  1732.                 {
  1733.                     /* The following line tells iffparse to stop at the
  1734.                      * very beginning of a `Type' chunk contained in a
  1735.                      * `TERM' FORM chunk.
  1736.                      */
  1737.  
  1738.                     if(!StopChunk(Handle,'TERM','KEYS'))
  1739.                     {
  1740.                         /* Parse the file... */
  1741.  
  1742.                         if(!ParseIFF(Handle,IFFPARSE_SCAN))
  1743.                         {
  1744.                             /* Did we get a version ID? */
  1745.  
  1746.                             if(Prop = FindProp(Handle,'TERM','VERS'))
  1747.                             {
  1748.                                 TermInfo = (struct TermInfo *)Prop -> sp_Data;
  1749.  
  1750.                                 /* Is it the file format we are able
  1751.                                  * to read?
  1752.                                  */
  1753.  
  1754.                                 if((TermInfo -> Version > TermVersion) || (TermInfo -> Version == TermVersion && TermInfo -> Revision > TermRevision) || (TermInfo -> Version == 1 && TermInfo -> Revision < 6))
  1755.                                 {
  1756.                                         /* Probably an older revision. */
  1757.  
  1758.                                     if(TermInfo -> Version == 1 && TermInfo -> Revision < 6)
  1759.                                     {
  1760.                                         memset(Keys,0,sizeof(struct MacroKeys));
  1761.  
  1762.                                         if(ReadChunkBytes(Handle,Keys,10 * 256) == 10 * 256)
  1763.                                             Success = TRUE;
  1764.                                     }
  1765.                                 }
  1766.                                 else
  1767.                                 {
  1768.                                     /* The file read pointer is positioned
  1769.                                      * just in front of the first data
  1770.                                      * to be read, so let's don't disappoint
  1771.                                      * iffparse and read it.
  1772.                                      */
  1773.  
  1774.                                     if(ReadChunkBytes(Handle,Keys,sizeof(struct MacroKeys)) == sizeof(struct MacroKeys))
  1775.                                         Success = TRUE;
  1776.                                 }
  1777.                             }
  1778.                             else
  1779.                             {
  1780.                                     /* File was created by WriteIFFData previous
  1781.                                      * to revision 1.4.
  1782.                                      */
  1783.  
  1784.                                 memset(Keys,0,sizeof(struct MacroKeys));
  1785.  
  1786.                                 if(ReadChunkBytes(Handle,Keys,10 * 256) == 10 * 256)
  1787.                                     Success = TRUE;
  1788.                             }
  1789.                         }
  1790.                     }
  1791.                 }
  1792.  
  1793.                 CloseIFF(Handle);
  1794.             }
  1795.  
  1796.             Close(Handle -> iff_Stream);
  1797.         }
  1798.  
  1799.         FreeIFF(Handle);
  1800.     }
  1801.  
  1802.     return(Success);
  1803. }
  1804.  
  1805.     /* FindThisItem(ULONG MenuID):
  1806.      *
  1807.      *    Scan the main menu for a menuitem associated with a
  1808.      *    menu ID.
  1809.      */
  1810.  
  1811. struct MenuItem *
  1812. FindThisItem(ULONG MenuID)
  1813. {
  1814.     struct Menu    *FirstMenu;
  1815.     struct MenuItem    *FirstItem;
  1816.  
  1817.     FirstMenu = Menu;
  1818.  
  1819.     while(FirstMenu)
  1820.     {
  1821.         FirstItem = FirstMenu -> FirstItem;
  1822.  
  1823.         while(FirstItem)
  1824.         {
  1825.             if((ULONG)GTMENUITEM_USERDATA(FirstItem) == MenuID)
  1826.                 return(FirstItem);
  1827.             else
  1828.                 FirstItem = FirstItem -> NextItem;
  1829.         }
  1830.  
  1831.         FirstMenu = FirstMenu -> NextMenu;
  1832.     }
  1833.  
  1834.     return(NULL);
  1835. }
  1836.  
  1837.     /* GetFileSize(UBYTE *Name):
  1838.      *
  1839.      *    Simple routine to return the size of a file in
  1840.      *    bytes.
  1841.      */
  1842.  
  1843. LONG
  1844. GetFileSize(UBYTE *Name)
  1845. {
  1846.     struct FileInfoBlock __aligned    FileInfo;
  1847.     BPTR                FileLock;
  1848.     LONG                FileSize = 0;
  1849.  
  1850.     if(FileLock = Lock(Name,ACCESS_READ))
  1851.     {
  1852.         if(Examine(FileLock,&FileInfo))
  1853.             FileSize = FileInfo . fib_Size;
  1854.  
  1855.         UnLock(FileLock);
  1856.     }
  1857.  
  1858.     return(FileSize);
  1859. }
  1860.  
  1861.     /* GetFile(UBYTE *Title,UBYTE *Directory,UBYTE *Name,UBYTE *Buffer,UBYTE *Pattern,BYTE SaveFlag,BYTE MultiSelect):
  1862.      *
  1863.      *    Call the asl.library file requester to select a single or
  1864.      *    a couple of files.
  1865.      */
  1866.  
  1867. struct FileRequester *
  1868. GetFile(UBYTE *Title,UBYTE *Directory,UBYTE *Name,UBYTE *Buffer,UBYTE *Pattern,BYTE SaveFlag,BYTE MultiSelect,BYTE DirsOnly,UBYTE *OKText)
  1869. {
  1870.     struct FileRequester    *AslFileRequest;
  1871.     BYTE             Result        = FALSE,
  1872.                  DefaultPattern    = FALSE;
  1873.     LONG             Flags,ExtFlags = 0;
  1874.     WORD             i,j;
  1875.  
  1876.     STATIC UBYTE         DirBuffer[256],
  1877.                  PatternBuffer[256],
  1878.                  OtherTitle[40];
  1879.  
  1880.         /* We use this tag array to remember the size and
  1881.          * position of the asl requester window.
  1882.          */
  1883.  
  1884.     STATIC struct {
  1885.         ULONG Tag1,    LeftEdge;
  1886.         ULONG Tag2,    TopEdge;
  1887.         ULONG Tag3,    Width;
  1888.         ULONG Tag4,    Height;
  1889.         ULONG Tag5;
  1890.     } Dims = {
  1891.         ASL_LeftEdge,    -1,
  1892.         ASL_TopEdge,    -1,
  1893.         ASL_Width,    -1,
  1894.         ASL_Height,    -1,
  1895.  
  1896.         TAG_DONE
  1897.     };
  1898.  
  1899.     for(i = j = 0 ; i < strlen(Title) ; i++)
  1900.     {
  1901.         if(Title[i] != '_')
  1902.             OtherTitle[j++] = Title[i];
  1903.     }
  1904.  
  1905.     OtherTitle[j] = 0;
  1906.  
  1907.     Title = OtherTitle;
  1908.  
  1909.     if(DirsOnly)
  1910.     {
  1911.         ExtFlags |= FIL1F_NOFILES;
  1912.  
  1913.         if(Pattern)
  1914.             ExtFlags |= FIL1F_MATCHDIRS;
  1915.     }
  1916.  
  1917.         /* Empty directory string? Revert to the last directory
  1918.          * name.
  1919.          */
  1920.  
  1921.     if(!Directory[0])
  1922.     {
  1923.         if(!DirBuffer[0])
  1924.         {
  1925.             if(!GetCurrentDirName(DirBuffer,256))
  1926.                 DirBuffer[0] = 0;
  1927.         }
  1928.  
  1929.         Directory = DirBuffer;
  1930.     }
  1931.  
  1932.         /* If a wildcard pattern is required, add a gadget
  1933.          * to display it.
  1934.          */
  1935.  
  1936.     if(Pattern)
  1937.     {
  1938.         Flags = FILF_PATGAD;
  1939.  
  1940.         if(!Pattern[0])
  1941.         {
  1942.             DefaultPattern = TRUE;
  1943.  
  1944.             if(PatternBuffer[0])
  1945.                 Pattern = PatternBuffer;
  1946.             else
  1947.                 Pattern = "#?";
  1948.         }
  1949.         else
  1950.         {
  1951.             if(!strcmp(Pattern,"#?") || !Stricmp(Pattern,PatternBuffer))
  1952.             {
  1953.                 DefaultPattern = TRUE;
  1954.  
  1955.                 Pattern = PatternBuffer;
  1956.             }
  1957.         }
  1958.     }
  1959.     else
  1960.     {
  1961.         Flags = 0;
  1962.  
  1963.         Pattern = "#?";
  1964.     }
  1965.  
  1966.         /* Set the save flag if we are about to save something. */
  1967.  
  1968.     if(SaveFlag)
  1969.         Flags |= FILF_SAVE;
  1970.  
  1971.         /* Set the multiselect bit if multiple files are
  1972.          * to be selected (e.g. for batch file upload).
  1973.          */
  1974.  
  1975.     if(MultiSelect)
  1976.         Flags |= FILF_MULTISELECT;
  1977.  
  1978.         /* Provide a standard `Ok' text if none
  1979.          * specified.
  1980.          */
  1981.  
  1982.     if(!OKText)
  1983.         OKText = (SaveFlag ? LocaleString(MSG_GLOBAL_SAVE_TXT) : LocaleString(MSG_GLOBAL_OPEN_TXT));
  1984.  
  1985.         /* Allocate the asl.library directory requester
  1986.          * and display it.
  1987.          */
  1988.  
  1989.     if(AslFileRequest = (struct FileRequester *)AllocAslRequestTags(ASL_FileRequest,
  1990.         ASL_Window,    Window,
  1991.         ASL_File,    Name,
  1992.         ASL_Dir,    Directory,
  1993.         ASL_Hail,    Title,
  1994.         ASL_FuncFlags,    Flags | FILF_NEWIDCMP,
  1995.         ASL_Pattern,    Pattern,
  1996.         ASL_OKText,    OKText,
  1997.         ASL_ExtFlags1,    ExtFlags,
  1998. #ifdef ASLFR_FilterFunc
  1999.         ASLFR_TextAttr,    &UserFont,
  2000. #endif    /* ASLFR_FilterFunc */
  2001.         (Dims . LeftEdge == -1) ? TAG_DONE : TAG_MORE,&Dims))
  2002.     {
  2003.         if(AslRequestTags(AslFileRequest,TAG_DONE))
  2004.         {
  2005.             Dims . LeftEdge    = AslFileRequest -> rf_LeftEdge;
  2006.             Dims . TopEdge    = AslFileRequest -> rf_TopEdge;
  2007.             Dims . Width    = AslFileRequest -> rf_Width;
  2008.             Dims . Height    = AslFileRequest -> rf_Height;
  2009.  
  2010.             if(!DirsOnly)
  2011.             {
  2012.                     /* Do we have a valid file name? */
  2013.  
  2014.                 if(AslFileRequest -> rf_File[0])
  2015.                 {
  2016.                         /* Build a legal path/file string. */
  2017.  
  2018.                     strcpy(Buffer,AslFileRequest -> rf_Dir);
  2019.  
  2020.                     AddPart((UBYTE *)Buffer,(UBYTE *)AslFileRequest -> rf_File,256);
  2021.  
  2022.                     Result = TRUE;
  2023.  
  2024.                     strcpy(DirBuffer,AslFileRequest -> rf_Dir);
  2025.                 }
  2026.             }
  2027.             else
  2028.             {
  2029.                 if(AslFileRequest -> rf_Dir[0])
  2030.                 {
  2031.                     strcpy(Buffer,AslFileRequest -> rf_Dir);
  2032.  
  2033.                     Result = TRUE;
  2034.  
  2035.                     strcpy(DirBuffer,AslFileRequest -> rf_Dir);
  2036.                 }
  2037.             }
  2038.         }
  2039.     }
  2040.  
  2041.         /* We didn't get a file, no need to keep the
  2042.          * file requester.
  2043.          */
  2044.  
  2045.     if(!Result && AslFileRequest)
  2046.     {
  2047.         FreeAslRequest(AslFileRequest);
  2048.  
  2049.         return(NULL);
  2050.     }
  2051.     else
  2052.     {
  2053.         if(DefaultPattern)
  2054.             strcpy(PatternBuffer,AslFileRequest -> rf_Pat);
  2055.  
  2056.         return(AslFileRequest);
  2057.     }
  2058. }
  2059.  
  2060. VOID
  2061. PrintSomething(BYTE Source)
  2062. {
  2063.     struct Window        *ReqWindow;
  2064.     struct EasyStruct     Easy;
  2065.     LONG             Error = 0;
  2066.  
  2067.     Easy . es_StructSize    = sizeof(struct EasyStruct);
  2068.     Easy . es_Flags        = NULL;
  2069.     Easy . es_Title        = (UBYTE *)LocaleString(MSG_TERMAUX_TERM_REQUEST_TXT);
  2070.     Easy . es_GadgetFormat    = (UBYTE *)LocaleString(MSG_PRINT_STOP_TXT);
  2071.  
  2072.     if(Source == PRINT_CLIP)
  2073.         Easy . es_TextFormat = (UBYTE *)LocaleString(MSG_PRINT_PRINTING_CLIP_TXT);
  2074.     else
  2075.         Easy . es_TextFormat = (UBYTE *)LocaleString(MSG_PRINT_PRINTING_SCREEN_TXT);
  2076.  
  2077.     if(ReqWindow = BuildEasyRequest(Window,&Easy,NULL))
  2078.     {
  2079.         BPTR SomeFile;
  2080.  
  2081.         if(PrinterCapture)
  2082.         {
  2083.             if(FPrintf(PrinterCapture,LocaleString(MSG_CONSOLE_SCREEN_PRINTOUT_FOLLOWS_TXT)) < 1)
  2084.             {
  2085.                 FreeSysRequest(ReqWindow);
  2086.  
  2087.                 ReqWindow = NULL;
  2088.  
  2089.                 Error = IoErr();
  2090.             }
  2091.             else
  2092.                 SomeFile = PrinterCapture;
  2093.         }
  2094.         else
  2095.         {
  2096.             if(!(SomeFile = Open("PRT:",MODE_NEWFILE)))
  2097.             {
  2098.                 FreeSysRequest(ReqWindow);
  2099.  
  2100.                 ReqWindow = NULL;
  2101.  
  2102.                 Error = IoErr();
  2103.             }
  2104.         }
  2105.  
  2106.         if(!Error)
  2107.         {
  2108.             BYTE Stopped = FALSE;
  2109.  
  2110.             if(Source == PRINT_SCREEN)
  2111.             {
  2112.                 WORD     i,j;
  2113.                 UBYTE    *Buffer;
  2114.  
  2115.                 for(i = 0 ; i <= LastLine ; i++)
  2116.                 {
  2117.                     Buffer = &Raster[i * RasterWidth];
  2118.  
  2119.                     j = LastColumn;
  2120.  
  2121.                     while(j >= 0 && Buffer[j] == ' ')
  2122.                         j--;
  2123.  
  2124.                     if(j >= 0)
  2125.                     {
  2126.                         if(!FWrite(SomeFile,Buffer,j + 1,1))
  2127.                         {
  2128.                             Error = IoErr();
  2129.  
  2130.                             break;
  2131.                         }
  2132.                     }
  2133.  
  2134.                     if(SysReqHandler(ReqWindow,NULL,FALSE) != -2)
  2135.                     {
  2136.                         Stopped = TRUE;
  2137.  
  2138.                         break;
  2139.                     }
  2140.  
  2141.                     if(!FWrite(SomeFile,"\n",1,1))
  2142.                     {
  2143.                         Error = IoErr();
  2144.  
  2145.                         break;
  2146.                     }
  2147.  
  2148.                     if(SysReqHandler(ReqWindow,NULL,FALSE) != -2)
  2149.                     {
  2150.                         Stopped = TRUE;
  2151.  
  2152.                         break;
  2153.                     }
  2154.                 }
  2155.             }
  2156.             else
  2157.             {
  2158.                 LONG ClipError;
  2159.  
  2160.                 if(ClipInput)
  2161.                 {
  2162.                     CloseClip();
  2163.  
  2164.                     ClipInput = ClipXerox = FALSE;
  2165.                 }
  2166.  
  2167.                 if(ClipError = OpenClip())
  2168.                 {
  2169.                     FreeSysRequest(ReqWindow);
  2170.  
  2171.                     ReqWindow = NULL;
  2172.  
  2173.                     MyEasyRequest(Window,LocaleString(MSG_GLOBAL_TERM_HAS_A_PROBLEM_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT),LocaleString(MSG_CLIP_ERROR_NOTEXT + ClipError - 1));
  2174.                 }
  2175.                 else
  2176.                 {
  2177.                     UBYTE    InputBuffer[257];
  2178.                     WORD    Len;
  2179.  
  2180.                     while((Len = GetClip(InputBuffer,256,TRUE)) > 0)
  2181.                     {
  2182.                         if(SysReqHandler(ReqWindow,NULL,FALSE) != -2)
  2183.                         {
  2184.                             Stopped = TRUE;
  2185.  
  2186.                             break;
  2187.                         }
  2188.                         else
  2189.                         {
  2190.                             if(!FWrite(SomeFile,InputBuffer,Len,1))
  2191.                             {
  2192.                                 Error = IoErr();
  2193.  
  2194.                                 break;
  2195.                             }
  2196.                         }
  2197.                     }
  2198.  
  2199.                     if(Len < 0)
  2200.                     {
  2201.                         if(SysReqHandler(ReqWindow,NULL,FALSE) == -2)
  2202.                         {
  2203.                             if(FPrintf(SomeFile,"\n") < 1)
  2204.                                 Error = IoErr();
  2205.                         }
  2206.                     }
  2207.  
  2208.                     CloseClip();
  2209.                 }
  2210.             }
  2211.  
  2212.             if(PrinterCapture)
  2213.             {
  2214.                 if(!Error && !Stopped)
  2215.                 {
  2216.                     if(FPrintf(PrinterCapture,LocaleString(MSG_CONSOLE_SCREEN_PRINTOUT_ENDING_TXT)) < 1)
  2217.                         Error = IoErr();
  2218.                 }
  2219.             }
  2220.             else
  2221.             {
  2222.                 if(!Close(SomeFile))
  2223.                     Error = IoErr();
  2224.             }
  2225.         }
  2226.  
  2227.         if(ReqWindow)
  2228.             FreeSysRequest(ReqWindow);
  2229.  
  2230.         if(Error)
  2231.         {
  2232.             STRPTR ErrorString;
  2233.  
  2234.             if(Fault(Error,"",SharedBuffer,256))
  2235.                 ErrorString = SharedBuffer;
  2236.             else
  2237.                 ErrorString = "???";
  2238.  
  2239.             MyEasyRequest(Window,LocaleString(MSG_PRINT_ERROR_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT),Error,ErrorString);
  2240.         }
  2241.     }
  2242. }
  2243.  
  2244.     /* MyEasyRequest(struct Window *Window,UBYTE *Text,UBYTE *Gadgets,...):
  2245.      *
  2246.      *    Really quite simple varargs version of Intuition's
  2247.      *    EasyRequest requester.
  2248.      */
  2249.  
  2250. WORD __stdargs
  2251. MyEasyRequest(struct Window *Window,UBYTE *Text,UBYTE *Gadgets,...)
  2252. {
  2253.     struct EasyStruct    Easy;
  2254.     WORD            Result;
  2255.     ULONG            IDCMP = NULL;
  2256.     va_list             VarArgs;
  2257.  
  2258.         /* Standard data. */
  2259.  
  2260.     Easy . es_StructSize    = sizeof(struct EasyStruct);
  2261.     Easy . es_Flags        = NULL;
  2262.     Easy . es_Title        = (UBYTE *)LocaleString(MSG_TERMAUX_TERM_REQUEST_TXT);
  2263.     Easy . es_TextFormat    = (UBYTE *)Text;
  2264.     Easy . es_GadgetFormat    = (UBYTE *)Gadgets;
  2265.  
  2266.         /* Use the argument array to build the
  2267.          * requester and display it.
  2268.          */
  2269.  
  2270.     va_start(VarArgs,Gadgets);
  2271.     Result = EasyRequestArgs(Window,&Easy,&IDCMP,VarArgs);
  2272.     va_end(VarArgs);
  2273.  
  2274.     return(Result);
  2275. }
  2276.  
  2277.     /* SelectTime():
  2278.      *
  2279.      *    Searches for the correct unit/pay conversion values.
  2280.      */
  2281.  
  2282. VOID
  2283. SelectTime(struct PhoneEntry *SomeEntry)
  2284. {
  2285.     struct TimeDateNode        *TimeDateNode;
  2286.     struct DateStamp __aligned     Date;
  2287.     struct ClockData         ClockData;
  2288.     UBYTE                 Time;
  2289.     BYTE                 FoundOne = FALSE;
  2290.     LONG                 i,Last;
  2291.  
  2292.         /* Obtain current time and date. */
  2293.  
  2294.     DateStamp(&Date);
  2295.  
  2296.         /* Convert into a more suitable form (note: seconds are
  2297.          * required as an input value, ice is extra).
  2298.          */
  2299.  
  2300.     Amiga2Date(Date . ds_Days * 86400 + Date . ds_Minute * 60 + Date . ds_Tick / TICKS_PER_SECOND,&ClockData);
  2301.  
  2302.         /* Apparently, in the US of A the week starts with Sunday, we'll
  2303.          * wrap the week around to let it start with Monday.
  2304.          */
  2305.  
  2306.     if(ClockData . wday)
  2307.         ClockData . wday--;
  2308.     else
  2309.         ClockData . wday = 6;
  2310.  
  2311.         /* Change the month, too... */
  2312.  
  2313.     ClockData . month--;
  2314.  
  2315.         /* First step: search for current day. */
  2316.  
  2317.     TimeDateNode = (struct TimeDateNode *)SomeEntry -> TimeDateList . mlh_Head;
  2318.  
  2319.         /* Skip first entry. */
  2320.  
  2321.     TimeDateNode = (struct TimeDateNode *)TimeDateNode -> VanillaNode . ln_Succ;
  2322.  
  2323.         /* First step: search for date settings. */
  2324.  
  2325.     while(TimeDateNode -> VanillaNode . ln_Succ)
  2326.     {
  2327.             /* Does it match a specific date? */
  2328.  
  2329.         if(TimeDateNode -> Month == ClockData . month && TimeDateNode -> Day == ClockData . mday)
  2330.         {
  2331.             FoundOne = TRUE;
  2332.  
  2333.             break;
  2334.         }
  2335.  
  2336.         TimeDateNode = (struct TimeDateNode *)TimeDateNode -> VanillaNode . ln_Succ;
  2337.     }
  2338.  
  2339.         /* Second step: search for week day settings. */
  2340.  
  2341.     if(!FoundOne)
  2342.     {
  2343.         TimeDateNode = (struct TimeDateNode *)SomeEntry -> TimeDateList . mlh_Head;
  2344.  
  2345.             /* Skip first entry. */
  2346.  
  2347.         TimeDateNode = (struct TimeDateNode *)TimeDateNode -> VanillaNode . ln_Succ;
  2348.  
  2349.         while(TimeDateNode -> VanillaNode . ln_Succ)
  2350.         {
  2351.                 /* Does it match a specific day? */
  2352.  
  2353.             if(TimeDateNode -> Month == -1 && (TimeDateNode -> Day & (1 << ClockData . wday)))
  2354.             {
  2355.                 FoundOne = TRUE;
  2356.  
  2357.                 break;
  2358.             }
  2359.  
  2360.             TimeDateNode = (struct TimeDateNode *)TimeDateNode -> VanillaNode . ln_Succ;
  2361.         }
  2362.     }
  2363.  
  2364.         /* Third step: use default settings. */
  2365.  
  2366.     if(!FoundOne)
  2367.         TimeDateNode = (struct TimeDateNode *)SomeEntry -> TimeDateList . mlh_Head;
  2368.  
  2369.         /* Convert current time to packed format. */
  2370.  
  2371.     Time = DT_GET_TIME(ClockData . hour,ClockData . min);
  2372.  
  2373.         /* Start with a blank. */
  2374.  
  2375.     Last = -1;
  2376.  
  2377.         /* Look for fitting time. */
  2378.  
  2379.     for(i = 0 ; i < TimeDateNode -> Table[0] . Count ; i++)
  2380.     {
  2381.             /* The time we are looking for must be >= the
  2382.              * current time.
  2383.              */
  2384.  
  2385.         if(TimeDateNode -> Table[i] . Time > Time)
  2386.         {
  2387.             if(i == 0)
  2388.                 break;
  2389.             else
  2390.             {
  2391.                 Last = i - 1;
  2392.                 break;
  2393.             }
  2394.         }
  2395.         else
  2396.             continue;
  2397.     }
  2398.  
  2399.         /* If none is found, take the last one in the list.
  2400.          * Note that this requires the list to be sorted in
  2401.          * ascending order.
  2402.          */
  2403.  
  2404.     if(Last == -1)
  2405.         Last = TimeDateNode -> Table[0] . Count - 1;
  2406.  
  2407.         /* Fill in the remaining data. */
  2408.  
  2409.     PayPerUnit[DT_FIRST_UNIT]    = TimeDateNode -> Table[Last] . PayPerUnit[DT_FIRST_UNIT];
  2410.     PayPerUnit[DT_NEXT_UNIT]    = TimeDateNode -> Table[Last] . PayPerUnit[DT_NEXT_UNIT];
  2411.     SecPerUnit[DT_FIRST_UNIT]    = TimeDateNode -> Table[Last] . SecPerUnit[DT_FIRST_UNIT];
  2412.     SecPerUnit[DT_NEXT_UNIT]    = TimeDateNode -> Table[Last] . SecPerUnit[DT_NEXT_UNIT];
  2413. }
  2414.  
  2415.     /* Raise(UWORD Colour):
  2416.      *
  2417.      *    Make an RGB value brighter.
  2418.      */
  2419.  
  2420. STATIC UWORD __regargs
  2421. Raise(UWORD Colour)
  2422. {
  2423.     WORD r,g,b;
  2424.  
  2425.     r =  (Colour >> 8)        + 4;
  2426.     g = ((Colour >> 4) & 0xF) + 4;
  2427.     b = ((Colour     ) & 0xF) + 4;
  2428.  
  2429.     if(r > 15)
  2430.         r = 15;
  2431.  
  2432.     if(g > 15)
  2433.         g = 15;
  2434.  
  2435.     if(b > 15)
  2436.         b = 15;
  2437.  
  2438.     return(r << 8 | g << 4 | b);
  2439. }
  2440.  
  2441.     /* VisualBeep():
  2442.      *
  2443.      *    Handle the visual part of the display beep.
  2444.      */
  2445.  
  2446. STATIC BYTE
  2447. VisualBeep()
  2448. {
  2449.     struct UCopList    *UserCopperList;
  2450.  
  2451.         /* Create a user copper list. */
  2452.  
  2453.     if(UserCopperList = (struct UCopList *)AllocMem(sizeof(struct UCopList),MEMF_ANY|MEMF_CLEAR))
  2454.     {
  2455.             /* Initialize for 35 commands. */
  2456.  
  2457.         if(UCopperListInit(UserCopperList,1 + 16 + 1 + 16 + 1))
  2458.         {
  2459.             WORD i;
  2460.  
  2461.                 /* Wait until first line of window. */
  2462.  
  2463.             CWAIT(UserCopperList,Window -> TopEdge,0);
  2464.  
  2465.                 /* Set the light colours. */
  2466.  
  2467.             for(i = 0 ; i < 16 ; i++)
  2468.                 CMOVE(UserCopperList,custom . color[i],Raise(GetRGB4(Screen -> ViewPort . ColorMap,i)));
  2469.  
  2470.                 /* Wait until bottom of window. */
  2471.  
  2472.             CWAIT(UserCopperList,Window -> TopEdge + Window -> Height - 1,0);
  2473.  
  2474.                 /* Set the standard colours. */
  2475.  
  2476.             for(i = 0 ; i < 16 ; i++)
  2477.                 CMOVE(UserCopperList,custom . color[i],GetRGB4(Screen -> ViewPort . ColorMap,i));
  2478.  
  2479.                 /* Finish list. */
  2480.  
  2481.             CEND(UserCopperList);
  2482.  
  2483.                 /* Install user copper list... */
  2484.  
  2485.             Screen -> ViewPort . UCopIns = UserCopperList;
  2486.  
  2487.                 /* ...and display it. */
  2488.  
  2489.             RethinkDisplay();
  2490.  
  2491.             return(TRUE);
  2492.         }
  2493.         else
  2494.             FreeMem(UserCopperList,sizeof(struct UCopList));
  2495.     }
  2496.  
  2497.     return(FALSE);
  2498. }
  2499.  
  2500.     /* PrintStatusLine(struct RastPort *RPort,STRPTR String):
  2501.      *
  2502.      *    Print a string into the status line,
  2503.      *    checks first to see if the Text() routine is
  2504.      *    likely to wait.
  2505.      */
  2506.  
  2507. STATIC VOID __stdargs
  2508. PrintStatusLine(LONG Offset,struct RastPort *RPort,STRPTR String,...)
  2509. {
  2510.     if(AttemptLockLayerRom(RPort -> Layer))
  2511.     {
  2512.         UBYTE    DummyBuffer[512];
  2513.         va_list    VarArgs;
  2514.  
  2515.         va_start(VarArgs,String);
  2516.         VSPrintf(DummyBuffer,String,VarArgs);
  2517.         va_end(VarArgs);
  2518.  
  2519.         Move(RPort,StatusOffset + Offset * UserFontWidth,UserFontBase + 1);
  2520.         Text(RPort,DummyBuffer,strlen(DummyBuffer));
  2521.  
  2522.         UnlockLayerRom(RPort -> Layer);
  2523.     }
  2524. }
  2525.  
  2526.     /* StatusServer():
  2527.      *
  2528.      *    Asynchronous process to continuosly display the current
  2529.      *    terminal settings.
  2530.      */
  2531.  
  2532. VOID __saveds
  2533. StatusServer()
  2534. {
  2535.     STATIC struct timeval     OnlineTime;
  2536.     STATIC UBYTE         OnlineBuffer[20];
  2537.     STATIC BYTE         GotOnline        = FALSE,
  2538.                  WasOnline        = FALSE,
  2539.                  ShowPay        = FALSE,
  2540.                  FlagBit        = FALSE;
  2541.     STATIC LONG         SecCount        = 0,
  2542.                  BeepCount        = 0;
  2543.  
  2544.     struct TextBox        *BoxArray[4],
  2545.                 *BoxList = NULL,
  2546.                 *Box;
  2547.  
  2548.     struct RastPort        *RPort;
  2549.     UBYTE             Buffer[100];
  2550.  
  2551.     struct timerequest    *TimeRequest;
  2552.     struct MsgPort        *TimePort;
  2553.  
  2554.     BYTE             Background        = FALSE,
  2555.                  FlashIt        = FALSE,
  2556.                  SetColours        = FALSE,
  2557.                  StandardColours    = TRUE,
  2558.                  KeepGoing        = TRUE,
  2559.                  Beeping        = FALSE;
  2560.  
  2561.     BYTE             LastProtocol[40],
  2562.                  ProtocolBuffer[20],
  2563.                  Pen;
  2564.  
  2565.     BYTE             LastFont        = -1,
  2566.                  LastEmulation        = -1,
  2567.                  LastBitsPerChar    = -1,
  2568.                  LastParity        = -1,
  2569.                  LastStopBits        = -1,
  2570.                  LastStatus        = -1;
  2571.  
  2572.     LONG             LastBaud        = -1;
  2573.  
  2574.     LONG             i,
  2575.                  ThisHour,
  2576.                  ThisMinute,
  2577.                  BoxCounter = 0,
  2578.                  FullWidth;
  2579.     WORD             ColumnLeft[4],
  2580.                  ColumnWidth[4],
  2581.                  Max,
  2582.                  Len;
  2583.     BYTE             AllFine = TRUE;
  2584.  
  2585.     LastProtocol[0] = 0;
  2586.  
  2587.     LocalizeString(ConfigFont,MSG_TERMAUX_STANDARD_FONT_TXT,MSG_TERMAUX_IBM_FONT_TXT);
  2588.     LocalizeString(ConfigEmulation,MSG_TERMAUX_ANSI_VT102_TXT,MSG_TERMAUX_EXTERNAL_TXT);
  2589.     LocalizeString(ConfigParity,MSG_TERMAUX_NONE_TXT,MSG_TERMAUX_SPACE_TXT);
  2590.     LocalizeString(ConfigStatus,MSG_TERMAUX_READY_TXT,MSG_TERMAUX_HANG_UP_TXT);
  2591.  
  2592.     if(StatusWindow)
  2593.     {
  2594.         RPort = StatusWindow -> RPort;
  2595.  
  2596.             /* Render the information. */
  2597.  
  2598.         switch(Config . ColourMode)
  2599.         {
  2600.             case COLOUR_EIGHT:    Pen = 7;
  2601.                         break;
  2602.  
  2603.             case COLOUR_SIXTEEN:    Pen = 15;
  2604.                         break;
  2605.  
  2606.             default:        Pen = 1;
  2607.                         break;
  2608.         }
  2609.  
  2610.         SZ_SizeSetup(Screen,&UserFont,TRUE);
  2611.  
  2612.         if(Config . StatusLine == STATUSLINE_COMPRESSED)
  2613.         {
  2614.             StatusOffset = (Screen -> Width - 80 * UserFontWidth) / 2;
  2615.  
  2616.             SetRast(RPort,Pen);
  2617.             SetAPen(RPort,Pen);
  2618.  
  2619.             RectFill(RPort,0,0,StatusWindow -> Width - 1,StatusWindow -> Height - 1);
  2620.  
  2621.             SetAPen(RPort,0);
  2622.             SetBPen(RPort,Pen);
  2623.         }
  2624.         else
  2625.         {
  2626.             SetAPen(RPort,Pen);
  2627.             SetBPen(RPort,0);
  2628.  
  2629.                 /* Draw a separating line. */
  2630.  
  2631.             Move(RPort,0,0);
  2632.             Draw(RPort,StatusWindow -> Width - 1,0);
  2633.  
  2634.             ColumnLeft[0] = SZ_LeftOffsetN(MSG_TERMINIT_STATUSLINE_STATUS_TXT,MSG_TERMINIT_STATUSLINE_FONT_TXT,-1);
  2635.             ColumnLeft[1] = SZ_LeftOffsetN(MSG_TERMINIT_STATUSLINE_PROTOCOL_TXT,MSG_TERMINIT_STATUSLINE_TERMINAL_TXT,-1);
  2636.             ColumnLeft[2] = SZ_LeftOffsetN(MSG_TERMINIT_STATUSLINE_BAUDRATE_TXT,MSG_TERMINIT_STATUSLINE_PARAMETERS_TXT,-1);
  2637.             ColumnLeft[3] = SZ_LeftOffsetN(MSG_TERMINIT_STATUSLINE_TIME_TXT,MSG_TERMINIT_STATUSLINE_ONLINE_TXT,-1);
  2638.  
  2639.             Max = 0;
  2640.  
  2641.             for(i = 0 ; ConfigStatus[i] ; i++)
  2642.             {
  2643.                 if((Len = SZ_BoxWidth(strlen(ConfigStatus[i]))) > Max)
  2644.                     Max = Len;
  2645.             }
  2646.  
  2647.             for(i = 0 ; ConfigFont[i] ; i++)
  2648.             {
  2649.                 if((Len = SZ_BoxWidth(strlen(ConfigFont[i]))) > Max)
  2650.                     Max = Len;
  2651.             }
  2652.  
  2653.             ColumnWidth[0] = Max;
  2654.  
  2655.             Max = SZ_BoxWidth(12);
  2656.  
  2657.             for(i = 0 ; ConfigEmulation[i] ; i++)
  2658.             {
  2659.                 if((Len = SZ_BoxWidth(strlen(ConfigEmulation[i]))) > Max)
  2660.                     Max = Len;
  2661.             }
  2662.  
  2663.             ColumnWidth[1] = Max;
  2664.  
  2665.             Max = SZ_BoxWidth(10);
  2666.  
  2667.             for(i = 0 ; ConfigParity[i] ; i++)
  2668.             {
  2669.                 if((Len = SZ_BoxWidth(4 + strlen(ConfigParity[i]))) > Max)
  2670.                     Max = Len;
  2671.             }
  2672.  
  2673.             ColumnWidth[2] = Max;
  2674.  
  2675.             ColumnWidth[3] = SZ_BoxWidth(8);
  2676.  
  2677.             FullWidth = 0;
  2678.  
  2679.             for(i = 0 ; i < 4 ; i++)
  2680.                 FullWidth += ColumnWidth[i] + ColumnLeft[i];
  2681.  
  2682.             FullWidth += 3 * InterWidth;
  2683.  
  2684.             if(FullWidth > Screen -> Width)
  2685.                 SZ_SetLeftEdge(ColumnLeft[0]);
  2686.             else
  2687.                 SZ_SetLeftEdge((Screen -> Width - FullWidth) / 2 + ColumnLeft[0]);
  2688.  
  2689.             SZ_SetAbsoluteTop(2);
  2690.             SZ_SetTopEdge(2);
  2691.  
  2692.             SZ_SetWidth(ColumnWidth[0]);
  2693.  
  2694.             BoxArray[BoxCounter++] = Box = SZ_CreateTextBox(&BoxList,
  2695.                 SZ_Lines,    2,
  2696.                 SZ_AutoWidth,    TRUE,
  2697.             TAG_DONE);
  2698.  
  2699.             SZ_SetBoxTitles(Box,LocaleString(MSG_TERMINIT_STATUSLINE_STATUS_TXT),LocaleString(MSG_TERMINIT_STATUSLINE_FONT_TXT),NULL);
  2700.  
  2701.             SZ_SetWidth(ColumnWidth[1]);
  2702.             SZ_AddLeftOffset(ColumnLeft[1]);
  2703.  
  2704.             BoxArray[BoxCounter++] = Box = SZ_CreateTextBox(&BoxList,
  2705.                 SZ_Lines,    2,
  2706.                 SZ_AutoWidth,    TRUE,
  2707.                 SZ_NewColumn,    TRUE,
  2708.             TAG_DONE);
  2709.  
  2710.             SZ_SetBoxTitles(Box,LocaleString(MSG_TERMINIT_STATUSLINE_PROTOCOL_TXT),LocaleString(MSG_TERMINIT_STATUSLINE_TERMINAL_TXT),NULL);
  2711.  
  2712.             SZ_SetWidth(ColumnWidth[2]);
  2713.             SZ_AddLeftOffset(ColumnLeft[2]);
  2714.  
  2715.             BoxArray[BoxCounter++] = Box = SZ_CreateTextBox(&BoxList,
  2716.                 SZ_Lines,    2,
  2717.                 SZ_AutoWidth,    TRUE,
  2718.                 SZ_NewColumn,    TRUE,
  2719.             TAG_DONE);
  2720.  
  2721.             SZ_SetBoxTitles(Box,LocaleString(MSG_TERMINIT_STATUSLINE_BAUDRATE_TXT),LocaleString(MSG_TERMINIT_STATUSLINE_PARAMETERS_TXT),NULL);
  2722.  
  2723.             SZ_SetWidth(ColumnWidth[3]);
  2724.             SZ_AddLeftOffset(ColumnLeft[3]);
  2725.  
  2726.             BoxArray[BoxCounter++] = Box = SZ_CreateTextBox(&BoxList,
  2727.                 SZ_Lines,    2,
  2728.                 SZ_AutoWidth,    TRUE,
  2729.                 SZ_NewColumn,    TRUE,
  2730.             TAG_DONE);
  2731.  
  2732.             SZ_SetBoxTitles(Box,LocaleString(MSG_TERMINIT_STATUSLINE_TIME_TXT),LocaleString(MSG_TERMINIT_STATUSLINE_ONLINE_TXT),NULL);
  2733.  
  2734.             if(!Box)
  2735.                 AllFine = FALSE;
  2736.             else
  2737.                 SZ_DrawBoxes(RPort,BoxList);
  2738.         }
  2739.     }
  2740.  
  2741.     if(AllFine)
  2742.     {
  2743.             /* Create a timer device request. */
  2744.  
  2745.         if(TimePort = (struct MsgPort *)CreateMsgPort())
  2746.         {
  2747.             if(TimeRequest = (struct timerequest *)CreateIORequest(TimePort,sizeof(struct timerequest)))
  2748.             {
  2749.                 if(!OpenDevice(TIMERNAME,UNIT_VBLANK,TimeRequest,0))
  2750.                 {
  2751.                         /* Signal our father process
  2752.                          * that we're running.
  2753.                          */
  2754.  
  2755.                     Signal(ThisProcess,SIGBREAKF_CTRL_C);
  2756.  
  2757.                     if(StatusWindow)
  2758.                     {
  2759.                         if(Config . StatusLine == STATUSLINE_COMPRESSED)
  2760.                             PrintStatusLine(0,RPort,"         ╖              ╖             ╖            ╖       ╖          ╖ 00:00:00");
  2761.                         else
  2762.                             SZ_PrintLine(RPort,BoxArray[STATUSBOX_TIME_ONLINE],1,"00:00:00");
  2763.                     }
  2764.                     else
  2765.                         RPort = NULL;
  2766.  
  2767.                         /* Keep on displaying. */
  2768.  
  2769.                     while(KeepGoing)
  2770.                     {
  2771.                             /* Are we to quit? */
  2772.  
  2773.                         if(CheckSignal(SIGBREAKF_CTRL_C))
  2774.                             KeepGoing = FALSE;
  2775.  
  2776.                             /* Get the current time. */
  2777.  
  2778.                         TimeRequest -> tr_node . io_Command = TR_GETSYSTIME;
  2779.  
  2780.                         DoIO(TimeRequest);
  2781.  
  2782.                             /* A connection has just
  2783.                              * been established.
  2784.                              */
  2785.  
  2786.                         if(Online && !GotOnline)
  2787.                         {
  2788.                             OnlineTime = TimeRequest -> tr_time;
  2789.  
  2790.                             GotOnline = TRUE;
  2791.  
  2792.                             SecCount = 0;
  2793.  
  2794.                             FlagBit = FALSE;
  2795.                         }
  2796.  
  2797.                             /* Print the current time. */
  2798.  
  2799.                         ThisHour    = (TimeRequest -> tr_time . tv_secs % 86400) / 3600;
  2800.                         ThisMinute    = (TimeRequest -> tr_time . tv_secs % 3600) / 60;
  2801.  
  2802.                         if(RPort)
  2803.                         {
  2804.                             if(Config . StatusLine == STATUSLINE_COMPRESSED)
  2805.                                 PrintStatusLine(61,RPort,"%02ld:%02ld:%02ld",ThisHour,ThisMinute,TimeRequest -> tr_time . tv_secs % 60);
  2806.                             else
  2807.                                 SZ_PrintLine(RPort,BoxArray[STATUSBOX_TIME_ONLINE],0,"%02ld:%02ld:%02ld",ThisHour,ThisMinute,TimeRequest -> tr_time . tv_secs % 60);
  2808.                         }
  2809.  
  2810.                         if(Online)
  2811.                         {
  2812.                             STATIC struct timeval    LastTime;
  2813.                             struct timeval        TempTime;
  2814.  
  2815.                             WasOnline = TRUE;
  2816.  
  2817.                                 /* Look if we are to tell
  2818.                                  * the main process to take
  2819.                                  * a look at the carrier
  2820.                                  * signal.
  2821.                                  */
  2822.  
  2823.                             if(Config . CheckCarrier && !(SecCount & 1) && ReadPort && Status == STATUS_READY)
  2824.                                 Signal(ThisProcess,SIG_CHECK);
  2825.  
  2826.                             if(ChosenEntry)
  2827.                             {
  2828.                                 if(!(ThisMinute % 10) && !(TimeRequest -> tr_time . tv_secs % 60))
  2829.                                 {
  2830.                                     ChosenInUse = TRUE;
  2831.  
  2832.                                     SelectTime(ChosenEntry);
  2833.  
  2834.                                     ChosenInUse = FALSE;
  2835.                                 }
  2836.  
  2837.                                 if(!CurrentPay)
  2838.                                     CurrentPay = PayPerUnit[DT_FIRST_UNIT];
  2839.  
  2840.                                 FlagBit ^= TRUE;
  2841.  
  2842.                                 if(!FlagBit)
  2843.                                 {
  2844.                                     if(SecPerUnit[WhichUnit] && SecCount == SecPerUnit[WhichUnit])
  2845.                                     {
  2846.                                         SecCount = 0;
  2847.  
  2848.                                         WhichUnit = DT_NEXT_UNIT;
  2849.  
  2850.                                         CurrentPay += PayPerUnit[DT_NEXT_UNIT];
  2851.                                     }
  2852.  
  2853.                                     SecCount++;
  2854.                                 }
  2855.                             }
  2856.  
  2857.                                 /* Show the time
  2858.                                  * we have been online
  2859.                                  * yet.
  2860.                                  */
  2861.  
  2862.                             TempTime = TimeRequest -> tr_time;
  2863.  
  2864.                             if(TempTime . tv_secs != LastTime . tv_secs)
  2865.                             {
  2866.                                 LastTime = TempTime;
  2867.  
  2868.                                 SubTime(&TempTime,&OnlineTime);
  2869.  
  2870.                                 if(!(TempTime . tv_secs % 5) && TempTime . tv_secs)
  2871.                                     ShowPay ^= TRUE;
  2872.  
  2873.                                 SPrintf(OnlineBuffer,"%02ld:%02ld:%02ld",(TempTime . tv_secs % 86400) / 3600,(TempTime . tv_secs % 3600) / 60,TempTime . tv_secs % 60);
  2874.  
  2875.                                 if(ShowPay && CurrentPay && ChosenEntry)
  2876.                                 {
  2877.                                     SPrintf(Buffer,"%s          ",CreateSum(CurrentPay,FALSE));
  2878.  
  2879.                                     Buffer[8] = 0;
  2880.                                 }
  2881.                                 else
  2882.                                     strcpy(Buffer,OnlineBuffer);
  2883.  
  2884.                                 if(RPort)
  2885.                                 {
  2886.                                     if(Config . StatusLine == STATUSLINE_COMPRESSED)
  2887.                                         PrintStatusLine(72,RPort,Buffer);
  2888.                                     else
  2889.                                         SZ_PrintLine(RPort,BoxArray[STATUSBOX_TIME_ONLINE],1,Buffer);
  2890.                                 }
  2891.                             }
  2892.                         }
  2893.                         else
  2894.                         {
  2895.                             if(WasOnline)
  2896.                             {
  2897.                                 WasOnline = FALSE;
  2898.  
  2899.                                 if(RPort)
  2900.                                 {
  2901.                                     if(Config . StatusLine == STATUSLINE_COMPRESSED)
  2902.                                         PrintStatusLine(72,RPort,OnlineBuffer);
  2903.                                     else
  2904.                                         SZ_PrintLine(RPort,BoxArray[STATUSBOX_TIME_ONLINE],1,OnlineBuffer);
  2905.                                 }
  2906.                             }
  2907.  
  2908.                             if(GotOnline)
  2909.                                 GotOnline = FALSE;
  2910.                         }
  2911.  
  2912.                             /* Take care of the visual beep
  2913.                              * if enabled.
  2914.                              */
  2915.  
  2916.                         if(Beeping)
  2917.                         {
  2918.                             if(!(BeepCount--))
  2919.                             {
  2920.                                 Beeping = FALSE;
  2921.  
  2922.                                     /* Remove the copper list. */
  2923.  
  2924.                                 FreeVPortCopLists(&Screen -> ViewPort);
  2925.  
  2926.                                     /* Really remove it. */
  2927.  
  2928.                                 RemakeDisplay();
  2929.  
  2930.                                     /* Clear the signal bit. */
  2931.  
  2932.                                 SetSignal(0,SIGBREAKF_CTRL_D);
  2933.                             }
  2934.                         }
  2935.  
  2936.                             /* Are we to show a visual beep? */
  2937.  
  2938.                         if(CheckSignal(SIGBREAKF_CTRL_D))
  2939.                         {
  2940.                             if(Config . SystemBeep)
  2941.                                 DisplayBeep(Screen);
  2942.                             else
  2943.                             {
  2944.                                 if(!Beeping)
  2945.                                 {
  2946.                                     if(VisualBeep())
  2947.                                     {
  2948.                                         Beeping = TRUE;
  2949.  
  2950.                                         BeepCount = 1;
  2951.                                     }
  2952.                                 }
  2953.                             }
  2954.                         }
  2955.  
  2956.                             /* Display the current terminal
  2957.                              * status.
  2958.                              */
  2959.  
  2960.                         if(LastStatus != Status)
  2961.                         {
  2962.                             LastStatus = Status;
  2963.  
  2964.                             if(RPort)
  2965.                             {
  2966.                                 if(Config . StatusLine == STATUSLINE_COMPRESSED)
  2967.                                     PrintStatusLine(0,RPort,ConfigStatus[LastStatus]);
  2968.                                 else
  2969.                                     SZ_PrintLine(RPort,BoxArray[STATUSBOX_STATUS_FONT],0,ConfigStatus[LastStatus]);
  2970.                             }
  2971.                         }
  2972.  
  2973.                             /* Show the current transfer
  2974.                              * protocol.
  2975.                              */
  2976.  
  2977.                         if(strcmp(LastProtocol,FilePart(Config . Protocol)))
  2978.                         {
  2979.                             strcpy(LastProtocol,FilePart(Config . Protocol));
  2980.  
  2981.                             strcpy(ProtocolBuffer,"        ");
  2982.  
  2983.                             for(i = 0 ; i < 8 ; i++)
  2984.                             {
  2985.                                 if(!LastProtocol[i + 3] || LastProtocol[i + 3] == '.')
  2986.                                     break;
  2987.                                 else
  2988.                                     ProtocolBuffer[i] = LastProtocol[i + 3];
  2989.                             }
  2990.  
  2991.                             if(RPort)
  2992.                             {
  2993.                                 if(Config . StatusLine == STATUSLINE_COMPRESSED)
  2994.                                     PrintStatusLine(26,RPort,ProtocolBuffer);
  2995.                                 else
  2996.                                     SZ_PrintLine(RPort,BoxArray[STATUSBOX_PROTOCOL_TERMINAL],0,ProtocolBuffer);
  2997.                             }
  2998.                         }
  2999.  
  3000.                             /* Show the current baud
  3001.                              * rate.
  3002.                              */
  3003.  
  3004.                         if(LastBaud != Config . BaudRate)
  3005.                         {
  3006.                             LastBaud = Config . BaudRate;
  3007.  
  3008.                             if(RPort)
  3009.                             {
  3010.                                 extern APTR LocaleBase;
  3011.  
  3012.                                 if(LocaleBase)
  3013.                                     SPrintf(Buffer,"%lD        ",LastBaud);
  3014.                                 else
  3015.                                     SPrintf(Buffer,"%ld        ",LastBaud);
  3016.  
  3017.                                 Buffer[7] = 0;
  3018.  
  3019.                                 if(Config . StatusLine == STATUSLINE_COMPRESSED)
  3020.                                     PrintStatusLine(40,RPort,Buffer);
  3021.                                 else
  3022.                                     SZ_PrintLine(RPort,BoxArray[STATUSBOX_RATE_PARAMETERS],0,Buffer);
  3023.                             }
  3024.                         }
  3025.  
  3026.                             /* Show the current
  3027.                              * terminal font.
  3028.                              */
  3029.  
  3030.                         if(LastFont != Config . Font)
  3031.                         {
  3032.                             LastFont = Config . Font;
  3033.  
  3034.                             if(RPort)
  3035.                             {
  3036.                                 if(Config . StatusLine != STATUSLINE_COMPRESSED)
  3037.                                     SZ_PrintLine(RPort,BoxArray[STATUSBOX_STATUS_FONT],1,ConfigFont[LastFont]);
  3038.                             }
  3039.                         }
  3040.  
  3041.                             /* Show the current terminal
  3042.                              * emulation.
  3043.                              */
  3044.  
  3045.                         if(Config . Emulation == 3)
  3046.                         {
  3047.                             LastEmulation = Config . Emulation;
  3048.  
  3049.                             if(RPort)
  3050.                             {
  3051.                                 SPrintf(Buffer,"%s         ",EmulationName);
  3052.  
  3053.                                 Buffer[10] = 0;
  3054.  
  3055.                                 if(Config . StatusLine == STATUSLINE_COMPRESSED)
  3056.                                     PrintStatusLine(11,RPort,Buffer);
  3057.                                 else
  3058.                                     SZ_PrintLine(RPort,BoxArray[STATUSBOX_PROTOCOL_TERMINAL],1,Buffer);
  3059.                             }
  3060.                         }
  3061.                         else
  3062.                         {
  3063.                             if(LastEmulation != Config . Emulation)
  3064.                             {
  3065.                                 LastEmulation = Config . Emulation;
  3066.  
  3067.                                 if(RPort)
  3068.                                 {
  3069.                                     if(Config . StatusLine == STATUSLINE_COMPRESSED)
  3070.                                         PrintStatusLine(11,RPort,ConfigEmulation[LastEmulation]);
  3071.                                     else
  3072.                                         SZ_PrintLine(RPort,BoxArray[STATUSBOX_PROTOCOL_TERMINAL],1,ConfigEmulation[LastEmulation]);
  3073.                                 }
  3074.                             }
  3075.                         }
  3076.  
  3077.                             /* Show the current serial
  3078.                              * parameters (parity, etc).
  3079.                              */
  3080.  
  3081.                         if(LastBitsPerChar != Config . BitsPerChar || LastParity != Config . Parity || LastStopBits != Config . StopBits)
  3082.                         {
  3083.                             LastBitsPerChar    = Config . BitsPerChar;
  3084.                             LastParity    = Config . Parity;
  3085.                             LastStopBits    = Config . StopBits;
  3086.  
  3087.                             if(RPort)
  3088.                             {
  3089.                                 if(Config . StatusLine == STATUSLINE_COMPRESSED)
  3090.                                 {
  3091.                                     STATIC UBYTE Parities[] =
  3092.                                     {
  3093.                                         'N','E','O','M','S'
  3094.                                     };
  3095.  
  3096.                                     PrintStatusLine(53,RPort,"%ld-%lc-%ld",LastBitsPerChar,Parities[LastParity],LastStopBits);
  3097.                                 }
  3098.                                 else
  3099.                                     SZ_PrintLine(RPort,BoxArray[STATUSBOX_RATE_PARAMETERS],1,"%ld-%s-%ld",LastBitsPerChar,ConfigParity[LastParity],LastStopBits);
  3100.                             }
  3101.                         }
  3102.  
  3103.                             /* Wait another half a second. */
  3104.  
  3105.                         if(KeepGoing)
  3106.                         {
  3107.                             ULONG Mask;
  3108.  
  3109.                             TimeRequest -> tr_node . io_Command    = TR_ADDREQUEST;
  3110.                             TimeRequest -> tr_time . tv_secs    = 0;
  3111.                             TimeRequest -> tr_time . tv_micro    = MILLION / 2;
  3112.  
  3113.                             SendIO(TimeRequest);
  3114.  
  3115.                             FOREVER
  3116.                             {
  3117.                                 Mask = Wait(SIGBREAKF_CTRL_D | (1 << TimePort -> mp_SigBit));
  3118.  
  3119.                                 if(Mask & SIGBREAKF_CTRL_D)
  3120.                                 {
  3121.                                     if(Config . SystemBeep)
  3122.                                     {
  3123.                                         DisplayBeep(Screen);
  3124.  
  3125.                                         SetSignal(0,SIGBREAKF_CTRL_D);
  3126.                                     }
  3127.                                     else
  3128.                                     {
  3129.                                         if(!Beeping)
  3130.                                         {
  3131.                                             if(VisualBeep())
  3132.                                             {
  3133.                                                 Beeping = TRUE;
  3134.  
  3135.                                                 BeepCount = 1;
  3136.                                             }
  3137.                                         }
  3138.                                     }
  3139.                                 }
  3140.  
  3141.                                 if(Mask & (1 << TimePort -> mp_SigBit))
  3142.                                 {
  3143.                                     WaitIO(TimeRequest);
  3144.  
  3145.                                     break;
  3146.                                 }
  3147.                             }
  3148.                         }
  3149.  
  3150.                             /* Make the colours blink. */
  3151.  
  3152.                         if(Screen == IntuitionBase -> FirstScreen)
  3153.                         {
  3154.                                 /* No main screen window active? */
  3155.  
  3156.                             if(StatusWindow)
  3157.                             {
  3158.                                 if(!(Window -> Flags & WFLG_WINDOWACTIVE) && !(StatusWindow -> Flags & WFLG_WINDOWACTIVE))
  3159.                                     StandardColours = TRUE;
  3160.                             }
  3161.                             else
  3162.                             {
  3163.                                 if(!(Window -> Flags & WFLG_WINDOWACTIVE))
  3164.                                     StandardColours = TRUE;
  3165.                             }
  3166.  
  3167.                                 /* Menu button pressed or window disabled? */
  3168.  
  3169.                             if(Window -> Flags & (WFLG_MENUSTATE|WFLG_INREQUEST))
  3170.                                 StandardColours = TRUE;
  3171.  
  3172.                                 /* User is currently dragging the
  3173.                                  * mouse in order to mark something
  3174.                                  * on the screen?
  3175.                                  */
  3176.  
  3177.                             if(Marking)
  3178.                                 StandardColours = TRUE;
  3179.  
  3180.                             Background = FALSE;
  3181.                         }
  3182.                         else
  3183.                         {
  3184.                             if(!Background)
  3185.                                 StandardColours = TRUE;
  3186.  
  3187.                             Background = TRUE;
  3188.                         }
  3189.  
  3190.                         if(StandardColours)
  3191.                         {
  3192.                             if(!SetColours)
  3193.                             {
  3194.                                 LoadRGB4(VPort,Config . Colours,16);
  3195.  
  3196.                                 SetColours = TRUE;
  3197.                             }
  3198.  
  3199.                             StandardColours = FlashIt = FALSE;
  3200.                         }
  3201.                         else
  3202.                         {
  3203.                                 /* Are we to flash the display? */
  3204.  
  3205.                             if(!(Config . DisableBlinking & ~TERMINAL_FASTER))
  3206.                             {
  3207.                                 if(Screen == IntuitionBase -> FirstScreen)
  3208.                                 {
  3209.                                     if(FlashIt)
  3210.                                     {
  3211.                                         LoadRGB4(VPort,BlinkColours,16);
  3212.  
  3213.                                         SetColours = FALSE;
  3214.                                     }
  3215.                                     else
  3216.                                     {
  3217.                                         LoadRGB4(VPort,Config . Colours,16);
  3218.  
  3219.                                         SetColours = TRUE;
  3220.                                     }
  3221.                                 }
  3222.  
  3223.                                 FlashIt ^= TRUE;
  3224.                             }
  3225.                         }
  3226.                     }
  3227.  
  3228.                     CloseDevice(TimeRequest);
  3229.                 }
  3230.  
  3231.                 DeleteIORequest(TimeRequest);
  3232.             }
  3233.  
  3234.             DeleteMsgPort(TimePort);
  3235.         }
  3236.  
  3237.         SZ_FreeBoxes(BoxList);
  3238.     }
  3239.  
  3240.         /* Signal the father process that we're done
  3241.          * and quietly remove ourselves.
  3242.          */
  3243.  
  3244.     Forbid();
  3245.  
  3246.     Signal(ThisProcess,SIGBREAKF_CTRL_C);
  3247.  
  3248.     StatusProcess = NULL;
  3249. }
  3250.  
  3251.     /* CloseWindowSafely(struct Window *Window):
  3252.      *
  3253.      *    Close a window freeing all messages pending at
  3254.      *    its user port (taken from example source code
  3255.      *    published once upon a time in Amiga Mail).
  3256.      */
  3257.  
  3258. VOID
  3259. CloseWindowSafely(struct Window *Window)
  3260. {
  3261.     struct IntuiMessage    *IntuiMessage;
  3262.     struct Node        *Successor;
  3263.  
  3264.     Forbid();
  3265.  
  3266.     IntuiMessage = (struct IntuiMessage *)Window -> UserPort -> mp_MsgList . lh_Head;
  3267.  
  3268.     while(Successor = IntuiMessage -> ExecMessage . mn_Node . ln_Succ)
  3269.     {
  3270.         if(IntuiMessage -> IDCMPWindow == Window)
  3271.         {
  3272.             Remove(IntuiMessage);
  3273.  
  3274.             ReplyMsg((struct Message *)IntuiMessage);
  3275.         }
  3276.  
  3277.         IntuiMessage = (struct IntuiMessage *)Successor;
  3278.     }
  3279.  
  3280.     Window -> UserPort = NULL;
  3281.  
  3282.     ModifyIDCMP(Window,NULL);
  3283.  
  3284.     Permit();
  3285.  
  3286.     CloseWindow(Window);
  3287. }
  3288.  
  3289.     /* WaitTime(LONG Secs,LONG Micros):
  3290.      *
  3291.      *    Wait a given period of time.
  3292.      */
  3293.  
  3294. VOID
  3295. WaitTime(LONG Secs,LONG Micros)
  3296. {
  3297.     TimeRequest -> tr_node . io_Command    = TR_ADDREQUEST;
  3298.     TimeRequest -> tr_time . tv_secs    = Secs;
  3299.     TimeRequest -> tr_time . tv_micro    = Micros;
  3300.  
  3301.     DoIO(TimeRequest);
  3302. }
  3303.  
  3304.     /* GetEnvDOS(UBYTE *Name,UBYTE *Buffer):
  3305.      *
  3306.      *    Get the contents of a vanilla AmigaDOS environment
  3307.      *    variable.
  3308.      */
  3309.  
  3310. UBYTE *
  3311. GetEnvDOS(UBYTE *Name,UBYTE *Buffer)
  3312. {
  3313.     LONG    Size;
  3314.     BPTR    File,SomeLock;
  3315.  
  3316.     Buffer[0] = 0;
  3317.  
  3318.         /* Is ENV: present? */
  3319.  
  3320.     if(SomeLock = Lock("Env:",ACCESS_READ))
  3321.     {
  3322.         UBYTE SomeBuffer[80];
  3323.  
  3324.         UnLock(SomeLock);
  3325.  
  3326.         strcpy(SomeBuffer,"Env:");
  3327.         strcat(SomeBuffer,Name);
  3328.  
  3329.             /* Open the file. */
  3330.  
  3331.         if(File = Open(SomeBuffer,MODE_OLDFILE))
  3332.         {
  3333.                 /* Read the contents. */
  3334.  
  3335.             Size = Read(File,Buffer,256);
  3336.  
  3337.             Close(File);
  3338.  
  3339.             if(Size > 0)
  3340.             {
  3341.                 Buffer[Size] = 0;
  3342.  
  3343.                 return(Buffer);
  3344.             }
  3345.         }
  3346.     }
  3347.  
  3348.     return(NULL);
  3349. }
  3350.  
  3351.     /* SetEnvDOS(UBYTE *Name,UBYTE *Value):
  3352.      *
  3353.      *    Set the contents of a vanilla AmigaDOS environment
  3354.      *    variable.
  3355.      */
  3356.  
  3357. BYTE
  3358. SetEnvDOS(UBYTE *Name,UBYTE *Value)
  3359. {
  3360.     UBYTE    Buffer[80],*Destination;
  3361.     LONG    Length = 0;
  3362.     BPTR    File,FileLock;
  3363.     BYTE    Success = FALSE;
  3364.     WORD    i;
  3365.  
  3366.     for(i = 0 ; i < 2 ; i++)
  3367.     {
  3368.         if(i)
  3369.             Destination = "EnvArc:";
  3370.         else
  3371.             Destination = "Env:";
  3372.  
  3373.             /* Is ENV:/ENVARC: present? */
  3374.  
  3375.         if(FileLock = Lock(Destination,ACCESS_READ))
  3376.         {
  3377.             UnLock(FileLock);
  3378.  
  3379.             strcpy(Buffer,Destination);
  3380.             strcat(Buffer,Name);
  3381.  
  3382.                 /* There already is a variable of that
  3383.                  * name in the environment storage
  3384.                  * directory.
  3385.                  */
  3386.  
  3387.             if(FileLock = Lock(Buffer,ACCESS_WRITE))
  3388.             {
  3389.                 UnLock(FileLock);
  3390.  
  3391.                     /* Delete the variable. */
  3392.  
  3393.                 if(!DeleteFile(Buffer))
  3394.                 {
  3395.                     Success = FALSE;
  3396.                     continue;
  3397.                 }
  3398.             }
  3399.  
  3400.                 /* Set the new variable. */
  3401.  
  3402.             if(Length = strlen(Value))
  3403.             {
  3404.                 if(File = Open(Buffer,MODE_NEWFILE))
  3405.                 {
  3406.                     if(Write(File,Value,Length) != Length)
  3407.                     {
  3408.                         Close(File);
  3409.                         DeleteFile(Buffer);
  3410.  
  3411.                         Success = FALSE;
  3412.                     }
  3413.                     else
  3414.                     {
  3415.                         Close(File);
  3416.                         SetProtection(Buffer,FIBF_EXECUTE);
  3417.  
  3418.                         Success = TRUE;
  3419.                     }
  3420.                 }
  3421.                 else
  3422.                     Success = FALSE;
  3423.             }
  3424.             else
  3425.                 Success = TRUE;
  3426.         }
  3427.         else
  3428.             Success = FALSE;
  3429.     }
  3430.  
  3431.     return(Success);
  3432. }
  3433.  
  3434.     /* BumpWindow(struct Window *SomeWindow):
  3435.      *
  3436.      *    Bring a window to the front (and shift the screen
  3437.      *    back to its initial position).
  3438.      */
  3439.  
  3440. VOID
  3441. BumpWindow(struct Window *SomeWindow)
  3442. {
  3443.     if(SomeWindow -> WScreen -> LeftEdge > 0)
  3444.     {
  3445.         if(SomeWindow -> WScreen -> TopEdge > 0)
  3446.             MoveScreen(SomeWindow -> WScreen,-SomeWindow -> WScreen -> LeftEdge,-SomeWindow -> WScreen -> TopEdge);
  3447.         else
  3448.             MoveScreen(SomeWindow -> WScreen,-SomeWindow -> WScreen -> LeftEdge,0);
  3449.     }
  3450.     else
  3451.     {
  3452.         if(SomeWindow -> WScreen -> TopEdge > 0)
  3453.             MoveScreen(SomeWindow -> WScreen,0,-SomeWindow -> WScreen -> TopEdge);
  3454.     }
  3455.  
  3456.     ScreenToFront(SomeWindow -> WScreen);
  3457.  
  3458.     ActivateWindow(SomeWindow);
  3459. }
  3460.  
  3461.     /* BumpDefault():
  3462.      *
  3463.      *    Bring the current default screen to the front.
  3464.      */
  3465.  
  3466. VOID
  3467. BumpDefault()
  3468. {
  3469.     struct Screen *DefaultScreen;
  3470.  
  3471.     if(DefaultScreen = (struct Screen *)LockPubScreen(NULL))
  3472.     {
  3473.         MoveScreen(DefaultScreen,-DefaultScreen -> LeftEdge,-DefaultScreen -> TopEdge);
  3474.  
  3475.         ScreenToFront(DefaultScreen);
  3476.  
  3477.         UnlockPubScreen(NULL,DefaultScreen);
  3478.     }
  3479. }
  3480.  
  3481.     /* WriteIFFData(UBYTE *Name,APTR Data,LONG Size,ULONG Type):
  3482.      *
  3483.      *    Write data to an IFF file (via iffparse.library).
  3484.      */
  3485.  
  3486. BYTE
  3487. WriteIFFData(UBYTE *Name,APTR Data,LONG Size,ULONG Type)
  3488. {
  3489.     struct IFFHandle    *Handle;
  3490.     BYTE             Success = FALSE;
  3491.  
  3492.         /* Allocate a handle. */
  3493.  
  3494.     if(Handle = AllocIFF())
  3495.     {
  3496.             /* Open an output stream. */
  3497.  
  3498.         if(Handle -> iff_Stream = Open(Name,MODE_NEWFILE))
  3499.         {
  3500.                 /* Tell iffparse that this is
  3501.                  * a DOS handle.
  3502.                  */
  3503.  
  3504.             InitIFFasDOS(Handle);
  3505.  
  3506.                 /* Open the handle for writing. */
  3507.  
  3508.             if(!OpenIFF(Handle,IFFF_WRITE))
  3509.             {
  3510.                     /* Push outmost chunk onto stack. */
  3511.  
  3512.                 if(!PushChunk(Handle,'TERM','FORM',IFFSIZE_UNKNOWN))
  3513.                 {
  3514.                         /* Add a version identifier. */
  3515.  
  3516.                     if(!PushChunk(Handle,0,'VERS',IFFSIZE_UNKNOWN))
  3517.                     {
  3518.                         struct TermInfo TermInfo;
  3519.  
  3520.                         TermInfo . Version    = TermVersion;
  3521.                         TermInfo . Revision    = TermRevision;
  3522.  
  3523.                             /* Write the version data. */
  3524.  
  3525.                         if(WriteChunkBytes(Handle,&TermInfo,sizeof(struct TermInfo)) == sizeof(struct TermInfo))
  3526.                         {
  3527.                                 /* Pop the version chunk, i.e. write it to the file. */
  3528.  
  3529.                             if(PopChunk(Handle))
  3530.                                 Success = FALSE;
  3531.                             else
  3532.                             {
  3533.                                     /* Push the real data chunk on the stack. */
  3534.  
  3535.                                 if(!PushChunk(Handle,0,Type,IFFSIZE_UNKNOWN))
  3536.                                 {
  3537.                                         /* Write the data. */
  3538.  
  3539.                                     if(WriteChunkBytes(Handle,Data,Size) == Size)
  3540.                                         Success = TRUE;
  3541.  
  3542.                                             /* Pop the data chunk. */
  3543.  
  3544.                                     if(PopChunk(Handle))
  3545.                                         Success = FALSE;
  3546.                                 }
  3547.                                 else
  3548.                                     Success = FALSE;
  3549.                             }
  3550.                         }
  3551.                         else
  3552.                             Success = FALSE;
  3553.                     }
  3554.  
  3555.                         /* Seems that we're done, now try to pop the FORM chunk
  3556.                          * and return.
  3557.                          */
  3558.  
  3559.                     if(PopChunk(Handle))
  3560.                         Success = FALSE;
  3561.                 }
  3562.  
  3563.                     /* Close the handle (flush any pending data). */
  3564.  
  3565.                 CloseIFF(Handle);
  3566.             }
  3567.  
  3568.                 /* Close the DOS handle itself. */
  3569.  
  3570.             Close(Handle -> iff_Stream);
  3571.         }
  3572.  
  3573.             /* And free the IFF handle. */
  3574.  
  3575.         FreeIFF(Handle);
  3576.     }
  3577.  
  3578.     if(Success)
  3579.         SetProtection(Name,FIBF_EXECUTE);
  3580.  
  3581.     return(Success);
  3582. }
  3583.  
  3584.     /* ReadIFFData(UBYTE *Name,APTR Data,LONG Size,ULONG Type):
  3585.      *
  3586.      *    Read data from a `TERM' FORM chunk contained in an IFF file.
  3587.      */
  3588.  
  3589. BYTE
  3590. ReadIFFData(UBYTE *Name,APTR Data,LONG Size,ULONG Type)
  3591. {
  3592.     struct IFFHandle    *Handle;
  3593.     BYTE             Success = FALSE;
  3594.     struct StoredProperty    *Prop;
  3595.     struct TermInfo        *TermInfo;
  3596.  
  3597.     if(Handle = AllocIFF())
  3598.     {
  3599.         if(Handle -> iff_Stream = Open(Name,MODE_OLDFILE))
  3600.         {
  3601.             InitIFFasDOS(Handle);
  3602.  
  3603.             if(!OpenIFF(Handle,IFFF_READ))
  3604.             {
  3605.                 /* Collect version number ID if
  3606.                  * available.
  3607.                  */
  3608.  
  3609.                 if(!PropChunks(Handle,&VersionProps[0],1))
  3610.                 {
  3611.                     /* The following line tells iffparse to stop at the
  3612.                      * very beginning of a `Type' chunk contained in a
  3613.                      * `TERM' FORM chunk.
  3614.                      */
  3615.  
  3616.                     if(!StopChunk(Handle,'TERM',Type))
  3617.                     {
  3618.                         /* Parse the file... */
  3619.  
  3620.                         if(!ParseIFF(Handle,IFFPARSE_SCAN))
  3621.                         {
  3622.                             /* Did we get a version ID? */
  3623.  
  3624.                             if(Prop = FindProp(Handle,'TERM','VERS'))
  3625.                             {
  3626.                                 TermInfo = (struct TermInfo *)Prop -> sp_Data;
  3627.  
  3628.                                 /* Is it the file format we are able
  3629.                                  * to read?
  3630.                                  */
  3631.  
  3632.                                 if((TermInfo -> Version > TermVersion) || (TermInfo -> Version == TermVersion && TermInfo -> Revision > TermRevision) || (TermInfo -> Version == 1 && TermInfo -> Revision < 6))
  3633.                                     Success = FALSE;
  3634.                                 else
  3635.                                 {
  3636.                                     struct ContextNode *Chunk = CurrentChunk(Handle);
  3637.  
  3638.                                     if(Chunk -> cn_Size < Size) 
  3639.                                         Size = Chunk -> cn_Size;
  3640.  
  3641.                                     /* The file read pointer is positioned
  3642.                                      * just in front of the first data
  3643.                                      * to be read, so let's don't disappoint
  3644.                                      * iffparse and read it.
  3645.                                      */
  3646.  
  3647.                                     if(ReadChunkBytes(Handle,Data,Size) == Size)
  3648.                                         Success = TRUE;
  3649.                                 }
  3650.                             }
  3651.                         }
  3652.                     }
  3653.                 }
  3654.  
  3655.                 CloseIFF(Handle);
  3656.             }
  3657.  
  3658.             Close(Handle -> iff_Stream);
  3659.         }
  3660.  
  3661.         FreeIFF(Handle);
  3662.     }
  3663.  
  3664.     return(Success);
  3665. }
  3666.  
  3667.     /* PushWindow(struct Window *Window):
  3668.      *
  3669.      *    Push/PopWindow implement a single lifo window stack
  3670.      *    which always updates the window to activate when
  3671.      *    LSHIFT+RSHIFT+RETURN is pressed. This routine will
  3672.      *    push a window on the stack.
  3673.      */
  3674.  
  3675. VOID
  3676. PushWindow(struct Window *Window)
  3677. {
  3678.     if(WindowStackPtr < 5)
  3679.     {
  3680.         WindowStack[WindowStackPtr++] = Window;
  3681.  
  3682.         TopWindow = Window;
  3683.     }
  3684. }
  3685.  
  3686.     /* PopWindow():
  3687.      *
  3688.      *    Remove topmost window from window stack.
  3689.      */
  3690.  
  3691. VOID
  3692. PopWindow()
  3693. {
  3694.     if(WindowStackPtr > 0)
  3695.     {
  3696.         WindowStackPtr--;
  3697.  
  3698.         if(WindowStackPtr)
  3699.             TopWindow = WindowStack[WindowStackPtr - 1];
  3700.         else
  3701.             TopWindow = Window;
  3702.     }
  3703. }
  3704.