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