Index: /readTracFiles_mod.f90
===================================================================
--- /readTracFiles_mod.f90	(revision 19)
+++ /readTracFiles_mod.f90	(revision 20)
@@ -21,4 +21,5 @@
 
   PUBLIC :: tran0, idxAncestor, ancestor                             !--- GENERATION 0 TRACER + TOOLS FOR GENERATIONS
+  PUBLIC :: maxTableWidth
 !------------------------------------------------------------------------------------------------------------------------------
   TYPE :: dataBase_type                                              !=== TYPE FOR TRACERS SECTION
@@ -59,9 +60,9 @@
   CHARACTER(LEN=maxlen), SAVE :: newH2OIso(5) = ['H2[16]O', 'H[2]HO ', 'H2[18]O', 'H2[17]O', 'H[3]HO ']
 
-
   !=== LOCAL COPIES OF THE TRACERS AND ISOTOPES DESCRIPTORS, USED BY getKey (INITIALIZED IN getKey_init)
   TYPE(trac_type), ALLOCATABLE, TARGET, SAVE ::  tracers(:)
   TYPE(isot_type), ALLOCATABLE, TARGET, SAVE :: isotopes(:)
 
+  INTEGER,    PARAMETER :: maxTableWidth = 192                       !--- Maximum width of a table displayed with "dispTable"
   CHARACTER(LEN=maxlen) :: modname
 
@@ -267,5 +268,5 @@
   TYPE(trac_type),       ALLOCATABLE :: tt(:)
   TYPE(trac_type)       :: tmp
-  CHARACTER(LEN=1024)   :: str
+  CHARACTER(LEN=1024)   :: str, str2
   CHARACTER(LEN=maxlen) :: secn
   INTEGER               :: ierr, n
@@ -273,5 +274,13 @@
   IF(.NOT.ALLOCATED(dBase)) ALLOCATE(dBase(0))
   OPEN(90, FILE=fnam, FORM='formatted', STATUS='old')
-  DO; READ(90,'(a)', IOSTAT=ierr)str
+  DO; str=''
+    DO
+      READ(90,'(a)', IOSTAT=ierr)str2                                !--- Read a full line
+      str=TRIM(str)//' '//TRIM(str2)                                 !--- Append "str" with the current line
+      n=LEN_TRIM(str); IF(n == 0) EXIT                               !--- Empty line (probably end of file)
+      IF(IACHAR(str(n:n))  /= 92) EXIT                               !--- No "\" continuing line symbol found => end of line
+      str = str(1:n-1)                                               !--- Remove the "\" continuing line symbol
+    END DO
+    str = ADJUSTL(str)                                               !--- Remove the front space
     IF(ierr    /= 0 ) EXIT                                           !--- Finished: error or end of file
     IF(str(1:1)=='#') CYCLE                                          !--- Skip comments lines
@@ -777,10 +786,10 @@
   phas =         [(fgetKey(iq, 'phases',tm(:)%keys, 'g' ), iq=1, nq)]
   CALL msg(TRIM(message)//':', modname)
-  IF(tm(1)%parent == '') THEN
-    IF(test(dispTable('iiiss',   ['iq    ','hadv  ','vadv  ','name  ','phase '], cat(tm%name, phas), cat([(iq, iq=1, nq)], &
-                                            hadv,    vadv),                 sub=modname), lerr)) RETURN
+  IF(ALL(tm(:)%parent == '')) THEN
+    IF(test(dispTable('iiiss',   ['iq    ','hadv  ','vadv  ','name  ','phase '], cat(tm%name, phas), &
+                 cat([(iq, iq=1, nq)], hadv, vadv),                 nColMax=maxTableWidth, nHead=2, sub=modname), lerr)) RETURN
   ELSE
     IF(test(dispTable('iiissis', ['iq    ','hadv  ','vadv  ','name  ','parent','igen  ','phase '], cat(tm%name, tm%parent, &
-           tm%phase), cat([(iq, iq=1, nq)], hadv,    vadv, tm%iGeneration), sub=modname), lerr)) RETURN
+      tm%phase), cat([(iq, iq=1, nq)], hadv, vadv, tm%iGeneration), nColMax=maxTableWidth, nHead=2, sub=modname), lerr)) RETURN
   END IF
 END FUNCTION dispTraSection
@@ -933,5 +942,5 @@
   CALL get_in('ok_iso_verif', isot(strIdx(isot%parent, 'H2O'))%check, .FALSE.)
 
-  lerr = dispIsotopes(isot, 'Isotopes parameters read from file', modname)
+  lerr = dispIsotopes(isot, 'Isotopes parameters read from file "'//TRIM(fnam)//'"', modname)
 
 END FUNCTION readIsotopesFile
@@ -945,5 +954,5 @@
 !===      NOTE: THIS IS DONE HERE (IN A ROUTINE CALLED BY THE DYNAMIC), BECAUSE THE DYNAMIC NEEDS FEW PHYSICAL PARAMETERS.  ===
 !==============================================================================================================================
-SUBROUTINE initIsotopes(trac, isot)
+LOGICAL FUNCTION initIsotopes(trac, isot) RESULT(lerr)
   TYPE(trac_type), ALLOCATABLE, TARGET, INTENT(INOUT) :: trac(:)
   TYPE(isot_type), ALLOCATABLE, TARGET, INTENT(INOUT) :: isot(:)
@@ -955,4 +964,5 @@
   TYPE(trac_type), POINTER   ::  t(:), t1
   TYPE(isot_type), POINTER   ::  i
+  lerr = .FALSE.
 
   t => trac
@@ -1019,7 +1029,7 @@
   !=== READ PHYSICAL PARAMETERS FROM "isotopes_params.def" FILE
   !    DONE HERE, AND NOT ONLY IN "infotrac_phy", BECAUSE SOME PHYSICAL PARAMS ARE NEEDED FOR RESTARTS (tnat AND alpha_ideal)
-  IF(readIsotopesFile('isotopes_params.def',isot)) CALL abort_gcm(modname,'Problem when reading isotopes parameters',1)
-
-END SUBROUTINE initIsotopes
+  lerr = readIsotopesFile('isotopes_params.def',isot)
+
+END FUNCTION initIsotopes
 !==============================================================================================================================
 
@@ -1046,6 +1056,6 @@
       END DO
     END DO
-    IF(test(fmsg('Problem with the table content', modname, dispTable(prf, ttl, val, cat([(it,it=1,nt)]), rFmt='(EN8.4)',     &
-       sub=modname)), lerr)) RETURN
+    IF(test(fmsg('Problem with the table content', modname, dispTable(prf, ttl, val, &
+            cat([(it,it=1,nt)]), rFmt='(EN8.4)', nColMax=maxTableWidth, nHead=2, sub=modname)), lerr)) RETURN
     DEALLOCATE(ttl, val)
   END DO        
Index: /strings_mod.F90
===================================================================
--- /strings_mod.F90	(revision 19)
+++ /strings_mod.F90	(revision 20)
@@ -853,6 +853,9 @@
 !--- Display a clean table composed of successive vectors of same length.
 !=== The profile "p" describe in which order to pick up the columns from "s", "i" and "r" for display.
-!==============================================================================================================================
-LOGICAL FUNCTION dispTable(p, titles, s, i, r, rFmt, nmax, unit, sub) RESULT(lerr)
+!===  * nRowMax lines are displayed (default: all lines)
+!===  * nColMax characters (default: as long as needed) are displayed at most on a line. If the effective total length is
+!===    higher, several partial tables are displayed ; the nHead (default: 1) first columns are included in each sub-table.
+!==============================================================================================================================
+LOGICAL FUNCTION dispTable(p, titles, s, i, r, rFmt, nRowMax, nColMax, nHead, unit, sub) RESULT(lerr)
   CHARACTER(LEN=*),           INTENT(IN)  :: p             !--- DISPLAY MAP: s/i/r
   CHARACTER(LEN=*),           INTENT(IN)  :: titles(:)     !--- TITLES (ONE EACH COLUMN)
@@ -861,5 +864,7 @@
   REAL,             OPTIONAL, INTENT(IN)  :: r(:,:)        !--- REALS
   CHARACTER(LEN=*), OPTIONAL, INTENT(IN)  :: rFmt          !--- Format for reals
-  INTEGER,          OPTIONAL, INTENT(IN)  :: nmax          !--- Display less than "nrow" rows
+  INTEGER,          OPTIONAL, INTENT(IN)  :: nRowMax       !--- Display at most "nRowMax" rows
+  INTEGER,          OPTIONAL, INTENT(IN)  :: nColMax       !--- Display at most "nColMax" characters each line
+  INTEGER,          OPTIONAL, INTENT(IN)  :: nHead         !--- Head columns repeated for multiple tables display
   INTEGER,          OPTIONAL, INTENT(IN)  :: unit          !--- Output unit (default: screen)
   CHARACTER(LEN=*), OPTIONAL, INTENT(IN)  :: sub           !--- Subroutine name
@@ -869,8 +874,8 @@
   CHARACTER(LEN=maxlen), ALLOCATABLE :: d(:,:)
   CHARACTER(LEN=1) :: s1, sp
-  INTEGER :: is, ii, ir, np, nrow, unt, ic
-  INTEGER :: ns, ni, nr, ncol, nmx
-  INTEGER, ALLOCATABLE :: n(:)
-  INTEGER, PARAMETER   :: nm=2                             !--- Space between values & columns
+  INTEGER :: is, ii, ir, it, k, nmx,  unt, ic, np
+  INTEGER :: ns, ni, nr, nt, l, ncol, nHd, ib, l0
+  INTEGER, ALLOCATABLE :: n(:), ncmx(:)
+  INTEGER, PARAMETER   :: nm=1                             !--- Space between values & columns
   LOGICAL :: ls, li, lr
 
@@ -884,5 +889,5 @@
 
   !--- CHECK ARGUMENTS COHERENCE
-  lerr = np /= SIZE(titles); IF(fmsg('string "pattern" length and titles list mismatch', subn, lerr)) RETURN
+  lerr = np /= SIZE(titles); IF(fmsg('display map "p" length and titles list mismatch', subn, lerr)) RETURN
   IF(ls) THEN
     ns = SIZE(s, 1); ncol = ncol + SIZE(s, 2); lerr = COUNT([(p(ic:ic)=='s', ic=1, np)]) /= SIZE(s, 2)
@@ -894,14 +899,13 @@
     nr = SIZE(r, 1); ncol = ncol + SIZE(r, 2); lerr = COUNT([(p(ic:ic)=='r', ic=1, np)]) /= SIZE(r, 2)
   END IF
-  IF(fmsg('string "pattern" length and arguments number mismatch', subn, lerr)) RETURN
+  IF(fmsg('display map "p" length and arguments number mismatch', subn, lerr)) RETURN
   lerr = ncol /= SIZE(titles); IF(fmsg('"titles" length and arguments number mismatch', subn, lerr)) RETURN
   lerr = ls.AND.li.AND.ns/=ni; IF(fmsg('string and integer arguments lengths mismatch', subn, lerr)) RETURN
   lerr = ls.AND.lr.AND.ns/=nr; IF(fmsg(   'string and real arguments lengths mismatch', subn, lerr)) RETURN
   lerr = li.AND.lr.AND.ni/=nr; IF(fmsg(  'integer and real arguments lengths mismatch', subn, lerr)) RETURN
-  nrow = MAX(ns,ni,nr)+1
-  nmx = nrow; IF(PRESENT(nmax)) nmx = MIN(nmx,nmax+1)
+  nmx = MAX(ns,ni,nr)+1; IF(PRESENT(nRowMax)) nmx = MIN(nmx,nRowMax+1)
 
   !--- Allocate the assembled quantities array
-  ALLOCATE(d(nrow,ncol), n(ncol))
+  ALLOCATE(d(nmx,ncol), n(ncol))
 
   !--- Assemble the vectors into a strings array in the order indicated by "pattern"
@@ -914,19 +918,46 @@
       CASE('r'); d(2:nmx,ic) = real2str(r(:,ir),rFm); ir = ir + 1
     END SELECT
+  END DO
+  CALL cleanZeros(d)
+  DO ic = 1, ncol
     n(ic)=0; DO ir=1, nmx; n(ic)=MAX(n(ic), LEN_TRIM(d(ir,ic))); END DO
   END DO
   n(:) = n(:) + 2*nm
 
+  !--- Build the vector of max column index in case the rows are too long (table must be displayed in multiple parts)
+  nHd = 1; IF(PRESENT(nHead)) nHd = nHead
+  IF(.NOT.PRESENT(nColMax)) THEN
+    nt = 1; ncmx = [ncol]
+  ELSE
+    nt = 1; l0 = SUM(n(1:nHd)+1)+1
+    IF(PRESENT(sub)) l0=l0+LEN_TRIM(subn)+1
+    !--- Count the number of table parts
+    l = l0; DO ic = nHd+1, ncol; l = l+n(ic)+1; IF(l>=nColMax) THEN; nt = nt+1; l = l0+n(ic)+1; END IF; END DO
+    !--- Get the index of the last column for each table part
+    ALLOCATE(ncmx(nt)); k = 1
+    l = l0; DO ic = nHd+1, ncol; l = l+n(ic)+1; IF(l>=nColMax) THEN; ncmx(k) = ic-1; l = l0+n(ic)+1; k = k+1; END IF; END DO
+    ncmx(nt) = ncol
+  END IF
+      
   !--- Display the strings array as a table
-  DO ir = 1, nmx; row = ''
-    DO ic = 1, ncol; el = d(ir,ic)
-      s1 = sp
-      row = TRIM(row)//REPEAT(' ',nm)//TRIM(el)//REPEAT(' ',n(ic)-LEN_TRIM(el)-nm)//s1
+  DO it = 1, nt
+    DO ir = 1, nmx; row = ''
+      DO ic = 1, nHd; el = d(ir,ic)
+        s1 = sp
+        row = TRIM(row)//REPEAT(' ',nm)//TRIM(el)//REPEAT(' ',n(ic)-LEN_TRIM(el)-nm)//s1
+      END DO
+      ib = nHd+1; IF(it>1) ib = ncmx(it-1)+1
+      DO ic = ib, ncmx(it); el = d(ir,ic)
+        s1 = sp
+        row = TRIM(row)//REPEAT(' ',nm)//TRIM(el)//REPEAT(' ',n(ic)-LEN_TRIM(el)-nm)//s1
+      END DO
+      nr = LEN_TRIM(row)-1                                           !--- Final separator removed
+      CALL msg(row(1:nr), subn, unit=unt)
+      IF(ir /= 1) CYCLE                                              !--- Titles are underlined
+      row=''; DO ic=1,nHd; row=TRIM(row)//REPEAT('-',n(ic))//'+'; END DO
+      DO ic = ib,ncmx(it); row=TRIM(row)//REPEAT('-',n(ic))//'+'; END DO
+      CALL msg(row(1:LEN_TRIM(row)-1), subn, unit=unt)
     END DO
-    nr = LEN_TRIM(row)-1                                             !--- Final separator removed
-    CALL msg(row(1:nr), subn, unit=unt)
-    IF(ir /= 1) CYCLE                                                !--- Titles are underlined
-    row=''; DO ic=1,ncol; row=TRIM(row)//REPEAT('-',n(ic))//'+'; END DO
-    CALL msg(row(1:LEN_TRIM(row)-1), subn, unit=unt)
+    CALL msg('', subn, unit=unt)
   END DO
 
@@ -970,5 +1001,5 @@
     lerr = COUNT([(p(ic:ic)=='r', ic=1, np)]) /= SIZE(r, DIM=2)
   END IF
-  IF(fmsg('string "pattern" length and arguments number mismatch', ll=lerr)) RETURN
+  IF(fmsg('display map "p" length and arguments number mismatch', ll=lerr)) RETURN
   lerr = ncol /= SIZE(titles); IF(fmsg('"titles" length and arguments number mismatch', ll=lerr)) RETURN
   lerr = ls.AND.li.AND.ns/=ni; IF(fmsg('string and integer arguments lengths mismatch', ll=lerr)) RETURN
@@ -989,4 +1020,7 @@
       CASE('r'); d(2:nrow,ic) = real2str(r(:,ir),rFm); ir = ir + 1
     END SELECT
+  END DO
+  CALL cleanZeros(d)
+  DO ic = 1, ncol
     n(ic) = 0; DO ir=1, nrow; n(ic)=MAX(n(ic), LEN_TRIM(d(ir,ic))); END DO
     IF(needQuotes(d(2,ic)) .AND. ic/=1) n(ic) = n(ic) + 2 !--- For quotes, using second line only
@@ -1016,5 +1050,5 @@
 
 !==============================================================================================================================
-LOGICAL FUNCTION dispOutliers_1(ll, a, n, err_msg, nam, subn, nmax, unit) RESULT(lerr)
+LOGICAL FUNCTION dispOutliers_1(ll, a, n, err_msg, nam, subn, nRowmax, nColMax, nHead, unit) RESULT(lerr)
 ! Display outliers list in tables
 ! If "nam" is supplied, it means the last index is for tracers => one table each tracer for rank > 2.
@@ -1024,9 +1058,12 @@
 
   CHARACTER(LEN=*), OPTIONAL, INTENT(IN)  :: err_msg, nam(:), subn   !--- Error message, variables and calling subroutine names
-  INTEGER,          OPTIONAL, INTENT(IN)  :: nmax, unit              !--- Maximum number of lines to display (default: all)
+  INTEGER,          OPTIONAL, INTENT(IN)  :: nRowMax                 !--- Maximum number of lines to display    (default: all)
+  INTEGER,          OPTIONAL, INTENT(IN)  :: nColMax                 !--- Maximum number of characters per line (default: 2048)
+  INTEGER,          OPTIONAL, INTENT(IN)  :: nHead                   !--- Number of front columns to duplicate  (default: 1)
+  INTEGER,          OPTIONAL, INTENT(IN)  :: unit                    !--- Output unit                           (def: lunout)
   CHARACTER(LEN=maxlen),      ALLOCATABLE :: ttl(:)
   LOGICAL,                    ALLOCATABLE :: m(:)
   INTEGER,                    ALLOCATABLE :: ki(:), kj(:)
-  INTEGER                                 :: i, j, k, rk, rk1, ib, ie, itr, nm, unt, nmx, nv
+  INTEGER                                 :: i, j, k, rk, rk1, ib, ie, itr, nm, unt, nRmx, nCmx, nHd, nv
   CHARACTER(LEN=maxlen)                   :: mes, sub, fm='(f12.9)', v, s
   CHARACTER(LEN=maxlen),      ALLOCATABLE :: vnm(:)
@@ -1037,5 +1074,7 @@
   vnm = ['a'];            IF(PRESENT(nam ))    vnm = nam             !--- Variables names
   sub = 'dispOutliers';   IF(PRESENT(subn))    sub = subn            !--- Calling subroutine name
-  nmx = SIZE(a);          IF(PRESENT(nmax))    nmx = MIN(nmx,nmax)   !--- Maximum number of lines to print
+  nRmx= SIZE(a);          IF(PRESENT(nRowMax)) nRmx=MIN(nRmx,nRowMax)!-- Maximum number of lines to print
+  nCmx= 2048;             IF(PRESENT(nColMax)) nCmx=MIN(nCmx,nColMax)!-- Maximum number of characters each line
+  nHd = 1;                IF(PRESENT(nHead))   nHd = nHead           !--- Number of front columns to duplicate
   unt = lunout;           IF(PRESENT(unit))    unt = unit            !--- Unit to print messages
 
@@ -1061,6 +1100,8 @@
   IF(rk==1) THEN
     ALLOCATE(ttl(2)); ttl(2) = TRIM(vnm(1))//'(i)'; ttl(1) = 'i'
-    IF(nv == 1) lerr = dispTable('sr', ttl,               s=cat(PACK(nam,ll)), r=cat(PACK(a,ll)), rFmt=fm, nmax=nmax)
-    IF(nv /= 1) lerr = dispTable('ir', ['name ','value'], i=cat(PACK(ki,m)),   r=cat(PACK(a,ll)), rFmt=fm, nmax=nmax)
+    IF(nv == 1) lerr = dispTable('sr', ttl,               s=cat(PACK(nam,ll)), r=cat(PACK(a,ll)), &
+                                 rFmt=fm, nRowMax=nRmx, nColMax=nCmx, nHead=nHd, unit=unt, sub=sub)
+    IF(nv /= 1) lerr = dispTable('ir', ['name ','value'], i=cat(PACK(ki,m)),   r=cat(PACK(a,ll)), &
+                                 rFmt=fm, nRowMax=nRmx, nColMax=nCmx, nHead=nHd, unit=unt, sub=sub)
     CALL msg("can't display outliers table", sub, lerr, unt)
     RETURN
@@ -1078,6 +1119,8 @@
     IF(nv == 1) ttl(rk) = TRIM(v)//','//int2str(itr)//')'            !--- "<name>(i,j,itr)" (single name)
     IF(nv /= 1) ttl(rk) = TRIM(v)//')'                               !--- "<nam(itr)>(i,j)" (one name each table/itr index)
-    IF(rk==2) lerr = dispTable('ir',  ttl, i=cat(PACK(ki,m)),            r=cat(PACK(a(ib:ie),m)), rFmt=fm, nmax=nmax)
-    IF(rk==3) lerr = dispTable('iir', ttl, i=cat(PACK(ki,m),PACK(kj,m)), r=cat(PACK(a(ib:ie),m)), rFmt=fm, nmax=nmax)
+    IF(rk==2) lerr = dispTable('ir',  ttl, i=cat(PACK(ki,m)),            r=cat(PACK(a(ib:ie),m)), &
+                                 rFmt=fm, nRowMax=nRmx, nColMax=nCmx, nHead=nHd, unit=unt, sub=sub)
+    IF(rk==3) lerr = dispTable('iir', ttl, i=cat(PACK(ki,m),PACK(kj,m)), r=cat(PACK(a(ib:ie),m)), &
+                                 rFmt=fm, nRowMax=nRmx, nColMax=nCmx, nHead=nHd, unit=unt, sub=sub)
     CALL msg("can't display outliers table", sub, lerr, unt)
     IF(lerr) RETURN
@@ -1085,5 +1128,5 @@
 END FUNCTION dispOutliers_1
 !==============================================================================================================================
-LOGICAL FUNCTION dispOutliers_2(ll, a, n, err_msg, nam, subn, nmax, unit) RESULT(lerr)
+LOGICAL FUNCTION dispOutliers_2(ll, a, n, err_msg, nam, subn, nRowMax, nColMax, nHead, unit) RESULT(lerr)
 ! Display outliers list in tables
 ! If "nam" is supplied and, it means the last index is for tracers => one table each tracer for rank > 2.
@@ -1092,5 +1135,8 @@
   INTEGER,                    INTENT(IN)  ::  n(:)                   !--- Profile before linearization
   CHARACTER(LEN=*), OPTIONAL, INTENT(IN)  :: err_msg, nam(:), subn   !--- Error message, variables and calling subroutine names
-  INTEGER,          OPTIONAL, INTENT(IN)  :: nmax, unit              !--- Maximum number of lines to display (default: all)
+  INTEGER,          OPTIONAL, INTENT(IN)  :: nRowMax                 !--- Maximum number of lines to display    (default: all)
+  INTEGER,          OPTIONAL, INTENT(IN)  :: nColMax                 !--- Maximum number of characters per line (default: 2048)
+  INTEGER,          OPTIONAL, INTENT(IN)  :: nHead                   !--- Number of front columns to duplicate  (default: 1)
+  INTEGER,          OPTIONAL, INTENT(IN)  :: unit                    !--- Output unit                           (def: lunout)
 
   CHARACTER(LEN=maxlen)                   :: mes, sub, fm='(f12.9)', prf
@@ -1098,17 +1144,19 @@
   LOGICAL,                    ALLOCATABLE :: m(:)
   INTEGER,                    ALLOCATABLE :: ki(:), kj(:), kl(:)
-  INTEGER                                 :: i, j, k, rk, ib, ie, itr, nm, nv, unt, nmx, rk1
+  INTEGER                                 :: i, j, k, rk, ib, ie, itr, nm, nv, unt, nRmx, nCmx, nHd, rk1
   REAL,                       ALLOCATABLE :: val(:,:)
 
-  lerr = ANY(ll); IF(.NOT.lerr) RETURN                                    !--- No outliers -> finished
+  lerr = ANY(ll); IF(.NOT.lerr) RETURN                               !--- No outliers -> finished
   rk = SIZE(n); nv = SIZE(a,2)
-  mes = 'outliers found';         IF(PRESENT(err_msg)) mes = err_msg      !--- Error message
-  vnm = [(ACHAR(k+96),k=1,nv)];   IF(PRESENT(nam ))    vnm = nam          !--- Variables names
-  sub = 'dispOutliers';           IF(PRESENT(subn))    sub = subn         !--- Calling subroutine name
-  nmx = SIZE(a);                  IF(PRESENT(nmax))    nmx = MIN(nmx,nmax)!--- Maximum number of lines to print
-  unt = lunout;                   IF(PRESENT(unit))    unt = unit         !--- Unit to print messages
-  lerr = SIZE(vnm) /= nv;         IF(fmsg('SIZE(nam) /= SIZE(a,2)',                  sub, lerr, unt)) RETURN
-  lerr = SIZE(a,1) /= SIZE(ll);   IF(fmsg('"ll" and "a" sizes mismatch',             sub, lerr, unt)) RETURN
-  lerr = SIZE(a,1) /= PRODUCT(n); IF(fmsg('profile "n" does not match "a" and "ll"', sub, lerr, unt)) RETURN
+  mes = 'outliers found';        IF(PRESENT(err_msg)) mes = err_msg  !--- Error message
+  vnm = [(ACHAR(k+96),k=1,nv)];  IF(PRESENT(nam ))    vnm = nam      !--- Variables names
+  sub = 'dispOutliers';          IF(PRESENT(subn))    sub = subn     !--- Calling subroutine name
+  nRmx= SIZE(a);          IF(PRESENT(nRowMax)) nRmx=MIN(nRmx,nRowMax)!-- Maximum number of lines to print
+  nCmx= 2048;             IF(PRESENT(nColMax)) nCmx=MIN(nCmx,nColMax)!-- Maximum number of characters each line
+  nHd = 1;                IF(PRESENT(nHead))   nHd = nHead           !--- Number of front columns to duplicate
+  unt = lunout;                  IF(PRESENT(unit))    unt = unit     !--- Unit to print messages
+  lerr= SIZE(vnm) /= nv;         IF(fmsg('SIZE(nam) /= SIZE(a,2)',                  sub, lerr, unt)) RETURN
+  lerr= SIZE(a,1) /= SIZE(ll);   IF(fmsg('"ll" and "a" sizes mismatch',             sub, lerr, unt)) RETURN
+  lerr= SIZE(a,1) /= PRODUCT(n); IF(fmsg('profile "n" does not match "a" and "ll"', sub, lerr, unt)) RETURN
 
   SELECT CASE(rk1)                                                   !--- Indices list
@@ -1124,8 +1172,10 @@
   prf = REPEAT('i',rk)//REPEAT('r',nv)                               !--- Profile
   ALLOCATE(val(COUNT(ll),nv)); DO k=1, nv; val(:,k) = PACK(a(:,k),ll); END DO
-  IF(rk == 1) lerr = dispTable(prf, ttl, i = cat(PACK(ki,ll)),             r = val, rFmt=fm, nmax=nmax)
-  IF(rk == 2) lerr = dispTable(prf, ttl, i = cat(PACK(ki,ll),PACK(kj,ll)), r = val, rFmt=fm, nmax=nmax)
-  IF(rk == 3) lerr = dispTable(prf, ttl, i = cat(PACK(ki,ll),PACK(kj,ll),PACK(kl,ll)), &
-                     r = val, rFmt=fm, nmax=nmax)
+  IF(rk == 1) lerr = dispTable(prf, ttl, i = cat(PACK(ki,ll)),                         r = val, &
+                                 rFmt=fm, nRowMax=nRmx, nColMax=nCmx, nHead=nHd, unit=unt, sub=sub)
+  IF(rk == 2) lerr = dispTable(prf, ttl, i = cat(PACK(ki,ll),PACK(kj,ll)),             r = val, &
+                                 rFmt=fm, nRowMax=nRmx, nColMax=nCmx, nHead=nHd, unit=unt, sub=sub)
+  IF(rk == 3) lerr = dispTable(prf, ttl, i = cat(PACK(ki,ll),PACK(kj,ll),PACK(kl,ll)), r = val, &
+                                 rFmt=fm, nRowMax=nRmx, nColMax=nCmx, nHead=nHd, unit=unt, sub=sub)
   CALL msg("can't display outliers table", sub, lerr, unt)
 END FUNCTION dispOutliers_2
@@ -1320,5 +1370,18 @@
 END FUNCTION dble2str
 !==============================================================================================================================
-
+ELEMENTAL SUBROUTINE cleanZeros(s)
+  CHARACTER(LEN=*), INTENT(INOUT) :: s
+  INTEGER :: ls, ix, i
+  IF(is_numeric(s)) THEN
+    ls = LEN_TRIM(s)
+    ix = MAX(INDEX(s,'E'),INDEX(s,'e'),INDEX(s,'D'),INDEX(s,'d'))
+    IF(ix == 0) THEN
+      DO ix = ls,1,-1; IF(s(ix:ix) /= '0') EXIT; END DO; s=s(1:ix+1)
+    ELSE IF(INDEX(s,'.')/=0) THEN
+      i = ix-1; DO WHILE(s(i:i) == '0'); i = i-1; END DO; s=s(1:i)//s(ix:ls)
+    END IF
+  END IF
+END SUBROUTINE cleanZeros
+!==============================================================================================================================
 
 !==============================================================================================================================
