/*
   MainWindow.c : Windowing support for the linux trace toolkit.
   Copyright (C) 1999, 2000, 2001 Karim Yaghmour, Jean-Hugues Deschenes.
 
   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

   History :
      ROC   02/2000, Add Interrupt name printout
      K.Y., 22/08/2000, Added RTAI task analysis to process thumbnail
      K.Y., 10/05/2000, Added keyboard support.
      JH.D., 07/08/1999, Added Toolbar to interface.
      K.Y., 26/06/1999, Renamed file.
      K.Y., 02/06/1999, Initial typing.
*/

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <gdk/gdkkeysyms.h>

#include <Tables.h>
#include <EventDB.h>
#if SUPP_RTAI
#include <RTAIDB.h>
#endif /* SUPP_RTAI */

#include "MainWindow.h"
#include "Pixmap.h"
#include "ViewTime.h"

/* Main list of system views */
static systemView* sMainSystemViewList = NULL;

/* List of raw events displayed */
static event sRawEventsDisplayed[RTCLIST_NB_ROWS];

/* Scrolling of the raw trace */
enum eScrollRawTrace
{
  SRT_UP = 0,
  SRT_DOWN,
  SRT_PAGE_UP,
  SRT_PAGE_DOWN
};

/**********************************************************************************/
/**************************** Window internal functions ***************************/
/**********************************************************************************/
/******************************************************************
 * Function :
 *    WDStatusBarsClear()
 * Description :
 * Parameters :
 * Return values :
 * History :
 * Note :
 ******************************************************************/
void WDIStatusBarsClear(gpointer pmMainWindow)
{
  mainWindow*   pMainWindow = (mainWindow*) pmMainWindow;  /* Main window pointer */

  /* Pop the last message off the status bars */
  gtk_statusbar_pop(GTK_STATUSBAR(pMainWindow->MainSBar),
		     pMainWindow->MainSBarContextID);		    
  gtk_statusbar_pop(GTK_STATUSBAR(pMainWindow->BegTimeSBar),
		     pMainWindow->BegTimeSBarContextID);
  gtk_statusbar_pop(GTK_STATUSBAR(pMainWindow->EndTimeSBar),
		     pMainWindow->EndTimeSBarContextID);

#if 0 /* Not necessary since popping the status bar erases what was there before */
  /* Push the message down to the status bar */
  gtk_statusbar_push(GTK_STATUSBAR(pMainWindow->MainSBar),
		     pMainWindow->MainSBarContextID,
		     "");
  gtk_statusbar_push(GTK_STATUSBAR(pMainWindow->BegTimeSBar),
		     pMainWindow->BegTimeSBarContextID,
		     "");
  gtk_statusbar_push(GTK_STATUSBAR(pMainWindow->EndTimeSBar),
		     pMainWindow->EndTimeSBarContextID,
		     "");
#endif
}

/******************************************************************
 * Function :
 *    WDI_gtk_clist_set_last_row_data_full()
 * Description :
 *    Appends data to the last row of a GtkClist.
 * Parameters :
 * Return values :
 *    NONE.
 * History :
 *    J.H.D., 27/08/99, Initial typing.
 * Note :
 *    Based on gtk_clist_set_row_data_full() version 1.2.3.
 *    Much faster than using gtk_clist_set_row_data_full().
 ******************************************************************/
void WDI_gtk_clist_set_last_row_data_full(GtkCList*         pmClist,
					  gpointer          pmData,
					  GtkDestroyNotify  pmDestroy)
{
  GtkCListRow *pClistRow;

  g_return_if_fail (pmClist != NULL);
  g_return_if_fail (GTK_IS_CLIST (pmClist));
  g_return_if_fail (pmClist->row_list_end != NULL);

  pClistRow = pmClist->row_list_end->data;
  pClistRow->data    = pmData;
  pClistRow->destroy = pmDestroy;
}

/******************************************************************
 * Function :
 *    WDISetWindowIcon()
 * Description :
 * Parameters :
 * Return values :
 * History :
 * Note :
 ******************************************************************/
void WDISetWindowIcon(GtkWidget* pmWindow)
{
  GdkPixmap* pixmap;
  GdkBitmap* mask;
  pixmap = gdk_pixmap_create_from_xpm_d (pmWindow->window, 
					 &mask, 
					 &pmWindow->style->bg[GTK_STATE_NORMAL],
					 mini_LTT);
  gdk_window_set_icon (pmWindow->window, NULL, pixmap, mask);
}

/******************************************************************
 * Function :
 *    WDISearchSubTree()
 * Description :
 * Parameters :
 * Return values :
 * History :
 * Note :
 ******************************************************************/
GtkTreeItem* WDISearchSubTree(GtkTree*     pmSubTreeToSearch,
			      const gchar* pmKey,
			      gpointer     pmDataToFind)
{
  GList*       Navigator;     /* Temporary pointer to a TreeItem */
  GtkTreeItem* pTempTreeItem; /* Temporary TreeItem pointer */

  /* Set the temporary pointer to the beginning of the children list */
  Navigator = pmSubTreeToSearch->children;

  /* Scroll through this tree's children */
  while(Navigator)
    {
    /* If this is the one, return its pointer */
    if(pmDataToFind == gtk_object_get_data(GTK_OBJECT(Navigator->data), pmKey))
      return GTK_TREE_ITEM(Navigator->data);

    /* If this item has a subtree */
    if(GTK_TREE_ITEM(Navigator->data)->subtree)

      /* Search this item's childern recursively */
      if((pTempTreeItem = WDISearchSubTree(GTK_TREE(GTK_TREE_ITEM(Navigator->data)->subtree),
					   pmKey, pmDataToFind)) != NULL)
	{
	/* If a match has been found within the children */

	/* Expand the parent of the match */
	gtk_tree_item_expand(GTK_TREE_ITEM(Navigator->data));
	
	/* return the match to the caller */
	return pTempTreeItem;
	}

    /* Check the next child */
    Navigator = Navigator->next;
    }
  return NULL;
}

/******************************************************************
 * Function :
 *    WDIClearSubTree()
 * Description :
 * Parameters :
 * Return values :
 * History :
 * Note :
 ******************************************************************/
void WDIClearSubTree(GtkTree* pmSubTreeToClear)
{
  GList*       Navigator;    /* Temporary pointer to a TreeItem */

  /* Set the temporary pointer to the beginning of the children list */
  Navigator = pmSubTreeToClear->children;

  /* Scroll through this tree's children */
  while(Navigator)
    {
    /* If this item has a subtree */
    if(GTK_TREE_ITEM(Navigator->data)->subtree)
      /* Clear the subtree recursively */
      WDIClearSubTree(GTK_TREE(GTK_TREE_ITEM(Navigator->data)->subtree));

    /* Check the next child */
    Navigator = Navigator->next;    
    }

  /* Remove all items from the subtree to clear */
  gtk_tree_clear_items(pmSubTreeToClear, 0, -1);      
}

/******************************************************************
 * Function :
 *    WDIIsInString()
 * Description :
 * Parameters :
 * Return values :
 * History :
 * Note :
 ******************************************************************/
gboolean WDIIsInString(gchar* pmStringSearched, gchar* pmStringSought)
{
  gchar* pSoughtCurrPos;   /* Cursor in the sought string */
  gchar* pSearchedCurrPos; /* Position we are testing for in pmStringSearched */

  while(TRUE)
    {
    /* Set the cursor position to the beginning of the sought string */
    pSoughtCurrPos = pmStringSought;

    /* Locate the start of the string */
    while(*pSoughtCurrPos != *pmStringSearched)
      {
      /* return if we reach the end of the searched string */
      if(*pmStringSearched == '\0') return(FALSE);
      
      /* Search at the next position */
      ++pmStringSearched;
      }
    
    /* Remember where we left off in case matching fails*/
    pSearchedCurrPos = pmStringSearched;

    /* Try to find the same sequence of characters */
    while(*pSoughtCurrPos == *pSearchedCurrPos)
      {
      /* Compare the next character */
      ++pSearchedCurrPos;
      ++pSoughtCurrPos;

      /* At this point, if we reach the end of string sought,
	 this means that pmStringSought is completely in String Searched */ 
      if(*pSoughtCurrPos == '\0') return(TRUE);
      }

    /* Keep searching at the next pmStringSearched position */
    pmStringSearched++;
    }
}

/******************************************************************
 * Function :
 *    WDISearchEventField()
 * Description :
 * Parameters :
 * Return values :
 * History :
 * Note :
 ******************************************************************/
event* WDISearchEventField(db*            pmDB,
			   systemInfo*    pmSystem,
			   event*         pmFirstEvent,
			   event*         pmFirstInList,
			   event*         pmEventFound,
			   GTESearchQuery pmSearchQuery)
{
  int              lForward;    /* Did we move forward */
  event            lEvent;      /* Event used to executed search */
  process*         pProcess;    /* Pointer to process */
  eventDescription lEventDesc;  /* Event description */

  /* Don't bother with an empty event list */
  if(!pmFirstInList) return(NULL);

  /* Did we get a first event */
  if(pmFirstEvent != NULL)
    lEvent = *pmFirstEvent;
  else
    lEvent = *pmFirstInList;
  
  /* Don't bother with empty strings */
  if((pmSearchQuery.SearchType == GOTO_EVENT_DESC) && (*pmSearchQuery.SearchString == '\0'))
    {
    *pmEventFound = lEvent;
    return NULL;
    }

  /* Navigate through the list of events */
  do
    {
    /* Get the event description */
    DBEventDescription(pmDB, &lEvent, TRUE, &lEventDesc);

    /* Depending on the search type */
    switch(pmSearchQuery.SearchType)
      {
      case GOTO_EVENT_DESC:
	/* return the event if it contains the description */
	if(WDIIsInString(lEventDesc.String, pmSearchQuery.SearchString) == TRUE)
	  {
	  /* Set the passed event and return it's address */
	  *pmEventFound = lEvent;
	  return pmEventFound;
	  }
	break;

      case GOTO_CPU_ID:
	/* return the event if it contains the CPU ID */
	if(lEventDesc.CPUID == pmSearchQuery.CPUID)
	  {
	  /* Set the passed event and return it's address */
	  *pmEventFound = lEvent;
	  return pmEventFound;
	  }
	break;

      case GOTO_EVENT_TYPE:
	/* return the event if it contains the Event Type */
	if(lEventDesc.ID == pmSearchQuery.EventType)
	  {
	  /* Set the passed event and return it's address */
	  *pmEventFound = lEvent;
	  return pmEventFound;
	  }
	break;

      case GOTO_PID:
	/* Get event's process */
	pProcess = DBEventProcess(pmDB, &lEvent, pmSystem, FALSE);

	/* Is there a Process associated? */
	if((pProcess != NULL) && (pProcess->PID == pmSearchQuery.PID))
	  {
	  /* Set the passed event and return it's address */
	  *pmEventFound = lEvent;
	  return pmEventFound;
	  }
	break;

      case GOTO_ENTRY_LENGTH:
	/* return the event if it contains the entry length */
	if(lEventDesc.Size == pmSearchQuery.EntryLength)
	  {
	  /* Set the passed event and return it's address */
	  *pmEventFound = lEvent;
	  return pmEventFound;
	  }
      }

    /* Check the next event */
    lForward = DBEventNext(pmDB, &lEvent);

    /* If we are at the end of the list, start over */
    if(lForward == FALSE)
      lEvent = *pmFirstInList;
    }
  while(!DBEventsEqual(lEvent, (*pmFirstInList)));

  /* if we reach this point, no event containing
     that description could be found */
  return NULL;
}

/******************************************************************
 * Function :
 *     WDIFreeTraceStructures()
 * Description :
 * Parameters :
 * Return values :
 * History :
 * Note :
 ******************************************************************/
void WDIFreeTraceStructures(systemView*  pmSysView)
{
  /* Destroy any open event graph dependant windows */
  /* The View time frame window */
  if(pmSysView->Window->ViewTimeFrameWindow) 
    gtk_widget_destroy(pmSysView->Window->ViewTimeFrameWindow->Window);
  /* The color selection window */
  if(pmSysView->Window->ColorSelectWindow)
    gtk_widget_destroy(pmSysView->Window->ColorSelectWindow->Window);
  /* The Go to event window */
  if(pmSysView->Window->GotoEventWindow)
    gtk_widget_destroy(pmSysView->Window->GotoEventWindow->Window);
  /* The DumpToFile window */
  if(pmSysView->Window->DumpToFileWindow)
    gtk_widget_destroy(pmSysView->Window->DumpToFileWindow->Window);

  /* Is there anything opened */
  if(pmSysView->EventDB)
    {
    /* Free memory used by System structures */
    DBDestroyTrace(pmSysView->System, pmSysView->EventDB);

    /* Clear the event graph */
    EGClearEventGraph(pmSysView->Window->GTEventGraph);
    }

  /* Free memory used by options */
  if(pmSysView->Options)
    DestroyOptions(pmSysView->Options);

  /* Reset system view pointers */
  pmSysView->Options = NULL;
  pmSysView->EventDB = NULL;
  pmSysView->System  = NULL;
}

/******************************************************************
 * Function :
 *     WDISelectRTEvent()
 * Description :
 * Parameters :
 * Return values :
 * History :
 * Note :
 ******************************************************************/
void WDISelectRTEvent(systemView*  pmSysView, event* pmEvent)
{
  gint        i;             /* Generic index */
  gint        CListRow = 0;  /* The Raw event list's row where the description was found */
  event       lEvent;        /* Event used for searching */
  guint32     Position;      /* Position at which the event was found */

  /* Set current position to the upper bound of the adjustment */
  Position = (guint32) pmSysView->Window->RTVAdjust->upper - 1;

  /* Start position search at the last event in the list */
  lEvent = pmSysView->EventDB->LastEvent;

  /* Search for that event's index */
  while(!DBEventsEqual(lEvent, (*pmEvent)))
    {
    /* Set the pointer to the previous in list */
    DBEventPrev(pmSysView->EventDB, &lEvent);

    /* decrement the position index */
    Position--;
    }

  /* Set the new adjustment position */
  gtk_adjustment_set_value(pmSysView->Window->RTVAdjust, (gfloat) (Position - 1));

  /* find the row to that event */
  for(i = 0; i < RTCLIST_NB_ROWS; i++)
    if(DBEventsEqual(sRawEventsDisplayed[i], lEvent))
      CListRow = i;

  /* Select it */
  gtk_clist_select_row(GTK_CLIST(pmSysView->Window->RTCList), CListRow, 0);

  /* Select the process tree notebook page */
  gtk_notebook_set_page(GTK_NOTEBOOK(pmSysView->Window->MNotebook), 2);
    
  /* Scroll the CList to that event
     - this call MUST be after gtk_notebook_set_page to react properly */
  gtk_clist_moveto(GTK_CLIST(pmSysView->Window->RTCList), CListRow, 0, 0, 0);
}

/******************************************************************
 * Function :
 *     WDIFormatTimeInReadableString()
 * Description :
 *     Takes a time value and inserts commas between every 3 digit
 *     in order to ease readability.
 * Parameters :
 *     pmFormatedString, String where the formatted time should be
 *                       written.
 *     pmTime, The time value to format.
 * Return values :
 *     NONE
 * History :
 * Note :
 ******************************************************************/
void WDIFormatTimeInReadableString(char* pmFormatedString, gdouble pmTime)
{
  char     lTempStr[TIME_STR_LEN];   /* Temporary string */
  guint    i, j;                     /* Generic indexes */
  guint    lStrLen;                  /* String length */
  guint    lExtraChars;              /* Characters more that the last triplet */
  guint    lFormatedStrStart;        /* Start of copying position into formated str */

  /* Print the time into the temporary string */
  sprintf(lTempStr, "%.0f", pmTime);

  /* How long is the string */
  lStrLen = strlen(lTempStr);

  /* How many digits are left after the last triplet */
  lFormatedStrStart = lExtraChars = lStrLen % 3;

  /* Are there any trailing characters */
  if(lExtraChars != 0)
    {
    /* Copy the trailing characters right away */
    for(i = 0; i < lExtraChars; i++)
      pmFormatedString[i] = lTempStr[i];

    /* Insert a comma */
    pmFormatedString[i] = ',';

    /* Start copying past the added comma */
    lFormatedStrStart += 1;
    }

  /* Copy the characters into the final string in groups of three */
  for(i = lFormatedStrStart, j = lExtraChars; j < lStrLen; i += 4, j += 3)
    {
    pmFormatedString[i]     = lTempStr[j];
    pmFormatedString[i + 1] = lTempStr[j + 1];
    pmFormatedString[i + 2] = lTempStr[j + 2];
    pmFormatedString[i + 3] = ',';
    }

  /* Insert the end of string marker */
  pmFormatedString[i - 1] = '\0';
}

/******************************************************************
 * Macro :
 *    WDITextInsert()
 * Description :
 * Parameters :
 * Return values :
 * History :
 * Note :
 ******************************************************************/
#define WDITextInsert(pmWindow, pmFormat, pmArg...)\
do \
{\
  char  lText[100]; \
\
  sprintf(lText, pmFormat, ##pmArg);\
  gtk_text_insert(GTK_TEXT(pmWindow->PTProcessText), \
                  pmWindow->PTTextFont /* Font */, \
		  NULL  /* Foreground color */, \
		  NULL  /* Background color */, \
		  lText /* Text string to be inserted */, \
		  -1    /* Display it all */); \
} while(0)

/******************************************************************
 * Macro :
 *    WDIRTScroll()
 * Description :
 * Parameters :
 * Return values :
 * History :
 * Note :
 ******************************************************************/
void WDIRTScroll(systemView* pmSysView, gint pmScrolling)
{
  gfloat          lNewValue;     /* The new value for the adjustment */
  GtkAdjustment*  pAdjustment;   /* The vertical adjustment of the scrolled list */

  /* Get the vertical adjustment of the scrolled process list */
  pAdjustment = pmSysView->Window->RTVAdjust;

  /* Get the adjustment's current value */
  lNewValue = pAdjustment->value;

  /* Depending on the type of scrolling */
  switch(pmScrolling)
    {
    /* Scroll up */
    case SRT_UP :
      /* Set the new value to scroll up */
      lNewValue -= pAdjustment->step_increment;

      /* Confine the adjustment to reasonable values */
      if(lNewValue < pAdjustment->lower)
	lNewValue = pAdjustment->lower;
      break;

    /* Scroll down */
    case SRT_DOWN :
      /* Set the new value to scroll down */
      lNewValue += pAdjustment->step_increment;

      /* Confine the adjustment to reasonable values */
      if(lNewValue > pAdjustment->upper)
	lNewValue = pAdjustment->upper;
      break;

    /* Scroll page up */
    case SRT_PAGE_UP :
      /* Set the new value to scroll page up */
      lNewValue -= pAdjustment->page_increment;

      /* Confine the adjustment to reasonable values */
      if(lNewValue < pAdjustment->lower)
	lNewValue = pAdjustment->lower;
      break;

    /* Scroll page down */
    case SRT_PAGE_DOWN :
      /* Set the new value to scroll page down */
      lNewValue += pAdjustment->page_increment;

      /* Confine the adjustment to reasonable values */
      if(lNewValue > pAdjustment->upper)
	lNewValue = pAdjustment->upper;
      break;
    }

  /* Update the adjustment's value */
  gtk_adjustment_set_value(pAdjustment, lNewValue);

  /* Make sure the list is drawn correctly */
  gtk_widget_queue_resize(pmSysView->Window->RTVScroll);
}

/**********************************************************************************/
/*********************** Open Trace window callback functions **********************/
/**********************************************************************************/
/******************************************************************
 * Function :
 *    OTCBCancel()
 * Description :
 * Parameters :
 * Return values :
 * History :
 * Note :
 ******************************************************************/
void OTCBCancel(gpointer pmSysView)
{
  systemView*   pSysView;   /* The system view */

  /* Do we have anything meaningfull */
  if((pSysView = (systemView*) pmSysView) == NULL)
    {
    g_print("Internal error: Cancel callback without system view \n");
    exit(1);
    }

  /* Destroy the window */
  OTDestroyOpenTraceWindow(pSysView->Window->OpenTraceWindow);

  /* Set the main window as free to open anothe open trace window */
  pSysView->Window->OpenTraceWindow = NULL;
}

/******************************************************************
 * Function :
 *    OTCBOK()
 * Description :
 * Parameters :
 * Return values :
 * History :
 * Note :
 ******************************************************************/
void OTCBOK(gpointer pmSysView, gchar* pmProfFileName, gchar* pmProcFileName)
{
  int           lStrLen;        /* String length */
  int           lTraceFile;     /* File containing raw trace */
  FILE*         lProcFile;      /* File containing proc information */
  db*           pEventDB;       /* Event database */
  systemInfo*   pSystem;        /* The system as is */
  options*      pOptions;       /* The options */
  systemView*   pSysView;       /* The system view */

  /* Do we have anything meaningfull */
  if((pSysView = (systemView*) pmSysView) == NULL)
    {
    g_print("Internal error: OK callback without system view \n");
    exit(1);
    }

  /* For now don't go any further if no files are selected */
  if((pmProfFileName == NULL) || (pmProcFileName == NULL)
   ||(strlen(pmProfFileName) == 0) || (strlen(pmProcFileName) == 0))
    {
    WDStatusBarDisplay(pSysView->Window, "Must select Trace and Proc files ...");
    return;
    }

  /* Does the current System View contain a trace? */
  if((pSysView->EventDB != NULL) && (pSysView->EventDB->TraceStart != NULL))
    /* If so, create a new system view and window */
    pSysView = WDCreateSystemView(NULL, NULL, NULL);

  /* Create some options if we don't have any */
  if(pSysView->Options)
    pOptions = pSysView->Options;
  else
    pSysView->Options = pOptions = CreateOptions();

  /* Create an event database if we don't have one */
  if(pSysView->EventDB)
    pEventDB = pSysView->EventDB;
  else
    pSysView->EventDB = pEventDB = DBCreateDB();

  /* Create some system options if we don't have any */
  if(pSysView->System)
    pSystem = pSysView->System;
  else
    pSysView->System  = pSystem  = DBCreateSystem();

  /* Copy file names to options structure */
  lStrLen = strlen(pmProfFileName);
  pOptions->InputFileName = (char*) g_malloc(lStrLen + 1);
  strcpy(pOptions->InputFileName, pmProfFileName);
  lStrLen = strlen(pmProcFileName);
  pOptions->ProcFileName = (char*) g_malloc(lStrLen + 1);
  strcpy(pOptions->ProcFileName, pmProcFileName);
  
  /* Open the input file */
  if((lTraceFile = open(pOptions->InputFileName, O_RDONLY, 0)) < 0)
    {
    /* File ain't good */
    WDStatusBarDisplay(pSysView->Window, "Unable to open input data file");

    /* The filenames are wrong */
    g_free(pOptions->InputFileName);
    g_free(pOptions->ProcFileName);
    pOptions->InputFileName = NULL;
    pOptions->ProcFileName = NULL;

    /* Was this a newly created system view */
    if(pSysView != pmSysView)
      WDDestroySystemView(pSysView);
    return;
    }

  /* Open the /proc information file */
  if((lProcFile = fopen(pOptions->ProcFileName, "r")) == NULL)
    {
    /* File ain't good */
    WDStatusBarDisplay(pSysView->Window, "Unable to open /proc data file");

    /* Close the opened trace file */
    close(lTraceFile);

    /* The filenames are wrong */
    g_free(pOptions->InputFileName);
    g_free(pOptions->ProcFileName);
    pOptions->InputFileName = NULL;
    pOptions->ProcFileName = NULL;

    /* Was this a newly created system view */
    if(pSysView != pmSysView)
      WDDestroySystemView(pSysView);
    return;
    }

  /* Read the trace */
  if(DBReadTrace(lTraceFile, pEventDB) != TRUE)
    {
    /* Something's wrong with the input file */
    WDStatusBarDisplay(pSysView->Window, "Input file isn't a valid trace file");

    /* Close the opened files */
    close(lTraceFile);
    fclose(lProcFile);

    /* Destroy the db and the system since they were operated on */
    DBDestroyTrace(pSystem, pEventDB);
    pSysView->System  = NULL;
    pSysView->EventDB = NULL;

    /* The filenames are wrong */
    g_free(pOptions->InputFileName);
    g_free(pOptions->ProcFileName);
    pOptions->InputFileName = NULL;
    pOptions->ProcFileName = NULL;

    /* Was this a newly created system view */
    if(pSysView != pmSysView)
      WDDestroySystemView(pSysView);
    return;
    }

  /* Process the /proc file */
  DBProcessProcInfo(lProcFile, pSystem);

  /* Close the opened files */
  close(lTraceFile);
  fclose(lProcFile);

  /* Process the trace per-se */
  DBProcessTrace(pSystem, pEventDB, pOptions);

  /* Set the system that this window will display */
  pSysView->Window->SystemView = pSysView;

  /* Make sure the horizon is displayed if required the first time */
  pSysView->Window->GTEventGraph->ShowHorizon = 
                      GTK_CHECK_MENU_ITEM(pSysView->Window->ShowHorizon)->active;

  /* Was a new SystemView created ? */
  if(pmSysView != (gpointer) pSysView)
    {
    /* Display the newly created window */
    WDShowMainWindow(pSysView);
    }

  /* Display the trace */
  WDDisplayTrace(pSysView);
}

/**********************************************************************************/
/******************** View Time Frame window callback functions *******************/
/**********************************************************************************/
/******************************************************************
 * Function :
 *    VTFCBCancel()
 * Description :
 * Parameters :
 * Return values :
 * History :
 * Note :
 ******************************************************************/
void VTFCBCancel(gpointer pmSysView)
{
  systemView*   pSysView;   /* The system view */

  /* Do we have anything meaningfull */
  if((pSysView = (systemView*) pmSysView) == NULL)
    {
    g_print("Internal error: Cancel callback without system view \n");
    exit(1);
    }

  /* Destroy the window */
  VTFDestroyViewTimeFrameWindow(pSysView->Window->ViewTimeFrameWindow);

  /* Set the main window as free to open another view time frame window */
  pSysView->Window->ViewTimeFrameWindow = NULL;
}

/******************************************************************
 * Function :
 *    VTFCBOK()
 * Description :
 * Parameters :
 * Return values :
 * History :
 * Note :
 ******************************************************************/
void VTFCBOK(gpointer pmSysView, gdouble pmStartTime, gdouble pmEndTime)
{
  systemView*   pSysView;   /* The system view */

  /* Do we have anything meaningfull */
  if((pSysView = (systemView*) pmSysView) == NULL)
    {
    g_print("Internal error: OK callback without system view \n");
    exit(1);
    }

  EGZoomTimeFrame(pSysView->Window->GTEventGraph, pmStartTime, pmEndTime);
}

/**********************************************************************************/
/********************** Go to event window callback functions *********************/
/**********************************************************************************/
/******************************************************************
 * Function :
 *    GTECBCancel()
 * Description :
 * Parameters :
 * Return values :
 * History :
 * Note :
 ******************************************************************/
void GTECBCancel(gpointer pmSysView)
{
  systemView*   pSysView;   /* The system view */

  /* Do we have anything meaningfull */
  if((pSysView = (systemView*) pmSysView) == NULL)
    {
    g_print("Internal error: Cancel callback without system view \n");
    exit(1);
    }

  /* Destroy the window */
  GTEDestroyGotoEventWindow(pSysView->Window->GotoEventWindow);

  /* Set the main window as free to open another view time frame window */
  pSysView->Window->GotoEventWindow = NULL;
}

/******************************************************************
 * Function :
 *    GTECBOK()
 * Description :
 * Parameters :
 * Return values :
 * History :
 * Note :
 ******************************************************************/
void GTECBOK(gpointer pmSysView, GTESearchQuery pmSearchQuery)
{
  gint        lCListRow;       /* The row after which searching should start */
  gchar       lString[256];    /* Temporary build string */
  event       lEventStart;     /* Event from which search should start */
  event       lEventFound;     /* Event to be filled by the search routine */
  event*      pEventFound;     /* The event found by the search */
  systemView* pSysView;        /* The system view */

  /* Do we have anything meaningfull */
  if((pSysView = (systemView*) pmSysView) == NULL)
    {
    g_print("Internal error: OK callback without system view \n");
    exit(1);
    }

  /* Is there an event selected */
  if(GTK_CLIST(pSysView->Window->RTCList)->selection != NULL)
    {
    /* Start the search after the selected row */
    lCListRow = GPOINTER_TO_INT(((GList*) GTK_CLIST(pSysView->Window->RTCList)->selection)->data);
    lEventStart = *((event*) (gtk_clist_get_row_data(GTK_CLIST(pSysView->Window->RTCList), lCListRow)));
    DBEventNext(pSysView->EventDB, &lEventStart);
    }
  else
    /* Set the pointer to the first event in the list */
    lEventStart = pSysView->EventDB->FirstEvent;

  /* search the event database for pmSearchString */
  if((pEventFound = WDISearchEventField(pSysView->EventDB,
				       pSysView->System,
				       &lEventStart,
				       &(pSysView->EventDB->FirstEvent),
				       &lEventFound,
				       pmSearchQuery)) != NULL)
    /* Select the event found in the CList */
    WDISelectRTEvent(pSysView, pEventFound);
  else
    {
    /* Depending on the query type */
    switch(pmSearchQuery.SearchType)
      {
      case GOTO_EVENT_DESC:
	sprintf(lString, "No match found for description \"%s\"", pmSearchQuery.SearchString);
	break;

      case GOTO_CPU_ID:
	sprintf(lString, "No match found for CPU ID \"%d\"", pmSearchQuery.CPUID);
	break;

      case GOTO_EVENT_TYPE:
	sprintf(lString, "No match found for event type \"%d\"", pmSearchQuery.EventType);
	break;

      case GOTO_PID:
	sprintf(lString, "No match found for PID \"%d\"", pmSearchQuery.PID);
	break;

      case GOTO_ENTRY_LENGTH:
	sprintf(lString, "No match found for entry length \"%d\"", pmSearchQuery.EntryLength);

      }

    /* Display error message in status bar */
    WDStatusBarDisplay(pSysView->Window, lString);
    }
}

/**********************************************************************************/
/********************* Dump To File  window callback functions ********************/
/**********************************************************************************/
/******************************************************************
 * Function :
 *    DTFCBCancel()
 * Description :
 * Parameters :
 * Return values :
 * History :
 * Note :
 ******************************************************************/
void DTFCBCancel(gpointer pmSysView)
{
  systemView*   pSysView;   /* The system view */

  /* Do we have anything meaningfull */
  if((pSysView = (systemView*) pmSysView) == NULL)
    {
    g_print("Internal error: Cancel callback without system view \n");
    exit(1);
    }

  /* Destroy the window */
  DTFDestroyDumpToFileWindow(pSysView->Window->DumpToFileWindow);

  /* Set the main window as free to open another dump to file window */
  pSysView->Window->DumpToFileWindow = NULL;
}

/******************************************************************
 * Function :
 *    DTFCBOK()
 * Description :
 * Parameters :
 * Return values :
 * History :
 * Note :
 ******************************************************************/
void DTFCBOK(gpointer pmSysView)
{
  systemView* pSysView;     /* The system view */
  int         lDumpFile;    /* The dumpfile ID */
  gchar       lString[256]; /* Temporary build string */

  /* Do we have anything meaningfull */
  if((pSysView = (systemView*) pmSysView) == NULL)
    {
    g_print("Internal error: OK callback without system view \n");
    exit(1);
    }

  /* Did the user select a filename */
  if((!pSysView->Options->OutputFileName) || (strlen(pSysView->Options->OutputFileName) == 0))
    {
    WDStatusBarDisplay(pSysView->Window, "Must select file for output ...");
    return;
    }

  /* Open the output file */
  if((lDumpFile = creat(pSysView->Options->OutputFileName, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) < 0)
    {
    /* File ain't good */
    sprintf(lString, "Unable to open %s for write!", pSysView->Options->OutputFileName);
    WDStatusBarDisplay(pSysView->Window, lString);
    return;
    }

  /* Print out the trace to the given file */
  DBPrintTrace(lDumpFile, pSysView->System, pSysView->EventDB, pSysView->Options);
}

/**********************************************************************************/
/*********************** About box Signal handling functions **********************/
/**********************************************************************************/
/******************************************************************
 * Function :
 * Description :
 * Parameters :
 * Return values :
 * History :
 * Note :
 ******************************************************************/
gint ABOUTSHDeleteEvent(GtkWidget* pmWidget, GdkEvent* pmEvent, gpointer pmData)
{
  /* Close it */
  return(FALSE);
}

/******************************************************************
 * Function :
 * Description :
 * Parameters :
 * Return values :
 * History :
 * Note :
 ******************************************************************/
void ABOUTSHDestroy(GtkWidget* pmWidget, gpointer pmData)
{
  systemView*  pSysView;        /* The system being displayed */

  /* Do we have anything meaningfull */
  if((pSysView = (systemView*) pmData) == NULL)
    {
    g_print("Internal error: Callback without about box \n");
    exit(1);
    }

  /* Set the system view as not having an about box */
  pSysView->Window->AboutBox = NULL;
}

/**********************************************************************************/
/********************* Help contents Signal handling functions ********************/
/**********************************************************************************/
/******************************************************************
 * Function :
 * Description :
 * Parameters :
 * Return values :
 * History :
 * Note :
 ******************************************************************/
gint HELPSHDeleteEvent(GtkWidget* pmWidget, GdkEvent* pmEvent, gpointer pmData)
{
  /* Close it */
  return(FALSE);
}

/******************************************************************
 * Function :
 * Description :
 * Parameters :
 * Return values :
 * History :
 * Note :
 ******************************************************************/
void HELPSHDestroy(GtkWidget* pmWidget, gpointer pmData)
{
  systemView*  pSysView;        /* The system being displayed */

  /* Do we have anything meaningfull */
  if((pSysView = (systemView*) pmData) == NULL)
    {
    g_print("Internal error: Callback without Help Window \n");
    exit(1);
    }

  /* Set the system view as not having a Help contents window */
  pSysView->Window->HelpContents = NULL;
}

/**********************************************************************************/
/******************** Color selection window callback functions *******************/
/**********************************************************************************/
/******************************************************************
 * Function :
 *    CSCBCancel()
 * Description :
 * Parameters :
 * Return values :
 * History :
 * Note :
 ******************************************************************/
void CSCBCancel(gpointer pmSysView)
{
  systemView*   pSysView;   /* The system view */

  /* Do we have anything meaningfull */
  if((pSysView = (systemView*) pmSysView) == NULL)
    {
    g_print("Internal error: Cancel callback without system view \n");
    exit(1);
    }

  /* Destroy the window */
  CSDestroyColorSelectWindow(pSysView->Window->ColorSelectWindow);

  /* Set the main window as free to open another color selection window */
  pSysView->Window->ColorSelectWindow = NULL;
}

/******************************************************************
 * Function :
 *    CSCBOK()
 * Description :
 * Parameters :
 * Return values :
 * History :
 * Note :
 ******************************************************************/
void CSCBOK(GtkWidget* pmWidget, gpointer pmCSWin)
{
  systemView*        pSysView; /* The system view */
  colorSelectWindow* pCSWin;   /* The color selection window */
  eventGraph*        pEGraph;  /* The event graph to modify */

  /* Do we have anything meaningfull */
  if((pCSWin = (colorSelectWindow*) pmCSWin) == NULL)
    {
    g_print("Internal error: OK callback without color window \n");
    exit(1);
    }

  /*  Set temporary pointers for ease of use */
  pSysView = (systemView*) pCSWin->SysView;
  pEGraph = pSysView->Window->GTEventGraph;

  /* Bring back the modified GCs */
  gdk_gc_copy(pEGraph->BackgroundGC, pCSWin->BackgroundGC);
  gdk_gc_copy(pEGraph->HorizonGC,    pCSWin->HorizonGC);
  gdk_gc_copy(pEGraph->ProcessGC,    pCSWin->ProcessGC);
  gdk_gc_copy(pEGraph->Process0GC,   pCSWin->Process0GC);
  gdk_gc_copy(pEGraph->KernelGC,     pCSWin->KernelGC);
  gdk_gc_copy(pEGraph->SelectedGC,   pCSWin->SelectedGC);
  gdk_gc_copy(pEGraph->SysCallGC,    pCSWin->SysCallGC);
  gdk_gc_copy(pEGraph->TrapGC,       pCSWin->TrapGC);
  gdk_gc_copy(pEGraph->InterruptGC,  pCSWin->InterruptGC);
  gdk_gc_copy(pEGraph->TextGC,       pCSWin->TextGC);

  /* Redraw the event graph */
  EGForceTraceRedraw(pEGraph);
}

/**********************************************************************************/
/**************************** Signal handling functions ***************************/
/**********************************************************************************/
/******************************************************************
 * Function :
 *    SHDeleteEvent()
 * Description :
 *    Delete handler.
 * Parameters :
 *    pmWidget,
 *    pmEvent,
 *    pmData,
 * Return values :
 *    FALSE, Go ahead and kill us of, we're done.
 *    TRUE, We don't really want to quit.
 * History :
 * Note :
 *    This is called if the user clicks on the close button of the
 *    window of if he chooses close in the menu of window
 *    operations. 
 ******************************************************************/
gint SHDeleteEvent(GtkWidget* pmWidget, GdkEvent* pmEvent, gpointer pmData)
{
  /* Destroy the associated SystemView */
  WDDestroySystemView(pmData);

  /* We're done */
  return(FALSE);
}

/******************************************************************
 * Function :
 *    SHDestroy()
 * Description :
 * Parameters :
 * Return values :
 * History :
 * Note :
 ******************************************************************/
void SHDestroy(GtkWidget* pmWidget, gpointer pmData)
{
  /* DEBUG */
#if 0
  g_print("Destroy summoned \n");
#endif
  /* if we were the last opened window */
  if(!sMainSystemViewList)
    /* Exit from gtk_main() */
    gtk_main_quit();
}

/******************************************************************
 * Function :
 *    SHOpenTrace()
 * Description :
 * Parameters :
 * Return values :
 * History :
 * Note :
 ******************************************************************/
void SHOpenTrace(GtkWidget* pmWidget, gpointer pmData)
{
  systemView*      pSysView;        /* The system being displayed */
  openTraceWindow* pOTWin;          /* Open trace window */

  /* Do we have anything meaningfull */
  if((pSysView = (systemView*) pmData) == NULL)
    return;

  /* Is there a window already open */
  if(pSysView->Window->OpenTraceWindow != NULL)
    {
    OTSetFocus(pSysView->Window->OpenTraceWindow);
    return;
    }

  /* Create a new trace file selection window */
  pOTWin = pSysView->Window->OpenTraceWindow =
    OTCreateOpenTraceWindow(pSysView,
			    pSysView->Window->MWindow,
			    OTCBOK,
			    OTCBCancel);

  /* Connect the signals */
  OTConnectSignals(pOTWin);

  /* Show it all to the world */
  OTShowOpenTraceWindow(pOTWin);
}

/******************************************************************
 * Function :
 *    SHColorSelect()
 * Description :
 * Parameters :
 * Return values :
 * History :
 * Note :
 ******************************************************************/
void SHColorSelect(GtkWidget* pmWidget, gpointer pmData)
{
  systemView*        pSysView;        /* The system being displayed */
  colorSelectWindow* pCSWin;          /* Open trace window */


  /* Do we have anything meaningfull */
  if((pSysView = (systemView*) pmData) == NULL)
    return;

  /* Is there a window already open */
  if(pSysView->Window->ColorSelectWindow != NULL)
    return;

  /* Create a new Color selection window */
  pCSWin = pSysView->Window->ColorSelectWindow =
    CSCreateColorSelectWindow(pSysView,
			      pSysView->Window->MWindow,
			      CSCBOK,
			      CSCBCancel);

  /* Connect the signals */
  CSConnectSignals(pCSWin);

  /* Show it all to the world */
  CSShowColorSelectWindow(pCSWin, pSysView->Window->GTEventGraph);

}

/******************************************************************
 * Function :
 *    SHViewTimeFrame()
 * Description :
 * Parameters :
 * Return values :
 * History :
 * Note :
 ******************************************************************/
void SHViewTimeFrame(GtkWidget* pmWidget, gpointer pmData)
{
  systemView*          pSysView;  /* The system being displayed */
  viewTimeFrameWindow* pVTFWin;   /* View time frame window */

  /* Do we have anything meaningfull */
  if((pSysView = (systemView*) pmData) == NULL)
    return;

  /* Is there a window already open  - this should never happen */
  if(pSysView->Window->ViewTimeFrameWindow) return;

  /* Create a new trace file selection window */
  pVTFWin = pSysView->Window->ViewTimeFrameWindow =
    VTFCreateViewTimeFrameWindow(pSysView,
				 pSysView->Window->MWindow,
				 pSysView->Window->GTEventGraph,
				 VTFCBOK,
				 VTFCBCancel);

  /* Connect the signals */
  VTFConnectSignals(pVTFWin);

  /* Show it all to the world */
  VTFShowViewTimeFrameWindow(pVTFWin);
}

/******************************************************************
 * Function :
 *    SHGotoEvent()
 * Description :
 * Parameters :
 * Return values :
 * History :
 * Note :
 ******************************************************************/
void SHGotoEvent(GtkWidget* pmWidget, gpointer pmData)
{
  systemView*      pSysView;  /* The system being displayed */
  gotoEventWindow* pGTEWin;   /* Go to event window */

  /* Do we have anything meaningfull */
  if((pSysView = (systemView*) pmData) == NULL)
    return;

  /* Is there a window already open  - this should never happen */
  if(pSysView->Window->GotoEventWindow) return;

  /* Create a new trace file selection window */
  pGTEWin = pSysView->Window->GotoEventWindow =
    GTECreateGotoEventWindow(pSysView,
			     pSysView->Window->MWindow,
			     GTECBOK,
			     GTECBCancel);

  /* Connect the signals */
  GTEConnectSignals(pGTEWin);

  /* Show it all to the world */
  GTEShowGotoEventWindow(pGTEWin);
}

/******************************************************************
 * Function :
 *    SHCloseTrace()
 * Description :
 * Parameters :
 * Return values :
 * History :
 * Note :
 ******************************************************************/
void SHCloseTrace(GtkWidget* pmWidget, gpointer pmData)
{
  systemView*  pSysView;        /* The system being displayed */

  /* Do we have anything meaningfull */
  if((pSysView = (systemView*) pmData) == NULL)
    return;

  /* Clear the process tree */
  WDIClearSubTree(GTK_TREE(pSysView->Window->PTProcessTree));

  /* Erase text describing process */
  gtk_text_backward_delete(GTK_TEXT(pSysView->Window->PTProcessText),
			   gtk_text_get_length(GTK_TEXT(pSysView->Window->PTProcessText)));

  /*  Clear raw event trace */
  gtk_clist_clear(GTK_CLIST(pSysView->Window->RTCList));
  gtk_widget_queue_resize(pSysView->Window->RTCList);

#if 0
  g_list_free(GTK_CLIST(pSysView->Window->RTCList)->row_list);
  GTK_CLIST(pSysView->Window->RTCList)->rows = 0;
  g_mem_chunk_destroy(GTK_CLIST(pSysView->Window->RTCList)->row_mem_chunk);
  GTK_CLIST(pSysView->Window->RTCList)->row_mem_chunk = NULL;
#endif

#if 0
  gtk_widget_destroy(pSysView->Window->RTCList);
  /* Create raw trace list */
  pSysView->Window->RTCList  = gtk_clist_new_with_titles(RTCLIST_NB_COLUMNS, RTCListTitles);
  gtk_clist_set_selection_mode(GTK_CLIST(pSysView->Window->RTCList), GTK_SELECTION_SINGLE);

  /* DO NOT USE gtk_scrolled_window_add_with_viewport() here, it doesn't work! */
  gtk_container_add(GTK_CONTAINER(pSysView->Window->RTScrolledCList), pSysView->Window->RTCList);

  /* Configure the columns of the list */
  gtk_clist_set_column_justification(GTK_CLIST(pSysView->Window->RTCList), 0, GTK_JUSTIFY_LEFT);
  gtk_clist_set_column_justification(GTK_CLIST(pSysView->Window->RTCList), 1, GTK_JUSTIFY_RIGHT);
  gtk_clist_set_column_justification(GTK_CLIST(pSysView->Window->RTCList), 2, GTK_JUSTIFY_RIGHT);
  gtk_clist_set_column_justification(GTK_CLIST(pSysView->Window->RTCList), 3, GTK_JUSTIFY_RIGHT);
  gtk_clist_set_column_justification(GTK_CLIST(pSysView->Window->RTCList), 4, GTK_JUSTIFY_LEFT);
  gtk_clist_set_column_width(GTK_CLIST(pSysView->Window->RTCList), 0, 80);
  gtk_clist_set_column_width(GTK_CLIST(pSysView->Window->RTCList), 1, 65);
  gtk_clist_set_column_width(GTK_CLIST(pSysView->Window->RTCList), 2, 65);
  gtk_clist_set_column_width(GTK_CLIST(pSysView->Window->RTCList), 3, 60);
  gtk_clist_set_column_width(GTK_CLIST(pSysView->Window->RTCList), 4, 250);
#endif

  /* Is this the only systemView left? */
  if(sMainSystemViewList->Next)
    {
    /* store the pointer to the window to destroy */
    pmWidget = pSysView->Window->MWindow;

    /* Destroy the associated SystemView */
    WDDestroySystemView(pSysView);

    /* Destroy the window which contains this trace */
    gtk_widget_destroy(pmWidget);
    }
  else
    {
    /* Simply free the TraceStructures */
    WDIFreeTraceStructures(pSysView);

    /* Reset the CList adjustment */
    pSysView->Window->RTVAdjust->lower          = 0;
    pSysView->Window->RTVAdjust->upper          = 0;
    pSysView->Window->RTVAdjust->step_increment = 0;
    pSysView->Window->RTVAdjust->page_increment = 0;
    pSysView->Window->RTVAdjust->page_size      = 0;
    gtk_adjustment_changed(GTK_ADJUSTMENT(pSysView->Window->RTVAdjust));

    /* Disable relevant menu items */
    WDSetMenusSensitivity(pSysView, FALSE);

    /* Set Main window title */
    gtk_window_set_title(GTK_WINDOW(pSysView->Window->MWindow), "Trace Visualizer");

    /* Clear the status bar */
    WDIStatusBarsClear(pSysView->Window);
    }
}

/******************************************************************
 * Function :
 *    SHDumpToFile()
 * Description :
 * Parameters :
 * Return values :
 * History :
 * Note :
 ******************************************************************/
void SHDumpToFile(GtkWidget* pmWidget, gpointer pmData)
{
  systemView*       pSysView;  /* The system being displayed */
  dumpToFileWindow* pDTFWin;   /* Dump to file window */

  /* Do we have anything meaningfull */
  if((pSysView = (systemView*) pmData) == NULL)
    return;

  /* Is there a window already open  - this should never happen */
  if(pSysView->Window->DumpToFileWindow) return;

  /* Create a new trace file selection window */
  pDTFWin = pSysView->Window->DumpToFileWindow =
    DTFCreateDumpToFileWindow(pSysView,
			      pSysView->Window->MWindow,
			      DTFCBOK,
			      DTFCBCancel);

  /* Connect the signals */
  DTFConnectSignals(pDTFWin);

  /* Show it all to the world */
  DTFShowDumpToFileWindow(pDTFWin);
}

/******************************************************************
 * Function :
 *    SHQuit()
 * Description :
 * Parameters :
 * Return values :
 * History :
 * Note :
 ******************************************************************/
void SHQuit(GtkWidget* pmWidget, gpointer pmData)
{
  /* Exit from gtk_main() */
  gtk_main_quit();
}

/******************************************************************
 * Function :
 *    SHClistInfo()
 * Description :
 * Parameters :
 * Return values :
 * History :
 * Note :
 *    For debugging purposes
 ******************************************************************/
#if 0 /* This isn't used */
void SHClistInfo(GtkWidget* pmWidget, gpointer pmData)
{
  systemView*  pSysView;        /* The system being displayed */

  /* Do we have anything meaningfull */
  if((pSysView = (systemView*) pmData) == NULL)
    return;

  g_print("************** \n");
  g_print(" CLIST INFO\n");
  g_print("**************\n");
  g_print("Number of rows: %d\n", GTK_CLIST(pSysView->Window->RTCList)->rows);
  g_print("Adjustment; upper: %f, lower: %f, value: %f \n", 
	  GTK_ADJUSTMENT(GTK_CLIST(pSysView->Window->RTCList)->hadjustment)->upper,
	  GTK_ADJUSTMENT(GTK_CLIST(pSysView->Window->RTCList)->hadjustment)->lower,
	  GTK_ADJUSTMENT(GTK_CLIST(pSysView->Window->RTCList)->hadjustment)->value);
  g_print("**************\n");

  WDFillEventList(pSysView->Window->RTCList, pSysView->EventDB, pSysView->System, NULL, NULL);
}
#endif

/******************************************************************
 * Function :
 *    SHZoomIn()
 * Description :
 * Parameters :
 * Return values :
 * History :
 * Note :
 ******************************************************************/
void SHZoomIn(GtkWidget* pmWidget, gpointer pmData)
{
  systemView*  pSysView;        /* The system being displayed */

  /* Do we have anything meaningfull */
  if((pSysView = (systemView*) pmData) == NULL)
    return;

  /* Is there anything opened */
  if(pSysView->EventDB == NULL)
    return;
  if(pSysView->EventDB->TraceStart == NULL)
    return;

  /* Zoom in on the event graph */
  EGZoomIn(pSysView->Window->GTEventGraph);
}


/******************************************************************
 * Function :
 *    SHZoomOut()
 * Description :
 * Parameters :
 * Return values :
 * History :
 * Note :
 ******************************************************************/
void SHZoomOut(GtkWidget* pmWidget, gpointer pmData)
{
  systemView*  pSysView;        /* The system being displayed */

  /* Do we have anything meaningfull */
  if((pSysView = (systemView*) pmData) == NULL)
    return;

  /* Is there anything opened */
  if(pSysView->EventDB == NULL)
    return;
  if(pSysView->EventDB->TraceStart == NULL)
    return;

  /* Zoom out on the event graph */
  EGZoomOut(pSysView->Window->GTEventGraph);
}

/******************************************************************
 * Function :
 *    SHShowHorizon()
 * Description :
 * Parameters :
 * Return values :
 * History :
 * Note :
 ******************************************************************/
void SHShowHorizon(GtkWidget* pmWidget, gpointer pmData)
{
  systemView*  pSysView;        /* The system being displayed */

  /* Do we have anything meaningfull */
  if((pSysView = (systemView*) pmData) == NULL)
    return;

  /* Is there anything opened */
  if(pSysView->EventDB == NULL)
    return;
  if(pSysView->EventDB->TraceStart == NULL)
    return;

  /* Was this called from the menu, or the toolbar? */
  if(pSysView->Window->tlbShowHorizon == pmWidget)
    /* Synchronize the menu accordingly */
    gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(pSysView->Window->ShowHorizon),
       gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(pSysView->Window->tlbShowHorizon)));

  else
    /* Synchronize the toolbar accordingly */
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pSysView->Window->tlbShowHorizon),
				 GTK_CHECK_MENU_ITEM(pSysView->Window->ShowHorizon)->active);

  /* Set the horizon's view */
  pSysView->Window->GTEventGraph->ShowHorizon = 
           gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(pSysView->Window->tlbShowHorizon));
  EGSetHorizonView(pSysView->Window->GTEventGraph);
}

/******************************************************************
 * Function :
 *    SHConfigureDaemon()
 * Description :
 * Parameters :
 * Return values :
 * History :
 * Note :
 ******************************************************************/
void SHConfigureDaemon(GtkWidget* pmWidget, gpointer pmData)
{
}

/******************************************************************
 * Function :
 *    SHContents()
 * Description :
 * Parameters :
 * Return values :
 * History :
 * Note :
 ******************************************************************/
void SHContents(GtkWidget* pmWidget, gpointer pmData)
{
  GtkWidget*   pContentText;      /* Help contents text */
  GtkWidget*   pContentOKButton;  /* OK button in the help contents */
  GtkWidget*   pContentWindow;    /* The Help contents window */
  systemView*  pSysView;          /* The system being displayed */

  /* Do we have anything meaningfull */
  if((pSysView = (systemView*) pmData) == NULL)
    return;

  /* Get the Contents window */
  pContentWindow = pSysView->Window->HelpContents;

  /* Is there acontents window already opened */
  if(pContentWindow != NULL)
    {
    /* Put the contents window on top */
    gtk_widget_hide(pContentWindow);
    gtk_widget_show(pContentWindow);
    return;
    }

  /* Build the Help contents window */
  pContentWindow   = gtk_dialog_new();
  pContentText     = gtk_label_new(HELP_CONTENTS_TEXT);
  pContentOKButton = gtk_button_new_with_label("OK");
  gtk_container_set_border_width(GTK_CONTAINER(pContentWindow), 5);
  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(pContentWindow)->vbox),
		     pContentText,
		     TRUE,
		     TRUE,
		     0);
  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(pContentWindow)->action_area),
		     pContentOKButton,
		     TRUE,
		     TRUE,
		     0);

  /* Connect the signals to the box */
  gtk_signal_connect(GTK_OBJECT(pContentWindow),
		     "delete_event",
		     GTK_SIGNAL_FUNC(HELPSHDeleteEvent),
		     pContentWindow);
  gtk_signal_connect(GTK_OBJECT(pContentWindow),
		     "destroy",
		     GTK_SIGNAL_FUNC(HELPSHDestroy),
		     pSysView);
  gtk_signal_connect_object(GTK_OBJECT(pContentOKButton),
			    "clicked",
			    GTK_SIGNAL_FUNC(gtk_widget_destroy),
			    GTK_OBJECT(pContentWindow));

  /* Set the window's title */
  gtk_window_set_title(GTK_WINDOW(pContentWindow), "Help: contents");
  
  /* Place the window in the middle of the screen */
  gtk_window_set_position(GTK_WINDOW(pContentWindow), GTK_WIN_POS_CENTER);

  /* Show the window */
  gtk_widget_show_all(pContentWindow);

  /* Update the Help contents window pointer*/
  pSysView->Window->HelpContents = pContentWindow;
}

/******************************************************************
 * Function :
 *    SHAbout()
 * Description :
 * Parameters :
 * Return values :
 * History :
 * Note :
 ******************************************************************/
void SHAbout(GtkWidget* pmWidget, gpointer pmData)
{
  GtkWidget*   pAboutText;      /* Text in about box */
  GtkWidget*   pAboutOKButton;  /* OK button in the about box */
  GtkWidget*   pAboutBox;       /* The about box */
  systemView*  pSysView;        /* The system being displayed */

  /* Do we have anything meaningfull */
  if((pSysView = (systemView*) pmData) == NULL)
    return;

  /* Get the about box */
  pAboutBox = pSysView->Window->AboutBox;

  /* Is there an about box already opened */
  if(pAboutBox != NULL)
    {
    /* Put the about box up top */
    gtk_widget_hide(pAboutBox);
    gtk_widget_show(pAboutBox);
    return;
    }

  /* Build the about box */
  pAboutBox      = gtk_dialog_new();
  pAboutText     = gtk_label_new(ABOUT_BOX_TEXT);
  pAboutOKButton = gtk_button_new_with_label("OK");
  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(pAboutBox)->vbox),
		     pAboutText,
		     TRUE,
		     TRUE,
		     0);
  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(pAboutBox)->action_area),
		     pAboutOKButton,
		     TRUE,
		     TRUE,
		     0);

  /* Connect the signals to the box */
  gtk_signal_connect(GTK_OBJECT(pAboutBox),
		     "delete_event",
		     GTK_SIGNAL_FUNC(ABOUTSHDeleteEvent),
		     pAboutBox);
  gtk_signal_connect(GTK_OBJECT(pAboutBox),
		     "destroy",
		     GTK_SIGNAL_FUNC(ABOUTSHDestroy),
		     pSysView);
  gtk_signal_connect_object(GTK_OBJECT(pAboutOKButton),
			    "clicked",
			    GTK_SIGNAL_FUNC(gtk_widget_destroy),
			    GTK_OBJECT(pAboutBox));

  /* Set the box's title */
  gtk_window_set_title(GTK_WINDOW(pAboutBox), "About");
  
  /* Place the box in the middle of the screen */
  gtk_window_set_position(GTK_WINDOW(pAboutBox), GTK_WIN_POS_CENTER);

  /* Set window size */
  gtk_widget_set_usize(GTK_WIDGET(pAboutBox), 300, 250);

  /* Show the box */
  gtk_widget_show_all(pAboutBox);

  /* Update the about box */
  pSysView->Window->AboutBox = pAboutBox;
}

/******************************************************************
 * Function : SHKeyReleased()
 * Description :
 *     Takes care of the keys released by the user.
 * Parameters :
 * Return values :
 * History :
 * Note :
 *     This funciton doesn't always get called. For some reason,
 *     if the window is resized, then the callback isn't called
 *     anymore. GTK bug???
 ******************************************************************/
gint SHKeyReleased(GtkWidget* pmWidget, GdkEventKey* pmKeyEvent, gpointer pmData)
{
  systemView*  pSysView;        /* The system being displayed */

#if 0
  g_print("LTT: key released \n");
#endif

  /* Do we have anything meaningfull */
  if((pSysView = (systemView*) pmData) == NULL)
    return TRUE;

  /* Depending on the key pressed */
  switch(pmKeyEvent->keyval)
    {
    case GDK_Control_L :
    case GDK_Control_R :
      break;
    }

  /* We're done */
  return TRUE;
}

/******************************************************************
 * Function : SHKeyPressed()
 * Description :
 *     Takes care of the keys pressed by the user.
 * Parameters :
 * Return values :
 * History :
 * Note :
 ******************************************************************/
gint SHKeyPressed(GtkWidget* pmWidget, GdkEventKey* pmKeyEvent, gpointer pmData)
{
  gint         lCurrentPage;    /* Current page in notebook */
  systemView*  pSysView;        /* The system being displayed */

#if 0
  g_print("LTT: Key pressed \n");
#endif

  /* Do we have anything meaningfull */
  if((pSysView = (systemView*) pmData) == NULL)
    return TRUE;

  /* If the user presses ESC, free the ctrl button press stuff */
  if(pmKeyEvent->state & GDK_CONTROL_MASK)
    return TRUE;

  /* Get the current page being viewed in the notebook */
  lCurrentPage = gtk_notebook_get_current_page(GTK_NOTEBOOK(pSysView->Window->MNotebook));

  /* Depending on the key pressed */
  switch(pmKeyEvent->keyval)
    {
    /* Left arrow */
    case GDK_Left :
      /* Depending on the current notebook page */
      switch(lCurrentPage)
	{
	/* Event Graph */
	case 0 :
	  EGScrollLeft(pSysView->Window->GTEventGraph);
	  break;
	}
      break;

    /* Right arrow */
    case GDK_Right :
      /* Depending on the current notebook page */
      switch(lCurrentPage)
	{
	/* Event Graph */
	case 0 :
	  EGScrollRight(pSysView->Window->GTEventGraph);	  
	  break;
	}
      break;

    /* Up arrow */
    case GDK_Up :
      /* Depending on the current notebook page */
      switch(lCurrentPage)
	{
	/* Event Graph */
	case 0 :
	  EGScrollUp(pSysView->Window->GTEventGraph);	  
	  break;

	/* Raw trace */
	case 2 :
	  WDIRTScroll(pSysView, SRT_UP);
	  break;
	}
      break;

    /* Down arrow */
    case GDK_Down :
      /* Depending on the current notebook page */
      switch(lCurrentPage)
	{
	/* Event Graph */
	case 0 :
       	  EGScrollDown(pSysView->Window->GTEventGraph);
	  break;

	/* Raw trace */
	case 2 :
	  WDIRTScroll(pSysView, SRT_DOWN);
	  break;
	}
      break;

    /* Page up */
    case GDK_Page_Up :
      /* Depending on the current notebook page */
      switch(lCurrentPage)
	{
	/* Event Graph */
	case 0 :
	  EGPageUp(pSysView->Window->GTEventGraph);	  
	  break;

	/* Raw trace */
	case 2 :
	  WDIRTScroll(pSysView, SRT_PAGE_UP);
	  break;
	}
      break;

    /* Page down */
    case GDK_Page_Down :
      /* Depending on the current notebook page */
      switch(lCurrentPage)
	{
	/* Event Graph */
	case 0 :
	  EGPageDown(pSysView->Window->GTEventGraph);
	  break;

	/* Raw trace */
	case 2 :
	  WDIRTScroll(pSysView, SRT_PAGE_DOWN);
	  break;
	}
      break;

    /* G or g */
    case 'g' :
    case 'G' :
      gtk_notebook_set_page(GTK_NOTEBOOK(pSysView->Window->MNotebook), 0);
      break;

    /* P or p */
    case 'p' :
    case 'P' :
      gtk_notebook_set_page(GTK_NOTEBOOK(pSysView->Window->MNotebook), 1);
      break;

    /* R or r */
    case 'r' :
    case 'R' :
      gtk_notebook_set_page(GTK_NOTEBOOK(pSysView->Window->MNotebook), 2);
      break;
    }

  return TRUE;
}

/******************************************************************
 * Function :
 *    SHToggleTBIcon()
 * Description : 
 *   Clearinghouse for several toolbar icons that forces a redraw.
 *   EGIEventInfo (the icon drawing routine) checks the toolbar value
 *   directly.  This provides tighter coupling, less code, smaller
 *   data structures and fewer errors.  
 * Parameters :
 * Return values :
 * History : 
 *   02/01	ROC, removed superfluous data structures and copying
 *   01/01	ROC, initial typing
 * Note :
 ******************************************************************/
void SHToggleTBIcon(GtkWidget* pmWidget, gpointer pmData)
{
  systemView*  pSysView;    /* The system view */

  /* Is this a valid event */
  if((pSysView = (systemView*) pmData) == NULL)
    {
    g_print("Toggle Toolbar Icon without valid SystemView pointer! \n");
    exit(1);
    }

   /* The redraw takes a kick (ie, event) to display.  See a similar (?) 
      comment in EGClearEventGraph.  This call was copied from EGZoomIn 
      (also in EGSetHorizonView).  What about EGShowEventGraph?  FYI,
      a hide/show pair seems to flash really bad */
   EGForceTraceRedraw(pSysView->Window->GTEventGraph);

   /* Update the draw area */
   gtk_widget_queue_resize(pSysView->Window->GTEventGraph->DrawArea);
}

/******************************************************************
 * Function :
 *    SHEGIconButtonPress()
 * Description :
 * Parameters :
 * Return values :
 * History :
 * Note :
 ******************************************************************/
void SHEGIconButtonPress(GtkWidget*      pmDrawArea,
			 GdkEventButton* pmEventButton,
			 gpointer        pmEGraph)
{
  eventGraph* pEGraph;   /* Pointer to the event graph */
  GSList*     Navigator; /* Temporary pointer to the EventIcons list */

  /* Fool-proof the function */
  if(!(pEGraph = (eventGraph*) pmEGraph))
    {
    g_print("Null Event Graph in function SHEGIconButtonPress! \n");
    exit(1);
    }

  /* Is this the first button */
  if (pmEventButton->button == 1)
    {
    /* Zoom in */
    EGOneClickZoom(pEGraph, pmEventButton->x, TRUE);
    return;
    }

  /* if we have a right-click event */
  if(pmEventButton->button == 3)
    {
    /* Set temporary list navigation item */
    Navigator = pEGraph->EventIcons;

    /* Go through the list of icon coordinates */
    while(Navigator)
      {
      if( EGMouseOnIcon((gint) pmEventButton->x, 
			(gint) pmEventButton->y,
			(eventInfo*) Navigator->data ) )
	{
	/* Memorize selected event */
	((mainWindow*) pEGraph->MainWindow)->LastSelectedEvent =
	               ((eventInfo*) Navigator->data)->Event;
	((mainWindow*) pEGraph->MainWindow)->EventSelected = TRUE;

	/* Display the popup menu */
	gtk_menu_popup(GTK_MENU(((mainWindow*) pEGraph->MainWindow)->EventGraphPopup),
		       NULL, NULL, NULL, NULL,
		       pmEventButton->button, GDK_CURRENT_TIME);

	return;
	}

      /* Go to the next item in list */
      Navigator = Navigator->next;
      }

    /* No matching event icon so fall through to zoom out */
    EGOneClickZoom(pEGraph, pmEventButton->x, FALSE);
    }
    /* If no corresponding icon was found, no menu will have been displayed */
}

/******************************************************************
 * Function :
 *    SHPTProcessSelect()
 * Description :
 * Parameters :
 * Return values :
 * History :
 * Note :
 ******************************************************************/
void SHPTProcessSelect(GtkWidget* pmWidget, gpointer pmData)
{
  gint           i;                       /* Generic index */
  gchar          lTabing[10];             /* Tab distance between syscall name and time */
  gchar          lTimeStr[TIME_STR_LEN];  /* Time string */
  process*       pProcess;                /* Process selected */
  syscallInfo*   pSyscall;                /* Syscall who's information is to be displayed */
  systemView*    pSysView = NULL;         /* System viewed */
  systemView*    pSysViewPtr;             /* System view pointer */
  GtkWidget*     pTextArea;               /* Text area where process information is to be printed */
  struct timeval lTraceDuration;          /* Duration of trace */

  /* Is there anything to be visualized */
  if((pProcess = (process*) pmData) == NULL)
    return;

  /* Get the system to which this process belongs */
  for(pSysViewPtr = sMainSystemViewList; pSysViewPtr != NULL; pSysViewPtr = pSysViewPtr->Next)
    if(pSysViewPtr->System == pProcess->System)
      pSysView = pSysViewPtr;

  /* Is there any such thing */
  if(pSysView == NULL)
    {
    /* Now I'm lost .... */
    g_print("Internal error: Process doesn't have valid parent system");
    exit(1);
    }

  /* Get the text area where information is to be displayed */
  pTextArea = pSysView->Window->PTProcessText;

  /* Freeze text area */
  gtk_text_freeze(GTK_TEXT(pTextArea));

  /* Erase current text content */
  gtk_text_backward_delete(GTK_TEXT(pTextArea), gtk_text_get_length(GTK_TEXT(pTextArea)));

  /*  Duration */
  DBTimeSub(lTraceDuration, pSysView->EventDB->EndTime, pSysView->EventDB->StartTime);

  /* If the user selected process 0, then show the system-wide analysis */
  if(pProcess->PID == 0)
    {
    /* Main trace characteristics */
    WDITextInsert(pSysView->Window,
		  "Main trace characteristics :\n");
    WDITextInsert(pSysView->Window,
		  "----------------------------\n");
    /*  Start time*/
    DBFormatTimeInReadableString(lTimeStr,
				 pSysView->EventDB->StartTime.tv_sec,
				 pSysView->EventDB->StartTime.tv_usec);
    WDITextInsert(pSysView->Window,
		  "Trace start time: \t %s \n",
		  lTimeStr);

    /*  End time */
    DBFormatTimeInReadableString(lTimeStr,
				 pSysView->EventDB->EndTime.tv_sec,
				 pSysView->EventDB->EndTime.tv_usec);
    WDITextInsert(pSysView->Window,
		  "Trace end time: \t %s \n",
		  lTimeStr);

    /*  Duration */
    DBFormatTimeInReadableString(lTimeStr,
				 lTraceDuration.tv_sec,
				 lTraceDuration.tv_usec);
    WDITextInsert(pSysView->Window,
		  "Trace duration: \t %s \n",
		  lTimeStr);

    /*  Time during which we were runing idle */
    DBFormatTimeInReadableString(lTimeStr,
				 pProcess->TimeRuning.tv_sec,
				 pProcess->TimeRuning.tv_usec);
    WDITextInsert(pSysView->Window,
		  "System idle: \t\t %s => %2.2f %% \n\n",
		  lTimeStr,
		  (float) 100 * (DBGetTimeInDouble(pProcess->TimeRuning) / DBGetTimeInDouble(lTraceDuration)));

    /*  Number of occurences of some events */
    WDITextInsert(pSysView->Window,
		  "Number of occurrences of some key events :\n");
    WDITextInsert(pSysView->Window,
		  "------------------------------------------\n");
    WDITextInsert(pSysView->Window,
		  "Events: \t\t\t %ld \n",
		  pSysView->EventDB->Nb);
    WDITextInsert(pSysView->Window,
		  "Scheduling changes: \t %ld \n",
		  pSysView->System->SchedChange);
    WDITextInsert(pSysView->Window,
		  "Kernel timer tics: \t\t %ld \n",
		  pSysView->System->KernelTimer);
    WDITextInsert(pSysView->Window,
		  "System call entries: \t %ld \n",
		  pSysView->System->SyscallEntry);
    WDITextInsert(pSysView->Window,
		  "System call exits: \t\t %ld \n",
		  pSysView->System->SyscallExit);
    WDITextInsert(pSysView->Window,
		  "Trap entries: \t\t\t %ld \n",
		  pSysView->System->TrapEntry);
    WDITextInsert(pSysView->Window,
		  "Trap exits: \t\t\t %ld \n",
		  pSysView->System->TrapExit);
    WDITextInsert(pSysView->Window,
		  "IRQ entries: \t\t\t %ld \n",
		  pSysView->System->IRQEntry);
    WDITextInsert(pSysView->Window,
		  "IRQ exits: \t\t\t %ld \n",
		  pSysView->System->IRQExit);
    WDITextInsert(pSysView->Window,
		  "Bottom halves: \t\t\t %ld \n",
		  pSysView->System->BH);
    WDITextInsert(pSysView->Window,
		  "Timer expiries: \t\t %ld \n",
		  pSysView->System->TimerExpire);
    WDITextInsert(pSysView->Window,
		  "Page allocations: \t\t %ld \n",
		  pSysView->System->PageAlloc);
    WDITextInsert(pSysView->Window,
		  "Page frees: \t\t\t %ld \n",
		  pSysView->System->PageFree);
    WDITextInsert(pSysView->Window,
		  "Packets Out: \t\t\t %ld \n",
		  pSysView->System->PacketOut);
    WDITextInsert(pSysView->Window,
		  "Packets In: \t\t\t %ld \n\n",
		  pSysView->System->PacketIn);

    /* Print out interrupt information header */
    WDITextInsert(pSysView->Window,"\nSystem Interrupts :\n");
    WDITextInsert(pSysView->Window,"-------------------\n");

    /* Print out interrupt information */
    for (i = 0; i < MAX_NB_INTERRUPTS; i++)
      if(pSysView->System->Interrupts[i] != NULL)
	WDITextInsert(pSysView->Window, "%d: \t %s\n", i, 
		      pSysView->System->Interrupts[i]) ;

    /* Leave a space between interrupts and syscall accounting */
    WDITextInsert(pSysView->Window,"\n");
    
    /* Show system-wide system call analysis */
    pSyscall = pSysView->System->Syscalls;
    }
  else
    {
    /* Process characteristics */
    WDITextInsert(pSysView->Window,
		  "Process characteristics :\n");
    WDITextInsert(pSysView->Window,
		  "-------------------------\n");

    /* Print detailed process information */
    WDITextInsert(pSysView->Window,
		  "Number of system calls: \t\t\t %d \n",
		  pProcess->NbSyscalls);
    WDITextInsert(pSysView->Window,
		  "Number of traps: \t\t\t\t\t %d \n",
		  pProcess->NbTraps);
    WDITextInsert(pSysView->Window,
		  "Quantity of data read from files: \t %d \n",
		  pProcess->QFileRead);
    WDITextInsert(pSysView->Window,
		  "Quantity of data written to files: \t %d \n",
		  pProcess->QFileWrite);
    DBFormatTimeInReadableString(lTimeStr,
				 pProcess->TimeProcCode.tv_sec,
				 pProcess->TimeProcCode.tv_usec);
    WDITextInsert(pSysView->Window,
		  "Time executing process code: \t\t %s => %2.2f %% \n",
		  lTimeStr,
		  (float) 100 * (DBGetTimeInDouble(pProcess->TimeProcCode) / DBGetTimeInDouble(lTraceDuration)));
    DBFormatTimeInReadableString(lTimeStr,
				 pProcess->TimeRuning.tv_sec,
				 pProcess->TimeRuning.tv_usec);
    WDITextInsert(pSysView->Window,
		  "Time running: \t\t\t\t\t\t %s => %2.2f %% \n",
		  lTimeStr,
		  (float) 100 * (DBGetTimeInDouble(pProcess->TimeRuning) / DBGetTimeInDouble(lTraceDuration)));
    DBFormatTimeInReadableString(lTimeStr,
				 pProcess->TimeIO.tv_sec,
				 pProcess->TimeIO.tv_usec);
    WDITextInsert(pSysView->Window,
		  "Time waiting for I/O: \t\t\t\t %s => %2.2f %% \n\n",
		  lTimeStr,
		  (float) 100 * (DBGetTimeInDouble(pProcess->TimeIO) / DBGetTimeInDouble(lTraceDuration)));

    /* Show process-specific system call analysis */
    pSyscall = pProcess->Syscalls;
    }

  /* System call information header */
  if(pSyscall != NULL)
    {
    WDITextInsert(pSysView->Window,
		  "System call accounting (name, nb times called, total time spent in syscall) :\n");
    WDITextInsert(pSysView->Window,
		  "-----------------------------------------------------------------------------\n");
    }

  /* Display the system call analysis */
  for(; pSyscall != NULL; pSyscall = pSyscall->Next)
    {
    /* Compute tabbing according to syscall's name length */
    if(strlen(pSysView->EventDB->SyscallString(pSysView->EventDB, pSyscall->ID)) < 6)
      sprintf(lTabing, "\t\t");
    else if (strlen(pSysView->EventDB->SyscallString(pSysView->EventDB, pSyscall->ID)) < 14)
      sprintf(lTabing, "\t");
    else
      lTabing[0] = '\0';

    /* Insert the system call description */
    DBFormatTimeInReadableString(lTimeStr,
				 pSyscall->Time.tv_sec,
				 pSyscall->Time.tv_usec);
    WDITextInsert(pSysView->Window,
		  "%s: %s %6d \t %s \n",
		  pSysView->EventDB->SyscallString(pSysView->EventDB, pSyscall->ID),
		  lTabing,
		  pSyscall->Nb,
		  lTimeStr);
    }

#if 0
  /* Place view at the begining of the scroll area */ /* This is dirty, but I didn't find any other way. K.Y. */
  gtk_adjustment_set_value(GTK_RANGE(GTK_SCROLLED_WINDOW(pSysView->Window->PTScrolledText)->hscrollbar)->adjustment,
			   0);
  gtk_adjustment_set_value(GTK_RANGE(GTK_SCROLLED_WINDOW(pSysView->Window->PTScrolledText)->vscrollbar)->adjustment,
			   0);
#endif

  /* Thaw text area */
  gtk_text_thaw(GTK_TEXT(pTextArea));
}

/******************************************************************
 * Function :
 *    SHPTRTAITaskSelect()
 * Description :
 *    Handles the occurence of a selection of a RTAI task.
 * Parameters :
 *    pmWidget, The widget selected.
 *    pmData, Pointer to the RTAI task selected
 * Return values :
 *    NONE
 * History :
 *    14/06/2000 K.Y., Initial typing.
 * Note :
 ******************************************************************/
#if SUPP_RTAI
void SHPTRTAITaskSelect(GtkWidget* pmWidget, gpointer pmData)
{
  gchar          lTimeStr[TIME_STR_LEN];  /* Time string */
  RTAItask*      pTask;                   /* Task selected */
  RTAIsystem*    pRTAISystem;             /* RTAI system description */
  systemView*    pSysView = NULL;         /* System viewed */
  systemView*    pSysViewPtr;             /* System view pointer */
  GtkWidget*     pTextArea;               /* Text area where process information is to be printed */
  struct timeval lTraceDuration;          /* Duration of trace */

  /* Is there anything to be visualized */
  if((pTask = (RTAItask*) pmData) == NULL)
    return;

  /* Get the system to which this task belongs */
  for(pSysViewPtr = sMainSystemViewList; pSysViewPtr != NULL; pSysViewPtr = pSysViewPtr->Next)
    if(pSysViewPtr->System == pTask->System)
      pSysView = pSysViewPtr;

  /* Is there any such thing */
  if(pSysView == NULL)
    {
    /* Now I'm lost .... */
    g_print("Internal error: RTAI Task doesn't have valid parent system");
    exit(1);
    }

  /* Get the text area where information is to be displayed */
  pTextArea = pSysView->Window->PTProcessText;

  /* Freeze text area */
  gtk_text_freeze(GTK_TEXT(pTextArea));

  /* Erase current text content */
  gtk_text_backward_delete(GTK_TEXT(pTextArea), gtk_text_get_length(GTK_TEXT(pTextArea)));

  /*  Duration */
  DBTimeSub(lTraceDuration, pSysView->EventDB->EndTime, pSysView->EventDB->StartTime);

  /* Get the RTAI system description */
  pRTAISystem = RTAI_SYSTEM(pSysView->System->SystemSpec);

  /* Are we dealing with the linux task */
  if(pTask->TID == 0)
    {
    /* Main trace characteristics */
    WDITextInsert(pSysView->Window,
		  "Main trace characteristics :\n");
    WDITextInsert(pSysView->Window,
		  "----------------------------\n");
    /*  Start time*/
    DBFormatTimeInReadableString(lTimeStr,
				 pSysView->EventDB->StartTime.tv_sec,
				 pSysView->EventDB->StartTime.tv_usec);
    WDITextInsert(pSysView->Window,
		  "Trace start time: \t %s \n",
		  lTimeStr);

    /*  End time */
    DBFormatTimeInReadableString(lTimeStr,
				 pSysView->EventDB->EndTime.tv_sec,
				 pSysView->EventDB->EndTime.tv_usec);
    WDITextInsert(pSysView->Window,
		  "Trace end time: \t %s \n",
		  lTimeStr);

    /*  Duration */
    DBFormatTimeInReadableString(lTimeStr,
				 lTraceDuration.tv_sec,
				 lTraceDuration.tv_usec);
    WDITextInsert(pSysView->Window,
		  "Trace duration: \t %s \n\n",
		  lTimeStr);


    /*  Number of occurences of some events */
    WDITextInsert(pSysView->Window,
		  "Number of occurrences of some key events :\n");
    WDITextInsert(pSysView->Window,
		  "------------------------------------------\n");
    WDITextInsert(pSysView->Window,
		  "Events: \t\t\t %ld \n",
		  pSysView->EventDB->Nb);
    WDITextInsert(pSysView->Window,
		  "RT-Events: \t\t\t %ld (%2.2f %%) \n",
		  pRTAISystem->NbRTEvents,
		  100 * ((float)pRTAISystem->NbRTEvents) / ((float)pSysView->EventDB->Nb));
    WDITextInsert(pSysView->Window,
		  "RTAI mounts: \t\t\t %ld \n",
		  pRTAISystem->Mount);
    WDITextInsert(pSysView->Window,
		  "RTAI un-mounts: \t\t %ld \n",
		  pRTAISystem->UMount);
    WDITextInsert(pSysView->Window,
		  "Global IRQ entries: \t %ld \n",
		  pRTAISystem->GlobalIRQEntry);
    WDITextInsert(pSysView->Window,
		  "Global IRQ exits: \t\t %ld \n",
		  pRTAISystem->GlobalIRQExit);
    WDITextInsert(pSysView->Window,
		  "CPU-own IRQ entries: \t %ld \n",
		  pRTAISystem->CPUOwnIRQEntry);
    WDITextInsert(pSysView->Window,
		  "CPU-own IRQ exits: \t\t %ld \n",
		  pRTAISystem->CPUOwnIRQExit);
    WDITextInsert(pSysView->Window,
		  "Trap entries: \t\t\t %ld \n",
		  pRTAISystem->TrapEntry);
    WDITextInsert(pSysView->Window,
		  "Trap exits: \t\t\t %ld \n",
		  pRTAISystem->TrapExit);
    WDITextInsert(pSysView->Window,
		  "SRQ entries: \t\t\t %ld \n",
		  pRTAISystem->SRQEntry);
    WDITextInsert(pSysView->Window,
		  "SRQ exits: \t\t\t %ld \n",
		  pRTAISystem->SRQExit);
    WDITextInsert(pSysView->Window,
		  "Switches to Linux: \t\t %ld \n",
		  pRTAISystem->SwitchToLinux);
    WDITextInsert(pSysView->Window,
		  "Switches to RT: \t\t %ld \n",
		  pRTAISystem->SwitchToRT);
    WDITextInsert(pSysView->Window,
		  "RT-Scheduling changes: \t %ld \n",
		  pRTAISystem->SchedChange);
    WDITextInsert(pSysView->Window,
		  "LXRT-Scheduling changes: %ld \n",
		  pRTAISystem->LXRTSchedChange);
    }
  else
    {
    /* Task characteristics */
    WDITextInsert(pSysView->Window,
		  "Task characteristics :\n");
    WDITextInsert(pSysView->Window,
		  "----------------------\n");

    /* Is this task a Linux process buddy */
    if(pTask->IsProcessBuddy == TRUE)
      {
      WDITextInsert(pSysView->Window,
		    "RT buddy of Linux process: \t %s(%d) \n",
		    pTask->BuddyProcess->Command,
		    pTask->BuddyProcess->PID);
      }

    /* Is this a linux process shadow */
    if(pTask->IsProcessShadow == TRUE)
      {
      WDITextInsert(pSysView->Window,
		    "RT shadow of Linux process:  %s(%d) \n",
		    pTask->ShadowProcess->Command,
		    pTask->ShadowProcess->PID);
      }

    /* Task times */
    WDITextInsert(pSysView->Window,
		  "\nTask time info (usecs) :\n");
    WDITextInsert(pSysView->Window,
		  "--------------------------\n");
    DBFormatTimeInReadableString(lTimeStr,
				 pTask->TimeOfBirth.tv_sec,
				 pTask->TimeOfBirth.tv_usec);
    WDITextInsert(pSysView->Window,
		  "Time of birth: \t\t\t\t %s\n",
		  lTimeStr);
    DBFormatTimeInReadableString(lTimeStr,
				 pTask->TimeRunning.tv_sec,
				 pTask->TimeRunning.tv_usec);
    WDITextInsert(pSysView->Window,
		  "Total time running: \t\t %s => %2.2f %% \n",
		  lTimeStr,
		  (float) 100 * (DBGetTimeInDouble(pTask->TimeRunning) / DBGetTimeInDouble(lTraceDuration)));
    WDITextInsert(pSysView->Window,
		  "Number of times scheduled: \t %d \n",
		  pTask->NbTimesScheduled);
    WDITextInsert(pSysView->Window,
		  "Average time running: \t\t %0.2f \n",
		  (float) (DBGetTimeInDouble(pTask->TimeRunning) / (float) pTask->NbTimesScheduled));
    WDITextInsert(pSysView->Window,
		  "Average time between runs: \t %0.2f \n",
		  (float) (DBGetTimeInDouble(pTask->TimeBetweenRuns) / (float) pTask->NbTimesScheduled));

    /* Communication info */
    WDITextInsert(pSysView->Window,
		  "\nTask communication info :\n");
    WDITextInsert(pSysView->Window,
		  "-------------------------\n");
    WDITextInsert(pSysView->Window,
		  "Bytes written to FIFO (PUT): \t %d \n",
		  pTask->QFIFOPut);
    WDITextInsert(pSysView->Window,
		  "Bytes read from FIFO (GET): \t %d \n",
		  pTask->QFIFOGet);
    }

  /* Thaw text area */
  gtk_text_thaw(GTK_TEXT(pTextArea));
}
#endif /* SUPP_RTAI */

/******************************************************************
 * Function :
 *    SHRTEventSelect()
 * Description :
 * Parameters :
 * Return values :
 * History :
 * Note :
 ******************************************************************/
void SHRTEventSelect(GtkWidget*      pmCList,
		     gint            pmRow,
		     gint            pmColumn,
		     GdkEventButton* pmEvent,
		     gpointer        pmData)
{
  systemView*  pSysView;        /* The system being displayed */

  /* Do we have anything meaningfull */
  if((pSysView = (systemView*) pmData) == NULL)
    return;

  /* Store the selected event */
  pSysView->Window->LastSelectedEvent = *(event*) gtk_clist_get_row_data(GTK_CLIST(pmCList), pmRow);
  pSysView->Window->EventSelected = TRUE;
}

/******************************************************************
 * Function :
 *    SHRTEventButtonPress()
 * Description :
 * Parameters :
 * Return values :
 * History :
 * Note :
 ******************************************************************/
void SHRTEventButtonPress(GtkWidget*      pmCList,
			  GdkEventButton* pmEvent,
			  gpointer        pmData)
{
  systemView*  pSysView;        /* The system being displayed */
  gint         row, column;     /* The clicked row and column */

  /* Do we have anything meaningfull */
  if((pSysView = (systemView*) pmData) == NULL)
    return;

  /* if we have a right-click event */
  if(pmEvent->button == 3)
    /* If we clicked on an item, get its row and column values */
    if(gtk_clist_get_selection_info(GTK_CLIST(pmCList), pmEvent->x, pmEvent->y, &row, &column))
      {
      /* Highlight the selected row */
      gtk_clist_select_row(GTK_CLIST(pmCList), row, column);

      /* Store the selected event */
      pSysView->Window->LastSelectedEvent = *(event*) gtk_clist_get_row_data(GTK_CLIST(pmCList), row);
      pSysView->Window->EventSelected = TRUE;

      /* Display the popup menu */
      gtk_menu_popup(GTK_MENU(pSysView->Window->RawEventPopup),
		     NULL, NULL, NULL, NULL,
		     pmEvent->button, GDK_CURRENT_TIME);
      }
}

/******************************************************************
 * Function :
 *    SHRTVAdjustValueChanged()
 * Description :
 * Parameters :
 * Return values :
 * History :
 * Note :
 ******************************************************************/
void SHRTVAdjustValueChanged(GtkAdjustment*  pmVAdjust,
			     gpointer        pmData)
{
  event        lEvent;          /* Event used for searching */
  guint32      lPosition;       /* The position to scroll to */
  systemView*  pSysView;        /* The system being displayed */

  /* Do we have anything meaningfull */
  if((pSysView = (systemView*) pmData) == NULL)
    return;

  /* Is there an event database? */
  if(pSysView->EventDB == NULL)
    return;

  /* Set the pointer to the first event */
  if(pSysView->EventDB->TraceStart == NULL)
    return;

  /* Are we closer to the beginning? */
  if((pmVAdjust->value - (pmVAdjust->upper / 2)) < 0)
    {
    /* Set the navigation pointer to the beginning of the list */
    lEvent =  pSysView->EventDB->FirstEvent;

    /* Calculate distance from beginning */
    lPosition = (guint32) pmVAdjust->value;

    /* Find the event in the event database */
    while(lPosition > 0)
      {
      lPosition--;
      if(DBEventNext(pSysView->EventDB, &lEvent) != TRUE)
	break;
      }
    }
  else
    {
    /* Set the navigation pointer to the end of the list */
    lEvent = pSysView->EventDB->LastEvent;

    /* Calculate distance from end */
    lPosition = (guint32) (pmVAdjust->upper - pmVAdjust->value);

    /* Find the event in the event database */
    while(lPosition > 0)
      {
      lPosition--;
      if(DBEventPrev(pSysView->EventDB, &lEvent) != TRUE)
	break;
      }
    }

  /* Fill the event list according to what was found */
  WDFillEventList(pSysView->Window->RTCList,
		  pSysView->EventDB,
		  pSysView->System,
		  &lEvent,
		  &(pSysView->Window->LastSelectedEvent));
}

/******************************************************************
 * Function :
 *    SHGotoProcAnalysis()
 * Description :
 * Parameters :
 * Return values :
 * History :
 * Note :
 ******************************************************************/
void SHGotoProcAnalysis(GtkWidget* pmWidget, gpointer pmData)
{
  char         lTreeItemType[30]; /* String describing type of item to look for */
  void*        pDataToFind;       /* Generic pointer to data to be found */
  systemView*  pSysView;          /* The system view */
  GtkTreeItem* pTempTreeItem;     /* Temporary pointer to the TreeItem */
  
  if((pSysView = (systemView*) pmData) == NULL)
    {
    g_print("Proc analysis without valid SystemView pointer! \n");
    exit(1);
    }

  /* If an item has been selected by popup menu */
  if(pSysView->Window->EventSelected)
    {
    /* Get the event's ID */
    if(DBEventID(pSysView->EventDB, &(pSysView->Window->LastSelectedEvent)) <= TRACE_MAX)
      {
      /* Get the event's process */
      pDataToFind = (void*) DBEventProcess(pSysView->EventDB, &(pSysView->Window->LastSelectedEvent), pSysView->System, FALSE);

      /* We are looking for process data */
      strcpy(lTreeItemType, TREE_ITEM_DATA_PROC);
      }
    else
#if SUPP_RTAI
      {
      /* Get the event's task */
      pDataToFind = (void*) RTAIDBEventTask(pSysView->EventDB, &(pSysView->Window->LastSelectedEvent), pSysView->System, FALSE);

      /* We are looking for task data */
      strcpy(lTreeItemType, TREE_ITEM_DATA_RTAI_TASK);
      }
#else
      pDataToFind = NULL;
#endif /* SUPP_RTAI */
    
    /* Is there something to look for */
    if(pDataToFind == NULL)
      return;

    /* Search for the TreeItem */
    pTempTreeItem = WDISearchSubTree(GTK_TREE(pSysView->Window->PTProcessTree),
				     lTreeItemType,
				     pDataToFind);

    /* Was a tree item found? */
    if(pTempTreeItem)
      /* Is the TreeItem already selected? */
      if(GTK_WIDGET(pTempTreeItem)->state != GTK_STATE_SELECTED)
	/* Select the node */
	gtk_tree_select_child(GTK_TREE(pSysView->Window->PTProcessTree), GTK_WIDGET(pTempTreeItem));

    /* No event should be selected anymore */
    pSysView->Window->EventSelected = FALSE;
    }

  /* Select the process tree notebook page */
  gtk_notebook_set_page(GTK_NOTEBOOK(pSysView->Window->MNotebook), 1);
}

/******************************************************************
 * Function :
 *    SHViewEventInEG()
 * Description :
 * Parameters :
 * Return values :
 * History :
 * Note :
 ******************************************************************/
void SHViewEventInEG(GtkWidget* pmWidget, gpointer pmData)
{
  systemView*  pSysView;    /* The system view */
  
  if((pSysView = (systemView*) pmData) == NULL)
    {
    g_print("Proc analysis without valid SystemView pointer! \n");
    exit(1);
    }

  /* If an item has been selected by popup menu */
  if(pSysView->Window->EventSelected)
    /* Display that event */
    EGScrollToEvent(pSysView->Window->GTEventGraph, &(pSysView->Window->LastSelectedEvent));

  /* No event should be selected anymore */
  pSysView->Window->EventSelected = FALSE;

  /* Display the event graph notebook page */
  gtk_notebook_set_page(GTK_NOTEBOOK(pSysView->Window->MNotebook), 0);
}

/******************************************************************
 * Function :
 *    SHViewEventInRT()
 * Description :
 * Parameters :
 * Return values :
 * History :
 * Note :
 ******************************************************************/
void SHViewEventInRT(GtkWidget* pmWidget, gpointer pmData)
{
  systemView*  pSysView;  /* The system view */
  
  if((pSysView = (systemView*) pmData) == NULL)
    {
    g_print("SHViewEventInRT without valid SystemView pointer! \n");
    exit(1);
    }

  /* Display the raw events notebook page */
  gtk_notebook_set_page(GTK_NOTEBOOK(pSysView->Window->MNotebook), 2);

  /* If an item has been selected by popup menu */
  if(pSysView->Window->EventSelected)
    {
    /* Select the event found */
    WDISelectRTEvent(pSysView, &(pSysView->Window->LastSelectedEvent));

    /* No event should be selected anymore */
    pSysView->Window->EventSelected = FALSE;
    }
}

/**********************************************************************************/
/******************************* Windowing functions ******************************/
/**********************************************************************************/
/******************************************************************
 * Function :
 *    WDAddAccelerators()
 * Description :
 *    Adds accelerators keys to the application.
 * Parameters :
 *    pmSysView, System view for which signals have to be connected
 * Return values :
 *    NONE
 * History :
 ******************************************************************/
void WDAddAccelerators(systemView* pmSysView)
{
  /* Add acceletor for opening traces */
  gtk_widget_add_accelerator(pmSysView->Window->OpenTrace,
			     "activate",
			     pmSysView->Window->MAccelerator,
			     'O',
			     GDK_CONTROL_MASK,
			     GTK_ACCEL_VISIBLE);

  /* Add acceletor for closing traces */
  gtk_widget_add_accelerator(pmSysView->Window->CloseTrace,
			     "activate",
			     pmSysView->Window->MAccelerator,
			     'C',
			     GDK_CONTROL_MASK,
			     GTK_ACCEL_VISIBLE);

  /* Add acceletor for dumping to file */
  gtk_widget_add_accelerator(pmSysView->Window->DumpToFile,
			     "activate",
			     pmSysView->Window->MAccelerator,
			     'D',
			     GDK_CONTROL_MASK,
			     GTK_ACCEL_VISIBLE);

  /* Add acceletor for exiting the application */
  gtk_widget_add_accelerator(pmSysView->Window->Quit,
			     "activate",
			     pmSysView->Window->MAccelerator,
			     'X',
			     GDK_CONTROL_MASK,
			     GTK_ACCEL_VISIBLE);

  /* Add acceletor for zooming in */
  gtk_widget_add_accelerator(pmSysView->Window->ZoomIn,
			     "activate",
			     pmSysView->Window->MAccelerator,
			     GDK_Page_Up,
			     GDK_CONTROL_MASK,
			     GTK_ACCEL_VISIBLE);

  /* Add acceletor for zooming out */
  gtk_widget_add_accelerator(pmSysView->Window->ZoomOut,
			     "activate",
			     pmSysView->Window->MAccelerator,
			     GDK_Page_Down,
			     GDK_CONTROL_MASK,
			     GTK_ACCEL_VISIBLE);

  /* Add acceletor for showing the horizon */
  gtk_widget_add_accelerator(pmSysView->Window->ShowHorizon,
			     "activate",
			     pmSysView->Window->MAccelerator,
			     'Z',
			     GDK_CONTROL_MASK,
			     GTK_ACCEL_VISIBLE);

  /* Add acceletor for going to an event */
  gtk_widget_add_accelerator(pmSysView->Window->ToolGoToEvent,
			     "activate",
			     pmSysView->Window->MAccelerator,
			     'E',
			     GDK_CONTROL_MASK,
			     GTK_ACCEL_VISIBLE);

  /* Add acceletor for going to viewing a time-frame */
  gtk_widget_add_accelerator(pmSysView->Window->ToolViewTimeFrame,
			     "activate",
			     pmSysView->Window->MAccelerator,
			     'T',
			     GDK_CONTROL_MASK,
			     GTK_ACCEL_VISIBLE);
}

/******************************************************************
 * Function :
 *    WDConnectSignals()
 * Description :
 *    Attaches signal handlers to the window items.
 * Parameters :
 *    pmSysView, System view for which signals have to be connected
 * Return values :
 *    NONE
 * History :
 * Note :
 *    This function attaches a pointer to the main window during
 *    the connect. This means that the handlers will get a pointer
 *    to the window in the data argument.
 ******************************************************************/
void WDConnectSignals(systemView* pmSysView)
{
  /* Connect the main window signals */
  gtk_signal_connect(GTK_OBJECT(pmSysView->Window->MWindow),
		     "delete_event",
		     GTK_SIGNAL_FUNC(SHDeleteEvent),
		     pmSysView);
  gtk_signal_connect(GTK_OBJECT(pmSysView->Window->MWindow),
		     "destroy",
		     GTK_SIGNAL_FUNC(SHDestroy),
		     pmSysView);

  /* Connect the menu items */
  /*  File menu */
  gtk_signal_connect(GTK_OBJECT(pmSysView->Window->OpenTrace),
		     "activate",
		     GTK_SIGNAL_FUNC(SHOpenTrace),
		     pmSysView);
  gtk_signal_connect(GTK_OBJECT(pmSysView->Window->CloseTrace),
		     "activate",
		     GTK_SIGNAL_FUNC(SHCloseTrace),
		     pmSysView);
  gtk_signal_connect(GTK_OBJECT(pmSysView->Window->DumpToFile),
		     "activate",
		     GTK_SIGNAL_FUNC(SHDumpToFile),
		     pmSysView);
  gtk_signal_connect(GTK_OBJECT(pmSysView->Window->Quit),
		     "activate",
		     GTK_SIGNAL_FUNC(SHQuit),
		     pmSysView);
  /*  Tools menu */
  gtk_signal_connect(GTK_OBJECT(pmSysView->Window->ZoomIn),
		     "activate",
		     GTK_SIGNAL_FUNC(SHZoomIn),
		     pmSysView);
  gtk_signal_connect(GTK_OBJECT(pmSysView->Window->ZoomOut),
		     "activate",
		     GTK_SIGNAL_FUNC(SHZoomOut),
		     pmSysView);
  gtk_signal_connect(GTK_OBJECT(pmSysView->Window->ShowHorizon),
		     "activate",
		     GTK_SIGNAL_FUNC(SHShowHorizon),
		     pmSysView);
  gtk_signal_connect(GTK_OBJECT(pmSysView->Window->ToolGoToEvent),
		     "activate",
		     GTK_SIGNAL_FUNC(SHGotoEvent),
		     pmSysView);
  gtk_signal_connect(GTK_OBJECT(pmSysView->Window->ToolViewTimeFrame),
		     "activate",
		     GTK_SIGNAL_FUNC(SHViewTimeFrame),
		     pmSysView);
  /*  Edit menu */
#if 0
  gtk_signal_connect(GTK_OBJECT(pmSysView->Window->),
		     "activate",
		     GTK_SIGNAL_FUNC(),
		     pmSysView);
#endif
  /*  Options menu */
  gtk_signal_connect(GTK_OBJECT(pmSysView->Window->Colors),
		     "activate",
		     GTK_SIGNAL_FUNC(SHColorSelect),
		     pmSysView);
  gtk_signal_connect(GTK_OBJECT(pmSysView->Window->ConfigureDaemon),
		     "activate",
		     GTK_SIGNAL_FUNC(SHConfigureDaemon),
		     pmSysView);
  /*  Help menu */
  gtk_signal_connect(GTK_OBJECT(pmSysView->Window->Contents),
		     "activate",
		     GTK_SIGNAL_FUNC(SHContents),
		     pmSysView);
  gtk_signal_connect(GTK_OBJECT(pmSysView->Window->About),
		     "activate",
		     GTK_SIGNAL_FUNC(SHAbout),
		     pmSysView);

  /* Popup menus */

  /* Raw event Popup menu */
  gtk_signal_connect(GTK_OBJECT(pmSysView->Window->RawGotoProcess),
		     "activate",
		     GTK_SIGNAL_FUNC(SHGotoProcAnalysis),
		     pmSysView);
  gtk_signal_connect(GTK_OBJECT(pmSysView->Window->RawViewEvent),
		     "activate",
		     GTK_SIGNAL_FUNC(SHViewEventInEG),
		     pmSysView);

  /* Event graph Popup menu */
  gtk_signal_connect(GTK_OBJECT(pmSysView->Window->EventGotoProcess),
		     "activate",
		     GTK_SIGNAL_FUNC(SHGotoProcAnalysis),
		     pmSysView);
  gtk_signal_connect(GTK_OBJECT(pmSysView->Window->EventViewRawEvent),
		     "activate",
		     GTK_SIGNAL_FUNC(SHViewEventInRT),
		     pmSysView);

  /* FORCEFULLY disconnect event handlers from the notebook widget */
  /*  I didn't find any cleaner way to do this. K.Y. 9/5/2000 */
  GTK_SIGNAL_FUNC(GTK_WIDGET_CLASS(GTK_OBJECT(pmSysView->Window->MNotebook)->klass)->key_press_event) = NULL,
  GTK_SIGNAL_FUNC(GTK_WIDGET_CLASS(GTK_OBJECT(pmSysView->Window->MNotebook)->klass)->focus_in_event) = NULL,

  /* Connect the key press event */
  gtk_signal_connect(GTK_OBJECT(pmSysView->Window->MWindow),
		     "key_press_event",
		     GTK_SIGNAL_FUNC(SHKeyPressed),
		     pmSysView);

  /* Enable the key-release and key-press events to be emitted */
  gtk_widget_add_events(pmSysView->Window->MWindow,
			GDK_KEY_RELEASE_MASK);

  /* Connect the key released event */
  gtk_signal_connect(GTK_OBJECT(pmSysView->Window->MWindow),
		     "key_release_event",
		     GTK_SIGNAL_FUNC(SHKeyReleased),
		     pmSysView);

  /* Set signals for event graph */
  EGConnectSignals(pmSysView->Window->GTEventGraph);

  /* Set process tree callbacks */
#if 0 /* This is now done in WDFillTree */
  gtk_signal_connect(GTK_OBJECT(pmSysView->Window->PTProcessTree),
		     "select_child",
		     GTK_SIGNAL_FUNC(SHPTProcessSelect),
		     pmSysView);
#endif

  /* Set event list callbacks */
  gtk_signal_connect(GTK_OBJECT(pmSysView->Window->RTCList),
		     "select_row",
		     GTK_SIGNAL_FUNC(SHRTEventSelect),
		     pmSysView);
  gtk_signal_connect(GTK_OBJECT(pmSysView->Window->RTCList),
		     "button-press-event",
		     GTK_SIGNAL_FUNC(SHRTEventButtonPress),
		     pmSysView);
  gtk_signal_connect(GTK_OBJECT(pmSysView->Window->RTVAdjust),
		     "value-changed",
		     GTK_SIGNAL_FUNC(SHRTVAdjustValueChanged),
		     pmSysView);

  /* Set DrawArea Popup menu callback */
  gtk_signal_connect(GTK_OBJECT(pmSysView->Window->GTEventGraph->DrawArea),
		     "button-press-event",
		     GTK_SIGNAL_FUNC(SHEGIconButtonPress),
		     pmSysView->Window->GTEventGraph);

  /* Add the accelerator keys */
  WDAddAccelerators(pmSysView);

#if 0 /* For coding only */
  gtk_signal_connect(GTK_OBJECT(pmSysView->Window->),
		     ,
		     GTK_SIGNAL_FUNC(),
		     pmSysView);
#endif
}

/******************************************************************
 * Function :
 *    WDShowMainWindow()
 * Description :
 *    Displays the toolkit window.
 * Parameters :
 *    pmWindow, Window to be displayed.
 * Return values :
 *    NONE.
 * History :
 * Note :
 ******************************************************************/
void WDShowMainWindow(systemView* pmSysView)
{
  mainWindow* pmWindow = pmSysView->Window; /* pointer to the main window */

  /* Show all the widgets */
  /*  Main widgets */
  gtk_widget_show(pmWindow->MVBox);
  gtk_widget_show(pmWindow->MMenu);
  gtk_widget_show(pmWindow->MNotebook);
  gtk_widget_show(pmWindow->MStatusBarBox);
  gtk_widget_show(pmWindow->MToolBar);

  /*  Main menu items */
  gtk_widget_show(pmWindow->FileMenuTitle);
#if 0
  gtk_widget_show(pmWindow->EditMenuTitle);
#endif
  gtk_widget_show(pmWindow->ToolsMenuTitle);
  gtk_widget_show(pmWindow->OptionsMenuTitle);
#if 0
  gtk_widget_show(pmWindow->TraceMenuTitle);
#endif
  gtk_widget_show(pmWindow->HelpMenuTitle);

  /*  Submenus */

  /*  File menu items */
  gtk_widget_show(pmWindow->OpenTrace);
  gtk_widget_show(pmWindow->CloseTrace);
  gtk_widget_show(pmWindow->DumpToFile);
  gtk_widget_show(pmWindow->FileMenuSeparator1);
  gtk_widget_show(pmWindow->Quit);

  /* Tools menu items */
  gtk_widget_show(pmWindow->ZoomIn);
  gtk_widget_show(pmWindow->ZoomOut);
  gtk_widget_show(pmWindow->ToolMenuSeparator1);
  gtk_widget_show(pmWindow->ShowHorizon);
  gtk_widget_show(pmWindow->ToolMenuSeparator2);
  gtk_widget_show(pmWindow->ToolGoToEvent);
  gtk_widget_show(pmWindow->ToolViewTimeFrame);

  /*  Options menu items */
  gtk_widget_show(pmWindow->Colors);
#if 0
  gtk_widget_show(pmWindow->OptMenuSeparator1);
  gtk_widget_show(pmWindow->ConfigureDaemon);
#endif

  /*  Help menu items */
  gtk_widget_show(pmWindow->Contents);
  gtk_widget_show(pmWindow->HelpMenuSeparator1);
  gtk_widget_show(pmWindow->About);

  /* Popup menus */

  /* Raw event popup and items */
  gtk_widget_show(pmWindow->RawEventPopup);
  gtk_widget_show(pmWindow->RawViewEvent);
  gtk_widget_show(pmWindow->RawGotoProcess);

  /* Event graph popup and items */
  gtk_widget_show(pmWindow->EventGraphPopup);
  gtk_widget_show(pmWindow->EventGotoProcess);
  gtk_widget_show(pmWindow->EventViewRawEvent);

  /* Note: Toolbar Buttons are created at the same time Signals are connected down
     at WDToolBarPopulate */

  /*  The Notebook thumbnails */
  gtk_widget_show(pmWindow->Graph);
  gtk_widget_show(pmWindow->Process);
  gtk_widget_show(pmWindow->RawTrace);

  /*  Graph thumbnail */
  gtk_widget_show(pmWindow->GTHBox);

  /*  Process thumbnail */
  gtk_widget_show(pmWindow->PTHPanned);
  gtk_widget_show(pmWindow->PTScrolledTree);
  gtk_widget_show(pmWindow->PTProcessTree);
  gtk_widget_show(pmWindow->PTScrolledText);
  gtk_widget_show(pmWindow->PTProcessText);

  /*  Raw event trace */
  gtk_widget_show(pmWindow->RTHBox);
  gtk_widget_show(pmWindow->RTCList);
  gtk_widget_show(pmWindow->RTVScroll);

  /*  Status bar components */
  gtk_widget_show(pmWindow->MainSBar);
  gtk_widget_show(pmWindow->BegTimeSBar);
  gtk_widget_show(pmWindow->EndTimeSBar);

  /* Set main window title if it has not been set */
  if(!pmSysView->Options->InputFileName)
    gtk_window_set_title(GTK_WINDOW(pmWindow->MWindow), "Trace Visualizer");

  /* Place the window in the middle of the screen */
  gtk_window_set_position(GTK_WINDOW(pmWindow->MWindow), GTK_WIN_POS_CENTER);

  /* Set window size */
#if 1
  gtk_widget_set_usize(GTK_WIDGET(pmWindow->MWindow), 770, 400);
#else
  gtk_widget_set_usize(GTK_WIDGET(pmWindow->MWindow), 400, 200);
#endif

  /* Main window, ALWAYS DO THIS LAST */
  gtk_widget_show(pmWindow->MWindow);

  /* Populate the toolbar and attach its signal handlers.  If you do this
     before the previous two operations, each pixmap throws an error. */
  WDToolBarPopulate(pmSysView);

  /* Event graph */
  EGShowEventGraph(pmWindow->GTEventGraph);

  /* Set main window icon */
  WDISetWindowIcon(pmWindow->MWindow);

  /* Enable menu items if an InputFile is opened */
  WDSetMenusSensitivity(pmSysView, pmSysView->Options->InputFileName != NULL);
}

/******************************************************************
 * Function :
 *    WDCreateMainWindow()
 * Description :
 *    Creates a toolkit main window.
 * Parameters :
 *    pmSysView, The system view the window will display.
 * Return values :
 *    Pointer to the newly created window.
 * History :
 * Note :
 *    Exits if there's a memory allocation problem.
 ******************************************************************/
mainWindow* WDCreateMainWindow(systemView* pmSysView)
{
  gchar*         RTCListTitles[RTCLIST_NB_COLUMNS] = {"CPU-ID",
                                                      "Event",
						      "Time",
						      "PID",
						      "Entry Length",
						      "Event Description"};
  mainWindow*    pWindow;     /* The main window to be created */

  /* Create space for the new window */
  if((pWindow = (mainWindow*) g_malloc(sizeof(mainWindow))) == NULL)
    {
    printf("Memory allocation problem \n");
    exit(1);
    }

  /* Initialize the fields that don't need extensive treatment */
  pWindow->SystemView          = pmSysView;
  pWindow->tlbOpenTrace        = NULL;
  pWindow->tlbCloseTrace       = NULL;
  pWindow->tlbDumpFile         = NULL;
  pWindow->tlbZoomIn           = NULL;
  pWindow->tlbZoomOut          = NULL;
  pWindow->tlbGotoEvent        = NULL;
  pWindow->tlbShowHorizon      = NULL;
  pWindow->tlbHideSysCalls     = NULL;
  pWindow->tlbHideIconText     = NULL;
  pWindow->tlbHideIRQs         = NULL;
  pWindow->tlbHideTraps        = NULL;
  pWindow->tlbHideSoftIRQs     = NULL;
  pWindow->tlbHideSchedChange  = NULL;
  pWindow->tlbSlowH            = NULL;
  pWindow->tlbSlowV            = NULL;
  pWindow->tlbSlowI            = NULL;
  pWindow->OpenTraceWindow     = NULL;
  pWindow->ColorSelectWindow   = NULL;
  pWindow->ViewTimeFrameWindow = NULL;
  pWindow->GotoEventWindow     = NULL;
  pWindow->DumpToFileWindow    = NULL;
  pWindow->HelpContents        = NULL;
  pWindow->AboutBox            = NULL;

  /* Allocate the main window's ressources */
  pWindow->MWindow       = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  pWindow->MVBox         = gtk_vbox_new(FALSE, 0);
  pWindow->MMenu         = gtk_menu_bar_new();
  pWindow->MToolBar      = gtk_toolbar_new(GTK_ORIENTATION_HORIZONTAL, GTK_TOOLBAR_ICONS);
  pWindow->MNotebook     = gtk_notebook_new();
  pWindow->MStatusBarBox = gtk_hbox_new(FALSE, 0);
  pWindow->MAccelerator  = gtk_accel_group_new();

  /* Attach accelerator group to main window */
  gtk_accel_group_attach(pWindow->MAccelerator, GTK_OBJECT(pWindow->MWindow));

  /* Pack the main window widgets */
  gtk_container_add(GTK_CONTAINER(pWindow->MWindow), pWindow->MVBox);
  gtk_box_pack_start(GTK_BOX(pWindow->MVBox), pWindow->MMenu, FALSE, TRUE, 0);
  gtk_box_pack_start(GTK_BOX(pWindow->MVBox), pWindow->MToolBar, FALSE, TRUE, 0);
  gtk_box_pack_start(GTK_BOX(pWindow->MVBox), pWindow->MNotebook, TRUE, TRUE, 0);
  gtk_box_pack_start(GTK_BOX(pWindow->MVBox), pWindow->MStatusBarBox, FALSE, TRUE, 0);

  /* Create the menu titles */
  pWindow->FileMenuTitle    = gtk_menu_item_new_with_label("File");
  pWindow->EditMenuTitle    = gtk_menu_item_new_with_label("Edit");
  pWindow->ToolsMenuTitle   = gtk_menu_item_new_with_label("Tools");
  pWindow->OptionsMenuTitle = gtk_menu_item_new_with_label("Options");
  pWindow->TraceMenuTitle   = gtk_menu_item_new_with_label("Trace");
  pWindow->HelpMenuTitle    = gtk_menu_item_new_with_label("Help");

  /* Pack the menu titles */
  gtk_menu_bar_append(GTK_MENU_BAR(pWindow->MMenu), pWindow->FileMenuTitle);
#if 0
  gtk_menu_bar_append(GTK_MENU_BAR(pWindow->MMenu), pWindow->EditMenuTitle);
#endif
  gtk_menu_bar_append(GTK_MENU_BAR(pWindow->MMenu), pWindow->ToolsMenuTitle);
  gtk_menu_bar_append(GTK_MENU_BAR(pWindow->MMenu), pWindow->OptionsMenuTitle);
  gtk_menu_bar_append(GTK_MENU_BAR(pWindow->MMenu), pWindow->TraceMenuTitle);
  gtk_menu_bar_append(GTK_MENU_BAR(pWindow->MMenu), pWindow->HelpMenuTitle);

  /* Create the submenus */
  pWindow->FileMenu    = gtk_menu_new();
  pWindow->EditMenu    = gtk_menu_new();
  pWindow->ToolsMenu   = gtk_menu_new();
  pWindow->OptionsMenu = gtk_menu_new();
  pWindow->TraceMenu   = gtk_menu_new();
  pWindow->HelpMenu    = gtk_menu_new();

  /* Set the submenus as corresponding to their titles */
  gtk_menu_item_set_submenu(GTK_MENU_ITEM(pWindow->FileMenuTitle), pWindow->FileMenu);
  gtk_menu_item_set_submenu(GTK_MENU_ITEM(pWindow->EditMenuTitle), pWindow->EditMenu);
  gtk_menu_item_set_submenu(GTK_MENU_ITEM(pWindow->ToolsMenuTitle), pWindow->ToolsMenu);
  gtk_menu_item_set_submenu(GTK_MENU_ITEM(pWindow->OptionsMenuTitle), pWindow->OptionsMenu);
  gtk_menu_item_set_submenu(GTK_MENU_ITEM(pWindow->TraceMenuTitle), pWindow->TraceMenu);
  gtk_menu_item_set_submenu(GTK_MENU_ITEM(pWindow->HelpMenuTitle), pWindow->HelpMenu);
  
  /* Create file menu items */
  pWindow->OpenTrace  = gtk_menu_item_new_with_label("Open Trace");
  pWindow->CloseTrace = gtk_menu_item_new_with_label("Close Trace");
  pWindow->DumpToFile = gtk_menu_item_new_with_label("Dump To File");
  pWindow->FileMenuSeparator1 = gtk_menu_item_new();
  pWindow->Quit       = gtk_menu_item_new_with_label("Exit");

  /* Fill the file menu */
  gtk_menu_append(GTK_MENU(pWindow->FileMenu), pWindow->OpenTrace);
  gtk_menu_append(GTK_MENU(pWindow->FileMenu), pWindow->CloseTrace);
  gtk_menu_append(GTK_MENU(pWindow->FileMenu), pWindow->DumpToFile);
  gtk_menu_append(GTK_MENU(pWindow->FileMenu), pWindow->FileMenuSeparator1);
  gtk_menu_append(GTK_MENU(pWindow->FileMenu), pWindow->Quit);

  /* Create the tools menu items */
  pWindow->ZoomIn             = gtk_menu_item_new_with_label("Zoom In");
  pWindow->ZoomOut            = gtk_menu_item_new_with_label("Zoom Out");
  pWindow->ToolMenuSeparator1 = gtk_menu_item_new();
  pWindow->ShowHorizon        = gtk_check_menu_item_new_with_label("Show Horizon");
  gtk_check_menu_item_set_show_toggle(GTK_CHECK_MENU_ITEM(pWindow->ShowHorizon),TRUE);
  pWindow->ToolMenuSeparator2 = gtk_menu_item_new();
  pWindow->ToolGoToEvent      = gtk_menu_item_new_with_label("Go to event...");
  pWindow->ToolViewTimeFrame  = gtk_menu_item_new_with_label("View Time Frame");

  /* Fill the tools menu */
  gtk_menu_append(GTK_MENU(pWindow->ToolsMenu), pWindow->ZoomIn);
  gtk_menu_append(GTK_MENU(pWindow->ToolsMenu), pWindow->ZoomOut);
  gtk_menu_append(GTK_MENU(pWindow->ToolsMenu), pWindow->ToolMenuSeparator1);
  gtk_menu_append(GTK_MENU(pWindow->ToolsMenu), pWindow->ShowHorizon);
  gtk_menu_append(GTK_MENU(pWindow->ToolsMenu), pWindow->ToolMenuSeparator2);
  gtk_menu_append(GTK_MENU(pWindow->ToolsMenu), pWindow->ToolGoToEvent);
  gtk_menu_append(GTK_MENU(pWindow->ToolsMenu), pWindow->ToolViewTimeFrame);

  /* Create options menu items */
  pWindow->Colors            = gtk_menu_item_new_with_label("Colors");
  pWindow->OptMenuSeparator1 = gtk_menu_item_new();
  pWindow->ConfigureDaemon   = gtk_menu_item_new_with_label("Configure Trace Daemon");

  /* Fill the options menu */
  gtk_menu_append(GTK_MENU(pWindow->OptionsMenu), pWindow->Colors);
  gtk_menu_append(GTK_MENU(pWindow->OptionsMenu), pWindow->OptMenuSeparator1);
  gtk_menu_append(GTK_MENU(pWindow->OptionsMenu), pWindow->ConfigureDaemon);

  /* Create help menu items */
  pWindow->Contents = gtk_menu_item_new_with_label("Contents");
  pWindow->HelpMenuSeparator1 = gtk_menu_item_new();
  pWindow->About    = gtk_menu_item_new_with_label("About");

  /* Fill the help menu */
  gtk_menu_append(GTK_MENU(pWindow->HelpMenu), pWindow->Contents);
  gtk_menu_append(GTK_MENU(pWindow->HelpMenu), pWindow->HelpMenuSeparator1);
  gtk_menu_append(GTK_MENU(pWindow->HelpMenu), pWindow->About);

  /* Create the Popup menus */

  /* Create and fill the Raw Event popup */
  pWindow->RawEventPopup = gtk_menu_new();
  pWindow->RawViewEvent  = gtk_menu_item_new_with_label("View event in graph");
  gtk_menu_append(GTK_MENU(pWindow->RawEventPopup), pWindow->RawViewEvent);
  pWindow->RawGotoProcess   = gtk_menu_item_new_with_label("Go to process analysis");
  gtk_menu_append(GTK_MENU(pWindow->RawEventPopup), pWindow->RawGotoProcess);

  /* Create and fill the Event graph popup */
  pWindow->EventGraphPopup   = gtk_menu_new();
  pWindow->EventViewRawEvent = gtk_menu_item_new_with_label("View raw event data");
  gtk_menu_append(GTK_MENU(pWindow->EventGraphPopup), pWindow->EventViewRawEvent);
  pWindow->EventGotoProcess  = gtk_menu_item_new_with_label("Go to process analysis");
  gtk_menu_append(GTK_MENU(pWindow->EventGraphPopup), pWindow->EventGotoProcess);

  /* Create thumbnail labels */
  pWindow->Graph    = gtk_label_new("Event Graph");
  pWindow->Process  = gtk_label_new("Process analysis");
  pWindow->RawTrace = gtk_label_new("Raw Trace");

  /* Create thumbnails' main content */
  pWindow->GTHBox     = gtk_hbox_new(FALSE, 0);
  pWindow->PTHPanned  = gtk_hpaned_new();
  pWindow->RTHBox     = gtk_hbox_new(FALSE, 0);
  gtk_container_set_border_width(GTK_CONTAINER(pWindow->PTHPanned), 5);
  gtk_container_set_border_width(GTK_CONTAINER(pWindow->RTHBox), 5);

  /* Create the notebook's pages */
  gtk_notebook_append_page(GTK_NOTEBOOK(pWindow->MNotebook), pWindow->GTHBox, pWindow->Graph);
  gtk_notebook_append_page(GTK_NOTEBOOK(pWindow->MNotebook), pWindow->PTHPanned, pWindow->Process);
  gtk_notebook_append_page(GTK_NOTEBOOK(pWindow->MNotebook), pWindow->RTHBox, pWindow->RawTrace);

  /* Create the event graph to be placed in the graph hbox */
  pWindow->GTEventGraph = EGCreateEventGraph(pWindow);

  /* Create window containing scrollable process tree */
  pWindow->PTProcessTree  = gtk_tree_new();
  pWindow->PTScrolledTree = gtk_scrolled_window_new(NULL, NULL);
  gtk_tree_set_selection_mode(GTK_TREE(pWindow->PTProcessTree), GTK_SELECTION_SINGLE);
  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(pWindow->PTScrolledTree),
				 GTK_POLICY_AUTOMATIC,
				 GTK_POLICY_AUTOMATIC);
  gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(pWindow->PTScrolledTree),
					pWindow->PTProcessTree);
  gtk_paned_add1(GTK_PANED(pWindow->PTHPanned), pWindow->PTScrolledTree);
  gtk_widget_set_usize(GTK_WIDGET(pWindow->PTScrolledTree), 175, 0);

  /* Create process text space */
  pWindow->PTScrolledText = gtk_scrolled_window_new(NULL, NULL);
  pWindow->PTProcessText  = gtk_text_new(NULL, NULL);
#if 0 /* This should be configurable through a font menu ... */
  pWindow->PTTextFont     = gdk_font_load("-*-courier-medium-r-*-*-12-*-*-*-m-*-*-*");
#else
  pWindow->PTTextFont     = gdk_font_load("-misc-fixed-medium-r-normal--10-100-75-75-c-60-iso8859-1");
#if 0
  pWindow->PTTextFont     = gdk_font_load("-misc-fixed-bold-r-normal--12-120-75-75-c-80-iso8859-1");
#endif
#endif
  gtk_text_set_editable(GTK_TEXT(pWindow->PTProcessText), FALSE);
  gtk_container_add(GTK_CONTAINER(pWindow->PTScrolledText),
		    pWindow->PTProcessText);
  gtk_paned_add2(GTK_PANED(pWindow->PTHPanned), pWindow->PTScrolledText);

  /* Create raw trace list and pack it */
  pWindow->RTCList  = gtk_clist_new_with_titles(RTCLIST_NB_COLUMNS, RTCListTitles);
  gtk_clist_set_selection_mode(GTK_CLIST(pWindow->RTCList), GTK_SELECTION_SINGLE);
  gtk_box_pack_start(GTK_BOX(pWindow->RTHBox), pWindow->RTCList, TRUE, TRUE, 0);

  /* Create vertical scrollbar and pack it */
  pWindow->RTVScroll  = gtk_vscrollbar_new(NULL);
  gtk_box_pack_start(GTK_BOX(pWindow->RTHBox), pWindow->RTVScroll, FALSE, TRUE, 0);

  /* Get the vertical scrollbar's adjustment */
  pWindow->RTVAdjust = gtk_range_get_adjustment(GTK_RANGE(pWindow->RTVScroll));

  /* Configure the columns of the list */
  gtk_clist_set_column_justification(GTK_CLIST(pWindow->RTCList), 0, GTK_JUSTIFY_LEFT);
  gtk_clist_set_column_justification(GTK_CLIST(pWindow->RTCList), 1, GTK_JUSTIFY_LEFT);
  gtk_clist_set_column_justification(GTK_CLIST(pWindow->RTCList), 2, GTK_JUSTIFY_RIGHT);
  gtk_clist_set_column_justification(GTK_CLIST(pWindow->RTCList), 3, GTK_JUSTIFY_RIGHT);
  gtk_clist_set_column_justification(GTK_CLIST(pWindow->RTCList), 4, GTK_JUSTIFY_RIGHT);
  gtk_clist_set_column_justification(GTK_CLIST(pWindow->RTCList), 5, GTK_JUSTIFY_LEFT);
  gtk_clist_set_column_width(GTK_CLIST(pWindow->RTCList), 0, 45);
  gtk_clist_set_column_width(GTK_CLIST(pWindow->RTCList), 1, 120);
  gtk_clist_set_column_width(GTK_CLIST(pWindow->RTCList), 2, 120);
  gtk_clist_set_column_width(GTK_CLIST(pWindow->RTCList), 3, 45);
  gtk_clist_set_column_width(GTK_CLIST(pWindow->RTCList), 4, 60);

  /* Allocate the status bar components */
  pWindow->MainSBar    = gtk_statusbar_new();
  pWindow->BegTimeSBar = gtk_statusbar_new();
  pWindow->EndTimeSBar = gtk_statusbar_new();

  /* Set the size of the status bar components */
  gtk_widget_set_usize(GTK_WIDGET(pWindow->BegTimeSBar), 160, 0);
  gtk_widget_set_usize(GTK_WIDGET(pWindow->EndTimeSBar), 160, 0);

  /* Get the status bar contexts */
  pWindow->MainSBarContextID =
    gtk_statusbar_get_context_id(GTK_STATUSBAR(pWindow->MainSBar),
				 "Main Status Bar");
  pWindow->BegTimeSBarContextID =
    gtk_statusbar_get_context_id(GTK_STATUSBAR(pWindow->MainSBar),
				 "Begining time Status Bar");
  pWindow->EndTimeSBarContextID =
    gtk_statusbar_get_context_id(GTK_STATUSBAR(pWindow->MainSBar),
				 "End time Status Bar");

  /* Pack the status bars into the status bar hbox */
  gtk_box_pack_start(GTK_BOX(pWindow->MStatusBarBox), pWindow->MainSBar, TRUE, TRUE, 0);
  gtk_box_pack_start(GTK_BOX(pWindow->MStatusBarBox), pWindow->BegTimeSBar, FALSE, TRUE, 5);
  gtk_box_pack_start(GTK_BOX(pWindow->MStatusBarBox), pWindow->EndTimeSBar, FALSE, TRUE, 0);

  /* No events have been selected */
  pWindow->EventSelected = FALSE;

  /* Give the caller the newly created window */
  return pWindow;
}

/******************************************************************
 * Function :
 *    WDDestroySystemView()
 * Description :
 *    Destroys a toolkit main window.
 * Parameters :
 *    pmSysView, pointer to the systemview to be destroyed
 * Return values :
 *    NONE
 * History :
 * Note :
 *    Event structures must be freed first. see WDIFreeTraceStructures().
 ******************************************************************/
void WDDestroySystemView(systemView* pmSystemView)
{
  systemView* Navigator; /* Temporary System View pointer */

  /* free the system elements */
  WDIFreeTraceStructures(pmSystemView);
  if(pmSystemView->Window)
    {
    /* Free the Event Graph structures */
    EGDestroyEventGraph(&pmSystemView->Window->GTEventGraph);

    /* Free the window itself */
    g_free(pmSystemView->Window);
    }

  /* Dequeue this system view from the main system view list */

  /* Is this SystemView the first one in the list? */
  if(sMainSystemViewList == pmSystemView) 
    /* Update the main list pointer */
    sMainSystemViewList = pmSystemView->Next;
  else
    {
    /* Find the previous item in the list */
    for(Navigator = sMainSystemViewList; Navigator->Next != pmSystemView; Navigator = Navigator->Next);

    /* Update the list pointer */
    Navigator->Next = pmSystemView->Next;
    }

  /* Free that SystemView */
  g_free(pmSystemView);
}

/******************************************************************
 * Function :
 *    WDFillTree()
 * Description :
 *    Fills a GTK tree with the content of the tree of processes in
 *    the system.
 * Parameters :
 *    pmGTKTree,
 *    pmTree, 
 * Return values :
 *    NONE.
 * History :
 *    K.Y., 17/06/99, Initial typing.
 * Note :
 ******************************************************************/
void WDFillTree(GtkWidget* pmGTKTree, process* pmTree)
{
  char       lLabel[256]; /* Maximum length of label*/
  process*   pProc;       /* Generic process pointer */
  GtkWidget* pTreeItem;   /* An item in the process tree */
  GtkWidget* pSubTree;    /* Subtree for children */

  /* For all the children of the same level */
  for(pProc = pmTree; pProc != NULL; pProc = pProc->NextChild)
    {
    /* Does this process have a name */
    if(pProc->Command != NULL)
      sprintf(lLabel, "%s (%d)", pProc->Command, pProc->PID);
    else if(pProc->PID == 0)
      sprintf(lLabel, "The All Mighty (0)");
    else
      sprintf(lLabel, "%d", pProc->PID);

    /* Create a new tree item */
    pTreeItem = gtk_tree_item_new_with_label(lLabel);
 
    /* Store Process pointer in the row data */
    gtk_object_set_data(GTK_OBJECT(pTreeItem),
			TREE_ITEM_DATA_PROC,
			(gpointer) pProc);

    /* Connect a signal to this item */
    gtk_signal_connect(GTK_OBJECT(pTreeItem),
		       "select",
		       GTK_SIGNAL_FUNC(SHPTProcessSelect),
		       pProc);

    /* Append this to the tree */
    gtk_tree_prepend (GTK_TREE(pmGTKTree), pTreeItem);

    /* Show it to the public */
    gtk_widget_show(pTreeItem);

    /* Does this process have any children */
    if(pProc->Children != NULL)
      {
      /* Create a subtree */
      pSubTree = gtk_tree_new();
      gtk_tree_set_selection_mode (GTK_TREE(pSubTree), GTK_SELECTION_SINGLE);
      gtk_tree_set_view_mode (GTK_TREE(pSubTree), GTK_TREE_VIEW_ITEM);
      gtk_tree_item_set_subtree (GTK_TREE_ITEM(pTreeItem), pSubTree);

      /* Fill the subtree */
      WDFillTree(pSubTree, pProc->Children);
      }
    }  
}

/******************************************************************
 * Function :
 *    WDFillRTAITaskTree()
 * Description :
 *    Fills a GTK tree with the content of the tree of tasks in
 *    the RTAI system.
 * Parameters :
 *    pmGTKTree, The GTK tree where tasks are to be inserted.
 *    pmTree, The task tree to be used to fill the GTK tree.
 * Return values :
 *    NONE.
 * History :
 *    K.Y., 14/06/2000, This is largely inspired by WDFillTree.
 * Note :
 ******************************************************************/
#if SUPP_RTAI
void WDFillRTAITaskTree(GtkWidget* pmGTKTree, RTAItask* pmTree)
{
  char       lLabel[256]; /* Maximum length of label*/
  RTAItask*  pTask;       /* Generic task pointer */
  GtkWidget* pTreeItem;   /* An item in the task tree */
  GtkWidget* pSubTree;    /* Subtree for children */

  /* For all the children of the same level */
  for(pTask = pmTree; pTask != NULL; pTask = pTask->NextChild)
    {
    /* Print the task ID */
    if(pTask->TID != 0)
      sprintf(lLabel, "%d", pTask->TID);
    else
      sprintf(lLabel, "RTAI Subsystem");

    /* Create a new tree item */
    pTreeItem = gtk_tree_item_new_with_label(lLabel);
 
    /* Store task pointer in the raw data */
    gtk_object_set_data(GTK_OBJECT(pTreeItem),
			TREE_ITEM_DATA_RTAI_TASK,
			(gpointer) pTask);

    /* Connect a signal to this item */
    gtk_signal_connect(GTK_OBJECT(pTreeItem),
		       "select",
		       GTK_SIGNAL_FUNC(SHPTRTAITaskSelect),
		       pTask);

    /* Append this to the tree */
    gtk_tree_prepend (GTK_TREE(pmGTKTree), pTreeItem);

    /* Show it to the public */
    gtk_widget_show(pTreeItem);

    /* Does this task have any children */
    if(pTask->Children != NULL)
      {
      /* Create a subtree */
      pSubTree = gtk_tree_new();
      gtk_tree_set_selection_mode (GTK_TREE(pSubTree), GTK_SELECTION_SINGLE);
      gtk_tree_set_view_mode (GTK_TREE(pSubTree), GTK_TREE_VIEW_ITEM);
      gtk_tree_item_set_subtree (GTK_TREE_ITEM(pTreeItem), pSubTree);

      /* Fill the subtree */
      WDFillRTAITaskTree(pSubTree, pTask->Children);
      }
    }  
}
#endif /* SUPP_RTAI */

/******************************************************************
 * Function :
 *    WDFillEventList()
 * Description :
 *    Fills the window's event list using the trace database.
 * Parameters :
 *    pmList, The list to be filled.
 *    pmTraceDB, The database of events.
 *    pmSystem, The system to which this list belongs.
 *    pmEvent, Event from which we start drawing.
 *    pmSelectedEvent, Event selected if any.
 * Return values :
 *    NONE.
 * History :
 *    K.Y., 18/06/99, Initial typing.
 * Note :
 ******************************************************************/
void WDFillEventList(GtkWidget*  pmList,
		     db*         pmTraceDB,
		     systemInfo* pmSystem,
		     event*      pmEvent,
		     event*      pmSelectedEvent)
{
  gint                i = 0;                              /* Generic index */
  event               lEvent;                             /* Generic event */
  gchar               lTimeStr[TIME_STR_LEN];             /* Time of event */
  static gchar*       lString[RTCLIST_NB_COLUMNS]={'\0'}; /* Strings describing event */
  process*            pProcess;                           /* Generic process pointer */
#if SUPP_RTAI
  RTAItask*           pTask = NULL;                       /* Generic task pointer */
#endif /* SUPP_RTAI */
  eventDescription    lEventDesc;                         /* Description of event */

  /* Did we allocate space for strings */
  if(lString[0] == NULL)
    /* Allocate space for strings */
    for (i = 0;  i < RTCLIST_NB_COLUMNS; i++)
      lString[i] = (char*) g_malloc(80);

  /* If no event was supplied, start at the beginning */
  if(pmEvent == NULL)
    lEvent = pmTraceDB->FirstEvent;
  else
    lEvent = *pmEvent;

  /* Freeze and clear clist */
  gtk_clist_freeze(GTK_CLIST(pmList));
  gtk_clist_clear(GTK_CLIST(pmList));

  /* Go through the event list */
  for(i = 0;
      (DBEventNext(pmTraceDB, &lEvent) == TRUE) && (i < RTCLIST_NB_ROWS);
      i++)
    {
    /* Get the event description */
    DBEventDescription(pmTraceDB, &lEvent, TRUE, &lEventDesc);

    /* Get the event's process */
    pProcess = DBEventProcess(pmTraceDB, &lEvent, pmSystem, FALSE);

#if SUPP_RTAI
    /* Does this trace contain RTAI information */
    if(pmTraceDB->SystemType == TRACE_SYS_TYPE_RTAI_LINUX)
      /* Get the RTAI task to which this event belongs */
      pTask = RTAIDBEventTask(pmTraceDB, &lEvent, pmSystem, FALSE);
#endif /* SUPP_RTAI */

    /* Set the event's entry in the list of raw events displayed */
    sRawEventsDisplayed[i] = lEvent;

    /* Add text describing the event */
    /*  The CPU ID */
    if(pmTraceDB->LogCPUID == TRUE)
      sprintf(lString[0], "%d", lEventDesc.CPUID);
    else
      sprintf(lString[0], "0");

    /*  The event ID */
    sprintf(lString[1], "%s", pmTraceDB->EventString(pmTraceDB, lEventDesc.ID, &lEvent));

    /*  The event's time of occurence */
    DBFormatTimeInReadableString(lTimeStr,
				 lEventDesc.Time.tv_sec,
				 lEventDesc.Time.tv_usec);    
    sprintf(lString[2], "%s", lTimeStr);

    /* Is this an RT event */
    if(lEventDesc.ID <= TRACE_MAX)
      {
      /*  The PID of the process to which the event belongs */
      if(pProcess != NULL)
	sprintf(lString[3], "%d", pProcess->PID);
      else
	sprintf(lString[3], "N/A");
      }
#if SUPP_RTAI
    else
      {
      /*  The TID of the task to which the event belongs */
      if(pTask != NULL)
	sprintf(lString[3], "RT:%d", pTask->TID);
      else
	sprintf(lString[3], "RT:N/A");
      }
#endif /* SUPP_RTAI */

    /*  The size of the entry */
    sprintf(lString[4], "%d", lEventDesc.Size);

    /*  The string describing the event */
    sprintf(lString[5], "%s", lEventDesc.String);

    /* Insert the entry into the list */
    gtk_clist_append(GTK_CLIST(pmList), lString);

    /* Set the row's data to point to the current event */
    WDI_gtk_clist_set_last_row_data_full(GTK_CLIST(pmList), (gpointer) &(sRawEventsDisplayed[i]), NULL);

    /* Was this the last selected event */
    if(DBEventsEqual(lEvent, (*pmSelectedEvent)))
      gtk_clist_select_row(GTK_CLIST(pmList), i, 0);
    }

  /* Resize the list's length */
  gtk_widget_queue_resize(pmList);

  /* Thaw the clist */
  gtk_clist_thaw(GTK_CLIST(pmList));
}

/******************************************************************
 * Function :
 *    WDDisplayTrace()
 * Description :
 *    Displays a trace in a given window.
 * Parameters :
 *    pmSysView, System view for which trace is to be displayed
 * Return values :
 *    NONE.
 * History :
 *    K.Y., 17/06/99, Initial typing.
 * Note :
 ******************************************************************/
void WDDisplayTrace(systemView* pmSysView)
{
  gchar         lString[256];    /* Temporary string to build window title */

  /* Display the event graph */
  EGDisplayEventTrace(pmSysView->Window->GTEventGraph,
		      pmSysView->System,
		      pmSysView->EventDB);

  /* Fill the process tree */
  WDFillTree(pmSysView->Window->PTProcessTree,
	     pmSysView->System->ProcTree);

#if SUPP_RTAI
  /* Does this trace contain RTAI information */
  if(pmSysView->EventDB->SystemType == TRACE_SYS_TYPE_RTAI_LINUX)
    WDFillRTAITaskTree(pmSysView->Window->PTProcessTree,
		       RTAI_SYSTEM(pmSysView->System->SystemSpec)->TaskTree);
#endif /* SUPP_RTAI */

  /* Fix a mysterious GTK+ bug... */
  if(!GTK_TREE(pmSysView->Window->PTProcessTree)->root_tree)
    GTK_TREE(pmSysView->Window->PTProcessTree)->root_tree = GTK_TREE(pmSysView->Window->PTProcessTree);

  /* Set the CList's extents */
  pmSysView->Window->RTVAdjust->lower          = 0;
  pmSysView->Window->RTVAdjust->upper          = (gfloat) pmSysView->EventDB->Nb;
  pmSysView->Window->RTVAdjust->step_increment = 1;
  pmSysView->Window->RTVAdjust->page_increment = RTCLIST_NB_COLUMNS;
  pmSysView->Window->RTVAdjust->page_size      = RTCLIST_NB_COLUMNS;
  gtk_adjustment_changed(GTK_ADJUSTMENT(pmSysView->Window->RTVAdjust));
  gtk_adjustment_set_value(GTK_ADJUSTMENT(pmSysView->Window->RTVAdjust), 0);

  /* Enable items requiring an event DB to be functionnal */
  WDSetMenusSensitivity(pmSysView, TRUE);

  /* Fail-safe method for building main window title */
  if(pmSysView->Options->InputFileName)
    sprintf(lString, "Trace Visualizer - %s", pmSysView->Options->InputFileName);
  else
    sprintf(lString, "Trace Visualizer");

  /* Set main window title */
  gtk_window_set_title(GTK_WINDOW(pmSysView->Window->MWindow), lString);
}

/******************************************************************
 * Function :
 *    WDCreateSystemView()
 * Description :
 * Parameters :
 * Return values :
 * History :
 * Note :
 ******************************************************************/
systemView* WDCreateSystemView(systemInfo* pmSystem, db* pmTraceDB, options* pmOptions)
{
  systemView*  pSystemView;   /* The system to be displayed */

  /* Create a new system view */
  pSystemView = (systemView*) g_malloc(sizeof(systemView));

  /* Set the system elements */
  pSystemView->EventDB = pmTraceDB;
  pSystemView->System  = pmSystem;
  pSystemView->Options = pmOptions;
  pSystemView->Window  = WDCreateMainWindow(pSystemView);

  /* Enqueue this system view to the main system view list */
  pSystemView->Next   = sMainSystemViewList;
  sMainSystemViewList = pSystemView;

  /* Connect the signal handlers to this system view */
  WDConnectSignals(pSystemView);

  /* Give the completed system view to the caller */
  return pSystemView;
}

/******************************************************************
 * Function :
 *    WDStatusBarDisplay()
 * Description :
 * Parameters :
 * Return values :
 * History :
 * Note :
 ******************************************************************/
void WDStatusBarDisplay(gpointer pmMainWindow, gchar* pmString)
{
  mainWindow*   pMainWindow = (mainWindow*) pmMainWindow;  /* Main window pointer */

  /* Pop the last message off the status bar */
  gtk_statusbar_pop(GTK_STATUSBAR(pMainWindow->MainSBar),
		     pMainWindow->MainSBarContextID);		    

  /* Push the message down to the status bar */
  gtk_statusbar_push(GTK_STATUSBAR(pMainWindow->MainSBar),
		     pMainWindow->MainSBarContextID,
		     pmString);
}

/******************************************************************
 * Function :
 *    WDTimeSBarDisplay()
 * Description :
 * Parameters :
 * Return values :
 * History :
 * Note :
 ******************************************************************/
void WDTimeSBarDisplay(gpointer pmMainWindow, gdouble pmStartTime, gdouble pmEndTime)
{
  char          lTimeString[TIME_STR_LEN];                 /* Time string */
  char          lSBarString[TIME_STR_LEN + 10];            /* Status bar string */
  mainWindow*   pMainWindow = (mainWindow*) pmMainWindow;  /* Main window pointer */

  /* Pop the last message off the main status bar */
  /*  This makes "visual sense" when used */
  gtk_statusbar_pop(GTK_STATUSBAR(pMainWindow->MainSBar),
		     pMainWindow->MainSBarContextID);		    

  /* Pop the last message off the status bars */
  gtk_statusbar_pop(GTK_STATUSBAR(pMainWindow->BegTimeSBar),
		     pMainWindow->BegTimeSBarContextID);
  gtk_statusbar_pop(GTK_STATUSBAR(pMainWindow->EndTimeSBar),
		     pMainWindow->EndTimeSBarContextID);

  /* Push the message down the status bars */
  WDIFormatTimeInReadableString(lTimeString, pmStartTime);
  sprintf(lSBarString, " Start: %s", lTimeString);
  gtk_statusbar_push(GTK_STATUSBAR(pMainWindow->BegTimeSBar),
		     pMainWindow->BegTimeSBarContextID,
		     lSBarString);
#if 0 /* Display the time of the end of the period drawn */
  WDIFormatTimeInReadableString(lTimeString, pmEndTime);
  sprintf(lSBarString, " End: %s", lTimeString);
#else /* Display the span of time displayed */
  WDIFormatTimeInReadableString(lTimeString, pMainWindow->GTEventGraph->Interval);
  sprintf(lSBarString, " Span: %s", lTimeString);
#endif
  gtk_statusbar_push(GTK_STATUSBAR(pMainWindow->EndTimeSBar),
		     pMainWindow->EndTimeSBarContextID,
		     lSBarString);
}

/******************************************************************
 * Function :
 *    WDSetMenusSensitivity()
 * Description : Sets the sensitivity of all relevant menu items
 * Parameters : 
 *    pmSysView, System view describing the current window
 *    pmSensitivityValue, 
 * Return values :
 *    NONE
 * History :
 *    JH.D., 13/09/99, First draft
 * Note :
 ******************************************************************/
void WDSetMenusSensitivity(systemView* pmSysView, gboolean pmSensitivityValue)
{
  /* File menu items */
  /* Close current trace trace */
  gtk_widget_set_sensitive(pmSysView->Window->CloseTrace, pmSensitivityValue);
  /* Dump trace to file */
  gtk_widget_set_sensitive(pmSysView->Window->DumpToFile, pmSensitivityValue);

  /* Edit menu items */

  /* Tools menu items */
  /* Zoom in */
  gtk_widget_set_sensitive(pmSysView->Window->ZoomIn, pmSensitivityValue);
  /* Zoom out */
  gtk_widget_set_sensitive(pmSysView->Window->ZoomOut, pmSensitivityValue);
  /* Show horizon */
  gtk_widget_set_sensitive(pmSysView->Window->ShowHorizon, pmSensitivityValue);
  /* View time frame */
  gtk_widget_set_sensitive(pmSysView->Window->ToolGoToEvent, pmSensitivityValue);
  /* View time frame */
  gtk_widget_set_sensitive(pmSysView->Window->ToolViewTimeFrame, pmSensitivityValue);

  /* Options menu items */
  /* Display colors */
  gtk_widget_set_sensitive(pmSysView->Window->Colors, pmSensitivityValue);

  /* Toolbar items, if they are created */
  /* Close trace */
  if(pmSysView->Window->tlbCloseTrace)
    gtk_widget_set_sensitive(pmSysView->Window->tlbCloseTrace, pmSensitivityValue);

  /* Dump to file */
  if(pmSysView->Window->tlbDumpFile)
    gtk_widget_set_sensitive(pmSysView->Window->tlbDumpFile, pmSensitivityValue);

  /* Zoom in */
  if(pmSysView->Window->tlbZoomIn)
    gtk_widget_set_sensitive(pmSysView->Window->tlbZoomIn, pmSensitivityValue);

  /* Zoom out */
  if(pmSysView->Window->tlbZoomOut)
    gtk_widget_set_sensitive(pmSysView->Window->tlbZoomOut, pmSensitivityValue);

  /* Go to event */
  if(pmSysView->Window->tlbGotoEvent)
    gtk_widget_set_sensitive(pmSysView->Window->tlbGotoEvent, pmSensitivityValue);

  /* Show Horizon */
  if(pmSysView->Window->tlbShowHorizon)
    gtk_widget_set_sensitive(pmSysView->Window->tlbShowHorizon, pmSensitivityValue);

  /* Hide icon text */
  if(pmSysView->Window->tlbHideIconText)
    gtk_widget_set_sensitive(pmSysView->Window->tlbHideIconText, pmSensitivityValue);

  /* Hide system call details */
  if(pmSysView->Window->tlbHideSysCalls)
    gtk_widget_set_sensitive(pmSysView->Window->tlbHideSysCalls, pmSensitivityValue);

  /* Hide IRQs */
  if(pmSysView->Window->tlbHideIRQs)
    gtk_widget_set_sensitive(pmSysView->Window->tlbHideIRQs, pmSensitivityValue);

  /* Hide traps */
  if(pmSysView->Window->tlbHideTraps)
    gtk_widget_set_sensitive(pmSysView->Window->tlbHideTraps, pmSensitivityValue);

  /* Hide soft IRQs */
  if(pmSysView->Window->tlbHideSoftIRQs)
    gtk_widget_set_sensitive(pmSysView->Window->tlbHideSoftIRQs, pmSensitivityValue);

  /* Hide scheduling changes */
  if(pmSysView->Window->tlbHideSchedChange)
    gtk_widget_set_sensitive(pmSysView->Window->tlbHideSchedChange, pmSensitivityValue);

  /* Hide kernel timer */
  if(pmSysView->Window->tlbHideKernelTimer)
    gtk_widget_set_sensitive(pmSysView->Window->tlbHideKernelTimer, pmSensitivityValue);

  /* Draw horizontal lines slow */
  if(pmSysView->Window->tlbSlowH)
    gtk_widget_set_sensitive(pmSysView->Window->tlbSlowH, pmSensitivityValue);

  /* Draw vertical lines slow */
  if(pmSysView->Window->tlbSlowV)
    gtk_widget_set_sensitive(pmSysView->Window->tlbSlowV, pmSensitivityValue);

  /* Draw icons slow */
  if(pmSysView->Window->tlbSlowI)
    gtk_widget_set_sensitive(pmSysView->Window->tlbSlowI, pmSensitivityValue);
}

/******************************************************************
 * Function :
 *    WDToolBarPopulate()
 * Description : Inserts all required buttons in the toolbar
 * Parameters : 
 *    pmSysView, System view describing the current window
 * Return values :
 *    NONE
 * History :
 *    JH.D., 07/08/99, First draft
 * Note :
 *    This function creates the buttons that will appear in the toolbar
 *    and attaches the same signals as their menu counterparts
 *    New "hide icon" toggles also share a single callback.  This
 *    function is called exactly once.
 ******************************************************************/
void WDToolBarPopulate(systemView* pmSysView)
{
  /* Insert the Toolbar Buttons and connect Signals*/
  /*  Open a trace */
  pmSysView->Window->tlbOpenTrace =
    gtk_toolbar_append_element(GTK_TOOLBAR (pmSysView->Window->MToolBar), 
			       GTK_TOOLBAR_CHILD_BUTTON, NULL,
			       "Open", "Open a new trace", NULL,
			       CreateWidgetFromXpm(pmSysView->Window->MWindow, 
						   (char **) xpm_open),
			       GTK_SIGNAL_FUNC(SHOpenTrace), pmSysView);       

  /*  Close the trace */
  pmSysView->Window->tlbCloseTrace =
    gtk_toolbar_append_element(GTK_TOOLBAR (pmSysView->Window->MToolBar), 
			       GTK_TOOLBAR_CHILD_BUTTON, NULL,
			       "Close", "Close this trace", NULL,
			       CreateWidgetFromXpm(pmSysView->Window->MWindow, 
						   (char **) xpm_close),
			       GTK_SIGNAL_FUNC(SHCloseTrace), pmSysView);

  /*  Insert a separator */
  gtk_toolbar_append_space(GTK_TOOLBAR (pmSysView->Window->MToolBar));         

  /*  Dump to file */
  pmSysView->Window->tlbDumpFile =
    gtk_toolbar_append_element(GTK_TOOLBAR (pmSysView->Window->MToolBar), 
			       GTK_TOOLBAR_CHILD_BUTTON, NULL,
			       "Dump", "Dump to file", NULL,
			       CreateWidgetFromXpm(pmSysView->Window->MWindow, 
						   (char **) xpm_dump),
			       GTK_SIGNAL_FUNC(SHDumpToFile), pmSysView);

  /*  Insert a separator */
  gtk_toolbar_append_space(GTK_TOOLBAR (pmSysView->Window->MToolBar));         

  /*  Zoom in */
  pmSysView->Window->tlbZoomIn =
    gtk_toolbar_append_element(GTK_TOOLBAR (pmSysView->Window->MToolBar), 
			       GTK_TOOLBAR_CHILD_BUTTON, NULL,
			       "Zoom in", "Zoom in on graph", NULL,
			       CreateWidgetFromXpm(pmSysView->Window->MWindow,
						   (char **) xpm_zoom_in),
			       GTK_SIGNAL_FUNC(SHZoomIn), pmSysView);          

  /*  Zoom out */
  pmSysView->Window->tlbZoomOut =
    gtk_toolbar_append_element(GTK_TOOLBAR (pmSysView->Window->MToolBar), 
			       GTK_TOOLBAR_CHILD_BUTTON, NULL,
			       "Zoom out", "Zoom out from graph", NULL,
			       CreateWidgetFromXpm(pmSysView->Window->MWindow,
						   (char **) xpm_zoom_out),
			       GTK_SIGNAL_FUNC(SHZoomOut), pmSysView);         
 
  /*  Insert a separator*/
  gtk_toolbar_append_space(GTK_TOOLBAR (pmSysView->Window->MToolBar));

  /*  Go to event */
  pmSysView->Window->tlbGotoEvent =
    gtk_toolbar_append_element(GTK_TOOLBAR (pmSysView->Window->MToolBar), 
			       GTK_TOOLBAR_CHILD_BUTTON, NULL,
			       "Go to Event", "Find event in event list", NULL,
			       CreateWidgetFromXpm(pmSysView->Window->MWindow,
						   (char **) xpm_find),
			       GTK_SIGNAL_FUNC(SHGotoEvent), pmSysView);

  /*  Insert a separator*/
  gtk_toolbar_append_space(GTK_TOOLBAR (pmSysView->Window->MToolBar));         

  /*  Show horizon */
  pmSysView->Window->tlbShowHorizon =
    gtk_toolbar_append_element(GTK_TOOLBAR (pmSysView->Window->MToolBar), 
			       GTK_TOOLBAR_CHILD_TOGGLEBUTTON, NULL,
			       "Horizon", "Toggle Horizon", NULL,
			       CreateWidgetFromXpm(pmSysView->Window->MWindow,
						   (char **) xpm_horizon),
			       GTK_SIGNAL_FUNC(SHShowHorizon), pmSysView);     

  /*  Insert a separator*/
  gtk_toolbar_append_space(GTK_TOOLBAR (pmSysView->Window->MToolBar));         

  /* "Hide icon" toggle buttons.  The callback just performs a redraw as
      EGI*Draw* routines now read the active state of the button. */

  /* Hide icon text */
  pmSysView->Window->tlbHideIconText =
    gtk_toolbar_append_element(GTK_TOOLBAR (pmSysView->Window->MToolBar), 
			       GTK_TOOLBAR_CHILD_TOGGLEBUTTON, NULL,
			       "Icons", "Hide Icon Text", NULL,
			       CreateWidgetFromXpm(pmSysView->Window->MWindow,
						   (char **) xpm_icon_textOFF),
			       GTK_SIGNAL_FUNC(SHToggleTBIcon), pmSysView);

  /* Hide system calls */
  pmSysView->Window->tlbHideSysCalls =
    gtk_toolbar_append_element(GTK_TOOLBAR (pmSysView->Window->MToolBar), 
			       GTK_TOOLBAR_CHILD_TOGGLEBUTTON, NULL,
			       "Syscalls", "Hide system calls", NULL,
			       CreateWidgetFromXpm(pmSysView->Window->MWindow,
						   (char **) xpm_SysCallsOFF),
			       GTK_SIGNAL_FUNC(SHToggleTBIcon), pmSysView);

  /* Hide hard IRQs */
  pmSysView->Window->tlbHideIRQs =
    gtk_toolbar_append_element(GTK_TOOLBAR (pmSysView->Window->MToolBar), 
			       GTK_TOOLBAR_CHILD_TOGGLEBUTTON, NULL,
			       "IRQs", "Hide Hard IRQs", NULL,
			       CreateWidgetFromXpm(pmSysView->Window->MWindow,
						   (char **) xpm_IRQsOFF),
			       GTK_SIGNAL_FUNC(SHToggleTBIcon), pmSysView);

  /* Hide traps */
  pmSysView->Window->tlbHideTraps =
    gtk_toolbar_append_element(GTK_TOOLBAR (pmSysView->Window->MToolBar), 
			       GTK_TOOLBAR_CHILD_TOGGLEBUTTON, NULL,
			       "Traps", "Hide Traps", NULL,
			       CreateWidgetFromXpm(pmSysView->Window->MWindow,
						   (char **) xpm_trapsOFF),
			       GTK_SIGNAL_FUNC(SHToggleTBIcon), pmSysView);

  /* Hide soft IRQs */
  pmSysView->Window->tlbHideSoftIRQs =
    gtk_toolbar_append_element(GTK_TOOLBAR (pmSysView->Window->MToolBar), 
			       GTK_TOOLBAR_CHILD_TOGGLEBUTTON, NULL,
			       "IRQs", "Hide Soft IRQs", NULL,
			       CreateWidgetFromXpm(pmSysView->Window->MWindow,
						   (char **) xpm_bottom_halfOFF),
			       GTK_SIGNAL_FUNC(SHToggleTBIcon), pmSysView);

  /* Hide scheduling changes */
  pmSysView->Window->tlbHideSchedChange =
    gtk_toolbar_append_element(GTK_TOOLBAR (pmSysView->Window->MToolBar), 
			       GTK_TOOLBAR_CHILD_TOGGLEBUTTON, NULL,
			       "IRQs", "Hide Schedule Changes", NULL,
			       CreateWidgetFromXpm(pmSysView->Window->MWindow,
						   (char **) xpm_sched_changeOFF),
			       GTK_SIGNAL_FUNC(SHToggleTBIcon), pmSysView);

  /* Toggle kernel timers. */
  pmSysView->Window->tlbHideKernelTimer =
    gtk_toolbar_append_element(GTK_TOOLBAR (pmSysView->Window->MToolBar), 
			       GTK_TOOLBAR_CHILD_TOGGLEBUTTON, NULL,
			       "Timer", "Hide Kernel Timer", NULL,
			       CreateWidgetFromXpm(pmSysView->Window->MWindow,
						   (char **) xpm_kernel_timerOFF),
			       GTK_SIGNAL_FUNC(SHToggleTBIcon), pmSysView);

  /*  Insert a separator*/
  gtk_toolbar_append_space(GTK_TOOLBAR (pmSysView->Window->MToolBar));

  /* Slow drawing (draw everything, even if it overlaps) */
  /* Draw slow horizon lines */
  pmSysView->Window->tlbSlowH =
    gtk_toolbar_append_element(GTK_TOOLBAR (pmSysView->Window->MToolBar), 
			       GTK_TOOLBAR_CHILD_TOGGLEBUTTON, NULL,
			       "Speed", "Slow HLines", NULL,
			       CreateWidgetFromXpm(pmSysView->Window->MWindow,
						   (char **) xpm_SlowH),
			       GTK_SIGNAL_FUNC(SHToggleTBIcon), pmSysView);
  /* Draw slow vertical lines */
  pmSysView->Window->tlbSlowV =
    gtk_toolbar_append_element(GTK_TOOLBAR (pmSysView->Window->MToolBar), 
			       GTK_TOOLBAR_CHILD_TOGGLEBUTTON, NULL,
			       "Speed", "Slow VLines", NULL,
			       CreateWidgetFromXpm(pmSysView->Window->MWindow,
						   (char **) xpm_SlowV),
			       GTK_SIGNAL_FUNC(SHToggleTBIcon), pmSysView);
  /* Draw slow icons */
  pmSysView->Window->tlbSlowI =
    gtk_toolbar_append_element(GTK_TOOLBAR (pmSysView->Window->MToolBar), 
			       GTK_TOOLBAR_CHILD_TOGGLEBUTTON, NULL,
			       "Speed", "Slow Icons", NULL,
			       CreateWidgetFromXpm(pmSysView->Window->MWindow,
						   (char **) xpm_SlowI),
			       GTK_SIGNAL_FUNC(SHToggleTBIcon), pmSysView);
}
