import re


def solve_status_str(hdrlbl, fmtmap=None, fwdth0=4, fwdthdlt=6,
                     fprec=2):
    """Construct header and format details for status display of an
    iterative solver.

    Parameters
    ----------
    hdrlbl : tuple of strings
      Tuple of field header strings
    fmtmap : dict or None, optional (default None)
      A dict providing a mapping from field header strings to print
      format strings, providing a mechanism for fields with print
      formats that depart from the standard format
    fwdth0 : int, optional (default 4)
      Number of characters in first field formatted for integers
    fwdthdlt : int, optional (default 6)
      The width of fields formatted for floats is the sum of the value
      of this parameter and the field precision
    fprec : int, optional (default 2)
      Precision of fields formatted for floats

    Returns
    -------
    hdrstr : string
      Complete header string
    fmtstr : string
      Complete print formatting string for numeric values
    nsep : integer
      Number of characters in separator string
    """

    if fmtmap is None:
        fmtmap = {}
    fwdthn = fprec + fwdthdlt

    # Construct a list specifying the format string for each field.
    # Use format string from fmtmap if specified, otherwise use
    # a %d specifier with field width fwdth0 for the first field,
    # or a %e specifier with field width fwdthn and precision
    # fprec
    fldfmt = [fmtmap[lbl] if lbl in fmtmap else
              (('%%%dd' % (fwdth0)) if idx == 0 else
               (('%%%d.%de' % (fwdthn, fprec))))
              for idx, lbl in enumerate(hdrlbl)]
    fmtstr = ('  ').join(fldfmt)

    # Construct a list of field widths for each field by extracting
    # field widths from field format strings
    cre = re.compile(r'%-?(\d+)')
    fldwid = []
    for fmt in fldfmt:
        mtch = cre.match(fmt)
        if mtch is None:
            raise ValueError("Format string '%s' does not contain field "
                             "width" % fmt)
        else:
            fldwid.append(int(mtch.group(1)))

    # Construct list of field header strings formatted to the
    # appropriate field width, and join to construct a combined field
    # header string
    hdrlst = [('%-*s' % (w, t)) for t, w in zip(hdrlbl, fldwid)]
    hdrstr = ('  ').join(hdrlst)

    return hdrstr, fmtstr, len(hdrstr)