home *** CD-ROM | disk | FTP | other *** search
/ Amiga Elysian Archive / AmigaElysianArchive.iso / comm / term33so.lha / termStatusDisplay.c < prev    next >
C/C++ Source or Header  |  1993-04-30  |  44KB  |  1,998 lines

  1. /*
  2. **    termStatusDisplay.c
  3. **
  4. **    Status information display routines
  5. **
  6. **    Copyright © 1990-1993 by Olaf `Olsen' Barthel & MXM
  7. **        All Rights Reserved
  8. */
  9.  
  10. #include "termGlobal.h"
  11.  
  12.     /* The information to be displayed. */
  13.  
  14. enum    {    INFO_STATUS,INFO_FONT,INFO_PROTOCOL,INFO_EMULATION,INFO_BAUDRATE,
  15.         INFO_PARAMETERS,INFO_CURRENTTIME,INFO_ONLINETIME,INFO_ONLINECOST };
  16.  
  17.     /* The current status line display mode. */
  18.  
  19. enum    {    MODE_SCREEN_NORMAL,MODE_SCREEN_COMPRESSED,MODE_WB_NORMAL,MODE_WB_COMPRESSED };
  20.  
  21.     /* Enumerated text boxes. */
  22.  
  23. enum    {    STATUSBOX_STATUS_FONT,STATUSBOX_PROTOCOL_TERMINAL,
  24.         STATUSBOX_RATE_PARAMETERS,STATUSBOX_TIME_ONLINE };
  25.  
  26.     /* The tags our private status gadget class responds to. */
  27.  
  28. #define SG_Status    (TAG_USER+1)
  29. #define SG_Font        (TAG_USER+2)
  30. #define SG_Protocol    (TAG_USER+3)
  31. #define SG_Emulation    (TAG_USER+4)
  32. #define SG_BaudRate    (TAG_USER+5)
  33. #define SG_Parameters    (TAG_USER+6)
  34. #define SG_CurrentTime    (TAG_USER+7)
  35. #define SG_OnlineTime    (TAG_USER+8)
  36. #define SG_OnlineCost    (TAG_USER+9)
  37.  
  38.     /* Special private information maintained and required
  39.      * by the status gadget class.
  40.      */
  41.  
  42. struct StatusInfo
  43. {
  44.     struct TextBox        *BoxArray[4],
  45.                 *BoxList;
  46.  
  47.     LONG             FullWidth;
  48.     LONG             FirstColumn;
  49.  
  50.     UWORD             Mask;
  51.     UWORD             Mode;
  52.  
  53.     LONG             LastWidth;
  54.  
  55.     UBYTE             Strings[8][20];
  56.  
  57.     struct SignalSemaphore     Semaphore;
  58. };
  59.  
  60.     /* The status server passes this structure to the
  61.      * rendering routine if the status information
  62.      * is to be updated.
  63.      */
  64.  
  65. struct ObjectCarrier
  66. {
  67.     struct RastPort     *RPort;
  68.     struct TextBox    **BoxArray;
  69. };
  70.  
  71.     /* A custom message type for the display update server. */
  72.  
  73. struct UpdateMessage
  74. {
  75.     struct Message    VanillaMessage;
  76.  
  77.     APTR        Object;
  78.     UBYTE        Mode,
  79.             Type;
  80. };
  81.  
  82.     /* The following static strings are displayed in the status
  83.      * window.
  84.      */
  85.  
  86. STATIC STRPTR    ConfigFont[3],
  87.         ConfigEmulation[6],
  88.         ConfigParity[6],
  89.         ConfigStatus[8];
  90.  
  91.     /* Width of the status line text, required in case the user interface
  92.      * font happens to be proportional-spaced.
  93.      */
  94.  
  95. STATIC LONG             StatusLineWidth;
  96.  
  97.     /* Our local private status gadget class. */
  98.  
  99. STATIC struct IClass        *StatusGadgetClass;
  100.  
  101.     /* The status display update task. */
  102.  
  103. STATIC struct Task        *StatusDisplayTask;
  104. STATIC struct MsgPort        *StatusDisplayPort;
  105.  
  106.     /* Prototypes for this module. */
  107.  
  108. STATIC ULONG            SetStatusGadget(struct IClass *class,Object *object,struct opSet *SetInfo);
  109. STATIC ULONG            GetStatusGadget(struct IClass *class,Object *object,struct opGet *GetInfo);
  110. STATIC ULONG            RenderStatusGadget(struct IClass *class,Object *object,struct gpRender *RenderInfo);
  111. STATIC ULONG            DelStatusGadget(struct IClass *class,Object *object,Msg msg);
  112. STATIC ULONG            NewStatusGadget(struct IClass *class,Object *object,struct opSet *SetMethod);
  113. STATIC ULONG __saveds __asm    StatusGadgetDispatch(register __a0 struct IClass *class,register __a2 Object *object,register __a1 Msg msg);
  114. STATIC VOID            FreeStatusGadgetClass(VOID);
  115. STATIC BYTE            NewStatusGadgetClass(VOID);
  116.  
  117.     /* GetStatusGadget():
  118.      *
  119.      *    Query information on the status gadget.
  120.      */
  121.  
  122. STATIC ULONG
  123. GetStatusGadget(struct IClass *class,Object *object,struct opGet *GetInfo)
  124. {
  125.     struct StatusInfo *StatusInfo = INST_DATA(class,object);
  126.  
  127.     switch(GetInfo -> opg_AttrID)
  128.     {
  129.         case SGA_FullWidth:
  130.  
  131.             *GetInfo -> opg_Storage = (ULONG)StatusInfo -> FullWidth;
  132.             return(1);
  133.  
  134.         default:
  135.  
  136.             return(DoSuperMethodA(class,object,(Msg)GetInfo));
  137.     }
  138. }
  139.  
  140.     /* SetStatusGadget():
  141.      *
  142.      *    Set certain attributes of the status gadget.
  143.      */
  144.  
  145. STATIC ULONG
  146. SetStatusGadget(struct IClass *class,Object *object,struct opSet *SetInfo)
  147. {
  148.     struct StatusInfo    *StatusInfo = INST_DATA(class,object);
  149.     LONG             i,j;
  150.     struct RastPort        *RPort;
  151.     struct TagItem        *Tag;
  152.  
  153.     DoSuperMethodA(class,object,(Msg)SetInfo);
  154.  
  155.         /* Make sure that the information is available and
  156.          * nobody else tries to modify it.
  157.          */
  158.  
  159.     ObtainSemaphore(&StatusInfo -> Semaphore);
  160.  
  161.         /* Obtain the new text to be displayed in the gadget. */
  162.  
  163.     for(i = SG_Status, j = 0 ; i <= SG_OnlineCost ; i++, j++)
  164.     {
  165.         if(Tag = FindTagItem(i,SetInfo -> ops_AttrList))
  166.         {
  167.             strcpy(StatusInfo -> Strings[j],(STRPTR)Tag -> ti_Data);
  168.  
  169.             StatusInfo -> Mask |= (1 << j);
  170.         }
  171.     }
  172.  
  173.         /* Release the lock. */
  174.  
  175.     ReleaseSemaphore(&StatusInfo -> Semaphore);
  176.  
  177.         /* Are we allowed to redraw the information? */
  178.  
  179.     if(!RefreshAllowed())
  180.         return(0);
  181.  
  182.         /* Obtain the drawing area lock. */
  183.  
  184.     if(RPort = ObtainGIRPort(SetInfo -> ops_GInfo))
  185.     {
  186.             /* Normal, uncompressed status line? */
  187.  
  188.         if(StatusInfo -> Mode == MODE_WB_NORMAL)
  189.         {
  190.                 /* Take a look at the strings which have
  191.                  * changed and render the corresponding
  192.                  * text.
  193.                  */
  194.  
  195.             for(i = 0 ; i < 8 ; i++)
  196.             {
  197.                 if(StatusInfo -> Mask & (1 << i))
  198.                 {
  199.                     SZ_SetLine(RPort,StatusInfo -> BoxArray[i / 2],i % 2,StatusInfo -> Strings[i]);
  200.  
  201.                     StatusInfo -> Mask &= ~(1 << i);
  202.                 }
  203.             }
  204.         }
  205.         else
  206.         {
  207.             STATIC BYTE Offsets[8] =
  208.             {
  209.                  0,
  210.                 -1,
  211.                 26,
  212.                 11,
  213.                 40,
  214.                 53,
  215.                 61,
  216.                 72
  217.             };
  218.  
  219.             struct Gadget    *Gadget;
  220.             UBYTE         LineBuffer[90];
  221.             WORD         i,j,k;
  222.             LONG         Width,
  223.                      Left,
  224.                      Top;
  225.  
  226.                 /* Get the real gadget. */
  227.  
  228.             Gadget = (struct Gadget *)object;
  229.  
  230.                 /* Fill the line with defaults. */
  231.  
  232.             strcpy(LineBuffer,"         ·              ·             ·            ·       ·          ·         ");
  233.  
  234.                 /* Add the information strings. */
  235.  
  236.             for(i = 0 ; i < 8 ; i++)
  237.             {
  238.                 if(Offsets[i] >= 0)
  239.                 {
  240.                     j = strlen(StatusInfo -> Strings[i]);
  241.  
  242.                     for(k = 0 ; k < j ; k++)
  243.                         LineBuffer[Offsets[i] + k] = StatusInfo -> Strings[i][k];
  244.                 }
  245.             }
  246.  
  247.                 /* Determine the pixel width of the string. */
  248.  
  249.             Width = TextLength(RPort,LineBuffer,80);
  250.  
  251.                 /* Get the rendering top offset. */
  252.  
  253.             Top = SetInfo -> ops_GInfo -> gi_Window -> Height + Gadget -> TopEdge;
  254.  
  255.             SetDrMd(RPort,JAM2);
  256.  
  257.                 /* Are we to clear the area the last rendering
  258.                  * operation obscured?
  259.                  */
  260.  
  261.             if(StatusInfo -> LastWidth && StatusInfo -> LastWidth != Width)
  262.             {
  263.                 Left = (SetInfo -> ops_GInfo -> gi_Window -> Width - StatusInfo -> LastWidth) / 2;
  264.  
  265.                     /* Set the approriate rendering pen. */
  266.  
  267.                 if(SetInfo -> ops_GInfo -> gi_Window -> Flags & WFLG_WINDOWACTIVE)
  268.                     SetAPen(RPort,SetInfo -> ops_GInfo -> gi_DrInfo -> dri_Pens[FILLPEN]);
  269.                 else
  270.                     SetAPen(RPort,SetInfo -> ops_GInfo -> gi_DrInfo -> dri_Pens[BACKGROUNDPEN]);
  271.  
  272.                     /* Clear the area. */
  273.  
  274.                 RectFill(RPort,Left,Top,Left + StatusInfo -> LastWidth - 1,Top + Gadget -> Height - 3);
  275.             }
  276.  
  277.                 /* Set the approriate rendering pens. */
  278.  
  279.             if(SetInfo -> ops_GInfo -> gi_Window -> Flags & WFLG_WINDOWACTIVE)
  280.             {
  281.                 SetAPen(RPort,SetInfo -> ops_GInfo -> gi_DrInfo -> dri_Pens[FILLTEXTPEN]);
  282.                 SetBPen(RPort,SetInfo -> ops_GInfo -> gi_DrInfo -> dri_Pens[FILLPEN]);
  283.             }
  284.             else
  285.             {
  286.                 SetAPen(RPort,SetInfo -> ops_GInfo -> gi_DrInfo -> dri_Pens[TEXTPEN]);
  287.                 SetBPen(RPort,SetInfo -> ops_GInfo -> gi_DrInfo -> dri_Pens[BACKGROUNDPEN]);
  288.             }
  289.  
  290.                 /* Remember the text pixel width. */
  291.  
  292.             StatusInfo -> LastWidth = Width;
  293.  
  294.                 /* Display the status line. */
  295.  
  296.             Move(RPort,(SetInfo -> ops_GInfo -> gi_Window -> Width - StatusInfo -> LastWidth) / 2,Top + RPort -> Font -> tf_Baseline);
  297.             Text(RPort,LineBuffer,80);
  298.         }
  299.  
  300.             /* Release the rendering area. */
  301.  
  302.         ReleaseGIRPort(RPort);
  303.     }
  304.  
  305.     return(1);
  306. }
  307.  
  308.     /* RenderStatusGadget():
  309.      *
  310.      *    Redraw the entire status gadget.
  311.      */
  312.  
  313. STATIC ULONG
  314. RenderStatusGadget(struct IClass *class,Object *object,struct gpRender *RenderInfo)
  315. {
  316.     struct StatusInfo    *StatusInfo    = INST_DATA(class,object);
  317.     struct RastPort        *RPort        = RenderInfo -> gpr_RPort;
  318.     LONG             i;
  319.  
  320.         /* Normal, uncompressed display? */
  321.  
  322.     if(StatusInfo -> Mode == MODE_WB_NORMAL)
  323.     {
  324.             /* Refresh the entire imagery (the default)? */
  325.  
  326.         if(RenderInfo -> gpr_Redraw == GREDRAW_REDRAW)
  327.         {
  328.             struct Gadget    *Gadget = (struct Gadget *)object;
  329.             LONG         X;
  330.  
  331.                 /* Don't let anyone modify the text. */
  332.  
  333.             ObtainSemaphore(&StatusInfo -> Semaphore);
  334.  
  335.                 /* Get the new gadget left offset. */
  336.  
  337.             if((X = (RenderInfo -> gpr_GInfo -> gi_Window -> Width - StatusInfo -> FullWidth) / 2) < 0)
  338.                 X = 0;
  339.  
  340.             X += StatusInfo -> FirstColumn - SZ_GetBoxInfo(StatusInfo -> BoxList,BOX_LEFT);
  341.  
  342.                 /* Move the status line to the new location. */
  343.  
  344.             SZ_SetBoxes(StatusInfo -> BoxList,-1,RenderInfo -> gpr_GInfo -> gi_Window -> Height + Gadget -> TopEdge + 1);
  345.  
  346.             if(X)
  347.                 SZ_MoveBoxes(StatusInfo -> BoxList,X,0);
  348.  
  349.                 /* Set the box title rendering pen. */
  350.  
  351.             if(RenderInfo -> gpr_GInfo -> gi_Window -> Flags & WFLG_WINDOWACTIVE)
  352.                 SZ_SetTitlePen(StatusInfo -> BoxList,RenderInfo -> gpr_GInfo -> gi_DrInfo -> dri_Pens[FILLTEXTPEN],RenderInfo -> gpr_GInfo -> gi_DrInfo -> dri_Pens[FILLPEN]);
  353.             else
  354.                 SZ_SetTitlePen(StatusInfo -> BoxList,RenderInfo -> gpr_GInfo -> gi_DrInfo -> dri_Pens[TEXTPEN],RenderInfo -> gpr_GInfo -> gi_DrInfo -> dri_Pens[BACKGROUNDPEN]);
  355.  
  356.                 /* Redraw the boxes. */
  357.  
  358.             SZ_DrawBoxes(RPort,StatusInfo -> BoxList);
  359.  
  360.                 /* Redraw all the strings. */
  361.  
  362.             StatusInfo -> Mask |= 0xFF;
  363.  
  364.             ReleaseSemaphore(&StatusInfo -> Semaphore);
  365.         }
  366.  
  367.             /* Update the information which has changed. */
  368.  
  369.         for(i = 0 ; i < 8 ; i++)
  370.         {
  371.             if(StatusInfo -> Mask & (1 << i))
  372.             {
  373.                 SZ_SetLine(RPort,StatusInfo -> BoxArray[i / 2],i % 2,StatusInfo -> Strings[i]);
  374.  
  375.                 StatusInfo -> Mask &= ~(1 << i);
  376.             }
  377.         }
  378.     }
  379.     else
  380.     {
  381.         STATIC BYTE Offsets[8] =
  382.         {
  383.              0,
  384.             -1,
  385.             26,
  386.             11,
  387.             40,
  388.             53,
  389.             61,
  390.             72
  391.         };
  392.  
  393.         struct Gadget    *Gadget;
  394.         UBYTE         LineBuffer[90];
  395.         WORD         i,j,k;
  396.         LONG         Width,
  397.                  Left,
  398.                  Top;
  399.  
  400.             /* Grab the access semaphore. */
  401.  
  402.         ObtainSemaphore(&StatusInfo -> Semaphore);
  403.  
  404.             /* Get the real gadget info. */
  405.  
  406.         Gadget = (struct Gadget *)object;
  407.  
  408.             /* Fill the line buffer with defaults. */
  409.  
  410.         strcpy(LineBuffer,"         ·              ·             ·            ·       ·          ·         ");
  411.  
  412.             /* Fill in the information strings. */
  413.  
  414.         for(i = 0 ; i < 8 ; i++)
  415.         {
  416.             if(Offsets[i] >= 0)
  417.             {
  418.                 j = strlen(StatusInfo -> Strings[i]);
  419.  
  420.                 for(k = 0 ; k < j ; k++)
  421.                     LineBuffer[Offsets[i] + k] = StatusInfo -> Strings[i][k];
  422.             }
  423.         }
  424.  
  425.             /* Determine the pixel width of the line. */
  426.  
  427.         Width = TextLength(RPort,LineBuffer,80);
  428.  
  429.             /* Get the line top offset. */
  430.  
  431.         Top = RenderInfo -> gpr_GInfo -> gi_Window -> Height + Gadget -> TopEdge;
  432.  
  433.         SetDrMd(RPort,JAM2);
  434.  
  435.             /* Clear the previously written text if necessary. */
  436.  
  437.         if(StatusInfo -> LastWidth && RenderInfo -> gpr_Redraw != GREDRAW_REDRAW)
  438.         {
  439.             Left = (RenderInfo -> gpr_GInfo -> gi_Window -> Width - StatusInfo -> LastWidth) / 2;
  440.  
  441.             if(RenderInfo -> gpr_GInfo -> gi_Window -> Flags & WFLG_WINDOWACTIVE)
  442.                 SetAPen(RPort,RenderInfo -> gpr_GInfo -> gi_DrInfo -> dri_Pens[FILLPEN]);
  443.             else
  444.                 SetAPen(RPort,RenderInfo -> gpr_GInfo -> gi_DrInfo -> dri_Pens[BACKGROUNDPEN]);
  445.  
  446.             RectFill(RPort,Left,Top,Left + StatusInfo -> LastWidth - 1,Top + Gadget -> Height - 3);
  447.         }
  448.  
  449.             /* Set the approriate rendering colours. */
  450.  
  451.         if(RenderInfo -> gpr_GInfo -> gi_Window -> Flags & WFLG_WINDOWACTIVE)
  452.         {
  453.             SetAPen(RPort,RenderInfo -> gpr_GInfo -> gi_DrInfo -> dri_Pens[FILLTEXTPEN]);
  454.             SetBPen(RPort,RenderInfo -> gpr_GInfo -> gi_DrInfo -> dri_Pens[FILLPEN]);
  455.         }
  456.         else
  457.         {
  458.             SetAPen(RPort,RenderInfo -> gpr_GInfo -> gi_DrInfo -> dri_Pens[TEXTPEN]);
  459.             SetBPen(RPort,RenderInfo -> gpr_GInfo -> gi_DrInfo -> dri_Pens[BACKGROUNDPEN]);
  460.         }
  461.  
  462.             /* Remember last pixel width. */
  463.  
  464.         StatusInfo -> LastWidth = Width;
  465.  
  466.             /* Render the status line. */
  467.  
  468.         Move(RPort,(RenderInfo -> gpr_GInfo -> gi_Window -> Width - StatusInfo -> LastWidth) / 2,Top + RPort -> Font -> tf_Baseline);
  469.         Text(RPort,LineBuffer,80);
  470.  
  471.             /* Release the lock. */
  472.  
  473.         ReleaseSemaphore(&StatusInfo -> Semaphore);
  474.     }
  475.  
  476.     return(0);
  477. }
  478.  
  479.     /* DelStatusGadget():
  480.      *
  481.      *    Deallocate the status gadget.
  482.      */
  483.  
  484. STATIC ULONG
  485. DelStatusGadget(struct IClass *class,Object *object,Msg msg)
  486. {
  487.     struct StatusInfo *StatusInfo = INST_DATA(class,object);
  488.  
  489.     if(StatusInfo -> BoxList)
  490.         SZ_FreeBoxes(StatusInfo -> BoxList);
  491.  
  492.     return(DoSuperMethodA(class,object,msg));
  493. }
  494.  
  495.     /* NewStatusGadget():
  496.      *
  497.      *    Create a new status gadget.
  498.      */
  499.  
  500. STATIC ULONG
  501. NewStatusGadget(struct IClass *class,Object *object,struct opSet *SetMethod)
  502. {
  503.     struct Gadget    *NewGadget;
  504.     struct TagItem    *OldTags,*Item;
  505.     LONG         NewItems[5][2],
  506.              Height,
  507.              Mode;
  508.  
  509.         /* Remember the old tag item list, as we will change it. */
  510.  
  511.     OldTags = SetMethod -> ops_AttrList;
  512.  
  513.         /* Determine the status line mode (compressed or normal). */
  514.  
  515.     if(Item = FindTagItem(SGA_Mode,OldTags))
  516.     {
  517.         switch(Item -> ti_Data)
  518.         {
  519.             case MODE_WB_NORMAL:
  520.             case MODE_WB_COMPRESSED:
  521.  
  522.                 Mode = Item -> ti_Data;
  523.                 break;
  524.  
  525.             default:
  526.  
  527.                 return(NULL);
  528.         }
  529.     }
  530.     else
  531.         return(NULL);
  532.  
  533.         /* Set up the defaults, note that this class
  534.          * implementation can, strictly speaking, not
  535.          * be considered reentrant.
  536.          */
  537.  
  538.     SZ_SizeSetup(DefaultPubScreen,&UserFont,TRUE);
  539.  
  540.         /* Determine object height. */
  541.  
  542.     if(Mode == MODE_WB_NORMAL)
  543.         Height = 3 + SZ_BoxHeight(2);
  544.     else
  545.         Height = 2 + UserFontHeight;
  546.  
  547.         /* Build new tag item list. */
  548.  
  549.     NewItems[0][0] = GA_RelBottom;
  550.     NewItems[0][1] = -Height;
  551.     NewItems[1][0] = GA_Height;
  552.     NewItems[1][1] = Height;
  553.     NewItems[2][0] = GA_BottomBorder;
  554.     NewItems[2][1] = TRUE;
  555.     NewItems[3][0] = GA_Highlight;
  556.     NewItems[3][1] = GFLG_GADGHNONE;
  557.     NewItems[4][0] = TAG_MORE;
  558.     NewItems[4][1] = (LONG)OldTags;
  559.  
  560.         /* Install the new tag item list. */
  561.  
  562.     SetMethod -> ops_AttrList = (struct TagItem *)NewItems;
  563.  
  564.         /* Create the new object. */
  565.  
  566.     if(NewGadget = (struct Gadget *)DoSuperMethodA(class,object,(Msg)SetMethod))
  567.     {
  568.         struct StatusInfo    *StatusInfo = INST_DATA(class,NewGadget);
  569.         LONG             SizeGadgetWidth;
  570.  
  571.             /* Determine the width of the window sizing gadget,
  572.              * hopefully these values are never going to be
  573.              * changed.
  574.              */
  575.  
  576.         if(DefaultPubScreen -> Flags & SCREENHIRES)
  577.             SizeGadgetWidth = SIZE_GADGET_WIDTH_HIGH;
  578.         else
  579.             SizeGadgetWidth = SIZE_GADGET_WIDTH_LOW;
  580.  
  581.             /* Clear the extra information area. */
  582.  
  583.         memset(StatusInfo,0,sizeof(struct StatusInfo));
  584.  
  585.             /* Initialize the signal semaphore. */
  586.  
  587.         InitSemaphore(&StatusInfo -> Semaphore);
  588.  
  589.             /* Is it the `big one'? */
  590.  
  591.         if((StatusInfo -> Mode = Mode) == MODE_WB_NORMAL)
  592.         {
  593.             WORD         ColumnLeft[4],
  594.                      ColumnWidth[4];
  595.             struct TextBox    *Box;
  596.             LONG         i,Max = 0,Len,FullWidth,BoxCounter = 0;
  597.  
  598.             ColumnLeft[0] = SZ_LeftOffsetN(MSG_TERMSTATUSDISPLAY_STATUS_TXT,MSG_TERMSTATUSDISPLAY_FONT_TXT,-1);
  599.             ColumnLeft[1] = SZ_LeftOffsetN(MSG_TERMSTATUSDISPLAY_PROTOCOL_TXT,MSG_TERMSTATUSDISPLAY_TERMINAL_TXT,-1);
  600.             ColumnLeft[2] = SZ_LeftOffsetN(MSG_TERMSTATUSDISPLAY_BAUDRATE_TXT,MSG_TERMSTATUSDISPLAY_PARAMETERS_TXT,-1);
  601.             ColumnLeft[3] = SZ_LeftOffsetN(MSG_TERMSTATUSDISPLAY_TIME_TXT,MSG_TERMSTATUSDISPLAY_ONLINE_TXT,-1);
  602.  
  603.             for(i = 0 ; ConfigStatus[i] ; i++)
  604.             {
  605.                 if((Len = SZ_BoxWidth(strlen(ConfigStatus[i]))) > Max)
  606.                     Max = Len;
  607.             }
  608.  
  609.             for(i = 0 ; ConfigFont[i] ; i++)
  610.             {
  611.                 if((Len = SZ_BoxWidth(strlen(ConfigFont[i]))) > Max)
  612.                     Max = Len;
  613.             }
  614.  
  615.             ColumnWidth[0] = Max;
  616.  
  617.             Max = SZ_BoxWidth(12);
  618.  
  619.             for(i = 0 ; ConfigEmulation[i] ; i++)
  620.             {
  621.                 if((Len = SZ_BoxWidth(strlen(ConfigEmulation[i]))) > Max)
  622.                     Max = Len;
  623.             }
  624.  
  625.             ColumnWidth[1] = Max;
  626.  
  627.             Max = SZ_BoxWidth(10);
  628.  
  629.             for(i = 0 ; ConfigParity[i] ; i++)
  630.             {
  631.                 if((Len = SZ_BoxWidth(4 + strlen(ConfigParity[i]))) > Max)
  632.                     Max = Len;
  633.             }
  634.  
  635.             ColumnWidth[2] = Max;
  636.  
  637.             ColumnWidth[3] = SZ_BoxWidth(8);
  638.  
  639.             FullWidth = 0;
  640.  
  641.             for(i = 0 ; i < 4 ; i++)
  642.                 FullWidth += ColumnWidth[i] + ColumnLeft[i];
  643.  
  644.             FullWidth += 3 * InterWidth;
  645.  
  646.             StatusInfo -> FullWidth        = FullWidth + 2 * SizeGadgetWidth;
  647.             StatusInfo -> FirstColumn    = ColumnLeft[0];
  648.  
  649.             if(FullWidth > DefaultPubScreen -> Width)
  650.                 SZ_SetLeftEdge(ColumnLeft[0]);
  651.             else
  652.                 SZ_SetLeftEdge((DefaultPubScreen -> Width - FullWidth) / 2 + ColumnLeft[0]);
  653.  
  654.             SZ_SetAbsoluteTop(2);
  655.             SZ_SetTopEdge(2);
  656.  
  657.             SZ_SetWidth(ColumnWidth[0]);
  658.  
  659.             StatusInfo -> BoxArray[BoxCounter++] = Box = SZ_CreateTextBox(&StatusInfo -> BoxList,
  660.                 SZ_Lines,    2,
  661.                 SZ_AutoWidth,    TRUE,
  662.             TAG_DONE);
  663.  
  664.             SZ_SetBoxTitles(Box,LocaleString(MSG_TERMSTATUSDISPLAY_STATUS_TXT),LocaleString(MSG_TERMSTATUSDISPLAY_FONT_TXT),NULL);
  665.  
  666.             SZ_SetWidth(ColumnWidth[1]);
  667.             SZ_AddLeftOffset(ColumnLeft[1]);
  668.  
  669.             StatusInfo -> BoxArray[BoxCounter++] = Box = SZ_CreateTextBox(&StatusInfo -> BoxList,
  670.                 SZ_Lines,    2,
  671.                 SZ_AutoWidth,    TRUE,
  672.                 SZ_NewColumn,    TRUE,
  673.             TAG_DONE);
  674.  
  675.             SZ_SetBoxTitles(Box,LocaleString(MSG_TERMSTATUSDISPLAY_PROTOCOL_TXT),LocaleString(MSG_TERMSTATUSDISPLAY_TERMINAL_TXT),NULL);
  676.  
  677.             SZ_SetWidth(ColumnWidth[2]);
  678.             SZ_AddLeftOffset(ColumnLeft[2]);
  679.  
  680.             StatusInfo -> BoxArray[BoxCounter++] = Box = SZ_CreateTextBox(&StatusInfo -> BoxList,
  681.                 SZ_Lines,    2,
  682.                 SZ_AutoWidth,    TRUE,
  683.                 SZ_NewColumn,    TRUE,
  684.             TAG_DONE);
  685.  
  686.             SZ_SetBoxTitles(Box,LocaleString(MSG_TERMSTATUSDISPLAY_BAUDRATE_TXT),LocaleString(MSG_TERMSTATUSDISPLAY_PARAMETERS_TXT),NULL);
  687.  
  688.             SZ_SetWidth(ColumnWidth[3]);
  689.             SZ_AddLeftOffset(ColumnLeft[3]);
  690.  
  691.             StatusInfo -> BoxArray[BoxCounter] = Box = SZ_CreateTextBox(&StatusInfo -> BoxList,
  692.                 SZ_Lines,    2,
  693.                 SZ_AutoWidth,    TRUE,
  694.                 SZ_NewColumn,    TRUE,
  695.             TAG_DONE);
  696.  
  697.             SZ_SetBoxTitles(Box,LocaleString(MSG_TERMSTATUSDISPLAY_TIME_TXT),LocaleString(MSG_TERMSTATUSDISPLAY_ONLINE_TXT),NULL);
  698.  
  699.             if(!Box)
  700.             {
  701.                 SZ_FreeBoxes(StatusInfo -> BoxList);
  702.  
  703.                 DoSuperMethod(class,(Object *)NewGadget,OM_DISPOSE);
  704.  
  705.                 NewGadget = NULL;
  706.             }
  707.         }
  708.         else
  709.             StatusInfo -> FullWidth = SZ_BoxWidth(80) + 2 * SizeGadgetWidth;
  710.     }
  711.  
  712.         /* Install the old tag item list. */
  713.  
  714.     SetMethod -> ops_AttrList = OldTags;
  715.  
  716.     return((ULONG)NewGadget);
  717. }
  718.  
  719.     /* StatusGadgetDispatch():
  720.      *
  721.      *    Dispatch an object message.
  722.      */
  723.  
  724. STATIC ULONG __saveds __asm
  725. StatusGadgetDispatch(register __a0 struct IClass *class,register __a2 Object *object,register __a1 Msg msg)
  726. {
  727.     switch(msg -> MethodID)
  728.     {
  729.             /* Create new gadget. */
  730.  
  731.         case OM_NEW:
  732.  
  733.             return(NewStatusGadget(class,object,(struct opSet *)msg));
  734.  
  735.             /* Set attributes. */
  736.  
  737.         case OM_SET:
  738.  
  739.             return(SetStatusGadget(class,object,(struct opSet *)msg));
  740.  
  741.             /* Get attributes. */
  742.  
  743.         case OM_GET:
  744.  
  745.             return(GetStatusGadget(class,object,(struct opGet *)msg));
  746.  
  747.             /* Dispose gadget. */
  748.  
  749.         case OM_DISPOSE:
  750.  
  751.             return(DelStatusGadget(class,object,msg));
  752.  
  753.             /* Render the gadget. */
  754.  
  755.         case GM_RENDER:
  756.  
  757.             return(RenderStatusGadget(class,object,(struct gpRender *)msg));
  758.  
  759.             /* Do nothing. */
  760.  
  761.         case GM_HITTEST:
  762.  
  763.             return(0);
  764.  
  765.             /* Catchall... */
  766.  
  767.         default:
  768.  
  769.             return(DoSuperMethodA(class,object,msg));
  770.     }
  771. }
  772.  
  773.     /* FreeStatusGadgetClass():
  774.      *
  775.      *    Free the private status gadget class.
  776.      */
  777.  
  778. STATIC VOID
  779. FreeStatusGadgetClass()
  780. {
  781.     if(StatusGadgetClass)
  782.     {
  783.         FreeClass(StatusGadgetClass);
  784.  
  785.         StatusGadgetClass = NULL;
  786.     }
  787. }
  788.  
  789.     /* NewStatusGadgetClass():
  790.      *
  791.      *    Create a new status gadget class.
  792.      */
  793.  
  794. STATIC BYTE
  795. NewStatusGadgetClass()
  796. {
  797.         /* Release the old instance. */
  798.  
  799.     FreeStatusGadgetClass();
  800.  
  801.         /* Localize the title texts. */
  802.  
  803.     LocalizeString(ConfigFont,MSG_TERMAUX_STANDARD_FONT_TXT,MSG_TERMAUX_IBM_FONT_TXT);
  804.     LocalizeString(ConfigEmulation,MSG_TERMAUX_ANSI_VT102_TXT,MSG_TERMAUX_HEX_TXT);
  805.     LocalizeString(ConfigParity,MSG_TERMAUX_NONE_TXT,MSG_TERMAUX_SPACE_TXT);
  806.     LocalizeString(ConfigStatus,MSG_TERMAUX_READY_TXT,MSG_TERMAUX_HANG_UP_TXT);
  807.  
  808.         /* Create the class. */
  809.  
  810.     if(StatusGadgetClass = MakeClass(NULL,GADGETCLASS,NULL,sizeof(struct StatusInfo),0))
  811.     {
  812.             /* Install the dispatcher. */
  813.  
  814.         StatusGadgetClass -> cl_Dispatcher . h_Entry = (LONG (*)())StatusGadgetDispatch;
  815.  
  816.         return(TRUE);
  817.     }
  818.     else
  819.         return(FALSE);
  820. }
  821.  
  822.     /* DeleteStatusGadget(struct Gadget *Gadget):
  823.      *
  824.      *    Delete the status gadget.
  825.      */
  826.  
  827. VOID
  828. DeleteStatusGadget(struct Gadget *Gadget)
  829. {
  830.     DisposeObject(Gadget);
  831.  
  832.     FreeStatusGadgetClass();
  833. }
  834.  
  835.     /* CreateStatusGadget(LONG Width,LONG ID):
  836.      *
  837.      *    Create the status gadget.
  838.      */
  839.  
  840. struct Gadget *
  841. CreateStatusGadget(LONG Width,LONG ID)
  842. {
  843.         /* Create the new class. */
  844.  
  845.     if(NewStatusGadgetClass())
  846.     {
  847.         struct Gadget    *Gadget;
  848.         UBYTE         Mode;
  849.  
  850.             /* Determine the mode of operation. */
  851.  
  852.         if(Config -> ScreenConfig -> StatusLine == STATUSLINE_COMPRESSED)
  853.             Mode = MODE_WB_COMPRESSED;
  854.         else
  855.             Mode = MODE_WB_NORMAL;
  856.  
  857.             /* Create the new gadget. */
  858.  
  859.         if(Gadget = NewObject(StatusGadgetClass,NULL,
  860.             GA_ID,        ID,
  861.             GA_Left,    0,
  862.             GA_Width,    Width,
  863.  
  864.             SGA_Mode,    Mode,
  865.         TAG_DONE))
  866.             return(Gadget);
  867.         else
  868.             FreeStatusGadgetClass();
  869.     }
  870.  
  871.     return(NULL);
  872. }
  873.  
  874.     /* DoStatusInfo(APTR Object,UBYTE Mode,UBYTE Type,STRPTR String):
  875.      *
  876.      *    Display information in the status line area.
  877.      */
  878.  
  879. STATIC VOID __regargs
  880. DoStatusInfo(APTR Object,UBYTE Mode,UBYTE Type,STRPTR String)
  881. {
  882.         /* What mode of operation is the status area in? */
  883.  
  884.     switch(Mode)
  885.     {
  886.             /* Uses the status gadget class. */
  887.  
  888.         case MODE_WB_NORMAL:
  889.         case MODE_WB_COMPRESSED:
  890.  
  891.             SetGadgetAttrs(Object,Window,NULL,
  892.                 SG_Status + Type,String,
  893.             TAG_DONE);
  894.  
  895.             break;
  896.  
  897.             /* Compressed mode. */
  898.  
  899.         case MODE_SCREEN_COMPRESSED:
  900.         {
  901.             struct RastPort *RPort = Object;
  902.  
  903.             STATIC BYTE Offsets[8] =
  904.             {
  905.                  0,
  906.                 -1,    /* Not supported */
  907.                 26,
  908.                 11,
  909.                 40,
  910.                 53,
  911.                 61,
  912.                 72
  913.             };
  914.  
  915.             STATIC UBYTE Strings[8][20];
  916.             UBYTE LineBuffer[90];
  917.             LONG i,j,k,Width;
  918.  
  919.             strcpy(Strings[Type],String);
  920.  
  921.             strcpy(LineBuffer,"         ·              ·             ·            ·       ·          ·         ");
  922.  
  923.             for(i = 0 ; i < 8 ; i++)
  924.             {
  925.                 if(Offsets[i] >= 0)
  926.                 {
  927.                     j = strlen(Strings[i]);
  928.  
  929.                     for(k = 0 ; k < j ; k++)
  930.                         LineBuffer[Offsets[i] + k] = Strings[i][k];
  931.                 }
  932.             }
  933.  
  934.             Width = TextLength(RPort,LineBuffer,80);
  935.  
  936.             if(StatusLineWidth && StatusLineWidth != Width)
  937.                 SetRast(RPort,DrawInfo -> dri_Pens[TEXTPEN]);
  938.  
  939.             StatusLineWidth = Width;
  940.  
  941.             Move(RPort,(StatusWindow -> Width - Width) / 2,UserFontBase);
  942.             Text(RPort,LineBuffer,80);
  943.         }
  944.  
  945.         break;
  946.  
  947.             /* Normal mode. */
  948.  
  949.         case MODE_SCREEN_NORMAL:
  950.         {
  951.             STATIC UBYTE Codes[8][2] =
  952.             {
  953.                 STATUSBOX_STATUS_FONT,        0,
  954.                 STATUSBOX_STATUS_FONT,        1,
  955.  
  956.                 STATUSBOX_PROTOCOL_TERMINAL,    0,
  957.                 STATUSBOX_PROTOCOL_TERMINAL,    1,
  958.  
  959.                 STATUSBOX_RATE_PARAMETERS,    0,
  960.                 STATUSBOX_RATE_PARAMETERS,    1,
  961.  
  962.                 STATUSBOX_TIME_ONLINE,        0,
  963.                 STATUSBOX_TIME_ONLINE,        1
  964.             };
  965.  
  966.             struct ObjectCarrier *Carrier = (struct ObjectCarrier *)Object;
  967.  
  968.             SZ_PrintLine(Carrier -> RPort,Carrier -> BoxArray[Codes[Type][0]],Codes[Type][1],String);
  969.         }
  970.  
  971.         break;
  972.     }
  973. }
  974.  
  975.     /* DoInfo(APTR Object,UBYTE Mode,UBYTE Type,STRPTR String):
  976.      *
  977.      *    Post an update message to the status display server.
  978.      */
  979.  
  980. STATIC VOID __regargs
  981. DoInfo(APTR Object,UBYTE Mode,UBYTE Type,STRPTR String)
  982. {
  983.     struct UpdateMessage    *Msg;
  984.     WORD             Len = strlen(String) + 1;
  985.  
  986.         /* Allocate enough space to hold both the string
  987.          * and the message.
  988.          */
  989.  
  990.     if(Msg = (struct UpdateMessage *)AllocVec(sizeof(struct UpdateMessage) + Len,MEMF_ANY | MEMF_PUBLIC | MEMF_CLEAR))
  991.     {
  992.             /* Fill in the message head. */
  993.  
  994.         Msg -> VanillaMessage . mn_Length = sizeof(struct UpdateMessage) + Len;
  995.  
  996.             /* Set up the name pointer. */
  997.  
  998.         Msg -> VanillaMessage . mn_Node . ln_Name = (STRPTR)(Msg + 1);
  999.  
  1000.             /* Copy the string. */
  1001.  
  1002.         strcpy(Msg -> VanillaMessage . mn_Node . ln_Name,String);
  1003.  
  1004.             /* Fill in the remaining data. */
  1005.  
  1006.         Msg -> Object    = Object;
  1007.         Msg -> Mode    = Mode;
  1008.         Msg -> Type    = Type;
  1009.  
  1010.             /* Post the message. */
  1011.  
  1012.         PutMsg(StatusDisplayPort,(struct Message *)Msg);
  1013.     }
  1014. }
  1015.  
  1016.     /* UpdateInfo(APTR Object,UBYTE Mode,UBYTE Type,...):
  1017.      *
  1018.      *    Update the information displayed in the status
  1019.      *    area.
  1020.      */
  1021.  
  1022. STATIC VOID __stdargs
  1023. UpdateInfo(APTR Object,UBYTE Mode,UBYTE Type,...)
  1024. {
  1025.     if(Object)
  1026.     {
  1027.         UBYTE     MiniBuffer[50];
  1028.         STRPTR    *String;
  1029.         LONG    *Numeral;
  1030.         va_list     VarArgs;
  1031.  
  1032.         va_start(VarArgs,Type);
  1033.  
  1034.         String    = (STRPTR *)VarArgs;
  1035.         Numeral    = (LONG *)VarArgs;
  1036.  
  1037.         switch(Type)
  1038.         {
  1039.             case INFO_STATUS:
  1040.  
  1041.                 strcpy(MiniBuffer,ConfigStatus[Numeral[0]]);
  1042.                 strcat(MiniBuffer,"         ");
  1043.  
  1044.                 MiniBuffer[9] = 0;
  1045.  
  1046.                 DoInfo(Object,Mode,Type,MiniBuffer);
  1047.  
  1048.                 break;
  1049.  
  1050.             case INFO_FONT:
  1051.  
  1052.                 if(Mode == MODE_SCREEN_NORMAL || Mode == MODE_WB_NORMAL)
  1053.                     DoInfo(Object,Mode,Type,ConfigFont[Numeral[0]]);
  1054.  
  1055.                 break;
  1056.  
  1057.             case INFO_ONLINECOST:
  1058.  
  1059.                 strcpy(MiniBuffer,String[0]);
  1060.                 strcat(MiniBuffer,"          ");
  1061.  
  1062.                 MiniBuffer[8] = 0;
  1063.  
  1064.                 DoInfo(Object,Mode,INFO_ONLINETIME,MiniBuffer);
  1065.  
  1066.                 break;
  1067.  
  1068.             case INFO_CURRENTTIME:
  1069.             case INFO_ONLINETIME:
  1070.  
  1071.                 SPrintf(MiniBuffer,"%02ld:%02ld:%02ld",Numeral[0],Numeral[1],Numeral[2]);
  1072.  
  1073.                 DoInfo(Object,Mode,Type,MiniBuffer);
  1074.  
  1075.                 break;
  1076.  
  1077.             case INFO_BAUDRATE:
  1078.  
  1079.                 if(LocaleBase)
  1080.                     SPrintf(MiniBuffer,"%lD        ",Numeral[0]);
  1081.                 else
  1082.                     SPrintf(MiniBuffer,"%ld        ",Numeral[0]);
  1083.  
  1084.                 MiniBuffer[7] = 0;
  1085.  
  1086.                 DoInfo(Object,Mode,Type,MiniBuffer);
  1087.  
  1088.                 break;
  1089.  
  1090.             case INFO_PROTOCOL:
  1091.             case INFO_EMULATION:
  1092.  
  1093.                 strcpy(MiniBuffer,String[0]);
  1094.  
  1095.                 strcat(MiniBuffer,"           ");
  1096.  
  1097.                 MiniBuffer[12] = 0;
  1098.  
  1099.                 DoInfo(Object,Mode,Type,MiniBuffer);
  1100.  
  1101.                 break;
  1102.  
  1103.             case INFO_PARAMETERS:
  1104.  
  1105.                 if(Mode == MODE_SCREEN_COMPRESSED || Mode == MODE_WB_COMPRESSED)
  1106.                 {
  1107.                     STATIC UBYTE Parities[5] =
  1108.                     {
  1109.                         'N','E','O','M','S'
  1110.                     };
  1111.  
  1112.                     SPrintf(MiniBuffer,"%ld-%lc-%ld",Numeral[0],Parities[Numeral[1]],Numeral[2]);
  1113.                 }
  1114.                 else
  1115.                     SPrintf(MiniBuffer,"%ld-%s-%ld",Numeral[0],ConfigParity[Numeral[1]],Numeral[2]);
  1116.  
  1117.                 DoInfo(Object,Mode,Type,MiniBuffer);
  1118.  
  1119.                 break;
  1120.         }
  1121.  
  1122.         va_end(VarArgs);
  1123.     }
  1124. }
  1125.  
  1126.     /* Raise(UWORD Colour):
  1127.      *
  1128.      *    Make an RGB value brighter.
  1129.      */
  1130.  
  1131. STATIC UWORD __inline
  1132. Raise(UWORD Colour)
  1133. {
  1134.     UWORD R,G,B;
  1135.  
  1136.     R =  (Colour >> 8)        + 4;
  1137.     G = ((Colour >> 4) & 0xF) + 4;
  1138.     B = ((Colour     ) & 0xF) + 4;
  1139.  
  1140.     if(R > 15)
  1141.         R = 15;
  1142.  
  1143.     if(G > 15)
  1144.         G = 15;
  1145.  
  1146.     if(B > 15)
  1147.         B = 15;
  1148.  
  1149.     return((UWORD)(R << 8 | G << 4 | B));
  1150. }
  1151.  
  1152.     /* VisualBeep():
  1153.      *
  1154.      *    Handle the visual part of the display beep.
  1155.      */
  1156.  
  1157. STATIC BYTE
  1158. VisualBeep(VOID)
  1159. {
  1160.     struct UCopList    *UserCopperList;
  1161.  
  1162.         /* Create a user copper list. */
  1163.  
  1164.     if(UserCopperList = (struct UCopList *)AllocMem(sizeof(struct UCopList),MEMF_ANY|MEMF_CLEAR))
  1165.     {
  1166.             /* Initialize for 35 commands. */
  1167.  
  1168.         if(UCopperListInit(UserCopperList,1 + 16 + 1 + 16 + 1))
  1169.         {
  1170.             WORD i;
  1171.  
  1172.                 /* Wait until first line of window. */
  1173.  
  1174.             CWAIT(UserCopperList,Window -> TopEdge,0);
  1175.  
  1176.                 /* Set the light colours. */
  1177.  
  1178.             for(i = 0 ; i < 16 ; i++)
  1179.                 CMOVE(UserCopperList,custom . color[i],Raise(GetRGB4(Screen -> ViewPort . ColorMap,i)));
  1180.  
  1181.                 /* Wait until bottom of window. */
  1182.  
  1183.             CWAIT(UserCopperList,Window -> TopEdge + Window -> Height - 1,0);
  1184.  
  1185.                 /* Set the standard colours. */
  1186.  
  1187.             for(i = 0 ; i < 16 ; i++)
  1188.                 CMOVE(UserCopperList,custom . color[i],GetRGB4(Screen -> ViewPort . ColorMap,i));
  1189.  
  1190.                 /* Finish list. */
  1191.  
  1192.             CEND(UserCopperList);
  1193.  
  1194.                 /* Install user copper list... */
  1195.  
  1196.             Screen -> ViewPort . UCopIns = UserCopperList;
  1197.  
  1198.                 /* ...and display it. */
  1199.  
  1200.             RethinkDisplay();
  1201.  
  1202.             return(TRUE);
  1203.         }
  1204.         else
  1205.             FreeMem(UserCopperList,sizeof(struct UCopList));
  1206.     }
  1207.  
  1208.     return(FALSE);
  1209. }
  1210.  
  1211.     /* StatusDisplayServer(VOID):
  1212.      *
  1213.      *    Yet another asynchronous background task to display
  1214.      *    some information.
  1215.      */
  1216.  
  1217. STATIC VOID __saveds
  1218. StatusDisplayServer(VOID)
  1219. {
  1220.         /* Create the interface port. */
  1221.  
  1222.     if(StatusDisplayPort = CreateMsgPort())
  1223.     {
  1224.         struct UpdateMessage    *Msg;
  1225.         ULONG             Signals;
  1226.  
  1227.             /* Ring back... */
  1228.  
  1229.         Signal(StatusProcess,SIG_HANDSHAKE);
  1230.  
  1231.             /* Wait for messages or termination signal. */
  1232.  
  1233.         FOREVER
  1234.         {
  1235.             Signals = Wait(SIG_KILL | PORTMASK(StatusDisplayPort));
  1236.  
  1237.                 /* Termination? */
  1238.  
  1239.             if(Signals & SIG_KILL)
  1240.                 break;
  1241.  
  1242.                 /* Message arrival? */
  1243.  
  1244.             if(Signals & PORTMASK(StatusDisplayPort))
  1245.             {
  1246.                     /* Process all pending messages. */
  1247.  
  1248.                 while(Msg = (struct UpdateMessage *)GetMsg(StatusDisplayPort))
  1249.                 {
  1250.                     DoStatusInfo(Msg -> Object,Msg -> Mode,Msg -> Type,Msg -> VanillaMessage . mn_Node . ln_Name);
  1251.  
  1252.                     FreeVec(Msg);
  1253.                 }
  1254.             }
  1255.         }
  1256.  
  1257.             /* Remove all pending messages. */
  1258.  
  1259.         while(Msg = (struct UpdateMessage *)GetMsg(StatusDisplayPort))
  1260.             FreeVec(Msg);
  1261.  
  1262.             /* Remove the msgport. */
  1263.  
  1264.         DeleteMsgPort(StatusDisplayPort);
  1265.     }
  1266.  
  1267.         /* Lock & quit... */
  1268.  
  1269.     Forbid();
  1270.  
  1271.     Signal(StatusProcess,SIG_HANDSHAKE);
  1272.  
  1273.     RemTask(StatusDisplayTask = NULL);
  1274. }
  1275.  
  1276.     /* StatusServer():
  1277.      *
  1278.      *    Asynchronous process to continuosly display the current
  1279.      *    terminal settings.
  1280.      */
  1281.  
  1282. VOID __saveds
  1283. StatusServer()
  1284. {
  1285.     STATIC struct timeval     OnlineTime,
  1286.                  LastTime,
  1287.                  TempTime;
  1288.     STATIC BYTE         GotOnline        = FALSE,
  1289.                  WasOnline        = FALSE,
  1290.                  ShowPay        = FALSE,
  1291.                  FlagBit        = FALSE;
  1292.     STATIC LONG         SecCount        = 0,
  1293.                  MinCount        = 0,
  1294.                  BeepCount        = 0;
  1295.  
  1296.     struct TextBox        *BoxArray[4],
  1297.                 *BoxList = NULL,
  1298.                 *Box;
  1299.  
  1300.     struct RastPort        *RPort;
  1301.  
  1302.     APTR             SomeObject;
  1303.     struct ObjectCarrier     Carrier;
  1304.  
  1305.     struct timerequest    *StatusTimeRequest;
  1306.     struct MsgPort        *StatusTimePort;
  1307.  
  1308.     BYTE             Background        = FALSE,
  1309.                  FlashIt        = FALSE,
  1310.                  SetColours        = FALSE,
  1311.                  StandardColours    = TRUE,
  1312.                  KeepGoing        = TRUE,
  1313.                  Beeping        = FALSE,
  1314.                  StatusMode        = Config -> ScreenConfig -> StatusLine;
  1315.  
  1316.     BYTE             LastProtocol[40],
  1317.                  ProtocolBuffer[40],
  1318.                  LastEmulationName[40];
  1319.  
  1320.     BYTE             LastFont        = -1,
  1321.                  LastEmulation        = -1,
  1322.                  LastBitsPerChar    = -1,
  1323.                  LastParity        = -1,
  1324.                  LastStopBits        = -1,
  1325.                  LastStatus        = -1;
  1326.  
  1327.     LONG             LastBaud        = -1;
  1328.  
  1329.     LONG             i,
  1330.                  ThisHour,
  1331.                  ThisMinute,
  1332.                  BoxCounter = 0,
  1333.                  FullWidth;
  1334.     WORD             ColumnLeft[4],
  1335.                  ColumnWidth[4],
  1336.                  Max,
  1337.                  Len;
  1338.     BYTE             AllFine = TRUE;
  1339.     UBYTE             Mode;
  1340.  
  1341.     StatusLineWidth = 0;
  1342.  
  1343.     LastProtocol[0] = 0;
  1344.  
  1345.     LastEmulationName[0] = 0;
  1346.  
  1347.     LocalizeString(ConfigFont,MSG_TERMAUX_STANDARD_FONT_TXT,MSG_TERMAUX_IBM_FONT_TXT);
  1348.     LocalizeString(ConfigEmulation,MSG_TERMAUX_ANSI_VT102_TXT,MSG_TERMAUX_HEX_TXT);
  1349.     LocalizeString(ConfigParity,MSG_TERMAUX_NONE_TXT,MSG_TERMAUX_SPACE_TXT);
  1350.     LocalizeString(ConfigStatus,MSG_TERMAUX_READY_TXT,MSG_TERMAUX_HANG_UP_TXT);
  1351.  
  1352.     if(StatusWindow)
  1353.     {
  1354.         RPort = StatusWindow -> RPort;
  1355.  
  1356.             /* Render the information. */
  1357.  
  1358.         SZ_SizeSetup(Screen,&UserFont,TRUE);
  1359.  
  1360.         if(StatusMode == STATUSLINE_COMPRESSED)
  1361.         {
  1362.             StatusOffset = (Screen -> Width - 80 * UserFontWidth) / 2;
  1363.  
  1364.             SetAPen(RPort,DrawInfo -> dri_Pens[TEXTPEN]);
  1365.  
  1366.             RectFill(RPort,0,0,StatusWindow -> Width - 1,StatusWindow -> Height - 1);
  1367.  
  1368.             SetAPen(RPort,0);
  1369.             SetBPen(RPort,DrawInfo -> dri_Pens[TEXTPEN]);
  1370.         }
  1371.         else
  1372.         {
  1373.             SetAPen(RPort,DrawInfo -> dri_Pens[TEXTPEN]);
  1374.             SetBPen(RPort,0);
  1375.  
  1376.                 /* Draw a separating line. */
  1377.  
  1378.             Move(RPort,0,0);
  1379.             Draw(RPort,StatusWindow -> Width - 1,0);
  1380.  
  1381.             ColumnLeft[0] = SZ_LeftOffsetN(MSG_TERMSTATUSDISPLAY_STATUS_TXT,MSG_TERMSTATUSDISPLAY_FONT_TXT,-1);
  1382.             ColumnLeft[1] = SZ_LeftOffsetN(MSG_TERMSTATUSDISPLAY_PROTOCOL_TXT,MSG_TERMSTATUSDISPLAY_TERMINAL_TXT,-1);
  1383.             ColumnLeft[2] = SZ_LeftOffsetN(MSG_TERMSTATUSDISPLAY_BAUDRATE_TXT,MSG_TERMSTATUSDISPLAY_PARAMETERS_TXT,-1);
  1384.             ColumnLeft[3] = SZ_LeftOffsetN(MSG_TERMSTATUSDISPLAY_TIME_TXT,MSG_TERMSTATUSDISPLAY_ONLINE_TXT,-1);
  1385.  
  1386.             Max = 0;
  1387.  
  1388.             for(i = 0 ; ConfigStatus[i] ; i++)
  1389.             {
  1390.                 if((Len = SZ_BoxWidth(strlen(ConfigStatus[i]))) > Max)
  1391.                     Max = Len;
  1392.             }
  1393.  
  1394.             for(i = 0 ; ConfigFont[i] ; i++)
  1395.             {
  1396.                 if((Len = SZ_BoxWidth(strlen(ConfigFont[i]))) > Max)
  1397.                     Max = Len;
  1398.             }
  1399.  
  1400.             ColumnWidth[0] = Max;
  1401.  
  1402.             Max = SZ_BoxWidth(12);
  1403.  
  1404.             for(i = 0 ; ConfigEmulation[i] ; i++)
  1405.             {
  1406.                 if((Len = SZ_BoxWidth(strlen(ConfigEmulation[i]))) > Max)
  1407.                     Max = Len;
  1408.             }
  1409.  
  1410.             ColumnWidth[1] = Max;
  1411.  
  1412.             Max = SZ_BoxWidth(10);
  1413.  
  1414.             for(i = 0 ; ConfigParity[i] ; i++)
  1415.             {
  1416.                 if((Len = SZ_BoxWidth(4 + strlen(ConfigParity[i]))) > Max)
  1417.                     Max = Len;
  1418.             }
  1419.  
  1420.             ColumnWidth[2] = Max;
  1421.  
  1422.             ColumnWidth[3] = SZ_BoxWidth(8);
  1423.  
  1424.             FullWidth = 0;
  1425.  
  1426.             for(i = 0 ; i < 4 ; i++)
  1427.                 FullWidth += ColumnWidth[i] + ColumnLeft[i];
  1428.  
  1429.             FullWidth += 3 * InterWidth;
  1430.  
  1431.             if(FullWidth > Screen -> Width)
  1432.                 SZ_SetLeftEdge(ColumnLeft[0]);
  1433.             else
  1434.                 SZ_SetLeftEdge((Screen -> Width - FullWidth) / 2 + ColumnLeft[0]);
  1435.  
  1436.             SZ_SetAbsoluteTop(2);
  1437.             SZ_SetTopEdge(2);
  1438.  
  1439.             SZ_SetWidth(ColumnWidth[0]);
  1440.  
  1441.             BoxArray[BoxCounter++] = Box = SZ_CreateTextBox(&BoxList,
  1442.                 SZ_Lines,    2,
  1443.                 SZ_AutoWidth,    TRUE,
  1444.             TAG_DONE);
  1445.  
  1446.             SZ_SetBoxTitles(Box,LocaleString(MSG_TERMSTATUSDISPLAY_STATUS_TXT),LocaleString(MSG_TERMSTATUSDISPLAY_FONT_TXT),NULL);
  1447.  
  1448.             SZ_SetWidth(ColumnWidth[1]);
  1449.             SZ_AddLeftOffset(ColumnLeft[1]);
  1450.  
  1451.             BoxArray[BoxCounter++] = Box = SZ_CreateTextBox(&BoxList,
  1452.                 SZ_Lines,    2,
  1453.                 SZ_AutoWidth,    TRUE,
  1454.                 SZ_NewColumn,    TRUE,
  1455.             TAG_DONE);
  1456.  
  1457.             SZ_SetBoxTitles(Box,LocaleString(MSG_TERMSTATUSDISPLAY_PROTOCOL_TXT),LocaleString(MSG_TERMSTATUSDISPLAY_TERMINAL_TXT),NULL);
  1458.  
  1459.             SZ_SetWidth(ColumnWidth[2]);
  1460.             SZ_AddLeftOffset(ColumnLeft[2]);
  1461.  
  1462.             BoxArray[BoxCounter++] = Box = SZ_CreateTextBox(&BoxList,
  1463.                 SZ_Lines,    2,
  1464.                 SZ_AutoWidth,    TRUE,
  1465.                 SZ_NewColumn,    TRUE,
  1466.             TAG_DONE);
  1467.  
  1468.             SZ_SetBoxTitles(Box,LocaleString(MSG_TERMSTATUSDISPLAY_BAUDRATE_TXT),LocaleString(MSG_TERMSTATUSDISPLAY_PARAMETERS_TXT),NULL);
  1469.  
  1470.             SZ_SetWidth(ColumnWidth[3]);
  1471.             SZ_AddLeftOffset(ColumnLeft[3]);
  1472.  
  1473.             BoxArray[BoxCounter] = Box = SZ_CreateTextBox(&BoxList,
  1474.                 SZ_Lines,    2,
  1475.                 SZ_AutoWidth,    TRUE,
  1476.                 SZ_NewColumn,    TRUE,
  1477.             TAG_DONE);
  1478.  
  1479.             SZ_SetBoxTitles(Box,LocaleString(MSG_TERMSTATUSDISPLAY_TIME_TXT),LocaleString(MSG_TERMSTATUSDISPLAY_ONLINE_TXT),NULL);
  1480.  
  1481.             if(!Box)
  1482.                 AllFine = FALSE;
  1483.             else
  1484.                 SZ_DrawBoxes(RPort,BoxList);
  1485.         }
  1486.     }
  1487.     else
  1488.     {
  1489.         if(Config -> ScreenConfig -> UseWorkbench && StatusGadget)
  1490.             AllFine = TRUE;
  1491.     }
  1492.  
  1493.         /* Everything fine so far? */
  1494.  
  1495.     if(AllFine)
  1496.     {
  1497.         Forbid();
  1498.  
  1499.             /* Create the display server task. */
  1500.  
  1501.         if(StatusDisplayTask = CreateTask("term status display task",5,StatusDisplayServer,4000))
  1502.         {
  1503.             ClrSignal(SIG_HANDSHAKE);
  1504.  
  1505.             Wait(SIG_HANDSHAKE);
  1506.         }
  1507.  
  1508.         Permit();
  1509.     }
  1510.  
  1511.         /* Is the display server task up and running? */
  1512.  
  1513.     if(StatusDisplayTask)
  1514.     {
  1515.             /* Create a timer device request. */
  1516.  
  1517.         if(StatusTimePort = (struct MsgPort *)CreateMsgPort())
  1518.         {
  1519.             if(StatusTimeRequest = (struct timerequest *)CreateIORequest(StatusTimePort,sizeof(struct timerequest)))
  1520.             {
  1521.                 if(!OpenDevice(TIMERNAME,UNIT_VBLANK,StatusTimeRequest,0))
  1522.                 {
  1523.                         /* Signal our father process
  1524.                          * that we're running.
  1525.                          */
  1526.  
  1527.                     Signal(ThisProcess,SIG_HANDSHAKE);
  1528.  
  1529.                     if(StatusWindow)
  1530.                     {
  1531.                         if(StatusMode == STATUSLINE_COMPRESSED)
  1532.                         {
  1533.                             Mode = MODE_SCREEN_COMPRESSED;
  1534.  
  1535.                             SomeObject = RPort;
  1536.                         }
  1537.                         else
  1538.                         {
  1539.                             Mode = MODE_SCREEN_NORMAL;
  1540.  
  1541.                             Carrier . RPort        = RPort;
  1542.                             Carrier . BoxArray    = BoxArray;
  1543.  
  1544.                             SomeObject = &Carrier;
  1545.                         }
  1546.  
  1547.                         UpdateInfo(SomeObject,Mode,INFO_ONLINETIME,0,0,0);
  1548.                     }
  1549.                     else
  1550.                     {
  1551.                         if(StatusGadget)
  1552.                         {
  1553.                             SomeObject = StatusGadget;
  1554.  
  1555.                             if(StatusMode == STATUSLINE_COMPRESSED)
  1556.                                 Mode = MODE_WB_COMPRESSED;
  1557.                             else
  1558.                                 Mode = MODE_WB_NORMAL;
  1559.  
  1560.                             UpdateInfo(SomeObject,Mode,INFO_ONLINETIME,0,0,0);
  1561.                         }
  1562.                         else
  1563.                             SomeObject = NULL;
  1564.                     }
  1565.  
  1566.                         /* Keep on displaying. */
  1567.  
  1568.                     while(KeepGoing)
  1569.                     {
  1570.                             /* Are we to quit? */
  1571.  
  1572.                         if(CheckSignal(SIG_KILL))
  1573.                             KeepGoing = FALSE;
  1574.  
  1575.                             /* Get the current time. */
  1576.  
  1577.                         StatusTimeRequest -> tr_node . io_Command = TR_GETSYSTIME;
  1578.  
  1579.                         DoIO(StatusTimeRequest);
  1580.  
  1581.                             /* A connection has just
  1582.                              * been established.
  1583.                              */
  1584.  
  1585.                         if(Online && !GotOnline)
  1586.                         {
  1587.                             OnlineTime = StatusTimeRequest -> tr_time;
  1588.  
  1589.                             GotOnline = TRUE;
  1590.  
  1591.                             SecCount = 0;
  1592.  
  1593.                             FlagBit = FALSE;
  1594.                         }
  1595.  
  1596.                             /* Print the current time. */
  1597.  
  1598.                         ThisHour    = (StatusTimeRequest -> tr_time . tv_secs % 86400) / 3600;
  1599.                         ThisMinute    = (StatusTimeRequest -> tr_time . tv_secs % 3600) / 60;
  1600.  
  1601.                         UpdateInfo(SomeObject,Mode,INFO_CURRENTTIME,ThisHour,ThisMinute,StatusTimeRequest -> tr_time . tv_secs % 60);
  1602.  
  1603.                         if(Online)
  1604.                         {
  1605.                             WasOnline = TRUE;
  1606.  
  1607.                                 /* Look if we are to tell
  1608.                                  * the main process to take
  1609.                                  * a look at the carrier
  1610.                                  * signal.
  1611.                                  */
  1612.  
  1613.                             if(Config -> SerialConfig -> CheckCarrier && !(SecCount & 1) && ReadPort && Status == STATUS_READY)
  1614.                                 Signal(ThisProcess,SIG_CHECK);
  1615.  
  1616.                             if(ChosenEntry)
  1617.                             {
  1618.                                 if(!(ThisMinute % 10) && !(StatusTimeRequest -> tr_time . tv_secs % 60))
  1619.                                 {
  1620.                                     ChosenInUse = TRUE;
  1621.  
  1622.                                     SelectTime(ChosenEntry);
  1623.  
  1624.                                     ChosenInUse = FALSE;
  1625.                                 }
  1626.  
  1627.                                 if(!CurrentPay)
  1628.                                     CurrentPay = PayPerUnit[DT_FIRST_UNIT];
  1629.  
  1630.                                 FlagBit ^= TRUE;
  1631.  
  1632.                                 if(!FlagBit)
  1633.                                 {
  1634.                                     if(SecPerUnit[WhichUnit] && SecCount == SecPerUnit[WhichUnit])
  1635.                                     {
  1636.                                         SecCount = 0;
  1637.  
  1638.                                         WhichUnit = DT_NEXT_UNIT;
  1639.  
  1640.                                         CurrentPay += PayPerUnit[DT_NEXT_UNIT];
  1641.                                     }
  1642.  
  1643.                                     SecCount++;
  1644.                                 }
  1645.                             }
  1646.  
  1647.                                 /* Show the time
  1648.                                  * we have been online
  1649.                                  * yet.
  1650.                                  */
  1651.  
  1652.                             TempTime = StatusTimeRequest -> tr_time;
  1653.  
  1654.                             SubTime(&TempTime,&OnlineTime);
  1655.  
  1656.                             if(StatusTimeRequest -> tr_time . tv_secs != LastTime . tv_secs)
  1657.                             {
  1658.                                 LastTime = StatusTimeRequest -> tr_time;
  1659.  
  1660.                                 switch(Config -> ScreenConfig -> TimeMode)
  1661.                                 {
  1662.                                     case ONLINETIME_TIME:    ShowPay = FALSE;
  1663.                                                 break;
  1664.  
  1665.                                     case ONLINETIME_COST:    ShowPay = TRUE;
  1666.                                                 break;
  1667.  
  1668.                                     case ONLINETIME_BOTH:    if(TempTime . tv_secs && !(TempTime . tv_secs % 5))
  1669.                                                     ShowPay ^= TRUE;
  1670.  
  1671.                                                 break;
  1672.                                 }
  1673.  
  1674.                                 if(ShowPay && ChosenEntry)
  1675.                                     UpdateInfo(SomeObject,Mode,INFO_ONLINECOST,CreateSum(CurrentPay,FALSE));
  1676.                                 else
  1677.                                     UpdateInfo(SomeObject,Mode,INFO_ONLINETIME,(TempTime . tv_secs % 86400) / 3600,(TempTime . tv_secs % 3600) / 60,TempTime . tv_secs % 60);
  1678.  
  1679.                                 OnlineMinutes = TempTime . tv_secs / 60;
  1680.                             }
  1681.                         }
  1682.                         else
  1683.                         {
  1684.                             if(WasOnline)
  1685.                             {
  1686.                                 WasOnline = FALSE;
  1687.  
  1688.                                 UpdateInfo(SomeObject,Mode,INFO_ONLINETIME,(TempTime . tv_secs % 86400) / 3600,(TempTime . tv_secs % 3600) / 60,TempTime . tv_secs % 60);
  1689.                             }
  1690.  
  1691.                             if(GotOnline)
  1692.                                 GotOnline = FALSE;
  1693.                         }
  1694.  
  1695.                             /* Take care of the visual beep
  1696.                              * if enabled.
  1697.                              */
  1698.  
  1699.                         if(Beeping)
  1700.                         {
  1701.                             if(!(BeepCount--))
  1702.                             {
  1703.                                 Beeping = FALSE;
  1704.  
  1705.                                     /* Remove the copper list. */
  1706.  
  1707.                                 FreeVPortCopLists(&Screen -> ViewPort);
  1708.  
  1709.                                     /* Really remove it. */
  1710.  
  1711.                                 RemakeDisplay();
  1712.  
  1713.                                     /* Clear the signal bit. */
  1714.  
  1715.                                 ClrSignal(SIG_BELL);
  1716.                             }
  1717.                         }
  1718.  
  1719.                             /* Are we to show a visual beep? */
  1720.  
  1721.                         if(CheckSignal(SIG_BELL))
  1722.                         {
  1723.                             if(Config -> TerminalConfig -> BellMode == BELL_SYSTEM)
  1724.                                 DisplayBeep(Window -> WScreen);
  1725.                             else
  1726.                             {
  1727.                                 if(Screen && !Config -> ScreenConfig -> UseWorkbench && !Beeping && (Config -> TerminalConfig -> BellMode == BELL_VISIBLE || Config -> TerminalConfig -> BellMode == BELL_BOTH))
  1728.                                 {
  1729.                                     if(VisualBeep())
  1730.                                     {
  1731.                                         Beeping = TRUE;
  1732.  
  1733.                                         BeepCount = 1;
  1734.                                     }
  1735.                                 }
  1736.                             }
  1737.                         }
  1738.  
  1739.                             /* Display the current terminal
  1740.                              * status.
  1741.                              */
  1742.  
  1743.                         if(LastStatus != Status)
  1744.                             UpdateInfo(SomeObject,Mode,INFO_STATUS,LastStatus = Status);
  1745.  
  1746.                             /* Show the current transfer
  1747.                              * protocol.
  1748.                              */
  1749.  
  1750.                         if(strcmp(LastProtocol,FilePart(Config -> FileConfig -> ProtocolFileName)))
  1751.                         {
  1752.                             strcpy(LastProtocol,FilePart(Config -> FileConfig -> ProtocolFileName));
  1753.  
  1754.                             if((Len = strlen(LastProtocol)) > 3)
  1755.                             {
  1756.                                 strcpy(ProtocolBuffer,&LastProtocol[3]);
  1757.  
  1758.                                 for(i = 0 ; i < Len - 3 ; i++)
  1759.                                 {
  1760.                                     if(ProtocolBuffer[i] == '.')
  1761.                                     {
  1762.                                         ProtocolBuffer[i] = 0;
  1763.  
  1764.                                         break;
  1765.                                     }
  1766.                                 }
  1767.  
  1768.                                 UpdateInfo(SomeObject,Mode,INFO_PROTOCOL,ProtocolBuffer);
  1769.                             }
  1770.                         }
  1771.  
  1772.                             /* Show the current baud
  1773.                              * rate.
  1774.                              */
  1775.  
  1776.                         if(LastBaud != Config -> SerialConfig -> BaudRate)
  1777.                             UpdateInfo(SomeObject,Mode,INFO_BAUDRATE,LastBaud = Config -> SerialConfig -> BaudRate);
  1778.  
  1779.                             /* Show the current
  1780.                              * terminal font.
  1781.                              */
  1782.  
  1783.                         if(LastFont != Config -> TerminalConfig -> FontMode)
  1784.                         {
  1785.                             LastFont = Config -> TerminalConfig -> FontMode;
  1786.  
  1787.                             UpdateInfo(SomeObject,Mode,INFO_FONT,LastFont != FONT_STANDARD);
  1788.                         }
  1789.  
  1790.                             /* Show the current terminal
  1791.                              * emulation.
  1792.                              */
  1793.  
  1794.                         if(LastEmulation != Config -> TerminalConfig -> EmulationMode || (Config -> TerminalConfig -> EmulationMode == EMULATION_EXTERNAL && Stricmp(EmulationName,LastEmulationName)))
  1795.                         {
  1796.                             LastEmulation = Config -> TerminalConfig -> EmulationMode;
  1797.  
  1798.                             if(Config -> TerminalConfig -> EmulationMode == EMULATION_EXTERNAL)
  1799.                             {
  1800.                                 UpdateInfo(SomeObject,Mode,INFO_EMULATION,EmulationName);
  1801.  
  1802.                                 strcpy(LastEmulationName,EmulationName);
  1803.                             }
  1804.                             else
  1805.                                 UpdateInfo(SomeObject,Mode,INFO_EMULATION,ConfigEmulation[LastEmulation]);
  1806.                         }
  1807.  
  1808.                             /* Show the current serial
  1809.                              * parameters (parity, etc).
  1810.                              */
  1811.  
  1812.                         if(LastBitsPerChar != Config -> SerialConfig -> BitsPerChar || LastParity != Config -> SerialConfig -> Parity || LastStopBits != Config -> SerialConfig -> StopBits)
  1813.                         {
  1814.                             LastBitsPerChar    = Config -> SerialConfig -> BitsPerChar;
  1815.                             LastParity    = Config -> SerialConfig -> Parity;
  1816.                             LastStopBits    = Config -> SerialConfig -> StopBits;
  1817.  
  1818.                             UpdateInfo(SomeObject,Mode,INFO_PARAMETERS,LastBitsPerChar,LastParity,LastStopBits);
  1819.                         }
  1820.  
  1821.                             /* Wait another half a second. */
  1822.  
  1823.                         if(KeepGoing)
  1824.                         {
  1825.                             ULONG Mask;
  1826.  
  1827.                             StatusTimeRequest -> tr_node . io_Command    = TR_ADDREQUEST;
  1828.                             StatusTimeRequest -> tr_time . tv_secs        = 0;
  1829.                             StatusTimeRequest -> tr_time . tv_micro        = MILLION / 2;
  1830.  
  1831.                             SendIO(StatusTimeRequest);
  1832.  
  1833.                             FOREVER
  1834.                             {
  1835.                                 Mask = Wait(SIG_BELL | PORTMASK(StatusTimePort));
  1836.  
  1837.                                 if(Mask & SIG_BELL)
  1838.                                 {
  1839.                                     if(Config -> TerminalConfig -> BellMode == BELL_SYSTEM)
  1840.                                         DisplayBeep(Window -> WScreen);
  1841.                                     else
  1842.                                     {
  1843.                                         if(Screen && !Config -> ScreenConfig -> UseWorkbench && !Beeping && (Config -> TerminalConfig -> BellMode == BELL_VISIBLE || Config -> TerminalConfig -> BellMode == BELL_BOTH))
  1844.                                         {
  1845.                                             if(VisualBeep())
  1846.                                             {
  1847.                                                 Beeping = TRUE;
  1848.  
  1849.                                                 BeepCount = 1;
  1850.                                             }
  1851.                                         }
  1852.                                     }
  1853.                                 }
  1854.  
  1855.                                 if(Mask & PORTMASK(StatusTimePort))
  1856.                                 {
  1857.                                     WaitIO(StatusTimeRequest);
  1858.  
  1859.                                     break;
  1860.                                 }
  1861.                             }
  1862.  
  1863.                                 /* Count up to a minute. */
  1864.  
  1865.                             if(MinCount++ == 120)
  1866.                             {
  1867.                                 MinCount = 0;
  1868.  
  1869.                                     /* Time limit present? */
  1870.  
  1871.                                 if(LimitCount > 0)
  1872.                                     LimitCount--;
  1873.  
  1874.                                     /* Limit reached? */
  1875.  
  1876.                                 if(!LimitCount)
  1877.                                     Signal(ThisProcess,SIG_CHECK);
  1878.                             }
  1879.                         }
  1880.  
  1881.                             /* Make the colours blink. */
  1882.  
  1883.                         if(Screen && !Config -> ScreenConfig -> UseWorkbench)
  1884.                         {
  1885.                             if(Screen == IntuitionBase -> FirstScreen)
  1886.                             {
  1887.                                     /* No main screen window active? */
  1888.     
  1889.                                 if(StatusWindow)
  1890.                                 {
  1891.                                     if(!(Window -> Flags & WFLG_WINDOWACTIVE) && !(StatusWindow -> Flags & WFLG_WINDOWACTIVE))
  1892.                                         StandardColours = TRUE;
  1893.                                 }
  1894.                                 else
  1895.                                 {
  1896.                                     if(!(Window -> Flags & WFLG_WINDOWACTIVE))
  1897.                                         StandardColours = TRUE;
  1898.                                 }
  1899.     
  1900.                                     /* Menu button pressed or window disabled? */
  1901.     
  1902.                                 if(Window -> Flags & (WFLG_MENUSTATE | WFLG_INREQUEST))
  1903.                                     StandardColours = TRUE;
  1904.     
  1905.                                     /* User is currently dragging the
  1906.                                      * mouse in order to mark something
  1907.                                      * on the screen?
  1908.                                      */
  1909.     
  1910.                                 if(Marking)
  1911.                                     StandardColours = TRUE;
  1912.     
  1913.                                 Background = FALSE;
  1914.                             }
  1915.                             else
  1916.                             {
  1917.                                 if(!Background)
  1918.                                     StandardColours = TRUE;
  1919.     
  1920.                                 Background = TRUE;
  1921.                             }
  1922.     
  1923.                             if(StandardColours)
  1924.                             {
  1925.                                 if(!SetColours)
  1926.                                 {
  1927.                                     LoadRGB4(VPort,Config -> ScreenConfig -> Colours,16);
  1928.     
  1929.                                     SetColours = TRUE;
  1930.                                 }
  1931.     
  1932.                                 StandardColours = FlashIt = FALSE;
  1933.                             }
  1934.                             else
  1935.                             {
  1936.                                     /* Are we to flash the display? */
  1937.     
  1938.                                 if(Config -> ScreenConfig -> Blinking)
  1939.                                 {
  1940.                                     if(Screen == IntuitionBase -> FirstScreen)
  1941.                                     {
  1942.                                         if(FlashIt)
  1943.                                         {
  1944.                                             LoadRGB4(VPort,BlinkColours,16);
  1945.     
  1946.                                             SetColours = FALSE;
  1947.                                         }
  1948.                                         else
  1949.                                         {
  1950.                                             LoadRGB4(VPort,Config -> ScreenConfig -> Colours,16);
  1951.     
  1952.                                             SetColours = TRUE;
  1953.                                         }
  1954.                                     }
  1955.     
  1956.                                     FlashIt ^= TRUE;
  1957.                                 }
  1958.                             }
  1959.                         }
  1960.                     }
  1961.  
  1962.                     CloseDevice(StatusTimeRequest);
  1963.                 }
  1964.  
  1965.                 DeleteIORequest(StatusTimeRequest);
  1966.             }
  1967.  
  1968.             DeleteMsgPort(StatusTimePort);
  1969.         }
  1970.  
  1971.         if(StatusDisplayTask)
  1972.         {
  1973.             Forbid();
  1974.  
  1975.             Signal(StatusDisplayTask,SIG_KILL);
  1976.  
  1977.             ClrSignal(SIG_HANDSHAKE);
  1978.  
  1979.             Wait(SIG_HANDSHAKE);
  1980.  
  1981.             Permit();
  1982.         }
  1983.  
  1984.         if(BoxList)
  1985.             SZ_FreeBoxes(BoxList);
  1986.     }
  1987.  
  1988.         /* Signal the father process that we're done
  1989.          * and quietly remove ourselves.
  1990.          */
  1991.  
  1992.     Forbid();
  1993.  
  1994.     Signal(ThisProcess,SIG_HANDSHAKE);
  1995.  
  1996.     StatusProcess = NULL;
  1997. }
  1998.