Index: Evidence/Alarm.cc
===================================================================
--- Evidence/Alarm.cc	(revision 151)
+++ Evidence/Alarm.cc	(revision 152)
@@ -51,5 +51,5 @@
   AlarmSummary = new char [SUMMARYSIZE];
   MasterAlarm = 0;
-  
+
   char *ServerNames = GetConfig(SERVER_NAME " servers");
 
Index: Evidence/DColl.cc
===================================================================
--- Evidence/DColl.cc	(revision 151)
+++ Evidence/DColl.cc	(revision 152)
@@ -11,4 +11,6 @@
 	written to the data file. Only if the new value has changed by a
 	minimum amout it will be added to the ring buffer.
+  - The history buffers are written to disk at program termination and
+    are tired to be read when adding a service.
   - The command 'DColl/Log' writes the associated string to the log 
     file specified in the configuration.
@@ -23,4 +25,9 @@
 
 #include "Evidence.h"
+
+#include <string>
+#include <sstream>
+#include <vector>
+#include <iomanip>
 
 #include <math.h>
@@ -44,16 +51,17 @@
 	  double LastValue;
 	  double MinAbsChange;
-	} *List;
-
+	};
+	vector<struct Item> List;
+	
 	DimCommand *LogCommand;
 		
-    unsigned int NumItems;
-	char *Filename;
     FILE *DataFile;
     FILE *LogFile;
+	char *Filename;
 	float DataSizekB, LogSizekB;
 	int DataSizeLastUpdate, LogSizeLastUpdate;
 	char *DataDir;
     DimService *LogSizeService, *DataSizeService, *DataFilename;
+	string HistDir;
     int HistSize;
 	int SizeUpdateDelay;
@@ -66,5 +74,5 @@
     void infoHandler();
     void commandHandler();
-	void AddService(char *);
+	void AddService(string);
 	float FileSize(FILE *);
 	    
@@ -80,8 +88,8 @@
 
   // Initialization to prevent freeing unallocated memory 
-  Filename = NULL;
   DataFile = NULL;
   LogFile = NULL;
-  List = NULL;
+  Filename = NULL;
+  
   LogSizeService = NULL;
   DataSizeService = NULL;
@@ -93,9 +101,15 @@
   // Request configuration data
   char *Change = GetConfig(SERVER_NAME " minchange");
+
   DataDir = GetConfig(SERVER_NAME " datadir");
+
   char *Logname = GetConfig(SERVER_NAME " logfile");
+
   SizeUpdateDelay = atoi(GetConfig(SERVER_NAME " sizeupdate"));
+
   HistSize = atoi(GetConfig(SERVER_NAME " histsize"));
   if (HistSize < 1) HistSize = 1; // Minimum one items
+
+  HistDir = GetConfig(SERVER_NAME " histdir");
    
   // Open log file
@@ -148,5 +162,5 @@
 
   // Subscribe to list of servers at DIS_DNS 
-  AddService((char *) "DIS_DNS/SERVER_LIST");
+  AddService("DIS_DNS/SERVER_LIST");
 
   DimClient::sendCommand("DColl/Log", SERVER_NAME" *** Logging started ***");
@@ -158,18 +172,31 @@
 DataHandler::~DataHandler() {
 
-  // Delete DIM services and command first so handlers and not called anymore
-  for (int i=0; i<NumItems; i++) {
+  DimClient::sendCommand("DColl/Log", SERVER_NAME" *** Logging stopped ***");
+
+  // Delete DIM subscriptions and command first so handlers and not called anymore
+  for (int i=0; i<List.size(); i++) {
+    delete List[i].DataItem;
+  }
+  delete LogCommand;
+  
+  // Save history buffers to files (replace '/' by '_')
+  for (int i=0; i<List.size(); i++) {
+    string Name = List[i].HistService->getName();
+	for (int j=0; j<Name.size(); j++) if (Name[j] == '/') Name[j] = '_';
+    FILE *File = fopen((HistDir + "/" + Name).c_str(), "wb");
+	if (File != NULL) {
+      fwrite(&List[i].HistPointer, sizeof(List[i].HistPointer), 1, File);
+      fwrite(List[i].HistBuffer, sizeof(EvidenceHistoryItem), HistSize, File);
+      fclose(File);
+	}
 	delete List[i].HistService;
-    delete List[i].DataItem;
     delete[] List[i].HistBuffer;
   }
-  free(List);
 
   delete DataFilename;
+  delete[] Filename;
+  
   //delete LogSizeService; // These create segmentation faults?!
   //delete DataSizeService;
-
-  delete LogCommand;
-  free(Filename);
 
   // Close files
@@ -203,15 +230,12 @@
   // If service is DIS_DNS/SERVER_LIST, subscribe to all SERVICE_LIST services
   if (strcmp(Info->getName(), "DIS_DNS/SERVER_LIST") == 0) {	
-	char *Token = strtok(Info->getString(), "+-!|@");	
+	char *Token = strtok(Info->getString(), "@");	
 	while (Token != NULL) {
-	  char *Buf;
-	  if (MakeString(&Buf, "%s/SERVICE_LIST", Token) != -1) {
-	    AddService(Buf);
-		free(Buf);
-	  }
-	  else State(ERROR, "MakeString() failed for server %s", Token);
+  	  if (isalpha(*Token) == 0) Token++; // Name can start with +,-,!
 	  
-  	  Token = strtok(NULL, "|");
-	  Token = strtok(NULL, "+-!|@");	
+	  AddService(string(Token)+"/SERVICE_LIST");	  
+  	  
+	  Token = strtok(NULL, "|");
+	  Token = strtok(NULL, "|@");	// ???? Why needed ?????
 	}	
 	return;
@@ -221,12 +245,14 @@
   // Subscribe to all services (but not to commands and RPCs)
   if (strstr(Info->getName(), "/SERVICE_LIST") != NULL) {
-	char *Name = strtok(Info->getString(), "+-!|");
+
+	char *Name = strtok(Info->getString(), "|");
 	while (Name != NULL) {
 	  char *Type = strtok(NULL, "\n");
 	  if (Type == NULL) return; // for safety, should not happen
+	  if (isalpha(*Name) == 0) Name++; // Name can start with +,-,!
       if (strstr(Type, "|CMD")==NULL && strstr(Type, "|RPC")==NULL) {
 		AddService(Name);
 	  }
-	  Name = strtok(NULL, "+-!|");
+	  Name = strtok(NULL, "|");
 	}
 	return;
@@ -245,10 +271,17 @@
 	time_t Time = time(NULL);
 	struct tm *T = localtime(&Time);
-	
+	ostringstream Buf;
+	
+	// Generate file name from date
 	if(T->tm_hour >= DATE_ROLLOVER) T->tm_mday++;
 	if (mktime(T) == -1) State(ERROR, "mktime() failed, check filename");
-
-	free(Filename);
-	if (MakeString(&Filename, "%s/%d%02d%02d.slow", DataDir, T->tm_year+1900, T->tm_mon+1, T->tm_mday) == -1) State(FATAL, "Could not create filename, MakeString() failed");
+	Buf << DataDir << "/" << T->tm_year+1900 << setw(2) << setfill('0') << T->tm_mon+1 << T->tm_mday << ".slow";
+	
+	// Copy filename to permanent buffer
+	delete[] Filename;
+	Filename = new char [Buf.str().size()+1];
+	strcpy(Filename, Buf.str().c_str());
+	
+	// Open file
 	if ((DataFile = fopen(Filename, "a")) == NULL) {
       State(FATAL, "Could not open data file '%s' (%s)", Filename, strerror(errno));
@@ -266,6 +299,6 @@
   // Identify index of service
   int Service;  
-  for (Service=0; Service<NumItems; Service++) if (Info == List[Service].DataItem) break;
-  if (Service == NumItems) return;  // Service not found
+  for (Service=0; Service<List.size(); Service++) if (Info == List[Service].DataItem) break;
+  if (Service == List.size()) return;  // Service not found
 
   // If negative value for absolute change, ignore this entry
@@ -360,52 +393,48 @@
 // Add service to watch list
 //
-void DataHandler::AddService(char *Name) {
+void DataHandler::AddService(string Name) {
 
   // Do not subscribe to history services (otherwise infinite loop)
-  if (strstr(Name, ".hist") != NULL) return;
+  if (Name.find(".hist") != string::npos) return;
 
   // Check if already subscribed to this service
-  for (int i=0; i<NumItems; i++) {
-	if(strcmp(Name, List[i].DataItem->getName()) == 0) return;
-  }
-
-  // Increase capacity of item list			
-  struct Item *New = (struct Item *) realloc(List, (NumItems+1)*sizeof(struct Item));
-  if (New != NULL) List = New;
-  else {
-	State(ERROR, "Could not allocate memory for item list, service '' not added (%s)", Name, strerror(errno));
-	return;
-  }
-  
+  for (int i=0; i<List.size(); i++) {
+	if (Name == List[i].DataItem->getName()) return;
+  }
+  
+  // Create new entry in item list
+  struct Item New;
+
   // Set minimum required change by comparing to regular expressions
-  List[NumItems].MinAbsChange = 0;
+  New.MinAbsChange = 0;
   for (int i=0; i<RegExCount; i++) {
-    if (regexec(&RegEx[i], Name, (size_t) 0, NULL, 0) == 0) {
-	  List[NumItems].MinAbsChange = MinChange[i];
-	}
-  }
-  
-  List[NumItems].LastValue = DBL_MAX;
-		
+    if (regexec(&RegEx[i], Name.c_str(), (size_t) 0, NULL, 0) == 0) {
+	  New.MinAbsChange = MinChange[i];
+	}
+  }
+  		
   // Create history service
-  List[NumItems].HistBuffer = new struct EvidenceHistoryItem [HistSize];
-  memset(List[NumItems].HistBuffer, 0, HistSize*sizeof(EvidenceHistoryItem));
-  List[NumItems].HistPointer = 0;
-
-  char *Buf;
-  if (MakeString(&Buf, "%s.hist", Name) == -1) {
-    State(ERROR, "Could not create history service for '%s', MakeString() failed", Name);
-  }
-  else {
-	List[NumItems].HistService = new DimService (Buf, (char *) "C",
-  					  List[NumItems].HistBuffer, HistSize*sizeof(EvidenceHistoryItem));
-    free(Buf);
-  }
-
+  New.HistBuffer = new struct EvidenceHistoryItem [HistSize];
+  memset(New.HistBuffer, 0, HistSize*sizeof(EvidenceHistoryItem));
+  New.HistPointer = 0;
+  New.LastValue = DBL_MAX;
+  New.HistService = new DimService ((Name+".hist").c_str(), (char *) "C",
+  					  New.HistBuffer, HistSize*sizeof(EvidenceHistoryItem));
+	
+  // Load history buffer from file if existing
+  string Filename = New.HistService->getName();
+  for (int j=0; j<Filename.size(); j++) if (Filename[j] == '/') Filename[j] = '_';
+  FILE *File = fopen((HistDir + "/" + Filename).c_str(), "rb");
+  if (File != NULL) {
+    fread(&New.HistPointer, sizeof(New.HistPointer), 1, File);
+    fread(New.HistBuffer, sizeof(EvidenceHistoryItem), HistSize, File);
+    fclose(File);
+  }
+  
   // Subscribe to service
-  List[NumItems].DataItem = new DimStampedInfo(Name, NO_LINK, this);
-
-  // Increase number only after all set-up
-  NumItems++;
+  New.DataItem = new DimStampedInfo(Name.c_str(), NO_LINK, this);
+
+  // Add item to list
+  List.push_back(New);
 }
 
Index: Evidence/Edd/Edd.cc
===================================================================
--- Evidence/Edd/Edd.cc	(revision 151)
+++ Evidence/Edd/Edd.cc	(revision 152)
@@ -174,6 +174,9 @@
   Grid->attach(this);
   Legend = new QwtLegend();
+  Legend->setItemMode(QwtLegend::ClickableItem);
   insertLegend(Legend, QwtPlot::TopLegend);
 
+  connect(this, SIGNAL(legendClicked (QwtPlotItem *)), SLOT(LegendClicked(QwtPlotItem *)));
+  
   // Connect to DIM handler
   if (connect(Handler, SIGNAL(YEP(DimInfo *, int, QString, QByteArray, QString)), SLOT(Update(DimInfo *, int, QString, QByteArray, QString))) == false) {
@@ -409,7 +412,5 @@
 }
     
-//
 // Opening context menu
-//
 void Edd_Plot::contextMenuEvent(QContextMenuEvent *Event) {
 
@@ -417,4 +418,16 @@
 }
 
+// Drag&Drop method
+void Edd_Plot::LegendClicked(QwtPlotItem *Item) {
+
+  QDrag *Drag = new QDrag(this);
+  QMimeData *MimeData = new QMimeData;
+  MimeData->setText(Item->title().text().remove(".hist"));
+  Drag->setMimeData(MimeData);
+  Drag->exec();
+}
+
+
+// Zoom completely out
 void Edd_Plot::MenuZoomOut() {
 
@@ -648,10 +661,10 @@
   Graph = new Edd_Plot();
   for (int i=0; i<18; i++) {
-    Text = Text.sprintf("BIAS/VOLT/ID00/00-%.3d",i);
+    Text = Text.sprintf("Bias/VOLT/ID00/00-%.3d",i);
     Value = new Edd_Indicator(Text);
     BiasLayout->addWidget(Value, i%9+1, 0+i/9, 1, 1);
     Graph->AddService(Text);
 
-    Text = Text.sprintf("BIAS/VOLT/ID00/01-%.3d",i);
+    Text = Text.sprintf("Bias/VOLT/ID00/01-%.3d",i);
     Value = new Edd_Indicator(Text);
     BiasLayout->addWidget(Value, i%9+1, 2+i/9, 1, 1);
@@ -660,9 +673,9 @@
 
   BiasLayout->addWidget(Graph, 0, 4, 12, 3);
-  Value = new Edd_Indicator("BIAS/Status");
+  Value = new Edd_Indicator("Bias/Status");
   Value->setMaximumWidth(200);
   BiasLayout->addWidget(Value, 0, 0, 1, 3);      
 
-  Textout = new Edd_Textout("BIAS/Textout");
+  Textout = new Edd_Textout("Bias/Textout");
   Textout->setFixedWidth(400);
   BiasLayout->addWidget(Textout, 10, 0, 4, 4);      
Index: Evidence/Edd/Edd.h
===================================================================
--- Evidence/Edd/Edd.h	(revision 151)
+++ Evidence/Edd/Edd.h	(revision 152)
@@ -96,5 +96,6 @@
 
     void HandleZoom(const QwtDoubleRect &);
-    void contextMenuEvent(QContextMenuEvent *);    
+    void contextMenuEvent(QContextMenuEvent *);
+	void LegendClicked(QwtPlotItem *);
     void MenuZoomOut();
     void MenuSingleTrace();        
Index: Evidence/Evidence.cc
===================================================================
--- Evidence/Evidence.cc	(revision 151)
+++ Evidence/Evidence.cc	(revision 152)
@@ -26,4 +26,5 @@
 
 bool EvidenceServer::ExitRequest = false;
+string __StatusName;
 
 // Constructor starts server with given name
@@ -34,4 +35,5 @@
   ConfigList = NULL;
   ConfigNum = 0;
+  __StatusName = string(Name) + "/Status";
   
   // Catch some signals
@@ -41,11 +43,9 @@
   signal(SIGHUP, &SignalHandler);   // Terminal closed
   
-  // Create server name
-  if (MakeString(&StatusName, "%s/Status", Name) == -1) {
-    State(FATAL, "Could not generate service name, asprintf() failed");
-  }
+  // Catch C++ unhandled exceptions
+  set_terminate(Terminate);
   
   // Start server
-  Status = new DimService(StatusName, (char *) "Server started");
+  Status = new DimService(__StatusName.c_str(), (char *) "Server started");
 
   start(Name);
@@ -56,6 +56,4 @@
 EvidenceServer::~EvidenceServer() {
 
-  free(StatusName);
-  
   for (unsigned int i=0; i<ConfigNum; i++) {
   	delete[] ConfigList[i].Name;
@@ -95,5 +93,5 @@
   va_end(ArgumentPointer);
 
-  snprintf(TBuf, sizeof(TBuf), "%s (%s): %s", StatusName, StateString[Severity], Tmp); // Normal string
+  snprintf(TBuf, sizeof(TBuf), "%s (%s): %s", __StatusName.c_str(), StateString[Severity], Tmp); // Normal string
   snprintf(SBuf, sizeof(SBuf), "%s*%c", Tmp, (char) Severity);
   *(strrchr(SBuf, '*')) = '\0';  // String with severity encoding
@@ -115,5 +113,5 @@
 // The memory allocated by all calls to this function will be freed by
 // the destructor.
-char* EvidenceServer::GetConfig(const char *Item) {
+char* EvidenceServer::GetConfig(const char *Item, const char *Default) {
   
   // Determine configuration file update time
@@ -138,8 +136,10 @@
   DimRpcInfo Config((char *) "ConfigRequest", (char *) "");
   Config.setData((char *) Item);
-
+  char *Result = Config.getString();
+  
   // Terminate if not successful
-  if (strlen(Config.getString()) == 0) {
-    State(FATAL, "Missing configuration data '%s'", Item);
+  if (strlen(Result) == 0) {
+    if (Default == NULL) State(FATAL, "Missing configuration data '%s'", Item);
+	Result = (char *) Default;
   }
 
@@ -157,8 +157,8 @@
   
   // Allocate memory for strings, and copy data to this memory
-  ConfigList[ItemNo].Value = new char [strlen(Config.getString())+1];
+  ConfigList[ItemNo].Value = new char [strlen(Result)+1];
   ConfigList[ItemNo].Name = new char [strlen(Item)+1];
   strcpy(ConfigList[ItemNo].Name, Item);
-  strcpy(ConfigList[ItemNo].Value, Config.getString());
+  strcpy(ConfigList[ItemNo].Value, Result);
 
   ConfigList[ItemNo].Time = Time;
@@ -175,4 +175,14 @@
 
   EvidenceServer::ExitRequest = true;
+}
+
+// C++ exception handler
+void EvidenceServer::Terminate() {
+
+  string Msg = __StatusName + ": Caught unhandled exception";
+  printf("%s\n", Msg.c_str());
+  DimClient::sendCommand("DColl/Log", Msg.c_str());
+  
+  abort();
 }
 
@@ -182,36 +192,18 @@
 
   char *Text;
+  int R;
   
   if (strlen(Item->getFormat()) != 1) return NULL;
   
   switch (*(Item->getFormat())) {
-    case 'I':  MakeString(&Text, "%d", Item->getInt());   break;
-    case 'C':  MakeString(&Text, "%s", Item->getString());   break;
-    case 'S':  MakeString(&Text, "%hd", Item->getShort());   break;
-    case 'F':  MakeString(&Text, "%.5f", Item->getFloat());   break;
-    case 'D':  MakeString(&Text, "%.5f", Item->getDouble());   break;
-    case 'X':  MakeString(&Text, "%lld", Item->getLonglong());   break;
+    case 'I':  R = asprintf(&Text, "%d", Item->getInt());   break;
+    case 'C':  R = asprintf(&Text, "%s", Item->getString());   break;
+    case 'S':  R = asprintf(&Text, "%hd", Item->getShort());   break;
+    case 'F':  R = asprintf(&Text, "%.5f", Item->getFloat());   break;
+    case 'D':  R = asprintf(&Text, "%.5f", Item->getDouble());   break;
+    case 'X':  R = asprintf(&Text, "%lld", Item->getLonglong());   break;
     default: return NULL;
   }
 
-  return Text;
-}
-
-//
-// Generate string with vasprintf()
-//
-// The pointer will be set to NULL in case of error, so can always safely passed to free().
-// In case vasprintf() is not available on a particular system, the functionality can
-// be manually implemented in this routine. 
-//
-int EvidenceServer::MakeString(char **Pointer, const char *Format, ...) {
-
-  int Ret;
-  va_list ArgumentPointer;  
-
-  va_start(ArgumentPointer, Format);  
-  if ((Ret = vasprintf(Pointer, Format, ArgumentPointer)) == -1) Pointer = NULL;
-  va_end(ArgumentPointer);
-  
-  return Ret;
-}
+  return (R == -1) ? NULL : Text;
+}
Index: Evidence/Evidence.h
===================================================================
--- Evidence/Evidence.h	(revision 151)
+++ Evidence/Evidence.h	(revision 152)
@@ -4,5 +4,7 @@
 #include <stdio.h>
 #include <stdarg.h>
+#include <string>
 #include <errno.h>
+#include <exception>
 
 #include "dis.hxx"
@@ -11,4 +13,6 @@
 #define NO_LINK (char *) "__&DIM&NOLINK&__" // Data if no link available
 #define STATUS_SIZE 1000					// Bytes for status service string
+
+using namespace std;
 
 // Declaration of item for history buffer (see DColl.cc)
@@ -29,8 +33,8 @@
 	unsigned int ConfigNum;
 
-    char *StatusName;
     DimService *Status;
 
-    static void SignalHandler(int);  // static needed for signal() function
+    static void SignalHandler(int); // static for signal()
+    static void Terminate();  		// static for set_terminate()
 	void errorHandler(int, int, char *);
 	void exitHandler(int);
@@ -43,9 +47,7 @@
 
 	void State(StateType, const char *, ...);
+	char* GetConfig(const char *, const char * = NULL);
+	static char* ToString(DimInfo *);
 
-	char* GetConfig(const char *);
-	static char *ToString(DimInfo *);
-	static int MakeString(char **Pointer, const char *Format, ...);
-	
     static bool ExitRequest;
 };
Index: Evidence/Makefile
===================================================================
--- Evidence/Makefile	(revision 151)
+++ Evidence/Makefile	(revision 152)
@@ -20,3 +20,3 @@
 	@rm -f $(PROG2) $(PROG2).o
 	@rm -f $(PROG3) $(PROG3).o
-	
+	@rm -f Evidence.o	
