Logo Search packages:      
Sourcecode: v-sim version File versions  Download package

gtk_main.c

/*   EXTRAITS DE LA LICENCE
      Copyright CEA, contributeurs : Luc BILLARD et Damien
      CALISTE, laboratoire L_Sim, (2001-2005)
  
      Adresse mèl :
      BILLARD, non joignable par mèl ;
      CALISTE, damien P caliste AT cea P fr.

      Ce logiciel est un programme informatique servant à visualiser des
      structures atomiques dans un rendu pseudo-3D. 

      Ce logiciel est régi par la licence CeCILL soumise au droit français et
      respectant les principes de diffusion des logiciels libres. Vous pouvez
      utiliser, modifier et/ou redistribuer ce programme sous les conditions
      de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA 
      sur le site "http://www.cecill.info".

      Le fait que vous puissiez accéder à cet en-tête signifie que vous avez 
      pris connaissance de la licence CeCILL, et que vous en avez accepté les
      termes (cf. le fichier Documentation/licence.fr.txt fourni avec ce logiciel).
*/

/*   LICENCE SUM UP
      Copyright CEA, contributors : Luc BILLARD et Damien
      CALISTE, laboratoire L_Sim, (2001-2005)

      E-mail address:
      BILLARD, not reachable any more ;
      CALISTE, damien P caliste AT cea P fr.

      This software is a computer program whose purpose is to visualize atomic
      configurations in 3D.

      This software is governed by the CeCILL  license under French law and
      abiding by the rules of distribution of free software.  You can  use, 
      modify and/ or redistribute the software under the terms of the CeCILL
      license as circulated by CEA, CNRS and INRIA at the following URL
      "http://www.cecill.info". 

      The fact that you are presently reading this means that you have had
      knowledge of the CeCILL license and that you accept its terms. You can
      find a copy of this licence shipped with this software at Documentation/licence.en.txt.
*/

#include <gtk/gtk.h>
#include <glib.h>
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h> /* For the access markers R_OK, W_OK ... */
#include <sys/stat.h>
#include <sys/types.h>

#include "interface.h"
#include "support.h"
#include "callbacks.h"
#include "gtk_main.h"
#include "gtk_observePick.h"
#include "gtk_pairs.h"
#include "gtk_about.h"
#include "gtk_renderingWindowWidget.h"
#include "extraGtkFunctions/gtk_colorComboBoxWidget.h"
#include "extraGtkFunctions/gtk_numericalEntryWidget.h"

#include "panelModules/externalModules.h"
#include "panelModules/externalRenderingMethods_gtk.h"
#include "panelModules/panelDataFile.h"
#include "panelModules/panelPlanes.h"
#include "panelModules/panelSurfaces.h"
#include "renderingMethods/renderingAtomic.h"
#include "renderingMethods/renderingSpin.h"

#include "opengl.h"
#include "visu_object.h"
#include "visu_rendering.h"
#include "visu_data.h"
#include "visu_configFile.h"
#include "visu_basic.h"            /* To have loadDataFromFile */
#include "visu_pairs.h"            /* To have setPairsOnOff */
#include "visu_commandLine.h"      /* To have getArgFilename and getXWindowGeometry*/
#include "visu_pickMesure.h"
#include "OSOpenGL/visu_openGL.h"
#include "renderingBackend/visu_windowInterface.h"
#include "coreTools/toolShade.h"
#include "coreTools/toolOptions.h"


/****************/
/* Private part */
/****************/

/* Initialisation */
int initGtkMain();
void createCallBacksMain();
gboolean initVisuPostGTK(gpointer data);
gboolean commandLineLoadWithGtk(gpointer data);

/* Fuctions to rule the combobox. */
void initSubPanel();
void initListeSubPanel();

/* pointer on different buttons. */
GtkWidget *loadButton;
GtkWidget *pairsButton;
GtkWidget *pickObserveButton;

/* Miscelaneous functions with gtk */
void loadFileWithGtk(VisuData **visuData);
void setRenderingButtonSensitive(gboolean bool);
void gtkMainAsk_optionValues(OptionTable *table, gpointer data);

/* Local callbacks */
void checkPairsChanged(GtkToggleButton *togglebutton, gpointer user_data);
void setFileButtonSensitive(GObject *obj, gpointer bool);
static void onResourcesLoaded(GObject *visu, gpointer data);
void onFileChange(GObject *obj, VisuData *dataObj, gpointer bool);
void onHideNextTime(GtkToggleButton *button, gpointer data);
static void onQuitButton(GtkButton *button, gpointer data);
static gboolean onKillRenderingWindowEvent(GtkWidget *widget, GdkEvent *event,
                                 gpointer user_data);

/* Parameter to store the position of windows. */
int rememberWindowPosition;
GHashTable *windowPosition;
#define PARAMETER_GTKMAIN_REMEMBER_DEFAULT 1

/* Parameter to change the policy of the warning quit dialog. */
gboolean warningWhenQuit;
#define FLAG_PARAMETER_GTKMAIN_QUIT    "main_confirmQuit"
#define DESC_PARAMETER_GTKMAIN_QUIT    "Show up a dialog to confirm when quit button is clicked ; boolean 0 or 1"
#define PARAMETER_GTKMAIN_QUIT_DEFAULT TRUE
gboolean readMainQuitPolicy(gchar **lines, int nbLines,
                      int position, GString *errorMessage);
#define FLAG_PARAMETER_GTKMAIN_PANEL   "main_panelStatus"
#define DESC_PARAMETER_GTKMAIN_PANEL   "Attach a panel to a tool window ; panel_name window_name (or None or Main)"
gboolean readMainPanelStatus(gchar **lines, int nbLines,
                       int position, GString *errorMessage);
#define FLAG_PARAMETER_GTKMAIN_DOCK   "main_dock"
#define DESC_PARAMETER_GTKMAIN_DOCK   "Define the characteristic of a dock window ; size(x,y) position(w,h) visibility window_name"
gboolean readMainDock(gchar **lines, int nbLines,
                  int position, GString *errorMessage);
gboolean exportParametersGtkMain(GString *data, int *nbLinesWritten,
                         VisuData *dataObj);


/* Store the last open directory. It is initialised
   to current working directory. */
gchar *lastOpenDirectory;

/* Number of time V_Sim try to attach the OpenGL context. */
#define GTK_MAIN_N_MAX_OPENGL 10

/* Store some informations on gtk method associated
   with different rendering methods. */
struct renderingMethod_gtkMain_struct
{
  createGtkWidgetFunc createOpenAddOn;
  createGtkLoadWidgetFunc createLoadAction;
};
GHashTable *renderingMethod_gtkMain;

/* Local variable for the statusbar stack */
gboolean statusInfo_isPicked;

GtkWidget *vboxMain;



int mainWithGtk(int argc, char *argv[])
{
  int width, height;

  gtk_init (&argc, &argv);

  /* Creating the visu object to handle the signals. */
  visu = g_object_new (VISU_TYPE, NULL);

  /* Nullify uninitialized pointers. */
  mainWindow = (GtkWidget*)0;

  /* Règle l'accès aux images */
  add_pixmap_directory(v_sim_pixmaps_dir);

  initVisuMain();

  DBG_fprintf(stderr,"--- Initialising the rendering window ---\n");
  commandLineGet_XWindowGeometry(&width, &height);
  currentRenderingWindow = renderingWindow_new("V_Sim", "v_sim_render", "V_Sim",
                                     width, height);
  if (!currentRenderingWindow)
    exit(1);


  DBG_fprintf(stderr,"--- Initialising the new gtk classes ---\n");
  /* Force the creation of the ColorComboBoxClass. */
  g_type_class_ref(colorComboBox_get_type());
  /* Force the creation of the VisuData class. */
  g_type_class_ref(visu_data_get_type());

  initGtkMain();

  /* Others elements linked to the main window. */
  DBG_fprintf(stderr, " | Gtk Pick and Observe");
  initObserveAndPickWindow();
  DBG_fprintf(stderr, " ... OK.\n");
  DBG_fprintf(stderr, " | Gtk Pairs");
  initPairsWindow();
  DBG_fprintf(stderr, " ... OK.\n");
  DBG_fprintf(stderr, " | Gtk About");
  initAboutWindow();
  DBG_fprintf(stderr, " ... OK.\n");

  DBG_fprintf(stderr, "GTK Main : adding loading parameters and resources"
            " callbacks in the queue.\n");
  g_idle_add(initVisuPostGTK, (gpointer)0);

  createCallBacksMain();
  DBG_fprintf(stderr, "GTK Main : Creating callbacks.\n");

  DBG_fprintf(stderr, "Gtk Main : starting main GTK loop.\n");
  gtk_main ();

  return 0;
}

int initGtkMain()
{
  int i;
  VisuConfigFileEntry *resourceEntry;

  /* Init the signal object for gtk stuffs. */
  visuGtkObject = g_object_new(VISU_GTK_TYPE, NULL);

  /* Set local variables */
  statusInfo_isPicked = FALSE;
  /* Retrieve the current working directory. */
  setLastOpenDirectory((char*)g_get_current_dir());
  /* Create the hashtable to store windows and their position. */
  windowPosition = g_hash_table_new_full(g_direct_hash,
                               g_direct_equal,
                               NULL, freeInt);
  setRememberPosition(PARAMETER_GTKMAIN_REMEMBER_DEFAULT);
  /* Create parameters. */
  warningWhenQuit = PARAMETER_GTKMAIN_QUIT_DEFAULT;
  resourceEntry = visuConfigFileAdd_entry(VISU_CONFIGFILE_PARAMETER,
                                FLAG_PARAMETER_GTKMAIN_QUIT,
                                DESC_PARAMETER_GTKMAIN_QUIT,
                                1, readMainQuitPolicy);
  resourceEntry = visuConfigFileAdd_entry(VISU_CONFIGFILE_PARAMETER,
                                FLAG_PARAMETER_GTKMAIN_PANEL,
                                DESC_PARAMETER_GTKMAIN_PANEL,
                                1, readMainPanelStatus);
  resourceEntry = visuConfigFileAdd_entry(VISU_CONFIGFILE_PARAMETER,
                                FLAG_PARAMETER_GTKMAIN_DOCK,
                                DESC_PARAMETER_GTKMAIN_DOCK,
                                1, readMainDock);
  visuConfigFileAdd_exportFunction(VISU_CONFIGFILE_PARAMETER,
                           exportParametersGtkMain);

  /* Create the hashtable of rendering method gtk functions. */
  renderingMethod_gtkMain = g_hash_table_new_full(g_direct_hash,
                                      g_direct_equal,
                                      NULL, freeGPointer);
  for (i = 0; listInitRendenringGtkFunc[i]; i++)
    listInitRendenringGtkFunc[i]();

  /* Initialise dependant gtk elements. */
  DBG_fprintf(stderr, "--- Initialising the GTK interface ---\n");
  DBG_fprintf(stderr, " | Gtk Main");
  mainWindow = create_main_window ();
  gtk_window_set_wmclass(GTK_WINDOW(mainWindow), "v_sim_commandPanel", "V_Sim");
  DBG_fprintf(stderr, " ... OK.\n");
  /* Signals and naming of widgets specific to the main window. */
  vboxMain = lookup_widget(mainWindow, "vboxMainWindow");
  loadButton = lookup_widget(mainWindow, "loadButton");
  pairsButton = lookup_widget(mainWindow, "pairsButton");
  pickObserveButton = lookup_widget(mainWindow, "pickObserveButton");
  /* init the sub panel contains. */
  initSubPanel();

  return 1;
}

void createCallBacksMain()
{
  GtkWidget *wd;

  /* Initialise the interface. */
  wd = lookup_widget(mainWindow, "checkPairs");
  g_signal_connect(G_OBJECT(wd), "toggled",
               G_CALLBACK(checkPairsChanged), (gpointer)0);
  wd = lookup_widget(mainWindow, "buttonQuit");
  g_signal_connect(G_OBJECT(wd), "clicked",
               G_CALLBACK(onQuitButton), (gpointer)0);
  /* Set the quit and destroy signals. */
  g_signal_connect(G_OBJECT(mainWindow), "delete-event",
               G_CALLBACK(onKillRenderingWindowEvent), (gpointer)0);
  g_signal_connect(G_OBJECT(mainWindow), "destroy-event",
               G_CALLBACK(onKillRenderingWindowEvent), (gpointer)0);


  g_signal_connect(G_OBJECT(visu), "dataReadyForRendering", 
               G_CALLBACK(onFileChange), (gpointer)0);
  g_signal_connect(G_OBJECT(visu), "renderingChanged",
               G_CALLBACK(setFileButtonSensitive),
               (gpointer)0);
  g_signal_connect(G_OBJECT(visu), "resourcesLoaded",
               G_CALLBACK(onResourcesLoaded), (gpointer)0);
}

gboolean initVisuPostGTK(gpointer data)
{
  char* path;
  int res;
  char *filename, *spin_filename;
  gchar *dirname, *normDir;
  GtkWidget *wd;
  VisuData *newData;
  GString *errorMessage;
  int width, height;
/*   struct timespec timeToSleep; */

  commandLineGet_XWindowGeometry(&width, &height);
  OpenGLViewSet_windowSize((OpenGLView*)0, (guint)width, (guint)height);

  DBG_fprintf(stderr,"--- Initialising the parameters ---\n");
  /* Save the gtk tag as a known tag to allow to read such parameters. */
  visuConfigFileAdd_knownTag("gtk");
  /* Look for parameters file */
  path = visuConfigFileGet_validPath(VISU_CONFIGFILE_PARAMETER, R_OK, 0);
  if (path)
    {
      errorMessage = (GString*)0;
      res = visuConfigFileLoad(VISU_CONFIGFILE_PARAMETER, path, &errorMessage);
      if (!res && errorMessage)
      raiseAlertDialogWithScrollView(errorMessage->str);
      if (errorMessage)
      g_string_free(errorMessage, TRUE);
      free(path);
    }
  else
    raiseAlertDialog(_("Unable to find a valid parameters file. Starting with defaults."));

  DBG_fprintf(stderr,"--- Initialising resources ---\n");
  /* Look for resources file */
  path = visuConfigFileGet_validPath(VISU_CONFIGFILE_RESOURCE, R_OK, 0);
  if (path)
    {
      errorMessage = (GString*)0;
      res = visuConfigFileLoad(VISU_CONFIGFILE_RESOURCE, path, &errorMessage);
      if (!res && errorMessage)
      raiseAlertDialogWithScrollView(errorMessage->str);
      if (errorMessage)
      g_string_free(errorMessage, TRUE);
      free(path);
    }

  newData = (VisuData*)0;
  filename = commandLineGet_ArgFilename();
  spin_filename = commandLineGet_ArgSpinFileName();
  if (spin_filename && filename)
    {
      setRenderingMethodInUse(pointerOnRenderingSpinMethod);
      newData = visuDataNew();
      if (!newData)
      exit(1);

      dirname = g_path_get_dirname(filename);
      normDir = normalize_path(dirname);
      setLastOpenDirectory((char*)normDir);
      g_free(dirname);
      g_free(normDir);

      visuDataAdd_file(newData, filename, FILE_KIND_POSITION, (FileFormat*)0);
      visuDataAdd_file(newData, spin_filename, FILE_KIND_SPIN, (FileFormat*)0);
      free(spin_filename);
      free(filename);
      spin_filename = (char*)0;
      filename = (char*)0;

      DBG_fprintf(stderr, "GTK Main : adding the load call back in the queue.\n");
      g_idle_add(commandLineLoadWithGtk, (gpointer)newData);
    }
  else if (filename)
    {
      setRenderingMethodInUse(pointerOnRenderingAtomicMethod);
      newData = visuDataNew();
      if (!newData)
      exit(1);

      dirname = g_path_get_dirname(filename);
      normDir = normalize_path(dirname);
      setLastOpenDirectory((char*)normDir);
      g_free(dirname);
      g_free(normDir);

      visuDataAdd_file(newData, filename, FILE_KIND_POSITION, (FileFormat*)0);
      free(filename);
      filename = (char*)0;

      DBG_fprintf(stderr, "GTK Main : adding the load call back in the queue.\n");
      g_idle_add(commandLineLoadWithGtk, (gpointer)newData);
    }
  else
    {
      setRenderingButtonSensitive(FALSE);
    }
  if (spin_filename)
    free(spin_filename);
  if (filename)
    free(filename);

  /* Initialise the buttons of the main interface. */
  wd = lookup_widget(mainWindow, "checkPairs");
  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(wd),
                         (gboolean)getPairsOnOff());

  gtk_widget_show (mainWindow);

  return FALSE;
}

gboolean commandLineLoadWithGtk(gpointer data)
{
  int i, somethingIsLoaded, presetShade, nb;
  gboolean res;
  gchar *colorizeFilename, *planeFile, *surfFile;
  float *values;
  int *colUsed;
  float *translations;
  GList *list;
  Shade *shade;
  VisuData *obj;
  GError *error;
  OptionTable *table;
  gchar **names;

  obj = (VisuData*)data;
  loadFileWithGtk(&obj);

  /* Post loading sequence, corresponding to all other arguments given to command line. */
  /* translate argument */
  if (obj)
    {
      translations = commandLineGet_translation();
      if (translations)
      {
        visuDataSet_XYZtranslation(obj, translations);
        visuData_constrainedInTheBox(obj);
      }
    }

  visuRenderingWindowSet_visuData(visuRenderingWindowGet_current(),
                          obj);

  if (!obj)
    {
      return FALSE;
    }

  /* Post loading sequence, corresponding to all other arguments given to command line. */
  /* colorize argument */
  colorizeFilename = commandLineGet_colorizeFileName();
  if (colorizeFilename)
    {
      somethingIsLoaded = panelDataFileLoad_file(obj, colorizeFilename);
      if (somethingIsLoaded)
      {
        colUsed = commandLineGet_colorizeColUsed();
        if (colUsed)
          for (i = 0; i < 3; i++)
            dataFileSet_colUsed(obj, colUsed[i] - 1, i);
        else
          {
            presetShade = commandLineGet_colorizePresetColor();
            if (presetShade < 0)
            presetShade = 0;
            list = toolShadeBuild_presetList();
            if (list)
            {
              shade = (Shade*)g_list_nth_data(list, presetShade);
              if (shade)
                dataFileSet_shade(obj, shade);
            }
          }
      }
    }
  /* plane file argument */
  planeFile = commandLineGet_planesFileName();
  if (planeFile)
    {
      panelPlanesSet_use(obj, TRUE);
      error = (GError*)0;
      res = panelPlanesLoad_file(obj, planeFile, &error);
      if (error)
      {
        raiseAlertDialog(error->message);
        g_clear_error(&error);
      }
      else if (res)
      panelPlanesApply_hidingScheme(obj);
    }
  /* iso-surface argument. */
  table = commandLineGet_options();
  surfFile = commandLineGet_isoSurfacesFileName();
  if (surfFile)
    {
      res = panelIsosurfacesLoad_file(surfFile, commandLineGet_fitToBox(), obj, table);
      if (!res)
      {
        panelIsosurfacesShow_all(TRUE);
        panelIsosurfacesSet_used(obj, TRUE);
      }
    }
  /* scalar field argument. */
  surfFile = commandLineGet_scalarFieldFileName();
  if (surfFile)
    {
      res = panelIsosurfacesLoad_file(surfFile, commandLineGet_fitToBox(), obj, table);
      if (!res)
      {
        values = commandLineGet_isoValues(&nb);
        names = commandLineGet_isoNames(&nb);
        for (i = 0; i < nb; i++)
          panelIsosurfacesAdd_withValue(surfFile, values[i], names[i]);
        panelIsosurfacesShow_all(TRUE);
        panelIsosurfacesSet_used(obj, TRUE);
      }
    }
  
  visuData_createAllNodes(obj);
  g_signal_emit (visu, VISU_GET_CLASS (visu)->OpenGLAskForReDraw_signal_id,
             0 , NULL);

  return FALSE;
}

gboolean loadAndRenderFileWithGtk(gpointer data)
{
  VisuData *obj;

  obj = VISU_DATA(data);
  loadFileWithGtk(&obj);

  visuRenderingWindowSet_visuData(visuRenderingWindowGet_current(),
                          obj);

  if (!obj)
    return FALSE;

  visuData_createAllNodes(obj);
  g_signal_emit (visu, VISU_GET_CLASS (visu)->OpenGLAskForReDraw_signal_id,
             0 , NULL);

  return FALSE;
}




/**********************************/
/* Fuctions to rule the notebook. */
/**********************************/
void initSubPanel()
{
  int i;
  ToolPanel *panel;
  DockWindow *dockMain;
  GtkWidget *wd;
  
  dockMain = toolPanelClassGet_commandPanel();
  wd = dockWindowGet_container(dockMain);
  gtk_box_pack_start(GTK_BOX(vboxMain), wd, TRUE, TRUE, 0);
  gtk_widget_show_all(wd);

  for (i = 0; listSubPanelInitFunc[i]; i++)
    {
      panel = listSubPanelInitFunc[i]();
      if (!panel)
      g_error("Can't initialise subpanel number %d.\n", i);

      toolPanelAttach(panel, dockMain);
      gtk_widget_show(GTK_WIDGET(panel));
      
      DBG_fprintf(stderr, "Gtk Main : initialise '%s' subpanel OK.\n",
              toolPanelGet_label(panel));
    }
}




/*******************/
/* Local callbacks */
/*******************/

void setRenderingButtonSensitive(gboolean bool)
{
  gtk_widget_set_sensitive(pairsButton, bool);
  gtk_widget_set_sensitive(pickObserveButton, bool);
}
void onFileChange(GObject *obj, VisuData *dataObj, gpointer bool)
{ 
  if (dataObj)
    setRenderingButtonSensitive(TRUE);
  else
    setRenderingButtonSensitive(FALSE);

  toolPanelClassSet_visuData(dataObj);
}
static void onResourcesLoaded(GObject *visu, gpointer data)
{
  GtkWidget *wd;

  wd = lookup_widget(mainWindow, "checkPairs");
  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(wd), (gboolean)getPairsOnOff());
}
void setFileButtonSensitive(GObject *obj, gpointer bool)
{
  if (getRenderingMethodInUse())
    gtk_widget_set_sensitive(loadButton, TRUE);
  else
    gtk_widget_set_sensitive(loadButton, FALSE);
  setRenderingButtonSensitive(FALSE);
}
void checkPairsChanged(GtkToggleButton *togglebutton, gpointer user_data)
{
  gboolean res;
  RenderingWindow *window;

  res = gtk_toggle_button_get_active(togglebutton);
  setPairsOnOff(res);
  if (res)
    {
      window = RENDERING_WINDOW(visuRenderingWindowGet_current());
      g_return_if_fail(window);
      if (createPairs(renderingWindowGet_visuData(window)))
      g_signal_emit (visu, VISU_GET_CLASS (visu)->OpenGLAskForReDraw_signal_id,
                   0 , NULL);
    }
  else
    g_signal_emit (visu, VISU_GET_CLASS (visu)->OpenGLAskForReDraw_signal_id,
               0 , NULL);
}



/*****************/
/* Miscellaneous */
/*****************/

char* getLastOpenDirectory()
{
  DBG_fprintf(stderr, "Gtk Main : get the last open directory : '%s'.\n", lastOpenDirectory);
  return lastOpenDirectory;
}
void setLastOpenDirectory(char* directory)
{
  if (lastOpenDirectory)
    g_free(lastOpenDirectory);

  if (!g_path_is_absolute(directory))
    lastOpenDirectory = g_build_filename(g_get_current_dir(), directory, NULL);
  else
    lastOpenDirectory = g_build_filename(directory, NULL);
  DBG_fprintf(stderr, "Gtk Main : set the last open directory to '%s', OK.\n", lastOpenDirectory);
}

/* This method loads the general function to load data from file
   and deals with errors with gtkDialogs. */
void loadFileWithGtk(VisuData **visuData)
{
  GError *error;
  VisuData *prevData;
  gboolean changeElement, res;
  RenderingWindow *window;

  if (!visuData)
    return;

  window = RENDERING_WINDOW(visuRenderingWindowGet_current());
  g_return_if_fail(window);

  prevData = renderingWindowGet_visuData(window);
  DBG_fprintf(stderr, "Gtk main : loading process ... %p points to"
            " previous VisuData.\n", (gpointer)prevData);

  error = (GError*)0;
  res = visuBasicLoad_dataFromFile(*visuData, (FileFormat*)0, &error);
  if (error)
    {
      raiseAlertDialog(error->message);
      g_error_free(error);
    }

  if (!res)
    {
      g_object_unref(*visuData);
      *visuData = (VisuData*)0;
      if (!error)
      g_warning("No error message!");
    }

  DBG_fprintf(stderr, "Gtk main : loading process ... %p points to"
            " previous VisuData.\n", (gpointer)prevData);

  if (prevData && *visuData)
    {
      changeElement = visuData_compareElements(prevData, *visuData);
      visuDataSet_changeElementFlag(*visuData, changeElement);
    }
  
  return;
}

void setRememberPosition(int val)
{
  DBG_fprintf(stderr, "GTK Main : set the remember parameter to %d.\n", val);
  rememberWindowPosition = val;
}
int getRememberPosition()
{
  return rememberWindowPosition;
}

gchar* getSelectedDirectory()
{
  GtkWidget *file_selector;
  gchar *dirname;
  char *directory;

  /* Create the selector */
  file_selector = gtk_file_chooser_dialog_new(_("Choose a directory"),
                                    GTK_WINDOW(mainWindow),
                                    GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
                                    GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
                                    GTK_STOCK_OPEN, GTK_RESPONSE_OK,
                                    NULL);
  directory = getLastOpenDirectory();
  if (directory)
    gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(file_selector), directory);
  gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(file_selector),
                               FALSE);

  gtk_widget_set_name(file_selector, "filesel");
  gtk_window_set_position(GTK_WINDOW(file_selector), GTK_WIN_POS_CENTER_ON_PARENT);
  gtk_window_set_modal(GTK_WINDOW (file_selector), TRUE);

  if (gtk_dialog_run (GTK_DIALOG (file_selector)) == GTK_RESPONSE_OK)
    {
      dirname = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER (file_selector));
      setLastOpenDirectory(dirname);
    }
  else
    dirname = (gchar*)0;

  gtk_widget_destroy (file_selector);

  return dirname;
}


/* This method hides the specified window and save its coordinates if
   it is specified by a parameter. */
void visuHideWindow(GtkWindow *win)
{
  int *val;

  if (!win)
    return;

  if (rememberWindowPosition)
    {
      val = (int*)g_hash_table_lookup(windowPosition, win);
      if (!val)
      {
        val = malloc(sizeof(int) * 2);
        if (!val)
          {
            allocationProblems();
            exit(1);
          }
        g_hash_table_insert(windowPosition, (gpointer)win, (gpointer)val);
      }
      gtk_window_get_position(win, &val[0], &val[1]);
      DBG_fprintf(stderr, "Gtk Main : store position (%d,%d) for window %d.\n", 
              val[0], val[1], GPOINTER_TO_INT(win));
    }
  gtk_widget_hide(GTK_WIDGET(win));
}

/* This method shows the specified window and try to put it at its
   former position if the good parameter is used. */
void visuShowWindow(GtkWindow *win)
{
  int *val;

  if (!win)
    return;

  if (rememberWindowPosition)
    {
      val = (int*)g_hash_table_lookup(windowPosition, win);
      if (val)
      {
        gtk_window_move(win, val[0], val[1]);
        DBG_fprintf(stderr, "Gtk Main : set position (%d,%d) for window %d.\n", 
                  val[0], val[1], GPOINTER_TO_INT(win));
      }
    }
  gtk_widget_show(GTK_WIDGET(win));
}






/* Draw the alert window with the specified message. */
void raiseAlertDialog(char *message)
{
  GtkWidget *alert;
  GtkWidget *label;
  GtkWidget *wd;

  alert = create_alertDialog ();
  label = lookup_widget(alert, "alertLabel");
  gtk_label_set_text(GTK_LABEL(label), message);
  gtk_widget_set_name(alert, "error");
  wd = lookup_widget(alert, "buttonAlert");
  gtk_widget_set_name(wd, "error_button");
  gtk_widget_show (alert);
  /* block in a loop waiting for reply. */
  gtk_dialog_run (GTK_DIALOG (alert));
  gtk_widget_destroy(alert);
}
/* Draw the alert window with the specified message. */
void raiseAlertDialogWithScrollView(char *message)
{
  GtkWidget *alert;
  GtkWidget *text;
  GtkWidget *wd;
  GtkTextBuffer *buf;

  alert = create_alertDialogLong ();
  text = lookup_widget(alert, "alertText");
  buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW(text));
  if (message)
    gtk_text_buffer_set_text (GTK_TEXT_BUFFER(buf), message, -1);
  else
    gtk_text_buffer_set_text (GTK_TEXT_BUFFER(buf), _("INTERNAL ERROR! No message available!"), -1);
  gtk_widget_set_name(alert, "error");
  wd = lookup_widget(alert, "buttonAlert");
  gtk_widget_set_name(wd, "error_button");
  gtk_widget_show (alert);
  /* block in a loop waiting for reply. */
  gtk_dialog_run (GTK_DIALOG (alert));
  gtk_widget_destroy(alert);
}
/* This function must be called in a blocking loop to update
   different things like the gtk for example. */
void visuWaitFunction()
{
  while(gtk_events_pending())
    gtk_main_iteration();
}


GList* gtkMainCreate_fileChooserFilter(GList *list, GtkWidget *fileChooser)
{
  GtkFileFilter *filter, *filterAll;
  GList *tmpLst, *tmpLst2;
  char *name;
  FileFilterCustom *data;
  GList *returnedFilters;

  DBG_fprintf(stderr, "Gtk Main : creating list of filters.\n");
  returnedFilters = (GList*)0;
  filterAll = gtk_file_filter_new ();
  gtk_file_filter_set_name(filterAll, _("All supported formats"));
  tmpLst = list;
  while(tmpLst)
    {
      filter = gtk_file_filter_new ();
      name = fileFormatGet_label((FileFormat*)tmpLst->data);
      if (name)
      gtk_file_filter_set_name(filter, name);
      else
      gtk_file_filter_set_name(filter, _("No description"));
      tmpLst2 = ((FileFormat*)tmpLst->data)->fileType;
      while (tmpLst2)
      {
        gtk_file_filter_add_pattern (filter, (char*)tmpLst2->data);
        gtk_file_filter_add_pattern (filterAll, (char*)tmpLst2->data);
        tmpLst2 = g_list_next(tmpLst2);
      }
      data = g_malloc(sizeof(FileFilterCustom));
      data->gtkFilter = filter;
      data->visuFilter = (FileFormat*)tmpLst->data;
      returnedFilters = g_list_append(returnedFilters, (gpointer)data);
      tmpLst = g_list_next(tmpLst);
    }
  data = g_malloc(sizeof(FileFilterCustom));
  data->gtkFilter = filterAll;
  data->visuFilter = (FileFormat*)0;
  returnedFilters = g_list_append(returnedFilters, (gpointer)data);
  filter = gtk_file_filter_new ();
  gtk_file_filter_set_name(filter, "All files");
  gtk_file_filter_add_pattern (filter, "*");
  data = g_malloc(sizeof(FileFilterCustom));
  data->gtkFilter = filter;
  data->visuFilter = (FileFormat*)0;
  returnedFilters = g_list_append(returnedFilters, (gpointer)data);
  
  DBG_fprintf(stderr, "Gtk Main : attach list to the given filechooser.\n");
  tmpLst = returnedFilters;
  while(tmpLst)
    {
      gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(fileChooser),
                          ((FileFilterCustom*)tmpLst->data)->gtkFilter);
      tmpLst = g_list_next(tmpLst);
    }
  gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(fileChooser), filterAll);

  return returnedFilters;
}
int gtkMainCreate_defaultFileChooser(VisuData *data, GtkFileChooser **fileChooser,
                             GtkWidget **fileWidget)
{
  GtkWidget *fileSelection;
  GList *filters, *tmpLst;
  RenderingMethod *method;
  gchar* directory, *filename;
  FileFormat *selectedFormat;
  GtkFileFilter *filterDefault;
  int res;

  if (!data)
    return 0;

  method = getRenderingMethodInUse();
  g_return_val_if_fail(method, -1);

  fileSelection = gtk_file_chooser_dialog_new(_("Load session"),
                                    GTK_WINDOW(mainWindow),
                                    GTK_FILE_CHOOSER_ACTION_OPEN,
                                    GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
                                    GTK_STOCK_OPEN, GTK_RESPONSE_OK,
                                    NULL);
  *fileChooser = GTK_FILE_CHOOSER(fileSelection);
  *fileWidget = fileSelection;
  directory = getLastOpenDirectory();
  if (directory)
    gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(fileSelection), directory);

  gtk_widget_set_name(fileSelection, "filesel");
  gtk_window_set_position(GTK_WINDOW(fileSelection), GTK_WIN_POS_CENTER_ON_PARENT);
  gtk_window_set_modal(GTK_WINDOW(fileSelection), TRUE);

  filters = gtkMainCreate_fileChooserFilter(method->fileType[0], fileSelection);
  
  if (gtk_dialog_run(GTK_DIALOG(fileSelection)) == GTK_RESPONSE_OK)
    {
      /* Get the selected filter. */
      selectedFormat = (FileFormat*)0;
      filterDefault = gtk_file_chooser_get_filter(GTK_FILE_CHOOSER(fileSelection));
      tmpLst = filters;
      while(tmpLst)
      {
        if (filterDefault == ((FileFilterCustom*)tmpLst->data)->gtkFilter)
          selectedFormat = ((FileFilterCustom*)tmpLst->data)->visuFilter;
        tmpLst = g_list_next(tmpLst);
      }
      filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fileSelection));
      visuDataAdd_file(data, filename, 0, selectedFormat);
      g_free(filename);
      res = 1;
    }
  else
    res = 0;

  /* Free the filters list. */
  DBG_fprintf(stderr, "Gtk Main : free load dialog.\n");
  tmpLst = filters;
  while(tmpLst)
    {
      g_free(tmpLst->data);
      tmpLst = g_list_next(tmpLst);
    }
  g_list_free(filters);
  return res;
}

void gtkMainSet_renderingSpecificMethods(RenderingMethod *method,
                               createGtkWidgetFunc createLoadWidget,
                               createGtkLoadWidgetFunc methodLoad)
{
  struct renderingMethod_gtkMain_struct *container;

  if (!method)
    return;

  container = malloc(sizeof(struct renderingMethod_gtkMain_struct));
  if (!container)
    {
      allocationProblems();
      exit(1);
    }
  container->createOpenAddOn = createLoadWidget;
  container->createLoadAction = methodLoad;
  
  g_hash_table_insert(renderingMethod_gtkMain, (gpointer)method, (gpointer)container);
}
createGtkLoadWidgetFunc gtkMainGet_renderingSpecificOpen(RenderingMethod *method)
{
  struct renderingMethod_gtkMain_struct *container;

  if (!method)
    return (createGtkLoadWidgetFunc)0;

  DBG_fprintf(stderr, "Gtk Main : looking for a specific load interface for rendering"
            " method '%s'...\n", method->name);
  
  container = (struct renderingMethod_gtkMain_struct *)
    g_hash_table_lookup(renderingMethod_gtkMain, (gpointer)method);

  if (!container)
    return (createGtkLoadWidgetFunc)0;
  
  if (container->createLoadAction)
    return container->createLoadAction;
  else
    return gtkMainCreate_defaultFileChooser;
}

void onHideNextTime(GtkToggleButton *button, gpointer data)
{
  char *posNext;
  gchar *path, *bufferR, *pos;
  GString *errorMessage, *bufferW, *bufferW2;
  gboolean resOk;
  int lines;
  GIOChannel *file;
  GError *err;
  gsize taille;
  GIOStatus statOK;

  g_return_if_fail(data);
  path = (gchar*)data;
  
  DBG_fprintf(stderr, "Gtk Main : change the warning dialog parameter in file '%s'.\n", path);
  warningWhenQuit = !gtk_toggle_button_get_active(button);

  /* If no file exists in the given path, we create it. */
  if (!g_file_test(path, G_FILE_TEST_EXISTS))
    {
      errorMessage = (GString*)0;
      resOk = visuConfigFileSave(VISU_CONFIGFILE_PARAMETER, path,
                         &errorMessage, &lines, (VisuData*)0);
      if (!resOk)
      {
        if (errorMessage)
          raiseAlertDialogWithScrollView(errorMessage->str);
      }
      if (errorMessage)
      {
        DBG_fprintf(stderr, "Gtk Main : trace from exporting par...\n%s",
                  errorMessage->str);
        g_string_free(errorMessage, TRUE);
      }
      return;
    }

  /* If a parameter file already exist, we then just change the right line. */
  err = (GError*)0;
  file = g_io_channel_new_file(path, "r", &err);
  if (err)
    {
      raiseAlertDialogWithScrollView(err->message);
      g_error_free(err);
      return;
    }

  bufferR = (gchar*)0;
  err = (GError*)0;
  statOK = g_io_channel_read_to_end(file, &bufferR, &taille, &err);
  if (err)
    {
      raiseAlertDialogWithScrollView(err->message);
      g_error_free(err);
      g_io_channel_shutdown(file, FALSE, (GError**)0);
      g_io_channel_unref(file);
      return;
    }

  
  g_io_channel_shutdown(file, FALSE, (GError**)0);
  g_io_channel_unref(file);

  /* We reopen the channel in write acces. */
  err = (GError*)0;
  file = g_io_channel_new_file(path, "w", &err);
  if (err)
    {
      raiseAlertDialogWithScrollView(err->message);
      g_error_free(err);
      return;
    }

  bufferW = g_string_new(bufferR);
  g_free(bufferR);
  /* Try to find the flag of the parameter. */
  pos = g_strrstr(bufferW->str, "\n"FLAG_PARAMETER_GTKMAIN_QUIT);
  if (!pos)
    {
      /* We append it at the end of the file. */
      DBG_fprintf(stderr, " | Can't find the option, appending it.\n");
      exportParametersGtkMain(bufferW, &lines, (VisuData*)0);

      err = (GError*)0;
      statOK = g_io_channel_write_chars(file, bufferW->str, -1,
                                        &taille, &err);
      if (err)
      {
        raiseAlertDialogWithScrollView(err->message);
        g_error_free(err);
      }
    }
  else
    {
      DBG_fprintf(stderr, " | Option found, changing its value.\n");
      /* We erase the line and rewrite it. */
      *(pos + 1) = '\0';
      bufferW2 = g_string_new(bufferW->str);
      g_string_append_printf(bufferW2, "%s[gtk]: %i\n", FLAG_PARAMETER_GTKMAIN_QUIT,
                       (int)warningWhenQuit);
      posNext = strstr(pos + 2, "\n");
      if (posNext)
      g_string_append(bufferW2, posNext + 1);
      
      err = (GError*)0;
      statOK = g_io_channel_write_chars(file, bufferW2->str, -1,
                                        &taille, &err);
      if (err)
      {
        raiseAlertDialogWithScrollView(err->message);
        g_error_free(err);
      }
      g_string_free(bufferW2, TRUE);
    }
  g_io_channel_shutdown(file, TRUE, (GError**)0);
  g_io_channel_unref(file);

  g_string_free(bufferW, TRUE);
}
static void onAddHomedir(GtkButton *button, gpointer quitDialog)
{
  GtkWidget *wd;
  GList *dirs, *tmplst;
  gchar *path;

  DBG_fprintf(stderr, "Gtk Main: try to create the local home directory.\n");
#if SYSTEM_X11 == 1
  if (mkdir(v_sim_local_conf_dir, 750))
#endif
#if SYSTEM_WIN32 == 1
  if (mkdir(v_sim_local_conf_dir))
#endif
    {
      /* Failed. */
      raiseAlertDialog(_("Can't create the directory '$HOME/.v_sim'."));
    }
  else
    {
      /* Succeed hide the warning. */
      wd = lookup_widget(GTK_WIDGET(quitDialog), "hboxHomedir");
      gtk_widget_hide(wd);
      /* Retest the path. */
      dirs = (GList*)0;
      dirs = g_list_prepend(dirs, (gpointer)v_sim_conf_dir);
      dirs = g_list_prepend(dirs, (gpointer)v_sim_local_conf_dir);
      tmplst = dirs;

      path = (gchar*)0;
      path = visuConfigFileGet_nextValidPath(VISU_CONFIGFILE_PARAMETER,
                                   W_OK, &tmplst, 0);
      if (path)
      {
        wd = lookup_widget(GTK_WIDGET(quitDialog), "hboxWarning");
        gtk_widget_hide(wd);
        wd = lookup_widget(GTK_WIDGET(quitDialog), "checkbuttonHideNextTime");
        gtk_widget_set_sensitive(wd, TRUE);
        g_signal_connect(G_OBJECT(wd), "toggled",
                     G_CALLBACK(onHideNextTime), (gpointer)path);
      }
      g_list_free(dirs);
    }
}
static gboolean onKillRenderingWindowEvent(GtkWidget *widget, GdkEvent *event,
                                 gpointer user_data)
{
  onQuitButton((GtkButton *)0, (gpointer)0);
  return TRUE;
}
static void onQuitButton(GtkButton *button, gpointer data)
{
  GtkWidget *quitDialog, *wd;
  GList *dirs, *tmplst;
  gchar *path;

  if (!warningWhenQuit)
    {
      gtk_main_quit();
      return;
    }

  quitDialog = create_quitDialog();
  
  /* Try to find installDir/v_sim.par or ~/.v_sim/v_sim.par
     that is writable to store the preference of the hiding
     mode of the dialog. */
  dirs = (GList*)0;
  dirs = g_list_prepend(dirs, (gpointer)v_sim_conf_dir);
  dirs = g_list_prepend(dirs, (gpointer)v_sim_local_conf_dir);
  tmplst = dirs;

  path = (gchar*)0;
  path = visuConfigFileGet_nextValidPath(VISU_CONFIGFILE_PARAMETER, W_OK, &tmplst, 0);
  if (!path)
    {
      wd = lookup_widget(quitDialog, "hboxWarning");
      gtk_widget_show(wd);
    }
  g_list_free(dirs);

  /* Attach a create the homedir method to the button. */
  wd = lookup_widget(quitDialog, "buttonAddHomedir");
  g_signal_connect(G_OBJECT(wd), "clicked",
               G_CALLBACK(onAddHomedir), (gpointer)quitDialog);
  /* Show the warning if the homedir is not existing and no path was found. */
  if (!g_file_test(v_sim_local_conf_dir, G_FILE_TEST_IS_DIR) && !path)
    {
      wd = lookup_widget(quitDialog, "hboxHomedir");
      gtk_widget_show(wd);
    }

  /* Attach a modify the parameter to the checkbox. */
  wd = lookup_widget(quitDialog, "checkbuttonHideNextTime");
  if (!path)
    gtk_widget_set_sensitive(wd, FALSE);
  else
    g_signal_connect(G_OBJECT(wd), "toggled",
                 G_CALLBACK(onHideNextTime), (gpointer)path);
  
  if (gtk_dialog_run(GTK_DIALOG(quitDialog)) == GTK_RESPONSE_OK)
    gtk_main_quit();
  else
    gtk_widget_destroy(quitDialog);
}

gboolean readMainQuitPolicy(gchar **lines, int nbLines,
                      int position, GString *errorMessage)
{
  int res;
  int bool;

  res = sscanf(lines[0],"%d", &bool);
  if (res != 1)
    {
      if (errorMessage)
      g_string_append_printf(errorMessage, _("WARNING! Parse error at line %d,"
                                     " 1 boolean value must appear"
                                     " after the %s markup.\n"),
                         position, FLAG_PARAMETER_GTKMAIN_QUIT);
      warningWhenQuit = PARAMETER_GTKMAIN_QUIT_DEFAULT;
      return FALSE;
    }
  
  if (bool)
    warningWhenQuit = TRUE;
  else
    warningWhenQuit = FALSE;
  
  return TRUE;
}
gboolean readMainPanelStatus(gchar **lines, int nbLines,
                       int position, GString *errorMessage)
{
  gchar **tokens;
  ToolPanel *toolpanel;
  char *pt;

  tokens = g_strsplit(g_strchug(lines[0]), " ", 2);
  if (!tokens[0] || !tokens[1])
    {
      if (errorMessage)
      g_string_append_printf(errorMessage, _("WARNING! Parse error at line %d,"
                                     " 'id id' awaited.\n"),
                         position);
      g_strfreev(tokens);
      return FALSE;
    }
  toolpanel = toolPanelClassGet_toolPanelById(tokens[0]);
  if (!toolpanel)
    {
      if (errorMessage)
      g_string_append_printf(errorMessage, _("WARNING! Parse error at line %d,"
                                     " unknown panel id '%s'.\n"),
                         position, tokens[0]);
      g_strfreev(tokens);
      return FALSE;
    }
  pt = strchr(tokens[1], '\n');
  if (pt)
    *pt = ' ';
  toolPanelSet_containerId(toolpanel, g_strchomp(tokens[1]));

  g_strfreev(tokens);
  return TRUE;
}
gboolean readMainDock(gchar **lines, int nbLines,
                  int position, GString *errorMessage)
{
  int res;
  gchar **tokens, *values;
  gboolean visible;
  int x, y, width, height;

  tokens = g_strsplit(g_strchug(lines[0]), " ", 4);
  if (!tokens[0] || !tokens[1] || !tokens[2] || !tokens[3])
    {
      if (errorMessage)
      g_string_append_printf(errorMessage, _("WARNING! Parse error at line %d,"
                                     " 'values id' awaited.\n"),
                         position);
      g_strfreev(tokens);
      return FALSE;
    }
  values = g_strjoin(" ", tokens[0], tokens[1], tokens[2], NULL);
  res = sscanf(values, "%d %dx%d %dx%d", (int*)&visible, &x, &y, &width, &height);
  g_free(values);
  if (res != 5)
    {
      if (errorMessage)
      g_string_append_printf(errorMessage, _("WARNING! Parse error at line %d,"
                                     " can't read dock characteristics"
                                     " value from '%s'.\n"),
                         position, values);
      g_strfreev(tokens);
      return FALSE;
    }
  toolPanelClassSet_windowSize(g_strchomp(tokens[3]), (guint)width, (guint)height);
  toolPanelClassSet_windowPosition(tokens[3], (guint)x, (guint)y);
  toolPanelClassSet_windowVisibility(tokens[3], visible);

  g_strfreev(tokens);
  return TRUE;
}
gboolean exportParametersGtkMain(GString *data, int *nbLinesWritten,
                         VisuData* dataObj)
{
  GList *tmplst, *panelLst, *dockLst;
  gint x, y, width, height;
  gboolean visilibity;
  gchar *id;

  g_string_append_printf(data, "# %s\n", DESC_PARAMETER_GTKMAIN_QUIT);
  g_string_append_printf(data, "%s[gtk]: %i\n\n", FLAG_PARAMETER_GTKMAIN_QUIT,
                   (int)warningWhenQuit);
  *nbLinesWritten = 3;

  /* Write the panel list. */
  panelLst = toolPanelClassGet_allToolPanels();
  if (panelLst)
    {
      g_string_append_printf(data, "# %s\n", DESC_PARAMETER_GTKMAIN_PANEL);
      *nbLinesWritten += 1;
    }
  tmplst = panelLst;
  while(tmplst)
    { 
      g_string_append_printf(data, "%s[gtk]: %s %s\n", FLAG_PARAMETER_GTKMAIN_PANEL,
                       toolPanelGet_id(TOOL_PANEL(tmplst->data)),
                       toolPanelGet_containerId(TOOL_PANEL(tmplst->data)));
      *nbLinesWritten += 1;
      tmplst = g_list_next(tmplst);
    }
  if (panelLst)
    {
      g_string_append_printf(data, "\n");
      *nbLinesWritten += 1;
    }
  g_list_free(panelLst);

  /* Write the panel list. */
  dockLst = toolPanelClassGet_allWindows();
  if (dockLst)
    {
      g_string_append_printf(data, "# %s\n", DESC_PARAMETER_GTKMAIN_DOCK);
      *nbLinesWritten += 1;
    }
  tmplst = dockLst;
  while(tmplst)
    { 
      toolPanelClassGet_windowCharacteristics((DockWindow*)(tmplst->data), &id,
                                    &visilibity, &x, &y, &width, &height);
      g_string_append_printf(data, "%s[gtk]: %d %dx%d %dx%d %s\n",
                       FLAG_PARAMETER_GTKMAIN_DOCK,
                       (int)visilibity, x, y, width, height, id);
      *nbLinesWritten += 1;
      tmplst = g_list_next(tmplst);
    }
  if (dockLst)
    {
      g_string_append_printf(data, "\n");
      *nbLinesWritten += 1;
    }
  g_list_free(dockLst);

  return TRUE;
}

Generated by  Doxygen 1.6.0   Back to index