# HG changeset patch
# User Julien Bect <julien.bect@supelec.fr>
# Date 1378888840 -7200
#      mer. sept. 11 10:40:40 2013 +0200
# Node ID f51171981614d71c897fa16a7a9dbf55bc279cf1
# Parent  a0d73e257b481a9d91d02a497133c52c9a463389
@dataframe/display.m: Fix bug #38397.

* @dataframe/display.m: Fix bug #38397. Rewrite for clarity.

diff -r a0d73e257b48 -r f51171981614 inst/@dataframe/display.m
--- a/inst/@dataframe/display.m	mar. sept. 03 07:50:42 2013 -0400
+++ b/inst/@dataframe/display.m	mer. sept. 11 10:40:40 2013 +0200
@@ -3,6 +3,7 @@
   %# function resu = display(df)
   %# Tries to produce a nicely formatted output of a dataframe.
 
+  %% Copyright (C) 2013 Julien Bect <julien.bect@supelec.fr>
   %% Copyright (C) 2009-2012 Pascal Dupuis <Pascal.Dupuis@uclouvain.be>
   %%
   %% This file is part of Octave.
@@ -22,182 +23,181 @@
   %% License along with Octave; see the file COPYING.  If not,
   %% write to the Free Software Foundation, 51 Franklin Street -
   %% Fifth Floor, Boston, MA 02110-1301, USA.
-  
+
   %#
   %# $Id$
   %#
 
-  %# generate header name
-  dummy = inputname (1);
-  if (isempty (dummy))
-    dummy = "ans";
+  %# header: dataframe name and size --------------------------------------------
+
+  df_name = inputname (1);
+  if (isempty (df_name))
+    head = "ans = dataframe with ";
+  else
+    head = [df_name " = dataframe with "];
   endif
 
-  if (2 == length (df._cnt))
-    head = sprintf ("%s = dataframe with %d rows and %d columns", ...
-                    dummy, df._cnt);
-  else
-    head = sprintf ("%s = dataframe with %d rows and %d columns on %d pages", ...
-                    dummy, df._cnt);
-  endif
+  switch (length (df._cnt))
+    case 2
+      head = [head sprintf("%d rows and %d columns", df._cnt)];
+    case 3
+      head = [head sprintf("%d rows and %d columns on %d pages", df._cnt)];
+    otherwise,
+      error ("Unexpected length for internal field _cnt.");
+  endswitch
 
-  if (~isempty (df._src))
-    for indi = (1:size (df._src, 1))
-      head = strvcat...
-          (head, [repmat("Src: ", size (df._src{indi, 1}, 1), 1)...
-                  df._src{indi, 1}]);
+  %# header: source -------------------------------------------------------------
+
+  if (~ isempty (df._src))
+    for i = (1:size (df._src, 1))
+      src = df._src{i, 1};
+      head = strvcat (head, [repmat("Src: ", size (src, 1), 1) src]);
     endfor
   endif
 
+  %# header: comments -----------------------------------------------------------
+
   if (~isempty (df._cmt))
-    for indi = (1:size(df._cmt, 1))
-      head = strvcat...
-          (head, [repmat("Comment: ", size (df._cmt{indi, 1}, 1), 1)...
-                  df._cmt{indi, 1}]);
+    for i = (1:size(df._cmt, 1))
+      cmt = df._cmt{i, 1};
+      head = strvcat (head, [repmat("Comment: ", size (cmt, 1), 1) cmt]);
     endfor
   endif
-  
-  if (all (df._cnt > 0))  %# stop for empty df
-    dummy = []; vspace = repmat (' ', df._cnt(1), 1);
-    indi = 1; %# the real, unfolded index
-    %# loop over columns where the corresponding _data really exists
-    for indc = (1:min (df._cnt(2), size (df._data, 2))) 
-      %# emit column names and type
-      if (1 == length (df._rep{indc}))
-        dummy{1, 2+indi} = deblank (disp (df._name{2}{indc}));
-        dummy{2, 2+indi} = deblank (df._type{indc});
+
+
+  %# body -----------------------------------------------------------------------
+
+  if any (df._cnt == 0)
+
+    %# empty df
+    resu = '';
+
+  else %# deal with non-empty df
+
+    C = {};
+    vspace = repmat (' ', df._cnt(1), 1);
+    i = 1; %# the real, unfolded index
+
+    %# loop over columns where the corresponding _data really exists ------------
+    for j = (1:min (df._cnt(2), size (df._data, 2)))
+
+      col_name = deblank (disp (df._name{2}{j}));  %# column name
+      col_type = deblank (df._type{j});            %# column type
+      col_rep  = df._rep{j};                       %# nb repetitions
+
+      %# emit column names and type ---------------------------------------------
+      if (1 == length (col_rep))
+        C{1, 2+i} = col_name;
+        C{2, 2+i} = col_type;
       else
         %# append a dot and the third-dimension index to column name
-        tmp_str = [deblank(disp (df._name{2}{indc})) "."];
-        tmp_str = arrayfun (@(x) horzcat (tmp_str, num2str(x)), ...
-                            (1:length (df._rep{indc})), 'UniformOutput', false); 
-        dummy{1, 2+indi} = tmp_str{1};
-        dummy{2, 2+indi} = deblank (df._type{indc});
-        for indk = (2:length (tmp_str))
-          dummy{1, 1+indi+indk} = tmp_str{indk};
-          dummy{2, 1+indi+indk} = dummy{2, 2+indi};
+        for k = (1:length (col_rep))
+          C{1, 1+i+k} = horzcat (col_name, ".", num2str(x));
+          C{2, 1+i+k} = col_type;
         endfor
       endif
-      %# "print" each column
-      switch df._type{indc}
-        case {'char'}
-          indk = 1; while (indk <= size (df._data{indc}, 2))
-            tmp_str = df._data{indc}(:, indk); %#get the whole column
-            indj = cellfun ('isprint', tmp_str, 'UniformOutput', false); 
-            indj = ~cellfun ('all', indj);
-            for indr = (1:length (indj))
-              if (indj(indr)),
-                if (isna (tmp_str{indr})),
-                  tmp_str{indr} = "NA";
+
+      %# "print" the column -----------------------------------------------------
+      switch col_type
+
+        case 'char'
+          k = 1;
+          while (k <= size (df._data{j}, 2))
+            s = df._data{j}(:, k); %#get the whole column
+            for r = 1:length (s)
+              if ~ all (isprint (s{r}))
+                if isna (s{r})
+                  s{r} = "NA";
                 else
-                  if (~ischar (tmp_str{indr}))
-                    tmp_str{indr} = char (tmp_str{indr});
+                  if ~ ischar (s{r})
+                    s{r} = char (s{r});
                   endif
-                  tmp_str{indr} = undo_string_escapes (tmp_str{indr});
+                  s{r} = undo_string_escapes (s{r});
                 endif
               endif
             endfor
             %# keep the whole thing, and add a vertical space
-            dummy{3, 2+indi} = disp (char (tmp_str));
-            dummy{3, 2+indi} = horzcat...
-                (vspace, char (regexp (dummy{3, 2+indi}, '.*', ...
-                                       'match', 'dotexceptnewline')));
-            indi = indi + 1; indk = indk + 1;
+	    s = disp (char (s));
+	    s = char (regexp (s, '.*', 'match', 'dotexceptnewline'));
+            C{3, 2+i} = horzcat (vspace, s);
+            i = i + 1; k = k + 1;
           endwhile
+
         otherwise
           %# keep only one horizontal space per line
-          unfolded = df._data{indc}(:, df._rep{indc});
-          indk = 1; while (indk <= size (unfolded, 2))
-            dummy{3, 2+indi} = disp (unfolded(:, indk));
-            tmp_str = char (regexp (dummy{3, 2+indi}, ...
-                                    '[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?(\s??[-+]\s??[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?i)?', ...
-                                    'match', 'dotexceptnewline'));
-            tmp_str = horzcat...
-                (vspace, char (regexp (dummy{3, 2+indi}, '\S.*', ...
-                                       'match', 'dotexceptnewline')));
-            dummy{3, 2+indi} = tmp_str;
-            indi = indi + 1; indk = indk + 1;
+          unfolded = df._data{j}(:, col_rep);  %# problem ? why 'colrep' here ?
+          k = 1; while (k <= size (unfolded, 2))
+            C{3, 2+i} = disp (unfolded(:, k));
+	    %# TODO: explain why we need such a complicated regexp here (do we ?)
+            s = char (regexp (C{3, 2+i}, ...
+                              '[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?(\s??[-+]\s??[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?i)?', ...
+                              'match', 'dotexceptnewline'));
+	    s = char (regexp (C{3, 2+i}, '\S.*', 'match', 'dotexceptnewline'));
+            C{3, 2+i} = horzcat (vspace, s);
+            i = i + 1; k = k + 1;
           endwhile
+
       endswitch
     endfor
 
-    %# put everything together
+    %# put everything together --------------------------------------------------
+
     vspace = [' '; ' '; vspace];
-    %# second line content
     resu = []; 
+
+    %# second line content (TODO: expand or fix comment)
     if (~isempty (df._ridx))
-      for (ind1 = 1:size (df._ridx, 2))
-        if ((1 == size(df._ridx, 3)) && ...
-              (any (~isna (df._ridx(1:df._cnt(1), ind1)))))
-          dummy{2, 1} = [sprintf("_%d", ind1) ; "Nr"];
-          dummy{3, 1} = disp (df._ridx(1:df._cnt(1), ind1)); 
-          indi = regexp (dummy{3, 1}, '\b.*\b', 'match', 'dotexceptnewline');
-          if (isempty (resu))
-            resu = strjust (char (dummy{2, 1}, indi), 'right');
-          else
-            resu = horzcat(resu, vspace, strjust (char (dummy{2, 1}, indi), ...
-                                                  'right'), vspace);
+      for ind1 = 1:size (df._ridx, 2)
+        for ind2 = 1:size (df._ridx, 3)
+	  ridx = df._ridx(1:df._cnt(1), ind1, ind2);
+          if any (~ isna (ridx))
+            C{2, 1} = [sprintf("_%d.%d", ind1, ind2) ; "Nr"];
+            C{3, 1} = regexp (disp (ridx), '.*', 'match', 'dotexceptnewline');
+	    s = strjust (char (C{2, 1}, C{3, 1}), 'right');
+	    if ~ isempty (resu)
+	      resu = horzcat (resu, vspace);
+	    endif
+            resu = horzcat(resu, s, vspace);   
           endif
-        else 
-          for ind2 = (1:size (df._ridx, 3))
-            if (any (~isna (df._ridx(1:df._cnt(1), ind1, ind2)))),
-              dummy{2, 1} = [sprintf("_%d.%d", ind1, ind2) ; "Nr"];
-              dummy{3, 1} = disp (df._ridx(1:df._cnt(1), ind1, ind2)); 
-              indi = regexp (dummy{3, 1}, '\b.*\b', 'match', 'dotexceptnewline');
-              if (isempty (resu)) 
-                resu = strjust (char (dummy{2, 1}, indi), 'right');
-              else
-                resu = horzcat (resu, vspace, strjust (char(dummy{2, 1}, indi), ...
-                                                       'right'), vspace);
-              endif
-            endif
-          endfor
-        endif
+        endfor
       endfor
     endif
+    
+    %# emit row names -----------------------------------------------------------
 
-    %# emit row names
     if (isempty (df._name{1})),
-      dummy{2, 2} = []; dummy{3, 2} = [];
+      C{2, 2} = [];
+      C{3, 2} = [];
     else
-      dummy{2, 2} = [" ";" "];
-      dummy{3, 2} = df._name{1};
+      C{2, 2} = [" "; " "];
+      C{3, 2} = df._name{1};
     endif
     
-    %# insert a vertical space
-    if (~isempty (dummy{3, 2}))
-      indi = ~cellfun ('isempty', dummy{3, 2});
-      if (any (indi))
-        try
-          resu = horzcat (resu, vspace, strjust (char(dummy{2, 2}, dummy{3, 2}),...
-                                                 'right'));
-        catch
-          disp ('line 172 '); keyboard
-        end_try_catch
+    %# insert a vertical space after row names (if necessary)
+    if ~ isempty (C{3, 2})
+      if any (~ cellfun ('isempty', C{3, 2}))
+        resu = horzcat (resu, vspace, strjust (char(C{2, 2}, C{3, 2}), 'right'));
       endif
     endif
     
-    %# emit each colum
-    for indi = (1:size (dummy, 2) - 2)
-      %# was max(df._cnt(2:end)),
-      try
-        %# avoid this column touching the previous one
-        if (any (cellfun ('size', dummy(1:2, 2+indi), 2) >= ...
-                 size (dummy{3, 2+indi}, 2)))
-          resu = horzcat (resu, vspace);
-        endif
-        resu = horzcat (resu, strjust (char (dummy{:, 2+indi}), 'right'));
-      catch
-        tmp_str = sprintf ("Emitting %d lines, expecting %d", ...
-                           size (dummy{3, 2+indi}, 1), df._cnt(1));
-        keyboard
-        error (tmp_str);
-      end_try_catch
+    %# emit columns -------------------------------------------------------------
+
+    for i = 1:(size (C, 2) - 2)
+      %# avoid this column touching the previous one
+      if (any (cellfun ('size', C(1:2, 2+i), 2) >= size (C{3, 2+i}, 2)))
+        resu = horzcat (resu, vspace);
+      endif
+      nb_emitted = size (C{3, 2+i}, 1);
+      if nb_emitted != df._cnt(1)
+	error ("Emitting %d lines, expecting %d", nb_emitted, df._cnt(1));
+      else
+	resu = horzcat (resu, strjust (char (C{:, 2+i}), 'right'));
+      endif
     endfor
-  else
-    resu = '';
+
   endif
   
-  resu = char (head, resu); disp (resu)
+  resu = char (head, resu);
+  disp (resu);
 
 endfunction
