def GetMolPopoverTag(Mol):
    """Set up a popover window containing any additional information about molecule."""

    if not OptionsInfo["Popover"]:
        return None

    # Set up data label and values...
    AvailableDataLabels = Mol.GetPropNames(includePrivate=False,
                                           includeComputed=False)

    DataContentLines = []
    MaxDataCharWidth = OptionsInfo["PopoverTextWidth"]
    MaxDataDisplayCount = OptionsInfo["PopoverDataCount"]

    DataDisplayCount = 0
    SkippedDataDisplay = False
    for DataLabel in AvailableDataLabels:
        DataDisplayCount += 1
        if DataDisplayCount > MaxDataDisplayCount:
            SkippedDataDisplay = True
            break

        DataValue = "%s" % Mol.GetProp(DataLabel)
        DataValue = DataValue.strip()
        if MiscUtil.IsEmpty(DataValue):
            continue

        # Change any new lines to ;
        if re.search("(\r\n|\r|\n)", DataValue):
            DataValue = re.sub("(\r\n|\r|\n)", "; ", DataValue)

        DataValue = MiscUtil.TruncateText(DataValue, MaxDataCharWidth, "...")
        DataValue = MiscUtil.ReplaceHTMLEntitiesInText(DataValue)

        DataContent = "<b>%s</b>: %s" % (DataLabel, DataValue)
        DataContentLines.append(DataContent)

    if not len(DataContentLines):
        return None

    if SkippedDataDisplay:
        DataContent = "<b>... ... ...</b>"
        DataContentLines.append(DataContent)

        DataContent = "Showing 1 to %s of %s" % (MaxDataDisplayCount,
                                                 len(AvailableDataLabels))
        DataContentLines.append(DataContent)
    else:
        DataContent = "Showing 1 to %s of %s" % (DataDisplayCount,
                                                 len(AvailableDataLabels))
        DataContentLines.append(DataContent)

    DataContent = MiscUtil.JoinWords(DataContentLines, "<br/>")
    PopoverTag = """class="MolPopover" data-toggle="popover" data-html="true" data-trigger="click" data-placement="right" title="<span class='small'><b>Additional Information</b></span>" data-content="<span class='small'>%s</span>" """ % DataContent

    return PopoverTag
def ProcessOptions():
    """Process and validate command line arguments and options"""
    
    MiscUtil.PrintInfo("Processing options...")
    
    # Validate options...
    ValidateOptions()
    
    OptionsInfo["Infile"] = Options["--infile"]
    OptionsInfo["Outfile"] = Options["--outfile"]
    OptionsInfo["Overwrite"] = Options["--overwrite"]
    
    # No need for any RDKit specific --outfileParams....
    OptionsInfo["InfileParams"] = MiscUtil.ProcessOptionInfileParameters("--infileParams", Options["--infileParams"], OptionsInfo["Infile"])

    AlignmentSMARTSPattern = None
    if not re.match("^None$", Options["--alignmentSMARTS"], re.I):
        AlignmentSMARTSPattern = Options["--alignmentSMARTS"]
    OptionsInfo["AlignmentSMARTSPattern"]  = AlignmentSMARTSPattern
    
    OptionsInfo["AtomLabelFontSize"] = Options["--atomLabelFontSize"]
    OptionsInfo["BondLineWidth"] = Options["--bondLineWidth"]
    
    Compute2DCoords = True
    if re.match("^yes$", Options["--compute2DCoords"], re.I):
        Compute2DCoords = True
    elif re.match("^no$", Options["--compute2DCoords"], re.I):
        Compute2DCoords = False
    OptionsInfo["Compute2DCoords"]  = Compute2DCoords

    CounterCol = True
    if re.match("^no$", Options["--counterCol"], re.I):
        CounterCol = False
    OptionsInfo["CounterCol"]  = CounterCol
    
    ColVisibility = True
    if re.match("^no$", Options["--colVisibility"], re.I):
        ColVisibility = False
    OptionsInfo["ColVisibility"]  = ColVisibility
    
    OptionsInfo["FontBold"] = True
    if re.match("^no$", Options["--fontBold"], re.I):
        OptionsInfo["FontBold"] = False
        
    Footer = None
    if not re.match("^None$", Options["--footer"], re.I):
        Footer = Options["--footer"]
    OptionsInfo["Footer"]  = Footer

    FooterClass = Options["--footerClass"].strip()
    if MiscUtil.IsEmpty(FooterClass):
        MiscUtil.PrintError("The value specified using option \"--footerClass\" is empty.")
    OptionsInfo["FooterClass"]  = FooterClass
    
    Header = None
    if not re.match("^None$", Options["--header"], re.I):
        Header = Options["--header"]
    OptionsInfo["Header"]  = Header
    
    HeaderStyle = Options["--headerStyle"].strip()
    if MiscUtil.IsEmpty(HeaderStyle):
        MiscUtil.PrintError("The value specified using option \"--headerStyle\" is empty.")
    OptionsInfo["HeaderStyle"]  = HeaderStyle
    
    HighlightSMARTSPattern = None
    if not re.match("^None$", Options["--highlightSMARTS"], re.I):
        HighlightSMARTSPattern = Options["--highlightSMARTS"]
    OptionsInfo["HighlightSMARTSPattern"]  = HighlightSMARTSPattern
    
    OptionsInfo["Kekulize"] = True
    if re.match("^no$", Options["--kekulize"], re.I):
        OptionsInfo["Kekulize"] = False
        
    OptionsInfo["KeysNavigation"] = True
    if re.match("^no$", Options["--keysNavigation"], re.I):
        OptionsInfo["KeysNavigation"] = False
    
    SizeValues = Options["--molImageSize"].split(",")
    OptionsInfo["MolImageWidth"] = int(SizeValues[0])
    OptionsInfo["MolImageHeight"] = int(SizeValues[1])

    OptionsInfo["MolImageEncoded"] = True
    if re.match("^no$", Options["--molImageEncoded"], re.I):
        OptionsInfo["MolImageEncoded"] = False
    
    OptionsInfo["NumOfMolsPerRow"] = int(Options["--numOfMolsPerRow"])

    OptionsInfo["Paging"] = True
    if re.match("^no$", Options["--paging"], re.I):
        OptionsInfo["Paging"] = False
    
    PagingType = Options["--pagingType"]
    if not re.match("^(numbers|simple|simple_numbers|full|full_numbers|simple_number)$", Options["--pagingType"], re.I):
        MiscUtil.PrintWarning("The paging type name, %s, specified using option \"--pagingType\" appears to be a unknown type..." % (PagingType))
    OptionsInfo["PagingType"] = PagingType.lower()
    
    OptionsInfo["PageLength"] = int(Options["--pageLength"])
    
    OptionsInfo["Popover"] = True
    if re.match("^no$", Options["--popover"], re.I):
        OptionsInfo["Popover"] = False
    OptionsInfo["PopoverDataCount"] = int(Options["--popoverDataCount"])
    OptionsInfo["PopoverTextWidth"] = int(Options["--popoverTextWidth"])
    
    OptionsInfo["ShowMolName"] = True
    if re.match("^no$", Options["--showMolName"], re.I):
        OptionsInfo["ShowMolName"] = False
    
    OptionsInfo["ScrollX"] = True
    if re.match("^no$", Options["--scrollX"], re.I):
        OptionsInfo["ScrollX"] = False
        
    OptionsInfo["ScrollY"] = True
    if re.match("^no$", Options["--scrollY"], re.I):
        OptionsInfo["ScrollY"] = False

    OptionsInfo["ScrollYSize"] = Options["--scrollYSize"]
    if re.match("vh$", Options["--scrollYSize"], re.I):
        ScrollYSize = int(re.sub("vh$", "", Options["--scrollYSize"]))
        if ScrollYSize <= 0:
            MiscUtil.PrintError("The value specified, %s, for option \"--scrollYSize\" is not valid. Supported value: > 0 followed by \"vh\"" % Options["--scrollYSize"])
    
    TableStyle = None
    if not re.match("^None$", Options["--tableStyle"], re.I):
        if re.match("^All$", Options["--tableStyle"], re.I):
            TableStyle = "table table-striped table-bordered table-hover table-dark"
        else:
            TableStyle = re.sub(" ", "", Options["--tableStyle"])
            for Style in [Style for Style in TableStyle.split(",")]:
                if not re.match("^(table|table-striped|table-bordered|table-hover|table-dark|table-sm)$", Style, re.I):
                    MiscUtil.PrintWarning("The table style name, %s, specified using option \"-t, --tableStyle\" appears to be a unknown style..." % (Style))
            TableStyle = re.sub(",", " ", TableStyle.lower())
    OptionsInfo["TableStyle"]  = TableStyle

    OptionsInfo["TableFooter"] = True
    if re.match("^no$", Options["--tableFooter"], re.I):
        OptionsInfo["TableFooter"] = False
    
    OptionsInfo["TableHeader"] = True
    if re.match("^no$", Options["--tableHeader"], re.I):
        OptionsInfo["TableHeader"] = False
    
    TableHeaderStyle = None
    if not re.match("^None$", Options["--tableHeaderStyle"], re.I):
        TableHeaderStyle = Options["--tableHeaderStyle"]
        TableHeaderStyle = TableHeaderStyle.lower()
        CheckOptionTableClassColorValues("--tableHeaderStyle", [TableHeaderStyle])
    OptionsInfo["TableHeaderStyle"]  = TableHeaderStyle