diff --git a/tsg_util/corTsgBias.m b/tsg_util/corTsgBias.m
index 08dc24f23f5ac63ddc34bef91d2891b32437c9fb..f9a37c7fb93171359ba82243de053fbae174f1dd 100644
--- a/tsg_util/corTsgBias.m
+++ b/tsg_util/corTsgBias.m
@@ -113,30 +113,28 @@ if dateMax > dateMin
                 
             end
             
-            defaultValueBias = {num2str(meanDif)};
-            defaultValueError = {num2str(stdDif)};
+            defaultValue = {num2str(meanDif),num2str(stdDif)};
             
         else
             
-            defaultValueBias = {'0'};
-            defaultValueError = {'0'};
-            
+            defaultValue = {'0','0'};
+
         end
         
     else
         
-        defaultValueBias = {'0'};
-        defaultValueError = {'0'};
+        defaultValue = {'0','0'};
         
     end
     
     
     % Enter the bias that will be applied to PARA{1}
     % ----------------------------------------------
-    prompt = ['Constant value to be applied to the ' PARA{1} ' time series'];
-    a = inputdlg(prompt,'Bias Correction',1,defaultValueBias);
-    prompt = ['Error value to be applied to the ' PARA{1} ' time series'];
-    b = inputdlg(prompt,'Bias Error',1,defaultValueError);
+    prompt = {['Constant value to be applied to the ' PARA{1} ' time series:'],...
+        ['Error value to be applied to the ' PARA{1} ' time series:']};
+    answer = inputdlg(prompt,'Bias adjustment',1,defaultValue);
+    a = answer(1);
+    b = answer(2);
     
     % everything OK
     % -------------
diff --git a/tsg_util/tsg_initialisation.m b/tsg_util/tsg_initialisation.m
index aeb96d44c7ec4b28e62df6f14e78f83c75b03ac1..3b4230c87cee61d8a40a619515378d6de22f07a2 100644
--- a/tsg_util/tsg_initialisation.m
+++ b/tsg_util/tsg_initialisation.m
@@ -217,6 +217,13 @@ for key = nca
   tsg.(char(key)) = '';
 end
 
+% set empty stack and parameters for undo/redo
+% --------------------------------------------
+tsg.qc_history_state = [];
+tsg.qc_history_pointer = 0;
+tsg.qc_history_size = 10;
+tsg.qc_redo_possible = 0;
+
 % set some fields
 % ---------------
 tsg.FORMAT_VERSION        =  GOSUD_FORMAT_VERSION;
diff --git a/tsgqc.m b/tsgqc.m
index cf8415999443c011956a9ae8992fce1d97113204..28214c130629e7e05a965d92f184ff466dd15ad9 100644
--- a/tsgqc.m
+++ b/tsgqc.m
@@ -38,9 +38,9 @@ global GOSUD_FORMAT_VERSION
 % version number, may be used to initialize some files when it change
 % 0.90x -> 1.0RCx
 % -------------------------------------------------------------------
-VERSION      = 1.470;  % -> 1.47.0
-CHAR_VERSION = '1.47.0';
-DATE_VERSION = '28/03/2018';
+VERSION      = 1.48;  % -> 1.44
+CHAR_VERSION = '1.48';
+DATE_VERSION = '25/05/2018';
 
 % netcdf file version, see DATA FORMAT TSG document:
 % CORTSG_format_gosud.doc
@@ -184,7 +184,7 @@ end
 % Create and then hide the GUI as it is being constructed.
 % --------------------------------------------------------
 hMainFig = figure(...
-  'Name', 'TSG Validation', ...
+  'Name', strcat('TSG Validation - v', CHAR_VERSION), ...
   'NumberTitle', 'off', ...
   'Resize', 'on', ...
   'Menubar', 'none', ...
@@ -2132,88 +2132,106 @@ hrbInterpCancel = uicontrol( ...
       % is used when the context menu (callback 'Qc') is called
       % -----------------------------------------------------------------
       if ~strcmp( get(gcf, 'SelectionType'), 'alt')
-        
-        % The QC is applied either on TSG data either on Sample data.
-        % it depends if the Botte Toggle button has been cliked on
-        % -----------------------------------------------------------
-        if strcmp( get(hBottleToggletool, 'state'), 'on')
-          
-          % get index on selected zone
-          % --------------------------
-          if ~isempty(tsg.DAYD_EXT)
-            
-            ind = find(tsg.DAYD_EXT > p1(1) &  tsg.DAYD_EXT < p2(1) & ...
-              tsg.EXT_DIF  > p1(2) &  tsg.EXT_DIF  < p2(2));
-            
-            % Keep the information on the indices of the selected zone
-            % --------------------------------------------------------
-            tsg.rbboxind = ind .* ones(size(ind));
-            
-            % Modifiy the QC
-            % --------------
-            tsg.([SAMPLE '_EXT_QC'])(ind) = tsg.qc.active.Code;
-            
-            % Save the modifications
-            % ----------------------
-            setappdata( hMainFig, 'tsg_data', tsg);
-            
-            % plot selected data with selected code
-            % --------------------------------------
-            plot_Correction( hMainFig, hPlotAxes, PARA);
-            
-          end
           
-        else
-          
-          % get index on selected zone
-          % ---------------------------
-          ind = find(tsg.DAYD   > p1(1,1) & tsg.DAYD   < p2(1,1) & ...
-            tsg.(PARA{1}) > p1(1,2) & tsg.(PARA{1}) < p2(1,2));
-          
-          % Keep the information on the indices of the selected zone
-          % --------------------------------------------------------
-          tsg.rbboxind = ind .* ones(size(ind));
-          
-          % Modifiy the QC
-          % --------------
-          tsg.([PARA{1} '_QC'])(ind) = tsg.qc.active.Code;
-          
-          % put last SSPS_QC in queue (Undo/Redo)
-          % -------------------------------------
-          %tsg.queue = push( tsg.queue, tsg.([PARA '_QC']));
-          
-          % store QC in queue object, for undo
-          % ----------------------------------
-          %tsg.queue = push(tsg.queue, tsg.([PARA '_QC']));
-          
-          % Save the modifications
-          % ----------------------
-          setappdata( hMainFig, 'tsg_data', tsg);
-          
-          % Draw plot 1 of the validation figure
-          % ------------------------------------
-          plot_Validation( hMainFig, hPlotAxes, 1, PARA{1} );
+          % The QC is applied either on TSG data either on Sample data.
+          % it depends if the Botte Toggle button has been cliked on
+          % -----------------------------------------------------------
+          if strcmp( get(hBottleToggletool, 'state'), 'on')
+              
+              % get index on selected zone
+              % --------------------------
+              if ~isempty(tsg.DAYD_EXT)
+                  
+                  ind = find(tsg.DAYD_EXT > p1(1) &  tsg.DAYD_EXT < p2(1) & ...
+                      tsg.EXT_DIF  > p1(2) &  tsg.EXT_DIF  < p2(2));
+                  
+                  % Keep the information on the indices of the selected zone
+                  % --------------------------------------------------------
+                  tsg.rbboxind = ind .* ones(size(ind));
+                  
+                  % Modifiy the QC
+                  % --------------
+                  tsg.([SAMPLE '_EXT_QC'])(ind) = tsg.qc.active.Code;
+                  
+                  % Save the modifications
+                  % ----------------------
+                  setappdata( hMainFig, 'tsg_data', tsg);
+                  
+                  % plot selected data with selected code
+                  % --------------------------------------
+                  plot_Correction( hMainFig, hPlotAxes, PARA);
+                  
+              end
+              
+          else
+              
+              % store last QC in history for undo
+              % ---------------------------------
+              
+              if (tsg.qc_history_pointer == 0)
+                  tsg.qc_history_state = int8(zeros(size(tsg.([PARA{1} '_QC']),1),tsg.qc_history_size));
+              end
+              
+              if (tsg.qc_history_pointer == tsg.qc_history_size)
+                  tsg.qc_history_state = circshift(tsg.qc_history_state,[0 -1]);
+              else
+                  tsg.qc_history_pointer = tsg.qc_history_pointer + 1;
+              end
+              
+              tsg.qc_history_state(:,tsg.qc_history_pointer) = tsg.([PARA{1} '_QC']);
+              tsg.qc_redo_possible = 0;
+                        
+              
+              % get index on selected zone
+              % ---------------------------
+              ind = find(tsg.DAYD   > p1(1,1) & tsg.DAYD   < p2(1,1) & ...
+                  tsg.(PARA{1}) > p1(1,2) & tsg.(PARA{1}) < p2(1,2));
+              
+              % Keep the information on the indices of the selected zone
+              % --------------------------------------------------------
+              tsg.rbboxind = ind .* ones(size(ind));
+              
+              % Modify the QC
+              % --------------
+              tsg.([PARA{1} '_QC'])(ind) = tsg.qc.active.Code;
+              
+              % Save the modifications
+              % ----------------------
+              setappdata( hMainFig, 'tsg_data', tsg);
+              
+              % Draw plot 1 of the validation figure
+              % ------------------------------------
+              plot_Validation( hMainFig, hPlotAxes, 1, PARA{1} );
+              
+              % refresh QC statistic panel
+              % --------------------------
+              display_QC( hMainFig );
+              
+              % Update the map if already displayed
+              % -----------------------------------
+              if strcmp( get(hMapFig,'visible'), 'on') == 1
+                  erase_Line( hPlotAxes, 4 );
+                  plot_map( hMainFig, hPlotAxes);
+              end
+              
+              % enable Undo menu if QC flags applied
+              % ------------------------------------
+              if (tsg.qc_history_pointer > 0)
+                  set(findobj('tag','UIMENU_UNDO'),'enable','on');
+              end
           
-          % refresh QC statistic panel
-          % --------------------------
-          display_QC( hMainFig );
+              % enable Redo menu if QC flags applied
+              % ------------------------------------
+              if (tsg.qc_history_pointer > 0)
+                  set(findobj('tag','UIMENU_REDO'),'enable','on');
+              end
           
-          % Update the map if already displayed
-          % -----------------------------------
-          if strcmp( get(hMapFig,'visible'), 'on') == 1
-            erase_Line( hPlotAxes, 4 );
-            plot_map( hMainFig, hPlotAxes);
           end
           
-          % enable undo menu
-          % ----------------
-          set(findobj('tag','UIMENU_UNDO'),'enable','on');
-        end
-        
-        % As soon as a modification took place the data should be saved
-        % -------------------------------------------------------------
-        set( hSaveMenu, 'UserData', 'on' );
-        
+          % As soon as a modification took place the data should be saved
+          % -------------------------------------------------------------
+          set( hSaveMenu, 'UserData', 'on' );
+          
       end
       
       % enable ButtonMotion on main fig after select QC area
@@ -2221,6 +2239,7 @@ hrbInterpCancel = uicontrol( ...
       set( hMainFig, 'WindowButtonMotionFcn', @MouseMotion);
       
     end
+    
   end
 
 %% QC_OffMenuCallback .............................. Quality Control Module
@@ -2302,7 +2321,7 @@ hrbInterpCancel = uicontrol( ...
     % ------------------------------------------
     if isfield(tsg, 'rbboxind') && ~isempty( tsg.rbboxind )
       
-      if strcmp( get(hBottleToggletool, 'state'), 'on')
+     if strcmp( get(hBottleToggletool, 'state'), 'on')
         
         tsg.([SAMPLE '_EXT_QC'])(tsg.rbboxind) = tsg.qc.active.Code;
         
@@ -2315,9 +2334,29 @@ hrbInterpCancel = uicontrol( ...
         % -----------------------------------------
         plot_Correction( hMainFig, hPlotAxes, PARA );
         
-      else
-        tsg.([PARA{1} '_QC'])(tsg.rbboxind) = tsg.qc.active.Code;
-        
+     else
+         
+         % store last QC in history for undo
+         % ---------------------------------
+
+         if (tsg.qc_history_pointer == 0)
+             tsg.qc_history_state = int8(zeros(size(tsg.([PARA{1} '_QC']),1),tsg.qc_history_size));
+         end
+         
+         if (tsg.qc_history_pointer == tsg.qc_history_size)
+             tsg.qc_history_state = circshift(tsg.qc_history_state,[0 -1]);
+         else
+             tsg.qc_history_pointer = tsg.qc_history_pointer + 1;
+         end
+         
+         tsg.qc_history_state(:,tsg.qc_history_pointer) = tsg.([PARA{1} '_QC']);
+         tsg.qc_redo_possible = 0;
+         
+         
+         % Modify the QC
+         % --------------
+         tsg.([PARA{1} '_QC'])(tsg.rbboxind) = tsg.qc.active.Code;
+         
         % Save tsg.SSPS_QC in the application data before use
         % inside plot_Validation
         % ---------------------------------------------------
@@ -3629,31 +3668,112 @@ hrbInterpCancel = uicontrol( ...
 % -----------------------------------------------------------------------
 % Callback function run when the Edit/Undo menu item is selected (Ctrl+Z)
 % -----------------------------------------------------------------------
-  function UndoMenuCallback(hObject, eventdata)
-    
-    % Undo module not yet implemented
-    % -------------------------------
-     msgbox('Undo module not yet implemented', 'modal');
-    
-    %tsg.queue = undo(tsg.queue);
-    %tsg.SSPS_QC = get(tsg.queue);
-    
-    % Make the Salinity, temperature and velocity plot
-    % ------------------------------------------------
-    %plot_SalTempVel( hMainFig, hPlotAxes );
-    
-  end
-
+    function UndoMenuCallback(hObject, eventdata)
+        
+        if (tsg.qc_history_pointer > 0)
+            
+            % Get the parameter (SSPS, SSJT or SSTP)
+            % --------------------------------------
+            PARA = getParaCorModule( hMainFig );
+            
+            if (tsg.qc_history_pointer == tsg.qc_history_size)
+                tsg.qc_history_state = circshift(tsg.qc_history_state,[0 -1]);
+                tsg.qc_history_pointer = tsg.qc_history_pointer - 1;
+            end
+            
+            % Back to previous QC flags
+            % -------------------------
+            tsg.qc_history_state(:,tsg.qc_history_pointer+1) = tsg.([PARA{1} '_QC']);
+            tsg.([PARA{1} '_QC']) = tsg.qc_history_state(:,tsg.qc_history_pointer);
+            tsg.qc_history_pointer = tsg.qc_history_pointer - 1;
+            
+            % Allow redo
+            % ----------
+            tsg.qc_redo_possible = tsg.qc_redo_possible + 1;
+            
+            % Save the modifications
+            % ----------------------
+            setappdata( hMainFig, 'tsg_data', tsg);
+            
+            % Draw plot 1 of the validation figure
+            % ------------------------------------
+            plot_Validation( hMainFig, hPlotAxes, 1, PARA{1} );
+            
+            % refresh QC statistic panel
+            % --------------------------
+            display_QC( hMainFig );
+            
+            % Update the map if already displayed
+            % -----------------------------------
+            if strcmp( get(hMapFig,'visible'), 'on') == 1
+                erase_Line( hPlotAxes, 4 );
+                plot_map( hMainFig, hPlotAxes);
+            end
+            
+            % As soon as a modification took place the data should be saved
+            % -------------------------------------------------------------
+            set( hSaveMenu, 'UserData', 'on' );
+            
+        else
+            
+            msgbox('Undo not possible', 'modal');
+            
+        end
+        
+    end
+        
+        
 %% RedoMenuCallback
 % -----------------------------------------------------------------------
 % Callback function run when the Edit/Redo menu item is selected (Ctrl+R)
 % -----------------------------------------------------------------------
   function RedoMenuCallback(hObject, eventdata)
     
-    % Redo module not yet implemented
-    % -------------------------------
-    msgbox('Redo module not yet implemented', 'modal');
-    
+        if (tsg.qc_redo_possible >0)
+            
+            % Get the parameter (SSPS, SSJT or SSTP)
+            % --------------------------------------
+            PARA = getParaCorModule( hMainFig );
+            
+            % Forward to undone QC flags
+            % --------------------------
+            tsg.qc_history_pointer = tsg.qc_history_pointer + 1;
+            tsg.([PARA{1} '_QC']) = tsg.qc_history_state(:,tsg.qc_history_pointer+1);
+            
+            % Reduce number of possible redo
+            % ------------------------------
+            tsg.qc_redo_possible = tsg.qc_redo_possible-1;
+            
+            % Save the modifications
+            % ----------------------
+            setappdata( hMainFig, 'tsg_data', tsg);
+            
+            % Draw plot 1 of the validation figure
+            % ------------------------------------
+            plot_Validation( hMainFig, hPlotAxes, 1, PARA{1} );
+            
+            % refresh QC statistic panel
+            % --------------------------
+            display_QC( hMainFig );
+            
+            % Update the map if already displayed
+            % -----------------------------------
+            if strcmp( get(hMapFig,'visible'), 'on') == 1
+                erase_Line( hPlotAxes, 4 );
+                plot_map( hMainFig, hPlotAxes);
+            end
+            
+            % As soon as a modification took place the data should be saved
+            % -------------------------------------------------------------
+            set( hSaveMenu, 'UserData', 'on' );
+            
+        else
+            
+            msgbox('Redo not possible', 'modal');
+            
+        end
+        
+   
   end
 
 %% KeyPressFcnCallback