/*ProfiPacket - packet radio terminal program
  Copyright (C) 1999  Alexander Feigl

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

  Author:

  Alexander Feigl
  Burachstraße 51

  D-88250 Weingarten

  Mail : Alexander.Feigl@gmx.de
*/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "GUIProtos.h"
#include "global.h"
#include "MHeard.h"

#include <libraries/mui.h>

#include <libraries/asl.h>

#include <devices/timer.h>

#include <exec/lists.h>
#include <exec/memory.h>

#include <dos/exall.h>

#include <clib/muimaster_protos.h>
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/alib_protos.h>
#include <clib/intuition_protos.h>
#include <clib/utility_protos.h>

#ifdef __GNUC__


extern void *DOSBase;
extern void *SysBase;
extern void *IntuitionBase;
extern void *UtilityBase;
extern void *MUIMasterBase;

#define NO_INLINE_STDARG
#include <inline/muimaster.h>
#include <inline/dos.h>
#include <inline/exec.h>
#include <inline/intuition.h>
#include <inline/utility.h>
#undef RawDoFmt
#endif

struct MHeardPlus

  {
   struct MHeardEntry MHeard;
   unsigned char TNCPort[16];
   unsigned char Time[64];
   unsigned char ControlPackets[16];
   unsigned char RRPackets[16];
   unsigned char REJPackets[16];
   unsigned char RNRPackets[16];
   unsigned char IPackets[16];
   unsigned char IBytes[16];
  };

struct MHeardSum
  {
   unsigned char Call[16];
   unsigned long Time[3];
   unsigned long TNC;
   unsigned long Port;
     signed long QRGTx[2];
     signed long QRGTotal[2];


   unsigned char StrTime[16];
   unsigned char StrPort[16];
   unsigned char StrQRGTx[16];
   unsigned char StrQRGTotal[16];
  };


#ifndef MAKE_ID
#define MAKE_ID(a,b,c,d) ((ULONG) (a)<<24 | (ULONG) (b)<<16 | (ULONG) (c)<<8 | (ULONG) (d))
#endif

void FillHook(struct Hook *MyHook,void (*Function)(),void *FunctionData);


void GUIMH_MHeardLControl(struct Hook *MyHook,unsigned long *Param,void *Object,
                          void *Data);


void *GUIMH_MHeardLConstruct(struct Hook *MyHook,struct MHeardEntry *Param,void *Object,
                          void *Data);


void GUIMH_MHeardLDestruct(struct Hook *MyHook,struct MHeardPlus *Param,void *Object,
                          void *Data);


long GUIMH_MHeardLDisplay(struct Hook *MyHook,struct MHeardPlus *Param,unsigned char **Object,
                          void *Data);


signed long GUIMH_MHeardLCompare(struct Hook *MyHook,struct MHeardPlus *e1,struct MHeardPlus *e2,
                          void *Data);



void GUIMH_MHeardControl(struct Hook *MyHook,unsigned long *Param,void *Object,
                          void *Data);


void *GUIMH_MHeardConstruct(struct Hook *MyHook,struct MHeardEntry *Param,void *Object,
                          void *Data);


void GUIMH_MHeardDestruct(struct Hook *MyHook,struct MHeardSum *Param,void *Object,
                          void *Data);


long GUIMH_MHeardDisplay(struct Hook *MyHook,struct MHeardSum *Param,unsigned char **Object,
                          void *Data);


signed long GUIMH_MHeardCompare(struct Hook *MyHook,struct MHeardSum *e1,struct MHeardSum *e2,
                          void *Data);










#define mhobject(xx) GlobalArraysP->MHeardObjects[xx]
#define mlobject(xx) GlobalArraysP->MHeardLObjects[xx]


static void GUIMH_GetFBaud(struct MHeardEntry *MHeard,unsigned long *baudp)
{
 /* evaluate link quality*/

 unsigned long baud[2];

 baud[0]=0;
 baud[1]=0;

 if (MHeard->IConnect!=0)
  {
   if (MHeard->TimeConnect.ds_Days!=0)
       {
        signed long secs;

        secs=((MHeard->Time.ds_Days-MHeard->TimeConnect.ds_Days)*3600*24)+
             ((MHeard->Time.ds_Minute-MHeard->TimeConnect.ds_Minute)*60)+
             ((MHeard->Time.ds_Tick-MHeard->TimeConnect.ds_Tick)/50);
        if (secs!=0)
          {
           baud[0]= (MHeard->IConnect*8)/secs;
           if (secs>100)
            {
             baud[1]= ((MHeard->IConnect*800)/secs)%100;
            }
          }
       }
  }
 *(baudp)=baud[0];
 *(baudp+1)=baud[1];
}

static void GUIMH_MHeardLongUpdate(void)
{
struct MHeardEntry *mhe;
unsigned long i;

set(mlobject(0),MUIA_List_Quiet,TRUE);
DoMethod(mlobject(0),MUIM_List_Clear);
i=0;
while ( (mhe=QSO_MHeardEntry(i))!=NULL)
{
++i;
DoMethod(mlobject(0),MUIM_List_InsertSingle,mhe,MUIV_List_Insert_Sorted);
}
set(mlobject(0),MUIA_List_Quiet,FALSE);
}

static void GUIMH_MHeardUpdate(void)
{
 struct MHeardEntry *mhe;
 unsigned long i;

 set(mhobject(0),MUIA_List_Quiet,TRUE);
 DoMethod(mhobject(0),MUIM_List_Clear);
 i=0;
 while ( (mhe=QSO_MHeardEntry(i))!=NULL)
  {
   ++i;
   DoMethod(mhobject(0),MUIM_List_InsertSingle,mhe,MUIV_List_Insert_Sorted);
  }
 set(mhobject(0),MUIA_List_Quiet,FALSE);
}

void GUIMH_MHeardLong(void)
{

  if (MHeardLWindow==NULL)
   {

     GlobalArraysP->MHeardLArray[0]=GUI_String(533);
     GlobalArraysP->MHeardLArray[1]=GUI_String(534);
     GlobalArraysP->MHeardLArray[2]=GUI_String(536);
     GlobalArraysP->MHeardLArray[3]=GUI_String(535);
     GlobalArraysP->MHeardLArray[4]=NULL;


     FillHook(&HooksP->MHeardLControl,(void *) GUIMH_MHeardLControl,NULL);
     FillHook(&HooksP->MHeardLConstruct,(void *) GUIMH_MHeardLConstruct,NULL);
     FillHook(&HooksP->MHeardLDestruct,(void *) GUIMH_MHeardLDestruct,NULL);
     FillHook(&HooksP->MHeardLDisplay,(void *) GUIMH_MHeardLDisplay,NULL);
     FillHook(&HooksP->MHeardLCompare,(void *) GUIMH_MHeardLCompare,NULL);


     MHeardLWindow =
                 WindowObject,
                     MUIA_Window_Title, GUI_String(530),
                     MUIA_Window_ID   , MAKE_ID('M','H','D','L'),

                     WindowContents,

                       VGroup,
                         Child,mlobject(2)=ListviewObject,
                            InputListFrame,
                            MUIA_Listview_DefClickColumn,0,
                            MUIA_Listview_List,
                              mlobject(0)=ListObject,

                                MUIA_List_ConstructHook,&HooksP->MHeardLConstruct,
                                MUIA_List_DestructHook,&HooksP->MHeardLDestruct,
                                MUIA_List_DisplayHook,&HooksP->MHeardLDisplay,
                                MUIA_List_CompareHook,&HooksP->MHeardLCompare,
                                MUIA_List_Format,"BAR,BAR,BAR,BAR,BAR,BAR,BAR,BAR,BAR,",
                                MUIA_List_Title,TRUE,
                              End,
                            End,

                         Child,HGroup,


                                 Child,Label(GUI_String(532)),
                                 Child,mlobject(7)=Cycle(GlobalArraysP->MHeardLArray),

                             End,

                         Child,HGroup,

                             Child,Label2(GUI_String(525)),
                             Child,mlobject(3)=TextObject,
                                     MUIA_Text_SetMin,FALSE,
                                     MUIA_Background,MUII_TextBack,
                                     MUIA_Frame,MUIV_Frame_Text,
                                   End,

                            End,
                         Child,HGroup,
                             Child,Label2(GUI_String(526)),
                             Child,mlobject(4)=TextObject,
                                     MUIA_Text_SetMin,FALSE,
                                     MUIA_Background,MUII_TextBack,
                                     MUIA_Frame,MUIV_Frame_Text,
                                     MUIA_Text_PreParse,"\33c",
                                   End,

                             Child,Label2(GUI_String(528)),
                             Child,mlobject(5)=TextObject,
                                     MUIA_Text_SetMin,FALSE,
                                     MUIA_Background,MUII_TextBack,
                                     MUIA_Frame,MUIV_Frame_Text,
                                     MUIA_Text_PreParse,"\33c",
                                   End,

                             Child,Label2(GUI_String(527)),
                             Child,mlobject(6)=TextObject,
                                     MUIA_Text_SetMin,FALSE,
                                     MUIA_Background,MUII_TextBack,
                                     MUIA_Frame,MUIV_Frame_Text,
                                     MUIA_Text_PreParse,"\33c",
                                   End,

                            End,

                         Child,mlobject(1)=SimpleButton(GUI_String(531)),

                         End,
                     End;

    if (MHeardLWindow==NULL)
        {
            GUI_LowMemory();
            return;
        }

    DoMethod(Application,OM_ADDMEMBER,MHeardLWindow);








    set(mlobject(1),MUIA_CycleChain,1);
    set(mlobject(2),MUIA_CycleChain,1);
    set(mlobject(7),MUIA_CycleChain,1);



    DoMethod(MHeardLWindow,MUIM_Notify,MUIA_Window_CloseRequest,TRUE,
             MHeardLWindow,3,MUIM_CallHook,&HooksP->MHeardLControl,0);

    DoMethod(mlobject(1),MUIM_Notify,MUIA_Pressed,FALSE,
             MHeardLWindow,3,MUIM_CallHook,&HooksP->MHeardLControl,1);

    DoMethod(mlobject(0),MUIM_Notify,MUIA_List_Active,MUIV_EveryTime,
             mlobject(0),4,MUIM_CallHook,&HooksP->MHeardLControl,2,MUIV_TriggerValue);

    DoMethod(mlobject(2),MUIM_Notify,MUIA_Listview_DoubleClick,MUIV_EveryTime,
             mlobject(2),3,MUIM_CallHook,&HooksP->MHeardLControl,3);

    DoMethod(mlobject(7),MUIM_Notify,MUIA_Cycle_Active,MUIV_EveryTime,
             MHeardLWindow,3,MUIM_CallHook,&HooksP->MHeardLControl,1);
   }


 GUIMH_MHeardLongUpdate();

  {
   unsigned long status;

   get(MHeardLWindow,MUIA_Window_Open,&status);
   if (status==TRUE) return;
  }

 set(MHeardLWindow,MUIA_Window_Open,TRUE);
 return;
}

void GUIMH_MHeardLControl(struct Hook *MyHook,unsigned long *Param,void *Object,
                         void *Data)
{


 switch (*(Param))
  {
   case 0:
    set (MHeardLWindow,MUIA_Window_Open,FALSE);
    break;
   case 1:
    GUIMH_MHeardLongUpdate();
    break;
   case 2:
     {
      unsigned long actent;
      struct MHeardPlus *entry;

      GetAttr(MUIA_List_Active,Object,&actent);
      if (actent==MUIV_List_Active_Off) break;
      DoMethod(Object,MUIM_List_GetEntry,actent,&entry);
      if (entry==NULL) break;
      set(mlobject(3),MUIA_Text_Contents,(ULONG) entry->MHeard.Path);
       {
        /* evaluate link quality*/

        unsigned long paclen;
        unsigned long baud[2];

        paclen=0;



        if ( (entry->MHeard.IPackets!=0) && (entry->MHeard.IBytes!=0))
         {
          paclen=entry->MHeard.IBytes/entry->MHeard.IPackets;

         }

        GUIMH_GetFBaud(&entry->MHeard,baud);

         {
          unsigned char tempo[16];
          RawDoFmt("%ld",&paclen,PutRawDoFmt,tempo);
          set(mlobject(4),MUIA_Text_Contents,(ULONG) tempo);
          RawDoFmt("%ld.%02ld",baud,PutRawDoFmt,tempo);
          set(mlobject(5),MUIA_Text_Contents,(ULONG) tempo);
         }


        if (entry->MHeard.FirstTime.ds_Days!=0)
         {
          unsigned char tempo[64];
          unsigned long array[3];
          array[0]=entry->MHeard.FirstTime.ds_Minute/60;
          array[1]=entry->MHeard.FirstTime.ds_Minute%60;
          array[2]=entry->MHeard.FirstTime.ds_Tick/50;
          RawDoFmt("%02ld:%02ld:%02ld",array,PutRawDoFmt,tempo);
          set (mlobject(6),MUIA_Text_Contents,(ULONG) tempo);
         }
         else
         {
          set (mlobject(6),MUIA_Text_Contents,(ULONG) "--:--:--");
         }


       }
      break;
     }
   case 3:
     {
      unsigned long actent;
      struct MHeardPlus *entry;

      GetAttr(MUIA_List_Active,Object,&actent);
      if (actent==MUIV_List_Active_Off) break;
      DoMethod(Object,MUIM_List_GetEntry,actent,&entry);
      if (entry==NULL) break;
      break;
     }
  }
 return;
}

void *GUIMH_MHeardLConstruct(struct Hook *MyHook,struct MHeardEntry *Param,void *Object,
                          void *Data)
{
 struct MHeardPlus *mhe;
 mhe=AllocVec(sizeof(struct MHeardPlus),1);
 if (mhe==NULL) return(NULL);
 CopyMem(Param,&mhe->MHeard,sizeof(struct MHeardEntry));

  {
   unsigned long array[2];
   array[0]=mhe->MHeard.TNCNumber+1;
   array[1]=mhe->MHeard.PortNumber;
   RawDoFmt("%ld / %ld",array,PutRawDoFmt,mhe->TNCPort);
  }
  {
   unsigned long array[3];
   array[0]=mhe->MHeard.Time.ds_Minute/60;
   array[1]=mhe->MHeard.Time.ds_Minute%60;
   array[2]=mhe->MHeard.Time.ds_Tick/50;
   RawDoFmt("%02ld:%02ld:%02ld",array,PutRawDoFmt,mhe->Time);
  }
 RawDoFmt("%ld",&mhe->MHeard.ControlPackets,PutRawDoFmt,mhe->ControlPackets);
 RawDoFmt("%ld",&mhe->MHeard.RRPackets,PutRawDoFmt,mhe->RRPackets);
 RawDoFmt("%ld",&mhe->MHeard.REJPackets,PutRawDoFmt,mhe->REJPackets);
 RawDoFmt("%ld",&mhe->MHeard.RNRPackets,PutRawDoFmt,mhe->RNRPackets);
 RawDoFmt("%ld",&mhe->MHeard.IPackets,PutRawDoFmt,mhe->IPackets);
 RawDoFmt("%ld",&mhe->MHeard.IBytes,PutRawDoFmt,mhe->IBytes);
 return(mhe);
}


void GUIMH_MHeardLDestruct(struct Hook *MyHook,struct MHeardPlus *Param,void *Object,
                          void *Data)
{
 if (Param!=NULL) FreeVec(Param);
 return;
}


long GUIMH_MHeardLDisplay(struct Hook *MyHook,struct MHeardPlus *Param,unsigned char **Object,
                          void *Data)
{
 if (Param==NULL)
  {
   unsigned char **array;
   array=Object;
   *(array++)=GUI_String(514);
   *(array++)=GUI_String(515);
   *(array++)=GUI_String(516);
   *(array++)=GUI_String(517);
   *(array++)=GUI_String(518);
   *(array++)=GUI_String(519);
   *(array++)=GUI_String(520);
   *(array++)=GUI_String(521);
   *(array++)=GUI_String(522);
   *(array++)=GUI_String(523);
   return(0);
  }

  {
   unsigned char **array;
   array=Object;
   *(array++)=Param->MHeard.FromCall;
   *(array++)=Param->MHeard.ToCall;
   *(array++)=Param->Time;
   *(array++)=Param->TNCPort;
   *(array++)=Param->ControlPackets;
   *(array++)=Param->RRPackets;
   *(array++)=Param->REJPackets;
   *(array++)=Param->RNRPackets;
   *(array++)=Param->IPackets;
   *(array++)=Param->IBytes;
   return(0);
  }

}

signed long GUIMH_MHeardLCompare(struct Hook *MyHook,struct MHeardPlus *e1,struct MHeardPlus *e2,
                          void *Data)
{
 unsigned long sorting;

 GetAttr(MUIA_Cycle_Active,mlobject(7),&sorting);

 switch (sorting)
  {
   case 0: /*time sorting*/
      if (e1->MHeard.Time.ds_Days!=e2->MHeard.Time.ds_Days)
        return (e2->MHeard.Time.ds_Days-e1->MHeard.Time.ds_Days);
      if (e1->MHeard.Time.ds_Minute!=e2->MHeard.Time.ds_Minute)
        return (e2->MHeard.Time.ds_Minute-e1->MHeard.Time.ds_Minute);
      if (e1->MHeard.Time.ds_Tick!=e2->MHeard.Time.ds_Tick)
        return (e2->MHeard.Time.ds_Tick-e1->MHeard.Time.ds_Tick);
      return(0);
   case 1: /*name sorting*/
      {
       signed char *sptr,*dptr;
       sptr=(signed char *) (e1->MHeard.FromCall);
       dptr=(signed char *) (e2->MHeard.FromCall);
       if (*sptr=='\0') return(-1);
       while ( *(sptr)!='\0')
        {
         if ( *(sptr++)!=*(dptr++) ) break;
        }
       return ( *(sptr-1)-*(dptr-1));
      }
    break;
   case 2: /*name sorting destination*/
      {
       signed char *sptr,*dptr;
       sptr=(signed char *) (e1->MHeard.ToCall);
       dptr=(signed char *) (e2->MHeard.ToCall);
       if (*sptr=='\0') return(-1);
       while ( *(sptr)!='\0')
        {
         if ( *(sptr++)!=*(dptr++) ) break;
        }
       return ( *(sptr-1)-*(dptr-1));
      }
    break;
   case 3: /*QRG sorting*/
     {
      unsigned long baud1[2];
      unsigned long baud2[2];
      GUIMH_GetFBaud(&e1->MHeard,baud1);
      GUIMH_GetFBaud(&e2->MHeard,baud2);
      if (baud1[0]!=baud2[0]) return (baud2[0]-baud1[0]);
      if (baud1[1]!=baud2[1]) return (baud2[1]-baud1[1]);
      if (e1->MHeard.IBytes!=e2->MHeard.IBytes)
         return( e2->MHeard.IBytes-e1->MHeard.IBytes);
      if (e1->MHeard.RRPackets!=e2->MHeard.RRPackets)
         return( e2->MHeard.RRPackets-e1->MHeard.RRPackets);
     }
    return(0);
    break;
  }

 return(0);
}

void GUIMH_MHeard(void)
{

  if (MHeardWindow==NULL)
   {

     GlobalArraysP->MHeardArray[0]=GUI_String(533);
     GlobalArraysP->MHeardArray[1]=GUI_String(534);
     GlobalArraysP->MHeardArray[2]=GUI_String(535);
     GlobalArraysP->MHeardArray[3]=NULL;


     FillHook(&HooksP->MHeardControl,(void *) GUIMH_MHeardControl,NULL);
     FillHook(&HooksP->MHeardConstruct,(void *) GUIMH_MHeardConstruct,NULL);
     FillHook(&HooksP->MHeardDestruct,(void *) GUIMH_MHeardDestruct,NULL);
     FillHook(&HooksP->MHeardDisplay,(void *) GUIMH_MHeardDisplay,NULL);
     FillHook(&HooksP->MHeardCompare,(void *) GUIMH_MHeardCompare,NULL);


     MHeardWindow =
                 WindowObject,
                     MUIA_Window_Title, GUI_String(529),
                     MUIA_Window_ID   , MAKE_ID('M','H','D','S'),

                     WindowContents,

                       VGroup,
                         Child,mhobject(2)=ListviewObject,
                            InputListFrame,
                            MUIA_Listview_DefClickColumn,0,
                            MUIA_Listview_List,
                              mhobject(0)=ListObject,

                                MUIA_List_ConstructHook,&HooksP->MHeardConstruct,
                                MUIA_List_DestructHook,&HooksP->MHeardDestruct,
                                MUIA_List_DisplayHook,&HooksP->MHeardDisplay,
                                MUIA_List_CompareHook,&HooksP->MHeardCompare,
                                MUIA_List_Format,"BAR,BAR,BAR,BAR,",
                                MUIA_List_Title,TRUE,
                              End,
                            End,

                         Child,HGroup,


                                 Child,Label(GUI_String(532)),
                                 Child,mhobject(7)=Cycle(GlobalArraysP->MHeardArray),

                             End,

                   

                         Child,mhobject(1)=SimpleButton(GUI_String(531)),

                         End,
                     End;

    if (MHeardWindow==NULL)
        {
            GUI_LowMemory();
            return;
        }

    DoMethod(Application,OM_ADDMEMBER,MHeardWindow);








    set(mhobject(1),MUIA_CycleChain,1);
    set(mhobject(2),MUIA_CycleChain,1);
    set(mhobject(7),MUIA_CycleChain,1);



    DoMethod(MHeardWindow,MUIM_Notify,MUIA_Window_CloseRequest,TRUE,
             MHeardWindow,3,MUIM_CallHook,&HooksP->MHeardControl,0);

    DoMethod(mhobject(1),MUIM_Notify,MUIA_Pressed,FALSE,
             MHeardWindow,3,MUIM_CallHook,&HooksP->MHeardControl,1);

    DoMethod(mhobject(0),MUIM_Notify,MUIA_List_Active,MUIV_EveryTime,
             mhobject(0),4,MUIM_CallHook,&HooksP->MHeardControl,2,MUIV_TriggerValue);

    DoMethod(mhobject(2),MUIM_Notify,MUIA_Listview_DoubleClick,MUIV_EveryTime,
             mhobject(2),3,MUIM_CallHook,&HooksP->MHeardControl,3);

    DoMethod(mhobject(7),MUIM_Notify,MUIA_Cycle_Active,MUIV_EveryTime,
             MHeardWindow,3,MUIM_CallHook,&HooksP->MHeardControl,1);
   }


 GUIMH_MHeardUpdate();

  {
   unsigned long status;

   get(MHeardWindow,MUIA_Window_Open,&status);
   if (status==TRUE) return;
  }

 set(MHeardWindow,MUIA_Window_Open,TRUE);
}

void GUIMH_MHeardControl(struct Hook *MyHook,unsigned long *Param,void *Object,
                         void *Data)
{


 switch (*(Param))
  {
   case 0:
    set (MHeardWindow,MUIA_Window_Open,FALSE);
    break;
   case 1:
    GUIMH_MHeardUpdate();
    break;
   case 2:
    break;
   case 3:
     {
      unsigned long actent;
      struct MHeardPlus *entry;

      GetAttr(MUIA_List_Active,Object,&actent);
      if (actent==MUIV_List_Active_Off) break;
      DoMethod(Object,MUIM_List_GetEntry,actent,&entry);
      if (entry==NULL) break;
      break;
     }
  }
 return;
}

void *GUIMH_MHeardConstruct(struct Hook *MyHook,struct MHeardEntry *Param,void *Object,
                          void *Data)
{
 struct MHeardSum *mhe;

 unsigned long qrgtx[2];
 unsigned long qrgtot[2];

  {
   unsigned long i;
   struct MHeardSum *mhs;
   i=0;
   while (DoMethod(mhobject(0),MUIM_List_GetEntry,i++,&mhs),mhs!=NULL)
    {
     if (mhs->Port!=Param->PortNumber) continue;
     if (mhs->TNC!=(Param->TNCNumber+1)) continue;
     if (CompareString(mhs->Call,Param->FromCall)) return(NULL);
    }
  }

 mhe=AllocVec(sizeof(struct MHeardSum),1);
 if (mhe==NULL) return(NULL);

 CopyString(mhe->Call,Param->FromCall);
  {
   unsigned long array[2];
   mhe->TNC=Param->TNCNumber+1;
   mhe->Port=Param->PortNumber;
   array[0]=mhe->TNC;
   array[1]=mhe->Port;
   RawDoFmt("%ld / %ld",array,PutRawDoFmt,mhe->StrPort);
  }
  {
   unsigned long array[3];
   mhe->Time[0]=Param->Time.ds_Days;
   mhe->Time[1]=Param->Time.ds_Minute;
   mhe->Time[2]=Param->Time.ds_Tick;
   array[0]=mhe->Time[1]/60;
   array[1]=mhe->Time[1]%60;
   array[2]=mhe->Time[2]/50;
   RawDoFmt("%02ld:%02ld:%02ld",array,PutRawDoFmt,mhe->StrTime);
  }
  {
   struct MHeardEntry *mhp;
   unsigned long i;
   unsigned long tbaud[2];
   qrgtx[0]=0;
   qrgtot[0]=0;
   qrgtot[1]=0;
   qrgtx[1]=0;
   mhe->Time[0]=0;
   mhe->Time[1]=0;
   mhe->Time[2]=0;


   i=0;
   while ( (mhp=QSO_MHeardEntry(i++))!=NULL)
    {
     if (mhp->PortNumber!=Param->PortNumber) continue;
     if (mhp->TNCNumber!=Param->TNCNumber) continue;

     GUIMH_GetFBaud(mhp,tbaud);
     if (CompareString(mhp->FromCall,Param->FromCall))
      {
       qrgtx[0]+=tbaud[0];
       qrgtx[1]+=tbaud[1];
       qrgtot[0]+=tbaud[0];
       qrgtot[1]+=tbaud[1];
       if (mhp->Time.ds_Days>mhe->Time[0])
        {
         mhe->Time[0]=mhp->Time.ds_Days;
         mhe->Time[1]=mhp->Time.ds_Minute;
         mhe->Time[2]=mhp->Time.ds_Tick;
        }
        else
        {
         if (mhp->Time.ds_Days==mhe->Time[0])
          {
           if (mhp->Time.ds_Minute>mhe->Time[1])
            {
             mhe->Time[0]=mhp->Time.ds_Days;
             mhe->Time[1]=mhp->Time.ds_Minute;
             mhe->Time[2]=mhp->Time.ds_Tick;
            }
            else
             {
              if (mhp->Time.ds_Minute==mhe->Time[1])
               {
                if (mhp->Time.ds_Tick>mhe->Time[2])
                 {
                  mhe->Time[0]=mhp->Time.ds_Days;
                  mhe->Time[1]=mhp->Time.ds_Minute;
                  mhe->Time[2]=mhp->Time.ds_Tick;
                 }
               }
             }
          }
        }

      }
     if (CompareString(mhp->ToCall,Param->FromCall))
      {
       qrgtot[0]+=tbaud[0];
       qrgtot[1]+=tbaud[1];
      }
    }
   while (qrgtot[1]>=100) {qrgtot[1]-=100;qrgtot[0]++;}
   while (qrgtx[1]>=100) {qrgtx[1]-=100;qrgtx[1]++;};
  }

 mhe->QRGTx[0]=qrgtx[0];
 mhe->QRGTx[1]=qrgtx[1];
 mhe->QRGTotal[0]=qrgtot[0];
 mhe->QRGTotal[1]=qrgtot[1];

 RawDoFmt("%ld.%02ld",qrgtx,PutRawDoFmt,mhe->StrQRGTx);
 RawDoFmt("%ld.%02ld",qrgtot,PutRawDoFmt,mhe->StrQRGTotal);

  {
   unsigned long array[3];
   array[0]=mhe->Time[1]/60;
   array[1]=mhe->Time[1]%60;
   array[2]=mhe->Time[2]/50;
   RawDoFmt("%02ld:%02ld:%02ld",array,PutRawDoFmt,mhe->StrTime);
  }


 return(mhe);
}


void GUIMH_MHeardDestruct(struct Hook *MyHook,struct MHeardSum *Param,void *Object,
                          void *Data)
{
 if (Param!=NULL) FreeVec(Param);
 return;
}


long GUIMH_MHeardDisplay(struct Hook *MyHook,struct MHeardSum *Param,unsigned char **Object,
                          void *Data)
{
 if (Param==NULL)
  {
   unsigned char **array;
   array=Object;
   *(array++)=GUI_String(524);
   *(array++)=GUI_String(516);
   *(array++)=GUI_String(517);
   *(array++)=GUI_String(537);
   *(array++)=GUI_String(538);
   return(0);
  }

  {
   unsigned char **array;
   array=Object;
   *(array++)=Param->Call;
   *(array++)=Param->StrTime;
   *(array++)=Param->StrPort;
   *(array++)=Param->StrQRGTx;
   *(array++)=Param->StrQRGTotal;
   return(0);
  }

}

signed long GUIMH_MHeardCompare(struct Hook *MyHook,struct MHeardSum *e1,struct MHeardSum *e2,
                          void *Data)
{
 unsigned long sorting;

 GetAttr(MUIA_Cycle_Active,mhobject(7),&sorting);

 switch (sorting)
  {
   case 0: /*time sorting*/
      if (e1->Time[0]!=e2->Time[0])
        return (e2->Time[0]-e1->Time[0]);
      if (e1->Time[1]!=e2->Time[1])
        return (e2->Time[1]-e1->Time[1]);
      if (e1->Time[2]!=e2->Time[2])
        return (e2->Time[2]-e1->Time[2]);
      return(0);
   case 1: /*name sorting*/
      {
       signed char *sptr,*dptr;
       sptr=(signed char *) (e1->Call);
       dptr=(signed char *) (e2->Call);
       if (*sptr=='\0') return(-1);
       while ( *(sptr)!='\0')
        {
         if ( *(sptr++)!=*(dptr++) ) break;
        }
       return ( *(sptr-1)-*(dptr-1));
      }
    break;
   case 2: /*QRG sorting*/
     {
      unsigned long baud1[2];
      unsigned long baud2[2];
      baud1[0]=e1->QRGTx[0];
      baud1[1]=e1->QRGTx[1];
      baud2[0]=e2->QRGTx[0];
      baud2[1]=e2->QRGTx[1];

      if (baud1[0]!=baud2[0]) return (baud2[0]-baud1[0]);
      if (baud1[1]!=baud2[1]) return (baud2[1]-baud1[1]);
      return(0);
     }

    break;
  }
 return(0);

}

