Index: Evidence/Edd/Edd.cc
===================================================================
--- Evidence/Edd/Edd.cc	(revision 231)
+++ Evidence/Edd/Edd.cc	(revision 232)
@@ -64,5 +64,4 @@
 
   W->setStatusTip(Status);
-  if (W->parent() == NULL) W->setToolTip(Status);
   
   return(Time != -1);
@@ -132,6 +131,6 @@
     }
 	Text = Text.section(' ', 1);
-  }	
-  else if (Format[0].toUpper() != 'C') Text = Text.section(' ', Index, Index);
+  }
+  else if (Format[0].toUpper() != 'C' && Format != "I:1;C") Text = Text.section(' ', Index, Index);
 
   if (!ShowAsTime) setText(Text);
@@ -233,5 +232,5 @@
 //////////////////////////////////
 
-EddPlot::EddPlot(QString DIMService, int Index, QWidget *P): EddBasePlot(P) {
+EddPlot::EddPlot(QString Service, int Index, QWidget *P): EddBasePlot(P) {
 
   // Widget properties
@@ -247,5 +246,5 @@
   // Connect to DIM handler
   if (connect(Handler, SIGNAL(YEP(QString, int, QByteArray, QString, QString)), SLOT(Update(QString, int, QByteArray, QString, QString))) == false) {
-    printf("Failed connection for %s\n", DIMService.toAscii().data());
+    printf("Failed connection for %s\n", Service.toAscii().data());
   }
 
@@ -259,5 +258,5 @@
 
   // DIM client
-  if (!DIMService.isEmpty()) AddService(DIMService, Index);
+  if (!Service.isEmpty()) AddService(Service, Index);
 }
 
@@ -328,5 +327,5 @@
 	}
 
- 	// Appen data only if service available
+ 	// Append data only if service available
 	if (SetStatus(this, Name, Time, Format)) {
 	  QString Txt = Text;
@@ -597,8 +596,8 @@
   // Rescale y axis (increase range if selected rectangle larger than axis area)
   if (R.right() < 0) {
-	if (R.top() < plotLayout()->canvasRect().top()) {
+	if (yMouse.maxValue() > axisScaleDiv(QwtPlot::yLeft)->upperBound()) {
 	  yMouse.setMaxValue(yMouse.maxValue() + yPlot.width());
 	}
-	if (R.bottom() > plotLayout()->canvasRect().bottom()) {
+	if (yMouse.minValue() < axisScaleDiv(QwtPlot::yLeft)->lowerBound()) {
 	  yMouse.setMinValue(yMouse.minValue() - yPlot.width());
 	}
@@ -609,10 +608,11 @@
   // Rescale x axis (increase range if selected rectangle larger than axis area)
   if (R.top() > plotLayout()->canvasRect().height()) {
-	if (R.left() < plotLayout()->canvasRect().left()) {
+	if (xMouse.maxValue() > axisScaleDiv(QwtPlot::xBottom)->upperBound()) {
+	  xMouse.setMaxValue(xMouse.maxValue() + xPlot.width());
+	}
+	if (xMouse.minValue() < axisScaleDiv(QwtPlot::xBottom)->lowerBound()) {
 	  xMouse.setMinValue(xMouse.minValue() - xPlot.width());
 	}
-	if (R.right() > plotLayout()->canvasRect().right()) {
-	  xMouse.setMaxValue(xMouse.maxValue() + xPlot.width());
-	}
+
 	setAxisScale(QwtPlot::xBottom, xMouse.minValue(), xMouse.maxValue());
   }
@@ -741,5 +741,5 @@
 
   if (!Pure) {
-	// Get history for this service 
+	// Get history for this service
 	const struct EvidenceHistory::Item *R;
 	class EvidenceHistory *Hist;
@@ -748,7 +748,7 @@
 	  while ((R=Hist->Next()) != NULL) {
 		moveCursor (QTextCursor::Start);
-		insertPlainText(QString("(")+QDateTime::fromTime_t(R->Time).toString()+") ");	  
-		insertPlainText(QString((char *) R->Data) + "\n");	  
-	  }
+		insertPlainText(QString("(")+QDateTime::fromTime_t(R->Time).toString()+") " +
+		  QString::fromStdString(EvidenceServer::ToString(Hist->GetFormat(), (void *) R->Data, R->Size)) + "\n"); 
+	  }	
 	}
 	Handler->DropHistory(Name);
@@ -814,7 +814,9 @@
 }
 
+// Destructor
 EddDim::~EddDim() {
 
-  for (int i=0; i<HistoryList.size(); i++) delete HistoryList[i].HistClass;
+  QList<QString> L = HistoryList.keys();
+  for(int i=0; i<L.size(); i++) delete HistoryList[L[i]].HistClass;
 
   delete Mutex;
@@ -827,23 +829,16 @@
   QMutexLocker Locker(Mutex);
 
-  // If already subscribed to service, increase usage count
-  for (int i=0; i<ServiceList.size(); i++) if (ServiceList[i].Name == Name) {
-	ServiceList[i].Count++;
-	// If service already received, reemit for new subscriber
-	if (!ServiceList[i].ByteArray.isEmpty()) {
-	  YEP(Name, ServiceList[i].TimeStamp, ServiceList[i].ByteArray, ServiceList[i].Format, ServiceList[i].Text);
-	}
-	else YEP(Name, -1);
+  // If already subscribed to service, increase usage count and reemit data for new subscriber
+  if (ServiceList.contains(Name)) {
+	ServiceList[Name].Count++;
+	YEP(Name, ServiceList[Name].TimeStamp, ServiceList[Name].ByteArray, ServiceList[Name].Format, ServiceList[Name].Text);
 	return;
   }
 
   // Create new entry in service list
-  struct Item New;
-  New.Name = Name;
-  New.ByteArray = QByteArray();
-  New.Count = 1;
-  New.DIMService = new DimStampedInfo(Name.toAscii().data(), INT_MAX, NO_LINK, this);
-  ServiceList.append(New);
-
+  ServiceList[Name].ByteArray = QByteArray();
+  ServiceList[Name].TimeStamp = -1;
+  ServiceList[Name].Count = 1;
+  ServiceList[Name].DIMService = new DimStampedInfo(Name.toAscii().data(), INT_MAX, NO_LINK, this);
   return;
 }
@@ -855,11 +850,10 @@
   QMutexLocker Locker(Mutex);
 
-  for (int i=0; i<ServiceList.size(); i++) if (ServiceList[i].Name == Name) {
-	ServiceList[i].Count--;
-	if (ServiceList[i].Count == 0) {
-	  delete ServiceList[i].DIMService;
-	  ServiceList.removeAt(i);
-	  return;
-	}
+  if (ServiceList.contains(Name)) ServiceList[Name].Count--;
+
+  if (ServiceList[Name].Count == 0) {
+	delete ServiceList[Name].DIMService;
+	ServiceList.remove(Name);
+	return;
   }
 }
@@ -869,24 +863,22 @@
 
   // History already available (only request again if too old)
-  for (int i=0; i<HistoryList.size(); i++) if (HistoryList[i].Name == Name) {
-	HistoryList[i].Count++;
-	if (time(NULL)-HistoryList[i].LastUpdate < 5) {
-	  HistoryList[i].HistClass->Rewind();
-	  return HistoryList[i].HistClass;
+  if (HistoryList.contains(Name)) {
+	HistoryList[Name].Count++;
+
+	if (time(NULL)-HistoryList[Name].LastUpdate < 5) {
+	  HistoryList[Name].HistClass->Rewind();
+	  return HistoryList[Name].HistClass;
 	}
-	HistoryList[i].LastUpdate = time(NULL);
-	if (HistoryList[i].HistClass->GetHistory()) return HistoryList[i].HistClass;
+	HistoryList[Name].LastUpdate = time(NULL);
+	if (HistoryList[Name].HistClass->GetHistory()) return HistoryList[Name].HistClass;
 	else return NULL;
   }
 
   // Create new history class
-  struct HistItem New;
-  New.Name = Name;
-  New.HistClass = new EvidenceHistory(Name.toStdString());
-  New.Count = 1;
-  New.LastUpdate = time(NULL);
-  HistoryList.append(New);
-
-  if (New.HistClass->GetHistory()) return New.HistClass;
+  HistoryList[Name].HistClass = new EvidenceHistory(Name.toStdString());
+  HistoryList[Name].Count = 1;
+  HistoryList[Name].LastUpdate = time(NULL);
+
+  if (HistoryList[Name].HistClass->GetHistory()) return HistoryList[Name].HistClass;
   else return NULL;
 }
@@ -895,7 +887,5 @@
 void EddDim::DropHistory(QString Name) {
 
-  for (int i=0; i<HistoryList.size(); i++) {
-	if (HistoryList[i].Name == Name) HistoryList[i].Count--;
-  }
+  if (HistoryList.contains(Name)) HistoryList[Name].Count--;
 }
 
@@ -903,22 +893,22 @@
 void EddDim::UpdateStatistics() {
 
-  // Remove unused histories after not less than 5 seconds
-  for (int i=0; i<HistoryList.size(); i++) {
-	if ((HistoryList[i].Count <= 0) && (time(NULL)-HistoryList[i].LastUpdate) > 5) { 
-	  delete HistoryList[i].HistClass;
-	  HistoryList.removeAt(i);
-	}
-  }
-
   // Lock before accessing internal variables
   QMutexLocker Locker(Mutex);
 
+  // Remove unused histories after not less than 5 seconds
+  QList<QString> L = HistoryList.keys();
+  for(int i=0; i<L.size(); i++) {
+	if ((HistoryList[L[i]].Count <= 0) && (time(NULL)-HistoryList[L[i]].LastUpdate) > 5) { 
+	  delete HistoryList[L[i]].HistClass;
+	  HistoryList.remove(L[i]);
+	}
+  }
+  
   float Rate = Volume/1024.0/10;
-
+  Volume = 0;
   YEP("Edd/Rate_kBSec", time(NULL), QByteArray::number(Rate), "F", QString::number(Rate));
-  Volume = 0;
-}
-
-// Store service information for usage by Subscribe() and update statistics
+}
+
+// Store service information for usage by Subscribe(), update statistics and emit signal to widgets
 void EddDim::Update(QString Name, int Time, QByteArray Data, QString Format, QString Text) {
 
@@ -926,18 +916,21 @@
   QMutexLocker Locker(Mutex);
 
-  for (int i=0; i<ServiceList.size(); i++) if (ServiceList[i].Name == Name) {
-	  ServiceList[i].TimeStamp = Time;
-	  ServiceList[i].ByteArray = Data;
-	  ServiceList[i].Format = Format;
-	  ServiceList[i].Text = Text;
-  }
-
-  // Update statistics only for Dim services
+  // Store service data
+  if (ServiceList.contains(Name)) {
+	  ServiceList[Name].TimeStamp = Time;
+	  ServiceList[Name].ByteArray = Data;
+	  ServiceList[Name].Format = Format;
+	  ServiceList[Name].Text = Text;
+  }
+
+  // Update statistics only for actual Dim services
   if (!Name.startsWith("Edd/")) Volume += Data.size();
   
-  YEP(Name, Time, Data, Format, Text);  
+  // Emit signal to all widgets
+  YEP(Name, Time, Data, Format, Text);
 }
 
 // Handling of DIM service update
+// No locking allowed. Signal triggers only EddDim::Update() when the main event loop is idle.
 void EddDim::infoHandler() {
 
@@ -945,5 +938,5 @@
   else {
 	INT(getInfo()->getName(), getInfo()->getTimestamp(), QByteArray((char *) getInfo()->getData(), 
-		getInfo()->getSize()), getInfo()->getFormat(), QString::fromStdString(EvidenceServer::ToString(getInfo())));
+		getInfo()->getSize()), getInfo()->getFormat(), QString::fromStdString(EvidenceServer::ToString(getInfo()->getFormat(), getInfo()->getData(), getInfo()->getSize())));
   }
 }
@@ -1235,5 +1228,5 @@
   EddText *Text = new EddText("Bias/ConsoleOut", true);
   Text->setFixedWidth(400);
-  Layout->addWidget(Text, 11, 0, 4, 4);      
+  Layout->addWidget(Text, 11, 0, 4, 4);
 }
 
@@ -1249,27 +1242,24 @@
   EddPlot *Plot = new EddPlot();
   for (int i=0; i<36; i++) {
-    Line = new EddLineDisplay("drsdaq/Average", i);
+    Line = new EddLineDisplay("Feedback/Average", i);
 	Line->setMaximumWidth(60);
-    Layout->addWidget(Line, i%9+1, 0+i/9, 1, 1);
-    Plot->AddService("drsdaq/Average", i);
+    Layout->addWidget(Line, i%9+2, 0+i/9, 1, 1);
+    Plot->AddService("Feedback/Average", i);
   }
   Layout->addWidget(Plot, 0, 4, 12, 10);
-
-  //Graph = new EddPlot();
-  //for (int i=0; i<36; i++) {
-    //Text = Text.sprintf("Feedback/Sigma/ID%.2d/%.2d-%.3d",i/16, (i%16)/8, i%8);
-    //Graph->AddService(Text);
-  //}
-  //FeedbackLayout->addWidget(Graph, 10, 0, 10, 3);
 
   Line = new EddLineDisplay("drsdaq/Message");
   Line->setMaximumWidth(200);
   Layout->addWidget(Line, 0, 0, 1, 2);      
-  Line = new EddLineDisplay("drsdaq/Count");
+
+  Line = new EddLineDisplay("Feedback/State");
+  Line->setMaximumWidth(150);
+  Layout->addWidget(Line, 1, 0, 1, 2);      
+  Line = new EddLineDisplay("Feedback/Count");
   Line->setMaximumWidth(60);
-  Layout->addWidget(Line, 0, 2);      
+  Layout->addWidget(Line, 1, 2);      
 
   QWidget *Button = new QPushButton("Details");
-  Layout->addWidget(Button, 10, 0, 1, 1);      
+  Layout->addWidget(Button, 12, 0, 1, 1);      
   connect(Button, SIGNAL(pressed()), SLOT(FeedbackDetails()));
 
@@ -1278,18 +1268,31 @@
 void TP_Feedback::FeedbackDetails() {
 
-  setAttribute(Qt::WA_DeleteOnClose);
+  QMainWindow *M = new QMainWindow;
+  M->setCentralWidget(new QWidget);
+  M->setStatusBar(new QStatusBar(M));
+  M->setWindowTitle("Edd - Feedback Details");
+  M->setAttribute(Qt::WA_DeleteOnClose);
+
+  QGridLayout *Layout = new QGridLayout(M->centralWidget());
   EddLineDisplay *Line;
-  QWidget *Widget = new QWidget();
-  QGridLayout *Layout = new QGridLayout(Widget);
   EddPlot *Plot = new EddPlot();
+
   for (int i=0; i<36; i++) {
-    Line = new EddLineDisplay("drsdaq/Sigma", i);
-	Line->setMaximumWidth(50);
-    Layout->addWidget(Line, i%9+1, 0+i/9, 1, 1);
-    Plot->AddService("drsdaq/Sigma", i);
-  }
-  Layout->addWidget(Plot, 0, 4, 12, 10);
-  
-  Widget->show();
+    Line = new EddLineDisplay("Feedback/Sigma", i);
+	Line->setMaximumWidth(60);
+    Layout->addWidget(Line, i%9, 0+i/9, 1, 1);
+    Plot->AddService("Feedback/Sigma", i);
+	
+    Line = new EddLineDisplay("Feedback/Target", i);
+	Line->setMaximumWidth(60);
+    Layout->addWidget(Line, i%9+10, 0+i/9, 1, 1);
+	
+	Line = new EddLineDisplay("Feedback/Response", i);
+	Line->setMaximumWidth(60);
+    Layout->addWidget(Line, i%9+20, 0+i/9, 1, 1);
+  }
+  Layout->addWidget(Plot, 0, 4, 30, 12);
+  
+  M->show();
 }
 
Index: Evidence/Edd/Edd.h
===================================================================
--- Evidence/Edd/Edd.h	(revision 231)
+++ Evidence/Edd/Edd.h	(revision 232)
@@ -36,4 +36,5 @@
 bool SetStatus(QWidget *, QString, int, QString, int = -1);
 
+
 // Base class for Edd plot
 // DeleteCurve() is pure virtual and needs to be implemented iin the application class
@@ -213,5 +214,4 @@
   private:
 	struct Item {
-	  QString Name;
 	  DimStampedInfo *DIMService;
 	  int Count;
@@ -221,14 +221,13 @@
 	  QString Text;
 	};
-    QList<Item> ServiceList;
+    QMap<QString, struct Item> ServiceList;
     QMutex *Mutex;
 
 	struct HistItem {
-	  QString Name;
 	  int Count;
 	  int LastUpdate;
 	  class EvidenceHistory *HistClass;
 	};
-    QList<HistItem> HistoryList;
+    QMap<QString, struct HistItem> HistoryList;
 
 	long long Volume;
