#
#  ooxml ECMA-376 Office Open XML File Formats
#  https://www.ecma-international.org/publications/standards/Ecma-376.htm
#
#  Copyright (C) 2025 Rolf Ade, DE
#  All rights reserved.
#
#  Redistribution and use in source and binary forms, with or without modification,
#  are permitted provided that the following conditions are met:
#
#  1. Redistributions of source code must retain the above copyright notice, this
#     list of conditions and the following disclaimer.
#  2. Redistributions in binary form must reproduce the above copyright notice,
#     this list of conditions and the following disclaimer in the documentation
#     and/or other materials provided with the distribution.
#  3. Neither the name of the project nor the names of its contributors may be used
#     to endorse or promote products derived from this software without specific
#     prior written permission.
#
#  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
#  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
#  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT
#  SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
#  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
#  TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
#  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
#  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
#  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
#  SUCH DAMAGE.
#

package require Tcl 8.6.7-
package require tdom 0.9.6-

namespace eval ::ooxml::docx {
    # To ensure it exists
}

namespace eval ::ooxml::docx::lib {

    namespace export OptVal MimeType NoCheck CT_* ST_* W3CDTF AllowedValues XSD_*

    variable mimeTypes
    # This uses the list found at
    # http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types
    # That are all kind of known mime types. Probably most of them
    # cannot be inserted into a office file but quite a few can.
    # The list is generated by 
    # wget -qO- http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types | egrep -v ^# | awk '{ for (i=2; i<=NF; i++) {print $i" "$1}}' | sort > contentTypes.txt
    array set mimeTypes {
        123 application/vnd.lotus-1-2-3
        3dml text/vnd.in3d.3dml
        3ds image/x-3ds
        3g2 video/3gpp2
        3gp video/3gpp
        7z application/x-7z-compressed
        aab application/x-authorware-bin
        aac audio/x-aac
        aam application/x-authorware-map
        aas application/x-authorware-seg
        abw application/x-abiword
        ac application/pkix-attr-cert
        acc application/vnd.americandynamics.acc
        ace application/x-ace-compressed
        acu application/vnd.acucobol
        acutc application/vnd.acucorp
        adp audio/adpcm
        aep application/vnd.audiograph
        afm application/x-font-type1
        afp application/vnd.ibm.modcap
        ahead application/vnd.ahead.space
        ai application/postscript
        aif audio/x-aiff
        aifc audio/x-aiff
        aiff audio/x-aiff
        air application/vnd.adobe.air-application-installer-package+zip
        ait application/vnd.dvb.ait
        ami application/vnd.amiga.ami
        apk application/vnd.android.package-archive
        appcache text/cache-manifest
        application application/x-ms-application
        apr application/vnd.lotus-approach
        arc application/x-freearc
        asc application/pgp-signature
        asf video/x-ms-asf
        asm text/x-asm
        aso application/vnd.accpac.simply.aso
        asx video/x-ms-asf
        atc application/vnd.acucorp
        atom application/atom+xml
        atomcat application/atomcat+xml
        atomsvc application/atomsvc+xml
        atx application/vnd.antix.game-component
        au audio/basic
        avif image/avif
        avi video/x-msvideo
        aw application/applixware
        azf application/vnd.airzip.filesecure.azf
        azs application/vnd.airzip.filesecure.azs
        azw application/vnd.amazon.ebook
        bat application/x-msdownload
        bcpio application/x-bcpio
        bdf application/x-font-bdf
        bdm application/vnd.syncml.dm+wbxml
        bed application/vnd.realvnc.bed
        bh2 application/vnd.fujitsu.oasysprs
        bin application/octet-stream
        blb application/x-blorb
        blorb application/x-blorb
        bmi application/vnd.bmi
        bmp image/bmp
        book application/vnd.framemaker
        box application/vnd.previewsystems.box
        boz application/x-bzip2
        bpk application/octet-stream
        btif image/prs.btif
        bz2 application/x-bzip2
        bz application/x-bzip
        c11amc application/vnd.cluetrust.cartomobile-config
        c11amz application/vnd.cluetrust.cartomobile-config-pkg
        c4d application/vnd.clonk.c4group
        c4f application/vnd.clonk.c4group
        c4g application/vnd.clonk.c4group
        c4p application/vnd.clonk.c4group
        c4u application/vnd.clonk.c4group
        cab application/vnd.ms-cab-compressed
        caf audio/x-caf
        cap application/vnd.tcpdump.pcap
        car application/vnd.curl.car
        cat application/vnd.ms-pki.seccat
        cb7 application/x-cbr
        cba application/x-cbr
        cbr application/x-cbr
        cbt application/x-cbr
        cbz application/x-cbr
        cct application/x-director
        cc text/x-c
        ccxml application/ccxml+xml
        cdbcmsg application/vnd.contact.cmsg
        cdf application/x-netcdf
        cdkey application/vnd.mediastation.cdkey
        cdmia application/cdmi-capability
        cdmic application/cdmi-container
        cdmid application/cdmi-domain
        cdmio application/cdmi-object
        cdmiq application/cdmi-queue
        cdx chemical/x-cdx
        cdxml application/vnd.chemdraw+xml
        cdy application/vnd.cinderella
        cer application/pkix-cert
        cfs application/x-cfs-compressed
        cgm image/cgm
        chat application/x-chat
        chm application/vnd.ms-htmlhelp
        chrt application/vnd.kde.kchart
        cif chemical/x-cif
        cii application/vnd.anser-web-certificate-issue-initiation
        cil application/vnd.ms-artgalry
        cla application/vnd.claymore
        class application/java-vm
        clkk application/vnd.crick.clicker.keyboard
        clkp application/vnd.crick.clicker.palette
        clkt application/vnd.crick.clicker.template
        clkw application/vnd.crick.clicker.wordbank
        clkx application/vnd.crick.clicker
        clp application/x-msclip
        cmc application/vnd.cosmocaller
        cmdf chemical/x-cmdf
        cml chemical/x-cml
        cmp application/vnd.yellowriver-custom-menu
        cmx image/x-cmx
        cod application/vnd.rim.cod
        com application/x-msdownload
        conf text/plain
        cpio application/x-cpio
        cpp text/x-c
        cpt application/mac-compactpro
        crd application/x-mscardfile
        crl application/pkix-crl
        crt application/x-x509-ca-cert
        cryptonote application/vnd.rig.cryptonote
        csh application/x-csh
        csml chemical/x-csml
        csp application/vnd.commonspace
        css text/css
        cst application/x-director
        csv text/csv
        c text/x-c
        cu application/cu-seeme
        curl text/vnd.curl
        cww application/prs.cww
        cxt application/x-director
        cxx text/x-c
        dae model/vnd.collada+xml
        daf application/vnd.mobius.daf
        dart application/vnd.dart
        dataless application/vnd.fdsn.seed
        davmount application/davmount+xml
        dbk application/docbook+xml
        dcr application/x-director
        dcurl text/vnd.curl.dcurl
        dd2 application/vnd.oma.dd2+xml
        ddd application/vnd.fujixerox.ddd
        deb application/x-debian-package
        def text/plain
        deploy application/octet-stream
        der application/x-x509-ca-cert
        dfac application/vnd.dreamfactory
        dgc application/x-dgc-compressed
        dic text/x-c
        dir application/x-director
        dis application/vnd.mobius.dis
        dist application/octet-stream
        distz application/octet-stream
        djv image/vnd.djvu
        djvu image/vnd.djvu
        dll application/x-msdownload
        dmg application/x-apple-diskimage
        dmp application/vnd.tcpdump.pcap
        dms application/octet-stream
        dna application/vnd.dna
        doc application/msword
        docm application/vnd.ms-word.document.macroenabled.12
        docx application/vnd.openxmlformats-officedocument.wordprocessingml.document
        dot application/msword
        dotm application/vnd.ms-word.template.macroenabled.12
        dotx application/vnd.openxmlformats-officedocument.wordprocessingml.template
        dp application/vnd.osgi.dp
        dpg application/vnd.dpgraph
        dra audio/vnd.dra
        dsc text/prs.lines.tag
        dssc application/dssc+der
        dtb application/x-dtbook+xml
        dtd application/xml-dtd
        dts audio/vnd.dts
        dtshd audio/vnd.dts.hd
        dump application/octet-stream
        dvb video/vnd.dvb.file
        dvi application/x-dvi
        dwf model/vnd.dwf
        dwg image/vnd.dwg
        dxf image/vnd.dxf
        dxp application/vnd.spotfire.dxp
        dxr application/x-director
        ecelp4800 audio/vnd.nuera.ecelp4800
        ecelp7470 audio/vnd.nuera.ecelp7470
        ecelp9600 audio/vnd.nuera.ecelp9600
        ecma application/ecmascript
        edm application/vnd.novadigm.edm
        edx application/vnd.novadigm.edx
        efif application/vnd.picsel
        ei6 application/vnd.pg.osasli
        elc application/octet-stream
        emf application/x-msmetafile
        eml message/rfc822
        emma application/emma+xml
        emz application/x-msmetafile
        eol audio/vnd.digital-winds
        eot application/vnd.ms-fontobject
        eps application/postscript
        epub application/epub+zip
        es3 application/vnd.eszigno3+xml
        esa application/vnd.osgi.subsystem
        esf application/vnd.epson.esf
        et3 application/vnd.eszigno3+xml
        etx text/x-setext
        eva application/x-eva
        evy application/x-envoy
        exe application/x-msdownload
        exi application/exi
        ext application/vnd.novadigm.ext
        ez2 application/vnd.ezpix-album
        ez3 application/vnd.ezpix-package
        ez application/andrew-inset
        f4v video/x-f4v
        f77 text/x-fortran
        f90 text/x-fortran
        fbs image/vnd.fastbidsheet
        fcdt application/vnd.adobe.formscentral.fcdt
        fcs application/vnd.isac.fcs
        fdf application/vnd.fdf
        fe_launch application/vnd.denovo.fcselayout-link
        fg5 application/vnd.fujitsu.oasysgp
        fgd application/x-director
        fh4 image/x-freehand
        fh5 image/x-freehand
        fh7 image/x-freehand
        fhc image/x-freehand
        fh image/x-freehand
        fig application/x-xfig
        flac audio/x-flac
        fli video/x-fli
        flo application/vnd.micrografx.flo
        flv video/x-flv
        flw application/vnd.kde.kivio
        flx text/vnd.fmi.flexstor
        fly text/vnd.fly
        fm application/vnd.framemaker
        fnc application/vnd.frogans.fnc
        for text/x-fortran
        fpx image/vnd.fpx
        frame application/vnd.framemaker
        fsc application/vnd.fsc.weblaunch
        fst image/vnd.fst
        ftc application/vnd.fluxtime.clip
        f text/x-fortran
        fti application/vnd.anser-web-funds-transfer-initiation
        fvt video/vnd.fvt
        fxp application/vnd.adobe.fxp
        fxpl application/vnd.adobe.fxp
        fzs application/vnd.fuzzysheet
        g2w application/vnd.geoplan
        g3 image/g3fax
        g3w application/vnd.geospace
        gac application/vnd.groove-account
        gam application/x-tads
        gbr application/rpki-ghostbusters
        gca application/x-gca-compressed
        gdl model/vnd.gdl
        geo application/vnd.dynageo
        gex application/vnd.geometry-explorer
        ggb application/vnd.geogebra.file
        ggs application/vnd.geogebra.slides
        ggt application/vnd.geogebra.tool
        ghf application/vnd.groove-help
        gif image/gif
        gim application/vnd.groove-identity-message
        gml application/gml+xml
        gmx application/vnd.gmx
        gnumeric application/x-gnumeric
        gph application/vnd.flographit
        gpx application/gpx+xml
        gqf application/vnd.grafeq
        gqs application/vnd.grafeq
        gram application/srgs
        gramps application/x-gramps-xml
        gre application/vnd.geometry-explorer
        grv application/vnd.groove-injector
        grxml application/srgs+xml
        gsf application/x-font-ghostscript
        gtar application/x-gtar
        gtm application/vnd.groove-tool-message
        gtw model/vnd.gtw
        gv text/vnd.graphviz
        gxf application/gxf
        gxt application/vnd.geonext
        h261 video/h261
        h263 video/h263
        h264 video/h264
        hal application/vnd.hal+xml
        hbci application/vnd.hbci
        hdf application/x-hdf
        hh text/x-c
        hlp application/winhlp
        hpgl application/vnd.hp-hpgl
        hpid application/vnd.hp-hpid
        hps application/vnd.hp-hps
        hqx application/mac-binhex40
        h text/x-c
        htke application/vnd.kenameaapp
        html text/html
        htm text/html
        hvd application/vnd.yamaha.hv-dic
        hvp application/vnd.yamaha.hv-voice
        hvs application/vnd.yamaha.hv-script
        i2g application/vnd.intergeo
        icc application/vnd.iccprofile
        ice x-conference/x-cooltalk
        icm application/vnd.iccprofile
        ico image/x-icon
        ics text/calendar
        ief image/ief
        ifb text/calendar
        ifm application/vnd.shana.informed.formdata
        iges model/iges
        igl application/vnd.igloader
        igm application/vnd.insors.igm
        igs model/iges
        igx application/vnd.micrografx.igx
        iif application/vnd.shana.informed.interchange
        imp application/vnd.accpac.simply.imp
        ims application/vnd.ms-ims
        ink application/inkml+xml
        inkml application/inkml+xml
        install application/x-install-instructions
        in text/plain
        iota application/vnd.astraea-software.iota
        ipfix application/ipfix
        ipk application/vnd.shana.informed.package
        irm application/vnd.ibm.rights-management
        irp application/vnd.irepository.package+xml
        iso application/x-iso9660-image
        itp application/vnd.shana.informed.formtemplate
        ivp application/vnd.immervision-ivp
        ivu application/vnd.immervision-ivu
        jad text/vnd.sun.j2me.app-descriptor
        jam application/vnd.jam
        jar application/java-archive
        java text/x-java-source
        jisp application/vnd.jisp
        jlt application/vnd.hp-jlyt
        jnlp application/x-java-jnlp-file
        joda application/vnd.joost.joda-archive
        jpeg image/jpeg
        jpe image/jpeg
        jpg image/jpeg
        jpgm video/jpm
        jpgv video/jpeg
        jpm video/jpm
        json application/json
        jsonml application/jsonml+json
        js text/javascript
        jxl image/jxl
        kar audio/midi
        karbon application/vnd.kde.karbon
        kfo application/vnd.kde.kformula
        kia application/vnd.kidspiration
        kml application/vnd.google-earth.kml+xml
        kmz application/vnd.google-earth.kmz
        kne application/vnd.kinar
        knp application/vnd.kinar
        kon application/vnd.kde.kontour
        kpr application/vnd.kde.kpresenter
        kpt application/vnd.kde.kpresenter
        kpxx application/vnd.ds-keypoint
        ksp application/vnd.kde.kspread
        ktr application/vnd.kahootz
        ktx image/ktx
        ktz application/vnd.kahootz
        kwd application/vnd.kde.kword
        kwt application/vnd.kde.kword
        lasxml application/vnd.las.las+xml
        latex application/x-latex
        lbd application/vnd.llamagraphics.life-balance.desktop
        lbe application/vnd.llamagraphics.life-balance.exchange+xml
        les application/vnd.hhe.lesson-player
        lha application/x-lzh-compressed
        link66 application/vnd.route66.link66+xml
        list3820 application/vnd.ibm.modcap
        listafp application/vnd.ibm.modcap
        list text/plain
        lnk application/x-ms-shortcut
        log text/plain
        lostxml application/lost+xml
        lrf application/octet-stream
        lrm application/vnd.ms-lrm
        ltf application/vnd.frogans.ltf
        lvp audio/vnd.lucent.voice
        lwp application/vnd.lotus-wordpro
        lzh application/x-lzh-compressed
        m13 application/x-msmediaview
        m14 application/x-msmediaview
        m1v video/mpeg
        m21 application/mp21
        m2a audio/mpeg
        m2ts video/mp2t
        m2t video/mp2t
        m2v video/mpeg
        m3a audio/mpeg
        m3u8 application/vnd.apple.mpegurl
        m3u audio/x-mpegurl
        m4a audio/mp4
        m4u video/vnd.mpegurl
        m4v video/x-m4v
        ma application/mathematica
        mads application/mads+xml
        mag application/vnd.ecowin.chart
        maker application/vnd.framemaker
        man text/troff
        mar application/octet-stream
        mathml application/mathml+xml
        mb application/mathematica
        mbk application/vnd.mobius.mbk
        mbox application/mbox
        mc1 application/vnd.medcalcdata
        mcd application/vnd.mcd
        mcurl text/vnd.curl.mcurl
        mdb application/x-msaccess
        mdi image/vnd.ms-modi
        mesh model/mesh
        meta4 application/metalink4+xml
        metalink application/metalink+xml
        me text/troff
        mets application/mets+xml
        mfm application/vnd.mfmp
        mft application/rpki-manifest
        mgp application/vnd.osgeo.mapguide.package
        mgz application/vnd.proteus.magazine
        mid audio/midi
        midi audio/midi
        mie application/x-mie
        mif application/vnd.mif
        mime message/rfc822
        mj2 video/mj2
        mjp2 video/mj2
        mjs text/javascript
        mk3d video/x-matroska
        mka audio/x-matroska
        mks video/x-matroska
        mkv video/x-matroska
        mlp application/vnd.dolby.mlp
        mmd application/vnd.chipnuts.karaoke-mmd
        mmf application/vnd.smaf
        mmr image/vnd.fujixerox.edmics-mmr
        mng video/x-mng
        mny application/x-msmoney
        mobi application/x-mobipocket-ebook
        mods application/mods+xml
        movie video/x-sgi-movie
        mov video/quicktime
        mp21 application/mp21
        mp2a audio/mpeg
        mp2 audio/mpeg
        mp3 audio/mpeg
        mp4a audio/mp4
        mp4s application/mp4
        mp4 video/mp4
        mp4v video/mp4
        mpc application/vnd.mophun.certificate
        mpeg video/mpeg
        mpe video/mpeg
        mpg4 video/mp4
        mpga audio/mpeg
        mpg video/mpeg
        mpkg application/vnd.apple.installer+xml
        mpm application/vnd.blueice.multipass
        mpn application/vnd.mophun.application
        mpp application/vnd.ms-project
        mpt application/vnd.ms-project
        mpy application/vnd.ibm.minipay
        mqy application/vnd.mobius.mqy
        mrc application/marc
        mrcx application/marcxml+xml
        mscml application/mediaservercontrol+xml
        mseed application/vnd.fdsn.mseed
        mseq application/vnd.mseq
        msf application/vnd.epson.msf
        msh model/mesh
        msi application/x-msdownload
        msl application/vnd.mobius.msl
        ms text/troff
        msty application/vnd.muvee.style
        mts video/mp2t
        mus application/vnd.musician
        musicxml application/vnd.recordare.musicxml+xml
        mvb application/x-msmediaview
        mwf application/vnd.mfer
        mxf application/mxf
        mxl application/vnd.recordare.musicxml
        mxml application/xv+xml
        mxs application/vnd.triscape.mxs
        mxu video/vnd.mpegurl
        n3 text/n3
        nb application/mathematica
        nbp application/vnd.wolfram.player
        nc application/x-netcdf
        ncx application/x-dtbncx+xml
        nfo text/x-nfo
        n-gage application/vnd.nokia.n-gage.symbian.install
        ngdat application/vnd.nokia.n-gage.data
        nitf application/vnd.nitf
        nlu application/vnd.neurolanguage.nlu
        nml application/vnd.enliven
        nnd application/vnd.noblenet-directory
        nns application/vnd.noblenet-sealer
        nnw application/vnd.noblenet-web
        npx image/vnd.net-fpx
        nsc application/x-conference
        nsf application/vnd.lotus-notes
        ntf application/vnd.nitf
        nzb application/x-nzb
        oa2 application/vnd.fujitsu.oasys2
        oa3 application/vnd.fujitsu.oasys3
        oas application/vnd.fujitsu.oasys
        obd application/x-msbinder
        obj application/x-tgif
        oda application/oda
        odb application/vnd.oasis.opendocument.database
        odc application/vnd.oasis.opendocument.chart
        odf application/vnd.oasis.opendocument.formula
        odft application/vnd.oasis.opendocument.formula-template
        odg application/vnd.oasis.opendocument.graphics
        odi application/vnd.oasis.opendocument.image
        odm application/vnd.oasis.opendocument.text-master
        odp application/vnd.oasis.opendocument.presentation
        ods application/vnd.oasis.opendocument.spreadsheet
        odt application/vnd.oasis.opendocument.text
        oga audio/ogg
        ogg audio/ogg
        ogv video/ogg
        ogx application/ogg
        omdoc application/omdoc+xml
        onepkg application/onenote
        onetmp application/onenote
        onetoc2 application/onenote
        onetoc application/onenote
        opf application/oebps-package+xml
        opml text/x-opml
        oprc application/vnd.palm
        opus audio/ogg
        org application/vnd.lotus-organizer
        osf application/vnd.yamaha.openscoreformat
        osfpvg application/vnd.yamaha.openscoreformat.osfpvg+xml
        otc application/vnd.oasis.opendocument.chart-template
        otf font/otf
        otg application/vnd.oasis.opendocument.graphics-template
        oth application/vnd.oasis.opendocument.text-web
        oti application/vnd.oasis.opendocument.image-template
        otp application/vnd.oasis.opendocument.presentation-template
        ots application/vnd.oasis.opendocument.spreadsheet-template
        ott application/vnd.oasis.opendocument.text-template
        oxps application/oxps
        oxt application/vnd.openofficeorg.extension
        p10 application/pkcs10
        p12 application/x-pkcs12
        p7b application/x-pkcs7-certificates
        p7c application/pkcs7-mime
        p7m application/pkcs7-mime
        p7r application/x-pkcs7-certreqresp
        p7s application/pkcs7-signature
        p8 application/pkcs8
        pas text/x-pascal
        paw application/vnd.pawaafile
        pbd application/vnd.powerbuilder6
        pbm image/x-portable-bitmap
        pcap application/vnd.tcpdump.pcap
        pcf application/x-font-pcf
        pcl application/vnd.hp-pcl
        pclxl application/vnd.hp-pclxl
        pct image/x-pict
        pcurl application/vnd.curl.pcurl
        pcx image/x-pcx
        pdb application/vnd.palm
        pdf application/pdf
        pfa application/x-font-type1
        pfb application/x-font-type1
        pfm application/x-font-type1
        pfr application/font-tdpfr
        pfx application/x-pkcs12
        pgm image/x-portable-graymap
        pgn application/x-chess-pgn
        pgp application/pgp-encrypted
        pic image/x-pict
        pkg application/octet-stream
        pki application/pkixcmp
        pkipath application/pkix-pkipath
        plb application/vnd.3gpp.pic-bw-large
        plc application/vnd.mobius.plc
        plf application/vnd.pocketlearn
        pls application/pls+xml
        pml application/vnd.ctc-posml
        png image/png
        pnm image/x-portable-anymap
        portpkg application/vnd.macports.portpkg
        pot application/vnd.ms-powerpoint
        potm application/vnd.ms-powerpoint.template.macroenabled.12
        potx application/vnd.openxmlformats-officedocument.presentationml.template
        ppam application/vnd.ms-powerpoint.addin.macroenabled.12
        ppd application/vnd.cups-ppd
        ppm image/x-portable-pixmap
        pps application/vnd.ms-powerpoint
        ppsm application/vnd.ms-powerpoint.slideshow.macroenabled.12
        ppsx application/vnd.openxmlformats-officedocument.presentationml.slideshow
        ppt application/vnd.ms-powerpoint
        pptm application/vnd.ms-powerpoint.presentation.macroenabled.12
        pptx application/vnd.openxmlformats-officedocument.presentationml.presentation
        pqa application/vnd.palm
        prc application/x-mobipocket-ebook
        pre application/vnd.lotus-freelance
        prf application/pics-rules
        ps application/postscript
        psb application/vnd.3gpp.pic-bw-small
        psd image/vnd.adobe.photoshop
        psf application/x-font-linux-psf
        pskcxml application/pskc+xml
        p text/x-pascal
        ptid application/vnd.pvi.ptid1
        pub application/x-mspublisher
        pvb application/vnd.3gpp.pic-bw-var
        pwn application/vnd.3m.post-it-notes
        pya audio/vnd.ms-playready.media.pya
        pyv video/vnd.ms-playready.media.pyv
        qam application/vnd.epson.quickanime
        qbo application/vnd.intu.qbo
        qfx application/vnd.intu.qfx
        qps application/vnd.publishare-delta-tree
        qt video/quicktime
        qwd application/vnd.quark.quarkxpress
        qwt application/vnd.quark.quarkxpress
        qxb application/vnd.quark.quarkxpress
        qxd application/vnd.quark.quarkxpress
        qxl application/vnd.quark.quarkxpress
        qxt application/vnd.quark.quarkxpress
        ra audio/x-pn-realaudio
        ram audio/x-pn-realaudio
        rar application/x-rar-compressed
        ras image/x-cmu-raster
        rcprofile application/vnd.ipunplugged.rcprofile
        rdf application/rdf+xml
        rdz application/vnd.data-vision.rdz
        rep application/vnd.businessobjects
        res application/x-dtbresource+xml
        rgb image/x-rgb
        rif application/reginfo+xml
        rip audio/vnd.rip
        ris application/x-research-info-systems
        rl application/resource-lists+xml
        rlc image/vnd.fujixerox.edmics-rlc
        rld application/resource-lists-diff+xml
        rm application/vnd.rn-realmedia
        rmi audio/midi
        rmp audio/x-pn-realaudio-plugin
        rms application/vnd.jcp.javame.midlet-rms
        rmvb application/vnd.rn-realmedia-vbr
        rnc application/relax-ng-compact-syntax
        roa application/rpki-roa
        roff text/troff
        rp9 application/vnd.cloanto.rp9
        rpss application/vnd.nokia.radio-presets
        rpst application/vnd.nokia.radio-preset
        rq application/sparql-query
        rs application/rls-services+xml
        rsd application/rsd+xml
        rss application/rss+xml
        rtf application/rtf
        rtx text/richtext
        s3m audio/s3m
        saf application/vnd.yamaha.smaf-audio
        sbml application/sbml+xml
        sc application/vnd.ibm.secure-container
        scd application/x-msschedule
        scm application/vnd.lotus-screencam
        scq application/scvp-cv-request
        scs application/scvp-cv-response
        scurl text/vnd.curl.scurl
        sda application/vnd.stardivision.draw
        sdc application/vnd.stardivision.calc
        sdd application/vnd.stardivision.impress
        sdkd application/vnd.solent.sdkm+xml
        sdkm application/vnd.solent.sdkm+xml
        sdp application/sdp
        sdw application/vnd.stardivision.writer
        see application/vnd.seemail
        seed application/vnd.fdsn.seed
        sema application/vnd.sema
        semd application/vnd.semd
        semf application/vnd.semf
        ser application/java-serialized-object
        setpay application/set-payment-initiation
        setreg application/set-registration-initiation
        sfd-hdstx application/vnd.hydrostatix.sof-data
        sfs application/vnd.spotfire.sfs
        sfv text/x-sfv
        sgi image/sgi
        sgl application/vnd.stardivision.writer-global
        sgml text/sgml
        sgm text/sgml
        sh application/x-sh
        shar application/x-shar
        shf application/shf+xml
        sid image/x-mrsid-image
        sig application/pgp-signature
        sil audio/silk
        silo model/mesh
        sis application/vnd.symbian.install
        sisx application/vnd.symbian.install
        sit application/x-stuffit
        sitx application/x-stuffitx
        skd application/vnd.koan
        skm application/vnd.koan
        skp application/vnd.koan
        skt application/vnd.koan
        sldm application/vnd.ms-powerpoint.slide.macroenabled.12
        sldx application/vnd.openxmlformats-officedocument.presentationml.slide
        slt application/vnd.epson.salt
        sm application/vnd.stepmania.stepchart
        smf application/vnd.stardivision.math
        smi application/smil+xml
        smil application/smil+xml
        smv video/x-smv
        smzip application/vnd.stepmania.package
        snd audio/basic
        snf application/x-font-snf
        so application/octet-stream
        spc application/x-pkcs7-certificates
        spf application/vnd.yamaha.smaf-phrase
        spl application/x-futuresplash
        spot text/vnd.in3d.spot
        spp application/scvp-vp-response
        spq application/scvp-vp-request
        spx audio/ogg
        sql application/x-sql
        src application/x-wais-source
        srt application/x-subrip
        sru application/sru+xml
        srx application/sparql-results+xml
        ssdl application/ssdl+xml
        sse application/vnd.kodak-descriptor
        ssf application/vnd.epson.ssf
        ssml application/ssml+xml
        st application/vnd.sailingtracker.track
        stc application/vnd.sun.xml.calc.template
        std application/vnd.sun.xml.draw.template
        s text/x-asm
        stf application/vnd.wt.stf
        sti application/vnd.sun.xml.impress.template
        stk application/hyperstudio
        stl application/vnd.ms-pki.stl
        str application/vnd.pg.format
        stw application/vnd.sun.xml.writer.template
        sub image/vnd.dvb.subtitle
        sub text/vnd.dvb.subtitle
        sus application/vnd.sus-calendar
        susp application/vnd.sus-calendar
        sv4cpio application/x-sv4cpio
        sv4crc application/x-sv4crc
        svc application/vnd.dvb.service
        svd application/vnd.svd
        svg image/svg+xml
        svgz image/svg+xml
        swa application/x-director
        swf application/x-shockwave-flash
        swi application/vnd.aristanetworks.swi
        sxc application/vnd.sun.xml.calc
        sxd application/vnd.sun.xml.draw
        sxg application/vnd.sun.xml.writer.global
        sxi application/vnd.sun.xml.impress
        sxm application/vnd.sun.xml.math
        sxw application/vnd.sun.xml.writer
        t3 application/x-t3vm-image
        taglet application/vnd.mynfc
        tao application/vnd.tao.intent-module-archive
        tar application/x-tar
        tcap application/vnd.3gpp2.tcap
        tcl application/x-tcl
        teacher application/vnd.smart.teacher
        tei application/tei+xml
        teicorpus application/tei+xml
        tex application/x-tex
        texi application/x-texinfo
        texinfo application/x-texinfo
        text text/plain
        tfi application/thraud+xml
        tfm application/x-tex-tfm
        tga image/x-tga
        thmx application/vnd.ms-officetheme
        tiff image/tiff
        tif image/tiff
        tmo application/vnd.tmobile-livetv
        torrent application/x-bittorrent
        tpl application/vnd.groove-tool-template
        tpt application/vnd.trid.tpt
        tra application/vnd.trueapp
        trm application/x-msterminal
        tr text/troff
        tsd application/timestamped-data
        ts video/mp2t
        tsv text/tab-separated-values
        ttc font/collection
        t text/troff
        ttf font/ttf
        ttl text/turtle
        twd application/vnd.simtech-mindmapper
        twds application/vnd.simtech-mindmapper
        txd application/vnd.genomatix.tuxedo
        txf application/vnd.mobius.txf
        txt text/plain
        u32 application/x-authorware-bin
        udeb application/x-debian-package
        ufd application/vnd.ufdl
        ufdl application/vnd.ufdl
        ulx application/x-glulx
        umj application/vnd.umajin
        unityweb application/vnd.unity
        uoml application/vnd.uoml+xml
        uris text/uri-list
        uri text/uri-list
        urls text/uri-list
        ustar application/x-ustar
        utz application/vnd.uiq.theme
        uu text/x-uuencode
        uva audio/vnd.dece.audio
        uvd application/vnd.dece.data
        uvf application/vnd.dece.data
        uvg image/vnd.dece.graphic
        uvh video/vnd.dece.hd
        uvi image/vnd.dece.graphic
        uvm video/vnd.dece.mobile
        uvp video/vnd.dece.pd
        uvs video/vnd.dece.sd
        uvt application/vnd.dece.ttml+xml
        uvu video/vnd.uvvu.mp4
        uvva audio/vnd.dece.audio
        uvvd application/vnd.dece.data
        uvvf application/vnd.dece.data
        uvvg image/vnd.dece.graphic
        uvvh video/vnd.dece.hd
        uvvi image/vnd.dece.graphic
        uvvm video/vnd.dece.mobile
        uvvp video/vnd.dece.pd
        uvvs video/vnd.dece.sd
        uvvt application/vnd.dece.ttml+xml
        uvvu video/vnd.uvvu.mp4
        uvv video/vnd.dece.video
        uvvv video/vnd.dece.video
        uvvx application/vnd.dece.unspecified
        uvvz application/vnd.dece.zip
        uvx application/vnd.dece.unspecified
        uvz application/vnd.dece.zip
        vcard text/vcard
        vcd application/x-cdlink
        vcf text/x-vcard
        vcg application/vnd.groove-vcard
        vcs text/x-vcalendar
        vcx application/vnd.vcx
        vis application/vnd.visionary
        viv video/vnd.vivo
        vob video/x-ms-vob
        vor application/vnd.stardivision.writer
        vox application/x-authorware-bin
        vrml model/vrml
        vsd application/vnd.visio
        vsf application/vnd.vsf
        vss application/vnd.visio
        vst application/vnd.visio
        vsw application/vnd.visio
        vtu model/vnd.vtu
        vxml application/voicexml+xml
        w3d application/x-director
        wad application/x-doom
        wasm application/wasm
        wav audio/x-wav
        wax audio/x-ms-wax
        wbmp image/vnd.wap.wbmp
        wbs application/vnd.criticaltools.wbs+xml
        wbxml application/vnd.wap.wbxml
        wcm application/vnd.ms-works
        wdb application/vnd.ms-works
        wdp image/vnd.ms-photo
        weba audio/webm
        webm video/webm
        webp image/webp
        wg application/vnd.pmi.widget
        wgt application/widget
        wks application/vnd.ms-works
        wma audio/x-ms-wma
        wmd application/x-ms-wmd
        wmf application/x-msmetafile
        wmlc application/vnd.wap.wmlc
        wmlsc application/vnd.wap.wmlscriptc
        wmls text/vnd.wap.wmlscript
        wml text/vnd.wap.wml
        wm video/x-ms-wm
        wmv video/x-ms-wmv
        wmx video/x-ms-wmx
        wmz application/x-msmetafile
        wmz application/x-ms-wmz
        woff2 font/woff2
        woff font/woff
        wpd application/vnd.wordperfect
        wpl application/vnd.ms-wpl
        wps application/vnd.ms-works
        wqd application/vnd.wqd
        wri application/x-mswrite
        wrl model/vrml
        wsdl application/wsdl+xml
        wspolicy application/wspolicy+xml
        wtb application/vnd.webturbo
        wvx video/x-ms-wvx
        x32 application/x-authorware-bin
        x3db model/x3d+binary
        x3dbz model/x3d+binary
        x3d model/x3d+xml
        x3dv model/x3d+vrml
        x3dvz model/x3d+vrml
        x3dz model/x3d+xml
        xaml application/xaml+xml
        xap application/x-silverlight-app
        xar application/vnd.xara
        xbap application/x-ms-xbap
        xbd application/vnd.fujixerox.docuworks.binder
        xbm image/x-xbitmap
        xdf application/xcap-diff+xml
        xdm application/vnd.syncml.dm+xml
        xdp application/vnd.adobe.xdp+xml
        xdssc application/dssc+xml
        xdw application/vnd.fujixerox.docuworks
        xenc application/xenc+xml
        xer application/patch-ops-error+xml
        xfdf application/vnd.adobe.xfdf
        xfdl application/vnd.xfdl
        xht application/xhtml+xml
        xhtml application/xhtml+xml
        xhvml application/xv+xml
        xif image/vnd.xiff
        xla application/vnd.ms-excel
        xlam application/vnd.ms-excel.addin.macroenabled.12
        xlc application/vnd.ms-excel
        xlf application/x-xliff+xml
        xlm application/vnd.ms-excel
        xls application/vnd.ms-excel
        xlsb application/vnd.ms-excel.sheet.binary.macroenabled.12
        xlsm application/vnd.ms-excel.sheet.macroenabled.12
        xlsx application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
        xlt application/vnd.ms-excel
        xltm application/vnd.ms-excel.template.macroenabled.12
        xltx application/vnd.openxmlformats-officedocument.spreadsheetml.template
        xlw application/vnd.ms-excel
        xm audio/xm
        xml application/xml
        xo application/vnd.olpc-sugar
        xop application/xop+xml
        xpi application/x-xpinstall
        xpl application/xproc+xml
        xpm image/x-xpixmap
        xpr application/vnd.is-xpr
        xps application/vnd.ms-xpsdocument
        xpw application/vnd.intercon.formnet
        xpx application/vnd.intercon.formnet
        xsl application/xml
        xslt application/xslt+xml
        xsm application/vnd.syncml+xml
        xspf application/xspf+xml
        xul application/vnd.mozilla.xul+xml
        xvm application/xv+xml
        xvml application/xv+xml
        xwd image/x-xwindowdump
        xyz chemical/x-xyz
        xz application/x-xz
        yang application/yang
        yin application/yin+xml
        z1 application/x-zmachine
        z2 application/x-zmachine
        z3 application/x-zmachine
        z4 application/x-zmachine
        z5 application/x-zmachine
        z6 application/x-zmachine
        z7 application/x-zmachine
        z8 application/x-zmachine
        zaz application/vnd.zzazz.deck+xml
        zip application/zip
        zir application/vnd.zul
        zirz application/vnd.zul
        zmm application/vnd.handheld-entertainment+xml
    }
}

if {![info exists ::ooxml::docx::docgen] || !$::ooxml::docx::docgen} {
    proc ::ooxml::docx::lib::AllowedValues {values {word "or"}} {
        return "[join [lrange $values 0 end-1] ", "] $word [lindex $values end]"
    }
} else {
    # Only used to generate documentation stubs for types
    proc ::ooxml::docx::lib::AllowedValues {values {word "or"}} {
        return "===[lindex [info level -1] 0]===[join $values |]"
    }
}

proc ::ooxml::docx::lib::CT_Boolean {value} {
    if {![string is boolean -strict $value]} {
        error "expected a Tcl boolean value"
    }
    if {$value} {
        return 1
    } else {
        return 0
    }
}

proc ::ooxml::docx::lib::CT_OnOff {value} {
    if {![string is boolean -strict $value]} {
        error "expected a Tcl boolean value"
    }
    if {$value} {
        return "1"
    } else {
        return "0"
    }
}

proc ::ooxml::docx::lib::CT_UnsignedInt {value} {
    if {![regexp {^[0-9]+$} $value]} {
        error "expected an unsigned integer"
    }
    return $value
}

proc ::ooxml::docx::lib::OptVal {
    arglist
    {prefix ""}
    {suffix ""}
    {starttext "invalid arguments, expected:"}} {
    if {[llength $arglist] % 2 != 0} {
        if {$prefix ne ""} {append prefix " "}
        if {$suffix ne ""} {set suffix " $suffix"}
        error "$starttext ${prefix}?-option value?\
               ?-option value? ..$suffix"
    }
    uplevel "array set opts [list $arglist]"
}

proc ::ooxml::docx::lib::MimeType {suffix} {
    variable mimeTypes

    set lsuffix [string tolower $suffix]
    if {![info exists mimeTypes($lsuffix)]} {
        error "do not know the mime type for the file suffix \"$suffix\"\
               - if this file can be included into libreoffice or word\
               please report this as bug"
    }
    return $mimeTypes($lsuffix)
}

proc ::ooxml::docx::lib::NoCheck {value} {
    return $value
}

proc ::ooxml::docx::lib::ST_AlignH {value} {
    set values {
        left
        right
        center
        inside
        outside
    }
    if {$value in $values} {
        return $value
    }
    error "unknown alignH value \"$value\", expected one of\
            [AllowedValues $values]"
}

proc ::ooxml::docx::lib::ST_AlgClass {value} {
    set values {
        hash
        custom
    }
    if {$value in $values} {
        return $value
    }
    error "unknown AlgClass value \"$value\", expected one of\
            [AllowedValues $values]"
}

proc ::ooxml::docx::lib::ST_AlgType {value} {
    set values {
        typeAny
        custom
    }
    if {$value in $values} {
        return $value
    }
    error "unknown AlgType value \"$value\", expected one of\
            [AllowedValues $values]"
}

proc ::ooxml::docx::lib::ST_AlignV {value} {
    set values {
        top
        bottom
        center
        inside
        outside
    }
    if {$value in $values} {
        return $value
    }
    error "unknown alignV value \"$value\", expected one of\
            [AllowedValues $values]"
}

proc ::ooxml::docx::lib::ST_Anchor {value} {
    set values {
        text
        margin
        page
    }
    if {$value in $values} {
        return $value
    }
    error "unknown vAnchor or hAnchor type \"$value\", expected one of\
            [AllowedValues $values]"
}

proc ::ooxml::docx::lib::ST_BlackWhiteMode {value} {
    set values {
        auto
        black
        blackGray
        blackWhite
        clr
        gray
        grayWhite
        hidden
        invGray
        ltGray
        white
    }
    if {$value in $values} {
        return $value
    }
    error "unknown back and white mode \"$value\", expected one of\
            [AllowedValues $values]"
}

proc ::ooxml::docx::lib::ST_Border {value} {
    # The xsd list a lot more but they seemed not to be supported
    # anymore by recent docx renderer.
    set values {
        nil
        none
        single
        thick
        double
        dotted
        dashed
        dotDash
        dotDotDash
        triple
        thinThickSmallGap
        thickThinSmallGap
        thinThickThinSmallGap
        thinThickMediumGap
        thickThinMediumGap
        thinThickThinMediumGap
        thinThickLargeGap
        thickThinLargeGap
        thinThickThinLargeGap
        wave
        doubleWave
        dashSmallGap
        dashDotStroked
        threeDEmboss
        threeDEngrave
        outset
        inset
    }
    if {$value in $values} {
        return $value
    }
    error "unknown border type value \"$value\", expected one of\
               [AllowedValues $values]"
}
 
proc ::ooxml::docx::lib::ST_ChapterSep {value} {
    set values {
        hyphen
        period
        colon
        emDash
        enDash
    }
    if {$value in $values} {
        return $value
    }
    error "unknown section separator character \"$value\", expected one of\
            [AllowedValues $values]"
}

proc ::ooxml::docx::lib::ST_CharacterSpacing {value} {
    set values {
        doNotCompress
        compressPunctuation
        compressPunctuationAndJapaneseKana
    }
    if {$value in $values} {
        return $value
    }
    error "unknown character spacing type \"$value\", expected one of\
            [AllowedValues $values]"
}

proc ::ooxml::docx::lib::ST_CryptProv {value} {
    set values {
        rsaAES
        rsaFull
        custom
    }
    if {$value in $values} {
        return $value
    }
    error "unknown CryptProv value \"$value\", expected one of\
            [AllowedValues $values]"
}

proc ::ooxml::docx::lib::ST_DateTime {value} {
    if {![::tdom::type::dateTime $value]} {
        error "expected an xsd dateTime value (which is closely like the\
               format of an ISO 8601 date item) but got \"$value\""
    }
    return $value
}

proc ::ooxml::docx::lib::ST_DecimalNumber {value} {
    if {![string is integer -strict $value]} {
        error "expected integer but got \"$value\""
    }
    return $value
}

proc ::ooxml::docx::lib::ST_DecimalNumberOrPercent {value} {
    if {[string is integer -strict $value]} {
        return $value
    }
    if {![regexp -- {-?[0-9]+(\.[0-9]+)?%} $value]} {
        error "expected integer or percent value but got \"$value\""
    }
    return $value
}

proc ::ooxml::docx::lib::ST_DocGrid {value} {
    set values {
        default
        lines
        linesAndChars
        snapToChars
    }
    if {$value in $values} {
        return $value
    }
    error "unknown document grid type \"$value\", expected one of\
            [AllowedValues $values]"
}

proc ::ooxml::docx::lib::ST_DocProtect {value} {
    set values {
        none
        readOnly
        comments
        trackedChanges
        forms
    }
    if {$value in $values} {
        return $value
    }
    error "unknown document protection edit value \"$value\", expected one of\
            [AllowedValues $values]"
}

proc ::ooxml::docx::lib::ST_DropCap {value} {
    set values {
        none
        drop
        margin
    }
    if {$value in $values} {
        return $value
    }
    error "unknown dropCap type \"$value\", expected one of\
            [AllowedValues $values]"
}

proc ::ooxml::docx::lib::ST_EdnPos {value} {
    set values {
        sectEnd
        docEnd
    }
    if {$value in $values} {
        return $value
    }
    error "unknown endnote position type \"$value\", expected one of\
            [AllowedValues $values]"
}

proc ::ooxml::docx::lib::ST_EighthPointMeasure {value} {
    if {[string is integer -strict $value] && $value >= 0} {
        return $value
    }
    error "\"$value\" is not a valid measure value - value must be an\
               integer"
}

proc ::ooxml::docx::lib::ST_Emu {value} {
    if {[string is integer -strict $value] && $value >= 0} {
        return $value
    }
    if {![regexp {[0-9]+(\.[0-9]+)?(mm|cm|in|pt|pc|pi)} $value]} {
        error "\"$value\" is not a valid measure value - value must be an\
                   integer or match the regular expression\
                   \[0-9\]+(\.\[0-9\]+)?(mm|cm|in|pt|pc|pi)"
    }
    scan $value "%f%s" value unit
    switch $unit {
        mm {set factor 36000}
        cm {set factor 360000}
        in {set factor 914400}
        pt {set factor 12700}
        pc {set factor 152400}
        pi {set factor 152400}
    }
    return [expr {round($value*$factor)}]
}

proc ::ooxml::docx::lib::ST_FtnPos {value} {
    set values {
        pageBottom
        beneathText
        sectEnd
        docEnd
    }
    if {$value in $values} {
        return $value
    }
    error "unknown footnote position type \"$value\", expected one of\
            [AllowedValues $values]"
}

proc ::ooxml::docx::lib::ST_HeightRule {value} {
    set values {
        auto
        exact
        atLeast
    }
    if {$value in $values} {
        return $value
    }
    error "unknown height rule value \"$value\", expected one of:\
               [AllowedValues $values]"
}

proc ::ooxml::docx::lib::ST_HexColor {value} {
    if {$value eq "auto"} {
        return $value
    }
    if {[string length $value] != 6 || ![string is xdigit $value]} {
        error "invalid color value \"$value\", should be \"auto\" or a hex value in\
                   RRGGBB format."
    }
    return $value
}

proc ::ooxml::docx::lib::ST_HighlightColor {value} {
    set values {
        black
        blue
        cyan
        green
        magenta
        red
        yellow
        white
        darkBlue
        darkCyan
        darkGreen
        darkMagenta
        darkRed
        darkYellow
        darkGray
        lightGray
        none
    }
    if {$value in $values} {
        return $value
    }
    error "unknown highlight color value \"$value\", expected one of:\
               [AllowedValues $values]"
}

proc ::ooxml::docx::lib::ST_Jc {value} {
    set values {
        start
        center
        end
        both
        mediumKashida
        distribute
        numTab
        highKashida
        lowKashida
        thaiDistribute
        left
        right
    }
    if {$value in $values} {
        return $value
    }
    error "unknown align value \"$value\", expected one of:\
               [AllowedValues $values]"
}

proc ::ooxml::docx::lib::ST_JcTable {value} {
    set values {
        center
        end
        left
        right
        start
    }
    if {$value in $values} {
        return $value
    }
    error "unknown table align value \"$value\", expected one of:\
               [AllowedValues $values]"
}

proc ::ooxml::docx::lib::ST_LineSpacingRule {value} {
    set values {
        auto
        exact
        atLeast
    }
    if {$value in $values} {
        return $value
    }
    error "unknown line spacing rule \"$value\", expected one of:\
               [AllowedValues $values]"
}

proc ::ooxml::docx::lib::ST_MeasurementOrPercent {value} {
    if {[string is integer -strict $value]} {
        return $value
    }
    # Percent form (e.g., "50%" or "12.5%") -> integer in 1/50 percent units
    #    100% -> 5000, 50% -> 2500, 12.5% -> 625
    if {[regexp -- {^(-?[0-9]+(\.[0-9]+)?)%$} $value -> num]} {
        return [expr {int(round(double($num) * 50.0))}]
    }
    # Physical measurement -> twips (Word canonical numeric form)
    if {[regexp -- {^-?[0-9]+(\.[0-9]+)?(mm|cm|in|pt|pc|pi)$} $value]} {
        return [::ooxml::docx::lib::ST_TwipsMeasure $value]
    }
    error "\"$value\" is not a valid measure or percent value — expected an\
          integer, a percentage (e.g. 50%), or a unit-suffixed measure\
          (mm|cm|in|pt|pc|pi)."
}

proc ::ooxml::docx::lib::ST_Merge {value} {
    set values {
        continue
        restart
    }
    if {$value in $values} {
        return $value
    }
    error "unknown merge value \"$value\", expected one of:\
               [AllowedValues $values]"
}

proc ::ooxml::docx::lib::ST_NumberFormat {value} {
    set values {
        decimal
        upperRoman
        lowerRoman
        upperLetter
        lowerLetter
        ordinal
        cardinalText
        ordinalText
        hex
        chicago
        ideographDigital
        japaneseCounting
        aiueo
        iroha
        decimalFullWidth
        decimalHalfWidth
        japaneseLegal
        japaneseDigitalTenThousand
        decimalEnclosedCircle
        decimalFullWidth2
        aiueoFullWidth
        irohaFullWidth
        decimalZero
        bullet
        ganada
        chosung
        decimalEnclosedFullstop
        decimalEnclosedParen
        decimalEnclosedCircleChinese
        ideographEnclosedCircle
        ideographTraditional
        ideographZodiac
        ideographZodiacTraditional
        taiwaneseCounting
        ideographLegalTraditional
        taiwaneseCountingThousand
        taiwaneseDigital
        chineseCounting
        chineseLegalSimplified
        chineseCountingThousand
        koreanDigital
        koreanCounting
        koreanLegal
        koreanDigital2
        vietnameseCounting
        russianLower
        russianUpper
        none
        numberInDash
        hebrew1
        hebrew2
        arabicAlpha
        arabicAbjad
        hindiVowels
        hindiConsonants
        hindiNumbers
        hindiCounting
        thaiLetters
        thaiNumbers
        thaiCounting
        bahtText
        dollarText
        custom
    }
    if {$value in $values} {
        return $value
    }
    error "unknown numbering format \"$value\", expected one of\
            [AllowedValues $values]"
}

proc ::ooxml::docx::lib::ST_PageOrientation {value} {
    if {$value ni {landscape portrait}} {
        error "unknown symbol \"$value\", expected \"landscape\"\
                   or \"portrait\""
    }
    return $value
}

proc ::ooxml::docx::lib::ST_PointMeasure {value} {
    if {[string is integer -strict $value] && $value >= 0} {
        return $value
    }
    error "\"$value\" is not a valid measure value - value must be an\
               integer"
}

proc ::ooxml::docx::lib::ST_Proof {value} {
    set values {
        clean
        dirty
    }
    if {$value in $values} {
        return $value
    }
    error "unknown proof value \"$value\", expected one of:\
               [AllowedValues $values]"
}

proc ::ooxml::docx::lib::ST_RelFromH {value} {
    set values {
        margin
        page
        column
        character
        leftMargin
        rightMargin
        insideMargin
        outsideMargin
    }
    if {$value in $values} {
        return $value
    }
    error "unknown horizontal relative from value \"$value\", expected one of:\
               [AllowedValues $values]"
}

proc ::ooxml::docx::lib::ST_RelFromV {value} {
    set values {
        margin
        page
        paragraph
        line
        topMargin
        bottomMargin
        insideMargin
        outsideMargin
    }
    if {$value in $values} {
        return $value
    }
    error "unknown vertical relative from value \"$value\", expected one of:\
               [AllowedValues $values]"
}

proc ::ooxml::docx::lib::ST_RestartNumber {value} {
    set values {
        continuous
        eachSect
        eachPage
    }
    if {$value in $values} {
        return $value
    }
    error "unknown foot-/endnote restart numbering type  \"$value\", expected\
           one of: [AllowedValues $values]"
}

# Convert a number+unit to twips (1pt=20 twips).
proc ::ooxml::docx::lib::_MeasureToTwips {value signed} {
    set value [string trim $value]
    if {$signed} {
        if {[string is integer -strict $value]} {return $value}
        if {![regexp {^(-?[0-9]+(?:\.[0-9]+)?)(mm|cm|in|pt|pc|pi)$} $value \
                  > num unit]} {
            error "\"$value\" is not a valid measure (int twips or\
                  number+unit: mm|cm|in|pt|pc|pi)"
        }
    } else {
        if {[string is integer -strict $value] && $value >= 0} {return $value}
        if {![regexp {^([0-9]+(?:\.[0-9]+)?)(mm|cm|in|pt|pc|pi)$} $value \
                  > num unit]} {
            error "\"$value\" is not a valid measure (non-negative int\
                  twips or number+unit: mm|cm|in|pt|pc|pi)"
        }
    }
    switch $unit {
        mm { set tw [expr {round($num * 1440.0 / 25.4)}] }
        cm { set tw [expr {round($num * 1440.0 / 2.54)}] }
        in { set tw [expr {round($num * 1440.0)}] }
        pt { set tw [expr {round($num * 20.0)}] }
        pc - pi { set tw [expr {round($num * 240.0)}] }
    }
    return $tw
}

proc ::ooxml::docx::lib::ST_SectionMark {value} {
    set values {
        continuous
        evenPage
        nextColumn
        nextPage
        oddPage
    }
    if {$value in $values} {
        return $value
    }
    error "unknown section type \"$value\", expected one of\
            [AllowedValues $values]"
}

proc ::ooxml::docx::lib::ST_Shd {value} {
    set values {
        nil
        clear
        solid
        horzStripe
        vertStripe
        reverseDiagStripe
        diagStripe
        horzCross
        diagCross
        thinHorzStripe
        thinVertStripe
        thinReverseDiagStripe
        thinDiagStripe
        thinHorzCross
        thinDiagCross
        pct5
        pct10
        pct12
        pct15
        pct20
        pct25
        pct30
        pct35
        pct37
        pct40
        pct45
        pct50
        pct55
        pct60
        pct62
        pct65
        pct70
        pct75
        pct80
        pct85
        pct87
        pct90
        pct95
    }
    if {$value in $values} {
        return $value
    }
    error "unknown shading pattern \"$value\", expected one of\
            [AllowedValues $values]"
}

proc ::ooxml::docx::lib::ST_TwipsMeasure {value} {
    return [::ooxml::docx::lib::_MeasureToTwips $value 0]
}

proc ::ooxml::docx::lib::ST_SignedTwipsMeasure {value} {
    return [::ooxml::docx::lib::_MeasureToTwips $value 1]
}

# Half-points (hps). Accept integer hps directly (e.g., 36) *or* a
# number+unit (e.g., 18pt, 1in, 3cm).
proc ::ooxml::docx::lib::ST_HpsMeasure {value} {
    if {[string is integer -strict $value] && $value >= 0} {
        return $value
    }
    set tw [::ooxml::docx::lib::ST_TwipsMeasure $value]  ;# ensures '18pt' -> 360
    return [expr {int(round($tw / 10.0))}]               ;# 360 twips -> 36 hps
}

proc ::ooxml::docx::lib::ST_TabJc {value} {
    set values {
        clear
        start
        center
        end
        decimal
        bar
        num
        left
        right
    }
    if {$value in $values} {
        return $value
    }
    error "unknown tab stop type \"$value\", expected one of\
            [AllowedValues $values]"
}

proc ::ooxml::docx::lib::ST_TabTlc {value} {
    set values {
        none
        dot
        hyphen
        underscore
        heavy
        middleDot
    }
    if {$value in $values} {
        return $value
    }
    error "unknown tab fill type \"$value\", expected one of\
            [AllowedValues $values]"
}

proc ::ooxml::docx::lib::ST_TblLayoutType {value} {
    set values {
        fixed
        autofit
    }
    if {$value in $values} {
        return $value
    }
    error "unknown table layout type \"$value\", expected one of\
            [AllowedValues $values]"
}

proc ::ooxml::docx::lib::ST_TblWidth {value} {
    set values {
        nil
        pct
        percent
        dxa
        measure
        auto
    }
    if {$value in $values} {
        switch $value {
            "percent" {return pct}
            "measure" {return dxa}
            default {return $value}
        }
    }
    error "unknown table width value type \"$value\", expected one of\
            [AllowedValues $values]"
}

proc ::ooxml::docx::lib::ST_TextAnchoringType {value} {
    set values {
        t
        ctr
        b
        just
        dist
    }
    if {$value in $values} {
        return $value
    }
    error "unknown text anchoring type \"$value\", expected one of\
           [AllowedValues $values]"
}

proc ::ooxml::docx::lib::ST_TextDirection {value} {
    set values {
        btLr
        lr
        lrTb
        lrTbV
        lrV
        rl
        rlV
        tb
        tbLrV
        tbRl
        tbRlV
        tbV
    }
    if {$value in $values} {
        return $value
    }
    error "unknown TextDirection value \"$value\", expected one of\
            [AllowedValues $values]"
}

proc ::ooxml::docx::lib::ST_TextHorzOverflowType {value} {
    set values {
        overflow
        clip
    }
    if {$value in $values} {
        return $value
    }
    error "unknown text horizontal overflow type \"$value\", expected one of\
           [AllowedValues $values]"
}

proc ::ooxml::docx::lib::ST_TextVerticalType {value} {
    set values {
        horz
        vert
        vert270
        wordArtVert
        eaVert
        mongolianVert
        wordArtVertRtl
    }
    if {$value in $values} {
        return $value
    }
    error "unknown text vertical type \"$value\", expected one of\
           [AllowedValues $values]"
}

proc ::ooxml::docx::lib::ST_TextVertOverflowType {value} {
    set values {
        overflow
        ellipsis
        clip
    }
    if {$value in $values} {
        return $value
    }
    error "unknown text vertical overflow type \"$value\", expected one of\
           [AllowedValues $values]"
}

proc ::ooxml::docx::lib::ST_TextWrappingType {value} {
    set values {
        none
        square
    }
    if {$value in $values} {
        return $value
    }
    error "unknown text wrapping type \"$value\", expected one of\
           [AllowedValues $values]"
}

proc ::ooxml::docx::lib::ST_Underline {value} {
    set values {
        single
        words
        double
        thick
        dotted
        dottedHeavy
        dash
        dashedHeavy
        dashLong
        dashLongHeavy
        dotDash
        dashDotHeavy
        dotDotDash
        dashDotDotHeavy
        wave
        wavyHeavy
        wavyDouble
        none
    }
    if {$value ni $values} {
        error "unknown underline value \"$value\", expected one of\
                  [AllowedValues $values]"
    }
    return $value
}

proc ::ooxml::docx::lib::ST_VerticalAlignRun {value} {
    set values {
        baseline
        superscript
        subscript
    }
    if {$value in $values} {
        return $value
    }
    error "unknown vertical align value \"$value\", expected one of\
            [AllowedValues $values]"
}

proc ::ooxml::docx::lib::ST_VerticalJc {value} {
    set values {
        top
        center
        both
        bottom
    }
    if {$value in $values} {
        return $value
    }
    error "unknown vertical alignment value \"$value\", expected one of\
            [AllowedValues $values]"
}

proc ::ooxml::docx::lib::ST_View {value} {
    set values {
        none
        print
        outline
        masterPages
        normal
        web
    }
    if {$value in $values} {
        return $value
    }
    error "unknown view value \"$value\", expected one of\
            [AllowedValues $values]"
}

proc ::ooxml::docx::lib::ST_Wrap {value} {
    set values {
        auto
        notBeside
        around
        tight
        through
        none
    }
    if {$value in $values} {
        return $value
    }
    error "unknown wrap type \"$value\", expected one of\
            [AllowedValues $values]"
}

proc ::ooxml::docx::lib::ST_WrapText {value} {
    set values {
        bothSides
        left
        right
        largest
    }
    if {$value in $values} {
        return $value
    }
    error "unknown wrapText value \"$value\", expected one of\
            [AllowedValues $values]"
}

proc ::ooxml::docx::lib::ST_XAlign {value} {
    set values {
        left
        center
        right
        inside
        outside
    }
    if {$value in $values} {
        return $value
    }
    error "unknown xAlign type \"$value\", expected one of\
            [AllowedValues $values]"
}

proc ::ooxml::docx::lib::ST_YAlign {value} {
    set values {
        inline
        top
        center
        bottom
        inside
        outside
    }
    if {$value in $values} {
        return $value
    }
    error "unknown yAlign type \"$value\", expected one of\
            [AllowedValues $values]"
}

proc ::ooxml::docx::lib::ST_Zoom {value} {
    set values {
        none
        fullPage
        bestFit
        textFit
    }
    if {$value in $values} {
        return $value
    }
    error "unknown zoom type \"$value\", expected one of\
            [AllowedValues $values]"
}

proc ::ooxml::docx::lib::W3CDTF {value} {
    if {[catch {
        set value [clock format [clock scan $value] -format %Y-%m-%dT%H:%M:%SZ -gmt 1]
    }]} {
        error "invalid datetime value \"$value\", expected everything which is\
                accepted by \[clock scan\]"
    }
    return $value
}

# OMML (Office Math) builder methods, contributed by Miguel Bañón
proc ::ooxml::docx::lib::ST_MJc {value} {
    set values {
        left
        center
        right
        centerGroup
    }
    if {$value in $values} {
        return $value
    }
    error "unknown math justification \"$value\", expected one of\
           [AllowedValues $values]"
}

proc ::ooxml::docx::lib::ST_FType {value} {
    set values {
        bar
        lin
        noBar
        skw
    }
    if {$value in $values} {
        return $value
    }
    error "unknown fraction type \"$value\", expected one of\
           [AllowedValues $values]"
}

proc ::ooxml::docx::lib::ST_LimLoc {value} {
    set values {
        undOvr
        subSup
    }
    if {$value in $values} {
        return $value
    }
    error "unknown limit location \"$value\", expected one of\
           [AllowedValues $values]"
}

proc ::ooxml::docx::lib::ST_MathStyle {value} {
    set values {
        p
        b
        i
        bi
    }
    if {$value in $values} {return $value}
    error "unknown math style \"$value\", expected one of\
           [AllowedValues $values]"
}

proc ::ooxml::docx::lib::ST_MScript {value} {
    set values {
        roman
        script
        fraktur
        double-struck
        sans-serif
        monospace
    }
    if {$value in $values} {return $value}
    error "unknown math script \"$value\", expected one of\
           [AllowedValues $values]"
}

proc ::ooxml::docx::lib::ST_TopBot {value} {
    set values {
        top
        bot
    }
    if {$value in $values} {
        return $value
    }
    error "unknown top/bottom value \"$value\", expected one of\
           [AllowedValues $values]"
}

proc ::ooxml::docx::lib::ST_Shp {value} {
    set values {
        centered
        match
    }
    if {$value in $values} {
        return $value
    }
    error "unknown delimiter shape \"$value\", expected one of\
           [AllowedValues $values]"
}

proc ::ooxml::docx::lib::ST_BaseJc {value} {
    set values {
        top
        center
        bottom
    }
    if {$value in $values} {
        return $value
    }
    error "unknown matrix base justification \"$value\", expected one of\
           [AllowedValues $values]"
}

proc ::ooxml::docx::lib::ST_McJc {value} {
    set values {
        left
        center
        right
    }
    if {$value in $values} {
        return $value
    }
    error "unknown matrix column justification \"$value\", expected one of\
           [AllowedValues $values]"
}

proc ::ooxml::docx::lib::ST_Integer255 {value} {
    if {$value eq ""} {return ""}
    if {[string is integer -strict $value] && $value >= 1 && $value <= 255} {
        return $value
    }
    error "expected integer 1..255, got \"$value\""
}

proc ::ooxml::docx::lib::XSD_base64Binary {value} {
    if {[package vsatisfies [package present tdom] 0.9.7-]} {
        if {[::tdom::type::base64 $value]} {
            return $value
        }
        error "expected base64 encoded data, got \"$value\""
    } else {
        return $value
    }
}

proc ::ooxml::docx::lib::XSD_hexBinary {value} {
    if {[package vsatisfies [package present tdom] 0.9.7-]} {
        if {[::tdom::type::hexBinary $value]} {
            return $value
        }
        error "expected hex binary data, got \"$value\""
    } else {
        return $value
    }
}

package provide ooxml::docx::lib 0.6
