home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d8xx / d832 / term.lha / Term / term-3.1-Source.lha / termAux.c < prev    next >
C/C++ Source or Header  |  1993-02-19  |  52KB  |  2,744 lines

  1. /*
  2. **    termAux.c
  3. **
  4. **    Miscellaneous support routines
  5. **
  6. **    Copyright © 1990-1993 by Olaf `Olsen' Barthel & MXM
  7. **        All Rights Reserved
  8. */
  9.  
  10. #include "termGlobal.h"
  11.  
  12.     /* Block window nest count. */
  13.  
  14. STATIC WORD BlockNestCount;
  15.  
  16.     /* This variable stores the current state of the
  17.      * dialing menu items.
  18.      */
  19.  
  20. STATIC BYTE DialItemsAvailable = TRUE;
  21.  
  22.     /* GetPubScreenName(struct Screen *Screen,STRPTR Name):
  23.      *
  24.      *    Get the name of a public screen.
  25.      */
  26.  
  27. BYTE __regargs
  28. GetPubScreenName(struct Screen *Screen,STRPTR Name)
  29. {
  30.     struct List        *PubScreenList;
  31.     struct PubScreenNode    *ScreenNode;
  32.  
  33.     PubScreenList = LockPubScreenList();
  34.  
  35.     for(ScreenNode = (struct PubScreenNode *)PubScreenList -> lh_Head ; ScreenNode -> psn_Node . ln_Succ ; ScreenNode = (struct PubScreenNode *)ScreenNode -> psn_Node . ln_Succ)
  36.     {
  37.         if(ScreenNode -> psn_Screen == Screen)
  38.         {
  39.             strcpy(Name,ScreenNode -> psn_Node . ln_Name);
  40.  
  41.             UnlockPubScreenList();
  42.  
  43.             return(TRUE);
  44.         }
  45.     }
  46.  
  47.     UnlockPubScreenList();
  48.  
  49.     return(FALSE);
  50. }
  51.  
  52.     /* InitSinglePort(struct MsgPort *Port):
  53.      *
  54.      *    Initialize a plain MsgPort (as created on the stack) for
  55.      *    usage. Don't try this at home, kids!
  56.      */
  57.  
  58. VOID __regargs
  59. InitSinglePort(struct MsgPort *Port)
  60. {
  61.     memset(Port,0,sizeof(struct MsgPort));
  62.  
  63.     Port -> mp_Flags    = PA_SIGNAL;
  64.     Port -> mp_SigBit    = SIGB_SINGLE;
  65.     Port -> mp_SigTask    = SysBase -> ThisTask;
  66.  
  67.     NewList(&Port -> mp_MsgList);
  68. }
  69.  
  70.     /* GoodStream(BPTR Stream):
  71.      *
  72.      *    Check to see whether the current input file
  73.      *    is an interactive stream.
  74.      */
  75.  
  76. BYTE __regargs
  77. GoodStream(BPTR Stream)
  78. {
  79.     if(!Stream)
  80.     {
  81.         struct Process *ThisProcess = (struct Process *)SysBase -> ThisTask;
  82.  
  83.         Stream = ThisProcess -> pr_CIS;
  84.     }
  85.  
  86.     if(Stream)
  87.     {
  88.         struct FileHandle *Handle = (struct FileHandle *)BADDR(Stream);
  89.  
  90.         if(Handle -> fh_Type)
  91.         {
  92.             if(IsInteractive(Stream))
  93.                 return(TRUE);
  94.         }
  95.     }
  96.  
  97.     return(FALSE);
  98. }
  99.  
  100.     /* GetProgramIcon():
  101.      *
  102.      *    Try to find the icon of the program.
  103.      */
  104.  
  105. struct DiskObject *
  106. GetProgramIcon()
  107. {
  108.     struct DiskObject *Icon = NULL;
  109.  
  110.         /* Run from Workbench? */
  111.  
  112.     if(WBenchMsg)
  113.     {
  114.             /* Sanity check. */
  115.  
  116.         if(WBenchMsg -> sm_ArgList)
  117.         {
  118.                 /* Yet another sanity check. */
  119.  
  120.             if(WBenchMsg -> sm_ArgList -> wa_Name)
  121.             {
  122.                     /* Try to find the icon in the current directory. */
  123.  
  124.                 if(Icon = GetDiskObjectNew(WBenchMsg -> sm_ArgList -> wa_Name))
  125.                 {
  126.                     if(Icon -> do_Type != WBTOOL)
  127.                     {
  128.                         FreeDiskObject(Icon);
  129.  
  130.                         Icon = NULL;
  131.                     }
  132.                 }
  133.  
  134.                 if(!Icon)
  135.                 {
  136.                     BPTR NewLock;
  137.  
  138.                         /* Move to the directory the
  139.                          * program was run from.
  140.                          */
  141.  
  142.                     if(NewLock = Lock("PROGDIR:",ACCESS_READ))
  143.                     {
  144.                         BPTR OldLock;
  145.  
  146.                         OldLock = CurrentDir(NewLock);
  147.  
  148.                             /* Try to fetch the icon, use the
  149.                              * default name if necessary.
  150.                              */
  151.  
  152.                         if(Icon = GetDiskObjectNew(WBenchMsg -> sm_ArgList -> wa_Name))
  153.                         {
  154.                             if(Icon -> do_Type != WBTOOL)
  155.                             {
  156.                                 FreeDiskObject(Icon);
  157.  
  158.                                 Icon = NULL;
  159.                             }
  160.                         }
  161.  
  162.                         if(!Icon)
  163.                         {
  164.                             if(Icon = GetDiskObjectNew("term"))
  165.                             {
  166.                                 if(Icon -> do_Type != WBTOOL)
  167.                                 {
  168.                                     FreeDiskObject(Icon);
  169.  
  170.                                     Icon = NULL;
  171.                                 }
  172.                             }
  173.                         }
  174.  
  175.                         CurrentDir(OldLock);
  176.  
  177.                         UnLock(NewLock);
  178.                     }
  179.                 }
  180.             }
  181.         }
  182.     }
  183.  
  184.         /* Still no success. */
  185.  
  186.     if(!Icon)
  187.     {
  188.             /* Use the default names. */
  189.  
  190.         if(Icon = GetDiskObjectNew("term"))
  191.         {
  192.             if(Icon -> do_Type != WBTOOL)
  193.             {
  194.                 FreeDiskObject(Icon);
  195.  
  196.                 Icon = NULL;
  197.             }
  198.         }
  199.  
  200.         if(!Icon)
  201.         {
  202.             if(Icon = GetDiskObjectNew("PROGDIR:term"))
  203.             {
  204.                 if(Icon -> do_Type != WBTOOL)
  205.                 {
  206.                     FreeDiskObject(Icon);
  207.  
  208.                     Icon = NULL;
  209.                 }
  210.             }
  211.         }
  212.     }
  213.  
  214.     return(Icon);
  215. }
  216.  
  217.     /* GetPenIndex(LONG Pen):
  218.      *
  219.      *    Get the table index corresponding to an on-screen
  220.      *    text rendering pen.
  221.      */
  222.  
  223. LONG __regargs
  224. GetPenIndex(LONG Pen)
  225. {
  226.     LONG i;
  227.  
  228.     for(i = 0 ; i < 16 ; i++)
  229.     {
  230.         if(MappedPens[0][i] == Pen)
  231.             return(i);
  232.     }
  233. }
  234.  
  235.     /* GetScreenWidth(struct Window *Window):
  236.      *
  237.      *    Query the current screen width.
  238.      */
  239.  
  240. LONG __regargs
  241. GetScreenWidth(struct Window *Window)
  242. {
  243.     if(Window)
  244.     {
  245.         if(Window -> Width > ScreenWidth || Window -> LeftEdge < -Window -> WScreen -> LeftEdge || Window -> LeftEdge + Window -> WScreen -> LeftEdge + Window -> Width > ScreenWidth)
  246.             return(ScreenWidth);
  247.         else
  248.             return(Window -> Width - (Window -> BorderLeft + Window -> BorderRight));
  249.     }
  250.     else
  251.         return(ScreenWidth);
  252. }
  253.  
  254.     /* GetScreenHeight(struct Window *Window):
  255.      *
  256.      *    Query the current screen height.
  257.      */
  258.  
  259. LONG __regargs
  260. GetScreenHeight(struct Window *Window)
  261. {
  262.     if(Window)
  263.     {
  264.         if(Window -> Height > ScreenHeight || Window -> TopEdge < -Window -> WScreen -> TopEdge || Window -> TopEdge + Window -> WScreen -> TopEdge + Window -> Height > ScreenHeight)
  265.             return(ScreenHeight);
  266.         else
  267.             return(Window -> Height - (Window -> BorderTop + Window -> BorderBottom));
  268.     }
  269.     else
  270.         return(ScreenHeight);
  271. }
  272.  
  273.     /* GetLeft(struct Screen *Screen):
  274.      *
  275.      *    Get the screen left edge.
  276.      */
  277.  
  278. STATIC LONG __regargs
  279. GetLeft(struct Screen *Screen)
  280. {
  281.     if(Screen -> LeftEdge >= 0)
  282.         return(0);
  283.     else
  284.         return(-Screen -> LeftEdge);
  285. }
  286.  
  287.     /* GetScreenLeft(struct Window *Window):
  288.      *
  289.      *    Query the current screen left edge.
  290.      */
  291.  
  292. LONG __regargs
  293. GetScreenLeft(struct Window *Window)
  294. {
  295.     if(Window)
  296.     {
  297.         if(Window -> Width > ScreenWidth || Window -> LeftEdge < -Window -> WScreen -> LeftEdge || Window -> LeftEdge + Window -> WScreen -> LeftEdge + Window -> Width > ScreenWidth)
  298.             return(GetLeft(Window -> WScreen));
  299.         else
  300.             return(Window -> LeftEdge + Window -> BorderLeft);
  301.     }
  302.     else
  303.         return(GetLeft(DefaultPubScreen));
  304. }
  305.  
  306.     /* GetTop(struct Screen *Screen):
  307.      *
  308.      *    Get the screen top edge.
  309.      */
  310.  
  311. STATIC LONG __regargs
  312. GetTop(struct Screen *Screen)
  313. {
  314.     if(Screen -> TopEdge >= 0)
  315.         return(0);
  316.     else
  317.         return(-Screen -> TopEdge);
  318. }
  319.  
  320.     /* GetScreenTop(struct Window *Window):
  321.      *
  322.      *    Query the current screen top edge.
  323.      */
  324.  
  325. LONG __regargs
  326. GetScreenTop(struct Window *Window)
  327. {
  328.     if(Window)
  329.     {
  330.         if(Window -> Height > ScreenHeight || Window -> TopEdge < -Window -> WScreen -> TopEdge || Window -> TopEdge + Window -> WScreen -> TopEdge + Window -> Height > ScreenHeight)
  331.             return(GetTop(Window -> WScreen));
  332.         else
  333.             return(Window -> TopEdge + Window -> BorderTop);
  334.     }
  335.     else
  336.         return(GetTop(DefaultPubScreen));
  337. }
  338.  
  339.     /* OldGetAPen(struct RastPort *RPort):
  340.      *
  341.      *    Query the current primary rendering colour (old style).
  342.      */
  343.  
  344. ULONG __regargs
  345. OldGetAPen(struct RastPort *RPort)
  346. {
  347.     return((ULONG)RPort -> FgPen);
  348. }
  349.  
  350.     /* OldGetBPen(struct RastPort *RPort):
  351.      *
  352.      *    Query the current seconary rendering colour (old style).
  353.      */
  354.  
  355. ULONG __regargs
  356. OldGetBPen(struct RastPort *RPort)
  357. {
  358.     return((ULONG)RPort -> BgPen);
  359. }
  360.  
  361.     /* OldGetDrMd(struct RastPort *RPort):
  362.      *
  363.      *    Query the current drawing mode (old style).
  364.      */
  365.  
  366. ULONG __regargs
  367. OldGetDrMd(struct RastPort *RPort)
  368. {
  369.     return((ULONG)RPort -> DrawMode);
  370. }
  371.  
  372.     /* OldSetWrMsk(struct RastPort *RPort,ULONG Mask):
  373.      *
  374.      *    Set the rendering plane mask (old style).
  375.      */
  376.  
  377. ULONG __regargs
  378. OldSetWrMsk(struct RastPort *RPort,ULONG Mask)
  379. {
  380.     RPort -> Mask = Mask;
  381.  
  382.     return((ULONG)1);
  383. }
  384.  
  385.     /* NewGetAPen(struct RastPort *RPort):
  386.      *
  387.      *    Query the current primary rendering colour (new style).
  388.      */
  389.  
  390. ULONG __regargs
  391. NewGetAPen(struct RastPort *RPort)
  392. {
  393.     return(GetAPen(RPort));
  394. }
  395.  
  396.     /* NewGetBPen(struct RastPort *RPort):
  397.      *
  398.      *    Query the current seconary rendering colour (new style).
  399.      */
  400.  
  401. ULONG __regargs
  402. NewGetBPen(struct RastPort *RPort)
  403. {
  404.     return(GetBPen(RPort));
  405. }
  406.  
  407.     /* NewGetDrMd(struct RastPort *RPort):
  408.      *
  409.      *    Query the current drawing mode (new style).
  410.      */
  411.  
  412. ULONG __regargs
  413. NewGetDrMd(struct RastPort *RPort)
  414. {
  415.     return(GetDrMd(RPort));
  416. }
  417.  
  418.     /* NewSetWrMsk(struct RastPort *RPort,ULONG Mask):
  419.      *
  420.      *    Set the rendering plane mask (new style).
  421.      */
  422.  
  423. ULONG __regargs
  424. NewSetWrMsk(struct RastPort *RPort,ULONG Mask)
  425. {
  426.     return(SetWriteMask(RPort,Mask));
  427. }
  428.  
  429.     /* SetWait(struct Window *Window):
  430.      *
  431.      *    Set the busy wait mouse pointer.
  432.      */
  433.  
  434. VOID
  435. SetWait(struct Window *Window)
  436. {
  437.     if(IntuitionBase -> LibNode . lib_Version >= 39)
  438.     {
  439.         SetWindowPointer(Window,
  440.             WA_BusyPointer,        TRUE,
  441.             WA_PointerDelay,    TRUE,
  442.         TAG_DONE);
  443.     }
  444.     else
  445.         SetPointer(Window,Stopwatch,16,16,-6,0);
  446. }
  447.  
  448.     /* ClrWait(struct Window *Window):
  449.      *
  450.      *    Remove the busy wait mouse pointer.
  451.      */
  452.  
  453. VOID
  454. ClrWait(struct Window *Window)
  455. {
  456.     if(IntuitionBase -> LibNode . lib_Version >= 39)
  457.         SetWindowPointer(Window,TAG_DONE);
  458.     else
  459.         ClearPointer(Window);
  460. }
  461.  
  462.     /* GetModeName(ULONG Mode):
  463.      *
  464.      *    Get the name of a display mode.
  465.      */
  466.  
  467. STRPTR
  468. GetModeName(ULONG Mode)
  469. {
  470.     STATIC UBYTE    Buffer[DISPLAYNAMELEN + 1];
  471.     struct NameInfo    NameInfo;
  472.  
  473.     if(GetDisplayInfoData(NULL,(APTR)&NameInfo,sizeof(struct NameInfo),DTAG_NAME,Mode))
  474.         strcpy(Buffer,NameInfo . Name);
  475.     else
  476.     {
  477.         struct DimensionInfo DimensionInfo;
  478.  
  479.         if(GetDisplayInfoData(NULL,(APTR)&DimensionInfo,sizeof(struct DimensionInfo),DTAG_NAME,Mode))
  480.         {
  481.             STRPTR MonitorName;
  482.  
  483.             switch(Mode & MONITOR_ID_MASK)
  484.             {
  485.                 case NTSC_MONITOR_ID:
  486.  
  487.                     MonitorName = "NTSC: ";
  488.                     break;
  489.  
  490.                 case PAL_MONITOR_ID:
  491.  
  492.                     MonitorName = "PAL: ";
  493.                     break;
  494.  
  495.                 case VGA_MONITOR_ID:
  496.  
  497.                     MonitorName = "VGA: ";
  498.                     break;
  499.  
  500.                 case A2024_MONITOR_ID:
  501.  
  502.                     MonitorName = "A2024: ";
  503.                     break;
  504.  
  505.                 default:
  506.  
  507.                     MonitorName = "";
  508.                     break;
  509.             }
  510.  
  511.             SPrintf(Buffer,"%s%ld × %ld",MonitorName,DimensionInfo . TxtOScan . MaxX - DimensionInfo . TxtOScan . MinX + 1,DimensionInfo . TxtOScan . MaxY - DimensionInfo . TxtOScan . MinY + 1);
  512.         }
  513.         else
  514.             strcpy(Buffer,LocaleString(MSG_SCREENPANEL_UNKNOWN_TXT));
  515.     }
  516.  
  517.     return(Buffer);
  518. }
  519.  
  520.     /* ModeOkay(ULONG ID):
  521.      *
  522.      *    Checks whether a display mode ID will do for deep
  523.      *    screen bitmaps.
  524.      */
  525.  
  526. BYTE __regargs
  527. ModeOkay(ULONG ID)
  528. {
  529.     struct DimensionInfo DimensionInfo;
  530.  
  531.     if(GetDisplayInfoData(NULL,(APTR)&DimensionInfo,sizeof(struct DimensionInfo),DTAG_DIMS,ID))
  532.     {
  533.         if(DimensionInfo . MaxDepth >= 4)
  534.             return(TRUE);
  535.     }
  536.  
  537.     return(FALSE);
  538. }
  539.  
  540.     /* SetRedialMenu():
  541.      *
  542.      *    Make the `redial' menu item available or make it
  543.      *    unavailable.
  544.      */
  545.  
  546. VOID
  547. SetRedialMenu()
  548. {
  549.     BYTE Mode;
  550.  
  551.     if(DialList)
  552.     {
  553.         if(DialList -> lh_Head -> ln_Succ)
  554.             Mode = TRUE;
  555.         else
  556.             Mode = FALSE;
  557.     }
  558.     else
  559.         Mode = FALSE;
  560.  
  561.     if(Mode && DialItemsAvailable)
  562.         OnItem(MEN_REDIAL);
  563.     else
  564.         OffItem(MEN_REDIAL);
  565. }
  566.  
  567.     /* SetDialMenu(BYTE Mode):
  568.      *
  569.      *    Block or enable the dialing menu.
  570.      */
  571.  
  572. VOID
  573. SetDialMenu(BYTE Mode)
  574. {
  575.     if(Window && Menu)
  576.     {
  577.         if(Mode)
  578.         {
  579.             if(DialList)
  580.             {
  581.                 if(DialList -> lh_Head -> ln_Succ)
  582.                     OnItem(MEN_REDIAL);
  583.                 else
  584.                     OffItem(MEN_REDIAL);
  585.             }
  586.             else
  587.                 OffItem(MEN_REDIAL);
  588.  
  589.             OnItem(MEN_DIAL_NUMBER);
  590.         }
  591.         else
  592.         {
  593.             OffItem(MEN_REDIAL);
  594.             OffItem(MEN_DIAL_NUMBER);
  595.         }
  596.  
  597.         DialItemsAvailable = Mode;
  598.     }
  599. }
  600.  
  601.     /* SetTransferMenu(BYTE Mode):
  602.      *
  603.      *    Block or enable the transfer menu.
  604.      */
  605.  
  606. VOID
  607. SetTransferMenu(BYTE Mode)
  608. {
  609.     if(Window && Menu)
  610.     {
  611.         if(Mode)
  612.         {
  613.             ULONG i;
  614.  
  615.             for(i = MEN_UPLOAD_ASCII ; i <= MEN_DOWNLOAD_BINARY ; i++)
  616.                 OnItem(i);
  617.  
  618.             OnItem(MEN_TRANSFER);
  619.         }
  620.         else
  621.         {
  622.             ULONG i;
  623.  
  624.             for(i = MEN_UPLOAD_ASCII ; i <= MEN_DOWNLOAD_BINARY ; i++)
  625.                 OffItem(i);
  626.  
  627.             OffItem(MEN_TRANSFER);
  628.         }
  629.     }
  630. }
  631.  
  632.     /* SetRasterMenu(BYTE Mode):
  633.      *
  634.      *    Block or enable the menu entries associated with
  635.      *    functions to access the screen raster.
  636.      */
  637.  
  638. VOID
  639. SetRasterMenu(BYTE Mode)
  640. {
  641.     if(Window && Menu)
  642.     {
  643.         if(Mode)
  644.         {
  645.             OnItem(MEN_SAVE_AS_TEXT);
  646.             OnItem(MEN_PRINT_SCREEN);
  647.  
  648.             OnItem(MEN_COPY);
  649.             OnItem(MEN_CLEAR);
  650.         }
  651.         else
  652.         {
  653.             OffItem(MEN_SAVE_AS_TEXT);
  654.             OffItem(MEN_PRINT_SCREEN);
  655.  
  656.             OffItem(MEN_COPY);
  657.             OffItem(MEN_CLEAR);
  658.         }
  659.     }
  660. }
  661.  
  662.     /* PickFont(struct Window *Window,STRPTR Name,WORD *Height,BYTE MonoSpaced):
  663.      *
  664.      *    Pick a font using asl.library
  665.      */
  666.  
  667. BYTE
  668. PickFont(struct Window *Window,STRPTR Name,WORD *Height,BYTE MonoSpaced)
  669. {
  670.     struct FontRequester    *Requester;
  671.     BYTE             Result = FALSE;
  672.  
  673.     if(Requester = (struct FontRequester *)AllocAslRequestTags(ASL_FontRequest,
  674.         ASL_Window,                    Window,
  675.         MonoSpaced ? ASL_FuncFlags : TAG_IGNORE,    FONF_FIXEDWIDTH,
  676.     TAG_DONE))
  677.     {
  678.         if(AslRequestTags(Requester,
  679.             ASL_FontName,    Name,
  680.             ASL_FontHeight,    *Height,
  681.         TAG_DONE))
  682.         {
  683.             strcpy(Name,Requester -> fo_Attr . ta_Name);
  684.  
  685.             *Height = Requester -> fo_Attr . ta_YSize;
  686.  
  687.             Result = TRUE;
  688.         }
  689.  
  690.         FreeAslRequest(Requester);
  691.     }
  692.  
  693.     return(Result);
  694. }
  695.  
  696.     /* ExtractString():
  697.      *
  698.      *    Extracts a string from a list separated by `|' characters.
  699.      */
  700.  
  701. STRPTR __regargs
  702. ExtractString(STRPTR String,STRPTR Destination,BYTE ReturnEnd)
  703. {
  704.     STRPTR OldString;
  705.  
  706.     if(ReturnEnd)
  707.         OldString = NULL;
  708.     else
  709.         OldString = String;
  710.  
  711.     while(*String)
  712.     {
  713.         if(*String == '|')
  714.         {
  715.             *Destination = 0;
  716.  
  717.             String++;
  718.  
  719.             if(*String)
  720.                 return(String);
  721.             else
  722.                 return(OldString);
  723.         }
  724.         else
  725.             *Destination++ = *String++;
  726.     }
  727.  
  728.     *Destination = 0;
  729.  
  730.     return(OldString);
  731. }
  732.  
  733.     /* GetListSize(struct List *List):
  734.      *
  735.      *    Determine the number of entries in a list.
  736.      */
  737.  
  738. LONG
  739. GetListSize(struct List *List)
  740. {
  741.     struct Node    *Node    = List -> lh_Head;
  742.     LONG         i    = 0;
  743.  
  744.     while(Node -> ln_Succ)
  745.     {
  746.         i++;
  747.  
  748.         Node = Node -> ln_Succ;
  749.     }
  750.  
  751.     return(i);
  752. }
  753.  
  754.     /* GetListNode(LONG Offset,struct List *List):
  755.      *
  756.      *    Return the n-th Node entry in a standard exec list.
  757.      */
  758.  
  759. struct Node *
  760. GetListNode(LONG Offset,struct List *List)
  761. {
  762.     struct Node    *Node;
  763.     LONG         i;
  764.  
  765.     Node = List -> lh_Head;
  766.  
  767.     for(i = 0 ; i < Offset ; i++)
  768.     {
  769.         if(!Node -> ln_Succ -> ln_Succ)
  770.             return(NULL);
  771.  
  772.         Node = Node -> ln_Succ;
  773.     }
  774.  
  775.     return(Node);
  776. }
  777.  
  778.     /* LogAction(STRPTR String,...):
  779.      *
  780.      *    Write an action to the default log file.
  781.      */
  782.  
  783. VOID __stdargs
  784. LogAction(STRPTR String,...)
  785. {
  786.     if(Config -> CaptureConfig -> LogActions && Config -> CaptureConfig -> LogFileName[0])
  787.     {
  788.         UBYTE    DummyBuffer[512];
  789.         BPTR    File;
  790.  
  791.         va_list    VarArgs;
  792.  
  793.             /* Build a valid string. */
  794.  
  795.         va_start(VarArgs,String);
  796.         VSPrintf(DummyBuffer,String,VarArgs);
  797.         va_end(VarArgs);
  798.  
  799.             /* Does the log file already exist? */
  800.  
  801.         if(GetFileSize(Config -> CaptureConfig -> LogFileName))
  802.         {
  803.                 /* It does, let's append the data. */
  804.  
  805.             if(File = Open(Config -> CaptureConfig -> LogFileName,MODE_READWRITE))
  806.             {
  807.                 if(Seek(File,0,OFFSET_END) == -1)
  808.                 {
  809.                     Close(File);
  810.  
  811.                     File = NULL;
  812.                 }
  813.             }
  814.         }
  815.         else
  816.         {
  817.                 /* Create a new file. */
  818.  
  819.             if(File = Open(Config -> CaptureConfig -> LogFileName,MODE_NEWFILE))
  820.                 FPrintf(File,LocaleString(MSG_TERMAUX_DATE_TIME_ACTION_TXT));
  821.         }
  822.  
  823.             /* The file is open, build the date/time string and
  824.              * write the log action.
  825.              */
  826.  
  827.         if(File)
  828.         {
  829.             UBYTE        TimeBuffer[20],DateBuffer[20];
  830.             struct DateTime    DateTime;
  831.  
  832.                 /* Obtain current time. */
  833.  
  834.             DateStamp(&DateTime . dat_Stamp);
  835.  
  836.                 /* Convert it to human readable form. */
  837.  
  838.             DateTime . dat_Format    = FORMAT_DOS;
  839.             DateTime . dat_Flags    = 0;
  840.             DateTime . dat_StrDay    = NULL;
  841.             DateTime . dat_StrDate    = DateBuffer;
  842.             DateTime . dat_StrTime    = TimeBuffer;
  843.  
  844.                 /* Conversion succeeded? */
  845.  
  846.             if(DateToStr(&DateTime))
  847.                 FPrintf(File,"%s %s %s\n",DateBuffer,TimeBuffer,DummyBuffer);
  848.  
  849.                 /* Done! */
  850.  
  851.             Close(File);
  852.         }
  853.     }
  854. }
  855.  
  856.     /* FlushMsg(struct Window *Window):
  857.      *
  858.      *    Cancel all pending messages of a window.
  859.      */
  860.  
  861. VOID
  862. FlushMsg(struct Window *Window)
  863. {
  864.     struct IntuiMessage *Massage;
  865.  
  866.     while(Massage = (struct IntuiMessage *)GetMsg(Window -> UserPort))
  867.         ReplyMsg(&Massage -> ExecMessage);
  868. }
  869.  
  870.     /* GetString(STRPTR Prompt,STRPTR Buffer):
  871.      *
  872.      *    Get a string from the user, very much the same as xpr_gets,
  873.      *    but also including the `Load File' gadget.
  874.      */
  875.  
  876. BYTE
  877. GetString(BYTE LoadGadget,BYTE Password,WORD MaxChars,STRPTR Prompt,STRPTR Buffer)
  878. {
  879.     struct Gadget        *GadgetList = NULL;
  880.     struct Gadget        *GadgetArray[4];
  881.     struct Window        *PanelWindow;
  882.     UBYTE             DummyBuffer[MAX_FILENAME_LENGTH];
  883.     struct FileRequester    *FileRequest;
  884.     BYTE             Success = FALSE;
  885.  
  886.     if(CreateAllGetsGadgets(LoadGadget,Password,MaxChars,Buffer,Prompt,GadgetArray,&GadgetList,VisualInfo,Window -> WScreen))
  887.     {
  888.         if(PanelWindow = OpenWindowTags(NULL,
  889.             WA_Left,    GetScreenLeft(Window) + (GetScreenWidth(Window) - SZ_GetWindowWidth()) / 2,
  890.             WA_Top,        GetScreenTop(Window) + (GetScreenHeight(Window) - SZ_GetWindowHeight())    / 2,
  891.             WA_Width,    SZ_GetWindowWidth(),
  892.             WA_Height,    SZ_GetWindowHeight(),
  893.  
  894.             WA_Activate,    TRUE,
  895.             WA_DragBar,    TRUE,
  896.             WA_DepthGadget,    TRUE,
  897.             WA_CloseGadget,    TRUE,
  898.             WA_RMBTrap,    TRUE,
  899.             WA_CustomScreen,Window -> WScreen,
  900.             WA_IDCMP,    IDCMP_GADGETDOWN | IDCMP_ACTIVEWINDOW | IDCMP_CLOSEWINDOW | IDCMP_GADGETUP | IDCMP_VANILLAKEY | IDCMP_RAWKEY | BUTTONIDCMP | STRINGIDCMP,
  901.             WA_Title,    LocaleString(MSG_GLOBAL_ENTER_TEXT_TXT),
  902.         TAG_DONE))
  903.         {
  904.             struct IntuiMessage    *Massage;
  905.             ULONG             IClass,Code;
  906.             struct Gadget        *Gadget;
  907.             BYTE             Terminated = FALSE;
  908.  
  909.             PushWindow(PanelWindow);
  910.  
  911.             AddGList(PanelWindow,GadgetList,(UWORD)-1,(UWORD)-1,NULL);
  912.             RefreshGList(GadgetList,PanelWindow,NULL,(UWORD)-1);
  913.             GT_RefreshWindow(PanelWindow,NULL);
  914.  
  915.             ActiveGadget = NULL;
  916.  
  917.             SetSignal(0,SIG_BREAK);
  918.  
  919.             while(!Terminated)
  920.             {
  921.                 if(Wait(PORTMASK(PanelWindow -> UserPort) | SIG_BREAK) & SIG_BREAK)
  922.                     break;
  923.  
  924.                 while(!Terminated && (Massage = (struct IntuiMessage *)GT_GetIMsg(PanelWindow -> UserPort)))
  925.                 {
  926.                     IClass    = Massage -> Class;
  927.                     Code    = Massage -> Code;
  928.                     Gadget    = (struct Gadget *)Massage -> IAddress;
  929.  
  930.                     GT_ReplyIMsg(Massage);
  931.  
  932.                     if(IClass == IDCMP_VANILLAKEY)
  933.                         KeySelect(GadgetArray,3,Code,PanelWindow,&Gadget,&IClass,&Code);
  934.  
  935.                     if(IClass == IDCMP_RAWKEY && Code == HELP_CODE)
  936.                         DisplayBeep(PanelWindow -> WScreen);
  937.  
  938.                     if(IClass == IDCMP_GADGETDOWN)
  939.                     {
  940.                         if((Gadget -> GadgetType & GTYP_GTYPEMASK) == GTYP_STRGADGET)
  941.                             ActiveGadget = Gadget;
  942.                     }
  943.  
  944.                     if(IClass == IDCMP_ACTIVEWINDOW && ActiveGadget)
  945.                         ActivateGadget(ActiveGadget,PanelWindow,NULL);
  946.  
  947.                     if(IClass == IDCMP_CLOSEWINDOW)
  948.                         Terminated = TRUE;
  949.  
  950.                     if(IClass == IDCMP_GADGETUP)
  951.                     {
  952.                         switch(Gadget -> GadgetID)
  953.                         {
  954.                             case 0:
  955.  
  956.                                 strcpy(Buffer,SZ_GetString(GadgetArray[0]));
  957.  
  958.                                 Success = TRUE;
  959.  
  960.                                 Terminated = TRUE;
  961.  
  962.                                 break;
  963.  
  964.                             case 1:
  965.  
  966.                                 BlockWindow(PanelWindow);
  967.  
  968.                                 if(FileRequest = GetFile(LocaleString(MSG_TERMAUX_LOAD_FILE_TXT),"","",DummyBuffer,NULL,FALSE,FALSE,FALSE,LocaleString(MSG_GLOBAL_SELECT_TXT)))
  969.                                 {
  970.                                     GT_SetGadgetAttrs(GadgetArray[0],PanelWindow,NULL,
  971.                                         GTST_String,DummyBuffer,
  972.                                     TAG_DONE);
  973.  
  974.                                     FreeAslRequest(FileRequest);
  975.                                 }
  976.  
  977.                                 ReleaseWindow(PanelWindow);
  978.  
  979.                                 break;
  980.  
  981.                             case 2:
  982.  
  983.                                 strcpy(Buffer,SZ_GetString(GadgetArray[0]));
  984.  
  985.                                 Success = TRUE;
  986.  
  987.                                 Terminated = TRUE;
  988.  
  989.                                 break;
  990.  
  991.                             case 3:
  992.  
  993.                                 Terminated = TRUE;
  994.                                 break;
  995.                         }
  996.                     }
  997.                 }
  998.             }
  999.  
  1000.             ActiveGadget = NULL;
  1001.  
  1002.             RemoveGList(PanelWindow,GadgetList,(UWORD)-1);
  1003.  
  1004.             PopWindow();
  1005.  
  1006.             CloseWindow(PanelWindow);
  1007.         }
  1008.     }
  1009.  
  1010.     FreeGadgets(GadgetList);
  1011.  
  1012.     return(Success);
  1013. }
  1014.  
  1015.     /* WakeUp(struct Window *Window):
  1016.      *
  1017.      *    Pop a window to the front and alert the user.
  1018.      */
  1019.  
  1020. VOID __regargs
  1021. WakeUp(struct Window *Window)
  1022. {
  1023.     if(Window)
  1024.     {
  1025.         if(Config -> TerminalConfig -> AlertMode == ALERT_SCREEN || Config -> TerminalConfig -> AlertMode == ALERT_BEEP_SCREEN)
  1026.         {
  1027.             if(Window -> WScreen -> LeftEdge > 0)
  1028.             {
  1029.                 if(Window -> WScreen -> TopEdge > 0)
  1030.                     MoveScreen(Window -> WScreen,-Window -> WScreen -> LeftEdge,-Window -> WScreen -> TopEdge);
  1031.                 else
  1032.                     MoveScreen(Window -> WScreen,-Window -> WScreen -> LeftEdge,0);
  1033.             }
  1034.             else
  1035.             {
  1036.                 if(Window -> WScreen -> TopEdge > 0)
  1037.                     MoveScreen(Window -> WScreen,0,-Window -> WScreen -> TopEdge);
  1038.             }
  1039.  
  1040.             WindowToFront(Window);
  1041.  
  1042.             ScreenToFront(Window -> WScreen);
  1043.         }
  1044.     }
  1045.  
  1046.     if(Config -> TerminalConfig -> AlertMode == ALERT_BEEP || Config -> TerminalConfig -> AlertMode == ALERT_BEEP_SCREEN)
  1047.         Beep();
  1048. }
  1049.  
  1050.     /* AmigaDOSBackgroundServer(VOID):
  1051.      *
  1052.      *    Background process to handle tool execution.
  1053.      */
  1054.  
  1055. STATIC VOID __saveds
  1056. AmigaDOSBackgroundServer(VOID)
  1057. {
  1058.     struct Process    *ThisProcess = (struct Process *)SysBase -> ThisTask;
  1059.     struct Message    *Message;
  1060.     BPTR         OldCOS,
  1061.              NewCOS = NULL;
  1062.  
  1063.     WaitPort(&ThisProcess -> pr_MsgPort);
  1064.  
  1065.     Message = GetMsg(&ThisProcess -> pr_MsgPort);
  1066.  
  1067.         /* Create console output stream, will be closed automagically on exit. */
  1068.  
  1069.     if(!ThisProcess -> pr_COS && ThisProcess -> pr_ConsoleTask)
  1070.     {
  1071.         if(NewCOS = Open("*",MODE_NEWFILE))
  1072.         {
  1073.             OldCOS = ThisProcess -> pr_COS;
  1074.  
  1075.             ThisProcess -> pr_COS = NewCOS;
  1076.         }
  1077.     }
  1078.  
  1079.     SystemTags(Message -> mn_Node . ln_Name,TAG_DONE);
  1080.  
  1081.     Forbid();
  1082.  
  1083.     if(NewCOS)
  1084.     {
  1085.         ThisProcess -> pr_COS = OldCOS;
  1086.  
  1087.         Close(NewCOS);
  1088.     }
  1089.  
  1090.     ReplyMsg(Message);
  1091. }
  1092.  
  1093.     /* SendAmigaDOSCommand(STRPTR Name):
  1094.      *
  1095.      *    Let the current default Shell execute an AmigaDOS
  1096.      *    command. Block until the command has returned.
  1097.      */
  1098.  
  1099. VOID
  1100. SendAmigaDOSCommand(STRPTR Name)
  1101. {
  1102.     BPTR Stream;
  1103.  
  1104.         /* Open the console window or whatever the user
  1105.          * wants us to open here.
  1106.          */
  1107.  
  1108.     if(Stream = Open(WindowName,MODE_NEWFILE))
  1109.     {
  1110.         struct MsgPort *ReplyPort;
  1111.  
  1112.         if(ReplyPort = CreateMsgPort())
  1113.         {
  1114.             struct Message __aligned     Message;
  1115.             struct Process            *NewProcess;
  1116.  
  1117.             memset(&Message,0,sizeof(struct Message));
  1118.  
  1119.             Message . mn_Node . ln_Name    = Name;
  1120.             Message . mn_Length        = sizeof(struct Message);
  1121.             Message . mn_ReplyPort        = ReplyPort;
  1122.  
  1123.             if(GoodStream(Stream))
  1124.             {
  1125.                 struct FileHandle *Handle = (struct FileHandle *)BADDR(Stream);
  1126.  
  1127.                 NewProcess = CreateNewProcTags(
  1128.                     NP_Entry,    AmigaDOSBackgroundServer,
  1129.                     NP_Input,    Stream,
  1130.                     NP_Output,    NULL,
  1131.                     NP_ConsoleTask,    Handle -> fh_Type,
  1132.                     NP_StackSize,    8000,
  1133.                     NP_Cli,        TRUE,
  1134.                     NP_Name,    "term AmigaDOS background process",
  1135.                 TAG_DONE);
  1136.             }
  1137.             else
  1138.             {
  1139.                 NewProcess = CreateNewProcTags(
  1140.                     NP_Entry,    AmigaDOSBackgroundServer,
  1141.                     NP_Output,    Stream,
  1142.                     NP_ConsoleTask,    NULL,
  1143.                     NP_StackSize,    8000,
  1144.                     NP_Cli,        TRUE,
  1145.                     NP_Name,    "term AmigaDOS background process",
  1146.                 TAG_DONE);
  1147.             }
  1148.  
  1149.             if(NewProcess)
  1150.             {
  1151.                 ULONG SignalSet;
  1152.  
  1153.                 PutMsg(&NewProcess -> pr_MsgPort,&Message);
  1154.  
  1155.                     /* Go into loop and wait for the
  1156.                      * background process to return.
  1157.                      */
  1158.  
  1159.                 FOREVER
  1160.                 {
  1161.                     SignalSet = Wait(SIG_REXX | PORTMASK(ReplyPort));
  1162.  
  1163.                         /* Yet another rexx message. */
  1164.  
  1165.                     if(SignalSet & SIG_REXX)
  1166.                         HandleRexx();
  1167.  
  1168.                         /* The background server has
  1169.                          * finished.
  1170.                          */
  1171.  
  1172.                     if(SignalSet & PORTMASK(ReplyPort))
  1173.                     {
  1174.                         GetMsg(ReplyPort);
  1175.  
  1176.                         break;
  1177.                     }
  1178.                 }
  1179.             }
  1180.             else
  1181.                 Close(Stream);
  1182.  
  1183.             DeleteMsgPort(ReplyPort);
  1184.         }
  1185.         else
  1186.             Close(Stream);
  1187.     }
  1188.  
  1189.     BumpWindow(Window);
  1190. }
  1191.  
  1192.     /* RexxBackgroundServer():
  1193.      *
  1194.      *    The background process to handle the rexx
  1195.      *    massaging.
  1196.      */
  1197.  
  1198. #ifdef USE_AREXX
  1199.  
  1200. STATIC VOID __saveds
  1201. RexxBackgroundServer(VOID)
  1202. {
  1203.     struct MsgPort     *RexxPort;
  1204.     struct Message    *Message;
  1205.     BPTR         OldCOS,
  1206.              NewCOS = NULL;
  1207.  
  1208.         /* Look who we are. */
  1209.  
  1210.     RexxBackgroundProcess = (struct Process *)SysBase -> ThisTask;
  1211.  
  1212.         /* Wait for startup message. */
  1213.  
  1214.     WaitPort(&RexxBackgroundProcess -> pr_MsgPort);
  1215.  
  1216.         /* Pick the message up. */
  1217.  
  1218.     Message = GetMsg(&RexxBackgroundProcess -> pr_MsgPort);
  1219.  
  1220.         /* Create console output stream, will be closed automagically on exit. */
  1221.  
  1222.     if(!RexxBackgroundProcess -> pr_COS && RexxBackgroundProcess -> pr_ConsoleTask)
  1223.     {
  1224.         if(NewCOS = Open("*",MODE_NEWFILE))
  1225.         {
  1226.             OldCOS = RexxBackgroundProcess -> pr_COS;
  1227.  
  1228.             RexxBackgroundProcess -> pr_COS = NewCOS;
  1229.         }
  1230.     }
  1231.  
  1232.     if(RexxPort = FindPort(RXSDIR))
  1233.     {
  1234.         struct MsgPort __aligned     ReplyPort;
  1235.         struct RexxMsg            *RexxMsg;
  1236.  
  1237.         InitSinglePort(&ReplyPort);
  1238.  
  1239.         if(RexxMsg = CreateRexxMsg(&ReplyPort,"term",RexxPortName))
  1240.         {
  1241.             if(RexxMsg -> rm_Args[0] = CreateArgstring(Message -> mn_Node . ln_Name,strlen(Message -> mn_Node . ln_Name)))
  1242.             {
  1243.                 RexxMsg -> rm_Action = RXCOMM;
  1244.  
  1245.                 Forbid();
  1246.  
  1247.                 SetSignal(0,SIGF_SINGLE);
  1248.  
  1249.                 PutMsg(RexxPort,(struct Message *)RexxMsg);
  1250.  
  1251.                 WaitPort(&ReplyPort);
  1252.  
  1253.                 GetMsg(&ReplyPort);
  1254.  
  1255.                 Permit();
  1256.  
  1257.                     /* This doesn't look too
  1258.                      * good, does it?
  1259.                      */
  1260.  
  1261.                 if(RexxMsg -> rm_Result1)
  1262.                     Printf(LocaleString(MSG_TERMAUX_COMMAND_HAS_TERMINATED_TXT),Message -> mn_Node . ln_Name,RexxMsg -> rm_Result1,RexxMsg -> rm_Result2);
  1263.  
  1264.                 DeleteArgstring(RexxMsg -> rm_Args[0]);
  1265.             }
  1266.  
  1267.             DeleteRexxMsg(RexxMsg);
  1268.         }
  1269.     }
  1270.  
  1271.         /* We are done, lock and reply the message causing the
  1272.          * main process to return to the input loop.
  1273.          */
  1274.  
  1275.     Forbid();
  1276.  
  1277.     if(NewCOS)
  1278.     {
  1279.         RexxBackgroundProcess -> pr_COS = OldCOS;
  1280.  
  1281.         Close(NewCOS);
  1282.     }
  1283.  
  1284.     ReplyMsg(Message);
  1285.  
  1286.     RexxBackgroundProcess = NULL;
  1287. }
  1288.  
  1289.     /* SendARexxCommand(STRPTR Name):
  1290.      *
  1291.      *    Let the ARexx server execute a command (or a script
  1292.      *    file if necessary) and block until the command
  1293.      *    has returned.
  1294.      */
  1295.  
  1296. VOID
  1297. SendARexxCommand(STRPTR Name)
  1298. {
  1299.     struct MsgPort *ReplyPort;
  1300.  
  1301.         /* Create a reply port for the info message. */
  1302.  
  1303.     if(ReplyPort = CreateMsgPort())
  1304.     {
  1305.         struct Process            *NewProcess;
  1306.         struct Message __aligned     Message;
  1307.         BPTR                 Stream;
  1308.  
  1309.             /* Set up the command name carrier message. */
  1310.  
  1311.         memset(&Message,0,sizeof(struct Message));
  1312.  
  1313.         Message . mn_Node . ln_Name    = Name;
  1314.         Message . mn_Length        = sizeof(struct Message);
  1315.         Message . mn_ReplyPort        = ReplyPort;
  1316.  
  1317.             /* Open the output file. */
  1318.  
  1319.         if(WindowName[0])
  1320.             Stream = Open(WindowName,MODE_NEWFILE);
  1321.         else
  1322.             Stream = NULL;
  1323.  
  1324.             /* Create the background process which will
  1325.              * handle all the messy rexx message sending
  1326.              * for us.
  1327.              */
  1328.  
  1329.         if(Stream)
  1330.         {
  1331.             if(GoodStream(Stream))
  1332.             {
  1333.                 struct FileHandle *Handle = (struct FileHandle *)BADDR(Stream);
  1334.  
  1335.                 NewProcess = (struct Process *)CreateNewProcTags(
  1336.                     NP_Entry,    RexxBackgroundServer,
  1337.                     NP_Name,    "term ARexx background process",
  1338.                     NP_Input,    Stream,
  1339.                     NP_Output,    NULL,
  1340.                     NP_Cli,        TRUE,
  1341.                     NP_ConsoleTask,    Handle -> fh_Type,
  1342.                     NP_StackSize,    16384,
  1343.                 TAG_END);
  1344.             }
  1345.             else
  1346.             {
  1347.                 NewProcess = (struct Process *)CreateNewProcTags(
  1348.                     NP_Entry,    RexxBackgroundServer,
  1349.                     NP_Name,    "term ARexx background process",
  1350.                     NP_Output,    Stream,
  1351.                     NP_Cli,        TRUE,
  1352.                     NP_ConsoleTask,    NULL,
  1353.                     NP_StackSize,    16384,
  1354.                 TAG_END);
  1355.             }
  1356.         }
  1357.         else
  1358.         {
  1359.             NewProcess = (struct Process *)CreateNewProcTags(
  1360.                 NP_Entry,    RexxBackgroundServer,
  1361.                 NP_Name,    "term ARexx background process",
  1362.                 NP_Cli,        TRUE,
  1363.                 NP_ConsoleTask,    NULL,
  1364.                 NP_StackSize,    16384,
  1365.             TAG_END);
  1366.         }
  1367.  
  1368.             /* Did we succeed in creating the process? */
  1369.  
  1370.         if(NewProcess)
  1371.         {
  1372.             ULONG SignalSet;
  1373.  
  1374.                 /* Send the startup message. */
  1375.  
  1376.             PutMsg(&NewProcess -> pr_MsgPort,&Message);
  1377.  
  1378.                 /* Go into loop and wait for the
  1379.                  * background process to return.
  1380.                  */
  1381.  
  1382.             FOREVER
  1383.             {
  1384.                 SignalSet = Wait(SIG_REXX | PORTMASK(ReplyPort));
  1385.  
  1386.                     /* Yet another rexx message. */
  1387.  
  1388.                 if(SignalSet & SIG_REXX)
  1389.                     HandleRexx();
  1390.  
  1391.                     /* The background server has
  1392.                      * finished.
  1393.                      */
  1394.  
  1395.                 if(SignalSet & PORTMASK(ReplyPort))
  1396.                 {
  1397.                     GetMsg(ReplyPort);
  1398.  
  1399.                     break;
  1400.                 }
  1401.             }
  1402.         }
  1403.         else
  1404.         {
  1405.             if(Stream)
  1406.                 Close(Stream);
  1407.         }
  1408.  
  1409.             /* Delete the reply port. */
  1410.  
  1411.         DeleteMsgPort(ReplyPort);
  1412.     }
  1413.  
  1414.     BumpWindow(Window);
  1415. }
  1416.  
  1417. #endif    /* USE_AREXX */
  1418.  
  1419.     /* BlockWindow(struct Window *Window):
  1420.      *
  1421.      *    Block a window (show a wait mouse pointer, block
  1422.      *    windows, custom and system gadgets) by adding
  1423.      *    an invisible requester to it.
  1424.      */
  1425.  
  1426. VOID __regargs
  1427. BlockWindow(struct Window *Window)
  1428. {
  1429.     if(Window)
  1430.     {
  1431.         struct Requester    *InvisibleRequest = NULL;
  1432.         WORD             i;
  1433.  
  1434.         Forbid();
  1435.  
  1436.             /* Is this window already on the list? */
  1437.  
  1438.         for(i = 0 ; i < 10 ; i++)
  1439.         {
  1440.             if(RequesterList[i] . RWindow == Window)
  1441.             {
  1442.                 Permit();
  1443.  
  1444.                 return;
  1445.             }
  1446.         }
  1447.  
  1448.             /* Look for an empty slot. */
  1449.  
  1450.         for(i = 0 ; i < 10 ; i++)
  1451.         {
  1452.             if(!RequesterList[i] . RWindow)
  1453.             {
  1454.                 InvisibleRequest = &RequesterList[i];
  1455.  
  1456.                 InvisibleRequest -> RWindow = (struct Window *)~0;
  1457.  
  1458.                 break;
  1459.             }
  1460.         }
  1461.  
  1462.         Permit();
  1463.  
  1464.             /* Install the wait mouse pointer. */
  1465.  
  1466.         SetWait(Window);
  1467.  
  1468.             /* Install the requester if possible. */
  1469.  
  1470.         if(InvisibleRequest)
  1471.             Request(InvisibleRequest,Window);
  1472.     }
  1473. }
  1474.  
  1475.     /* ReleaseWindow(struct Window *Window):
  1476.      *
  1477.      *    Release a window blocked by `BlockWindow()'.
  1478.      */
  1479.  
  1480. VOID __regargs
  1481. ReleaseWindow(struct Window *Window)
  1482. {
  1483.     if(Window)
  1484.     {
  1485.         struct Requester    *InvisibleRequest = NULL;
  1486.         WORD             i;
  1487.  
  1488.             /* Search all slots for the requester to block this window. */
  1489.  
  1490.         for(i = 0 ; i < 10 ; i++)
  1491.         {
  1492.             if(RequesterList[i] . RWindow == Window)
  1493.             {
  1494.                 InvisibleRequest = &RequesterList[i];
  1495.  
  1496.                 break;
  1497.             }
  1498.         }
  1499.  
  1500.             /* Restore the mouse pointer. */
  1501.  
  1502.         ClrWait(Window);
  1503.  
  1504.             /* If disabled, restore the window. */
  1505.  
  1506.         if(InvisibleRequest)
  1507.         {
  1508.                 /* End the requester activity. */
  1509.  
  1510.             EndRequest(InvisibleRequest,Window);
  1511.  
  1512.                 /* Reset it to zeroes. */
  1513.  
  1514.             memset(InvisibleRequest,0,sizeof(struct Requester));
  1515.         }
  1516.     }
  1517. }
  1518.  
  1519.     /* BlockWindows():
  1520.      *
  1521.      *    Block the main window and the status window (i.e. disable
  1522.      *    the menu and attach a wait pointer).
  1523.      */
  1524.  
  1525. VOID
  1526. BlockWindows()
  1527. {
  1528.     if(!(BlockNestCount++))
  1529.     {
  1530.         BlockWindow(Window);
  1531.         BlockWindow(StatusWindow);
  1532.         BlockWindow(PacketWindow);
  1533.         BlockWindow(FastWindow);
  1534.         BlockWindow(ReviewWindow);
  1535.         BlockWindow(InfoWindow);
  1536.  
  1537.         WeAreBlocking = TRUE;
  1538.     }
  1539. }
  1540.  
  1541.     /* ReleaseWindows():
  1542.      *
  1543.      *    Reenable the menus and clear the wait pointer.
  1544.      */
  1545.  
  1546. VOID
  1547. ReleaseWindows()
  1548. {
  1549.     if(!(--BlockNestCount))
  1550.     {
  1551.         ReleaseWindow(Window);
  1552.         ReleaseWindow(StatusWindow);
  1553.         ReleaseWindow(PacketWindow);
  1554.         ReleaseWindow(FastWindow);
  1555.         ReleaseWindow(ReviewWindow);
  1556.         ReleaseWindow(InfoWindow);
  1557.  
  1558.         WeAreBlocking = FALSE;
  1559.     }
  1560. }
  1561.  
  1562.     /* LineRead(BPTR File,STRPTR Buffer,LONG MaxChars):
  1563.      *
  1564.      *    Read a few bytes from a file (à la gets).
  1565.      */
  1566.  
  1567. LONG
  1568. LineRead(BPTR File,STRPTR Buffer,LONG MaxChars)
  1569. {
  1570.     STATIC    UBYTE    Data[1024];
  1571.  
  1572.     STATIC    LONG    ReadIndex = 0,
  1573.             ReadLen = 0;
  1574.  
  1575.         LONG    BytesRead = 0,
  1576.             i;
  1577.  
  1578.     if(File)
  1579.     {
  1580.         for(i = 0 ; i < MaxChars ; i++)
  1581.         {
  1582.             if(ReadIndex >= ReadLen)
  1583.             {
  1584.                 ReadLen = Read(File,Data,1024);
  1585.  
  1586.                 ReadIndex = 0;
  1587.  
  1588.                 if(ReadLen <= 0)
  1589.                 {
  1590.                     Buffer[i] = 0;
  1591.  
  1592.                     return(BytesRead);
  1593.                 }
  1594.             }
  1595.  
  1596.             BytesRead++;
  1597.  
  1598.             if((Buffer[i] = Data[ReadIndex++]) == '\n')
  1599.             {
  1600.                 Buffer[i + 1] = 0;
  1601.  
  1602.                 return(BytesRead);
  1603.             }
  1604.         }
  1605.  
  1606.         return(BytesRead);
  1607.     }
  1608.     else
  1609.         ReadIndex = ReadLen = 0;
  1610. }
  1611.  
  1612.     /* GetBaudRate(STRPTR Buffer):
  1613.      *
  1614.      *    Calculate the baud rate contained in a connect string.
  1615.      */
  1616.  
  1617. LONG
  1618. GetBaudRate(STRPTR Buffer)
  1619. {
  1620.     LONG Rate,i,j;
  1621.  
  1622.     for(i = j = 0 ; i < strlen(Buffer) ; i++)
  1623.     {
  1624.         if(Buffer[i] == ' ')
  1625.             continue;
  1626.         else
  1627.         {
  1628.             if(Buffer[i] >= '0' && Buffer[i] <= '9')
  1629.                 SharedBuffer[j++] = Buffer[i];
  1630.             else
  1631.                 break;
  1632.         }
  1633.     }
  1634.  
  1635.     SharedBuffer[j] = 0;
  1636.  
  1637.     if(StrToLong(SharedBuffer,&Rate) > 0)
  1638.     {
  1639.         if(Rate > 0)
  1640.             return(Rate);
  1641.     }
  1642.  
  1643.     return(0);
  1644. }
  1645.  
  1646.     /* LookForIt(struct MenuItem *Item,ULONG ID):
  1647.      *
  1648.      *    Auxilary routine for FindThisItem(), scans
  1649.      *    menu item and sub item lists.
  1650.      */
  1651.  
  1652. STATIC struct MenuItem * __inline
  1653. LookForIt(struct MenuItem *Item,ULONG ID)
  1654. {
  1655.     while(Item)
  1656.     {
  1657.         if((ULONG)GTMENUITEM_USERDATA(Item) == ID)
  1658.             return(Item);
  1659.         else
  1660.         {
  1661.             if(Item -> SubItem)
  1662.             {
  1663.                 register struct MenuItem *TheItem;
  1664.  
  1665.                 if(TheItem = LookForIt(Item -> SubItem,ID))
  1666.                     return(TheItem);
  1667.             }
  1668.  
  1669.             Item = Item -> NextItem;
  1670.         }
  1671.     }
  1672.  
  1673.     return(NULL);
  1674. }
  1675.  
  1676.     /* FindThisItem(struct Menu *FirstMenu,ULONG MenuID):
  1677.      *
  1678.      *    Scan a menu for a menuitem associated with a
  1679.      *    menu ID.
  1680.      */
  1681.  
  1682. struct MenuItem *
  1683. FindThisItem(struct Menu *FirstMenu,ULONG MenuID)
  1684. {
  1685.     struct MenuItem *Item;
  1686.  
  1687.     while(FirstMenu)
  1688.     {
  1689.         if(Item = LookForIt(FirstMenu -> FirstItem,MenuID))
  1690.             return(Item);
  1691.         else
  1692.             FirstMenu = FirstMenu -> NextMenu;
  1693.     }
  1694.  
  1695.     return(NULL);
  1696. }
  1697.  
  1698.     /* GetItem(ULONG MenuID):
  1699.      *
  1700.      *    Get the checkmark state of a menu item.
  1701.      */
  1702.  
  1703. BYTE __regargs
  1704. GetItem(ULONG MenuID)
  1705. {
  1706.     if(Menu)
  1707.     {
  1708.         struct MenuItem *Item;
  1709.  
  1710.         if(Item = FindThisItem(Menu,MenuID))
  1711.         {
  1712.             if(Item -> Flags & CHECKED)
  1713.                 return(TRUE);
  1714.         }
  1715.     }
  1716.  
  1717.     return(FALSE);
  1718. }
  1719.  
  1720.     /* SetItem(ULONG MenuID,BYTE Mode):
  1721.      *
  1722.      *    Clear or set the checkmark or state of a menu item.
  1723.      */
  1724.  
  1725. VOID
  1726. SetItem(ULONG MenuID,BYTE Mode)
  1727. {
  1728.         /* Is the global pull-down menu available? */
  1729.  
  1730.     if(Menu)
  1731.     {
  1732.         struct MenuItem *Item;
  1733.  
  1734.             /* Try to find the menu item and change
  1735.              * the state of the checkmark.
  1736.              */
  1737.  
  1738.         if(Item = FindThisItem(Menu,MenuID))
  1739.         {
  1740.                 /* Remove the menu from the windows. */
  1741.  
  1742.             if(Window)
  1743.                 ClearMenuStrip(Window);
  1744.  
  1745.             if(StatusWindow)
  1746.                 ClearMenuStrip(StatusWindow);
  1747.  
  1748.             if(FastWindow)
  1749.                 ClearMenuStrip(FastWindow);
  1750.  
  1751.             if(InfoWindow)
  1752.                 ClearMenuStrip(InfoWindow);
  1753.  
  1754.             switch(Mode)
  1755.             {
  1756.                 case SETITEM_SETCHECK:
  1757.  
  1758.                     Item -> Flags |= CHECKED;
  1759.                     break;
  1760.  
  1761.                 case SETITEM_CLRCHECK:
  1762.  
  1763.                     Item -> Flags &= ~CHECKED;
  1764.                     break;
  1765.  
  1766.                 case SETITEM_ON:
  1767.  
  1768.                     Item -> Flags |= ITEMENABLED;
  1769.                     break;
  1770.  
  1771.                 case SETITEM_OFF:
  1772.  
  1773.                     Item -> Flags &= ~ITEMENABLED;
  1774.                     break;
  1775.             }
  1776.  
  1777.  
  1778.                 /* Reattach the menu to the windows. */
  1779.  
  1780.             if(Window)
  1781.                 ResetMenuStrip(Window,Menu);
  1782.  
  1783.             if(StatusWindow)
  1784.                 ResetMenuStrip(StatusWindow,Menu);
  1785.  
  1786.             if(FastWindow)
  1787.                 ResetMenuStrip(FastWindow,Menu);
  1788.  
  1789.             if(InfoWindow)
  1790.                 ResetMenuStrip(InfoWindow,Menu);
  1791.         }
  1792.     }
  1793. }
  1794.  
  1795.     /* GetFileSize(STRPTR Name):
  1796.      *
  1797.      *    Simple routine to return the size of a file in
  1798.      *    bytes.
  1799.      */
  1800.  
  1801. LONG
  1802. GetFileSize(STRPTR Name)
  1803. {
  1804.     struct FileInfoBlock    *FileInfo;
  1805.     LONG             FileSize = 0;
  1806.  
  1807.     if(FileInfo = (struct FileInfoBlock *)AllocDosObject(DOS_FIB,TAG_DONE))
  1808.     {
  1809.         BPTR FileLock;
  1810.  
  1811.         if(FileLock = Lock(Name,ACCESS_READ))
  1812.         {
  1813.             if(Examine(FileLock,FileInfo))
  1814.             {
  1815.                 if(FileInfo -> fib_DirEntryType < 0)
  1816.                     FileSize = FileInfo -> fib_Size;
  1817.             }
  1818.  
  1819.             UnLock(FileLock);
  1820.         }
  1821.  
  1822.         FreeDosObject(DOS_FIB,FileInfo);
  1823.     }
  1824.  
  1825.     return(FileSize);
  1826. }
  1827.  
  1828.     /* GetFile(STRPTR Title,STRPTR Directory,STRPTR Name,STRPTR Buffer,STRPTR Pattern,BYTE SaveFlag,BYTE MultiSelect):
  1829.      *
  1830.      *    Call the asl.library file requester to select a single or
  1831.      *    a couple of files.
  1832.      */
  1833.  
  1834. struct FileRequester *
  1835. GetFile(STRPTR Title,STRPTR Directory,STRPTR Name,STRPTR Buffer,STRPTR Pattern,BYTE SaveFlag,BYTE MultiSelect,BYTE DirsOnly,STRPTR OKText)
  1836. {
  1837.     struct FileRequester    *AslFileRequest;
  1838.     BYTE             Result        = FALSE,
  1839.                  DefaultPattern    = FALSE;
  1840.     LONG             Flags,ExtFlags = 0;
  1841.     WORD             i,j;
  1842.  
  1843.     STATIC UBYTE         DirBuffer[MAX_FILENAME_LENGTH],
  1844.                  PatternBuffer[256],
  1845.                  OtherTitle[60];
  1846.  
  1847.         /* We use this tag array to remember the size and
  1848.          * position of the asl requester window.
  1849.          */
  1850.  
  1851.     STATIC struct {
  1852.         ULONG Tag1,    LeftEdge;
  1853.         ULONG Tag2,    TopEdge;
  1854.         ULONG Tag3,    Width;
  1855.         ULONG Tag4,    Height;
  1856.         ULONG Tag5;
  1857.     } Dims = {
  1858.         ASL_LeftEdge,    -1,
  1859.         ASL_TopEdge,    -1,
  1860.         ASL_Width,    -1,
  1861.         ASL_Height,    -1,
  1862.  
  1863.         TAG_DONE
  1864.     };
  1865.  
  1866.     for(i = j = 0 ; i < strlen(Title) ; i++)
  1867.     {
  1868.         if(Title[i] != '_')
  1869.             OtherTitle[j++] = Title[i];
  1870.     }
  1871.  
  1872.     OtherTitle[j] = 0;
  1873.  
  1874.     Title = OtherTitle;
  1875.  
  1876.     if(DirsOnly)
  1877.     {
  1878.         ExtFlags |= FIL1F_NOFILES;
  1879.  
  1880.         if(Pattern)
  1881.             ExtFlags |= FIL1F_MATCHDIRS;
  1882.     }
  1883.  
  1884.         /* Empty directory string? Revert to the last directory
  1885.          * name.
  1886.          */
  1887.  
  1888.     if(!Directory[0])
  1889.     {
  1890.         if(!DirBuffer[0])
  1891.         {
  1892.             if(!GetCurrentDirName(DirBuffer,MAX_FILENAME_LENGTH))
  1893.                 DirBuffer[0] = 0;
  1894.         }
  1895.  
  1896.         Directory = DirBuffer;
  1897.     }
  1898.  
  1899.         /* If a wildcard pattern is required, add a gadget
  1900.          * to display it.
  1901.          */
  1902.  
  1903.     if(Pattern)
  1904.     {
  1905.         Flags = FILF_PATGAD;
  1906.  
  1907.         if(!Pattern[0])
  1908.         {
  1909.             DefaultPattern = TRUE;
  1910.  
  1911.             if(PatternBuffer[0])
  1912.                 Pattern = PatternBuffer;
  1913.             else
  1914.                 Pattern = "#?";
  1915.         }
  1916.         else
  1917.         {
  1918.             if(!Stricmp(Pattern,"#?") || !Stricmp(Pattern,PatternBuffer))
  1919.             {
  1920.                 DefaultPattern = TRUE;
  1921.  
  1922.                 Pattern = PatternBuffer;
  1923.             }
  1924.         }
  1925.     }
  1926.     else
  1927.     {
  1928.         Flags = 0;
  1929.  
  1930.         Pattern = "#?";
  1931.     }
  1932.  
  1933.         /* Set the save flag if we are about to save something. */
  1934.  
  1935.     if(SaveFlag)
  1936.         Flags |= FILF_SAVE;
  1937.  
  1938.         /* Set the multiselect bit if multiple files are
  1939.          * to be selected (e.g. for batch file upload).
  1940.          */
  1941.  
  1942.     if(MultiSelect)
  1943.         Flags |= FILF_MULTISELECT;
  1944.  
  1945.         /* Provide a standard `Ok' text if none
  1946.          * specified.
  1947.          */
  1948.  
  1949.     if(!OKText)
  1950.         OKText = (SaveFlag ? LocaleString(MSG_GLOBAL_SAVE_TXT) : LocaleString(MSG_GLOBAL_OPEN_TXT));
  1951.  
  1952.         /* Allocate the asl.library directory requester
  1953.          * and display it.
  1954.          */
  1955.  
  1956.     if(AslFileRequest = (struct FileRequester *)AllocAslRequestTags(ASL_FileRequest,
  1957.         ASL_Window,    Window,
  1958.         ASL_File,    Name,
  1959.         ASL_Dir,    Directory,
  1960.         Title ? ASL_Hail : TAG_IGNORE,    Title,
  1961.         ASL_FuncFlags,    Flags | FILF_NEWIDCMP,
  1962.         ASL_Pattern,    Pattern,
  1963.         ASL_OKText,    OKText,
  1964.         ASL_ExtFlags1,    ExtFlags,
  1965.         ASLFR_TextAttr,    &UserFont,
  1966.         (Dims . LeftEdge == -1) ? TAG_DONE : TAG_MORE,&Dims))
  1967.     {
  1968.         if(AslRequestTags(AslFileRequest,TAG_DONE))
  1969.         {
  1970.             Dims . LeftEdge    = AslFileRequest -> rf_LeftEdge;
  1971.             Dims . TopEdge    = AslFileRequest -> rf_TopEdge;
  1972.             Dims . Width    = AslFileRequest -> rf_Width;
  1973.             Dims . Height    = AslFileRequest -> rf_Height;
  1974.  
  1975.             if(!DirsOnly)
  1976.             {
  1977.                     /* Do we have a valid file name? */
  1978.  
  1979.                 if(AslFileRequest -> rf_File[0])
  1980.                 {
  1981.                         /* Build a legal path/file string. */
  1982.  
  1983.                     strcpy(Buffer,AslFileRequest -> rf_Dir);
  1984.  
  1985.                     AddPart((STRPTR)Buffer,(STRPTR)AslFileRequest -> rf_File,MAX_FILENAME_LENGTH);
  1986.  
  1987.                     Result = TRUE;
  1988.  
  1989.                     strcpy(DirBuffer,AslFileRequest -> rf_Dir);
  1990.                 }
  1991.             }
  1992.             else
  1993.             {
  1994.                 if(AslFileRequest -> rf_Dir[0])
  1995.                 {
  1996.                     strcpy(Buffer,AslFileRequest -> rf_Dir);
  1997.  
  1998.                     Result = TRUE;
  1999.  
  2000.                     strcpy(DirBuffer,AslFileRequest -> rf_Dir);
  2001.                 }
  2002.             }
  2003.         }
  2004.     }
  2005.  
  2006.         /* We didn't get a file, no need to keep the
  2007.          * file requester.
  2008.          */
  2009.  
  2010.     if(!Result && AslFileRequest)
  2011.     {
  2012.         FreeAslRequest(AslFileRequest);
  2013.  
  2014.         return(NULL);
  2015.     }
  2016.     else
  2017.     {
  2018.         if(SaveFlag)
  2019.         {
  2020.             if(GetFileSize(Buffer))
  2021.             {
  2022.                 if(!MyEasyRequest(Window,LocaleString(MSG_GLOBAL_FILE_ALREADY_EXISTS_OVERWRITE_TXT),LocaleString(MSG_GLOBAL_REPLACE_CANCEL_TXT),FilePart(Buffer)))
  2023.                 {
  2024.                     FreeAslRequest(AslFileRequest);
  2025.  
  2026.                     return(NULL);
  2027.                 }
  2028.             }
  2029.         }
  2030.  
  2031.         if(DefaultPattern)
  2032.             strcpy(PatternBuffer,AslFileRequest -> rf_Pat);
  2033.  
  2034.         return(AslFileRequest);
  2035.     }
  2036. }
  2037.  
  2038.     /* MyEasyRequest(struct Window *Window,STRPTR Text,STRPTR Gadgets,...):
  2039.      *
  2040.      *    Really quite simple varargs version of Intuition's
  2041.      *    EasyRequest requester.
  2042.      */
  2043.  
  2044. WORD __stdargs
  2045. MyEasyRequest(struct Window *Window,STRPTR Text,STRPTR Gadgets,...)
  2046. {
  2047.     struct EasyStruct    Easy;
  2048.     WORD            Result;
  2049.     ULONG            IDCMP = NULL;
  2050.     va_list             VarArgs;
  2051.  
  2052.         /* Standard data. */
  2053.  
  2054.     Easy . es_StructSize    = sizeof(struct EasyStruct);
  2055.     Easy . es_Flags        = NULL;
  2056.     Easy . es_Title        = (STRPTR)LocaleString(MSG_TERMAUX_TERM_REQUEST_TXT);
  2057.     Easy . es_TextFormat    = (STRPTR)Text;
  2058.     Easy . es_GadgetFormat    = (STRPTR)Gadgets;
  2059.  
  2060.         /* Use the argument array to build the
  2061.          * requester and display it.
  2062.          */
  2063.  
  2064.     va_start(VarArgs,Gadgets);
  2065.     Result = EasyRequestArgs(Window,&Easy,&IDCMP,VarArgs);
  2066.     va_end(VarArgs);
  2067.  
  2068.     return(Result);
  2069. }
  2070.  
  2071.     /* SelectTime():
  2072.      *
  2073.      *    Searches for the correct unit/pay conversion values.
  2074.      */
  2075.  
  2076. VOID
  2077. SelectTime(struct PhoneEntry *SomeEntry)
  2078. {
  2079.     struct TimeDateNode        *TimeDateNode;
  2080.     struct DateStamp __aligned     Date;
  2081.     struct ClockData         ClockData;
  2082.     UBYTE                 Time;
  2083.     BYTE                 FoundOne = FALSE;
  2084.     LONG                 i,Last;
  2085.  
  2086.         /* Obtain current time and date. */
  2087.  
  2088.     DateStamp(&Date);
  2089.  
  2090.         /* Convert into a more suitable form (note: seconds are
  2091.          * required as an input value, ice is extra).
  2092.          */
  2093.  
  2094.     Amiga2Date(Date . ds_Days * 86400 + Date . ds_Minute * 60 + Date . ds_Tick / TICKS_PER_SECOND,&ClockData);
  2095.  
  2096.         /* Apparently, in the US of A the week starts with Sunday, we'll
  2097.          * wrap the week around to let it start with Monday.
  2098.          */
  2099.  
  2100.     if(ClockData . wday)
  2101.         ClockData . wday--;
  2102.     else
  2103.         ClockData . wday = 6;
  2104.  
  2105.         /* Change the month, too... */
  2106.  
  2107.     ClockData . month--;
  2108.  
  2109.         /* First step: search for current day. */
  2110.  
  2111.     TimeDateNode = (struct TimeDateNode *)SomeEntry -> TimeDateList . mlh_Head;
  2112.  
  2113.         /* Skip first entry. */
  2114.  
  2115.     TimeDateNode = (struct TimeDateNode *)TimeDateNode -> VanillaNode . ln_Succ;
  2116.  
  2117.         /* First step: search for date settings. */
  2118.  
  2119.     while(TimeDateNode -> VanillaNode . ln_Succ)
  2120.     {
  2121.             /* Does it match a specific date? */
  2122.  
  2123.         if(TimeDateNode -> Header . Month == ClockData . month && TimeDateNode -> Header . Day == ClockData . mday)
  2124.         {
  2125.             FoundOne = TRUE;
  2126.  
  2127.             break;
  2128.         }
  2129.  
  2130.         TimeDateNode = (struct TimeDateNode *)TimeDateNode -> VanillaNode . ln_Succ;
  2131.     }
  2132.  
  2133.         /* Second step: search for week day settings. */
  2134.  
  2135.     if(!FoundOne)
  2136.     {
  2137.         TimeDateNode = (struct TimeDateNode *)SomeEntry -> TimeDateList . mlh_Head;
  2138.  
  2139.             /* Skip first entry. */
  2140.  
  2141.         TimeDateNode = (struct TimeDateNode *)TimeDateNode -> VanillaNode . ln_Succ;
  2142.  
  2143.         while(TimeDateNode -> VanillaNode . ln_Succ)
  2144.         {
  2145.                 /* Does it match a specific day? */
  2146.  
  2147.             if(TimeDateNode -> Header . Month == -1 && (TimeDateNode -> Header . Day & (1 << ClockData . wday)))
  2148.             {
  2149.                 FoundOne = TRUE;
  2150.  
  2151.                 break;
  2152.             }
  2153.  
  2154.             TimeDateNode = (struct TimeDateNode *)TimeDateNode -> VanillaNode . ln_Succ;
  2155.         }
  2156.     }
  2157.  
  2158.         /* Third step: use default settings. */
  2159.  
  2160.     if(!FoundOne)
  2161.         TimeDateNode = (struct TimeDateNode *)SomeEntry -> TimeDateList . mlh_Head;
  2162.  
  2163.         /* Convert current time to packed format. */
  2164.  
  2165.     Time = DT_GET_TIME(ClockData . hour,ClockData . min);
  2166.  
  2167.         /* Start with a blank. */
  2168.  
  2169.     Last = -1;
  2170.  
  2171.         /* Look for fitting time. */
  2172.  
  2173.     for(i = 0 ; i < TimeDateNode -> Table[0] . Count ; i++)
  2174.     {
  2175.             /* The time we are looking for must be >= the
  2176.              * current time.
  2177.              */
  2178.  
  2179.         if(TimeDateNode -> Table[i] . Time > Time)
  2180.         {
  2181.             if(i == 0)
  2182.                 break;
  2183.             else
  2184.             {
  2185.                 Last = i - 1;
  2186.                 break;
  2187.             }
  2188.         }
  2189.         else
  2190.             continue;
  2191.     }
  2192.  
  2193.         /* If none is found, take the last one in the list.
  2194.          * Note that this requires the list to be sorted in
  2195.          * ascending order.
  2196.          */
  2197.  
  2198.     if(Last == -1)
  2199.         Last = TimeDateNode -> Table[0] . Count - 1;
  2200.  
  2201.         /* Fill in the remaining data. */
  2202.  
  2203.     PayPerUnit[DT_FIRST_UNIT]    = TimeDateNode -> Table[Last] . PayPerUnit[DT_FIRST_UNIT];
  2204.     PayPerUnit[DT_NEXT_UNIT]    = TimeDateNode -> Table[Last] . PayPerUnit[DT_NEXT_UNIT];
  2205.     SecPerUnit[DT_FIRST_UNIT]    = TimeDateNode -> Table[Last] . SecPerUnit[DT_FIRST_UNIT];
  2206.     SecPerUnit[DT_NEXT_UNIT]    = TimeDateNode -> Table[Last] . SecPerUnit[DT_NEXT_UNIT];
  2207. }
  2208.  
  2209.     /* CloseWindowSafely(struct Window *Window):
  2210.      *
  2211.      *    Close a window freeing all messages pending at
  2212.      *    its user port (taken from example source code
  2213.      *    published once upon a time in Amiga Mail).
  2214.      */
  2215.  
  2216. VOID
  2217. CloseWindowSafely(struct Window *Window)
  2218. {
  2219.     struct IntuiMessage    *IntuiMessage;
  2220.     struct Node        *Successor;
  2221.  
  2222.     Forbid();
  2223.  
  2224.     IntuiMessage = (struct IntuiMessage *)Window -> UserPort -> mp_MsgList . lh_Head;
  2225.  
  2226.     while(Successor = IntuiMessage -> ExecMessage . mn_Node . ln_Succ)
  2227.     {
  2228.         if(IntuiMessage -> IDCMPWindow == Window)
  2229.         {
  2230.             Remove(IntuiMessage);
  2231.  
  2232.             ReplyMsg((struct Message *)IntuiMessage);
  2233.         }
  2234.  
  2235.         IntuiMessage = (struct IntuiMessage *)Successor;
  2236.     }
  2237.  
  2238.     Window -> UserPort = NULL;
  2239.  
  2240.     ModifyIDCMP(Window,NULL);
  2241.  
  2242.     Permit();
  2243.  
  2244.     CloseWindow(Window);
  2245. }
  2246.  
  2247.     /* WaitTime(LONG Secs,LONG Micros):
  2248.      *
  2249.      *    Wait a given period of time.
  2250.      */
  2251.  
  2252. VOID
  2253. WaitTime(LONG Secs,LONG Micros)
  2254. {
  2255.     TimeRequest -> tr_node . io_Command    = TR_ADDREQUEST;
  2256.     TimeRequest -> tr_time . tv_secs    = Secs;
  2257.     TimeRequest -> tr_time . tv_micro    = Micros;
  2258.  
  2259.     DoIO(TimeRequest);
  2260. }
  2261.  
  2262.     /* GetEnvDOS(STRPTR Name,STRPTR Buffer):
  2263.      *
  2264.      *    Get the contents of a vanilla AmigaDOS environment
  2265.      *    variable.
  2266.      */
  2267.  
  2268. STRPTR
  2269. GetEnvDOS(STRPTR Name,STRPTR Buffer)
  2270. {
  2271.     LONG    Size;
  2272.     BPTR    File,SomeLock;
  2273.  
  2274.     Buffer[0] = 0;
  2275.  
  2276.         /* Is ENV: present? */
  2277.  
  2278.     if(SomeLock = Lock("Env:",ACCESS_READ))
  2279.     {
  2280.         UBYTE SomeBuffer[MAX_FILENAME_LENGTH];
  2281.  
  2282.         UnLock(SomeLock);
  2283.  
  2284.         strcpy(SomeBuffer,"Env:");
  2285.         strcat(SomeBuffer,Name);
  2286.  
  2287.             /* Open the file. */
  2288.  
  2289.         if(File = Open(SomeBuffer,MODE_OLDFILE))
  2290.         {
  2291.                 /* Read the contents. */
  2292.  
  2293.             Size = Read(File,Buffer,256);
  2294.  
  2295.             Close(File);
  2296.  
  2297.             if(Size > 0)
  2298.             {
  2299.                 Buffer[Size] = 0;
  2300.  
  2301.                 return(Buffer);
  2302.             }
  2303.         }
  2304.     }
  2305.  
  2306.     return(NULL);
  2307. }
  2308.  
  2309.     /* SetEnvDOS(STRPTR Name,STRPTR Value):
  2310.      *
  2311.      *    Set the contents of a vanilla AmigaDOS environment
  2312.      *    variable.
  2313.      */
  2314.  
  2315. BYTE
  2316. SetEnvDOS(STRPTR Name,STRPTR Value)
  2317. {
  2318.     UBYTE    Buffer[MAX_FILENAME_LENGTH],*Destination;
  2319.     LONG    Length;
  2320.     BPTR    File,FileLock;
  2321.     BYTE    Success = FALSE;
  2322.     WORD    i;
  2323.  
  2324.     for(i = 0 ; i < 2 ; i++)
  2325.     {
  2326.         if(i)
  2327.             Destination = "EnvArc:";
  2328.         else
  2329.             Destination = "Env:";
  2330.  
  2331.             /* Is ENV:/ENVARC: present? */
  2332.  
  2333.         if(FileLock = Lock(Destination,ACCESS_READ))
  2334.         {
  2335.             UnLock(FileLock);
  2336.  
  2337.             strcpy(Buffer,Destination);
  2338.             strcat(Buffer,Name);
  2339.  
  2340.                 /* There already is a variable of that
  2341.                  * name in the environment storage
  2342.                  * directory.
  2343.                  */
  2344.  
  2345.             if(FileLock = Lock(Buffer,ACCESS_WRITE))
  2346.             {
  2347.                 UnLock(FileLock);
  2348.  
  2349.                     /* Delete the variable. */
  2350.  
  2351.                 if(!DeleteFile(Buffer))
  2352.                 {
  2353.                     Success = FALSE;
  2354.  
  2355.                     continue;
  2356.                 }
  2357.             }
  2358.  
  2359.                 /* Set the new variable. */
  2360.  
  2361.             if(Length = strlen(Value))
  2362.             {
  2363.                 if(File = Open(Buffer,MODE_NEWFILE))
  2364.                 {
  2365.                     if(Write(File,Value,Length) != Length)
  2366.                     {
  2367.                         Close(File);
  2368.  
  2369.                         DeleteFile(Buffer);
  2370.  
  2371.                         Success = FALSE;
  2372.                     }
  2373.                     else
  2374.                     {
  2375.                         Close(File);
  2376.  
  2377.                         SetProtection(Buffer,FIBF_EXECUTE);
  2378.  
  2379.                         Success = TRUE;
  2380.                     }
  2381.                 }
  2382.                 else
  2383.                     Success = FALSE;
  2384.             }
  2385.             else
  2386.                 Success = TRUE;
  2387.         }
  2388.         else
  2389.             Success = FALSE;
  2390.     }
  2391.  
  2392.     return(Success);
  2393. }
  2394.  
  2395.     /* BumpWindow(struct Window *SomeWindow):
  2396.      *
  2397.      *    Bring a window to the front (and shift the screen
  2398.      *    back to its initial position).
  2399.      */
  2400.  
  2401. VOID
  2402. BumpWindow(struct Window *SomeWindow)
  2403. {
  2404.     if(SomeWindow -> WScreen -> LeftEdge > 0)
  2405.     {
  2406.         if(SomeWindow -> WScreen -> TopEdge > 0)
  2407.             MoveScreen(SomeWindow -> WScreen,-SomeWindow -> WScreen -> LeftEdge,-SomeWindow -> WScreen -> TopEdge);
  2408.         else
  2409.             MoveScreen(SomeWindow -> WScreen,-SomeWindow -> WScreen -> LeftEdge,0);
  2410.     }
  2411.     else
  2412.     {
  2413.         if(SomeWindow -> WScreen -> TopEdge > 0)
  2414.             MoveScreen(SomeWindow -> WScreen,0,-SomeWindow -> WScreen -> TopEdge);
  2415.     }
  2416.  
  2417.     ScreenToFront(SomeWindow -> WScreen);
  2418.  
  2419.     ActivateWindow(SomeWindow);
  2420. }
  2421.  
  2422.     /* PushWindow(struct Window *Window):
  2423.      *
  2424.      *    Push/PopWindow implement a single lifo window stack
  2425.      *    which always updates the window to activate when
  2426.      *    LSHIFT+RSHIFT+RETURN is pressed. This routine will
  2427.      *    push a window on the stack.
  2428.      */
  2429.  
  2430. VOID
  2431. PushWindow(struct Window *Window)
  2432. {
  2433.     if(WindowStackPtr < 5)
  2434.     {
  2435.         WindowStack[WindowStackPtr++] = Window;
  2436.  
  2437.         TopWindow = Window;
  2438.     }
  2439. }
  2440.  
  2441.     /* PopWindow():
  2442.      *
  2443.      *    Remove topmost window from window stack.
  2444.      */
  2445.  
  2446. VOID
  2447. PopWindow()
  2448. {
  2449.     if(WindowStackPtr > 0)
  2450.     {
  2451.         WindowStackPtr--;
  2452.  
  2453.         if(WindowStackPtr)
  2454.             TopWindow = WindowStack[WindowStackPtr - 1];
  2455.         else
  2456.             TopWindow = Window;
  2457.     }
  2458. }
  2459.  
  2460.     /* LoadMacros(STRPTR Name,struct MacroKeys *Keys):
  2461.      *
  2462.      *    Load the keyboard macros from a file.
  2463.      */
  2464.  
  2465. BYTE
  2466. LoadMacros(STRPTR Name,struct MacroKeys *Keys)
  2467. {
  2468.     struct IFFHandle    *Handle;
  2469.     BYTE             Success = FALSE;
  2470.     struct StoredProperty    *Prop;
  2471.     struct TermInfo        *TermInfo;
  2472.  
  2473.     if(Handle = AllocIFF())
  2474.     {
  2475.         if(Handle -> iff_Stream = Open(Name,MODE_OLDFILE))
  2476.         {
  2477.             InitIFFasDOS(Handle);
  2478.  
  2479.             if(!OpenIFF(Handle,IFFF_READ))
  2480.             {
  2481.                 /* Collect version number ID if
  2482.                  * available.
  2483.                  */
  2484.  
  2485.                 if(!PropChunks(Handle,VersionProps,1))
  2486.                 {
  2487.                     /* The following line tells iffparse to stop at the
  2488.                      * very beginning of a `Type' chunk contained in a
  2489.                      * `TERM' FORM chunk.
  2490.                      */
  2491.  
  2492.                     if(!StopChunk(Handle,ID_TERM,ID_KEYS))
  2493.                     {
  2494.                         /* Parse the file... */
  2495.  
  2496.                         if(!ParseIFF(Handle,IFFPARSE_SCAN))
  2497.                         {
  2498.                             /* Did we get a version ID? */
  2499.  
  2500.                             if(Prop = FindProp(Handle,ID_TERM,ID_VERS))
  2501.                             {
  2502.                                 TermInfo = (struct TermInfo *)Prop -> sp_Data;
  2503.  
  2504.                                 /* Is it the file format we are able
  2505.                                  * to read?
  2506.                                  */
  2507.  
  2508.                                 if((TermInfo -> Version > TermVersion) || (TermInfo -> Version == TermVersion && TermInfo -> Revision > TermRevision) || (TermInfo -> Version == 1 && TermInfo -> Revision < 6))
  2509.                                 {
  2510.                                         /* Probably an older revision. */
  2511.  
  2512.                                     if(TermInfo -> Version == 1 && TermInfo -> Revision < 6)
  2513.                                     {
  2514.                                         memset(Keys,0,sizeof(struct MacroKeys));
  2515.  
  2516.                                         if(ReadChunkBytes(Handle,Keys,10 * 256) == 10 * 256)
  2517.                                             Success = TRUE;
  2518.                                     }
  2519.                                 }
  2520.                                 else
  2521.                                 {
  2522.                                     /* The file read pointer is positioned
  2523.                                      * just in front of the first data
  2524.                                      * to be read, so let's don't disappoint
  2525.                                      * iffparse and read it.
  2526.                                      */
  2527.  
  2528.                                     if(ReadChunkBytes(Handle,Keys,sizeof(struct MacroKeys)) == sizeof(struct MacroKeys))
  2529.                                         Success = TRUE;
  2530.                                 }
  2531.                             }
  2532.                             else
  2533.                             {
  2534.                                     /* File was created by WriteIFFData previous
  2535.                                      * to revision 1.4.
  2536.                                      */
  2537.  
  2538.                                 memset(Keys,0,sizeof(struct MacroKeys));
  2539.  
  2540.                                 if(ReadChunkBytes(Handle,Keys,10 * 256) == 10 * 256)
  2541.                                     Success = TRUE;
  2542.                             }
  2543.                         }
  2544.                     }
  2545.                 }
  2546.  
  2547.                 CloseIFF(Handle);
  2548.             }
  2549.  
  2550.             Close(Handle -> iff_Stream);
  2551.         }
  2552.  
  2553.         FreeIFF(Handle);
  2554.     }
  2555.  
  2556.     return(Success);
  2557. }
  2558.  
  2559.     /* WriteIFFData(STRPTR Name,APTR Data,LONG Size,ULONG Type):
  2560.      *
  2561.      *    Write data to an IFF file (via iffparse.library).
  2562.      */
  2563.  
  2564. BYTE
  2565. WriteIFFData(STRPTR Name,APTR Data,LONG Size,ULONG Type)
  2566. {
  2567.     struct IFFHandle    *Handle;
  2568.     BYTE             Success = FALSE;
  2569.  
  2570.         /* Allocate a handle. */
  2571.  
  2572.     if(Handle = AllocIFF())
  2573.     {
  2574.             /* Open an output stream. */
  2575.  
  2576.         if(Handle -> iff_Stream = Open(Name,MODE_NEWFILE))
  2577.         {
  2578.                 /* Tell iffparse that this is
  2579.                  * a DOS handle.
  2580.                  */
  2581.  
  2582.             InitIFFasDOS(Handle);
  2583.  
  2584.                 /* Open the handle for writing. */
  2585.  
  2586.             if(!OpenIFF(Handle,IFFF_WRITE))
  2587.             {
  2588.                     /* Push outmost chunk onto stack. */
  2589.  
  2590.                 if(!PushChunk(Handle,ID_TERM,ID_FORM,IFFSIZE_UNKNOWN))
  2591.                 {
  2592.                         /* Add a version identifier. */
  2593.  
  2594.                     if(!PushChunk(Handle,0,ID_VERS,IFFSIZE_UNKNOWN))
  2595.                     {
  2596.                         struct TermInfo TermInfo;
  2597.  
  2598.                         TermInfo . Version    = TermVersion;
  2599.                         TermInfo . Revision    = TermRevision;
  2600.  
  2601.                             /* Write the version data. */
  2602.  
  2603.                         if(WriteChunkBytes(Handle,&TermInfo,sizeof(struct TermInfo)) == sizeof(struct TermInfo))
  2604.                         {
  2605.                                 /* Pop the version chunk, i.e. write it to the file. */
  2606.  
  2607.                             if(PopChunk(Handle))
  2608.                                 Success = FALSE;
  2609.                             else
  2610.                             {
  2611.                                     /* Push the real data chunk on the stack. */
  2612.  
  2613.                                 if(!PushChunk(Handle,0,Type,IFFSIZE_UNKNOWN))
  2614.                                 {
  2615.                                         /* Write the data. */
  2616.  
  2617.                                     if(WriteChunkBytes(Handle,Data,Size) == Size)
  2618.                                         Success = TRUE;
  2619.  
  2620.                                             /* Pop the data chunk. */
  2621.  
  2622.                                     if(PopChunk(Handle))
  2623.                                         Success = FALSE;
  2624.                                 }
  2625.                                 else
  2626.                                     Success = FALSE;
  2627.                             }
  2628.                         }
  2629.                         else
  2630.                             Success = FALSE;
  2631.                     }
  2632.  
  2633.                         /* Seems that we're done, now try to pop the FORM chunk
  2634.                          * and return.
  2635.                          */
  2636.  
  2637.                     if(PopChunk(Handle))
  2638.                         Success = FALSE;
  2639.                 }
  2640.  
  2641.                     /* Close the handle (flush any pending data). */
  2642.  
  2643.                 CloseIFF(Handle);
  2644.             }
  2645.  
  2646.                 /* Close the DOS handle itself. */
  2647.  
  2648.             Close(Handle -> iff_Stream);
  2649.         }
  2650.  
  2651.             /* And free the IFF handle. */
  2652.  
  2653.         FreeIFF(Handle);
  2654.     }
  2655.  
  2656.     if(Success)
  2657.         SetProtection(Name,FIBF_EXECUTE);
  2658.  
  2659.     return(Success);
  2660. }
  2661.  
  2662.     /* ReadIFFData(STRPTR Name,APTR Data,LONG Size,ULONG Type):
  2663.      *
  2664.      *    Read data from a `TERM' FORM chunk contained in an IFF file.
  2665.      */
  2666.  
  2667. BYTE
  2668. ReadIFFData(STRPTR Name,APTR Data,LONG Size,ULONG Type)
  2669. {
  2670.     struct IFFHandle    *Handle;
  2671.     BYTE             Success = FALSE;
  2672.     struct StoredProperty    *Prop;
  2673.     struct TermInfo        *TermInfo;
  2674.  
  2675.     if(Handle = AllocIFF())
  2676.     {
  2677.         if(Handle -> iff_Stream = Open(Name,MODE_OLDFILE))
  2678.         {
  2679.             InitIFFasDOS(Handle);
  2680.  
  2681.             if(!OpenIFF(Handle,IFFF_READ))
  2682.             {
  2683.                 /* Collect version number ID if
  2684.                  * available.
  2685.                  */
  2686.  
  2687.                 if(!PropChunks(Handle,VersionProps,1))
  2688.                 {
  2689.                     /* The following line tells iffparse to stop at the
  2690.                      * very beginning of a `Type' chunk contained in a
  2691.                      * `TERM' FORM chunk.
  2692.                      */
  2693.  
  2694.                     if(!StopChunk(Handle,ID_TERM,Type))
  2695.                     {
  2696.                         /* Parse the file... */
  2697.  
  2698.                         if(!ParseIFF(Handle,IFFPARSE_SCAN))
  2699.                         {
  2700.                             /* Did we get a version ID? */
  2701.  
  2702.                             if(Prop = FindProp(Handle,ID_TERM,ID_VERS))
  2703.                             {
  2704.                                 TermInfo = (struct TermInfo *)Prop -> sp_Data;
  2705.  
  2706.                                 /* Is it the file format we are able
  2707.                                  * to read?
  2708.                                  */
  2709.  
  2710.                                 if((TermInfo -> Version > TermVersion) || (TermInfo -> Version == TermVersion && TermInfo -> Revision > TermRevision) || (TermInfo -> Version == 1 && TermInfo -> Revision < 6))
  2711.                                     Success = FALSE;
  2712.                                 else
  2713.                                 {
  2714.                                     struct ContextNode *Chunk = CurrentChunk(Handle);
  2715.  
  2716.                                     if(Chunk -> cn_Size < Size)
  2717.                                         Size = Chunk -> cn_Size;
  2718.  
  2719.                                     /* The file read pointer is positioned
  2720.                                      * just in front of the first data
  2721.                                      * to be read, so let's don't disappoint
  2722.                                      * iffparse and read it.
  2723.                                      */
  2724.  
  2725.                                     if(ReadChunkBytes(Handle,Data,Size) == Size)
  2726.                                         Success = TRUE;
  2727.                                 }
  2728.                             }
  2729.                         }
  2730.                     }
  2731.                 }
  2732.  
  2733.                 CloseIFF(Handle);
  2734.             }
  2735.  
  2736.             Close(Handle -> iff_Stream);
  2737.         }
  2738.  
  2739.         FreeIFF(Handle);
  2740.     }
  2741.  
  2742.     return(Success);
  2743. }
  2744.