ooxml/000755 000765 000024 00000000000 15221665317 012320 5ustar00alexstaff000000 000000 ooxml/pkgIndex.tcl.in000644 000765 000024 00000000514 15213015413 015165 0ustar00alexstaff000000 000000 # # Tcl package index file # package ifneeded @PACKAGE_NAME@ @PACKAGE_VERSION@ [list source [file join $dir @PACKAGE_NAME@.tcl]] package ifneeded @PACKAGE_NAME@::docx 0.6 [list source [file join $dir @PACKAGE_NAME@-docx.tcl]] package ifneeded @PACKAGE_NAME@::docx::lib 0.6 [list source [file join $dir @PACKAGE_NAME@-docx-lib.tcl]] ooxml/ooxml-docx-lib.tcl000664 000765 000024 00000203303 15217572310 015657 0ustar00alexstaff000000 000000 # # 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 ooxml/ooxml.tcl000644 000765 000024 00000474415 15221665112 014172 0ustar00alexstaff000000 000000 # # ooxml ECMA-376 Office Open XML File Formats # https://www.ecma-international.org/publications/standards/Ecma-376.htm # # Copyright (C) 2018-2025 Alexander Schoepe, Bochum, DE, # Copyright (C) 2019-2025 Rolf Ade, DE # Copyright (C) 2023-2024 Harald Oehlmann, 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. # # # INDEX and ID are zero based # # # BORDERLINESTYLE # dashDot | dashDotDot | dashed | dotted | double | hair | medium | # mediumDashDot | mediumDashDotDot | mediumDashDotDot | none | slantDashDot | thick | thin # # COLOR # 0-65 # Aqua | Black | Blue | BlueRomance | Canary | CarnationPink | Citrus | Cream | DarkSlateBlue | DeepSkyBlue | # Eucalyptus | Fuchsia | Gray | Green | Karaka | LavenderBlue | LightCoral | LightCyan | LightSkyBlue | Lime | # Lipstick | Maroon | Mauve | MediumTurquoise | Myrtle | Navy | NavyBlue | NightRider | Nobel | Olive | # OrangePeel | PeachOrange | Portage | PrussianBlue | Purple | Red | RoyalBlue | SaddleBrown | SafetyOrange | # Scampi | Silver | TangerineYellow | Teal | White | Yellow | # SystemBackground | SystemForeground # RGB # ARGB # # DEGREE # 0-360 # # DIAGONALDIRECTION # up | down # # HORIZONTAL # left | center | right # # PATTERNTYPE # darkDown | darkGray | darkGrid | darkHorizontal | darkTrellis | darkUp | darkVertical | # gray0625 | gray125 | lightDown | lightGray | # lightGrid | lightHorizontal | lightTrellis | lightUp | lightVertical | mediumGray | none | solid # # VERTICAL # top | center | bottom # # # ::ooxml::Default name value # name = path # # # ::ooxml::RowColumnToString rowcol # return name # # # ::ooxml::StringToRowColumn name # return rowcol # # # ::ooxml::IndexFix index fix # return fixedIndex # # # ::ooxml::CalcColumnWidth numberOfCharacters {maximumDigitWidth 7} {pixelPadding 5} # return width # # # ::ooxml::xl_sheets file # return sheetInformation # # # ::ooxml::xl_read file # -valuesonly -keylist -sheets PATTERN -sheetnames PATTERN -datefmt FORMAT # return workbookData # # # ::ooxml::xl_write # # constructor args # -creator CREATOR # -created UTC-TIMESTAMP # -modifiedby NAME # -modified UTC-TIMESTAMP # -application NAME # return class # # method numberformat args # -format FORMAT -general -date -time -datetime -iso8601 -number -decimal -red -separator -fraction -scientific -percent -text -string # -tag NAME # return NUMFMTID # # method defaultdatestyle STYLEID # # method font args # -list -name NAME -family FAMILY -size SIZE -color COLOR -scheme SCHEME -bold -italic -underline -color COLOR -tag NAME # return FONTID # # method fill args # -list -patterntype PATTERNTYPE -fgcolor COLOR -bgcolor COLOR -tag NAME # return FILLID # # method border args # -list -leftstyle BORDERLINESTYLE -leftcolor COLOR -rightstyle BORDERLINESTYLE -rightcolor COLOR -topstyle BORDERLINESTYLE -topcolor COLOR # -bottomstyle BORDERLINESTYLE -bottomcolor COLOR -diagonalstyle BORDERLINESTYLE -diagonalcolor COLOR -diagonaldirection DIAGONALDIRECTION # -tag NAME # return BORDERID # # method style args # -list -numfmt NUMFMTID -font FONTID -fill FILLID -border BORDERID -xf XFID -horizontal HORIZONTAL -vertical VERTICAL -rotate DEGREE -wrap # -tag NAME # return STYLEID # # method worksheet name # return SHEETID # # method column sheet args # -index INDEX -to INDEX -width WIDTH -style STYLEID -bestfit -customwidth -string -nozero -calcfit # autoincrement of column if INDEX not applied # return column # # method row sheet args # -index INDEX -height HEIGHT # autoincrement of row if INDEX not applied # return row # # method cell sheet {data {}} args # -index INDEX -style STYLEID -formula FORMULA -formulaidx SHARE -formularef INDEX:INDEX -string -nozero -height HEIGHT # autoincrement of column if INDEX not applied # return row,column # # method pageSetup sheet args # -orientation (landscape|portrait) # -scale Print scaling. The standard say this attribute is restricted # to values ranging from 10 to 400. Enforced is a positiv integer. # # method pageMarginsDefault args # -left inch -right inch -top inch -bottom inch -header inch -footer inch # # method pageMargins sheet args # -left inch -right inch -top inch -bottom inch -header inch -footer inch # # method autofilter sheet indexFrom indexTo # # method freeze sheet index # # method printarea sheet indexFrom indexTo # # method presetstyles # # method presetsheets # # method view args # -avtivetab TAB -x TWIPS -y TWIPS -height TWIPS -width TWIPS -list # # method write filename # # # ::ooxml::tablelist_to_xl lb args # -callback CALLBACK -path PATH -file FILENAME -creator CREATOR -name NAME -rootonly -addtimestamp # Callback arguments # spreadsheet sheet maxcol column title width align sortmode hide # package require Tcl 8.6.7- package require tdom 0.9.0- package require msgcat namespace eval ::ooxml { namespace export xl_sheets xl_read xl_write variable defaults variable initNodeCmds variable predefNumFmts variable predefColors variable predefColorsName variable predefColorsARBG variable predefBorderLineStyles variable predefPatternType variable xmlns variable pkgPath # Initialize to the empty string to determinate method on first usage of a # zip read function. variable zipAccessMethod {} # Cache for the probed legacy zip backend (tcl9 zipfs, tcllib or tclvfs), # used when the built-in zlib based reader cannot handle an archive. variable zipLegacyMethod {} set defaults(path) {.} set defaults(numFmts,start) 166 set defaults(cols,width) 10.83203125 # predefined formats array set predefNumFmts { 0 {dt 0 fmt {General}} 1 {dt 0 fmt {0}} 2 {dt 0 fmt {0.00}} 3 {dt 0 fmt {#,##0}} 4 {dt 0 fmt {#,##0.00}} 9 {dt 0 fmt {0%}} 10 {dt 0 fmt {0.00%}} 11 {dt 0 fmt {0.00E+00}} 12 {dt 0 fmt {#\ ?/?}} 13 {dt 0 fmt {#\ ??/??}} 14 {dt 1 fmt {mm-dd-yy}} 15 {dt 1 fmt {d-mmm-yy}} 16 {dt 1 fmt {d-mmm}} 17 {dt 1 fmt {mmm-yy}} 18 {dt 1 fmt {h:mm\ AM/PM}} 19 {dt 1 fmt {h:mm:ss\ AM/PM}} 20 {dt 1 fmt {h:mm}} 21 {dt 1 fmt {h:mm:ss}} 22 {dt 1 fmt {m/d/yy h:mm}} 37 {dt 0 fmt {#,##0\ ;(#,##0)}} 38 {dt 0 fmt {#,##0\ ;[Red](#,##0)}} 39 {dt 0 fmt {#,##0.00;(#,##0.00)}} 40 {dt 0 fmt {#,##0.00;[Red](#,##0.00)}} 45 {dt 1 fmt {mm:ss}} 46 {dt 1 fmt {[h]:mm:ss}} 47 {dt 1 fmt {mmss.0}} 48 {dt 0 fmt {##0.0E+0}} 49 {dt 0 fmt {@}} } array set predefColors { 0 {argb 00000000 name Black} 1 {argb 00FFFFFF name White} 2 {argb 00FF0000 name Red} 3 {argb 0000FF00 name Lime} 4 {argb 000000FF name Blue} 5 {argb 00FFFF00 name Yellow} 6 {argb 00FF00FF name Fuchsia} 7 {argb 0000FFFF name Aqua} 8 {argb 00000000 name Black} 9 {argb 00FFFFFF name White} 10 {argb 00FF0000 name Red} 11 {argb 0000FF00 name Lime} 12 {argb 000000FF name Blue} 13 {argb 00FFFF00 name Yellow} 14 {argb 00FF00FF name Fuchsia} 15 {argb 0000FFFF name Aqua} 16 {argb 00800000 name Maroon} 17 {argb 00008000 name Green} 18 {argb 00000080 name Navy} 19 {argb 00808000 name Olive} 20 {argb 00800080 name Purple} 21 {argb 00008080 name Teal} 22 {argb 00C0C0C0 name Silver} 23 {argb 00808080 name Gray} 24 {argb 009999FF name Portage} 25 {argb 00993366 name Lipstick} 26 {argb 00FFFFCC name Cream} 27 {argb 00CCFFFF name LightCyan} 28 {argb 00660066 name Purple} 29 {argb 00FF8080 name LightCoral} 30 {argb 000066CC name NavyBlue} 31 {argb 00CCCCFF name LavenderBlue} 32 {argb 00000080 name Navy} 33 {argb 00FF00FF name Fuchsia} 34 {argb 00FFFF00 name Yellow} 35 {argb 0000FFFF name Aqua} 36 {argb 00800080 name Purple} 37 {argb 00800000 name Maroon} 38 {argb 00008080 name Teal} 39 {argb 000000FF name Blue} 40 {argb 0000CCFF name DeepSkyBlue} 41 {argb 00CCFFFF name LightCyan} 42 {argb 00CCFFCC name BlueRomance} 43 {argb 00FFFF99 name Canary} 44 {argb 0099CCFF name LightSkyBlue} 45 {argb 00FF99CC name CarnationPink} 46 {argb 00CC99FF name Mauve} 47 {argb 00FFCC99 name PeachOrange} 48 {argb 003366FF name RoyalBlue} 49 {argb 0033CCCC name MediumTurquoise} 50 {argb 0099CC00 name Citrus} 51 {argb 00FFCC00 name TangerineYellow} 52 {argb 00FF9900 name OrangePeel} 53 {argb 00FF6600 name SafetyOrange} 54 {argb 00666699 name Scampi} 55 {argb 00969696 name Nobel} 56 {argb 00003366 name PrussianBlue} 57 {argb 00339966 name Eucalyptus} 58 {argb 00003300 name Myrtle} 59 {argb 00333300 name Karaka} 60 {argb 00993300 name SaddleBrown} 61 {argb 00993366 name Lipstick} 62 {argb 00333399 name DarkSlateBlue} 63 {argb 00333333 name NightRider} 64 {argb {} name SystemForeground} 65 {argb {} name SystemBackground} } set predefColorsName {} set predefColorsARBG {} foreach idx [lsort -integer [array names predefColors]] { lappend predefColorsName [dict get $predefColors($idx) name] lappend predefColorsARBG [dict get $predefColors($idx) argb] } set predefPatternType { darkDown darkGray darkGrid darkHorizontal darkTrellis darkUp darkVertical gray0625 gray125 lightDown lightGray lightGrid lightHorizontal lightTrellis lightUp lightVertical mediumGray none solid } set predefBorderLineStyles { dashDot dashDotDot dashed dotted double hair medium mediumDashDot mediumDashDotDot mediumDashDotDot none slantDashDot thick thin } array set xmlns { M http://schemas.openxmlformats.org/spreadsheetml/2006/main CT http://schemas.openxmlformats.org/package/2006/content-types EP http://schemas.openxmlformats.org/officeDocument/2006/extended-properties PR http://schemas.openxmlformats.org/package/2006/relationships a http://schemas.openxmlformats.org/drawingml/2006/main cp http://schemas.openxmlformats.org/package/2006/metadata/core-properties dc http://purl.org/dc/elements/1.1/ dcmitype http://purl.org/dc/dcmitype/ dcterms http://purl.org/dc/terms/ mc http://schemas.openxmlformats.org/markup-compatibility/2006 r http://schemas.openxmlformats.org/officeDocument/2006/relationships vt http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes x14ac http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac x16r2 http://schemas.microsoft.com/office/spreadsheetml/2015/02/main xsi http://www.w3.org/2001/XMLSchema-instance } # ar - Arabic - العربية msgcat::mcset ar LANGUAGE \u0627\u0644\u0639\u0631\u0628\u064a\u0629 msgcat::mcset ar Book \u0627\u0644\u0643\u062a\u0627\u0628 msgcat::mcset ar Worksheets "\u0623\u0648\u0631\u0627\u0642 \u0627\u0644\u0639\u0645\u0644" msgcat::mcset ar Sheet \u0627\u0644\u0648\u0631\u0642\u0629 # cs - Czech - čeština, český jazyk msgcat::mcset cs LANGUAGE \u010de\u0161tina msgcat::mcset cs Book Ses\u030cit msgcat::mcset cs Worksheets Listy msgcat::mcset cs Sheet List # da - Danish - dansk msgcat::mcset da LANGUAGE dansk msgcat::mcset da Book Mappe msgcat::mcset da Worksheets Regneark msgcat::mcset da Sheet Ark # de - German - Deutsch msgcat::mcset de LANGUAGE Deutsch msgcat::mcset de Book Mappe msgcat::mcset de Worksheets Arbeitsbl\u00e4tter msgcat::mcset de Sheet Blatt msgcat::mcset de {Tablelist does not exists!} {Die Tablelist existiert nicht!} msgcat::mcset de {No file selected!} "Keine Datei ausgew\u00e4hlt!" # el - Greek - ελληνικά msgcat::mcset el LANGUAGE \u03b5\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u03ac msgcat::mcset el Book \u0392\u03b9\u03b2\u03bb\u03b9\u0301\u03bf msgcat::mcset el Worksheets "\u03a6\u03cd\u03bb\u03bb\u03b1 \u03b5\u03c1\u03b3\u03b1\u03c3\u03af\u03b1\u03c2" msgcat::mcset el Sheet \u03a6\u03cd\u03bb\u03bb\u03bf # en - English - English msgcat::mcset en LANGUAGE English msgcat::mcset en Book Book msgcat::mcset en Worksheets Worksheets msgcat::mcset en Sheet Sheet msgcat::mcset en {Tablelist does not exists!} {Tablelist does not exists!} msgcat::mcset en {No file selected!} {No file selected!} # es - Spanish - Español msgcat::mcset es LANGUAGE Espa\u00f1ol msgcat::mcset es Book Libro msgcat::mcset es Worksheets "Hojas de c\u00e1lculo" msgcat::mcset es Sheet Hoja msgcat::mcset es {Tablelist does not exists!} "\u00a1Tablelist no existe!" msgcat::mcset es {No file selected!} "\u00a1Ning\u00fan archivo seleccionado!" # fi - Finnish - suomi, suomen kieli msgcat::mcset fi LANGUAGE suomi msgcat::mcset fi Book Tyo\u0308kirja msgcat::mcset fi Worksheets Laskentataulukot msgcat::mcset fi Sheet Taulukko # fr - French - français, langue française msgcat::mcset fr LANGUAGE fran\u00e7ais msgcat::mcset fr Book Classeur msgcat::mcset fr Worksheets "Feuilles de calcul" msgcat::mcset fr Sheet Feuil msgcat::mcset fr {Tablelist does not exists!} {Tablelist n'existe pas!} msgcat::mcset fr {No file selected!} "Aucun fichier s\u00e9lectionn\u00e9!" # he - Hebrew - עברית msgcat::mcset he LANGUAGE \u05e2\u05d1\u05e8\u05d9\u05ea msgcat::mcset he Book \u05d7\u05d5\u05d1\u05e8\u05ea msgcat::mcset he Worksheets "\u05d2\u05dc\u05d9\u05d5\u05e0\u05d5\u05ea \u05e2\u05d1\u05d5\u05d3\u05d4" msgcat::mcset he Sheet \u05d2\u05d9\u05dc\u05d9\u05d5\u05df # hu - Hungarian - magyar msgcat::mcset hu LANGUAGE magyar msgcat::mcset hu Book Munkafu\u0308zet msgcat::mcset hu Worksheets Munkalapok msgcat::mcset hu Sheet Munkalap # it - italian - Italiano msgcat::mcset it LANGUAGE Italiano msgcat::mcset it Book Cartel msgcat::mcset it Worksheets "Fogli di lavoro" msgcat::mcset it Sheet Foglio msgcat::mcset it {Tablelist does not exists!} {Tablelist non esiste!} msgcat::mcset it {No file selected!} {Nessun file selezionato!} # ja - Japanese - 日本語 (にほんご) msgcat::mcset ja LANGUAGE "\u65e5\u672c\u8a9e (\u306b\u307b\u3093\u3054)" msgcat::mcset ja Book Book msgcat::mcset ja Worksheets \u30ef\u30fc\u30af\u30b7\u30fc\u30c8 msgcat::mcset ja Sheet Sheet # ko - Korean - 한국어 msgcat::mcset ko LANGUAGE "\ud55c\uad6d\uc5b4" msgcat::mcset ko Book "\u1110\u1169\u11bc\u1112\u1161\u11b8 \u1106\u116e\u11ab\u1109\u1165" msgcat::mcset ko Worksheets \uc6cc\ud06c\uc2dc\ud2b8 msgcat::mcset ko Sheet \uc2dc\ud2b8 # nl - Dutch, Flemish - Nederlands, Vlaams msgcat::mcset nl LANGUAGE Nederlands msgcat::mcset nl Book Map msgcat::mcset nl Worksheets Werkbladen msgcat::mcset nl Sheet Blad msgcat::mcset nl {Tablelist does not exists!} {Tablelist bestaat niet!} msgcat::mcset nl {No file selected!} {Geen bestand geselecteerd!} # no - Norwegian - Norsk msgcat::mcset no LANGUAGE Norsk msgcat::mcset no Book Bok msgcat::mcset no Worksheets Regneark msgcat::mcset no Sheet Ark # pl - Polish - język polski, polszczyzna msgcat::mcset pl LANGUAGE polszczyzna msgcat::mcset pl Book Skoroszyt msgcat::mcset pl Worksheets Arkusze msgcat::mcset pl Sheet Arkusz # pt - Portuguese - Português msgcat::mcset pt LANGUAGE Portugu\u00eas msgcat::mcset pt Book Livro msgcat::mcset pt Worksheets "Folhas de C\u00e1lculo" msgcat::mcset pt Sheet Folha # ru - Russian - русский msgcat::mcset ru LANGUAGE \u0440\u0443\u0441\u0441\u043a\u0438\u0439 msgcat::mcset ru Book \u041a\u043d\u0438\u0433\u0430 msgcat::mcset ru Worksheets \u041b\u0438\u0441\u0442\u044b msgcat::mcset ru Sheet \u041b\u0438\u0441\u0442 # sl - Slovenian - Slovenski Jezik, Slovenščina msgcat::mcset sl LANGUAGE Sloven\u0161\u010dina msgcat::mcset sl Book Zos\u030cit msgcat::mcset sl Worksheets H\u00e1rky msgcat::mcset sl Sheet H\u00e1rok # sv - Swedish - Svenska msgcat::mcset sv LANGUAGE Svenska msgcat::mcset sv Book Bok msgcat::mcset sv Worksheets Kalkylblad msgcat::mcset sv Sheet Blad # th - Thai - ไทย msgcat::mcset th LANGUAGE \u0e44\u0e17\u0e22 msgcat::mcset th Book \u0e2a\u0e21\u0e38\u0e14\u0e07\u0e32\u0e19 msgcat::mcset th Worksheets \u0e40\u0e27\u0e34\u0e23\u0e4c\u0e01\u0e0a\u0e35\u0e15 msgcat::mcset th Sheet \u0e41\u0e1c\u0e48\u0e19\u0e07\u0e32\u0e19 # tr - Turkish - Türkçe msgcat::mcset tr LANGUAGE T\u00fcrk\u00e7e msgcat::mcset tr Book Kitap msgcat::mcset tr Worksheets "\u00c7al\u0131\u015fma Sayfalar\u0131" msgcat::mcset tr Sheet Sayfa # zh - Chinese - 中文 (Zhōngwén), 汉语, 漢語 msgcat::mcset zh LANGUAGE \u4e2d\u6587 msgcat::mcset zh Book \u5de5\u4f5c\u7c3f msgcat::mcset zh Worksheets \u5de5\u4f5c\u8868 msgcat::mcset zh Sheet \u5de5\u4f5c\u8868 } # ooxml::timet_to_dos # # Convert a unix timestamp into a DOS timestamp for ZIP times. # # DOS timestamps are 32 bits split into bit regions as follows: # 24 16 8 0 # +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ # |Y|Y|Y|Y|Y|Y|Y|m| |m|m|m|d|d|d|d|d| |h|h|h|h|h|m|m|m| |m|m|m|s|s|s|s|s| # +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ # # From tcllib / zipfile::mkzip proc ::ooxml::timet_to_dos {time_t} { set s [clock format $time_t -format {%Y %m %e %k %M %S}] scan $s {%d %d %d %d %d %d} year month day hour min sec expr {(($year-1980) << 25) | ($month << 21) | ($day << 16) | ($hour << 11) | ($min << 5) | ($sec >> 1)} } # ooxml::add_str_to_archive -- # # Add a string as a single file with string as content with # argument path to a zip archive. The zipchan channel must # already be open and binary. The return value is the central # directory record that will need to be used when finalizing # the zip archive. # # Derived from tcllib / zipfile::mkzip::add_file_to_archive proc ::ooxml::add_str_to_archive {zipchan path data {comment {}} {isBin 0}} { set mtime [timet_to_dos [clock seconds]] set utfpath [encoding convertto utf-8 $path] set utfcomment [encoding convertto utf-8 $comment] set flags [expr {(1<<11)}] ;# utf-8 comment and path set method 0 ;# store 0, deflate 8 set attr 0 ;# text or binary (default binary) set version 20 ;# minumum version req'd to extract set extra {} set crc 0 set size 0 set csize 0 set seekable [expr {[tell $zipchan] != -1}] set attrex 0x81b60020 ;# 0o100666 (-rw-rw-rw-) if {$isBin} { set utfdata $data } else { set utfdata [encoding convertto utf-8 $data] } set size [string length $utfdata] set offset [tell $zipchan] set local [binary format a4sssiiiiss PK\03\04 $version $flags $method $mtime $crc $csize $size [string length $utfpath] [string length $extra]] append local $utfpath $extra puts -nonewline $zipchan $local set crc [::zlib crc32 $utfdata] set cdata [::zlib deflate $utfdata] if {[string length $cdata] < $size} { set method 8 set utfdata $cdata } set csize [string length $utfdata] puts -nonewline $zipchan $utfdata # update the header set local [binary format a4sssiiii PK\03\04 $version $flags $method $mtime $crc $csize $size] set current [tell $zipchan] seek $zipchan $offset puts -nonewline $zipchan $local seek $zipchan $current set hdr [binary format a4ssssiiiisssssii PK\01\02 0x0317 $version $flags $method $mtime $crc $csize $size [string length $utfpath] [string length $extra] [string length $utfcomment] 0 $attr $attrex $offset] append hdr $utfpath $extra $utfcomment return $hdr } proc ::ooxml::add_file_with_path_to_archive {zipchan path filepath {comment ""}} { set fullpath $filepath set mtime [timet_to_dos [file mtime $fullpath]] if {[file isdirectory $fullpath]} { append path / } set utfpath [encoding convertto utf-8 $path] set utfcomment [encoding convertto utf-8 $comment] set flags [expr {(1<<11)}] ;# utf-8 comment and path set method 0 ;# store 0, deflate 8 set attr 0 ;# text or binary (default binary) set version 20 ;# minumum version req'd to extract set extra "" set crc 0 set size 0 set csize 0 set data "" set seekable [expr {[tell $zipchan] != -1}] if {[file isdirectory $fullpath]} { set attrex 0x41ff0010 ;# 0o040777 (drwxrwxrwx) } elseif {[file executable $fullpath]} { set attrex 0x81ff0080 ;# 0o100777 (-rwxrwxrwx) } else { set attrex 0x81b60020 ;# 0o100666 (-rw-rw-rw-) if {[file extension $fullpath] in {".tcl" ".txt" ".c"}} { set attr 1 ;# text } } if {[file isfile $fullpath]} { set size [file size $fullpath] if {!$seekable} {set flags [expr {$flags | (1 << 3)}]} } set offset [tell $zipchan] set local [binary format a4sssiiiiss PK\03\04 \ $version $flags $method $mtime $crc $csize $size \ [string length $utfpath] [string length $extra]] append local $utfpath $extra puts -nonewline $zipchan $local if {[file isfile $fullpath]} { # If the file is under 2MB then zip in one chunk, otherwize we use # streaming to avoid requiring excess memory. This helps to prevent # storing re-compressed data that may be larger than the source when # handling PNG or JPEG or nested ZIP files. if {$size < 0x00200000} { set fin [::open $fullpath rb] set data [::read $fin] set crc [::zlib crc32 $data] set cdata [::zlib deflate $data] if {[string length $cdata] < $size} { set method 8 set data $cdata } close $fin set csize [string length $data] puts -nonewline $zipchan $data } else { set method 8 set fin [::open $fullpath rb] set zlib [::zlib stream deflate] while {![eof $fin]} { set data [read $fin 4096] set crc [zlib crc32 $data $crc] $zlib put $data if {[string length [set zdata [$zlib get]]]} { incr csize [string length $zdata] puts -nonewline $zipchan $zdata } } close $fin $zlib finalize set zdata [$zlib get] incr csize [string length $zdata] puts -nonewline $zipchan $zdata $zlib close } if {$seekable} { # update the header if the output is seekable set local [binary format a4sssiiii PK\03\04 \ $version $flags $method $mtime $crc $csize $size] set current [tell $zipchan] seek $zipchan $offset puts -nonewline $zipchan $local seek $zipchan $current } else { # Write a data descriptor record set ddesc [binary format a4iii PK\7\8 $crc $csize $size] puts -nonewline $zipchan $ddesc } } set hdr [binary format a4ssssiiiisssssii PK\01\02 0x0317 \ $version $flags $method $mtime $crc $csize $size \ [string length $utfpath] [string length $extra]\ [string length $utfcomment] 0 $attr $attrex $offset] append hdr $utfpath $extra $utfcomment return $hdr } proc ::ooxml::Default { name value } { variable defaults switch -- $name { path { set defaults($name) [string trim $value] if {$value eq {}} { set defaults($name) . } } default { } } } proc ::ooxml::ScanDateTime { scan {iso8601 0} } { set d 1 set m 1 set ml {} set y 1970 set H 0 set M 0 set S 0 set F 0 set z {} if {[regexp {^(\d{1,2})\.(\d{1,2})\.(\d{2,4})(?:[ T]|$)(?:(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?(?:([+-])(\d{1,2}):(\d{1,2})|(Z))?)?)?$} $scan all d m y H M S F x a b z] || [regexp {^(\d{2,4})-(\d{2})-(\d{2})(?:[ T]|$)(?:(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?(?:([+-])(\d{2}):(\d{2})|(Z)$)?)?)?$} $scan all y m d H M S F x a b z] || [regexp {^(\d{1,2})-(\w+)-(\d{2,4})(?:[ T]|$)(?:(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?(?:([+-])(\d{1,2}):(\d{1,2})|(Z))?)?)?$} $scan all d ml y H M S F x a b z] || [regexp {^(\d{1,2})/(\d{1,2})/(\d{2,4})(?:[ T]|$)(?:(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?(?:([+-])(\d{1,2}):(\d{1,2})|(Z))?)?)?$} $scan all m d y H M S F x a b z]} { scan $y %u y if {[string is integer -strict $y] && $y >= 0 && $y <= 2038} { switch -- [string tolower $ml] { jan - ene - gen - tam {set m 1} feb - fev - fév - hel {set m 2} mrz - mar - mär - maa {set m 3} apr - avr - abr - huh {set m 4} mai - may - mei - mag - maj - tou {set m 5} jun - jui - giu - kes {set m 6} jul - jui - lug - hei {set m 7} aug - aou - aoû - ago - elo {set m 8} sep - set - syy {set m 9} okt - oct - out - ott - lok {set m 10} nov - mar {set m 11} dez - dec - déc - dic - des - jou {set m 12} default { set m [string trimleft $m 0] } } foreach name {y m d H M S F a b} { upvar 0 $name var set var [string trimleft $var 0] if {![string is integer -strict $var]} { set var 0 } } if {$y < 100} { if {$y < 50} { incr y 2000 } else { incr y 1900 } } if {$y < 1900} { return {} } set Y [format %04u $y] set y [format %02u [expr {$y - int($y / 100) * 100}]] set m [format %02u $m] set d [format %02u $d] set H [format %02u $H] set M [format %02u $M] set S [format %02u $S] if {$z eq {Z} && $Y >= 1970} { set utc [clock scan ${Y}-${m}-${d}T${H}:${M}:${S} -gmt 1] set Y [clock format $utc -format %Y] set y [clock format $utc -format %y] set m [clock format $utc -format %m] set d [clock format $utc -format %d] set H [clock format $utc -format %H] set M [clock format $utc -format %M] set S [clock format $utc -format %S] } if {$iso8601} { return [list ${Y}-${m}-${d}T${H}:${M}:${S}] } return [set ole [expr {[clock scan ${Y}${m}${d}T${H}${M}${S} -gmt 1] / 86400.0 + 25569}]] } } return {} } proc ::ooxml::Column { col } { set name {} while {$col >= 0} { set char [binary format c [expr {($col % 26) + 65}]] set name $char$name set col [expr {$col / 26 -1}] } return $name } proc ::ooxml::RowColumnToString { rowcol } { lassign [split $rowcol ,] row col return [Column $col][incr row 1] } proc ::ooxml::StringToRowColumn { name } { set row 0 set col 0 binary scan [string toupper $name] c* vals foreach val $vals { if {$val < 58} { # 0-9, "0" = 48 set row [expr {$row * 10 + ($val-48)}] } else { # A-Z, "A" = 65 (-1 zero based shift) set col [expr {$col * 26 + ($val-64)}] } } return [incr row -1],[incr col -1] } proc ::ooxml::IndexFix { index {fix {row col}} } { if {[regexp {^([A-Za-z]+)([0-9]+)$} $index all col row]} { if {[string match -nocase {*r*} $fix]} { set col [string cat {$} $col] } if {[string match -nocase {*r*} $fix]} { set row [string cat {$} $row] } return ${col}${row} } else { return $index } } proc ::ooxml::IndexToString { index } { lassign [split $index ,] row col if {[string is integer -strict $row] && [string is integer -strict $col] && $row > -1 && $col > -1} { return [RowColumnToString $index] } else { lassign [split [StringToRowColumn $index] ,] row col if {[string is integer -strict $row] && [string is integer -strict $col] && $row > -1 && $col > -1} { return $index } } return {} } proc ::ooxml::CalcColumnWidth { numberOfCharacters {maximumDigitWidth 7} {pixelPadding 5} } { return [expr {int(($numberOfCharacters * $maximumDigitWidth + $pixelPadding + 0.0) / $maximumDigitWidth * 256.0) / 256.0}] } proc ::ooxml::arrayDeleteSheet { array sheetId args } { upvar $array a array set opts { sheetname 0 } set len [llength $args] set idx 0 for {set idx 0} {$idx < $len} {incr idx} { switch -- [set opt [lindex $args $idx]] { -sheetname { set opts([string range $opt 1 end]) 1 } default { error "unknown option \"$opt\", should be: -sheetname" } } } if {$opts(sheetname)} { foreach sheet $a(sheets) { if {$a($sheet,n) eq $sheetId} { set removeSheet $sheet break } } } else { set removeSheet $sheetId } if {[llength $a(sheets)] > 1} { set removed false foreach sheet [lsort -integer $a(sheets)] { if {!$removed && $sheet == $removeSheet} { array unset a $sheet,* set removed true continue } if {$removed} { set new [expr {$sheet - 1}] foreach src [array names a $sheet,*] { set dst [join [list $new {*}[lrange [split $src ,] 1 end]] ,] set a($dst) $a($src) } array unset a $sheet,* } } if {$removed} { set a(sheets) [lrange $a(sheets) 0 end-1] # Keep the active tab of the workbook view pointing to the same # worksheet (or at least to a valid one) after the removal. if {[info exists a(view)] && [dict exists $a(view) activetab]} { set activetab [dict get $a(view) activetab] if {[string is integer -strict $activetab]} { if {$activetab > $removeSheet} { incr activetab -1 } set maxtab [expr {[llength $a(sheets)] - 1}] if {$activetab > $maxtab} { set activetab $maxtab } dict set a(view) activetab $activetab } } } } } # Seite 3947 # # # # # # # proc ::ooxml::Color { color } { variable predefColors variable predefColorsName variable predefColorsARBG if {[string trim $color] eq {}} { return {} } elseif {$color in {auto none}} { return [list $color 1] } elseif {[string is integer -strict $color] && $color >= 0 && $color <= 65} { return [list indexed $color] } elseif {[set idx [lsearch -exact -nocase [array names predefColors] $color]] && $idx > -1} { return [list indexed $idx] } elseif {[set idx [lsearch -exact -nocase $predefColorsName $color]] && $idx > -1} { return [list indexed $idx] } if {[string is xdigit -strict $color]} { if {[string length $color] == 6} { set color 00$color } if {[set idx [lsearch -exact -nocase $predefColorsARBG $color]] && $idx > -1} { return [list indexed $idx] } else { return [list rgb $color] } } return {} } # # ooxml::ZipOpen # # Helper to open a zip file for reading. # On first call, the zip access method is found and initialized # # Whether tcllib's zipfile::decode can actually decompress deflated # entries in this interpreter. It uses either the core [zlib inflate] # (when it considers the native zlib functions available) or the Trf # [zip] command. On installations where the native path is not taken and # the Trf 'zip' command is missing, getfile fails with # 'invalid command name "zip"'. Detect that so ZipOpen can fall back to # another zip backend (ticket 0da3bc4b65). proc ::ooxml::ZipfileDecodeUsable {} { if {[info exists ::zipfile::decode::native_zip_functs] && $::zipfile::decode::native_zip_functs} { return 1 } return [expr {[llength [info commands zip]] > 0}] } # Built-in zip reader based on the core zlib command (available since # Tcl 8.6). Locates the end of central directory record, parses the # central directory and decompresses single entries with [zlib inflate]. # This needs no external package at all. Archives it cannot handle # (ZIP64, encrypted or exotically compressed entries) raise an error and # ZipOpen falls back to one of the legacy backends. proc ::ooxml::ZlibZipOpen {file} { variable zlibfd variable zlibcdir set fd [open $file rb] try { # Locate the end of central directory record: last occurrence of # its signature within the last 64k (max comment length) + 22 bytes. seek $fd 0 end set fsize [tell $fd] if {$fsize < 22} { error "file is too short to be a zip archive" } set rlen [expr {$fsize < 65558 ? $fsize : 65558}] seek $fd [expr {$fsize - $rlen}] set tail [read $fd $rlen] set pos [string last "PK\x05\x06" $tail] if {$pos < 0} { error "end of central directory record not found" } binary scan $tail @${pos}x4susususuiuiu disk cddisk nrecsdisk nrecs cdsize cdoff if {$nrecs == 0xFFFF || $cdsize == 0xFFFFFFFF || $cdoff == 0xFFFFFFFF} { error "ZIP64 archives are not supported by the built-in zip reader" } # Read and parse the central directory. seek $fd $cdoff set cd [read $fd $cdsize] set cdir [dict create] set p 0 for {set i 0} {$i < $nrecs} {incr i} { binary scan $cd @${p}a4x4susux4iuiuiusususux8iu \ sig flags method crc csize usize nlen elen clen offset if {$sig ne "PK\x01\x02"} { error "bad central directory entry" } if {$csize == 0xFFFFFFFF || $usize == 0xFFFFFFFF || $offset == 0xFFFFFFFF} { error "ZIP64 archives are not supported by the built-in zip reader" } set raw [string range $cd [expr {$p + 46}] [expr {$p + 45 + $nlen}]] if {$flags & 0x800} { set name [encoding convertfrom utf-8 $raw] } else { set name [encoding convertfrom cp437 $raw] } dict set cdir $name [list flags $flags method $method \ csize $csize usize $usize offset $offset] incr p [expr {46 + $nlen + $elen + $clen}] } } on error {errMsg errOpts} { close $fd return -options $errOpts $errMsg } set zlibfd $fd set zlibcdir $cdir } # Return the decompressed raw (binary) data of the given zip member. proc ::ooxml::ZlibZipGet {path} { variable zlibfd variable zlibcdir set entry [dict get $zlibcdir $path] if {[dict get $entry flags] & 1} { error "zip member \"$path\" is encrypted" } if {[dict get $entry csize] == 0} { return {} } # The sizes of the local file header name and extra fields may differ # from those in the central directory - read them from the local header. seek $zlibfd [dict get $entry offset] set lh [read $zlibfd 30] binary scan $lh a4x22susu sig nlen elen if {$sig ne "PK\x03\x04"} { error "bad local file header of zip member \"$path\"" } seek $zlibfd [expr {$nlen + $elen}] current set data [read $zlibfd [dict get $entry csize]] switch -exact -- [dict get $entry method] { 0 { return $data } 8 { # The optional buffer size hint of [zlib inflate] must be within # 16 and 65536 - the buffer still grows as needed beyond the # hint, so cap it (ticket a308a654f0). set hint [dict get $entry usize] if {$hint > 65536} { set hint 65536 } elseif {$hint < 16} { set hint 16 } return [zlib inflate $data $hint] } default { error "zip member \"$path\" uses unsupported compression method\ [dict get $entry method]" } } } proc ::ooxml::ZipOpen {file} { variable zipAccessMethod variable zipLegacyMethod # Prefer the built-in reader based on the core zlib command. Fall back # to a legacy backend for archives it cannot handle. if {[llength [info commands zlib]]} { if {![catch {ZlibZipOpen $file} zlibErr]} { set zipAccessMethod zlib return } } else { set zlibErr {no zlib command available} } if {$zipLegacyMethod eq {}} { if {[package vsatisfies [package present Tcl] 9]} { set zipLegacyMethod tcl9 variable zipfs [zipfs root] } elseif {![catch {package require zipfile::decode}] && [ooxml::ZipfileDecodeUsable]} { set zipLegacyMethod tcllib } elseif {![catch {package require vfs::zip 1.0.4-}]} { # As Version 1.0.3 has serious bugs like returning empty data, require # 1.0.4 and further set zipLegacyMethod vfs variable zipfs {} } else { return -code error "ooxml: cannot read \"$file\": $zlibErr; and no\ fallback zip backend is available (tcl9 zipfs, tclvfs\ vfs::zip >= 1.0.4 or a tcllib whose zipfile::decode can\ decompress with the native zlib functions)" } } set zipAccessMethod $zipLegacyMethod switch -exact -- $zipAccessMethod { tcl9 { variable mnt [zipfs mount $file xlsx] } vfs { variable mnt [vfs::zip::Mount $file xlsx] } default { ::zipfile::decode::open $file variable zipdesc [::zipfile::decode::archive] } } } proc ::ooxml::ZipMembers {} { switch -exact -- $::ooxml::zipAccessMethod { zlib { set files {} foreach name [dict keys $::ooxml::zlibcdir] { # skip directory entries if {[string index $name end] eq {/}} continue lappend files $name } return $files } tcllib { return [::zipfile::decode::files $::ooxml::zipdesc] } default { # Tcl 9 zipfs or vfs::zip: traverse the mounted "${::ooxml::zipfs}xlsx" package require fileutil::traverse set base "${::ooxml::zipfs}xlsx" if {![file exists $base]} { return {} } set files {} ::fileutil::traverse it $base set baseLen [string length "$base/"] it foreach f { if {[file isdirectory $f]} continue lappend files [string range $f $baseLen end] } it destroy return $files } } } proc ::ooxml::ZipReadBinaryFile {path} { switch -exact -- $::ooxml::zipAccessMethod { zlib { return [ZlibZipGet $path] } tcllib { return [::zipfile::decode::getfile $::ooxml::zipdesc $path] } default { set fd [open ${::ooxml::zipfs}xlsx/$path rb] set data [read $fd] close $fd return $data } } } # # ooxml::ZipReadParse # # Read the data of a zip file wether by vfs or tcllib # Return the handle to the tdom object # Return the empty string, if file not found # Throws errors on file error, decoding error or xml parse error proc ::ooxml::ZipReadParse {file} { variable zipAccessMethod switch -exact -- $zipAccessMethod { zlib { variable zlibcdir if {![dict exists $zlibcdir $file]} { # File not found is ok - return empty string return } set filedata [encoding convertfrom utf-8 [ZlibZipGet $file]] } tcllib { variable zipdesc try { set filedata [encoding convertfrom utf-8\ [::zipfile::decode::getfile $zipdesc $file]] } trap {ZIP DECODE BAD PATH} {} { # File not found error is ok - return empty string return } } default { # Use virtual file system variable zipfs try { set fd [open ${zipfs}xlsx/$file r] fconfigure $fd -encoding utf-8 # Specially catch read, as it may fire utf-8 translation errors on Tcl9 set filedata [read $fd] } trap {POSIX ENOENT} {} { # File not found error is ok - return empty string return } finally { if {[info exists fd]} { close $fd } } } } # Parse the file data # This throws an error if parsing fails if {[package vsatisfies [package present tdom] 0.9.7-]} { # Since tdom 0.9.7 xml:space='preserve' are respected return [dom parse $filedata] } else { return [dom parse -keepEmpties $filedata] } } # # ooxml::ZipClose # # Close the zip file # proc ::ooxml::ZipClose {} { variable zipAccessMethod switch -exact -- $zipAccessMethod { zlib { variable zlibfd variable zlibcdir close $zlibfd unset zlibfd zlibcdir } tcl9 { variable mnt zipfs unmount $mnt unset mnt } vfs { variable mnt vfs::zip::Unmount $mnt xlsx unset mnt } tcllib { ::zipfile::decode::close # Clear zip metadata variable zipdesc unset zipdesc } } } # # ooxml::xl_sheets # proc ::ooxml::xl_sheets { file args} { variable xmlns set sheets {} ZipOpen $file # As zip is open now, open try block to close it for sure try { set rdoc [ZipReadParse "xl/_rels/workbook.xml.rels"] # relsroot is needed below to add sheets. # If it is not present, there will be an error below if {$rdoc eq {}} { return -code error "No valid xlsx file" } $rdoc documentElement relsRoot $rdoc selectNodesNamespaces [list PR $xmlns(PR)] set doc [ZipReadParse "xl/workbook.xml"] if {$doc eq {}} { return -code error "No valid xlsx file" } $doc documentElement root $doc selectNodesNamespaces [list M $xmlns(M) r $xmlns(r)] set idx -1 foreach node [$root selectNodes /M:workbook/M:sheets/M:sheet] { if {[$node hasAttribute sheetId] && [$node hasAttribute name]} { set sheetId [$node @sheetId] set name [$node @name] set rid [$node getAttributeNS $xmlns(r) id] foreach node [$relsRoot selectNodes {/PR:Relationships/PR:Relationship[@Id=$rid]}] { if {[$node hasAttribute Target]} { lappend sheets [incr idx] [list sheetId $sheetId name $name rId $rid] } } } } $doc delete $rdoc delete return $sheets } finally { ZipClose } } # # ooxml::xl_read # proc ::ooxml::xl_read { file args } { variable xmlns variable predefNumFmts array set cellXfs {} array set numFmts [array get predefNumFmts] array set sharedStrings {} set sheets {} array set printArea {} array set opts { valuesonly 0 keylist 0 sheets {} sheetnames {} datefmt {%Y-%m-%d %H:%M:%S} as array } set len [llength $args] set idx 0 for {set idx 0} {$idx < $len} {incr idx} { switch -- [set opt [lindex $args $idx]] { -sheets - -sheetnames - -datefmt - -as { incr idx if {$idx < $len} { set opts([string range $opt 1 end]) [lindex $args $idx] } else { error "option '$opt': missing argument" } } -valuesonly - -keylist { set opts([string range $opt 1 end]) 1 } default { error "unknown option \"$opt\", should be: -sheets, -sheetnames, -datefmt, -as, -valuesonly or -keylist" } } } if {[string trim $opts(sheets)] eq {} && [string trim $opts(sheetnames)] eq {}} { set opts(sheetnames) * } ZipOpen $file # As zip is open now, open try block to close it for sure try { set rdoc [ZipReadParse "xl/_rels/workbook.xml.rels"] # relsroot is needed below to add sheets. # If it is not present, there will be an error below if {$rdoc eq {}} { return -code error "No valid xlsx file" } $rdoc documentElement relsRoot $rdoc selectNodesNamespaces [list PR $xmlns(PR)] set doc [ZipReadParse "xl/workbook.xml"] if {$doc eq {}} { return -code error "No valid xlsx file" } $doc documentElement root $doc selectNodesNamespaces [list M $xmlns(M) r $xmlns(r)] set idx -1 foreach node [$root selectNodes /M:workbook/M:sheets/M:sheet] { if {[$node hasAttribute sheetId] && [$node hasAttribute name]} { set sheetId [$node @sheetId] set name [$node @name] set rid [$node getAttributeNS $xmlns(r) id] foreach node [$relsRoot selectNodes {/PR:Relationships/PR:Relationship[@Id=$rid]}] { if {[$node hasAttribute Target]} { lappend sheets [incr idx] $sheetId $name $rid [$node @Target] } } } } foreach node [$root selectNodes {/M:workbook/M:definedNames/M:definedName[@name="_xlnm.Print_Area"]}] { if {[$node hasAttribute localSheetId]} { set printArea([$node @localSheetId]) [lindex [split [$node text] !] end] } } foreach node [$root selectNodes /M:workbook/M:bookViews/M:workbookView] { if {[$node hasAttribute activeTab]} { lappend wb(view) activetab [$node @activeTab] } if {[$node hasAttribute xWindow]} { lappend wb(view) x [$node @xWindow] } if {[$node hasAttribute yWindow]} { lappend wb(view) y [$node @yWindow] } if {[$node hasAttribute windowHeight]} { lappend wb(view) height [$node @windowHeight] } if {[$node hasAttribute windowWidth]} { lappend wb(view) width [$node @windowWidth] } } $doc delete $rdoc delete set doc [ZipReadParse "xl/sharedStrings.xml"] if {$doc ne {}} { $doc documentElement root $doc selectNodesNamespaces [list M $xmlns(M)] set idx -1 foreach shared [$root selectNodes /M:sst/M:si] { incr idx foreach node [$shared selectNodes M:t/text()] { append sharedStrings($idx) [$node nodeValue] } foreach node [$shared selectNodes */M:t/text()] { append sharedStrings($idx) [$node nodeValue] } } $doc delete } set doc [ZipReadParse "xl/styles.xml"] if {$doc ne {}} { $doc documentElement root $doc selectNodesNamespaces [list M $xmlns(M) mc $xmlns(mc) x14ac $xmlns(x14ac) x16r2 $xmlns(x16r2)] set idx -1 foreach node [$root selectNodes /M:styleSheet/M:numFmts/M:numFmt] { incr idx if {[$node hasAttribute numFmtId] && [$node hasAttribute formatCode]} { set numFmtId [$node @numFmtId] set formatCode [$node @formatCode] set datetime 0 foreach tag {*y* *m* *d* *h* *s*} { if {[string match -nocase $tag [string map {Black {} Blue {} Cyan {} Green {} Magenta {} Red {} White {} Yellow {}} $formatCode]]} { set datetime 1 break } } set numFmts($numFmtId) [list dt $datetime fmt $formatCode] } } set idx -1 foreach node [$root selectNodes /M:styleSheet/M:cellXfs/M:xf] { incr idx if {[$node hasAttribute numFmtId]} { set numFmtId [$node @numFmtId] if {[$node hasAttribute applyNumberFormat]} { set applyNumberFormat [$node @applyNumberFormat] } else { set applyNumberFormat 0 } set cellXfs($idx) [list nfi $numFmtId anf $applyNumberFormat] } } if {!$opts(valuesonly)} { ### READING KNOWN FORMATS AND STYLES ### set wb(s,@) {} array unset a * set a(max) 0 set wb(s,numFmtsIds) {} foreach node [$root selectNodes /M:styleSheet/M:numFmts/M:numFmt] { if {[$node hasAttribute numFmtId] && [$node hasAttribute formatCode]} { set wb(s,numFmts,[set idx [$node @numFmtId]]) [$node @formatCode] lappend wb(s,numFmtsIds) $idx if {$idx > $a(max)} { set a(max) $idx } } } if {$a(max) < $::ooxml::defaults(numFmts,start)} { set a(max) $::ooxml::defaults(numFmts,start) } lappend wb(s,@) numFmtId [incr a(max)] set idx -1 array unset a * foreach node [$root selectNodes /M:styleSheet/M:fonts/M:font] { incr idx array set a {name {} family {} size {} color {} scheme {} bold 0 italic 0 underline 0 color {}} foreach node1 [$node childNodes] { switch -- [$node1 nodeName] { b { set a(bold) 1 } i { set a(italic) 1 } u { set a(underline) 1 } sz { if {[$node1 hasAttribute val]} { set a(size) [$node1 @val] } } color { if {[$node1 hasAttribute auto]} { set a(color) [list auto [$node1 @auto]] } elseif {[$node1 hasAttribute rgb]} { set a(color) [list rgb [$node1 @rgb]] } elseif {[$node1 hasAttribute indexed]} { set a(color) [list indexed [$node1 @indexed]] } elseif {[$node1 hasAttribute theme]} { set a(color) [list theme [$node1 @theme]] } } name { if {[$node1 hasAttribute val]} { set a(name) [$node1 @val] } } family { if {[$node1 hasAttribute val]} { set a(family) [$node1 @val] } } scheme { if {[$node1 hasAttribute val]} { set a(scheme) [$node1 @val] } } } } set wb(s,fonts,$idx) [array get a] } lappend wb(s,@) fonts [incr idx] set idx -1 array unset a * foreach node [$root selectNodes /M:styleSheet/M:fills/M:fill] { incr idx array set a {patterntype {} fgcolor {} bgcolor {}} foreach node1 [$node childNodes] { switch -- [$node1 nodeName] { patternFill { if {[$node1 hasAttribute patternType]} { set a(patterntype) [$node1 @patternType] } foreach node2 [$node1 childNodes] { if {[$node2 nodeName] in { fgColor bgColor}} { if {[$node2 hasAttribute auto]} { set a([string tolower [$node2 nodeName]]) [list auto [$node2 @auto]] } elseif {[$node2 hasAttribute rgb]} { set a([string tolower [$node2 nodeName]]) [list rgb [$node2 @rgb]] } elseif {[$node2 hasAttribute indexed]} { set a([string tolower [$node2 nodeName]]) [list indexed [$node2 @indexed]] } elseif {[$node2 hasAttribute theme]} { set a([string tolower [$node2 nodeName]]) [list theme [$node2 @theme]] } } } } } } set wb(s,fills,$idx) [array get a] } lappend wb(s,@) fills [incr idx] set idx -1 unset -nocomplain d foreach node [$root selectNodes /M:styleSheet/M:borders/M:border] { incr idx set d {left {style {} color {}} right {style {} color {}} top {style {} color {}} bottom {style {} color {}} diagonal {style {} color {} direction {}}} foreach node1 [$node childNodes] { if {[$node1 hasAttribute style]} { set style [$node1 @style] } else { set style {} } set color {} foreach node2 [$node1 childNodes] { if {[$node2 nodeName] eq {color}} { if {[$node2 hasAttribute auto]} { set color [list auto [$node2 @auto]] } elseif {[$node2 hasAttribute rgb]} { set color [list rgb [$node2 @rgb]] } elseif {[$node2 hasAttribute indexed]} { set color [list indexed [$node2 @indexed]] } elseif {[$node2 hasAttribute theme]} { set color [list theme [$node2 @theme]] } } } if {[$node1 nodeName] in {left right top bottom diagonal}} { if {$style ne {}} { dict set d [$node1 nodeName] style $style } if {$color ne {}} { dict set d [$node1 nodeName] color $color } } } if {[$node hasAttribute diagonalUp]} { dict set d diagonal direction diagonalUp } elseif {[$node hasAttribute diagonalDown]} { dict set d diagonal direction diagonalDown } set wb(s,borders,$idx) $d } lappend wb(s,@) borders [incr idx] set idx -1 array unset a * foreach node [$root selectNodes /M:styleSheet/M:cellXfs/M:xf] { incr idx array set a {numfmt 0 font 0 fill 0 border 0 xf 0 horizontal {} vertical {} rotate {} wrap {}} if {[$node hasAttribute numFmtId]} { set a(numfmt) [$node @numFmtId] } if {[$node hasAttribute fontId]} { set a(font) [$node @fontId] } if {[$node hasAttribute fillId]} { set a(fill) [$node @fillId] } if {[$node hasAttribute borderId]} { set a(border) [$node @borderId] } if {[$node hasAttribute xfId]} { set a(xf) [$node @xfId] } foreach node1 [$node childNodes] { switch -- [$node1 nodeName] { alignment { if {[$node1 hasAttribute horizontal]} { set a(horizontal) [$node1 @horizontal] } if {[$node1 hasAttribute vertical]} { set a(vertical) [$node1 @vertical] } if {[$node1 hasAttribute textRotation]} { set a(rotate) [$node1 @textRotation] } if {[$node1 hasAttribute wrapText]} { set a(wrap) [$node1 @wrapText] } } } } set wb(s,styles,$idx) [array get a] } lappend wb(s,@) styles [incr idx] } $doc delete } ### HYPERLINKS ### foreach {sheet sid name rid target} $sheets { set doc [ZipReadParse "xl/worksheets/_rels/sheet[expr {$sheet + 1}].xml.rels"] if {$doc ne {}} { $doc documentElement root $doc selectNodesNamespaces [list M $xmlns(PR)] foreach hlink [$root selectNodes /M:Relationships/M:Relationship] { if {[$hlink hasAttribute Id] && [$hlink hasAttribute Target]} { set hl($sheet,[$hlink @Id]) [$hlink @Target] } } $doc delete } } ### SHEET AND DATA ### array set wb {} foreach {sheet sid name rid target} $sheets { set read false if {$opts(sheets) ne {}} { foreach pat $opts(sheets) { if {[string match $pat $sheet]} { set read true break } } } if {!$read && $opts(sheetnames) ne {}} { foreach pat $opts(sheetnames) { if {[string match $pat $name]} { set read true break } } } if {!$read} continue lappend wb(sheets) $sheet set wb($sheet,n) $name set wb($sheet,max_row) -1 set wb($sheet,max_column) -1 set doc [ZipReadParse "xl/$target"] # This file must be present if {$doc eq {}} { return -code error "Excel file error: No data for sheet [expr {$sheet+1}]" } $doc documentElement root $doc selectNodesNamespaces [list M $xmlns(M) r $xmlns(r) mc $xmlns(mc) x14ac $xmlns(x14ac)] if {!$opts(valuesonly)} { set idx -1 foreach col [$root selectNodes /M:worksheet/M:cols/M:col] { incr idx set cols {} foreach item {min max width style bestFit customWidth} { if {[$col hasAttribute $item]} { switch -- $item { min - max { lappend cols [string tolower $item] [expr {[$col @$item] - 1}] } default { lappend cols [string tolower $item] [$col @$item] } } } else { lappend cols [string tolower $item] 0 } } lappend cols string 0 nozero 0 calcfit 0 set wb($sheet,col,[dict get $cols min]) $cols } set wb($sheet,cols) [incr idx] } set rowindex -1 foreach row [$root selectNodes /M:worksheet/M:sheetData/M:row] { incr rowindex set cellindex -1 foreach cell [$row selectNodes M:c] { incr cellindex # Get cell position # if r exists, it contains the cell position like "A1". # Otherwise, use the counter values # The cell may omit positions so, set the counters if explicit # cell position is given if {[$cell hasAttribute r]} { set rowcol [StringToRowColumn [$cell @r]] # Correct the current counters scan $rowcol %d,%d rowindex cellindex } else { set rowcol $rowindex,$cellindex } if {[$cell hasAttribute t]} { set type [$cell @t] } else { set type n } set value {} set datetime {} ## FORMULA ## if {!$opts(valuesonly) && [set node [$cell selectNodes M:f]] ne {}} { set wb($sheet,f,$rowcol) {} if {[set formula [$cell selectNodes M:f/text()]] ne {}} { lappend wb($sheet,f,$rowcol) f [$formula nodeValue] } if {[$node hasAttribute t] && [$node @t] eq {shared}} { if {[$node hasAttribute si]} { lappend wb($sheet,f,$rowcol) i [$node @si] } if {[$node hasAttribute ref]} { lappend wb($sheet,f,$rowcol) r [$node @ref] } } } switch -- $type { n - b - d - str { # number (default), boolean, iso-date, formula string if {[set node [$cell selectNodes M:v/text()]] ne {}} { set value [$node nodeValue] if {$type eq {n} && [$cell hasAttribute s] && [string is double -strict $value]} { set idx [$cell @s] if {[info exists cellXfs($idx)] && [dict exists $cellXfs($idx) nfi]} { set numFmtId [dict get $cellXfs($idx) nfi] if {[info exists numFmts($numFmtId)] && [dict exists $numFmts($numFmtId) dt] && [dict get $numFmts($numFmtId) dt]} { set datetime $value catch {clock format [expr {round(($value - 25569) * 86400.0)}] -format $opts(datefmt) -gmt 1} value } } } } else { if {![$cell hasAttribute s]} continue } } s { # shared string if {[set node [$cell selectNodes M:v/text()]] ne {}} { set index [$node nodeValue] if {[info exists sharedStrings($index)]} { set value $sharedStrings($index) } } else { if {![$cell hasAttribute s]} continue } } inlineStr { # inline string if {[set string [$cell selectNodes M:is]] ne {}} { foreach node [$string selectNodes M:t/text()] { append value [$node nodeValue] } foreach node [$string selectNodes */M:t/text()] { append value [$node nodeValue] } } else { if {![$cell hasAttribute s]} continue } } e { # error } } if {!$opts(valuesonly)} { set wb($sheet,c,$rowcol) [$cell @r] } if {!$opts(valuesonly)} { if {[$cell hasAttribute s]} { set wb($sheet,s,$rowcol) [$cell @s] } } if {!$opts(valuesonly)} { if {[$cell hasAttribute t]} { set wb($sheet,t,$rowcol) [$cell @t] } } set wb($sheet,v,$rowcol) $value if {!$opts(valuesonly) && $datetime ne {}} { set wb($sheet,d,$rowcol) $datetime } } } if {!$opts(valuesonly)} { foreach hlink [$root selectNodes /M:worksheet/M:hyperlinks/M:hyperlink] { if {[$hlink hasAttribute ref] && [$hlink hasAttribute r:id]} { set idx [::ooxml::StringToRowColumn [$hlink @ref]] if {[info exists hl($sheet,[$hlink @r:id])]} { if {[$hlink hasAttribute tooltip]} { set tt [$hlink @tooltip] } else { set tt {} } set wb($sheet,l,$idx) [list l $hl($sheet,[$hlink @r:id]) t $tt] } } } } if {!$opts(valuesonly)} { foreach {n v} [array get printArea] { set wb($n,printarea) $v } } if {!$opts(valuesonly)} { foreach row [$root selectNodes /M:worksheet/M:sheetData/M:row] { if {[$row hasAttribute r] && [$row hasAttribute ht] && [$row hasAttribute customHeight] && [$row @customHeight] == 1} { dict set wb($sheet,rowheight) [expr {[$row @r] - 1}] [$row @ht] } } } if {!$opts(valuesonly)} { foreach freeze [$root selectNodes /M:worksheet/M:sheetViews/M:sheetView/M:pane] { if {[$freeze hasAttribute topLeftCell] && [$freeze hasAttribute state] && [$freeze @state] eq {frozen}} { set wb($sheet,freeze) [$freeze @topLeftCell] } } } if {!$opts(valuesonly)} { foreach filter [$root selectNodes /M:worksheet/M:autoFilter] { if {[$filter hasAttribute ref]} { lappend wb($sheet,filter) [$filter @ref] } } } if {!$opts(valuesonly)} { foreach merge [$root selectNodes /M:worksheet/M:mergeCells/M:mergeCell] { if {[$merge hasAttribute ref]} { lappend wb($sheet,merge) [$merge @ref] } } } if {!$opts(valuesonly)} { foreach node [$root selectNodes /M:worksheet/M:pageMargins] { foreach n [$node attributeNames] { if {$n in {left right top bottom header footer}} { dict set wb($sheet,pageMargins) -$n [$node @$n] } } } } if {!$opts(valuesonly)} { foreach node [$root selectNodes /M:worksheet/M:pageSetup] { foreach n [$node attributeNames] { if {$n in {blackAndWhite cellComments copies draft errors firstPageNumber fitToHeight fitToWidth horziontalDpi horizontalDpi orientation pageOrder paperHeight paperSize paperWide paperWidth scale useFirstPageNumber verticalDpi}} { dict set wb($sheet,pageSetup) -$n [$node @$n] } } } } $doc delete } } finally { ZipClose } foreach cell [lsort -dictionary [array names wb *,v,*]] { lassign [split $cell ,] sheet tag row column if {$opts(keylist)} { dict lappend wb($sheet,k) $row $column } if {$row > $wb($sheet,max_row)} { set wb($sheet,max_row) $row } if {$column > $wb($sheet,max_column)} { set wb($sheet,max_column) $column } } return [array get wb] } # Internal helper proc ooxml::Dom2zip {zf node path cd count} { upvar $cd mycd upvar $count mycount append mycd [::ooxml::add_str_to_archive $zf $path [$node asXML -indent none -xmlDeclaration 1 -encString "UTF-8"]] incr mycount } # # ooxml::InitNodeCommands # proc ooxml::InitNodeCommands {} { variable initNodeCmds variable xmlns if {[info exists initNodeCmds] && $initNodeCmds} return set elementNodes { AppVersion Application Company Default DocSecurity HeadingPairs HyperlinksChanged LinksUpToDate Override Relationship Relationships ScaleCrop SharedDoc TitlesOfParts a:accent1 a:accent2 a:accent3 a:accent4 a:accent5 a:accent6 a:alpha a:bevelT a:bgFillStyleLst a:bodyPr a:camera a:clrScheme a:cs a:dk1 a:dk2 a:ea a:effectLst a:effectRef a:effectStyle a:effectStyleLst a:extraClrSchemeLst a:fillRef a:fillStyleLst a:fillToRect a:fmtScheme a:folHlink a:font a:fontRef a:fontScheme a:gradFill a:gs a:gsLst a:hlink a:latin a:lightRig a:lin a:ln a:lnDef a:lnRef a:lnStyleLst a:lstStyle a:lt1 a:lt2 a:majorFont a:minorFont a:objectDefaults a:outerShdw a:path a:prstDash a:rot a:satMod a:scene3d a:schemeClr a:shade a:solidFill a:sp3d a:spDef a:spPr a:srgbClr a:style a:sysClr a:themeElements a:tint alignment autoFilter b bgColor bookViews border borders bottom c calcPr cellStyle cellStyleXfs cellStyles cellXfs col color cols cp:lastModifiedBy dc:creator dcterms:created dcterms:modified definedName definedNames diagonal dimension dxfs f family fgColor fileVersion fill fills font fonts hyperlink hyperlinks i left mergeCell mergeCells name numFmt numFmts pageMargins pageSetup pane patternFill right row scheme sheet sheetData sheetFormatPr sheetView sheetViews sheets si sz t tableStyles top u v vt:i4 vt:lpstr vt:variant vt:vector workbookPr workbookView xf } namespace eval ::ooxml "dom createNodeCmd textNode Text; namespace export Text" # In the commented out part, serialization is done with namespaces set correctly, but this takes a few milliseconds more time. # Since we may process large amounts of data and do not use the same tag names in different namespaces and do not search in # the DOM during serialization, we only set the namespaces as attributes, which leads to the same result in the serialized XML. # # foreach tag $elementNodes { # switch -glob -- $tag { # a:* { # set ns $xmlns(a) # } # cp:* { # set ns $xmlns(cp) # } # dc:* { # set ns $xmlns(dc) # } # dcterms:* { # set ns $xmlns(dcterms) # } # vt:* { # set ns $xmlns(vt) # } # AppVersion - Application - Company - DocSecurity - HeadingPairs - HyperlinksChanged - LinksUpToDate - ScaleCrop - SharedDoc - TitlesOfParts { # set ns $xmlns(EP) # } # Default - Override { # set ns $xmlns(CT) # } # Relationship { # set ns $xmlns(PR) # } # default { # set ns $xmlns(M) # } # } # namespace eval ::ooxml "dom createNodeCmd -tagName $tag -namespace $ns elementNode Tag_$tag; namespace export Tag_$tag" # } foreach tag $elementNodes { namespace eval ::ooxml "dom createNodeCmd -tagName $tag elementNode Tag_$tag; namespace export Tag_$tag" } set initNodeCmds 1 } # # ooxml::xl_write # oo::class create ooxml::xl_write { constructor { args } { my variable obj my variable cells my variable sharedStrings my variable fonts my variable numFmts my variable styles my variable fills my variable borders my variable cols my variable view my variable tags my variable hlinks my variable pageMargins my variable pageMarginsDefault my variable pageSetups array set opts { creator {unknown} created {} modifiedby {} modified {} application {} } array set tags {} set pageMarginsDefault { left 0.75 right 0.75 top 1 bottom 1 header 0.5 footer 0.5 } set len [llength $args] set idx 0 for {set idx 0} {$idx < $len} {incr idx} { switch -- [set opt [lindex $args $idx]] { -creator - -created - -modifiedby - -modified - -application { incr idx if {$idx < $len} { set opts([string range $opt 1 end]) [lindex $args $idx] } else { error "option '$opt': missing argument" } } default { error "unknown option \"$opt\", should be: -creator, -created, -modifiedby, -modified or -application" } } } set obj(blockPreset) 0 set obj(encoding) utf-8 set obj(indent) none if {[string trim $opts(creator)] eq {}} { set obj(creator) {unknown} } else { set obj(creator) $opts(creator) } if {[string trim $opts(created)] eq {} || [catch {clock scan $opts(created)}]} { set obj(created) [clock format [clock seconds] -format %Y-%m-%dT%H:%M:%SZ -gmt 1] } elseif {[string is integer -strict $opts(created)] && $opts(created) > 0} { set obj(created) [clock format $opts(created) -format %Y-%m-%dT%H:%M:%SZ -gmt 1] } else { set obj(created) [clock format [clock scan $opts(created)] -format %Y-%m-%dT%H:%M:%SZ -gmt 1] } if {[string trim $opts(modifiedby)] eq {}} { set obj(lastModifiedBy) $opts(creator) } else { set obj(lastModifiedBy) $opts(modifiedby) } if {[string trim $opts(modified)] eq {} || [catch {clock scan $opts(modified)}]} { set obj(modified) [clock format [clock seconds] -format %Y-%m-%dT%H:%M:%SZ -gmt 1] } elseif {[string is integer -strict $opts(modified)] && $opts(modified) > 0} { set obj(modified) [clock format $opts(modified) -format %Y-%m-%dT%H:%M:%SZ -gmt 1] } else { set obj(modified) [clock format [clock scan $opts(modified)] -format %Y-%m-%dT%H:%M:%SZ -gmt 1] } if {[string trim $opts(application)] eq {}} { set obj(application) {Tcl - Office Open XML - Spreadsheet} } else { set obj(application) $opts(application) } set obj(sheets) 0 array set sheets {} set obj(sharedStrings) 0 set sharedStrings {} set obj(numFmts) $::ooxml::defaults(numFmts,start) array set numFmts {} set obj(borders) 1 set borders(0) {left {style {} color {}} right {style {} color {}} top {style {} color {}} bottom {style {} color {}} diagonal {style {} color {} direction {}}} set obj(fills) 2 set fills(0) {patterntype none fgcolor {} bgcolor {}} set fills(1) {patterntype gray125 fgcolor {} bgcolor {}} set obj(fonts) 1 set fonts(0) {name Calibri family 2 size 12 color {theme 1} scheme minor bold 0 italic 0 underline 0 color {}} set obj(styles) 1 set styles(0) {numfmt 0 font 0 fill 0 border 0 xf 0 horizontal {} vertical {} rotate {} wrap {}} set obj(cols) 0 array set cols {} set obj(calcChain) 0 set obj(defaultdatestyle) 0 array set cells {} array set hlinks {} array set view {activetab 0} return 0 } destructor { return 0 } method numberformat { args } { my variable obj my variable numFmts my variable tags array set opts { list 0 format {} general 0 date 0 time 0 datetime 0 iso8601 0 number 0 decimal 0 red 0 separator 0 fraction 0 scientific 0 percent 0 string 0 text 0 tag {} } set len [llength $args] set idx 0 for {set idx 0} {$idx < $len} {incr idx} { switch -- [set opt [lindex $args $idx]] { -format { incr idx if {$idx < $len} { set opts([string range $opt 1 end]) [lindex $args $idx] } else { error "option '$opt': missing argument" } } -list - -general - -date - -time - -datetime - -iso8601 - -number - -decimal - -red - -separator - -fraction - -scientific - -percent - -string - -text { set opts([string range $opt 1 end]) 1 } -tag { incr idx if {$idx < $len} { if {[string is integer -strict [set tag [lindex $args $idx]]]} { error "option '$opt': should not be an integer value" } else { set opts([string range $opt 1 end]) $tag } unset tag } else { error "option '$opt': missing argument" } } default { error "unknown option \"$opt\", should be: -format, -list, -general, -date, -time, -datetime, -iso8601, -number, -decimal, -red, -separator, -fraction, -scientific, -percent, -string, -text or tag" } } } if {$opts(list)} { array set tmp [array get ::ooxml::predefNumFmts] array set tmp [array get numFmts] return [array get tmp] } set obj(blockPreset) 1 if {$opts(general)} { if {$opts(tag) ne {}} { set tags(numFmts,$opts(tag)) 0 } return 0 } if {$opts(date)} { if {$opts(tag) ne {}} { set tags(numFmts,$opts(tag)) 14 } return 14 } if {$opts(time)} { if {$opts(tag) ne {}} { set tags(numFmts,$opts(tag)) 20 } return 20 } if {$opts(number)} { if {$opts(separator)} { if {$opts(red)} { if {$opts(tag) ne {}} { set tags(numFmts,$opts(tag)) 38 } return 38 } else { if {$opts(tag) ne {}} { set tags(numFmts,$opts(tag)) 3 } return 3 } } else { if {$opts(red)} { return -1 } else { if {$opts(tag) ne {}} { set tags(numFmts,$opts(tag)) 1 } return 1 } } } if {$opts(decimal)} { if {$opts(percent)} { if {$opts(tag) ne {}} { set tags(numFmts,$opts(tag)) 10 } return 10 } if {$opts(separator)} { if {$opts(red)} { if {$opts(tag) ne {}} { set tags(numFmts,$opts(tag)) 40 } return 40 } else { if {$opts(tag) ne {}} { set tags(numFmts,$opts(tag)) 4 } return 4 } } else { if {$opts(red)} { return -1 } else { if {$opts(tag) ne {}} { set tags(numFmts,$opts(tag)) 2 } return 2 } } } if {$opts(fraction)} { if {$opts(tag) ne {}} { set tags(numFmts,$opts(tag)) 12 } return 12 } if {$opts(scientific)} { if {$opts(tag) ne {}} { set tags(numFmts,$opts(tag)) 11 } return 11 } if {$opts(percent)} { if {$opts(tag) ne {}} { set tags(numFmts,$opts(tag)) 9 } return 9 } if {$opts(text) || $opts(string)} { if {$opts(tag) ne {}} { set tags(numFmts,$opts(tag)) 49 } return 49 } if {$opts(datetime)} { set opts(format) {dd/mm/yyyy\ hh:mm;@} } if {$opts(iso8601)} { set opts(format) {yyyy\-mm\-dd\ hh:mm:ss;@} } foreach idx [array names ::ooxml::predefNumFmts] { if {[dict get $::ooxml::predefNumFmts($idx) fmt] eq $opts(format)} { if {$opts(tag) ne {}} { set tags(numFmts,$opts(tag)) $idx } return $idx } } foreach idx [array names numFmts] { if {$numFmts($idx) eq $opts(format)} { if {$opts(tag) ne {}} { set tags(numFmts,$opts(tag)) $idx } return $idx } } if {$opts(format) eq {}} { return -1 } set idx $obj(numFmts) set numFmts($idx) $opts(format) incr obj(numFmts) if {$opts(tag) ne {}} { set tags(numFmts,$opts(tag)) $idx } return $idx } method defaultdatestyle { style } { my variable obj my variable tags if {![string is integer -strict $style] && [info exists tags(styles,$style)]} { set style $tags(styles,$style) } set obj(defaultdatestyle) $style } method font { args } { my variable obj my variable fonts my variable tags array set a $fonts(0) array set opts " list 0 name [list $a(name)] family [list $a(family)] size [list $a(size)] color [list $a(color)] scheme [list $a(scheme)] bold 0 italic 0 underline 0 tag {} " set len [llength $args] set idx 0 for {set idx 0} {$idx < $len} {incr idx} { switch -- [set opt [lindex $args $idx]] { -name - -family - -size - -color - -scheme { incr idx if {$idx < $len} { set opts([string range $opt 1 end]) [lindex $args $idx] } else { error "option '$opt': missing argument" } } -list - -bold - -italic - -underline { set opts([string range $opt 1 end]) 1 } -tag { incr idx if {$idx < $len} { if {[string is integer -strict [set tag [lindex $args $idx]]]} { error "option '$opt': should not be an integer value" } else { set opts([string range $opt 1 end]) $tag } unset tag } else { error "option '$opt': missing argument" } } default { error "unknown option \"$opt\", should be: -name, -family, -size, -color, -scheme, -list, -bold, -italic, -underline or -tag" } } } if {$opts(list)} { return [array get fonts] } set obj(blockPreset) 1 if {$opts(name) eq {}} { set opts(name) $a(name) } if {![string is integer -strict $opts(family)] || $opts(family) < 0} { set opts(family) $a(family) } if {![string is integer -strict $opts(size)] || $opts(size) < 0} { set opts(size) $a(size) } if {$opts(scheme) ni {major minor none}} { set opts(scheme) $a(scheme) } set opts(color) [::ooxml::Color $opts(color)] foreach idx [lsort -integer [array names fonts]] { array set a $fonts($idx) set found 1 foreach name [array names a] { if {$a($name) ne $opts($name)} { set found 0 break } } if {$found} { if {$opts(tag) ne {}} { set tags(fonts,$opts(tag)) $idx } return $idx } } set fonts($obj(fonts)) {} foreach item {name family size bold italic underline color scheme} { lappend fonts($obj(fonts)) $item $opts($item) } set idx $obj(fonts) incr obj(fonts) if {$opts(tag) ne {}} { set tags(fonts,$opts(tag)) $idx } return $idx } method fill { args } { my variable obj my variable fills my variable tags array set opts { list 0 patterntype none fgcolor {} bgcolor {} tag {} } set len [llength $args] set idx 0 for {set idx 0} {$idx < $len} {incr idx} { switch -- [set opt [lindex $args $idx]] { -patterntype - -fgcolor - -bgcolor { incr idx if {$idx < $len} { set opts([string range $opt 1 end]) [lindex $args $idx] } else { error "option '$opt': missing argument" } } -list { set opts([string range $opt 1 end]) 1 } -tag { incr idx if {$idx < $len} { if {[string is integer -strict [set tag [lindex $args $idx]]]} { error "option '$opt': should not be an integer value" } else { set opts([string range $opt 1 end]) $tag } unset tag } else { error "option '$opt': missing argument" } } default { error "unknown option \"$opt\", should be: -patterntype, -fgcolor, -bgcolor, -list or -tag" } } } if {$opts(list)} { return [array get fills] } set obj(blockPreset) 1 if {$opts(patterntype) ni $::ooxml::predefPatternType} { set opts(patterntype) none } set opts(fgcolor) [::ooxml::Color $opts(fgcolor)] set opts(bgcolor) [::ooxml::Color $opts(bgcolor)] foreach idx [lsort -integer [array names fills]] { array set a $fills($idx) set found 1 foreach name [array names a] { if {$a($name) ne $opts($name)} { set found 0 break } } if {$found} { if {$opts(tag) ne {}} { set tags(fills,$opts(tag)) $idx } return $idx } } set fills($obj(fills)) {} foreach item {patterntype fgcolor bgcolor} { lappend fills($obj(fills)) $item $opts($item) } set idx $obj(fills) incr obj(fills) if {$opts(tag) ne {}} { set tags(fills,$opts(tag)) $idx } return $idx } method border { args } { my variable obj my variable borders my variable tags array set opts { list 0 leftstyle {} leftcolor {} rightstyle {} rightcolor {} topstyle {} topcolor {} bottomstyle {} bottomcolor {} diagonalstyle {} diagonalcolor {} diagonaldirection {} tag {} } set len [llength $args] set idx 0 for {set idx 0} {$idx < $len} {incr idx} { switch -- [set opt [lindex $args $idx]] { -leftstyle - -leftcolor - -rightstyle - -rightcolor - -topstyle - -topcolor - -bottomstyle - -bottomcolor - -diagonalstyle - -diagonalcolor - -diagonaldirection { incr idx if {$idx < $len} { set opts([string range $opt 1 end]) [lindex $args $idx] } else { error "option '$opt': missing argument" } } -list { set opts([string range $opt 1 end]) 1 } -tag { incr idx if {$idx < $len} { if {[string is integer -strict [set tag [lindex $args $idx]]]} { error "option '$opt': should not be an integer value" } else { set opts([string range $opt 1 end]) $tag } unset tag } else { error "option '$opt': missing argument" } } default { error "unknown option \"$opt\", should be: -leftstyle, -leftcolor, -rightstyle, -rightcolor, -topstyle, -topcolor, -bottomstyle, -bottomcolor, -diagonalstyle, -diagonalcolor, -diagonaldirection, -list or -tag" } } } if {$opts(list)} { return [array get borders] } set obj(blockPreset) 1 if {$opts(leftstyle) ni $::ooxml::predefBorderLineStyles || $opts(leftstyle) eq {none}} { set opts(leftstyle) {} } set opts(leftcolor) [::ooxml::Color $opts(leftcolor)] if {$opts(rightstyle) ni $::ooxml::predefBorderLineStyles || $opts(rightstyle) eq {none}} { set opts(rightstyle) {} } set opts(rightcolor) [::ooxml::Color $opts(rightcolor)] if {$opts(topstyle) ni $::ooxml::predefBorderLineStyles || $opts(topstyle) eq {none}} { set opts(topstyle) {} } set opts(topcolor) [::ooxml::Color $opts(topcolor)] if {$opts(bottomstyle) ni $::ooxml::predefBorderLineStyles || $opts(bottomstyle) eq {none}} { set opts(bottomstyle) {} } set opts(bottomcolor) [::ooxml::Color $opts(bottomcolor)] if {$opts(diagonalstyle) ni $::ooxml::predefBorderLineStyles || $opts(diagonalstyle) eq {none}} { set opts(diagonalstyle) {} } set opts(diagonalcolor) [::ooxml::Color $opts(diagonalcolor)] if {$opts(diagonaldirection) ni {up down}} { set opts(diagonaldirection) {} } switch -- $opts(diagonaldirection) { up { set opts(diagonaldirection) diagonalUp } down { set opts(diagonaldirection) diagonalDown } default { set opts(diagonaldirection) {} } } dict set tmp left style $opts(leftstyle) dict set tmp left color $opts(leftcolor) dict set tmp right style $opts(rightstyle) dict set tmp right color $opts(rightcolor) dict set tmp top style $opts(topstyle) dict set tmp top color $opts(topcolor) dict set tmp bottom style $opts(bottomstyle) dict set tmp bottom color $opts(bottomcolor) dict set tmp diagonal style $opts(diagonalstyle) dict set tmp diagonal color $opts(diagonalcolor) dict set tmp diagonal direction $opts(diagonaldirection) foreach idx [lsort -integer [array names borders]] { set found 1 foreach key [dict keys $tmp] { foreach subkey [dict keys [dict get $tmp $key]] { if {[dict get $borders($idx) $key $subkey] ne [dict get $tmp $key $subkey]} { set found 0 break } } } if {$found} { if {$opts(tag) ne {}} { set tags(borders,$opts(tag)) $idx } return $idx } } set borders($obj(borders)) $tmp set idx $obj(borders) incr obj(borders) if {$opts(tag) ne {}} { set tags(borders,$opts(tag)) $idx } return $idx } method style { args } { my variable obj my variable styles my variable tags array set opts { list 0 numfmt 0 font 0 fill 0 border 0 xf 0 horizontal {} vertical {} rotate {} wrap 0 tag {} } set len [llength $args] set idx 0 for {set idx 0} {$idx < $len} {incr idx} { switch -- [set opt [lindex $args $idx]] { -numfmt - -font - -fill - -border - -xf - -horizontal - -vertical - -rotate { incr idx if {$idx < $len} { set opts([string range $opt 1 end]) [lindex $args $idx] } else { error "option '$opt': missing argument" } } -list - -wrap { set opts([string range $opt 1 end]) 1 } -tag { incr idx if {$idx < $len} { if {[string is integer -strict [set tag [lindex $args $idx]]]} { error "option '$opt': should not be an integer value" } else { set opts([string range $opt 1 end]) $tag } unset tag } else { error "option '$opt': missing argument" } } default { error "unknown option \"$opt\", should be: -numfmt, -font, -fill, -border, -xf, -horizontal, -vertical, -rotate, -list, -wrap or -tag" } } } if {$opts(list)} { return [array get styles] } if {![string is integer -strict $opts(numfmt)] && [info exists tags(numFmts,$opts(numfmt))]} { set opts(numfmt) $tags(numFmts,$opts(numfmt)) } if {![string is integer -strict $opts(font)] && [info exists tags(fonts,$opts(font))]} { set opts(font) $tags(fonts,$opts(font)) } if {![string is integer -strict $opts(fill)] && [info exists tags(fills,$opts(fill))]} { set opts(fill) $tags(fills,$opts(fill)) } if {![string is integer -strict $opts(border)] && [info exists tags(borders,$opts(border))]} { set opts(border) $tags(borders,$opts(border)) } set obj(blockPreset) 1 if {![string is integer -strict $opts(numfmt)] || $opts(numfmt) < 0} { set opts(numfmt) 0 } if {![string is integer -strict $opts(font)] || $opts(font) < 0} { set opts(font) 0 } if {![string is integer -strict $opts(fill)] || $opts(fill) < 0} { set opts(fill) 0 } if {![string is integer -strict $opts(border)] || $opts(border) < 0} { set opts(border) 0 } if {![string is integer -strict $opts(xf)] || $opts(xf) < 0} { set opts(xf) 0 } if {$opts(horizontal) ni {right center left}} { set opts(horizontal) {} } if {$opts(vertical) ni {top center bottom}} { set opts(vertical) {} } if {![string is integer -strict $opts(rotate)] || $opts(rotate) < 0 || $opts(rotate) > 360} { set opts(rotate) {} } if {$opts(wrap) ne {1}} { set opts(wrap) {} } foreach idx [lsort -integer [array names styles]] { array set a $styles($idx) set found 1 foreach name [array names a] { if {$a($name) ne $opts($name)} { set found 0 break } } if {$found} { if {$opts(tag) ne {}} { set tags(styles,$opts(tag)) $idx } return $idx } } set styles($obj(styles)) {} foreach item {numfmt font fill border xf horizontal vertical rotate wrap} { lappend styles($obj(styles)) $item $opts($item) } set idx $obj(styles) incr obj(styles) if {$opts(tag) ne {}} { set tags(styles,$opts(tag)) $idx } return $idx } method worksheet { name } { my variable obj incr obj(sheets) set obj(callRow,$obj(sheets)) 0 set obj(sheet,$obj(sheets)) [string range [string map {: - \\ - / - ? - * - \[ ( \] )} $name] 0 30] set obj(gCol,$obj(sheets)) -1 set obj(row,$obj(sheets)) -1 set obj(col,$obj(sheets)) -1 set obj(dminrow,$obj(sheets)) 4294967295 set obj(dmaxrow,$obj(sheets)) 0 set obj(dmincol,$obj(sheets)) 4294967295 set obj(dmaxcol,$obj(sheets)) 0 set obj(autofilter,$obj(sheets)) {} set obj(freeze,$obj(sheets)) {} set obj(printarea,$obj(sheets)) {} set obj(merge,$obj(sheets)) {} set obj(rowHeight,$obj(sheets)) {} return $obj(sheets) } method column { sheet args } { my variable obj my variable cols my variable tags array set opts { index {} to {} width {} style 0 bestfit 0 customwidth 0 string 0 nozero 0 calcfit 0 } set len [llength $args] set idx 0 for {set idx 0} {$idx < $len} {incr idx} { switch -- [set opt [lindex $args $idx]] { -index - -to - -width - -style { incr idx if {$idx < $len} { set opts([string range $opt 1 end]) [lindex $args $idx] } else { error "option '$opt': missing argument" } } -bestfit - -customwidth - -string - -nozero - -calcfit { set opts([string range $opt 1 end]) 1 } default { error "unknown option \"$opt\", should be: -index, -to, -width, -style, -bestfit, -customwidth, -string, -nozero or -calcfit" } } } if {![string is integer -strict $opts(style)] && [info exists tags(styles,$opts(style))]} { set opts(style) $tags(styles,$opts(style)) } if {[regexp {^\d+$} $opts(index)] && $opts(index) > -1} { set obj(gCol,$sheet) $opts(index) } elseif {[regexp {^[A-Z]+$} $opts(index)]} { set obj(gCol,$sheet) [lindex [split [::ooxml::StringToRowColumn $opts(index)] ,] end] } elseif {[string trim $opts(index)] eq {}} { incr obj(gCol,$sheet) } set opts(index) $obj(gCol,$sheet) if {[regexp {^[A-Z]+$} $opts(to)]} { set opts(to) [lindex [split [::ooxml::StringToRowColumn $opts(to)] ,] end] } elseif {[string trim $opts(to)] eq {} || ![string is integer -strict $opts(to)] || $opts(to) <= $opts(index)} { set opts(to) $opts(index) } if {![string is double -strict $opts(width)] || $opts(width) < 0} { set opts(width) {} } if {![string is integer -strict $opts(style)] || $opts(style) < 0} { set opts(style) {} } if {$opts(width) ne {} || ([string is integer -strict $opts(style)] && $opts(style) >= 0) || $opts(bestfit) > 0} { if {$opts(width) eq {}} { set opts(width) $::ooxml::defaults(cols,width) } set cols($sheet,$opts(index)) [list min $opts(index) max $opts(to) width $opts(width) style $opts(style) bestfit $opts(bestfit) customwidth $opts(customwidth) string $opts(string) nozero $opts(nozero)] } set obj($sheet,cols) [llength [array names cols $sheet,*]] return $obj(gCol,$sheet) } method row { sheet args } { my variable obj array set opts { index {} height {} } set len [llength $args] set idx 0 for {set idx 0} {$idx < $len} {incr idx} { switch -- [set opt [lindex $args $idx]] { -index - -height { incr idx if {$idx < $len} { set opts([string range $opt 1 end]) [lindex $args $idx] } else { error "option '$opt': missing argument" } } default { error "unknown option \"$opt\", should be: -index or -height" } } } if {![string is integer -strict $opts(height)] || $opts(height) < 1 || $opts(height) > 1024} { set opts(height) {} } if {[string is integer -strict $opts(index)] && $opts(index) > -1} { set obj(callRow,$obj(sheets)) 1 set obj(col,$obj(sheets)) -1 set obj(row,$sheet) $opts(index) if {$opts(height) ne {}} { dict set obj(rowHeight,$sheet) $obj(row,$sheet) $opts(height) } return $obj(row,$sheet) } if {[string trim $opts(index)] eq {}} { set obj(callRow,$obj(sheets)) 1 set obj(col,$obj(sheets)) -1 incr obj(row,$sheet) if {$opts(height) ne {}} { dict set obj(rowHeight,$sheet) $obj(row,$sheet) $opts(height) } return $obj(row,$sheet) } return -1 } method rowheight { sheet row height } { my variable obj if {![string is integer -strict $row] || ![string is integer -strict $height] || $height < 1 || $height > 1024} { return -1 } dict set obj(rowHeight,$sheet) $row $height return $row } method cell { sheet {data {}} args } { my variable obj my variable cells my variable cols my variable tags my variable hlinks array set opts { index {} style -1 formula {} formulaidx {} formularef {} string -1 nostring -1 zero -1 nozero -1 globalstyle {} height {} hyperlink {} tooltip {} } set hyperlink 0 set len [llength $args] set idx 0 for {set idx 0} {$idx < $len} {incr idx} { switch -- [set opt [lindex $args $idx]] { -index - -style - -formula - -formulaidx - -formularef - -height - -hyperlink - -tooltip { incr idx if {$idx < $len} { set opts([string range $opt 1 end]) [lindex $args $idx] } else { error "option '$opt': missing argument" } } -string - -nostring - -zero - -nozero - -globalstyle { set opts([string range $opt 1 end]) 1 } default { error "unknown option \"$opt\", should be: -index, -style, -formula, -formulaidx, -formularef, -height, -hyperlink, -string, -nostring, -tooltip -zero or -nozero" } } } if {![string is integer -strict $opts(style)] && [info exists tags(styles,$opts(style))]} { set opts(style) $tags(styles,$opts(style)) } if {$opts(nostring) == 1} { set opts(string) 0 } if {$opts(zero) == 1} { set opts(nozero) 0 } if {!$obj(callRow,$obj(sheets))} { set obj(callRow,$obj(sheets)) 1 incr obj(row,$sheet) } if {[regexp {^\d+$} $opts(index)] && $opts(index) > -1} { set obj(col,$sheet) $opts(index) } elseif {[regexp {^[A-Z]+$} $opts(index)]} { set obj(col,$sheet) [lindex [split [::ooxml::StringToRowColumn $opts(index)] ,] end] } elseif {[regexp {^(\d+),(\d+)$} $opts(index)]} { lassign [split $opts(index) ,] obj(row,$sheet) obj(col,$sheet) } elseif {[regexp {^[A-Z]+\d+$} $opts(index)]} { lassign [split [::ooxml::StringToRowColumn $opts(index)] ,] obj(row,$sheet) obj(col,$sheet) } elseif {[string trim $opts(index)] eq {}} { incr obj(col,$sheet) } elseif {[string is double -strict $opts(index)]} { error "option '-index $opts(index)': wrong argument, should not be double" } if {$obj(row,$sheet) < 0 || $obj(col,$sheet) < 0} { return -1 } if {[string is integer -strict $opts(style)] && $opts(style) == -1} { if {[info exists cols($sheet,$obj(col,$sheet))] && [dict get $cols($sheet,$obj(col,$sheet)) style] >= 0} { set opts(style) [dict get $cols($sheet,$obj(col,$sheet)) style] } elseif {$opts(style) == -1} { set opts(style) 0 } } if {[string is integer -strict $opts(string)] && $opts(string) == -1} { if {[info exists cols($sheet,$obj(col,$sheet))] && [dict get $cols($sheet,$obj(col,$sheet)) string] == 1} { set opts(string) 1 } elseif {$opts(string) == -1} { set opts(string) 0 } } if {[string is integer -strict $opts(nozero)] && $opts(nozero) == -1} { if {[info exists cols($sheet,$obj(col,$sheet))] && [dict get $cols($sheet,$obj(col,$sheet)) nozero] == 1} { set opts(nozero) 1 } elseif {$opts(nozero) == -1} { set opts(nozero) 0 } } set cell ${sheet},$obj(row,$sheet),$obj(col,$sheet) set cells($cell) {} if {[string is integer -strict $opts(height)] && $opts(height) > 0 && $opts(height) < 1024} { dict set obj(rowHeight,$sheet) $obj(row,$sheet) $opts(height) } set data [string trimright $data] if {$opts(nozero) && [string is double -strict $data] && $data == 0} { set data {} } if {[string trim $opts(hyperlink)] ne {}} { set hyperlink 1 set hlinks($cell) [list l [string trim $opts(hyperlink)]] if {$data eq {}} { set data [dict get $hlinks($cell) l] } if {[string trim $opts(tooltip)] ne {}} { lappend hlinks($cell) t [string trim $opts(tooltip)] } } if {$opts(string)} { set type s } elseif {[set datetime [::ooxml::ScanDateTime $data]] ne {}} { set type n set data $datetime if {[string is integer -strict $opts(style)] && $opts(style) < 1} { set opts(style) $obj(defaultdatestyle) } } elseif {[string is double -strict $data]} { set type n set data [string trim $data] if {$data in {Inf infinity NaN -NaN} || $opts(string)} { set type s } } else { set type s } if {[string is integer -strict $opts(style)] && $opts(style) > 0} { lappend cells($cell) s $opts(style) } ## FORMULA ## if {!$hyperlink && ([string trim $opts(formula)] ne {} || [string is integer -strict $opts(formulaidx)])} { lappend cells($cell) t $type lappend cells($cell) f $opts(formula) if {[string trim $opts(formulaidx)] ne {}} { lappend cells($cell) fsi $opts(formulaidx) } if {[string trim $opts(formularef)] ne {}} { set lref [split [string trim $opts(formularef)] :] if {[llength $lref] == 2} { set fref {} if {[regexp {^(\d+),(\d+)$} [lindex $lref 0]]} { append fref [::ooxml::IndexToString [lindex $lref 0]] } else { append fref [lindex $lref 0] } append fref : if {[regexp {^(\d+),(\d+)$} [lindex $lref 1]]} { append fref [::ooxml::IndexToString [lindex $lref 1]] } else { append fref [lindex $lref 1] } lappend cells($cell) fsr $fref } } } else { lappend cells($cell) v $data t $type } if {[string trim $data] eq {} && [string trim $opts(formula)] eq {} && [string trim $opts(formulaidx)] eq {} && ![string is integer -strict $opts(style)] && $opts(style) < 1} { unset -nocomplain cells($cell) } else { if {$obj(row,$sheet) < $obj(dminrow,$sheet)} { set obj(dminrow,$sheet) $obj(row,$sheet) } if {$obj(row,$sheet) > $obj(dmaxrow,$sheet)} { set obj(dmaxrow,$sheet) $obj(row,$sheet) } if {$obj(col,$sheet) < $obj(dmincol,$sheet)} { set obj(dmincol,$sheet) $obj(col,$sheet) } if {$obj(col,$sheet) > $obj(dmaxcol,$sheet)} { set obj(dmaxcol,$sheet) $obj(col,$sheet) } } return $obj(row,$sheet),$obj(col,$sheet) } method autofilter { sheet indexFrom indexTo } { my variable obj set indexFrom [::ooxml::IndexToString $indexFrom] set indexTo [::ooxml::IndexToString $indexTo] if {$indexFrom ne {} && $indexTo ne {}} { set obj(autofilter,$sheet) $indexFrom:$indexTo return 0 } return 1 } method freeze { sheet index } { my variable obj set index [::ooxml::IndexToString $index] if {$index ne {}} { set obj(freeze,$sheet) $index return 0 } return 1 } method printarea { sheet indexFrom indexTo } { my variable obj set indexFrom [::ooxml::IndexFix [::ooxml::IndexToString $indexFrom] {row col}] set indexTo [::ooxml::IndexFix [::ooxml::IndexToString $indexTo] {row col}] if {$indexFrom ne {} && $indexTo ne {}} { set obj(printarea,$sheet) $indexFrom:$indexTo return 0 } return 1 } method merge { sheet indexFrom indexTo } { my variable obj set indexFrom [::ooxml::IndexToString $indexFrom] set indexTo [::ooxml::IndexToString $indexTo] if {$indexFrom ne {} && $indexTo ne {} && "$indexFrom:$indexTo" ni $obj(merge,$sheet)} { lappend obj(merge,$sheet) $indexFrom:$indexTo return 0 } return 1 } method presetstyles { valName args } { my variable obj my variable cols my variable fonts my variable numFmts my variable styles my variable fills my variable borders if {$obj(blockPreset)} { return 1 } upvar $valName a if {[info exists a(s,@)]} { set obj(blockPreset) 1 if {[dict exists $a(s,@) numFmtId]} { set obj(numFmts) [dict get $a(s,@) numFmtId] foreach idx $a(s,numFmtsIds) { if {[info exists a(s,numFmts,$idx)]} { set numFmts($idx) $a(s,numFmts,$idx) } } } foreach item {fonts fills borders styles} { if {[dict exists $a(s,@) $item]} { upvar 0 $item ad for {set idx 0} {$idx < [dict get $a(s,@) $item]} {incr idx} { if {[info exists a(s,$item,$idx)]} { set ad($idx) $a(s,$item,$idx) } } set obj($item) [dict get $a(s,@) $item] } } } foreach sheet $a(sheets) { foreach item [array names a $sheet,col,*] { set idx [lindex [split $item ,] end] if {[info exists a($sheet,col,$idx)]} { set cols([expr {$sheet + 1}],$idx) $a($sheet,col,$idx) } } set obj([expr {$sheet + 1}],cols) [llength [array names cols]] } return 0 } method presetsheets { valName args } { upvar $valName a # [self object] -> my if {[info exists a(sheets)]} { foreach sheet [lsort -integer $a(sheets)] { if {[set currentSheet [my worksheet $a($sheet,n)]] > -1} { dict set a(sheetmap) $sheet $currentSheet foreach item [lsort -dictionary [array names a $sheet,v,*]] { lassign [split $item ,] sheet tag row col set options [list -index $row,$col] if {[info exists a($sheet,f,$row,$col)]} { ## FORMULA ## if {[dict exists $a($sheet,f,$row,$col) f]} { lappend options -formula [dict get $a($sheet,f,$row,$col) f] if {[dict exists $a($sheet,f,$row,$col) r]} { lappend options -formularef [dict get $a($sheet,f,$row,$col) r] } } if {[dict exists $a($sheet,f,$row,$col) i]} { lappend options -formulaidx [dict get $a($sheet,f,$row,$col) i] } } if {[info exists a($sheet,t,$row,$col)] && $a($sheet,t,$row,$col) eq {s}} { lappend options -string } if {[info exists a($sheet,s,$row,$col)]} { lappend options -style $a($sheet,s,$row,$col) } if {[info exists a($sheet,l,$row,$col)]} { lappend options -hyperlink [dict get $a($sheet,l,$row,$col) l] if {[dict exists $a($sheet,l,$row,$col) t] && [string trim [dict get $a($sheet,l,$row,$col) t]] ne {}} { lappend options -tooltip [dict get $a($sheet,l,$row,$col) t] } } my cell $currentSheet $a($item) {*}$options } if {[info exists a($sheet,rowheight)]} { foreach {row height} $a($sheet,rowheight) { my rowheight $currentSheet $row $height } } if {[info exists a($sheet,freeze)]} { my freeze $currentSheet $a($sheet,freeze) } if {[info exists a($sheet,filter)]} { foreach item $a($sheet,filter) { my autofilter $currentSheet {*}[split $item :] } } if {[info exists a($sheet,printarea)]} { foreach item $a($sheet,printarea) { my printarea $currentSheet {*}[split [string map {{$} {}} $item] :] } } if {[info exists a($sheet,merge)]} { foreach item $a($sheet,merge) { my merge $currentSheet {*}[split $item :] } } } if {[info exists a($sheet,pageMargins)]} { my pageMargins $currentSheet {*}$a($sheet,pageMargins) } if {[info exists a($sheet,pageSetup)]} { my pageSetup $currentSheet {*}$a($sheet,pageSetup) } } } if {[info exists a(view)]} { foreach item {activetab} { if {[dict exists $a(view) $item]} { my view -$item [dict get $a(view) $item] } } } } method view { args } { my variable view array set opts { list 0 } set len [llength $args] set idx 0 for {set idx 0} {$idx < $len} {incr idx} { switch -- [set opt [lindex $args $idx]] { -activetab - -x - -y - -height - -width { incr idx if {$idx < $len} { if {[string is integer -strict [lindex $args $idx]] && [lindex $args $idx] > -1} { set view([string range $opt 1 end]) [lindex $args $idx] } else { error "option '$opt': must be a positive integer" } } else { error "option '$opt': missing argument" } } -list { set opts([string range $opt 1 end]) 1 } default { error "unknown option \"$opt\", should be: -activetab, -x, -y, -height, -width or -list" } } } if {$opts(list)} { return [array get view] } } method processPageMarigns { defaults options } { array set opts $defaults set len [llength $options] set idx 0 for {set idx 0} {$idx < $len} {incr idx} { switch -- [set opt [lindex $options $idx]] { -left - -right - -top - -bottom - -header - -footer { incr idx if {$idx < $len} { set value [lindex $options $idx] if {![string is double -strict $value]} { error "option '$opt': value must be a double (in inch)" } set opts([string range $opt 1 end]) $value } else { error "option '$opt': missing argument" } } default { error "unknown option \"$opt\", should be: -left -right -top -bottom -header or -footer" } } } return [array get opts] } method pageMarginsDefault { args } { my variable pageMarginsDefault set pageMarginsDefault [my processPageMarigns $pageMarginsDefault $args] } method pageMargins { sheet args } { my variable pageMargins my variable pageMarginsDefault if {[info exists pageMargins($sheet)]} { set defaults $pageMargins($sheet) } else { set defaults $pageMarginsDefault } set pageMarginsDefault [my processPageMarigns $defaults $args] } method pageSetup { sheet args } { my variable pageSetups if {[info exists pageSetups($sheet)]} { array set opts $pageSetups($sheet) } set validOptions { -blackAndWhite -cellComments -copies -draft -errors -firstPageNumber -fitToHeight -fitToWidth -horziontalDpi -horizontalDpi -orientation -pageOrder -paperHeight -paperSize -paperWide -paperWidth -scale -useFirstPageNumber -verticalDpi } set len [llength $args] set idx 0 for {set idx 0} {$idx < $len} {incr idx} { set opt [lindex $args $idx] if {$opt in $validOptions} { incr idx if {$idx < $len} { set value [lindex $args $idx] switch -- $opt { -blackAndWhite - -draft - -useFirstPageNumber - -usePrinterDefaults { # xsd boolean value if {$value ni {true false 0 1}} { error "invalid value '$value' for the $opt option:\ must be an XSD boolean (true, false, 0 or 1)" } } -cellComments { if {$value ni {none asDisplayed atEnd}} { error "invalid value '$value' for the -cellComments option:\ must be none, asDisplayed or atEnd" } } -copies - -firstPageNumber - -fitToHeight - -fitToWidth - -horziontalDpi - -horizontalDpi - -scale - -verticalDpi { # xsd unsignedInt if {![string is integer -strict $value] || $value < 0} { error "invalid value '$value' for the $opt option:\ must be an XSD unsignedInt" } } -errors { if {$value ni {displayed blank dash NA}} { error "invalid value '$value' for the -errors option:\ must be displayed blank dash or NA" } } -orientation { if {$value ni {default portrait landscape}} { error "invalid value '$value' for the -orientation option:\ must be default, portrait or landscape" } } -pageOrder { if {$value ni {downThenOver overThenDown}} { error "invalid value '$value' for the -pageOrder option:\ must be downThenOver or overThenDown" } } -paperHeight - -paperWide - -paperWidth { if {![regexp {[0-9]+(\.[0-9]+)?(mm|cm|in|pt|pc|pi)} $value]} { error "invalid value '$value' for the $opt option:\ must match the regular expresion \[0-9\]+(\\.\[0-9\]+)?(mm|cm|in|pt|pc|pi)" } } -paperSize { if {![string is integer -strict $value] || $value < 1 || $value > 118} { error "invalid value '$value' for the -paperSize option:\ must be an integer from 1 to 118. See the user documentation\ for what paper size each number stand ( 1 = Letter, 9 = A4)" } } } set opts([string range $opt 1 end]) $value } else { error "option '$opt': missing argument" } } else { error "unknown option \"$opt\", should be: [join [lrange $validOptions 0 end-1] ,] or [lindex $validOptions end]" } } set pageSetups($sheet) [array get opts] } method debug { args } { foreach item $args { catch { my variable $item parray $item } } } method write { file } { my variable obj my variable cells my variable sharedStrings my variable fonts my variable numFmts my variable styles my variable fills my variable borders my variable cols my variable view my variable hlinks my variable pageMargins my variable pageMarginsDefault my variable pageSetups upvar #0 ::ooxml::xmlns xmlns ooxml::InitNodeCommands namespace import ::ooxml::Tag_* ::ooxml::Text # Initialize zip file set file [string trim $file] if {$file eq {}} { set file {spreadsheetml.xlsx} } if {[file extension $file] ne {.xlsx}} { append file {.xlsx} } if {[catch {open $file w} zf]} { error "cannot open file $file for writing" } fconfigure $zf -translation binary -eofchar {} set count 0 set cd {} foreach {n v} [array get cells] { if {[dict exists $v t] && [dict get $v t] eq {s} && [dict exists $v v] && [dict get $v v] ne {}} { set thisv [dict get $v v] if {[info exists lookup($thisv)]} { set pos $lookup($thisv) } else { set pos [llength $sharedStrings] lappend sharedStrings $thisv set lookup($thisv) $pos } set obj(sharedStrings) 1 dict set cells($n) v $pos } } unset -nocomplain n v array unset lookup # ------------------------------ _rels/.rels ------------------------------ # In the commented out part, serialization is done with namespaces set correctly, but this takes a few milliseconds more time. # Since we may process large amounts of data and do not use the same tag names in different namespaces and do not search in # the DOM during serialization, we only set the namespaces as attributes, which leads to the same result in the serialized XML. # set doc [dom createDocumentNS $xmlns(PR) Relationships] # set root [$doc documentElement] dom createDocument Relationships doc $doc documentElement root $root setAttribute xmlns $xmlns(PR) set rId 0 $root appendFromScript { Tag_Relationship Id rId1 Type http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument Target xl/workbook.xml {} Tag_Relationship Id rId2 Type http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties Target docProps/app.xml {} Tag_Relationship Id rId3 Type http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties Target docProps/core.xml {} } ::ooxml::Dom2zip $zf $root "_rels/.rels" cd count $doc delete # ------------------------------ [Content_Types].xml ------------------------------ # In the commented out part, serialization is done with namespaces set correctly, but this takes a few milliseconds more time. # Since we may process large amounts of data and do not use the same tag names in different namespaces and do not search in # the DOM during serialization, we only set the namespaces as attributes, which leads to the same result in the serialized XML. # set doc [dom createDocumentNS $xmlns(CT) Types] # set root [$doc documentElement] dom createDocument Types doc $doc documentElement root $root setAttribute xmlns $xmlns(CT) $root appendFromScript { Tag_Default Extension xml ContentType application/xml {} Tag_Default Extension rels ContentType application/vnd.openxmlformats-package.relationships+xml {} Tag_Override PartName /xl/workbook.xml ContentType application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml {} Tag_Override PartName /xl/worksheets/sheet1.xml ContentType application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml {} for {set ws 1} {$ws <= $obj(sheets)} {incr ws} { Tag_Override PartName /xl/theme/theme${ws}.xml ContentType application/vnd.openxmlformats-officedocument.theme+xml {} } Tag_Override PartName /xl/styles.xml ContentType application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml {} if {$obj(sharedStrings) > 0} { Tag_Override PartName /xl/sharedStrings.xml ContentType application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml {} } if {$obj(calcChain)} { Tag_Override PartName /xl/calcChain.xml ContentType application/vnd.openxmlformats-officedocument.spreadsheetml.calcChain+xml {} } Tag_Override PartName /docProps/core.xml ContentType application/vnd.openxmlformats-package.core-properties+xml {} Tag_Override PartName /docProps/app.xml ContentType application/vnd.openxmlformats-officedocument.extended-properties+xml {} } ::ooxml::Dom2zip $zf $root "\[Content_Types\].xml" cd count $doc delete # ------------------------------ docProps/app.xml ------------------------------ # In the commented out part, serialization is done with namespaces set correctly, but this takes a few milliseconds more time. # Since we may process large amounts of data and do not use the same tag names in different namespaces and do not search in # the DOM during serialization, we only set the namespaces as attributes, which leads to the same result in the serialized XML. # set doc [dom createDocumentNS $xmlns(EP) Properties] # set root [$doc documentElement] # $root setAttributeNS {} xmlns:vt $xmlns(vt) dom createDocument Properties doc $doc documentElement root $root setAttribute xmlns $xmlns(EP) $root setAttribute xmlns:vt $xmlns(vt) $root appendFromScript { Tag_Application { Text $obj(application) } Tag_DocSecurity { Text 0 } Tag_ScaleCrop { Text false } Tag_HeadingPairs { Tag_vt:vector size 2 baseType variant { Tag_vt:variant { Tag_vt:lpstr { Text [msgcat::mc Worksheets] } } Tag_vt:variant { Tag_vt:i4 { Text $obj(sheets) } } } } Tag_TitlesOfParts { Tag_vt:vector size $obj(sheets) baseType lpstr { for {set ws 1} {$ws <= $obj(sheets)} {incr ws} { Tag_vt:lpstr { Text [msgcat::mc Sheet]$ws } } } } Tag_Company {} Tag_LinksUpToDate { Text false } Tag_SharedDoc { Text false } Tag_HyperlinksChanged { Text false } Tag_AppVersion { Text 1.0 } } ::ooxml::Dom2zip $zf $root "docProps/app.xml" cd count $doc delete # ------------------------------ docProps/core.xml ------------------------------ # In the commented out part, serialization is done with namespaces set correctly, but this takes a few milliseconds more time. # Since we may process large amounts of data and do not use the same tag names in different namespaces and do not search in # the DOM during serialization, we only set the namespaces as attributes, which leads to the same result in the serialized XML. # set doc [dom createDocumentNS $xmlns(cp) cp:coreProperties] # set root [$doc documentElement] # $root setAttributeNS {} xmlns:dc $xmlns(dc) # $root setAttributeNS {} xmlns:dcterms $xmlns(dcterms) # $root setAttributeNS {} xmlns:dcmitype $xmlns(dcmitype) # $root setAttributeNS {} xmlns:xsi $xmlns(xsi) dom createDocument cp:coreProperties doc $doc documentElement root $root setAttributeNS {} xmlns:cp $xmlns(cp) $root setAttributeNS {} xmlns:dc $xmlns(dc) $root setAttributeNS {} xmlns:dcterms $xmlns(dcterms) $root setAttributeNS {} xmlns:dcmitype $xmlns(dcmitype) $root setAttributeNS {} xmlns:xsi $xmlns(xsi) $root setAttribute xmlns:xsi $xmlns(xsi) $root appendFromScript { Tag_dc:creator { Text $obj(creator) } Tag_cp:lastModifiedBy { Text $obj(lastModifiedBy) } Tag_dcterms:created xsi:type dcterms:W3CDTF { Text $obj(created) } Tag_dcterms:modified xsi:type dcterms:W3CDTF { Text $obj(modified) } } ::ooxml::Dom2zip $zf $root "docProps/core.xml" cd count $doc delete # ------------------------------ xl/_rels/workbook.xml.rels ------------------------------ # In the commented out part, serialization is done with namespaces set correctly, but this takes a few milliseconds more time. # Since we may process large amounts of data and do not use the same tag names in different namespaces and do not search in # the DOM during serialization, we only set the namespaces as attributes, which leads to the same result in the serialized XML. # set doc [dom createDocumentNS $xmlns(PR) Relationships] # set root [$doc documentElement] dom createDocument Relationships doc $doc documentElement root $root setAttribute xmlns $xmlns(PR) $root appendFromScript { for {set ws 1} {$ws <= $obj(sheets)} {incr ws} { Tag_Relationship Id rId$ws Type http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet Target worksheets/sheet${ws}.xml {} } set rId [incr ws -1] Tag_Relationship Id rId[incr rId] Type http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme Target theme/theme1.xml {} Tag_Relationship Id rId[incr rId] Type http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles Target styles.xml {} if {$obj(sharedStrings) > 0} { Tag_Relationship Id rId[incr rId] Type http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings Target sharedStrings.xml {} } if {$obj(calcChain)} { Tag_Relationship Id rId[incr rId] Type http://schemas.openxmlformats.org/officeDocument/2006/relationships/calcChain Target calcChain.xml {} } } ::ooxml::Dom2zip $zf $root "xl/_rels/workbook.xml.rels" cd count $doc delete # ------------------------------ xl/sharedStrings.xml ------------------------------ # In the commented out part, serialization is done with namespaces set correctly, but this takes a few milliseconds more time. # Since we may process large amounts of data and do not use the same tag names in different namespaces and do not search in # the DOM during serialization, we only set the namespaces as attributes, which leads to the same result in the serialized XML. # set doc [dom createDocumentNS $xmlns(M) sst] # set root [$doc documentElement] if {$obj(sharedStrings) > 0} { dom createDocument sst doc $doc documentElement root $root setAttribute xmlns $xmlns(M) $root setAttribute count [llength $sharedStrings] $root setAttribute uniqueCount [llength $sharedStrings] $root appendFromScript { foreach string $sharedStrings { Tag_si { Tag_t { Text $string } } } # garbage collection set sharedStrings {} } ::ooxml::Dom2zip $zf $root "xl/sharedStrings.xml" cd count $doc delete } # ------------------------------ xl/calcChain.xml ------------------------------ # In the commented out part, serialization is done with namespaces set correctly, but this takes a few milliseconds more time. # Since we may process large amounts of data and do not use the same tag names in different namespaces and do not search in # the DOM during serialization, we only set the namespaces as attributes, which leads to the same result in the serialized XML. # set doc [dom createDocumentNS $xmlns(M) calcChain] # set root [$doc documentElement] if {$obj(calcChain)} { dom createDocument calcChain doc $doc documentElement root $root setAttribute xmlns $xmlns(M) $root appendFromScript { Tag_c r C1 i 3 l 1 {} Tag_c r A3 i 2 {} } ::ooxml::Dom2zip $zf $root "xl/calcChain.xml" cd count $doc delete } # ------------------------------ xl/styles.xml ------------------------------ # In the commented out part, serialization is done with namespaces set correctly, but this takes a few milliseconds more time. # Since we may process large amounts of data and do not use the same tag names in different namespaces and do not search in # the DOM during serialization, we only set the namespaces as attributes, which leads to the same result in the serialized XML. # set doc [dom createDocumentNS $xmlns(M) styleSheet] # set root [$doc documentElement] # $root setAttributeNS {} xmlns:mc $xmlns(mc) # $root setAttributeNS {} xmlns:x14ac $xmlns(x14ac) dom createDocument styleSheet doc $doc documentElement root $root setAttribute xmlns $xmlns(M) $root setAttributeNS {} xmlns:mc $xmlns(mc) $root setAttributeNS {} xmlns:x14ac $xmlns(x14ac) $root setAttribute mc:Ignorable x14ac $root appendFromScript { if {$obj(numFmts) > $::ooxml::defaults(numFmts,start)} { Tag_numFmts count [llength [array names numFmts]] { foreach idx [lsort -integer [array names numFmts]] { Tag_numFmt numFmtId $idx formatCode $numFmts($idx) {} } } } Tag_fonts count $obj(fonts) x14ac:knownFonts 1 { foreach idx [lsort -integer [array names fonts]] { Tag_font { if {[dict get $fonts($idx) color] ne {}} { Tag_color [lindex [dict get $fonts($idx) color] 0] [lindex [dict get $fonts($idx) color] 1] } if {[dict get $fonts($idx) bold] == 1} { Tag_b {} } if {[dict get $fonts($idx) italic] == 1} { Tag_i {} } if {[dict get $fonts($idx) underline] == 1} { Tag_u {} } Tag_sz val [dict get $fonts($idx) size] {} Tag_name val [dict get $fonts($idx) name] {} Tag_family val [dict get $fonts($idx) family] {} Tag_scheme val [dict get $fonts($idx) scheme] {} } } } if {$obj(fills) > 0} { Tag_fills count $obj(fills) { foreach idx [lsort -integer [array names fills]] { Tag_fill { Tag_patternFill patternType [dict get $fills($idx) patterntype] { foreach tag {fgColor bgColor} { set key [string tolower $tag] if {[dict get $fills($idx) $key] ne {}} { Tag_$tag [lindex [dict get $fills($idx) $key] 0] [lindex [dict get $fills($idx) $key] 1] {} } } } } } } } if {$obj(borders) > 0} { Tag_borders count $obj(borders) { foreach idx [lsort -integer [array names borders]] { set attr {} if {[dict exists $borders($idx) diagonal direction] && [dict get $borders($idx) diagonal direction] ne {}} { lappend attr [string map {up diagonalUp down diagonalDown} [dict get $borders($idx) diagonal direction]] 1 } Tag_border {*}$attr { foreach item {left right top bottom diagonal} { set attr {} if {[dict exists $borders($idx) $item style] && [dict get $borders($idx) $item style] ne {}} { lappend attr style [dict get $borders($idx) $item style] } Tag_$item {*}$attr { if {[dict exists $borders($idx) $item color] && [dict get $borders($idx) $item color] ne {}} { Tag_color [lindex [dict get $borders($idx) $item color] 0] [lindex [dict get $borders($idx) $item color] 1] {} } } } } } } } Tag_cellStyleXfs count 1 { Tag_xf numFmtId 0 fontId 0 fillId 0 borderId 0 {} } Tag_cellXfs count $obj(styles) { foreach idx [lsort -integer [array names styles]] { set attr {} lappend attr numFmtId [dict get $styles($idx) numfmt] lappend attr fontId [dict get $styles($idx) font] lappend attr fillId [dict get $styles($idx) fill] lappend attr borderId [dict get $styles($idx) border] lappend attr xfId [dict get $styles($idx) xf] if {[dict get $styles($idx) numfmt] > 0} { lappend attr applyNumberFormat 1 } if {[dict get $styles($idx) font] > 0} { lappend attr applyFont 1 } if {[dict get $styles($idx) fill] > 0} { lappend attr applyFill 1 } if {[dict get $styles($idx) border] > 0} { lappend attr applyBorder 1 } # lappend attr applyProtection 1 quotePrefix 1 if {[dict get $styles($idx) horizontal] ne {} || [dict get $styles($idx) vertical] ne {} || [dict get $styles($idx) rotate] ne {} || [dict get $styles($idx) wrap] ne {}} { lappend attr applyAlignment 1 set alignment 1 } else { set alignment 0 } Tag_xf {*}$attr { set attr {} if {$alignment} { if {[dict get $styles($idx) horizontal] ne {}} { lappend attr horizontal [dict get $styles($idx) horizontal] } if {[dict get $styles($idx) vertical] ne {}} { lappend attr vertical [dict get $styles($idx) vertical] } if {[dict get $styles($idx) rotate] ne {}} { lappend attr textRotation [dict get $styles($idx) rotate] } if {[dict get $styles($idx) wrap] ne {}} { lappend attr wrapText [dict get $styles($idx) wrap] } Tag_alignment {*}$attr {} } } } } Tag_cellStyles count 1 { Tag_cellStyle name Standard xfId 0 builtinId 0 {} } Tag_dxfs count 0 {} Tag_tableStyles count 0 {} } ::ooxml::Dom2zip $zf $root "xl/styles.xml" cd count $doc delete # ------------------------------ xl/theme/theme1.xml ------------------------------ # In the commented out part, serialization is done with namespaces set correctly, but this takes a few milliseconds more time. # Since we may process large amounts of data and do not use the same tag names in different namespaces and do not search in # the DOM during serialization, we only set the namespaces as attributes, which leads to the same result in the serialized XML. set doc [dom createDocumentNS $xmlns(a) a:theme] set root [$doc documentElement] dom createDocument a:theme doc $doc documentElement root $root setAttribute xmlns:a $xmlns(a) $root setAttribute name Office-Design $root appendFromScript { Tag_a:themeElements { Tag_a:clrScheme name Office { Tag_a:dk1 { Tag_a:sysClr val windowText lastClr 000000 {} } Tag_a:lt1 { Tag_a:sysClr val window lastClr FFFFFF {} } Tag_a:dk2 { Tag_a:srgbClr val 1F497D {} } Tag_a:lt2 { Tag_a:srgbClr val EEECE1 {} } Tag_a:accent1 { Tag_a:srgbClr val 4F81BD {} } Tag_a:accent2 { Tag_a:srgbClr val C0504D {} } Tag_a:accent3 { Tag_a:srgbClr val 9BBB59 {} } Tag_a:accent4 { Tag_a:srgbClr val 8064A2 {} } Tag_a:accent5 { Tag_a:srgbClr val 4BACC6 {} } Tag_a:accent6 { Tag_a:srgbClr val F79646 {} } Tag_a:hlink { Tag_a:srgbClr val 0000FF {} } Tag_a:folHlink { Tag_a:srgbClr val 800080 {} } } Tag_a:fontScheme name Office { Tag_a:majorFont { Tag_a:latin typeface Cambria {} Tag_a:ea typeface {} {} Tag_a:cs typeface {} {} Tag_a:font script Jpan typeface \uFF2D\uFF33\u0020\uFF30\u30B4\u30B7\u30C3\u30AF {} Tag_a:font script Hang typeface \uB9D1\uC740\u0020\uACE0\uB515 {} Tag_a:font script Hans typeface \u5B8B\u4F53 {} Tag_a:font script Hant typeface \u65B0\u7D30\u660E\u9AD4 {} Tag_a:font script Arab typeface {Times New Roman} {} Tag_a:font script Hebr typeface {Times New Roman} {} Tag_a:font script Thai typeface Tahoma {} Tag_a:font script Ethi typeface Nyala {} Tag_a:font script Beng typeface Vrinda {} Tag_a:font script Gujr typeface Shruti {} Tag_a:font script Khmr typeface MoolBoran {} Tag_a:font script Knda typeface Tunga {} Tag_a:font script Guru typeface Raavi {} Tag_a:font script Cans typeface Euphemia {} Tag_a:font script Cher typeface {Plantagenet Cherokee} {} Tag_a:font script Yiii typeface {Microsoft Yi Baiti} {} Tag_a:font script Tibt typeface {Microsoft Himalaya} {} Tag_a:font script Thaa typeface {MV Boli} {} Tag_a:font script Deva typeface Mangal {} Tag_a:font script Telu typeface Gautami {} Tag_a:font script Taml typeface Latha {} Tag_a:font script Syrc typeface {Estrangelo Edessa} {} Tag_a:font script Orya typeface Kalinga {} Tag_a:font script Mlym typeface Kartika {} Tag_a:font script Laoo typeface DokChampa {} Tag_a:font script Sinh typeface {Iskoola Pota} {} Tag_a:font script Mong typeface {Mongolian Baiti} {} Tag_a:font script Viet typeface {Times New Roman} {} Tag_a:font script Uigh typeface {Microsoft Uighur} {} Tag_a:font script Geor typeface Sylfaen {} } Tag_a:minorFont { Tag_a:latin typeface Calibri {} Tag_a:ea typeface {} {} Tag_a:cs typeface {} {} Tag_a:font script Jpan typeface \uFF2D\uFF33\u0020\uFF30\u30B4\u30B7\u30C3\u30AF {} Tag_a:font script Hang typeface \uB9D1\uC740\u0020\uACE0\uB515 {} Tag_a:font script Hans typeface \u5B8B\u4F53 {} Tag_a:font script Hant typeface \u65B0\u7D30\u660E\u9AD4 {} Tag_a:font script Arab typeface Arial {} Tag_a:font script Hebr typeface Arial {} Tag_a:font script Thai typeface Tahoma {} Tag_a:font script Ethi typeface Nyala {} Tag_a:font script Beng typeface Vrinda {} Tag_a:font script Gujr typeface Shruti {} Tag_a:font script Khmr typeface DaunPenh {} Tag_a:font script Knda typeface Tunga {} Tag_a:font script Guru typeface Raavi {} Tag_a:font script Cans typeface Euphemia {} Tag_a:font script Cher typeface {Plantagenet Cherokee} {} Tag_a:font script Yiii typeface {Microsoft Yi Baiti} {} Tag_a:font script Tibt typeface {Microsoft Himalaya} {} Tag_a:font script Thaa typeface {MV Boli} {} Tag_a:font script Deva typeface Mangal {} Tag_a:font script Telu typeface Gautami {} Tag_a:font script Taml typeface Latha {} Tag_a:font script Syrc typeface {Estrangelo Edessa} {} Tag_a:font script Orya typeface Kalinga {} Tag_a:font script Mlym typeface Kartika {} Tag_a:font script Laoo typeface DokChampa {} Tag_a:font script Sinh typeface {Iskoola Pota} {} Tag_a:font script Mong typeface {Mongolian Baiti} {} Tag_a:font script Viet typeface Arial {} Tag_a:font script Uigh typeface {Microsoft Uighur} {} Tag_a:font script Geor typeface Sylfaen {} } } Tag_a:fmtScheme name Office { Tag_a:fillStyleLst { Tag_a:solidFill { Tag_a:schemeClr val phClr {} } Tag_a:gradFill rotWithShape 1 { Tag_a:gsLst { Tag_a:gs pos 0 { Tag_a:schemeClr val phClr { Tag_a:tint val 50000 {} Tag_a:satMod val 300000 {} } } Tag_a:gs pos 35000 { Tag_a:schemeClr val phClr { Tag_a:tint val 37000 {} Tag_a:satMod val 300000 {} } } Tag_a:gs pos 100000 { Tag_a:schemeClr val phClr { Tag_a:tint val 15000 {} Tag_a:satMod val 350000 {} } } } Tag_a:lin ang 16200000 scaled 1 {} } Tag_a:gradFill rotWithShape 1 { Tag_a:gsLst { Tag_a:gs pos 0 { Tag_a:schemeClr val phClr { Tag_a:tint val 100000 {} Tag_a:shade val 100000 {} Tag_a:satMod val 130000 {} } } Tag_a:gs pos 100000 { Tag_a:schemeClr val phClr { Tag_a:tint val 50000 {} Tag_a:shade val 100000 {} Tag_a:satMod val 350000 {} } } } Tag_a:lin ang 16200000 scaled 0 {} } } Tag_a:lnStyleLst { Tag_a:ln w 9525 cap flat cmpd sng algn ctr { Tag_a:solidFill { Tag_a:schemeClr val phClr { Tag_a:shade val 95000 { } Tag_a:satMod val 105000 { } } } Tag_a:prstDash val solid {} } Tag_a:ln w 25400 cap flat cmpd sng algn ctr { Tag_a:solidFill { Tag_a:schemeClr val phClr {} } Tag_a:prstDash val solid {} } Tag_a:ln w 38100 cap flat cmpd sng algn ctr { Tag_a:solidFill { Tag_a:schemeClr val phClr {} } Tag_a:prstDash val solid {} } } Tag_a:effectStyleLst { Tag_a:effectStyle { Tag_a:effectLst { Tag_a:outerShdw blurRad 40000 dist 20000 dir 5400000 rotWithShape 0 { Tag_a:srgbClr val 000000 { Tag_a:alpha val 38000 {} } } } } Tag_a:effectStyle { Tag_a:effectLst { Tag_a:outerShdw blurRad 40000 dist 23000 dir 5400000 rotWithShape 0 { Tag_a:srgbClr val 000000 { Tag_a:alpha val 35000 {} } } } } Tag_a:effectStyle { Tag_a:effectLst { Tag_a:outerShdw blurRad 40000 dist 23000 dir 5400000 rotWithShape 0 { Tag_a:srgbClr val 000000 { Tag_a:alpha val 35000 {} } } } Tag_a:scene3d { Tag_a:camera prst orthographicFront { Tag_a:rot lat 0 lon 0 rev 0 { } } Tag_a:lightRig rig threePt dir t { Tag_a:rot lat 0 lon 0 rev 1200000 { } } } Tag_a:sp3d { Tag_a:bevelT w 63500 h 25400 {} } } } Tag_a:bgFillStyleLst { Tag_a:solidFill { Tag_a:schemeClr val phClr {} } Tag_a:gradFill rotWithShape 1 { Tag_a:gsLst { Tag_a:gs pos 0 { Tag_a:schemeClr val phClr { Tag_a:tint val 40000 {} Tag_a:satMod val 350000 {} } } Tag_a:gs pos 40000 { Tag_a:schemeClr val phClr { Tag_a:tint val 45000 {} Tag_a:shade val 99000 {} Tag_a:satMod val 350000 {} } } Tag_a:gs pos 100000 { Tag_a:schemeClr val phClr { Tag_a:shade val 20000 {} Tag_a:satMod val 255000 {} } } } Tag_a:path path circle { Tag_a:fillToRect l 50000 t -80000 r 50000 b 180000 {} } } Tag_a:gradFill rotWithShape 1 { Tag_a:gsLst { Tag_a:gs pos 0 { Tag_a:schemeClr val phClr { Tag_a:tint val 80000 {} Tag_a:satMod val 300000 {} } } Tag_a:gs pos 100000 { Tag_a:schemeClr val phClr { Tag_a:shade val 30000 {} Tag_a:satMod val 200000 {} } } } Tag_a:path path circle { Tag_a:fillToRect l 50000 t 50000 r 50000 b 50000 {} } } } } } Tag_a:objectDefaults { Tag_a:spDef { Tag_a:spPr {} Tag_a:bodyPr {} Tag_a:lstStyle {} Tag_a:style { Tag_a:lnRef idx 1 { Tag_a:schemeClr val accent1 {} } Tag_a:fillRef idx 3 { Tag_a:schemeClr val accent1 {} } Tag_a:effectRef idx 2 { Tag_a:schemeClr val accent1 {} } Tag_a:fontRef idx minor { Tag_a:schemeClr val lt1 {} } } } Tag_a:lnDef { Tag_a:spPr {} Tag_a:bodyPr {} Tag_a:lstStyle {} Tag_a:style { Tag_a:lnRef idx 2 { Tag_a:schemeClr val accent1 {} } Tag_a:fillRef idx 0 { Tag_a:schemeClr val accent1 {} } Tag_a:effectRef idx 1 { Tag_a:schemeClr val accent1 {} } Tag_a:fontRef idx minor { Tag_a:schemeClr val tx1 {} } } } } Tag_a:extraClrSchemeLst {} } ::ooxml::Dom2zip $zf $root "xl/theme/theme1.xml" cd count $doc delete # ------------------------------ xl/workbook.xml ------------------------------ # In the commented out part, serialization is done with namespaces set correctly, but this takes a few milliseconds more time. # Since we may process large amounts of data and do not use the same tag names in different namespaces and do not search in # the DOM during serialization, we only set the namespaces as attributes, which leads to the same result in the serialized XML. # set doc [dom createDocumentNS $xmlns(M) workbook] # set root [$doc documentElement] # $root setAttributeNS {} xmlns:r $xmlns(r) dom createDocument workbook doc $doc documentElement root $root setAttribute xmlns $xmlns(M) $root setAttributeNS {} xmlns:r $xmlns(r) $root appendFromScript { Tag_fileVersion appName xl lastEdited 5 lowestEdited 5 rupBuild 5000 {} Tag_workbookPr showInkAnnotation 0 autoCompressPictures 0 {} Tag_bookViews { set attr {} foreach {n v} [array get view] { switch -- $n { activetab { # activeTab is a zero based tab index - valid values are # 0 up to the number of worksheets minus 1. An out of # range value makes Excel treat the file as corrupted. if {![string is integer -strict $v] || $v < 0 || $v >= $obj(sheets)} { set v 0 } lappend attr activeTab $v } x { lappend attr xWindow $v } y { lappend attr yWindow $v } height { lappend attr windowHeight $v } width { lappend attr windowWidth $v } default { } } } Tag_workbookView {*}$attr {} } Tag_sheets { for {set ws 1} {$ws <= $obj(sheets)} {incr ws} { Tag_sheet name $obj(sheet,$ws) sheetId $ws r:id rId$ws {} } } Tag_definedNames { for {set ws 1} {$ws <= $obj(sheets)} {incr ws} { if {$obj(printarea,$ws) ne {}} { Tag_definedName name _xlnm.Print_Area localSheetId [expr {$ws - 1}] { Text [string cat ' $obj(sheet,$ws) '! $obj(printarea,$ws)] } } } # Tag_definedName name _xlnm._FilterDatabase localSheetId 0 hidden 1 { Text Blatt1!$A$1:$C$1 } } Tag_calcPr calcId 140000 concurrentCalc 0 {} # fullCalcOnLoad 1 } ::ooxml::Dom2zip $zf $root "xl/workbook.xml" cd count $doc delete # ------------------------------ xl/worksheets/_rels/sheet1.xml.rels SHEET ------------------------------ # In the commented out part, serialization is done with namespaces set correctly, but this takes a few milliseconds more time. # Since we may process large amounts of data and do not use the same tag names in different namespaces and do not search in # the DOM during serialization, we only set the namespaces as attributes, which leads to the same result in the serialized XML. # set doc [dom createDocumentNS $xmlns(PR) Relationships] # set root [$doc documentElement] for {set ws 1} {$ws <= $obj(sheets)} {incr ws} { if {[array names hlinks $ws,*,*] ne {}} { dom createDocument Relationships doc $doc documentElement root $root setAttribute xmlns $xmlns(PR) set hrefId 0 array unset rows foreach idx [lsort -dictionary [array names hlinks $ws,*,*]] { lassign [split $idx ,] sheet row col lappend rows($row) $col } foreach row [lsort -integer [array names rows]] { $root appendFromScript { foreach col $rows($row) { set idx "$ws,$row,$col" Tag_Relationship Id rId[incr hrefId] Type http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink Target [dict get $hlinks($idx) l] TargetMode External {} } } } ::ooxml::Dom2zip $zf $root "xl/worksheets/_rels/sheet$ws.xml.rels" cd count $doc delete } } # ------------------------------ xl/worksheets/sheet1.xml SHEET ------------------------------ # In the commented out part, serialization is done with namespaces set correctly, but this takes a few milliseconds more time. # Since we may process large amounts of data and do not use the same tag names in different namespaces and do not search in # the DOM during serialization, we only set the namespaces as attributes, which leads to the same result in the serialized XML. # set doc [dom createDocumentNS $xmlns(M) worksheet] # set root [$doc documentElement] # $root setAttributeNS {} xmlns:r $xmlns(r) # $root setAttributeNS {} xmlns:mc $xmlns(mc) # $root setAttributeNS {} xmlns:x14ac $xmlns(x14ac) # $doc selectNodesNamespaces [list M $xmlns(M) r $xmlns(r) mc $xmlns(mc) ac $xmlns(x14ac)] for {set ws 1} {$ws <= $obj(sheets)} {incr ws} { dom createDocument worksheet doc $doc documentElement root $root setAttribute xmlns $xmlns(M) $root setAttributeNS {} xmlns:r $xmlns(r) $root setAttributeNS {} xmlns:mc $xmlns(mc) $root setAttributeNS {} xmlns:x14ac $xmlns(x14ac) $root setAttribute mc:Ignorable x14ac $root appendFromScript { Tag_dimension ref [::ooxml::RowColumnToString $obj(dminrow,$ws),$obj(dmincol,$ws)]:[::ooxml::RowColumnToString $obj(dmaxrow,$ws),$obj(dmaxcol,$ws)] {} Tag_sheetViews { Tag_sheetView workbookViewId 0 { if {$obj(freeze,$ws) ne {}} { lassign [split [::ooxml::StringToRowColumn $obj(freeze,$ws)] ,] row col Tag_pane xSplit $col ySplit $row topLeftCell $obj(freeze,$ws) state frozen {} } } } Tag_sheetFormatPr baseColWidth 10 defaultRowHeight 16 x14ac:dyDescent 0.2 {} if {[info exists obj($ws,cols)] && $obj($ws,cols) > 0} { Tag_cols {} } Tag_sheetData { array unset rows foreach idx [lsort -dictionary [array names cells $ws,*,*]] { lassign [split $idx ,] sheet row col lappend rows($row) $col } foreach row [lsort -integer [array names rows]] { set attr {} if {[dict exists $obj(rowHeight,$ws) $row]} { lappend attr ht [dict get $obj(rowHeight,$ws) $row] customHeight 1 } # lappend attr spans [expr {$minCol + 1}]:[expr {$maxCol + 1}] Tag_row r [expr {$row + 1}] {*}$attr { foreach col $rows($row) { set idx "$ws,$row,$col" if {([dict exists $cells($idx) v] && [string trim [dict get $cells($idx) v]] ne {}) || ([dict exists $cells($idx) f] && [string trim [dict get $cells($idx) f]] ne {}) || [dict exists $cells($idx) fsi]} { set attr {} if {[dict exists $cells($idx) s] && [dict get $cells($idx) s] > 0} { lappend attr s [dict get $cells($idx) s] } if {[dict exists $cells($idx) t] && [dict get $cells($idx) t] ne {n}} { lappend attr t [dict get $cells($idx) t] } Tag_c r [::ooxml::RowColumnToString $row,$col] {*}$attr { if {[dict exists $cells($idx) v] && [dict get $cells($idx) v] ne {}} { Tag_v { Text [dict get $cells($idx) v] } } if {([dict exists $cells($idx) f] && [dict get $cells($idx) f] ne {}) || [dict exists $cells($idx) fsi]} { ## FORMULA ## set attr {} if {[dict exists $cells($idx) fsi] && [dict get $cells($idx) fsi] > -1} { lappend attr t shared } if {[dict exists $cells($idx) fsr] && [dict get $cells($idx) fsr] ne {}} { lappend attr ref [dict get $cells($idx) fsr] } if {[dict exists $cells($idx) fsi] && [dict get $cells($idx) fsi] > -1} { lappend attr si [dict get $cells($idx) fsi] } Tag_f {*}$attr { if {[dict exists $cells($idx) f] && [dict get $cells($idx) f] ne {}} { Text [dict get $cells($idx) f] } } } } } elseif {[dict exists $cells($idx) s] && [string is integer -strict [dict get $cells($idx) s]] && [dict get $cells($idx) s] > 0} { Tag_c r [::ooxml::RowColumnToString $row,$col] s [dict get $cells($idx) s] {} } # garbage collection unset -nocomplain cells($idx) } } } } if {$obj(autofilter,$ws) ne {}} { Tag_autoFilter ref $obj(autofilter,$ws) {} } if {[info exists obj(merge,$ws)] && $obj(merge,$ws) ne {}} { Tag_mergeCells count [llength $obj(merge,$ws)] { foreach item $obj(merge,$ws) { Tag_mergeCell ref $item {} } } } # hyperlinks if {[array names hlinks $ws,*,*] ne {}} { Tag_hyperlinks { set hrefId 0 array unset rows foreach idx [lsort -dictionary [array names hlinks $ws,*,*]] { lassign [split $idx ,] sheet row col lappend rows($row) $col } foreach row [lsort -integer [array names rows]] { foreach col $rows($row) { set idx "$ws,$row,$col" if {[dict exists $hlinks($idx) t]} { set tooltip [list tooltip [dict get $hlinks($idx) t]] } else { set tooltip {} } Tag_hyperlink ref [::ooxml::RowColumnToString $row,$col] r:id rId[incr hrefId] {*}$tooltip {} } } } } if {[info exists pageMargins($ws)]} { Tag_pageMargins {*}$pageMargins($ws) } else { Tag_pageMargins {*}$pageMarginsDefault } # Page Setup if {[info exists pageSetups($ws)]} { Tag_pageSetup {*}$pageSetups($ws) } } if {[set colsNode [$root selectNodes /worksheet/cols]] ne {}} { if {[info exists obj($ws,cols)] && $obj($ws,cols) > 0} { $colsNode appendFromScript { foreach idx [lsort -dictionary [array names cols $ws,*]] { set attr {} lappend attr min [expr {[dict get $cols($idx) min] + 1}] max [expr {[dict get $cols($idx) max] + 1}] if {[dict get $cols($idx) width] ne {}} { lappend attr width [dict get $cols($idx) width] if {[dict get $cols($idx) width] != $::ooxml::defaults(cols,width)} { dict set $cols($idx) customwidth 1 } } if {[dict get $cols($idx) style] ne {} && [dict get $cols($idx) style] > 0} { lappend attr style [dict get $cols($idx) style] } if {[dict get $cols($idx) bestfit] == 1} { lappend attr bestFit [dict get $cols($idx) bestfit] } if {[dict get $cols($idx) customwidth] == 1} { lappend attr customWidth [dict get $cols($idx) customwidth] } Tag_col {*}$attr {} } } } } ::ooxml::Dom2zip $zf $root "xl/worksheets/sheet$ws.xml" cd count $doc delete } # Finalize zip. set cdoffset [tell $zf] set endrec [binary format a4ssssiis PK\05\06 0 0 $count $count [string length $cd] $cdoffset 0] puts -nonewline $zf $cd puts -nonewline $zf $endrec close $zf return 0 } } # # ooxml::tablelist_to_xl # proc ::ooxml::tablelist_to_xl { lb args } { variable defaults if {![winfo exists $lb]} { tk_messageBox -message [msgcat::mc {Tablelist does not exists!}] return } array set opts " callback ::ooxml::tablelist_to_xl_callback path [list $defaults(path)] file tablelist.xlsx creator unknown name Tablelist1 rootonly 0 addtimestamp 0 globalstyle 0 " set len [llength $args] set idx 0 for {set idx 0} {$idx < $len} {incr idx} { switch -- [set opt [lindex $args $idx]] { -callback - -path - -file - -creator - -name { incr idx if {$idx < $len} { set opts([string range $opt 1 end]) [lindex $args $idx] } else { error "option '$opt': missing argument" } } -rootonly - -addtimestamp - -globalstyle { set opts([string range $opt 1 end]) 1 } default { error "unknown option \"$opt\", should be: -callback, -path, -file, -creator, -name, -rootonly, -addtimestamp or -globalstyle" } } } if {$opts(callback) eq {} || ([info commands $opts(callback)] eq {} && [info commands ::$opts(callback)] eq {})} { set opts(callback) ::ooxml::tablelist_to_xl_callback } if {[string trim $opts(path)] eq {}} { set opts(path) {.} } if {[string trim $opts(file)] eq {}} { set opts(file) {tablelist.xlsx} } if {[file extension $opts(file)] eq {.xlsx}} { set opts(file) [file tail [file rootname $opts(file)]] } if {$opts(addtimestamp)} { append opts(file) _[clock format [clock seconds] -format %Y%m%dT%H%M%S] } append opts(file) {.xlsx} if {$opts(globalstyle)} { set globalstyle {-globalstyle} } else { set globalstyle {} } set file [tk_getSaveFile -confirmoverwrite 1 -filetypes {{{Excel Office Open XML} {.xlsx}}} -initialdir $opts(path) -initialfile $opts(file) -parent . -title "Excel Office Open XML"] if {$file eq {}} { tk_messageBox -message [msgcat::mc {No file selected!}] return } set spreadsheet [::ooxml::xl_write new -creator $opts(creator)] if {[set sheet [$spreadsheet worksheet $opts(name)]] > -1} { set columncount [expr {[$lb columncount] - 1}] if {$columncount > 0} { $spreadsheet autofilter $sheet 0,0 0,$columncount } set titlecolumns [$lb cget -titlecolumns] if {$titlecolumns > 0} { $spreadsheet freeze $sheet 1,$titlecolumns } set col -1 set title SETUP set width 0 set align {} set sortmode {} set hide 1 $opts(callback) $spreadsheet $sheet $columncount $col $title $width $align $sortmode $hide $spreadsheet row $sheet for {set col 0} {$col <= $columncount} {incr col} { set title [$lb columncget $col -title] set width [$lb columncget $col -width] set align [$lb columncget $col -align] set sortmode [$lb columncget $col -sortmode] set hide [$lb columncget $col -hide] $opts(callback) $spreadsheet $sheet $columncount $col $title $width $align $sortmode $hide $spreadsheet cell $sheet $title } if {$opts(rootonly)} { foreach row [$lb get [$lb childkeys root]] { $spreadsheet row $sheet set idx 0 foreach col $row { if {[string trim $col] ne {}} { $spreadsheet cell $sheet $col -index $idx {*}$globalstyle } incr idx } } } else { foreach row [$lb get 0 end] { $spreadsheet row $sheet set idx 0 foreach col $row { if {[string trim $col] ne {}} { $spreadsheet cell $sheet $col -index $idx {*}$globalstyle } incr idx } } } $spreadsheet write $file } } proc ::ooxml::tablelist_to_xl_callback { spreadsheet sheet maxcol column title width align sortmode hide } { set left 0 set center [$spreadsheet style -horizontal center] set right [$spreadsheet style -horizontal right] set date [$spreadsheet style -numfmt [$spreadsheet numberformat -datetime]] set decimal [$spreadsheet style -numfmt [$spreadsheet numberformat -decimal -red]] set text [$spreadsheet style -numfmt [$spreadsheet numberformat -string]] if {$column == -1} { $spreadsheet defaultdatestyle $date } else { switch -- $align { center { $spreadsheet column $sheet -index $column -style $center } right { $spreadsheet column $sheet -index $column -style $right } default { $spreadsheet column $sheet -index $column -style $left } } } } proc ::ooxml::build-info { {cmd {}} } { variable pkgPath # TIP 599: Extended build information # https://core.tcl-lang.org/tips/doc/trunk/tip/599.md set file [file join $pkgPath manifest.txt] if {[file readable $file] && ![catch {open $file r} fd]} { set manifest [read $fd] close $fd set uuid [dict get $manifest MANIFEST_UUID] set checkin [string map {[ {} ] {}} [dict get $manifest MANIFEST_VERSION]] set build [dict get $manifest FOSSIL_BUILD_HASH] set datetime [string map {{ } T} [dict get $manifest MANIFEST_DATE]]Z set version [dict get $manifest RELEASE_VERSION] set compiler {tcl.noarch} switch -- $cmd { commit { return $uuid } version - patchlevel { return $version } compiler { return $compiler } path { return $pkgPath } default { return ${version}+${checkin}.${datetime}.${compiler} } } } else { return {?.manifest_not_found} } } package provide ooxml 1.13.1 set ::ooxml::pkgPath [file dirname [info script]] # Local Variables: # tcl-indent-level: 2 # End: ooxml/configure.ac000644 000765 000024 00000011651 15221665101 014601 0ustar00alexstaff000000 000000 #!/bin/bash -norc dnl This file is an input file used by the GNU "autoconf" program to dnl generate the file "configure", which is run during Tcl installation dnl to configure the system for the local environment. # Copyright (C) 2019 Alexander Schoepe, Bochum, DE #----------------------------------------------------------------------- # This initializes the environment with PACKAGE_NAME and PACKAGE_VERSION # set as provided. These will also be added as -D defs in your Makefile # so you can encode the package version directly into the source files. # This will also define a special symbol for Windows (BUILD_ # so that we create the export library with the dll. #----------------------------------------------------------------------- AC_INIT([ooxml],[1.13.1]) #-------------------------------------------------------------------- # Remember whether the user gave --prefix on the command line, before # TEA_INIT and TEA_PREFIX get their hands on the variables. Needed to # fix up the exec_prefix after TEA_PREFIX (see below). #-------------------------------------------------------------------- if test "${prefix}" != "NONE"; then user_prefix=yes fi #-------------------------------------------------------------------- # Call TEA_INIT as the first TEA_ macro to set up initial vars. # This will define a ${TEA_PLATFORM} variable == "unix" or "windows" # as well as PKG_LIB_FILE and PKG_STUB_LIB_FILE. #-------------------------------------------------------------------- TEA_INIT() AC_CONFIG_AUX_DIR(tclconfig) #-------------------------------------------------------------------- # Load the tclConfig.sh file #-------------------------------------------------------------------- TEA_PATH_TCLCONFIG TEA_LOAD_TCLCONFIG #----------------------------------------------------------------------- # Handle the --prefix=... option by defaulting to what Tcl gave. # Must be called after TEA_LOAD_TCLCONFIG and before TEA_SETUP_COMPILER. #----------------------------------------------------------------------- TEA_PREFIX #----------------------------------------------------------------------- # When the user gave --prefix but not --exec-prefix, TEA_INIT sets # exec_prefix to the prefix but notes exec_prefix_default=yes, which # makes TEA_PREFIX overwrite it again with the exec prefix recorded in # tclConfig.sh - the package then installs into the Tcl tree no matter # what --prefix said (ticket 1a64a34982). Restore the user's choice. #----------------------------------------------------------------------- if test x"${user_prefix}" = x"yes" -a x"${exec_prefix_default}" = x"yes"; then AC_MSG_NOTICE([--prefix given: overriding exec_prefix back to ${prefix}]) exec_prefix=$prefix fi #----------------------------------------------------------------------- # Specify the C source files to compile in TEA_ADD_SOURCES, # public headers that need to be installed in TEA_ADD_HEADERS, # stub library C source files to compile in TEA_ADD_STUB_SOURCES, # and runtime Tcl library files in TEA_ADD_TCL_SOURCES. # This defines PKG(_STUB)_SOURCES, PKG(_STUB)_OBJECTS, PKG_HEADERS # and PKG_TCL_SOURCES. #----------------------------------------------------------------------- TEA_ADD_TCL_SOURCES([ooxml.tcl \ ooxml-docx.tcl \ ooxml-docx-lib.tcl \ ooxml-docx-math.tcl]) #-------------------------------------------------------------------- # You can add more files to clean if your extension creates any extra # files by extending CLEANFILES. # Add pkgIndex.tcl if it is generated in the Makefile instead of ./configure # and change Makefile.in to move it from CONFIG_CLEAN_FILES to BINARIES var. # # A few miscellaneous platform-specific items: # TEA_ADD_* any platform specific compiler/build info here. #-------------------------------------------------------------------- #CLEANFILES="$CLEANFILES" #-------------------------------------------------------------------- # Determine the name of the tclsh and/or wish executables in the # Tcl and Tk build directories or the location they were installed # into. These paths are used to support running test cases only, # the Makefile should not be making use of these paths to generate # a pkgIndex.tcl file or anything else at extension build time. #-------------------------------------------------------------------- TEA_PROG_TCLSH #-------------------------------------------------------------------- # Local autoconf addition not worth an own file #-------------------------------------------------------------------- AC_CHECK_PROG(HAVE_PANDOC,pandoc,yes,no) #-------------------------------------------------------------------- # Finally, substitute all of the various values into the Makefile. # You may alternatively have a special pkgIndex.tcl.in or other files # which require substituting th AC variables in. Include these here. #-------------------------------------------------------------------- AC_CONFIG_FILES([Makefile pkgIndex.tcl]) AC_OUTPUT ooxml/tools/000755 000765 000024 00000000000 15221526153 013452 5ustar00alexstaff000000 000000 ooxml/ANNOUNCE000644 000765 000024 00000003720 15221665171 013451 0ustar00alexstaff000000 000000 ANNOUNCE: ooxml 1.13.1 released =============================== ooxml is a pure Tcl extension for reading and writing ECMA-376 Office Open XML files: it reads and writes Excel .xlsx spreadsheets and creates Word .docx documents. Developed by Alexander Schoepe with contributions by Rolf Ade, Harald Oehlmann and Miguel Bañón, it requires only Tcl 8.6.7+ and tdom. 1.13.1 is a small bugfix release for a shortcoming in the built-in zip reader introduced with 1.13. Download / Repository: https://fossil.sowaswie.de/ooxml English ------- Fixes since 1.13: * The built-in zip reader passed the uncompressed size of a zip member as buffer size hint to Tcl's zlib inflate, which only accepts values from 16 to 65536 - reading any xlsx or docx file containing an XML part larger than 64 KB failed with 'buffer size must be 16 to 65536' (ticket a308a654f0). The hint is now capped to the allowed range; the buffer still grows as needed beyond it. A regression test was added. Thanks to Miguel Bañón for spotting and suggesting the fix. If you are on 1.13, updating is recommended: any spreadsheet with roughly more than a thousand filled cells or a document with more than a few hundred paragraphs is affected when read. Deutsch ------- Fehlerbehebungen seit 1.13: * Der eingebaute Zip-Reader übergab die unkomprimierte Größe eines Zip-Eintrags als Puffergrößen-Hinweis an Tcls zlib inflate, das nur Werte von 16 bis 65536 akzeptiert - das Lesen von xlsx- oder docx-Dateien mit einem XML-Teil größer als 64 KB scheiterte mit 'buffer size must be 16 to 65536' (Ticket a308a654f0). Der Hinweis wird jetzt auf den erlaubten Bereich geklemmt; der Puffer wächst darüber hinaus weiterhin nach Bedarf. Ein Regressionstest wurde ergänzt. Dank an Miguel Bañón für das Aufspüren und den Fix-Vorschlag. Wer 1.13 einsetzt, sollte aktualisieren: Betroffen ist beim Lesen jede Tabelle mit grob mehr als tausend gefüllten Zellen bzw. jedes Dokument mit mehr als ein paar hundert Absätzen. ooxml/docxtest.tcl000664 000765 000024 00000005023 15213015413 014646 0ustar00alexstaff000000 000000 source ./ooxml.tcl source ./ooxml-docx.tcl set docx [::ooxml::docx::docx new -creator foo -created 2025-02-10] # foreach type {paragraph character} { # foreach styleid [$docx style ids $type] { # $docx style delete $type $styleid # } # } $docx pagesetup -sizeAndOrientaion {width 16838 height 23811 orientation landscape} -margins {left 2000 right 2000} -paperSource {first 1 other 2} $docx style characterdefault -fontsize 20 -font "Liberation Serif" $docx style paragraph Heading1 -fontsize 28 -bold on $docx paragraph "My first heading" -style Heading1 -spacing {before 240 after 120} $docx paragraph [string repeat "My first paragraph " 50] -spacing {after 120} $docx append "build in parts" -bold on -fontsize 16 $docx append " serveral parts indeed" -italic on $docx append " and different fonts" -font "Utopia" $docx style character myCharacterStyle -bold on -italic true -font "Utopia" $docx append " and a part with character style" -style myCharacterStyle $docx simpletable { {1 2 3} {aaaaaa bbbbb ccccc} {"foo bar" "grill baz" "lore ipsum"} } $docx style paragraph Mystyle -font Utopia -bold 1 -italic true \ -spacing {before 120 after 60} -color ff0000 -underline wave $docx paragraph "Another paragraph with its own style" -style Mystyle $docx paragraph [string repeat "Next paragraph, back to default style, with a few local changes. " 20] -spacing {line 400} -align center $docx paragraph "Another paragraph with its own style (local applied)" -align right $docx style paragraph RigthAlign -align right $docx paragraph "Another paragraph with its own style (applied by style)" -style RigthAlign $docx paragraph [string repeat "Next paragraph with stupid text. " 20] \ -indentation {firstLine 3cm hanging 2cm start 1cm end 4cm} $docx url "click this" "https://www.staatstheater-stuttgart.de/" -underline single $docx url "and click that" "https://core.tcl-lang.org/" -underline single $docx append " more text" $docx paragraph "A new paragraph" # Prevent error if someone follow this actually testing if {[file exists book.jpg]} { #$docx image book.jpg -dimension {width 2872105 height 2872105} $docx image book.jpg -dimension {width 3cm height 3cm} -bwMode black } else { puts "Missing book.jpg to include into docx" } puts "paragraph style ids: [$docx style ids paragraph]" puts "character style ids: [$docx style ids character]" $docx write testout.docx $docx writepart word/styles.xml document.xml $docx readpart word/styles.xml document.xml $docx configure -creator bar $docx write testout.docx $docx destroy ooxml/tclconfig/000755 000765 000024 00000000000 14764622263 014274 5ustar00alexstaff000000 000000 ooxml/ooxml.code-workspace000644 000765 000024 00000000112 14764622263 016304 0ustar00alexstaff000000 000000 { "folders": [ { "path": "." } ], "settings": {} }ooxml/configure000755 000765 000024 00000443165 15221665125 014241 0ustar00alexstaff000000 000000 #! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.73 for ooxml 1.13.1. # # # Copyright (C) 1992-1996, 1998-2017, 2020-2026 Free Software Foundation, # Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1 then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # contradicts POSIX and common usage. Disable this. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case e in #( e) case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac ;; esac fi # Reset variables that may have inherited troublesome values from # the environment. # IFS needs to be set, to space, tab, and newline, in precisely that order. # (If _AS_PATH_WALK were called with IFS unset, it would have the # side effect of setting IFS to empty, thus disabling word splitting.) # Quoting is to prevent editors from complaining about space-tab. as_nl=' ' export as_nl IFS=" "" $as_nl" PS1='$ ' PS2='> ' PS4='+ ' # Ensure predictable behavior from utilities with locale-dependent output. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # We cannot yet rely on "unset" to work, but we need these variables # to be unset--not just set to an empty or harmless value--now, to # avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct # also avoids known problems related to "unset" and subshell syntax # in other old shells (e.g. bash 2.01 and pdksh 5.2.14). for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH do eval test \${$as_var+y} \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done # Ensure that fds 0, 1, and 2 are open. if (exec 3>&0) 2>/dev/null; then :; else exec 0&1) 2>/dev/null; then :; else exec 1>/dev/null; fi if (exec 3>&2) ; then :; else exec 2>/dev/null; fi # The user is always right. if ${PATH_SEPARATOR+false} :; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac test -r "$as_dir$0" && as_myself=$as_dir$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as 'sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then printf '%s\n' "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac case $# in # (( 0) exec $CONFIG_SHELL $as_opts "$as_myself" ;; *) exec $CONFIG_SHELL $as_opts "$as_myself" "$@" ;; esac # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed 'exec'. printf '%s\n' "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test \${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1 then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # contradicts POSIX and common usage. Disable this. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case e in #( e) case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ) then : else case e in #( e) exitcode=1; echo positional parameters were not saved. ;; esac fi test x\$exitcode = x0 || exit 1 blah=\$(echo \$(echo blah)) test x\"\$blah\" = xblah || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1" if (eval "$as_required") 2>/dev/null then : as_have_required=yes else case e in #( e) as_have_required=no ;; esac fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null then : else case e in #( e) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && as_run=a "$as_shell" -c "$as_bourne_compatible""$as_required" 2>/dev/null then : CONFIG_SHELL=$as_shell as_have_required=yes if as_run=a "$as_shell" -c "$as_bourne_compatible""$as_suggested" 2>/dev/null then : break 2 fi fi done;; esac as_found=false done IFS=$as_save_IFS if $as_found then : else case e in #( e) if { test -f "$SHELL" || test -f "$SHELL.exe"; } && as_run=a "$SHELL" -c "$as_bourne_compatible""$as_required" 2>/dev/null then : CONFIG_SHELL=$SHELL as_have_required=yes fi ;; esac fi if test "x$CONFIG_SHELL" != x then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac case $# in # (( 0) exec $CONFIG_SHELL $as_opts "$as_myself" ;; *) exec $CONFIG_SHELL $as_opts "$as_myself" "$@" ;; esac # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed 'exec'. printf '%s\n' "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno then : printf '%s\n' "$0: This script requires a shell more modern than all" printf '%s\n' "$0: the shells that I found on your system." if test ${ZSH_VERSION+y} ; then printf '%s\n' "$0: In particular, zsh $ZSH_VERSION has bugs and should" printf '%s\n' "$0: be upgraded to zsh 4.3.4 or later." else printf '%s\n' "$0: Please tell bug-autoconf@gnu.org about your system, $0: including any error possibly output before this $0: message. Then install a modern shell, or manually run $0: the script under such a shell if you do have one." fi exit 1 fi ;; esac fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`printf '%s\n' "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || printf '%s\n' X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null then : eval 'as_fn_append () { eval $1+=\$2 }' else case e in #( e) as_fn_append () { eval $1=\$$1\$2 } ;; esac fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null then : eval 'as_fn_arith () { as_val=$(( $* )) }' else case e in #( e) as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } ;; esac fi # as_fn_arith # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack printf '%s\n' "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi printf '%s\n' "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || printf '%s\n' X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' t clear :clear s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { printf '%s\n' "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both 'ln -s file dir' and 'ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; 'ln -s' creates a wrapper executable. # In both cases, we have to default to 'cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_sed_cpp="y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g" as_tr_cpp="eval sed '$as_sed_cpp'" # deprecated # Sed expression to map a string onto a valid variable name. as_sed_sh="y%*+%pp%;s%[^_$as_cr_alnum]%_%g" as_tr_sh="eval sed '$as_sed_sh'" # deprecated test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_CONFIG_STATUS= ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='ooxml' PACKAGE_TARNAME='ooxml' PACKAGE_VERSION='1.13.1' PACKAGE_STRING='ooxml 1.13.1' PACKAGE_BUGREPORT='' PACKAGE_URL='' ac_subst_vars='LTLIBOBJS LIBOBJS HAVE_PANDOC TCLSH_PROG TCL_SHLIB_LD_LIBS TCL_LD_FLAGS TCL_EXTRA_CFLAGS TCL_DEFS TCL_LIBS CLEANFILES OBJEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC TCL_STUB_LIB_SPEC TCL_STUB_LIB_FLAG TCL_STUB_LIB_FILE TCL_LIB_SPEC TCL_LIB_FLAG TCL_LIB_FILE TCL_SRC_DIR TCL_BIN_DIR TCL_PATCH_LEVEL TCL_VERSION INSTALL_LIBRARY INSTALL_SCRIPT INSTALL_PROGRAM INSTALL_DATA INSTALL_DATA_DIR INSTALL PKG_CFLAGS PKG_LIBS PKG_INCLUDES PKG_HEADERS PKG_TCL_SOURCES PKG_STUB_OBJECTS PKG_STUB_SOURCES PKG_LIB_FILE9 PKG_LIB_FILE8 PKG_LIB_FILE EXEEXT CYGPATH ECHO_T ECHO_N ECHO_C target_alias host_alias build_alias LIBS DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir runstatedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking with_tcl with_tcl8 ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: '$ac_useropt'" ac_useropt_orig=$ac_useropt ac_useropt=`printf '%s\n' "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: '$ac_useropt'" ac_useropt_orig=$ac_useropt ac_useropt=`printf '%s\n' "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -runstatedir | --runstatedir | --runstatedi | --runstated \ | --runstate | --runstat | --runsta | --runst | --runs \ | --run | --ru | --r) ac_prev=runstatedir ;; -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ | --run=* | --ru=* | --r=*) runstatedir=$ac_optarg ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: '$ac_useropt'" ac_useropt_orig=$ac_useropt ac_useropt=`printf '%s\n' "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: '$ac_useropt'" ac_useropt_orig=$ac_useropt ac_useropt=`printf '%s\n' "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: '$ac_option' Try '$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: '$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. printf '%s\n' "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && printf '%s\n' "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`printf '%s\n' $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) printf '%s\n' "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir runstatedir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: '$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || printf '%s\n' X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but 'cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF 'configure' configures ooxml 1.13.1 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print 'checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for '--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or '..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, 'make install' will install all the files in '$ac_default_prefix/bin', '$ac_default_prefix/lib' etc. You can specify an installation prefix other than '$ac_default_prefix' using '--prefix', for instance '--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/ooxml] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of ooxml 1.13.1:";; esac cat <<\_ACEOF Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-tcl directory containing tcl configuration (tclConfig.sh) --with-tcl8 Compile for Tcl8 in Tcl9 environment Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory Use these variables to override the choices made by 'configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to the package provider. _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`printf '%s\n' "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`printf '%s\n' "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for configure.gnu first; this name is used for a wrapper for # Metaconfig's "Configure" on case-insensitive file systems. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else printf '%s\n' "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF ooxml configure 1.13.1 generated by GNU Autoconf 2.73 Copyright (C) 2026 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest.beam if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf '%s\n' "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi printf '%s\n' "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext then : ac_retval=0 else case e in #( e) printf '%s\n' "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 ;; esac fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile ac_configure_args_raw= for ac_arg do case $ac_arg in *\'*) ac_arg=`printf '%s\n' "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append ac_configure_args_raw " '$ac_arg'" done case $ac_configure_args_raw in *$as_nl*) ac_safe_unquote= ;; *) ac_unsafe_z='|&;<>()$`\\"*?[ '' ' # This string ends in space, tab. ac_unsafe_a="$ac_unsafe_z#~" ac_safe_unquote="s/ '\\([^$ac_unsafe_a][^$ac_unsafe_z]*\\)'/ \\1/g" ac_configure_args_raw=` printf '%s\n' "$ac_configure_args_raw" | sed "$ac_safe_unquote"`;; esac cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by ooxml $as_me 1.13.1, which was generated by GNU Autoconf 2.73. Invocation command line was $ $0$ac_configure_args_raw _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac printf '%s\n' "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`printf '%s\n' "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # Dump the cache to stdout. It can be in a pipe (this is a requirement). ac_cache_dump () { # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { printf '%s\n' "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 printf '%s\n' "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # 'set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # 'set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) } # Print debugging info to stdout. ac_dump_debugging_info () { echo printf '%s\n' "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo ac_cache_dump echo printf '%s\n' "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'*) ac_val=`printf '%s\n' "$ac_val" | sed "s/'/'\\\\\\\\''/g"`;; esac printf '%s\n' "$ac_var='$ac_val'" done | sort echo if test -n "$ac_subst_files"; then printf '%s\n' "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'*) ac_val=`printf '%s\n' "$ac_val" | sed "s/'/'\\\\\\\\''/g"`;; esac printf '%s\n' "$ac_var='$ac_val'" done | sort echo fi if test -s confdefs.h; then printf '%s\n' "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && printf '%s\n' "$as_me: caught signal $ac_signal" printf '%s\n' "$as_me: exit $exit_status" } # When interrupted or exit'd, cleanup temporary files, and complete # config.log. ac_exit_trap () { exit_status= # Sanitize IFS. IFS=" "" $as_nl" # Save into config.log some information that might help in debugging. ac_dump_debugging_info >&5 eval "rm -f $ac_clean_CONFIG_STATUS core *.core core.conftest.*" && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status } trap 'ac_exit_trap $?' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h printf '%s\n' "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. printf '%s\n' "#define PACKAGE_NAME \"$PACKAGE_NAME\"" >>confdefs.h printf '%s\n' "#define PACKAGE_TARNAME \"$PACKAGE_TARNAME\"" >>confdefs.h printf '%s\n' "#define PACKAGE_VERSION \"$PACKAGE_VERSION\"" >>confdefs.h printf '%s\n' "#define PACKAGE_STRING \"$PACKAGE_STRING\"" >>confdefs.h printf '%s\n' "#define PACKAGE_BUGREPORT \"$PACKAGE_BUGREPORT\"" >>confdefs.h printf '%s\n' "#define PACKAGE_URL \"$PACKAGE_URL\"" >>confdefs.h # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. if test -n "$CONFIG_SITE"; then ac_site_files="$CONFIG_SITE" elif test "x$prefix" != xNONE; then ac_site_files="$prefix/share/config.site $prefix/etc/config.site" else ac_site_files="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" fi for ac_site_file in $ac_site_files do case $ac_site_file in #( */*) : ;; #( *) : ac_site_file=./$ac_site_file ;; esac if test -f "$ac_site_file" && test -r "$ac_site_file"; then { printf '%s\n' "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 printf '%s\n' "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { printf '%s\n' "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5 printf '%s\n' "$as_me: error: in '$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See 'config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { printf '%s\n' "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 printf '%s\n' "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { printf '%s\n' "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 printf '%s\n' "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Test code for whether the C compiler supports C23 (global declarations) ac_c_conftest_c23_globals=' /* Does the compiler advertise conformance to C17 or earlier? Although GCC 14 does not do that, even with -std=gnu23, it is close enough, and defines __STDC_VERSION == 202000L. */ #if !defined __STDC_VERSION__ || __STDC_VERSION__ <= 201710L # error "Compiler advertises conformance to C17 or earlier" #endif // Check alignas. char alignas (double) c23_aligned_as_double; char alignas (0) c23_no_special_alignment; extern char c23_aligned_as_int; char alignas (0) alignas (int) c23_aligned_as_int; // Check alignof. enum { c23_int_alignment = alignof (int), c23_int_array_alignment = alignof (int[100]), c23_char_alignment = alignof (char) }; static_assert (0 < -alignof (int), "alignof is signed"); int function_with_unnamed_parameter (int) { return 0; } void c23_noreturn (); /* Test parsing of string and char UTF-8 literals (including hex escapes). The parens pacify GCC 15. */ bool use_u8 = (!sizeof u8"\xFF") == (!u8'\''x'\''); bool check_that_bool_works = true | false | !nullptr; #if !true # error "true does not work in #if" #endif #if false #elifdef __STDC_VERSION__ #else # error "#elifdef does not work" #endif #ifndef __has_c_attribute # error "__has_c_attribute not defined" #endif #ifndef __has_include # error "__has_include not defined" #endif #define LPAREN() ( #define FORTY_TWO(x) 42 #define VA_OPT_TEST(r, x, ...) __VA_OPT__ (FORTY_TWO r x)) static_assert (VA_OPT_TEST (LPAREN (), 0, <:-) == 42); static_assert (0b101010 == 42); static_assert (0B101010 == 42); static_assert (0xDEAD'\''BEEF == 3'\''735'\''928'\''559); static_assert (0.500'\''000'\''000 == 0.5); enum unsignedish : unsigned int { uione = 1 }; static_assert (0 < -uione); #include constexpr nullptr_t null_pointer = nullptr; static typeof (1 + 1L) two () { return 2; } static long int three () { return 3; } ' # Test code for whether the C compiler supports C23 (body of main). ac_c_conftest_c23_main=' { label_before_declaration: int arr[10] = {}; if (arr[0]) goto label_before_declaration; if (!arr[0]) goto label_at_end_of_block; label_at_end_of_block: } ok |= !null_pointer; ok |= two != three; ' # Test code for whether the C compiler supports C23 (complete). ac_c_conftest_c23_program="${ac_c_conftest_c23_globals} int main (int, char **) { int ok = 0; ${ac_c_conftest_c23_main} return ok; } " # Test code for whether the C compiler supports C89 (global declarations) ac_c_conftest_c89_globals=' /* Do not test the value of __STDC__, because some compilers define it to 0 or do not define it, while otherwise adequately conforming. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7 src/conf.sh. */ struct buf { int x; }; struct buf * (*rcsopen) (struct buf *, struct stat *, int); static char *e (char **p, int i) { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* C89 style stringification. */ #define noexpand_stringify(a) #a const char *stringified = noexpand_stringify(arbitrary+token=sequence); /* C89 style token pasting. Exercises some of the corner cases that e.g. old MSVC gets wrong, but not very hard. */ #define noexpand_concat(a,b) a##b #define expand_concat(a,b) noexpand_concat(a,b) extern int vA; extern int vbee; #define aye A #define bee B int *pvA = &expand_concat(v,aye); int *pvbee = &noexpand_concat(v,bee); /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not \xHH hex character constants. These do not provoke an error unfortunately, instead are silently treated as an "x". The following induces an error, until -std is added to get proper ANSI mode. Curiously \x00 != x always comes out true, for an array size at least. It is necessary to write \x00 == 0 to get something that is true only with -std. */ int osf4_cc_array ['\''\x00'\'' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) '\''x'\'' int xlc6_cc_array[FOO(a) == '\''x'\'' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, int *(*)(struct buf *, struct stat *, int), int, int);' # Test code for whether the C compiler supports C89 (body of main). ac_c_conftest_c89_main=' ok |= (argc == 0 || f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]); ' # Test code for whether the C compiler supports C99 (global declarations) ac_c_conftest_c99_globals=' /* Does the compiler advertise C99 conformance? */ #if !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L # error "Compiler does not advertise C99 conformance" #endif // See if C++-style comments work. #include extern int puts (const char *); extern int printf (const char *, ...); extern int dprintf (int, const char *, ...); extern void *malloc (size_t); extern void free (void *); // Check varargs macros. These examples are taken from C99 6.10.3.5. // dprintf is used instead of fprintf to avoid needing to declare // FILE and stderr, and "aND" is used instead of "and" to work around // GCC bug 40564 which is irrelevant here. #define debug(...) dprintf (2, __VA_ARGS__) #define showlist(...) puts (#__VA_ARGS__) #define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__)) static void test_varargs_macros (void) { int x = 1234; int y = 5678; debug ("Flag"); debug ("X = %d\n", x); showlist (The first, second, aND third items.); report (x>y, "x is %d but y is %d", x, y); } // Check long long types. #define BIG64 18446744073709551615ull #define BIG32 4294967295ul #define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0) #if !BIG_OK #error "your preprocessor is broken" #endif #if BIG_OK #else #error "your preprocessor is broken" #endif static long long int bignum = -9223372036854775807LL; static unsigned long long int ubignum = BIG64; struct incomplete_array { int datasize; double data[]; }; struct named_init { int number; const wchar_t *name; double average; }; typedef const char *ccp; static inline int test_restrict (ccp restrict text) { // Iterate through items via the restricted pointer. // Also check for declarations in for loops. for (unsigned int i = 0; *(text+i) != '\''\0'\''; ++i) continue; return 0; } // Check varargs and va_copy. static bool test_varargs (const char *format, ...) { va_list args; va_start (args, format); va_list args_copy; va_copy (args_copy, args); const char *str = ""; int number = 0; float fnumber = 0; while (*format) { switch (*format++) { case '\''s'\'': // string str = va_arg (args_copy, const char *); break; case '\''d'\'': // int number = va_arg (args_copy, int); break; case '\''f'\'': // float fnumber = va_arg (args_copy, double); break; default: break; } } va_end (args_copy); va_end (args); return *str && number && fnumber; } ' # Test code for whether the C compiler supports C99 (body of main). ac_c_conftest_c99_main=' // Check bool. _Bool success = false; success |= (argc != 0); // Check restrict. if (test_restrict ("String literal") == 0) success = true; const char *restrict newvar = "Another string"; // Check varargs. success &= test_varargs ("s, d'\'' f .", "string", 65, 34.234); test_varargs_macros (); // Check flexible array members. static struct incomplete_array *volatile incomplete_array_pointer; struct incomplete_array *ia = incomplete_array_pointer; ia->datasize = 10; for (int i = 0; i < ia->datasize; ++i) ia->data[i] = i * 1.234; // Work around memory leak warnings. free (ia); // Check named initializers. struct named_init ni = { .number = 34, .name = L"Test wide string", .average = 543.34343, }; ni.number = 58; // Do not test for VLAs, as some otherwise-conforming compilers lack them. // C code should instead use __STDC_NO_VLA__; see Autoconf manual. // work around unused variable warnings ok |= (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == '\''x'\'' || ni.number != 58); ' # Test code for whether the C compiler supports C11 (global declarations) ac_c_conftest_c11_globals=' /* Does the compiler advertise C11 conformance? */ #if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112L # error "Compiler does not advertise C11 conformance" #endif // Check _Alignas. char _Alignas (double) aligned_as_double; char _Alignas (0) no_special_alignment; extern char aligned_as_int; char _Alignas (0) _Alignas (int) aligned_as_int; // Check _Alignof. enum { int_alignment = _Alignof (int), int_array_alignment = _Alignof (int[100]), char_alignment = _Alignof (char) }; _Static_assert (0 < -_Alignof (int), "_Alignof is signed"); // Check _Noreturn. int _Noreturn does_not_return (void) { for (;;) continue; } // Check _Static_assert. struct test_static_assert { int x; _Static_assert (sizeof (int) <= sizeof (long int), "_Static_assert does not work in struct"); long int y; }; // Check UTF-8 literals. #define u8 syntax error! char const utf8_literal[] = u8"happens to be ASCII" "another string"; // Check duplicate typedefs. typedef long *long_ptr; typedef long int *long_ptr; typedef long_ptr long_ptr; // Anonymous structures and unions -- taken from C11 6.7.2.1 Example 1. struct anonymous { union { struct { int i; int j; }; struct { int k; long int l; } w; }; int m; } v1; ' # Test code for whether the C compiler supports C11 (body of main). ac_c_conftest_c11_main=' _Static_assert ((offsetof (struct anonymous, i) == offsetof (struct anonymous, w.k)), "Anonymous union alignment botch"); v1.i = 2; v1.w.k = 5; ok |= v1.i != 5; ' # Test code for whether the C compiler supports C11 (complete). ac_c_conftest_c11_program="${ac_c_conftest_c89_globals} ${ac_c_conftest_c99_globals} ${ac_c_conftest_c11_globals} int main (int argc, char **argv) { int ok = 0; ${ac_c_conftest_c89_main} ${ac_c_conftest_c99_main} ${ac_c_conftest_c11_main} return ok; } " # Test code for whether the C compiler supports C99 (complete). ac_c_conftest_c99_program="${ac_c_conftest_c89_globals} ${ac_c_conftest_c99_globals} int main (int argc, char **argv) { int ok = 0; ${ac_c_conftest_c89_main} ${ac_c_conftest_c99_main} return ok; } " # Test code for whether the C compiler supports C89 (complete). ac_c_conftest_c89_program="${ac_c_conftest_c89_globals} int main (int argc, char **argv) { int ok = 0; ${ac_c_conftest_c89_main} return ok; } " # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { printf '%s\n' "$as_me:${as_lineno-$LINENO}: error: '$ac_var' was set to '$ac_old_val' in the previous run" >&5 printf '%s\n' "$as_me: error: '$ac_var' was set to '$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { printf '%s\n' "$as_me:${as_lineno-$LINENO}: error: '$ac_var' was not set in the previous run" >&5 printf '%s\n' "$as_me: error: '$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w= for ac_val in x $ac_old_val; do ac_old_val_w="$ac_old_val_w $ac_val" done ac_new_val_w= for ac_val in x $ac_new_val; do ac_new_val_w="$ac_new_val_w $ac_val" done if test "$ac_old_val_w" != "$ac_new_val_w"; then { printf '%s\n' "$as_me:${as_lineno-$LINENO}: error: '$ac_var' has changed since the previous run:" >&5 printf '%s\n' "$as_me: error: '$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { printf '%s\n' "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in '$ac_var' since the previous run:" >&5 printf '%s\n' "$as_me: warning: ignoring whitespace changes in '$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { printf '%s\n' "$as_me:${as_lineno-$LINENO}: former value: '$ac_old_val'" >&5 printf '%s\n' "$as_me: former value: '$ac_old_val'" >&2;} { printf '%s\n' "$as_me:${as_lineno-$LINENO}: current value: '$ac_new_val'" >&5 printf '%s\n' "$as_me: current value: '$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`printf '%s\n' "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { printf '%s\n' "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5 printf '%s\n' "$as_me: error: in '$ac_pwd':" >&2;} { printf '%s\n' "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 printf '%s\n' "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run '${MAKE-make} distclean' and/or 'rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## # Determine whether it's possible to make 'echo' print without a newline. # These variables are no longer used directly by Autoconf, but are AC_SUBSTed # for compatibility with existing Makefiles. ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu #-------------------------------------------------------------------- # Remember whether the user gave --prefix on the command line, before # TEA_INIT and TEA_PREFIX get their hands on the variables. Needed to # fix up the exec_prefix after TEA_PREFIX (see below). #-------------------------------------------------------------------- if test "${prefix}" != "NONE"; then user_prefix=yes fi #-------------------------------------------------------------------- # Call TEA_INIT as the first TEA_ macro to set up initial vars. # This will define a ${TEA_PLATFORM} variable == "unix" or "windows" # as well as PKG_LIB_FILE and PKG_STUB_LIB_FILE. #-------------------------------------------------------------------- TEA_VERSION="3.13" { printf '%s\n' "$as_me:${as_lineno-$LINENO}: checking TEA configuration" >&5 printf %s "checking TEA configuration... " >&6; } if test x"${PACKAGE_NAME}" = x ; then as_fn_error $? " The PACKAGE_NAME variable must be defined by your TEA configure.ac" "$LINENO" 5 fi { printf '%s\n' "$as_me:${as_lineno-$LINENO}: result: ok (TEA ${TEA_VERSION})" >&5 printf '%s\n' "ok (TEA ${TEA_VERSION})" >&6; } # If the user did not set CFLAGS, set it now to keep macros # like AC_PROG_CC and AC_TRY_COMPILE from adding "-g -O2". if test "${CFLAGS+set}" != "set" ; then CFLAGS="" fi case "`uname -s`" in *win32*|*WIN32*|*MINGW32_*|*MINGW64_*|*MSYS_*) # Extract the first word of "cygpath", so it can be a program name with args. set dummy cygpath; ac_word=$2 { printf '%s\n' "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CYGPATH+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$CYGPATH"; then ac_cv_prog_CYGPATH="$CYGPATH" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CYGPATH="cygpath -m" printf '%s\n' "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_CYGPATH" && ac_cv_prog_CYGPATH="echo" fi ;; esac fi CYGPATH=$ac_cv_prog_CYGPATH if test -n "$CYGPATH"; then { printf '%s\n' "$as_me:${as_lineno-$LINENO}: result: $CYGPATH" >&5 printf '%s\n' "$CYGPATH" >&6; } else { printf '%s\n' "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf '%s\n' "no" >&6; } fi EXEEXT=".exe" TEA_PLATFORM="windows" ;; *CYGWIN_*) EXEEXT=".exe" # CYGPATH and TEA_PLATFORM are determined later in LOAD_TCLCONFIG ;; *) CYGPATH=echo # Maybe we are cross-compiling.... case ${host_alias} in *mingw32*) EXEEXT=".exe" TEA_PLATFORM="windows" ;; *) EXEEXT="" TEA_PLATFORM="unix" ;; esac ;; esac # Check if exec_prefix is set. If not use fall back to prefix. # Note when adjusted, so that TEA_PREFIX can correct for this. # This is needed for recursive configures, since autoconf propagates # $prefix, but not $exec_prefix (doh!). if test x$exec_prefix = xNONE ; then exec_prefix_default=yes exec_prefix=$prefix fi { printf '%s\n' "$as_me:${as_lineno-$LINENO}: configuring ${PACKAGE_NAME} ${PACKAGE_VERSION}" >&5 printf '%s\n' "$as_me: configuring ${PACKAGE_NAME} ${PACKAGE_VERSION}" >&6;} # This package name must be replaced statically for AC_SUBST to work # We AC_SUBST these here to ensure they are subst'ed, # in case the user doesn't call TEA_ADD_... # Configure the installer. INSTALL='$(SHELL) $(srcdir)/tclconfig/install-sh -c' INSTALL_DATA_DIR='${INSTALL} -d -m 755' INSTALL_DATA='${INSTALL} -m 644' INSTALL_PROGRAM='${INSTALL} -m 755' INSTALL_SCRIPT='${INSTALL} -m 755' { printf '%s\n' "$as_me:${as_lineno-$LINENO}: checking system version" >&5 printf %s "checking system version... " >&6; } if test ${tcl_cv_sys_version+y} then : printf %s "(cached) " >&6 else case e in #( e) # TEA specific: if test "${TEA_PLATFORM}" = "windows" ; then tcl_cv_sys_version=windows else tcl_cv_sys_version=`uname -s`-`uname -r` if test "$?" -ne 0 ; then { printf '%s\n' "$as_me:${as_lineno-$LINENO}: WARNING: can't find uname command" >&5 printf '%s\n' "$as_me: WARNING: can't find uname command" >&2;} tcl_cv_sys_version=unknown else if test "`uname -s`" = "AIX" ; then tcl_cv_sys_version=AIX-`uname -v`.`uname -r` fi if test "`uname -s`" = "NetBSD" -a -f /etc/debian_version ; then tcl_cv_sys_version=NetBSD-Debian fi fi fi ;; esac fi { printf '%s\n' "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_sys_version" >&5 printf '%s\n' "$tcl_cv_sys_version" >&6; } system=$tcl_cv_sys_version case $system in HP-UX-*) INSTALL_LIBRARY='${INSTALL} -m 755' ;; *) INSTALL_LIBRARY='${INSTALL} -m 644' ;; esac #-------------------------------------------------------------------- # Load the tclConfig.sh file #-------------------------------------------------------------------- # # Ok, lets find the tcl configuration # First, look for one uninstalled. # the alternative search directory is invoked by --with-tcl # if test x"${no_tcl}" = x ; then # we reset no_tcl in case something fails here no_tcl=true # Check whether --with-tcl was given. if test ${with_tcl+y} then : withval=$with_tcl; with_tclconfig="${withval}" fi # Check whether --with-tcl8 was given. if test ${with_tcl8+y} then : withval=$with_tcl8; with_tcl8="${withval}" fi { printf '%s\n' "$as_me:${as_lineno-$LINENO}: checking for Tcl configuration" >&5 printf %s "checking for Tcl configuration... " >&6; } if test ${ac_cv_c_tclconfig+y} then : printf %s "(cached) " >&6 else case e in #( e) # First check to see if --with-tcl was specified. if test x"${with_tclconfig}" != x ; then case "${with_tclconfig}" in */tclConfig.sh ) if test -f "${with_tclconfig}"; then { printf '%s\n' "$as_me:${as_lineno-$LINENO}: WARNING: --with-tcl argument should refer to directory containing tclConfig.sh, not to tclConfig.sh itself" >&5 printf '%s\n' "$as_me: WARNING: --with-tcl argument should refer to directory containing tclConfig.sh, not to tclConfig.sh itself" >&2;} with_tclconfig="`echo "${with_tclconfig}" | sed 's!/tclConfig\.sh$!!'`" fi ;; esac if test -f "${with_tclconfig}/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd "${with_tclconfig}"; pwd)`" else as_fn_error $? "${with_tclconfig} directory doesn't contain tclConfig.sh" "$LINENO" 5 fi fi # then check for a private Tcl installation if test x"${ac_cv_c_tclconfig}" = x ; then for i in \ ../tcl \ `ls -dr ../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \ `ls -dr ../tcl[8-9].[0-9] 2>/dev/null` \ `ls -dr ../tcl[8-9].[0-9]* 2>/dev/null` \ ../../tcl \ `ls -dr ../../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \ `ls -dr ../../tcl[8-9].[0-9] 2>/dev/null` \ `ls -dr ../../tcl[8-9].[0-9]* 2>/dev/null` \ ../../../tcl \ `ls -dr ../../../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \ `ls -dr ../../../tcl[8-9].[0-9] 2>/dev/null` \ `ls -dr ../../../tcl[8-9].[0-9]* 2>/dev/null` ; do if test "${TEA_PLATFORM}" = "windows" \ -a -f "$i/win/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i/win; pwd)`" break fi if test -f "$i/unix/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i/unix; pwd)`" break fi done fi # on Darwin, check in Framework installation locations if test "`uname -s`" = "Darwin" -a x"${ac_cv_c_tclconfig}" = x ; then for i in `ls -d ~/Library/Frameworks 2>/dev/null` \ `ls -d /Library/Frameworks 2>/dev/null` \ `ls -d /Network/Library/Frameworks 2>/dev/null` \ `ls -d /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/Library/Frameworks/Tcl.framework 2>/dev/null` \ `ls -d /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/Network/Library/Frameworks/Tcl.framework 2>/dev/null` \ `ls -d /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/Tcl.framework 2>/dev/null` \ ; do if test -f "$i/Tcl.framework/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i/Tcl.framework; pwd)`" break fi done fi # TEA specific: on Windows, check in common installation locations if test "${TEA_PLATFORM}" = "windows" \ -a x"${ac_cv_c_tclconfig}" = x ; then for i in `ls -d C:/Tcl/lib 2>/dev/null` \ `ls -d C:/Progra~1/Tcl/lib 2>/dev/null` \ ; do if test -f "$i/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i; pwd)`" break fi done fi # check in a few common install locations if test x"${ac_cv_c_tclconfig}" = x ; then for i in `ls -d ${libdir} 2>/dev/null` \ `ls -d ${exec_prefix}/lib 2>/dev/null` \ `ls -d ${prefix}/lib 2>/dev/null` \ `ls -d /usr/local/lib 2>/dev/null` \ `ls -d /usr/contrib/lib 2>/dev/null` \ `ls -d /usr/pkg/lib 2>/dev/null` \ `ls -d /usr/lib 2>/dev/null` \ `ls -d /usr/lib64 2>/dev/null` \ `ls -d /usr/lib/tcl8.6 2>/dev/null` \ `ls -d /usr/lib/tcl8.5 2>/dev/null` \ `ls -d /usr/local/lib/tcl8.6 2>/dev/null` \ `ls -d /usr/local/lib/tcl8.5 2>/dev/null` \ `ls -d /usr/local/lib/tcl/tcl8.6 2>/dev/null` \ `ls -d /usr/local/lib/tcl/tcl8.5 2>/dev/null` \ ; do if test -f "$i/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i; pwd)`" break fi done fi # check in a few other private locations if test x"${ac_cv_c_tclconfig}" = x ; then for i in \ ${srcdir}/../tcl \ `ls -dr ${srcdir}/../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \ `ls -dr ${srcdir}/../tcl[8-9].[0-9] 2>/dev/null` \ `ls -dr ${srcdir}/../tcl[8-9].[0-9]* 2>/dev/null` ; do if test "${TEA_PLATFORM}" = "windows" \ -a -f "$i/win/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i/win; pwd)`" break fi if test -f "$i/unix/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i/unix; pwd)`" break fi done fi ;; esac fi if test x"${ac_cv_c_tclconfig}" = x ; then TCL_BIN_DIR="# no Tcl configs found" as_fn_error $? "Can't find Tcl configuration definitions. Use --with-tcl to specify a directory containing tclConfig.sh" "$LINENO" 5 else no_tcl= TCL_BIN_DIR="${ac_cv_c_tclconfig}" { printf '%s\n' "$as_me:${as_lineno-$LINENO}: result: found ${TCL_BIN_DIR}/tclConfig.sh" >&5 printf '%s\n' "found ${TCL_BIN_DIR}/tclConfig.sh" >&6; } fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { printf '%s\n' "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" printf '%s\n' "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf '%s\n' "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf '%s\n' "$CC" >&6; } else { printf '%s\n' "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf '%s\n' "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { printf '%s\n' "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_CC+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" printf '%s\n' "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { printf '%s\n' "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 printf '%s\n' "$ac_ct_CC" >&6; } else { printf '%s\n' "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf '%s\n' "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { printf '%s\n' "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf '%s\n' "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { printf '%s\n' "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" printf '%s\n' "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf '%s\n' "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf '%s\n' "$CC" >&6; } else { printf '%s\n' "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf '%s\n' "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { printf '%s\n' "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then if test "$as_dir$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" printf '%s\n' "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir$ac_word${1+' '}$@" fi fi fi ;; esac fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf '%s\n' "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf '%s\n' "$CC" >&6; } else { printf '%s\n' "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf '%s\n' "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { printf '%s\n' "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" printf '%s\n' "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf '%s\n' "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf '%s\n' "$CC" >&6; } else { printf '%s\n' "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf '%s\n' "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { printf '%s\n' "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_CC+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" printf '%s\n' "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { printf '%s\n' "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 printf '%s\n' "$ac_ct_CC" >&6; } else { printf '%s\n' "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf '%s\n' "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { printf '%s\n' "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf '%s\n' "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}clang", so it can be a program name with args. set dummy ${ac_tool_prefix}clang; ac_word=$2 { printf '%s\n' "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}clang" printf '%s\n' "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf '%s\n' "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf '%s\n' "$CC" >&6; } else { printf '%s\n' "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf '%s\n' "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "clang", so it can be a program name with args. set dummy clang; ac_word=$2 { printf '%s\n' "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_CC+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="clang" printf '%s\n' "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { printf '%s\n' "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 printf '%s\n' "$ac_ct_CC" >&6; } else { printf '%s\n' "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf '%s\n' "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { printf '%s\n' "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf '%s\n' "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi fi test -z "$CC" && { { printf '%s\n' "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5 printf '%s\n' "$as_me: error: in '$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See 'config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. printf '%s\n' "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion -version; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf '%s\n' "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err printf '%s\n' "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { printf '%s\n' "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 printf %s "checking whether the C compiler works... " >&6; } ac_link_default=`printf '%s\n' "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf '%s\n' "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? printf '%s\n' "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then : # Autoconf-2.13 could set the ac_cv_exeext variable to 'no'. # So ignore a value of 'no', otherwise this would lead to 'EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test ${ac_cv_exeext+y} && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an '-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else case e in #( e) ac_file='' ;; esac fi if test -z "$ac_file" then : { printf '%s\n' "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf '%s\n' "no" >&6; } printf '%s\n' "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { printf '%s\n' "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5 printf '%s\n' "$as_me: error: in '$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See 'config.log' for more details" "$LINENO" 5; } else case e in #( e) { printf '%s\n' "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf '%s\n' "yes" >&6; } ;; esac fi { printf '%s\n' "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 printf %s "checking for C compiler default output file name... " >&6; } { printf '%s\n' "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 printf '%s\n' "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { printf '%s\n' "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 printf %s "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf '%s\n' "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? printf '%s\n' "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then : # If both 'conftest.exe' and 'conftest' are 'present' (well, observable) # catch 'conftest.exe'. For instance with Cygwin, 'ls conftest' will # work properly (i.e., refer to 'conftest.exe'), while it won't with # 'rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else case e in #( e) { { printf '%s\n' "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5 printf '%s\n' "$as_me: error: in '$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See 'config.log' for more details" "$LINENO" 5; } ;; esac fi rm -f conftest conftest$ac_cv_exeext { printf '%s\n' "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 printf '%s\n' "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { FILE *f = fopen ("conftest.out", "w"); if (!f) return 1; return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { printf '%s\n' "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 printf %s "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf '%s\n' "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? printf '%s\n' "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf '%s\n' "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? printf '%s\n' "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { printf '%s\n' "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5 printf '%s\n' "$as_me: error: in '$ac_pwd':" >&2;} as_fn_error 77 "cannot run C compiled programs. If you meant to cross compile, use '--host'. See 'config.log' for more details" "$LINENO" 5; } fi fi fi { printf '%s\n' "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 printf '%s\n' "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext \ conftest.o conftest.obj conftest.out ac_clean_files=$ac_clean_files_save { printf '%s\n' "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 printf %s "checking for suffix of object files... " >&6; } if test ${ac_cv_objext+y} then : printf %s "(cached) " >&6 else case e in #( e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf '%s\n' "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? printf '%s\n' "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else case e in #( e) printf '%s\n' "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { printf '%s\n' "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5 printf '%s\n' "$as_me: error: in '$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See 'config.log' for more details" "$LINENO" 5; } ;; esac fi rm -f conftest.$ac_cv_objext conftest.$ac_ext ;; esac fi { printf '%s\n' "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 printf '%s\n' "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { printf '%s\n' "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C" >&5 printf %s "checking whether the compiler supports GNU C... " >&6; } if test ${ac_cv_c_compiler_gnu+y} then : printf %s "(cached) " >&6 else case e in #( e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_compiler_gnu=yes else case e in #( e) ac_compiler_gnu=no ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu ;; esac fi { printf '%s\n' "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 printf '%s\n' "$ac_cv_c_compiler_gnu" >&6; } ac_compiler_gnu=$ac_cv_c_compiler_gnu if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+y} ac_save_CFLAGS=$CFLAGS { printf '%s\n' "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 printf %s "checking whether $CC accepts -g... " >&6; } if test ${ac_cv_prog_cc_g+y} then : printf %s "(cached) " >&6 else case e in #( e) ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_g=yes else case e in #( e) CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : else case e in #( e) ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag ;; esac fi { printf '%s\n' "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 printf '%s\n' "$ac_cv_prog_cc_g" >&6; } if test $ac_test_CFLAGS; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi ac_prog_cc_stdc=no if test x$ac_prog_cc_stdc = xno then : { printf '%s\n' "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C23 features" >&5 printf %s "checking for $CC option to enable C23 features... " >&6; } if test ${ac_cv_prog_cc_c23+y} then : printf %s "(cached) " >&6 else case e in #( e) ac_cv_prog_cc_c23=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_c_conftest_c23_program _ACEOF for ac_arg in '' -std=gnu23 do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_c23=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cc_c23" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC ;; esac fi if test "x$ac_cv_prog_cc_c23" = xno then : { printf '%s\n' "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf '%s\n' "unsupported" >&6; } else case e in #( e) if test "x$ac_cv_prog_cc_c23" = x then : { printf '%s\n' "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf '%s\n' "none needed" >&6; } else case e in #( e) { printf '%s\n' "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c23" >&5 printf '%s\n' "$ac_cv_prog_cc_c23" >&6; } CC="$CC $ac_cv_prog_cc_c23" ;; esac fi ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c23 ac_prog_cc_stdc=c23 ;; esac fi fi if test x$ac_prog_cc_stdc = xno then : { printf '%s\n' "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C11 features" >&5 printf %s "checking for $CC option to enable C11 features... " >&6; } if test ${ac_cv_prog_cc_c11+y} then : printf %s "(cached) " >&6 else case e in #( e) ac_cv_prog_cc_c11=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_c_conftest_c11_program _ACEOF for ac_arg in '' -std=gnu11 -std:c11 do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_c11=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cc_c11" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC ;; esac fi if test "x$ac_cv_prog_cc_c11" = xno then : { printf '%s\n' "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf '%s\n' "unsupported" >&6; } else case e in #( e) if test "x$ac_cv_prog_cc_c11" = x then : { printf '%s\n' "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf '%s\n' "none needed" >&6; } else case e in #( e) { printf '%s\n' "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c11" >&5 printf '%s\n' "$ac_cv_prog_cc_c11" >&6; } CC="$CC $ac_cv_prog_cc_c11" ;; esac fi ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c11 ac_prog_cc_stdc=c11 ;; esac fi fi if test x$ac_prog_cc_stdc = xno then : { printf '%s\n' "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C99 features" >&5 printf %s "checking for $CC option to enable C99 features... " >&6; } if test ${ac_cv_prog_cc_c99+y} then : printf %s "(cached) " >&6 else case e in #( e) ac_cv_prog_cc_c99=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_c_conftest_c99_program _ACEOF for ac_arg in '' -std=gnu99 -std=c99 -c99 -qlanglvl=extc1x -qlanglvl=extc99 -AC99 -D_STDC_C99= do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_c99=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cc_c99" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC ;; esac fi if test "x$ac_cv_prog_cc_c99" = xno then : { printf '%s\n' "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf '%s\n' "unsupported" >&6; } else case e in #( e) if test "x$ac_cv_prog_cc_c99" = x then : { printf '%s\n' "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf '%s\n' "none needed" >&6; } else case e in #( e) { printf '%s\n' "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5 printf '%s\n' "$ac_cv_prog_cc_c99" >&6; } CC="$CC $ac_cv_prog_cc_c99" ;; esac fi ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99 ac_prog_cc_stdc=c99 ;; esac fi fi if test x$ac_prog_cc_stdc = xno then : { printf '%s\n' "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C89 features" >&5 printf %s "checking for $CC option to enable C89 features... " >&6; } if test ${ac_cv_prog_cc_c89+y} then : printf %s "(cached) " >&6 else case e in #( e) ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_c_conftest_c89_program _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC ;; esac fi if test "x$ac_cv_prog_cc_c89" = xno then : { printf '%s\n' "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf '%s\n' "unsupported" >&6; } else case e in #( e) if test "x$ac_cv_prog_cc_c89" = x then : { printf '%s\n' "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf '%s\n' "none needed" >&6; } else case e in #( e) { printf '%s\n' "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 printf '%s\n' "$ac_cv_prog_cc_c89" >&6; } CC="$CC $ac_cv_prog_cc_c89" ;; esac fi ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89 ac_prog_cc_stdc=c89 ;; esac fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { printf '%s\n' "$as_me:${as_lineno-$LINENO}: checking for existence of ${TCL_BIN_DIR}/tclConfig.sh" >&5 printf %s "checking for existence of ${TCL_BIN_DIR}/tclConfig.sh... " >&6; } if test -f "${TCL_BIN_DIR}/tclConfig.sh" ; then { printf '%s\n' "$as_me:${as_lineno-$LINENO}: result: loading" >&5 printf '%s\n' "loading" >&6; } . "${TCL_BIN_DIR}/tclConfig.sh" else { printf '%s\n' "$as_me:${as_lineno-$LINENO}: result: could not find ${TCL_BIN_DIR}/tclConfig.sh" >&5 printf '%s\n' "could not find ${TCL_BIN_DIR}/tclConfig.sh" >&6; } fi # If the TCL_BIN_DIR is the build directory (not the install directory), # then set the common variable name to the value of the build variables. # For example, the variable TCL_LIB_SPEC will be set to the value # of TCL_BUILD_LIB_SPEC. An extension should make use of TCL_LIB_SPEC # instead of TCL_BUILD_LIB_SPEC since it will work with both an # installed and uninstalled version of Tcl. if test -f "${TCL_BIN_DIR}/Makefile" ; then TCL_LIB_SPEC="${TCL_BUILD_LIB_SPEC}" TCL_STUB_LIB_SPEC="${TCL_BUILD_STUB_LIB_SPEC}" TCL_STUB_LIB_PATH="${TCL_BUILD_STUB_LIB_PATH}" elif test "`uname -s`" = "Darwin"; then # If Tcl was built as a framework, attempt to use the libraries # from the framework at the given location so that linking works # against Tcl.framework installed in an arbitrary location. case ${TCL_DEFS} in *TCL_FRAMEWORK*) if test -f "${TCL_BIN_DIR}/${TCL_LIB_FILE}"; then for i in "`cd "${TCL_BIN_DIR}"; pwd`" \ "`cd "${TCL_BIN_DIR}"/../..; pwd`"; do if test "`basename "$i"`" = "${TCL_LIB_FILE}.framework"; then TCL_LIB_SPEC="-F`dirname "$i" | sed -e 's/ /\\\\ /g'` -framework ${TCL_LIB_FILE}" break fi done fi if test -f "${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}"; then TCL_STUB_LIB_SPEC="-L`echo "${TCL_BIN_DIR}" | sed -e 's/ /\\\\ /g'` ${TCL_STUB_LIB_FLAG}" TCL_STUB_LIB_PATH="${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}" fi ;; esac fi { printf '%s\n' "$as_me:${as_lineno-$LINENO}: checking platform" >&5 printf %s "checking platform... " >&6; } hold_cc=$CC; CC="$TCL_CC" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { #ifdef _WIN32 #error win32 #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : # first test we've already retrieved platform (cross-compile), fallback to unix otherwise: TEA_PLATFORM="${TEA_PLATFORM-unix}" CYGPATH=echo else case e in #( e) TEA_PLATFORM="windows" # Extract the first word of "cygpath", so it can be a program name with args. set dummy cygpath; ac_word=$2 { printf '%s\n' "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CYGPATH+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$CYGPATH"; then ac_cv_prog_CYGPATH="$CYGPATH" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CYGPATH="cygpath -m" printf '%s\n' "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_CYGPATH" && ac_cv_prog_CYGPATH="echo" fi ;; esac fi CYGPATH=$ac_cv_prog_CYGPATH if test -n "$CYGPATH"; then { printf '%s\n' "$as_me:${as_lineno-$LINENO}: result: $CYGPATH" >&5 printf '%s\n' "$CYGPATH" >&6; } else { printf '%s\n' "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf '%s\n' "no" >&6; } fi ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext CC=$hold_cc { printf '%s\n' "$as_me:${as_lineno-$LINENO}: result: $TEA_PLATFORM" >&5 printf '%s\n' "$TEA_PLATFORM" >&6; } # The BUILD_$pkg is to define the correct extern storage class # handling when making this package cat >>confdefs.h <<_ACEOF #define BUILD_${PACKAGE_NAME} /**/ _ACEOF # Do this here as we have fully defined TEA_PLATFORM now if test "${TEA_PLATFORM}" = "windows" ; then EXEEXT=".exe" CLEANFILES="$CLEANFILES *.lib *.dll *.pdb *.exp" fi # TEA specific: #----------------------------------------------------------------------- # Handle the --prefix=... option by defaulting to what Tcl gave. # Must be called after TEA_LOAD_TCLCONFIG and before TEA_SETUP_COMPILER. #----------------------------------------------------------------------- if test "${prefix}" = "NONE"; then prefix_default=yes if test x"${TCL_PREFIX}" != x; then { printf '%s\n' "$as_me:${as_lineno-$LINENO}: --prefix defaulting to TCL_PREFIX ${TCL_PREFIX}" >&5 printf '%s\n' "$as_me: --prefix defaulting to TCL_PREFIX ${TCL_PREFIX}" >&6;} prefix=${TCL_PREFIX} else { printf '%s\n' "$as_me:${as_lineno-$LINENO}: --prefix defaulting to /usr/local" >&5 printf '%s\n' "$as_me: --prefix defaulting to /usr/local" >&6;} prefix=/usr/local fi fi if test "${exec_prefix}" = "NONE" -a x"${prefix_default}" = x"yes" \ -o x"${exec_prefix_default}" = x"yes" ; then if test x"${TCL_EXEC_PREFIX}" != x; then { printf '%s\n' "$as_me:${as_lineno-$LINENO}: --exec-prefix defaulting to TCL_EXEC_PREFIX ${TCL_EXEC_PREFIX}" >&5 printf '%s\n' "$as_me: --exec-prefix defaulting to TCL_EXEC_PREFIX ${TCL_EXEC_PREFIX}" >&6;} exec_prefix=${TCL_EXEC_PREFIX} else { printf '%s\n' "$as_me:${as_lineno-$LINENO}: --exec-prefix defaulting to ${prefix}" >&5 printf '%s\n' "$as_me: --exec-prefix defaulting to ${prefix}" >&6;} exec_prefix=$prefix fi fi #----------------------------------------------------------------------- # When the user gave --prefix but not --exec-prefix, TEA_INIT sets # exec_prefix to the prefix but notes exec_prefix_default=yes, which # makes TEA_PREFIX overwrite it again with the exec prefix recorded in # tclConfig.sh - the package then installs into the Tcl tree no matter # what --prefix said (ticket 1a64a34982). Restore the user's choice. #----------------------------------------------------------------------- if test x"${user_prefix}" = x"yes" -a x"${exec_prefix_default}" = x"yes"; then { printf '%s\n' "$as_me:${as_lineno-$LINENO}: --prefix given: overriding exec_prefix back to ${prefix}" >&5 printf '%s\n' "$as_me: --prefix given: overriding exec_prefix back to ${prefix}" >&6;} exec_prefix=$prefix fi #----------------------------------------------------------------------- # Specify the C source files to compile in TEA_ADD_SOURCES, # public headers that need to be installed in TEA_ADD_HEADERS, # stub library C source files to compile in TEA_ADD_STUB_SOURCES, # and runtime Tcl library files in TEA_ADD_TCL_SOURCES. # This defines PKG(_STUB)_SOURCES, PKG(_STUB)_OBJECTS, PKG_HEADERS # and PKG_TCL_SOURCES. #----------------------------------------------------------------------- vars="ooxml.tcl \ ooxml-docx.tcl \ ooxml-docx-lib.tcl \ ooxml-docx-math.tcl" for i in $vars; do # check for existence, be strict because it is installed if test ! -f "${srcdir}/$i" ; then as_fn_error $? "could not find tcl source file '${srcdir}/$i'" "$LINENO" 5 fi PKG_TCL_SOURCES="$PKG_TCL_SOURCES $i" done #-------------------------------------------------------------------- # You can add more files to clean if your extension creates any extra # files by extending CLEANFILES. # Add pkgIndex.tcl if it is generated in the Makefile instead of ./configure # and change Makefile.in to move it from CONFIG_CLEAN_FILES to BINARIES var. # # A few miscellaneous platform-specific items: # TEA_ADD_* any platform specific compiler/build info here. #-------------------------------------------------------------------- #CLEANFILES="$CLEANFILES" #-------------------------------------------------------------------- # Determine the name of the tclsh and/or wish executables in the # Tcl and Tk build directories or the location they were installed # into. These paths are used to support running test cases only, # the Makefile should not be making use of these paths to generate # a pkgIndex.tcl file or anything else at extension build time. #-------------------------------------------------------------------- { printf '%s\n' "$as_me:${as_lineno-$LINENO}: checking for tclsh" >&5 printf %s "checking for tclsh... " >&6; } if test -f "${TCL_BIN_DIR}/Makefile" ; then # tclConfig.sh is in Tcl build directory if test "${TEA_PLATFORM}" = "windows"; then if test -f "${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${EXEEXT}" ; then TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${EXEEXT}" elif test -f "${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}s${EXEEXT}" ; then TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}s${EXEEXT}" elif test -f "${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}t${EXEEXT}" ; then TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}t${EXEEXT}" elif test -f "${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}st${EXEEXT}" ; then TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}st${EXEEXT}" fi else TCLSH_PROG="${TCL_BIN_DIR}/tclsh" fi else # tclConfig.sh is in install location if test "${TEA_PLATFORM}" = "windows"; then TCLSH_PROG="tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${EXEEXT}" else TCLSH_PROG="tclsh${TCL_MAJOR_VERSION}.${TCL_MINOR_VERSION}" fi list="`ls -d ${TCL_BIN_DIR}/../bin 2>/dev/null` \ `ls -d ${TCL_BIN_DIR}/.. 2>/dev/null` \ `ls -d ${TCL_PREFIX}/bin 2>/dev/null`" for i in $list ; do if test -f "$i/${TCLSH_PROG}" ; then REAL_TCL_BIN_DIR="`cd "$i"; pwd`/" break fi done TCLSH_PROG="${REAL_TCL_BIN_DIR}${TCLSH_PROG}" fi { printf '%s\n' "$as_me:${as_lineno-$LINENO}: result: ${TCLSH_PROG}" >&5 printf '%s\n' "${TCLSH_PROG}" >&6; } #-------------------------------------------------------------------- # Local autoconf addition not worth an own file #-------------------------------------------------------------------- # Extract the first word of "pandoc", so it can be a program name with args. set dummy pandoc; ac_word=$2 { printf '%s\n' "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_HAVE_PANDOC+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$HAVE_PANDOC"; then ac_cv_prog_HAVE_PANDOC="$HAVE_PANDOC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_HAVE_PANDOC="yes" printf '%s\n' "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_HAVE_PANDOC" && ac_cv_prog_HAVE_PANDOC="no" fi ;; esac fi HAVE_PANDOC=$ac_cv_prog_HAVE_PANDOC if test -n "$HAVE_PANDOC"; then { printf '%s\n' "$as_me:${as_lineno-$LINENO}: result: $HAVE_PANDOC" >&5 printf '%s\n' "$HAVE_PANDOC" >&6; } else { printf '%s\n' "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf '%s\n' "no" >&6; } fi #-------------------------------------------------------------------- # Finally, substitute all of the various values into the Makefile. # You may alternatively have a special pkgIndex.tcl.in or other files # which require substituting th AC variables in. Include these here. #-------------------------------------------------------------------- ac_config_files="$ac_config_files Makefile pkgIndex.tcl" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # 'ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* 'ac_cv_foo' will be assigned the # following values. _ACEOF ac_cache_dump | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test ${\1+y} || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { printf '%s\n' "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 printf '%s\n' "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { printf '%s\n' "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 printf '%s\n' "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # Transform confdefs.h into DEFS. # Protect against shell expansion while executing Makefile rules. # Protect against Makefile macro expansion. # # If the first sed substitution is executed (which looks for macros that # take arguments), then branch to the quote section. Otherwise, # look for a macro that doesn't take arguments. ac_script=' :mline /\\$/{ N s,\\\n,, b mline } t clear :clear s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g t quote s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g t quote b any :quote s/[][ `~#$^&*(){}\\|;'\''"<>?]/\\&/g s/\$/$$/g H :any ${ g s/^\n// s/\n/ /g p } ' DEFS=`sed -n "$ac_script" confdefs.h` ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`printf '%s\n' "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs : "${CONFIG_STATUS=./config.status}" case $CONFIG_STATUS in #( -*) : CONFIG_STATUS=./$CONFIG_STATUS ;; #( */*) : ;; #( *) : CONFIG_STATUS=./$CONFIG_STATUS ;; esac ac_write_fail=0 ac_clean_CONFIG_STATUS='"$CONFIG_STATUS"' { printf '%s\n' "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 printf '%s\n' "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >"$CONFIG_STATUS" <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>"$CONFIG_STATUS" <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1 then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # contradicts POSIX and common usage. Disable this. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case e in #( e) case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac ;; esac fi # Reset variables that may have inherited troublesome values from # the environment. # IFS needs to be set, to space, tab, and newline, in precisely that order. # (If _AS_PATH_WALK were called with IFS unset, it would have the # side effect of setting IFS to empty, thus disabling word splitting.) # Quoting is to prevent editors from complaining about space-tab. as_nl=' ' export as_nl IFS=" "" $as_nl" PS1='$ ' PS2='> ' PS4='+ ' # Ensure predictable behavior from utilities with locale-dependent output. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # We cannot yet rely on "unset" to work, but we need these variables # to be unset--not just set to an empty or harmless value--now, to # avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct # also avoids known problems related to "unset" and subshell syntax # in other old shells (e.g. bash 2.01 and pdksh 5.2.14). for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH do eval test \${$as_var+y} \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done # Ensure that fds 0, 1, and 2 are open. if (exec 3>&0) 2>/dev/null; then :; else exec 0&1) 2>/dev/null; then :; else exec 1>/dev/null; fi if (exec 3>&2) ; then :; else exec 2>/dev/null; fi # The user is always right. if ${PATH_SEPARATOR+false} :; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac test -r "$as_dir$0" && as_myself=$as_dir$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as 'sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then printf '%s\n' "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack printf '%s\n' "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi printf '%s\n' "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null then : eval 'as_fn_append () { eval $1+=\$2 }' else case e in #( e) as_fn_append () { eval $1=\$$1\$2 } ;; esac fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null then : eval 'as_fn_arith () { as_val=$(( $* )) }' else case e in #( e) as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } ;; esac fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || printf '%s\n' X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both 'ln -s file dir' and 'ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; 'ln -s' creates a wrapper executable. # In both cases, we have to default to 'cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`printf '%s\n' "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || printf '%s\n' X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_sed_cpp="y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g" as_tr_cpp="eval sed '$as_sed_cpp'" # deprecated # Sed expression to map a string onto a valid variable name. as_sed_sh="y%*+%pp%;s%[^_$as_cr_alnum]%_%g" as_tr_sh="eval sed '$as_sed_sh'" # deprecated exec 6>&1 ## ------------------------------------- ## ## Main body of "$CONFIG_STATUS" script. ## ## ------------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x "$CONFIG_STATUS" || ac_write_fail=1 cat >>"$CONFIG_STATUS" <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by ooxml $as_me 1.13.1, which was generated by GNU Autoconf 2.73. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac cat >>"$CONFIG_STATUS" <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" _ACEOF cat >>"$CONFIG_STATUS" <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ '$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE Configuration files: $config_files Report bugs to the package provider." _ACEOF ac_cs_config=`printf '%s\n' "$ac_configure_args" | sed "$ac_safe_unquote"` ac_cs_config_escaped=`printf '%s\n' "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\''/g"` cat >>"$CONFIG_STATUS" <<_ACEOF || ac_write_fail=1 ac_cs_config='$ac_cs_config_escaped' ac_cs_version="\\ ooxml config.status 1.13.1 configured by $0, generated by GNU Autoconf 2.73, with options \\"\$ac_cs_config\\" Copyright (C) 2026 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' test -n "\$AWK" || { awk '' >"$CONFIG_STATUS" <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) printf '%s\n' "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) printf '%s\n' "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`printf '%s\n' "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --he | --h | --help | --hel | -h ) printf '%s\n' "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: '$1' Try '$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>"$CONFIG_STATUS" <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \printf '%s\n' "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>"$CONFIG_STATUS" <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX printf '%s\n' "$ac_log" } >&5 _ACEOF cat >>"$CONFIG_STATUS" <<_ACEOF || ac_write_fail=1 _ACEOF cat >>"$CONFIG_STATUS" <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "pkgIndex.tcl") CONFIG_FILES="$CONFIG_FILES pkgIndex.tcl" ;; *) as_fn_error $? "invalid argument: '$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test ${CONFIG_FILES+y} || CONFIG_FILES=$config_files fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to '$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with './config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | sed -n '$='` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | sed -n '$='` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>"$CONFIG_STATUS" <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >"$CONFIG_STATUS" || ac_write_fail=1 rm -f conf$$subs.awk cat >>"$CONFIG_STATUS" <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>"$CONFIG_STATUS" <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>"$CONFIG_STATUS" <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" eval set X " :F $CONFIG_FILES " shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag '$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain ':'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: '$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`printf '%s\n' "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is 'configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` printf '%s\n' "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { printf '%s\n' "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 printf '%s\n' "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`printf '%s\n' "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || printf '%s\n' X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`printf '%s\n' "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`printf '%s\n' "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # _ACEOF cat >>"$CONFIG_STATUS" <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { printf '%s\n' "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 printf '%s\n' "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>"$CONFIG_STATUS" <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when '$srcdir' = '.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>"$CONFIG_STATUS" <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>"$CONFIG_STATUS" <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { printf '%s\n' "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable 'datarootdir' which seems to be undefined. Please make sure it is defined" >&5 printf '%s\n' "$as_me: WARNING: $ac_file contains a reference to the variable 'datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_CONFIG_STATUS= test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: case $CONFIG_STATUS in #( -*) : ac_no_opts=-- ;; #( *) : ac_no_opts= ;; esac ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $ac_no_opts "$CONFIG_STATUS" $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { printf '%s\n' "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 printf '%s\n' "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi ooxml/manifest.txt000644 000765 000024 00000000547 15221665353 014675 0ustar00alexstaff000000 000000 MANIFEST_UUID 8f9305b374703d5698eca1f89d7ad9a7ec6ed0807da172fd3f11d30a4cdb1190 MANIFEST_VERSION 8f9305b374 FOSSIL_BUILD_HASH 07b23278057c2b78f16758397f937bc9 MANIFEST_DATE {2026-07-03 07:54:55} MANIFEST_YEAR 2026 MANIFEST_NUMERIC_DATE 20260703 MANIFEST_NUMERIC_TIME 075455 RELEASE_VERSION 1.13.1 RELEASE_VERSION_NUMBER 11310 RELEASE_RESOURCE_VERSION 1,13,1,0 ooxml/Makefile000644 000765 000024 00000011747 15221665126 013770 0ustar00alexstaff000000 000000 # Makefile.in -- # # If ths is "Makefile.in" then it is a template for a Makefile; to generate # the actual Makefile, run "./configure", which is a configuration script # generated by the "autoconf" program (constructs like "@foo@" will get # replaced in the actual Makefile. # # Copyright (C) 2019 Alexander Schoepe, Bochum, DE # #======================================================================== # Nothing of the variables below this line need to be changed. #======================================================================== SHELL = /bin/sh srcdir = . top_srcdir = . prefix = /opt/tcl/8.6 exec_prefix = /opt/tcl/8.6 datarootdir = ${prefix}/share libdir = ${exec_prefix}/lib mandir = ${datarootdir}/man bindir = ${exec_prefix}/bin DESTDIR = pkglibdir = $(libdir)/ooxml1.13.1 top_builddir = /Users/alex/src/ooxml PACKAGE_NAME = ooxml PACKAGE_VERSION = 1.13.1 CYGPATH = echo #======================================================================== # TCLLIBPATH seeds the auto_path in Tcl's init.tcl so we can test our # package without installing. The other environment variables allow us # to test against an uninstalled Tcl. Add special env vars that you # require for testing here (like TCLX_LIBRARY). #======================================================================== TCL_BIN_DIR = /Library/Frameworks/Tcl.framework TCL_SRC_DIR = /Users/alex/src/tcl8.6.17 EXTRA_PATH = $(top_builddir):$(TCL_BIN_DIR) TCLLIBPATH = $(top_builddir) TCLSH_ENV = TCL_LIBRARY=`echo $(TCL_SRC_DIR)/library` PKG_ENV = LD_LIBRARY_PATH="$(EXTRA_PATH):$(@LD_LIBRARY_PATH_VAR@)" \ PATH="$(EXTRA_PATH):$(PATH)" \ TCLLIBPATH="$(TCLLIBPATH)" TCLSH_PROG = /opt/tcl/8.6/bin/tclsh8.6 TCLSH = $(PKG_ENV) $(TCLSH_ENV) $(TCLSH_PROG) PKG_TCL_SOURCES = ooxml.tcl ooxml-docx.tcl ooxml-docx-lib.tcl ooxml-docx-math.tcl manifest.txt CONFIG_CLEAN_FILES = Makefile pkgIndex.tcl manifest.txt CLEANFILES = HAVE_PANDOC = yes #======================================================================== # Start of user-definable TARGETS section #======================================================================== # Keep the generated build files in sync with their templates, so that # e.g. a version bump in configure.ac propagates automatically before # any target is built (GNU make re-executes itself after remaking the # Makefile). configure: configure.ac autoconf config.status: configure ./config.status --recheck Makefile: Makefile.in config.status ./config.status Makefile pkgIndex.tcl: pkgIndex.tcl.in config.status ./config.status pkgIndex.tcl manifest.txt: manifest manifest.uuid tools/mkversion.tcl configure.ac $(TCLSH) tools/mkversion.tcl > $@ havepandoc: @if test "${HAVE_PANDOC}" != "yes" ; then \ echo "No pandoc found in the path. Pandoc is needed to" ;\ echo "build the nroff and html versions of the documentation." ;\ fi doc/ooxml.html: doc/ooxml.md @if test "${HAVE_PANDOC}" = "yes" ; then \ pandoc --template doc/ooxml-default.html -f markdown -t html doc/ooxml.md \ --css tcl-docs.css -o doc/ooxml.html;\ fi doc/ooxml.n: doc/ooxml.md @if test "${HAVE_PANDOC}" = "yes" ; then \ pandoc --standalone -f markdown -t man doc/ooxml.md -o doc/ooxml.n ;\ fi doc/ooxml-docx.html: doc/ooxml-docx.md @if test "${HAVE_PANDOC}" = "yes" ; then \ pandoc --template doc/ooxml-default.html -f markdown -t html doc/ooxml-docx.md \ --css tcl-docs.css -o doc/ooxml-docx.html;\ fi doc/ooxml-docx.n: doc/ooxml-docx.md @if test "${HAVE_PANDOC}" = "yes" ; then \ pandoc --standalone -f markdown -t man doc/ooxml-docx.md \ -o doc/ooxml-docx.n ;\ fi doc: havepandoc doc/ooxml.html doc/ooxml.n doc/ooxml-docx.html doc/ooxml-docx.n all: havepandoc manifest.txt doc/ooxml.html doc/ooxml.n install: all $(TCLSH) `echo $(srcdir)/helper.tcl` cp $(PKG_TCL_SOURCES) pkgIndex.tcl $(pkglibdir) test: $(TCLSH) `echo $(srcdir)/tests/all.tcl` $(TESTFLAGS) \ -load "package ifneeded ${PACKAGE_NAME} ${PACKAGE_VERSION} [list source [file join `echo $(srcdir)` $(PACKAGE_NAME).tcl]]" archive: manifest.txt pkgIndex.tcl sh tools/archive.sh ooxml 1.13.1 $(PKG_TCL_SOURCES) release: archive @echo "" @echo "Release packages for $(PACKAGE_NAME) $(PACKAGE_VERSION) created in uv/:" @ls -l uv/$(PACKAGE_NAME)$(PACKAGE_VERSION)*.zip uv/$(PACKAGE_NAME)$(PACKAGE_VERSION)*.tar.gz @echo "Publish them with: make publish" publish: fossil uv add uv/$(PACKAGE_NAME)$(PACKAGE_VERSION).zip --as $(PACKAGE_NAME)$(PACKAGE_VERSION).zip fossil uv add uv/$(PACKAGE_NAME)$(PACKAGE_VERSION).tar.gz --as $(PACKAGE_NAME)$(PACKAGE_VERSION).tar.gz fossil uv add uv/$(PACKAGE_NAME)$(PACKAGE_VERSION)-src.tar.gz --as $(PACKAGE_NAME)$(PACKAGE_VERSION)-src.tar.gz fossil uv add uv/download.html --as download.html fossil uv sync fossil uv list clean: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) -rm -rf doc/ooxml.html doc/ooxml.n doc/ooxml-docx.html doc/ooxml-docx.n distclean: clean -rm -f $(CONFIG_CLEAN_FILES) -rm -rf autom4te.cache -rm -f config.cache config.log config.status .PHONY: install test archive release publish clean distclean ooxml/claude/000775 000765 000024 00000000000 15172101247 013547 5ustar00alexstaff000000 000000 ooxml/manifest000644 000765 000024 00000031662 15221665317 014061 0ustar00alexstaff000000 000000 C Version-1.13.1 D 2026-07-03T07:54:55.352 F .fossil-settings/ignore-glob 33bdb1e9e22c8e4d0253b2e6938a216b0538178bb8df9046e0e4c9f2f12ca303 F .fossil-settings/manifest 4598ba9e1e19cdadf19aa4881b2cb5a74fe4813ceea9bfe7e2fe382904cd14fe F .fossil-settings/manifest.no-warn a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a F .gitattributes 9973c70e220d7b30212ae7a21a18d04f7af8d2e7446359c6b5a0ded1a1c7d502 F Makefile.in 8d5e0e0dca70333286cf5135a558435700773e1a9b9470fd7a740cdbfeb2fe34 F README e4bda99e7ad19b37f7be2402050a1973fd19bb098ab03e9986468feb99ca83cd F aclocal.m4 f416a9740ff524cbf7b8eaee5298836b095a4c34d9910d3d7d988ddd776e1d27 F claude/skills/ooxml/SKILL.md d8cdc8c3ed0b27ed2832ea56b5458b34795ee4278183ffd91c277da5530da11c F configure 43e63ff6073bba8264511c4b957082adc0d6efd47852b12233356888104957d2 x F configure.ac 4d18ef67705abf68e6d02483e830dbeeb6611b813020cec597d7b1a74f9276b6 F doc/main.css 4b090f665ce2463a4213fe7625caf13d671674e985fafa06fd7bf41cd5d92cbb F doc/ooxml-default.html 501e4a9e055ec2eba462c40b5882dfbd6b84a636938036898ff968a4c2381cca F doc/ooxml-docx-dev.md 456ae2a9c147597f7e0962b0ee15aa285093f111b870064faec31cecb54c5124 F doc/ooxml-docx.md 26e71811ce4a2c202ab4dd296736ed3e980aa44e9fe97653986a13289be475bc F doc/ooxml.md a2aa5347450770305908c564ef5a8d425b6562bee35b3f49da8bdc60a4407640 F doc/tcl-docs.css 1864d346150f579ea5d9efaa9ca83c2078c8ed696c494f37e9f122d5f1d4350f F docxtest.tcl d55c5fbee8d7e3d7fcb7193578abf8d554c99f87c2d3eabc2d94b61856636f38 F examples/array.tcl 604dc1907b39797a2fa0d065f44b7923cb48af2fff4ce99bda6cd717af94ddbb F examples/bench.tcl 9b53b74d06da7d4033374941c1fe66b2f341b4e94e60c7177564921deb619c9e F examples/book.jpg 89003dbedbef8431de9047390a7a04856029dedaee02ebc2c0ee2472462e8581 F examples/docx-example1.tcl 05f157e48530681667d04cc8384c8513cfb78fc4a45c389c4372ecb7c1fdc395 x F examples/docx-example10.tcl 674ffd8d66cf56f8213260eb1e3c9dd4fec537f7b143880e27a01f88e569cbac x F examples/docx-example11.tcl 69f1f3504305e2660dd275d05780a272d3150a984f627b6a6d1a49cb264e6bcf x F examples/docx-example12.tcl 0b84f51a3a190b52594c814af4d279b20251f9d3af655a7cfa5bd64ea6819d8c x F examples/docx-example2.tcl 3da5eaa318efd90db0b151f1954bfbcc95879de134772ff567fb86b73629fa0b x F examples/docx-example3.tcl 94fe90025a8fa7a96fe782d048094daa508ce963de8013358f3d743fd967e4f2 x F examples/docx-example4-in.docx 3ae216f142325eca22df5a5a624451e39e20005b06d3fcdaca8419b977e599e5 F examples/docx-example4.tcl 51b9a0bddda7f4a3bd20047408723885e326338ea5897ec493942d1cf7d83653 x F examples/docx-example5.tcl b40f8bd8cb56a51d422fa474474017a9767b64afe4674c18cd6b3965d828216d x F examples/docx-example6.tcl af223157c37d04383f5cca5ca77730a736516e64e5c54e46e1c345904d94c1a0 x F examples/docx-example7.tcl 319abf289e2a7f39fae3d82f9bde8f290e5d7ac6b5c7bc5c637a9ff9e84595ce x F examples/docx-example8.tcl c04d6fd24f5639385da9416807a0677243b8565ffb367d5f197326618373c8ea x F examples/docx-example9.tcl ab3cf2b5c88c3f19ac864738ce358891f3a5bc877fb833248b854a811fc5e5b7 x F examples/form8.xlsx a95d57f14fbd46188dbe504e025914b14a2118a303e2cd952e85a7d3a807e4f1 F examples/original_excel.xlsx e560157e92837ef3b6be15e730b344117fd46acae74f16881d42c60538bfc964 F examples/strings.tcl 67b1f274ec9e7d3734ffe27deeb33552784f617e5cded0155d9273a1f5f7b0f3 F examples/xlsx-aLotOfFormats.tcl fd3b2750163a62752416f8fc5123cd42d52d1c43b25178384bdea18e6fc345b1 x F examples/xlsx-complexReadWrite.tcl 8deb193d195deb0c5456dbabe5b5b01fea1cf752ebc09031745733e01f93e633 x F examples/xlsx-defaultDateStyle.tcl cb70a3b8962a0ec8c382bd76c8bb2eff2a43ff11d7fb076c356618222bf3c1b8 x F examples/xlsx-formula.tcl 38991099460e1398859765d2746a9afde37711349c059a40d6b6482b4a7856a8 x F examples/xlsx-hyperlinksTooltips.tcl 9aa020ff3df24c26f9055418eb98a55d6d0bd832763d2d6728f7a77d6c22eaad x F examples/xlsx-printArea.tcl af29f66d4308c8b43ec0eff5b5951ae3cc2144ba024c252331e70a6042c061cd x F examples/xlsx-searchAndReplace.tcl 47c2951e84812564cb7fc9ab79bc91a62c24f7a45077be172e2e1bac9dd55b9f x F examples/xlsx-tablelist.tcl f44af307e1e0695de63a3bfd068f5a4ed41ba3846cb3294098d86e8d266c93b9 x F examples/xlsx-writeRowsAutoIncr.tcl 6d6e067804218cbfa2e560aef0a1f3cd0df2b39d0ef2116fe974097bbf2ae82a x F examples/xlsx-writeRowsIndex.tcl 6573bf42eb166f1049a8bece29398c5210a3e3d164854b158e6e94960caf057c x F helper.tcl 8c40832a9aed4ab56d777dca4aa242d36efd338a6d285650d2c6cb702e95fbf0 x F license.terms b6f4565b9a907e09f40eeee91b6fd3cddf8923a2c43926323c2858fa274d11b6 F ooxml-docx-lib.tcl 27d46e7d6f53f7026a748f9efff2d03cb0e6fe4f8fc1829556db9a9601fd2738 F ooxml-docx-math.tcl c1eccd73c7cd71c1e800fd09caf0ab14067ea58be69687909c13c543e53c26c8 F ooxml-docx.tcl 9a299972cbc0f225634f4f90e85c9fa8cc812146039b9fd6842d9c637024d224 F ooxml.code-workspace d7e95db5f18683291a3c38296e5e1926aa4011244e2c953ea81f86c702cf821a F ooxml.tcl bd7e4ac9d18ced3a96f4effdd1efe95e9d147ac2affc40d70818e3a98c96ddcd F pkgIndex.tcl.in c2fdcf3bca389bef6d9c349842f102ce228a17703dbf9691001815f7e555c43f F tclconfig/ChangeLog 5afc872331b2b8e3ecfdbd0e8222da460b071c2f815080e47e0a1f6c49843a7f F tclconfig/README.txt 8285d9bad9933ad1ca9fd89398e7f22bea1b96dc68fb3d1536d0b3922725b21d F tclconfig/install-sh d5e7acec82cb30a616dc8023b6d77abf3e7109f86175f47741afe89b34d1d4f8 x F tclconfig/tcl.m4 24841be70516af95124d989e9b9a9fb07879fdc9cf2248c4ce6fc7aa3a5ae72b F tests/all.tcl 5844719246237ec493efdaa4b73f0f2493b6dec2b08f584694d8205bd3ef612f F tests/docx-basic.test ff84c68e247c6048d1ea146d77abd8a0de7da8646641e5046ebbbcd52dcda362 F tests/docx-comments.test fec68bafcf684ccaf95beacfe3cbd24e7326929553f2b7f6b3feeb1d0df9e7e0 F tests/docx-ecma.test 289c7986329f638556fef17c53c41d5492bcce04822f2f03fc57393e0682e3b0 F tests/docx-features.test 1751d50ba71da756a6b8a034054578b8a7891495d93db245c2420587aa0af9a8 F tests/docx-headerfooter.test 2f928dd0a9ddbbd3044c999b04cc3c139041fc54c4e60a55d6cc2561bc27edc2 F tests/docx-import.test 1ec47229d585680da2e8d2552d91530043360892a797bacd758eac0bc411736c F tests/docx-lib.test 7eecff2bfda3d4a1c91eaaf4e3947bdb789729012dae7cd8e9c5f40ed1583fb2 F tests/docx-math.test ce8b608d25b7bb915c7c13c3ffb93caf60e1ba4c1918f20cb9fdcec0421cbbb2 F tests/docx-media.test 53502d3062ebf5ba5490ba2369190a688cd88a4bc68bc07639f1402dea791fca F tests/docx-misc.test 50f47b566380cbda7fdd5bd1fc6de43c39dc0c03ac11ad9c96a9b98620136fec F tests/docx-notes.test dd453b7049130a511e41823817b8be0191e660d8f637531d61305eaea2d83b79 F tests/docx-pkg.test b15bd521ea6583f1a94fcaaa9151d282414f89689d3ac7ba480712f51c4076db F tests/docx-reg.test 63e4f5526ba4118ed027aababc546600bcc46d8dc31f3bd00f532d693ebb0206 F tests/docx-settings.test 3424d30c8d565bba4b6e731ca9e26a99e712cf5ef62e7d2d2084670d5a941730 F tests/docx-style.test 85bbf9dc14f051608d57d7cd481edf5aa469b94917ab42570136a82df6f86a5c F tests/docx-tables.test 6b19cf08da444b765b733a5f674a89130d5f9e43d86e9c2ad922253da1ca5c98 F tests/docx-val.test 31a1cec94b384be18da568d72e65be456e29f8423703862b468d67d8b703a7d1 F tests/docx-write.test 37ee5b12e64b3b255eb466790ae33d4780f2a70e2a64b85263779b1d5d43beb1 F tests/docx.test b2527c0ab13bdd7ffee83fb937a134982d91b3f2b84bc3defcec01cf1d350023 F tests/docx_helpers.tcl 4aecbbdafd8249f7ab850411e93b36da949407e1b575184c15a1f75d000261b6 F tests/ecma376/RULES.txt 79610fa032ab1ffcda5df871d3e3adc674f9c8bc5a38ccb1915814bede07c69f F tests/ecma376/schema-data.tcl 6541b42eb71635234c663bb682d62b7609387d3335c52e6d3f55cc8cd7b1c248 F tests/ecma376/shared-commonSimpleTypes.rnc 0740d07ccef634ac30d499cd06003bbf53d572b7555c7ee358357a3f05b598fc F tests/ecma376/validate.tcl 9fb0830c7daaf847dc712dacd597075ff1c6643f9f21a191f54e626dfe019a37 F tests/ecma376/wml.rnc 3d3a9b90340e555ac35f5aac3406f4dbe8c8cde51f1bb399d62c0b28853ba7e0 F tests/test_sheet1_xml_missing.xlsx 52d9c760f650bc518388b7982ff875cdff401001fd0a7f7ee1813499ab8861f8 F tests/test_sheet1_xml_no_utf8.xlsx 72b45333998f053a4e5de86408727b76836389550876be819b49ce811faebb9a F tests/test_sheet1_xml_no_xml.xlsx 016667d0ed9266be829dea35b8d8c38dea973a552380c333126a6c4c69978c02 F tests/test_worksheets_xml_missing.xlsx 1ab0ee8183d26ee9a24ff3928d0dcae38dcb12397205c8a6660d97b755cbbdd2 F tests/xlsx-benchmark.test 34df7f786ddac47fc5702ef4206cb5c56f124c4099db5e22ca35e006fb2f889d F tests/xlsx-bigpart.test 72029bfaead7145f7ad60d0f1e8a8ff05e3b5091d9286cb1e13b14ab041664d1 F tests/xlsx-formatcell.test d2bf52f15e81a84046970933a41f1c05073f35e65e89682f67d2eacde18e88ea F tests/xlsx-formula.test 8f5624d8f324bb9c26040373a201bbcb9d2565c0734c32c7c77142b4c75ce7a8 F tests/xlsx-misc.test 43ef59a4de4bcc03e717470adc3d570ae74d466c7ae156ee3d6da039c711d2ce F tests/xlsx-namedfmts.test a256cebeef32996f0280a3071b941a961d7dbca9e709945394b4edd448655c47 F tests/xlsx-printarea.test b786b6320be430c00225650963596bee80b66e0fcf968d261d9283fefe8648c8 F tests/xlsx-readerror.test 28d07b6f22f1ac0d9fdd4bdcfc9161afd716d87f5e0a62a76403de3d36577e5c F tests/xlsx-simple.test 88cd5283edd5564ff0c5f41104f463267171c188f273e9b210f3a533649daf15 F tests/xlsx-view.test 604e4cbee249e582d4f7335c8268e382f186a09fcd0cc32faa7ba769a20d13fd F tools/BUILD-PACKAGE.md bc872ea7feb65e9bd7646ebdaba4672ab6ce5c5ab49ae12e33904d24098ad72b F tools/archive.sh 6a12348fecee9545a649666821da016bb47b503e633605d902daa5dbfcc09a33 x F tools/createTypeCode.tcl 1ac80b06e3269290f05065e055c1a449bcb177dbf6c1acec21331a0461faba06 x F tools/debugging/builddiff.sh 109cbd277e478cb6949d41fbe644d72637f308f3ba665210dbcd648a3e43d476 F tools/demo.xml 55f59231394d7d3ea6cbed36c1d6765b64df98bc7b8089c3c569fdd0331dfb91 F tools/gendoc.tcl 23d9305b8730e37bbe3905b8679d9af1b363aabaf1ee16342cce227f3d13d359 x F tools/getlanguageinfo.tcl fa7c5c6295d44f20cc34390579fcd8547bba2bc809d0d7d31e99261414d4d501 F tools/languages/Bok1-norwegisch-no.xlsx afe817c2fd69739c755ec7f7f86defa3c7582de78b42739a0465db27138bcff3 F tools/languages/Bok1-schwedisch-sv.xlsx 126c011b6c96207c71514dc12b35449a81b992fc16d821ef0ba05aecb3e4329a F tools/languages/Book1-englisch-en.xlsx aadb8847997ab6a359e98427044dfe4511d5e735592340a4cb6fdfaf1894fa0a F tools/languages/Book1-japanisch-ja.xlsx 0eef3e6a3f1b9975983d8066cf365d02ca48e59a6c52eb3879fcedec8654ecc2 F tools/languages/Cartel1-italienisch-it.xlsx 7c164e528497101f972a0230801f8f3794f2210d5f7552d304605223d3a9f4b9 F tools/languages/Classeur1-französisch-fr.xlsx 9c310df9d5937ad7fc66103b152fed0bce6ee54f058d53adc9fdbd2b143c2835 F tools/languages/Kitap1-türkisch-tr.xlsx fe325531bac506c95a9095170e53386d6c218a87c0db92b86f55b4e8a7dbadbc F tools/languages/Libro1-spanisch-es.xlsx 7893dfd6f93ef6ea4f008991a3a5031a8610a7a652fd365d53ecc97e54db1940 F tools/languages/Livro1-portugiesisch-pt.xlsx d893dd77991dae287db2fbde7d8d50ff605e6d4bff363077e2471d1a08618c08 F tools/languages/Map1-niederländisch-nl.xlsx 53c9754959604d0ebd9170aef7d38a3c512ac3698a5d76e05a2e8933ca2ca976 F tools/languages/Mappe1-deutsch-de.xlsx 460bba60b3dee7283d42c86e2ef766214b8240a9813e93a4d90df61f3600ac2f F tools/languages/Mappe1-dänisch-da.xlsx 125a4c41cbd73043dda0468d4e911a5b59622db61b35ef8b7b5bedf43db10c5a F tools/languages/Munkafüzet1-ungarisch-hu.xlsx 0fec7892820caddac31b664c75782ac7714ae5d8e3382d8e9317cc4216036cf3 F tools/languages/Sešit1-tschechisch-cs.xlsx c8df343b8cde906368af69011790fd9c20a542748d8d43e8197db4a63c7bf005 F tools/languages/Skoroszyt1-polnisch-pl.xlsx d961f87b46c461589f758f8ab9ddb7551bda7713bb3f841f6fd8f3c23c4ef4a5 F tools/languages/Työkirja1-finnisch-fi.xlsx 420b5c2bccc963cc99ec398850a1a872035459ea32b05fe08d3e6fae030564b9 F tools/languages/Zošit1-slowakisch-sl.xlsx ef7220fb07dad29c2b10143a3e6e17bb7a46dff2735291fdc701a0d401c94280 F tools/languages/Βιβλίο1-griechisch-el.xlsx ac7a21f28d57c47831cfddea1410951fa7c6dbb76442c497608f107c883a224b F tools/languages/Книга1-russisch-ru.xlsx 1c0a36d04967c5fd9e59f061c1bacf84dcdc54ef59436b50585947dfe58c49af F tools/languages/חוברת1-hebräisch-he.xlsx b5aee43e401ad6f4a891cc2a57dea582011610495d6900f4f225898ba1453111 F tools/languages/الكتاب1-arabisch-ar.xlsx 9c716332082f7ed01a817a1c6bc0101a3943b5feba84b470c68768a909247d47 F tools/languages/สมุดงาน1-thailändisch-th.xlsx 62fbf07dc72e7afcaca345f9121b79cccbc83a91564d05ac7a58f41d66dbd36c F tools/languages/工作簿1-chinesisch-zh.xlsx ffecda35303c5ebcd3fe8debb0e5da2226624bb3101c1d8d596d6425bb7de93e F tools/languages/통합\s문서1-koreanisch-ko.xlsx 6bfc4d052b7fc16445c92809b5fdfabb02ee331d2d2b60f8e34192eaf320d38a F tools/mkversion.c 6bd67f53bfadf182e380ad077fc3e2c8a101d4080a891449e10a9b7e43e3956b F tools/mkversion.tcl 79af84aa1e11456632dfb9527293bff4f9038693a7f8ce4e1dd35cabd00122e2 F tools/pp.tcl 86d75bd2f3ce7c814112b11831a8c4c28eed9114e30399548227182104963893 F tools/re.tcl 9528bd8702643a34e95da285e2370ac8c37c93024c29d336c469240f78e7997a F tools/xmltotdom.tcl 2f99796ee54518a1166e216e976e6b63ccd8a38773bf5e6821bcdd4a393960b8 x F tools/xmltotdomnodecmd.tcl 4fcd7f81e031596d3eb380cb0c95b003457d70f10c688d4b2875ba602ed690ba x F uv/min-download.html 3f433be823b4caea9f81be7d618eaa05585b30129af73b728497bca29ccee847 F uv/template-download.html e2d57ca4804a4e02a688779f9b1e4a1bebe865de508e45f68fff773a52341728 P 6eda274d5f641b908fd85ddbdde1738d34f5d478a9443359d8c43f68d1441631 R fbdf2cbda53c33b9e3254eb84df2c261 T +bgcolor * #fea5f4 T +sym-release * T +sym-version-1.13.1 * U alex Z 3efe4712538c778f164928193ba5f82f # Remove this line to create a well-formed Fossil manifest. ooxml/helper.tcl000755 000765 000024 00000000643 14764622263 014315 0ustar00alexstaff000000 000000 #!/bin/sh #\ exec tclsh "$0" "$@" # Copyright (C) 2019 Alexander Schoepe, Bochum, DE package require Tcl 8.6- switch -- [set cmd [lindex $argv 0]] { cp { set src [lrange $argv 1 end-1] set dst [lindex $argv end] if {![file exists $dst]} { file mkdir $dst } if {[file exists $dst] && [file isdirectory $dst]} { file copy -force -- {*}$src $dst } } default { exit 1 } } ooxml/tests/000755 000765 000024 00000000000 15221664315 013457 5ustar00alexstaff000000 000000 ooxml/license.terms000644 000765 000024 00000003314 14764622263 015023 0ustar00alexstaff000000 000000 ooxml - ECMA-376 Office Open XML File Formats BSD-3 Copyright (C) 2018-2024 Alexander Schoepe, Bochum, DE, Copyright (C) 2019-2024 Rolf Ade, DE, Copyright (C) 2023-2024 Harald Oehmann, 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. ooxml/README000644 000765 000024 00000005413 15221552672 013202 0ustar00alexstaff000000 000000 ooxml ECMA-376 Office Open XML File Formats This directory contains a freely distributable pure tcl extension called ooxml. SYNOPSIS Read and write Office Open XML "XLSX" spreadsheets (since Excel 2007) and create Office Open XML "DOCX" word processing documents. Spreadsheets (package ooxml) This package contains several commands to edit Excel files. The three most important are the following three: Import Excel files into a Tcl array with ::ooxml::xl_read, export Tcl data to an Excel file with ::ooxml::xl_write and export a Tcl tablelist to an Excel file with ::ooxml::tablelist_to_xl. Word processing documents (package ooxml::docx) Create ECMA-376 WordprocessingML documents readable by Microsoft Word and LibreOffice. Documents are built from scratch or from an existing .docx template with ::ooxml::docx::docx. The objects have methods to add and style paragraphs, tables, images, headers and footers, footnotes, comments, fields, hyperlinks, lists, textboxes and math formulas (OMML). For information on how to use these commands, see the examples and the man-pages at https://fossil.sowaswie.de/ooxml. DEPENDENCIES Tcl >= 8.6.7 tdom >= 0.9.0 (the docx writer requires tdom >= 0.9.6) Reading xlsx and docx files uses the zlib command built into Tcl and needs no additional package. Optional fallback backends for archives the built-in reader cannot handle: Tcl 9 zipfs, tcllib zipfile::decode or tclvfs vfs::zip >= 1.0.4. GETTING THE CODE The development repository is hosted at https://fossil.sowaswie.de/ooxml You are encouraged to use trunk. INSTALLING Simply extract the download ooxml-.zip into your Tcl library path. Since ooxml is TEA-compatible you should be able to do ./configure make test make install By default this installs into the lib directory of the Tcl installation found by configure (use --with-tcl to point it to the tclConfig.sh of another Tcl), so that this tclsh finds the package on its auto_path. To install into a different location use ./configure --prefix /path/to/tree which installs the package into /path/to/tree/lib/ooxml. REPORTING BUGS Please head to https://fossil.sowaswie.de/ooxml/ticket and click on "New Ticket". Log in as anonymous and report your findings. If you prefer to have an individual login write Alex a mail. HISTORY ooxml was started by Alexander Schoepe (fossil@sowaswie.de) and improved with contributions by Rolf Ade (rolf@pointsman.de), Harald Oehlmann and Miguel Bañón. The docx subsystem was developed by Rolf Ade with contributions by Miguel Bañón. ooxml/pkgIndex.tcl000644 000765 000024 00000000413 15221665131 014565 0ustar00alexstaff000000 000000 # # Tcl package index file # package ifneeded ooxml 1.13.1 [list source [file join $dir ooxml.tcl]] package ifneeded ooxml::docx 0.6 [list source [file join $dir ooxml-docx.tcl]] package ifneeded ooxml::docx::lib 0.6 [list source [file join $dir ooxml-docx-lib.tcl]] ooxml/docxtest_tmp/000755 000765 000024 00000000000 15221665127 015034 5ustar00alexstaff000000 000000 ooxml/examples/000755 000765 000024 00000000000 15217572310 014131 5ustar00alexstaff000000 000000 ooxml/ooxml-docx-math.tcl000664 000765 000024 00000071426 15213015413 016043 0ustar00alexstaff000000 000000 # # ooxml ECMA-376 Office Open XML File Formats # https://www.ecma-international.org/publications/standards/Ecma-376.htm # # Copyright (C) 2025 Rolf Ade, DE # Copyright (C) 2025, 2026 Miguel Bañón # 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. # namespace eval ::ooxml::docx { # ── Fraction properties ────────────────────────────────────────── set properties(fPr) { -type {m:type ST_FType} } # ── Math run properties ────────────────────────────────────────── set properties(mrun1) { -lit {m:lit CT_OnOff} | { { -scr {m:scr ST_MScript} -sty {m:sty ST_MathStyle} } { -nor {m:nor CT_OnOff} } } } set properties(mrun2) { -aln {m:aln CT_OnOff} } # ── N-ary operator properties ──────────────────────────────────── set properties(naryPr) { -char {m:chr NoCheck} -limLoc {m:limLoc ST_LimLoc} -grow {m:grow CT_OnOff} -subHide {m:subHide CT_OnOff} -supHide {m:supHide CT_OnOff} } # ── Accent properties (Phase 1) ───────────────────────────────── set properties(accPr) { -char {m:chr NoCheck} } # ── Bar properties (Phase 1) ───────────────────────────────────── set properties(barPr) { -pos {m:pos ST_TopBot} } # ── Delimiter properties (Phase 1) ─────────────────────────────── set properties(dPr) { -begChr {m:begChr NoCheck} -endChr {m:endChr NoCheck} -sepChr {m:sepChr NoCheck} -grow {m:grow CT_OnOff} -shp {m:shp ST_Shp} } # ── Grouping character properties (Phase 1) ────────────────────── set properties(groupChrPr) { -char {m:chr NoCheck} -pos {m:pos ST_TopBot} -vertJc {m:vertJc ST_TopBot} } # ── Matrix column properties (Phase 1) ─────────────────────────── set properties(mcPr) { -count {m:count ST_Integer255} -mcJc {m:mcJc ST_McJc} } # ── Tag registration ───────────────────────────────────────────── # Original tags foreach tag { m:acc m:accPr m:aln m:bar m:barPr m:baseJc m:begChr m:brk m:chr m:count m:d m:dPr m:deg m:degHide m:den m:e m:endChr m:f m:fName m:fPr m:func m:groupChr m:groupChrPr m:grow m:jc m:lim m:limLoc m:limLow m:limUpp m:lit m:m m:mPr m:mc m:mcJc m:mcPr m:mcs m:mr m:nary m:naryPr m:nor m:num m:oMath m:oMathPara m:oMathParaPr m:pos m:r m:rPr m:rad m:radPr m:sSub m:sSubSup m:sSup m:scr m:sepChr m:shp m:sty m:sub m:subHide m:sup m:supHide m:t m:type m:vertJc } { dom createNodeCmd -tagName $tag -namespace $xmlns(m) elementNode Tag_$tag } } # OMML related methods, the initial code contributed by Miguel Bañón oo::define ooxml::docx::docx { # Guard: math sub-methods must be called from within a math zone method RequireMathZone {} { my variable inMathZone set methodName [lindex [info level [expr {[info level] - 1}]] 1] if {![info exists inMathZone] || !$inMathZone} { error "$methodName must be called from within a math zone\ (inside the script argument of the math method)" } } method EvalChildScript {tag script} { my variable body set savedbody $body Tag_$tag { set body [dom fromScriptContext] if {$script ne "" && [catch {uplevel 2 [list eval $script]} errMsg]} { set body $savedbody error $errMsg } } set body $savedbody } method Mt {text} { set atts "" if {[string index $text 0] eq " " || [string index $text end] eq " "} { lappend atts xml:space preserve } Tag_m:t $atts { Text [dom clearString -replace $text] } } # Inline or display math zone. # doc math { ...OMML... } ;# inline (m:oMath) in current paragraph # doc math -display 1 { ...OMML... } ;# display (m:oMathPara/m:oMath) on its own paragraph # Options: # -display CT_OnOff (default off) # -jc ST_MJc (left|center|right|centerGroup) - only used for display method math {args} { my variable body my variable valPrefix my variable inMathZone set savedValPrefix $valPrefix set savedInMathZone [expr {[info exists inMathZone] && $inMathZone}] set valPrefix m set inMathZone 1 if {[catch { set script [lindex $args end] OptVal [lrange $args 0 end-1] "math" "script" set display [my EatOption -display CT_OnOff] ;# "1" or "0" set jc [my EatOption -jc ST_MJc] ;# left|center|right|centerGroup my CheckRemainingOpts if {$display eq "1"} { $body appendFromScript { Tag_w:p { Tag_m:oMathPara { if {$jc ne ""} { Tag_m:oMathParaPr { Tag_m:jc m:val $jc } } my EvalChildScript m:oMath $script } } } } else { # Inline math inside current paragraph; create one if needed [my LastParagraph 1] appendFromScript { my EvalChildScript m:oMath $script } } } errMsg]} { set valPrefix $savedValPrefix set inMathZone $savedInMathZone return -code error $errMsg } set valPrefix $savedValPrefix set inMathZone $savedInMathZone } # ────────────────────────────────────────────────────────────────── # Accent: # base # # Puts an accent (hat, tilde, dot, arrow, …) above the base. # The default accent character (when -char is omitted) is the # combining circumflex accent (U+0302), per ECMA-376 §22.1.2.1. # # Usage: # $doc maccent { $doc mrun "x" } ;# x-hat (default) # $doc maccent -char "\u0303" { $doc mrun "x" } ;# x-tilde # $doc maccent -char "\u0307" { $doc mrun "x" } ;# x-dot # $doc maccent -char "\u20D7" { $doc mrun "v" } ;# vector arrow # ────────────────────────────────────────────────────────────────── method maccent {args} { my variable body variable ::ooxml::docx::properties if {[catch { my RequireMathZone OptVal [lrange $args 0 end-1] "" "baseScript" set baseScript [lindex $args end] $body appendFromScript { Tag_m:acc { Tag_m:accPr { my Create $properties(accPr) } my EvalChildScript m:e $baseScript } } my CheckRemainingOpts } errMsg]} { return -code error $errMsg } } # ────────────────────────────────────────────────────────────────── # Bar (overline / underline): # # base # # Default position is "top" (overline) per ECMA-376 §22.1.2.7. # # Usage: # $doc mbar { $doc mrun "x" } ;# overline (default) # $doc mbar -pos bot { $doc mrun "x" } ;# underline # ────────────────────────────────────────────────────────────────── method mbar {args} { my variable body variable ::ooxml::docx::properties if {[catch { my RequireMathZone OptVal [lrange $args 0 end-1] "" "baseScript" set baseScript [lindex $args end] $body appendFromScript { Tag_m:bar { Tag_m:barPr { my Create $properties(barPr) } my EvalChildScript m:e $baseScript } } my CheckRemainingOpts } errMsg]} { return -code error $errMsg } } # ────────────────────────────────────────────────────────────────── # Delimiter: # Wraps one or more sub-expressions in matching delimiters # (parentheses, brackets, braces, |·|, ‖·‖, ⌊·⌋, etc.) # # The default delimiters are parentheses "(" and ")" per # ECMA-376 §22.1.2.24. For a single argument, the script body # creates content directly. For multiple arguments separated # by the separator character, use mdelimarg to wrap each one # in its own m:e child. # # Options: # -begChr string opening delimiter (default "(") # -endChr string closing delimiter (default ")") # -sepChr string separator between arguments (default "|") # -grow CT_OnOff delimiters grow to match content height # -shp ST_Shp centered or match # # Usage: # # Simple parentheses: (x+1) # $doc mdelim { $doc mrun "x+1" } # # # Brackets: [a, b] # $doc mdelim -begChr "\[" -endChr "\]" { # $doc mdelimarg { $doc mrun "a" } # $doc mdelimarg { $doc mrun "b" } # } # # # Absolute value: |x| # $doc mdelim -begChr "|" -endChr "|" { $doc mrun "x" } # # # Braces with grow # $doc mdelim -begChr "\{" -endChr "\}" -grow 1 { # $doc mrun "expr" # } # # # Norm: ‖v‖ # $doc mdelim -begChr "\u2016" -endChr "\u2016" { $doc mrun "v" } # ────────────────────────────────────────────────────────────────── method mdelim {args} { my variable body variable ::ooxml::docx::properties if {[catch { my RequireMathZone OptVal [lrange $args 0 end-1] "" "script" set script [lindex $args end] $body appendFromScript { Tag_m:d { Tag_m:dPr { my Create $properties(dPr) } # Run script at the m:d level so that mdelimarg # creates m:e children directly under m:d. set savedbody $body set dNode [dom fromScriptContext] set body $dNode if {$script ne "" && [catch {uplevel 1 [list eval $script]} errMsg]} { set body $savedbody error $errMsg } set body $savedbody # If user did not use mdelimarg, no m:e exists # yet — wrap all non-dPr children in a single m:e. set hasE 0 foreach child [$dNode childNodes] { if {[$child nodeName] eq "m:e"} { set hasE 1 break } } if {!$hasE} { set loose [list] foreach child [$dNode childNodes] { if {[$child nodeName] ne "m:dPr"} { lappend loose $child } } set ns "http://schemas.openxmlformats.org/officeDocument/2006/math" set eNode [[$dNode ownerDocument] createElementNS $ns "m:e"] $dNode appendChild $eNode foreach child $loose { $eNode appendChild $child } } } } my CheckRemainingOpts } errMsg]} { return -code error $errMsg } } # Helper: creates a delimiter argument (m:e) inside mdelim. # Each call wraps its script in an child of the # enclosing . # # For multi-argument delimiters the main mdelim script should # consist solely of mdelimarg calls: # # $doc mdelim -sepChr "," { # $doc mdelimarg { $doc mrun "a" } # $doc mdelimarg { $doc mrun "b" } # $doc mdelimarg { $doc mrun "c" } # } method mdelimarg {script} { my variable body if {[catch { my RequireMathZone $body appendFromScript { my EvalChildScript m:e $script } } errMsg]} { return -code error $errMsg } } # Fraction: with optional # Usage: doc mfrac { ...numerator... } { ...denominator... } ?-type bar|lin|noBar|skw? method mfrac {args} { my variable body variable ::ooxml::docx::properties if {[catch { my RequireMathZone OptVal [lrange $args 0 end-2] "" "numScript denScript" set numScript [lindex $args end-1] set denScript [lindex $args end] $body appendFromScript { Tag_m:f { Tag_m:fPr { my Create $properties(fPr) } my EvalChildScript m:num $numScript my EvalChildScript m:den $denScript } } my CheckRemainingOpts } errMsg]} { return -code error $errMsg } } # ────────────────────────────────────────────────────────────────── # Grouping character (underbrace / overbrace with label): # # base # # The default character is U+23DF (bottom curly bracket ⏟) per # ECMA-376 §22.1.2.41, positioned at the bottom with the label # above. # # Options: # -char string grouping character (default ⏟) # -pos ST_TopBot position of the character (top|bot, default bot) # -vertJc ST_TopBot vertical justification of the base relative # to the grouping character (top|bot) # # Usage: # # Underbrace (default) # $doc mgroupchr { $doc mrun "a+b+c" } # # # Overbrace # $doc mgroupchr -char "\u23DE" -pos top -vertJc bot { # $doc mrun "x+y" # } # ────────────────────────────────────────────────────────────────── method mgroupchr {args} { my variable body variable ::ooxml::docx::properties if {[catch { my RequireMathZone OptVal [lrange $args 0 end-1] "" "baseScript" set baseScript [lindex $args end] $body appendFromScript { Tag_m:groupChr { Tag_m:groupChrPr { my Create $properties(groupChrPr) } my EvalChildScript m:e $baseScript } } my CheckRemainingOpts } errMsg]} { return -code error $errMsg } } # Lower limit wrapper: baselow method mlimlow {baseScript lowScript} { if {[catch { my RequireMathZone my variable body $body appendFromScript { Tag_m:limLow { my EvalChildScript m:e $baseScript my EvalChildScript m:lim $lowScript } } } errMsg]} { return -code error $errMsg } } # Upper limit wrapper: baseup method mlimupp {baseScript upScript} { if {[catch { my RequireMathZone my variable body $body appendFromScript { Tag_m:limUpp { my EvalChildScript m:e $baseScript my EvalChildScript m:lim $upScript } } } errMsg]} { return -code error $errMsg } } # ────────────────────────────────────────────────────────────────── # Matrix: # # The matrix body is a list of row scripts. Each row script # creates cells via mmatcell, which wraps content in an . # # Options: # -baseJc ST_BaseJc vertical alignment of the matrix relative to # the math baseline (top|center|bottom) # -mcJc ST_McJc column justification (left|center|right) # -count 0..255 number of adjacent columns sharing the same # justification (default: omitted) # # Usage: # # 2×2 identity matrix # $doc mmatrix { # { # $doc mmatcell { $doc mrun "1" } # $doc mmatcell { $doc mrun "0" } # } # { # $doc mmatcell { $doc mrun "0" } # $doc mmatcell { $doc mrun "1" } # } # } # # # Centered columns # $doc mmatrix -mcJc center { # { $doc mmatcell { $doc mrun "a" } # $doc mmatcell { $doc mrun "b" } } # { $doc mmatcell { $doc mrun "c" } # $doc mmatcell { $doc mrun "d" } } # } # # # Wrap in brackets for a proper matrix notation: [M] # $doc mdelim -begChr "\[" -endChr "\]" { # $doc mmatrix { # { $doc mmatcell { $doc mrun "a" } # $doc mmatcell { $doc mrun "b" } } # { $doc mmatcell { $doc mrun "c" } # $doc mmatcell { $doc mrun "d" } } # } # } # ────────────────────────────────────────────────────────────────── method mmatrix {args} { my variable body variable ::ooxml::docx::properties if {[catch { my RequireMathZone OptVal [lrange $args 0 end-1] "" "rowScripts" set rowScripts [lindex $args end] if {![llength $rowScripts]} { error "mmatrix requires at least one row" } set baseJc [my EatOption -baseJc ST_BaseJc] $body appendFromScript { Tag_m:m { # Matrix properties Tag_m:mPr { if {$baseJc ne ""} { Tag_m:baseJc m:val $baseJc } # Column specification — only emitted if the # user provided -mcJc or -count set hasMcPr 0 foreach {opt _} [array get opts] { if {$opt in {-mcJc -count}} { set hasMcPr 1 break } } if {$hasMcPr} { Tag_m:mcs { Tag_m:mc { Tag_m:mcPr { my Create $properties(mcPr) } } } } } # Rows — each rowScript is evaluated to produce # mmatcell calls that create m:e children of m:mr foreach rowScript $rowScripts { Tag_m:mr { set savedbody $body set body [dom fromScriptContext] if {[catch {uplevel 1 [list eval $rowScript]} errMsg]} { set body $savedbody error $errMsg } set body $savedbody } } } } my CheckRemainingOpts } errMsg]} { return -code error $errMsg } } # Helper: creates a matrix cell (m:e) inside a matrix row (m:mr). method mmatcell {script} { my variable body if {[catch { my RequireMathZone $body appendFromScript { my EvalChildScript m:e $script } } errMsg]} { return -code error $errMsg } } # Function application: namearg method mfunc {nameScript argScript} { my variable body if {[catch { my RequireMathZone $body appendFromScript { Tag_m:func { my EvalChildScript m:fName $nameScript my EvalChildScript m:e $argScript } } } errMsg]} { return -code error $errMsg } } # n-ary operator (sum/product/integral/⋂ etc.) # Usage: # doc mnary { base } -char "∑" -limLoc undOvr -sub { i=1 } -sup { n } -grow 1 -subHide 0 -supHide 0 method mnary {args} { my variable body variable ::ooxml::docx::properties if {[catch { my RequireMathZone OptVal [lrange $args 0 end-1] "" "baseScript" set baseScript [lindex $args end] set subSc [my EatOption -sub NoCheck] set supSc [my EatOption -sup NoCheck] $body appendFromScript { Tag_m:nary { Tag_m:naryPr { my Create $properties(naryPr) } my EvalChildScript m:sub $subSc my EvalChildScript m:sup $supSc my EvalChildScript m:e $baseScript } } my CheckRemainingOpts } errMsg]} { return -code error $errMsg } } # nth-root: n # Per ECMA-376 §22.1.2.88, m:radPr is optional and omitted when # there are no properties to set. method mroot {degreeScript radicandScript} { my variable body if {[catch { my RequireMathZone $body appendFromScript { Tag_m:rad { my EvalChildScript m:deg $degreeScript my EvalChildScript m:e $radicandScript } } } errMsg]} { return -code error $errMsg } } method mrun {args} { variable ::ooxml::docx::properties if {[catch { my RequireMathZone OptVal [lrange $args 0 end-1] "" "text" set text [lindex $args end] set brk [my EatOption -brk CT_OnOff] set brkAt [my EatOption -brkAt ST_Integer255] Tag_m:r { Tag_m:rPr { my Create $properties(mrun1) if {$brk eq "1"} { if {$brkAt ne ""} { Tag_m:brk m:alnAt $brkAt } else { Tag_m:brk } } my Create $properties(mrun2) } my Mt $text } my CheckRemainingOpts } errMsg]} { return -code error $errMsg } } # Subscript: basesub method msub {baseScript subScript} { my variable body if {[catch { my RequireMathZone $body appendFromScript { Tag_m:sSub { my EvalChildScript m:e $baseScript my EvalChildScript m:sub $subScript } } } errMsg]} { return -code error $errMsg } } # Sub+Sup: base method msubsup {baseScript subScript supScript} { my variable body if {[catch { my RequireMathZone $body appendFromScript { Tag_m:sSubSup { my EvalChildScript m:e $baseScript my EvalChildScript m:sub $subScript my EvalChildScript m:sup $supScript } } } errMsg]} { return -code error $errMsg } } # Superscript: basesup method msup {baseScript supScript} { my variable body if {[catch { my RequireMathZone $body appendFromScript { Tag_m:sSup { my EvalChildScript m:e $baseScript my EvalChildScript m:sup $supScript } } } errMsg]} { return -code error $errMsg } } # Square root: # # Per ECMA-376 §22.1.2.89, degHide must be explicitly set and # an empty m:deg element must be present for strict conformance. method msqrt {radicandScript} { my variable body if {[catch { my RequireMathZone $body appendFromScript { Tag_m:rad { Tag_m:radPr { Tag_m:degHide m:val 1 } Tag_m:deg my EvalChildScript m:e $radicandScript } } } errMsg]} { return -code error $errMsg } } } ooxml/doc/000755 000765 000024 00000000000 15221547620 013061 5ustar00alexstaff000000 000000 ooxml/manifest.uuid000644 000765 000024 00000000101 15221665317 015006 0ustar00alexstaff000000 000000 8f9305b374703d5698eca1f89d7ad9a7ec6ed0807da172fd3f11d30a4cdb1190 ooxml/ooxml-docx.tcl000664 000765 000024 00000404260 15217572310 015120 0ustar00alexstaff000000 000000 # # ooxml ECMA-376 Office Open XML File Formats # https://www.ecma-international.org/publications/standards/Ecma-376.htm # # Copyright (C) 2024, 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- package require ooxml source [file join [file dir [info script]] ooxml-docx-lib.tcl] package require ooxml::docx::lib namespace eval ::ooxml::docx { namespace export docx # These are acually used as namespace variables variable prefixnslist variable properties variable staticDocx variable xmlns # These variables are only used in the namespace setup and # defined here only to avoid changes of possibly global variables # with the same name for Tcl < 9.0 # (See https://core.tcl-lang.org/tips/doc/trunk/tip/278.md # "Fix Variable Name Resolution Quirks") variable BorderOpts variable borderOptions variable property variable option variable name variable xml variable tag array set xmlns { a http://schemas.openxmlformats.org/drawingml/2006/main ct http://schemas.openxmlformats.org/package/2006/content-types m http://schemas.openxmlformats.org/officeDocument/2006/math mc http://schemas.openxmlformats.org/markup-compatibility/2006 o urn:schemas-microsoft-com:office:office pic http://schemas.openxmlformats.org/drawingml/2006/picture r http://schemas.openxmlformats.org/officeDocument/2006/relationships rel http://schemas.openxmlformats.org/package/2006/relationships sl http://schemas.openxmlformats.org/schemaLibrary/2006/main v urn:schemas-microsoft-com:vml w http://schemas.openxmlformats.org/wordprocessingml/2006/main w10 urn:schemas-microsoft-com:office:word w14 http://schemas.microsoft.com/office/word/2010/wordml wp http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing wp14 http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing wpg http://schemas.microsoft.com/office/word/2010/wordprocessingGroup wps http://schemas.microsoft.com/office/word/2010/wordprocessingShape } set prefixnslist [array get xmlns] # Most WordprocessingML elements have a sequence content model. So # the basic rule is to keep the order of the options below as is # (and to care that new options are inserted at the right place). # Exceptions are locally noted. set properties(abstractNumStyle) { -numberFormat {w:numFmt ST_NumberFormat} -levelRestart {w:lvlRestart ST_DecimalNumber} -levelText {w:lvlText NoCheck} -align {w:lvlJc ST_Jc} } set properties(cell1) { -cellWidth {w:tcW { type ST_TblWidth {value w} ST_MeasurementOrPercent}} -span {w:gridSpan ST_DecimalNumber} -hspan {w:hMerge ST_Merge} -vspan {w:vMerge ST_Merge} } set properties(cell2) { -shading {w:shd { {type val} {ST_Shd !} color ST_HexColor fill ST_HexColor}} } set properties(cell3) { -textDirection {w:textDirection ST_TextDirection} -tcFitText {w:tcFitText CT_OnOff} -vAlign {w:vAlign ST_VerticalJc} -hideMark {w:hideMark CT_OnOff} } set properties(cellMargins) { -cellMarginTop {w:top { type ST_TblWidth {value w} ST_MeasurementOrPercent}} -cellMarginStart {w:start { type ST_TblWidth {value w} ST_MeasurementOrPercent}} -cellMarginLeft {w:left { type ST_TblWidth {value w} ST_MeasurementOrPercent}} -cellMarginBottom {w:bottom { type ST_TblWidth {value w} ST_MeasurementOrPercent}} -cellMarginEnd {w:end { type ST_TblWidth {value w} ST_MeasurementOrPercent}} -cellMarginRight {w:right { type ST_TblWidth {value w} ST_MeasurementOrPercent}} } set properties(paragraph1) { -pstyle {w:pStyle PStyle} -keepNext {w:keepNext CT_OnOff} -keepLines {w:keepLines CT_OnOff} -pageBreakBefore {w:pageBreakBefore CT_OnOff} -textframe {w:framePr { {width w} ST_TwipsMeasure {height h} ST_TwipsMeasure wrap ST_Wrap vAnchor ST_Anchor hAnchor ST_Anchor xAlign ST_XAlign yAlign ST_YAlign dropCap ST_DropCap lines ST_DecimalNumber vSpace ST_TwipsMeasure hSpace ST_TwipsMeasure hrule ST_HeightRule anchorLock CT_OnOff}} -widowControl {w:widowControl CT_OnOff} +w:numPr { -level {w:ilvl ST_DecimalNumber} -numberingStyle {w:numId ST_DecimalNumber} } -suppressLineNumbers {w:suppressLineNumbers CT_OnOff} } set properties(paragraph2) { -shading {w:shd { {type val} {ST_Shd !} color ST_HexColor fill ST_HexColor}} } set properties(paragraph3) { -bidi {w:bidi CT_OnOff} -spacing {w:spacing { after ST_TwipsMeasure before ST_TwipsMeasure line ST_TwipsMeasure lineRule ST_LineSpacingRule}} -indentation {w:ind { end ST_SignedTwipsMeasure endChars ST_DecimalNumber firstLine ST_SignedTwipsMeasure firstLineChars ST_DecimalNumber hanging ST_SignedTwipsMeasure hangingChars ST_DecimalNumber start ST_SignedTwipsMeasure startChars ST_DecimalNumber}} -align {w:jc ST_Jc} } set properties(row) { -wBefore {w:wBefore { type ST_TblWidth {value w} ST_MeasurementOrPercent}} -wAfter {w:wAfter { type ST_TblWidth {value w} ST_MeasurementOrPercent}} -cantSplit {w:cantSplit CT_OnOff} -rowHeight {w:trHeight { {value val} ST_TwipsMeasure hRule ST_HeightRule}} -headerrow {w:tblHeader CT_OnOff} -cellSpacing {w:tblCellSpacing { type ST_TblWidth {value w} ST_MeasurementOrPercent}} -align {w:jc ST_JcTable} } # According to the specification the children elements of rPr are # in unspecified order. Since Miguel uses an in this case limited # validator which wrongly insists on a certain order we follow # this for now. set properties(run) { -cstyle {w:rStyle RStyle} -font {w:rFonts NoCheck RFonts} -bold {{w:b w:bCs} CT_OnOff} -italic {{w:i w:iCs} CT_OnOff} -strike {w:strike CT_OnOff} -dstrike {w:dstrike CT_OnOff} -emboss {w:emboss CT_OnOff} -noProof {w:noProof CT_OnOff} -color {w:color ST_HexColor} -fontsize {{w:sz w:szCs} ST_HpsMeasure} -highlight {w:highlight ST_HighlightColor} -underline {w:u ST_Underline} -verticalAlign {w:vertAlign ST_VerticalAlignRun} -rtl {w:rtl CT_OnOff} } set properties(sectionsetup1) { +w:footnotePr { -fn_pos {w:pos ST_FtnPos} -fn_numFmt {w:numFmt ST_NumberFormat} -fn_numStart {w:numStart ST_DecimalNumber} -fn_numRestart {w:numRestart ST_RestartNumber} } +w:endnotePr { -en_pos {w:pos ST_EdnPos} -en_numFmt {w:numFmt ST_NumberFormat} -en_numStart {w:numStart ST_DecimalNumber} -en_numRestart {w:numRestart ST_RestartNumber} } -sectionType {w:type ST_SectionMark} -sizeAndOrientation {w:pgSz { {height h} ST_TwipsMeasure {orientation orient} ST_PageOrientation {width w} ST_TwipsMeasure}} -margins {w:pgMar { bottom {ST_TwipsMeasure ! 1134} footer {ST_TwipsMeasure ! 0} gutter {ST_TwipsMeasure ! 0} header {ST_TwipsMeasure ! 0} left {ST_TwipsMeasure ! 1134} right {ST_TwipsMeasure ! 1134} top {ST_TwipsMeasure ! 1134}}} -paperSource {w:paperSrc { first ST_DecimalNumber other ST_DecimalNumber }} } set properties(sectionsetup2) { -pageNumbering {w:pgNumType { chapSep ST_ChapterSep chapStyle ST_DecimalNumber fmt ST_NumberFormat start ST_DecimalNumber }} -vAlign {w:vAlign ST_VerticalJc} -docGrid {w:docGrid { type ST_DocGrid linePitch ST_DecimalNumber charSpace ST_DecimalNumber }} } set properties(settings) { -writeProtection {w:writeProtection { recommended CT_OnOff algorithmName NoCheck hashValue XSD_base64Binary saltValue XSD_base64Binary spinCount ST_DecimalNumber cryptProviderType ST_CryptProv cryptAlgorithmClass ST_AlgClass cryptAlgorithmType ST_AlgType cryptAlgorithmSid ST_DecimalNumber cryptSpinCount ST_DecimalNumber cryptProvider NoCheck algIdExt XSD_hexBinary algIdExtSource NoCheck cryptProviderTypeExt XSD_hexBinary cryptProviderTypeExtSource NoCheck hash XSD_base64Binary salt XSD_base64Binary }} -view {w:view ST_View} -zoom {w:zoom { {type val} ST_Zoom percent ST_DecimalNumberOrPercent }} -removePersonalInformation {w:removePersonalInformation CT_OnOff} -removeDateAndTime {w:removeDateAndTime CT_OnOff} -doNotDisplayPageBoundaries {w:doNotDisplayPageBoundaries CT_OnOff} -displayBackgroundShape {w:displayBackgroundShape CT_OnOff} -printPostScriptOverText {w:printPostScriptOverText CT_OnOff} -printFractionalCharacterWidth {w:printFractionalCharacterWidth CT_OnOff} -printFormsData {w:printFormsData CT_OnOff} -embedTrueTypeFonts {w:embedTrueTypeFonts CT_OnOff} -embedSystemFonts {w:embedSystemFonts CT_OnOff} -saveSubsetFonts {w:saveSubsetFonts CT_OnOff} -saveFormsData {w:saveFormsData CT_OnOff} -mirrorMargins {w:mirrorMargins CT_OnOff} -alignBordersAndEdges {w:alignBordersAndEdges CT_OnOff} -bordersDoNotSurroundHeader {w:bordersDoNotSurroundHeader CT_OnOff} -bordersDoNotSurroundFooter {w:bordersDoNotSurroundFooter CT_OnOff} -gutterAtTop {w:gutterAtTop CT_OnOff} -hideSpellingErrors {w:hideSpellingErrors CT_OnOff} -hideGrammaticalErrors {w:hideGrammaticalErrors CT_OnOff} / w:activeWritingStyle -proofState {w:proofState { spelling ST_Proof grammar ST_Proof }} -formsDesign {w:formsDesign CT_OnOff} -linkStyles {w:linkStyles CT_OnOff} / w:stylePaneFormatFilter / w:stylePaneSortMethod -documentType {w:documentType NoCheck} / w:revisionView -trackRevisions {w:trackRevisions CT_OnOff} -doNotTrackMoves {w:doNotTrackMoves CT_OnOff} -doNotTrackFormatting {w:doNotTrackFormatting CT_OnOff} -documentProtection {w:documentProtection { edit ST_DocProtect formatting CT_OnOff enforcement CT_OnOff }} -autoFormatOverride {w:autoFormatOverride CT_OnOff} -styleLockTheme {w:styleLockTheme CT_OnOff} -styleLockQFSet {w:styleLockQFSet CT_OnOff} -defaultTabStop {w:defaultTabStop ST_TwipsMeasure} -autoHyphenation {w:autoHyphenation CT_OnOff} -consecutiveHyphenLimit {w:consecutiveHyphenLimit ST_DecimalNumber} -hyphenationZone {w:hyphenationZone ST_TwipsMeasure} -doNotHyphenateCaps {w:doNotHyphenateCaps CT_OnOff} -showEnvelope {w:showEnvelope CT_OnOff} -summaryLength {w:summaryLength ST_DecimalNumberOrPercent} -clickAndTypeStyle {w:clickAndTypeStyle NoCheck} -defaultTableStyle {w:defaultTableStyle NoCheck} -evenAndOddHeaders {w:evenAndOddHeaders CT_OnOff} -bookFoldRevPrinting {w:bookFoldRevPrinting CT_OnOff} -bookFoldPrinting {w:bookFoldPrinting CT_OnOff} -bookFoldPrintingSheets {w:bookFoldPrintingSheets ST_DecimalNumber} -drawingGridHorizontalSpacing {w:drawingGridHorizontalSpacing ST_TwipsMeasure} -drawingGridVerticalSpacing {w:drawingGridVerticalSpacing ST_TwipsMeasure} -displayHorizontalDrawingGridEvery {w:displayHorizontalDrawingGridEvery ST_DecimalNumber} -displayVerticalDrawingGridEvery {w:displayVerticalDrawingGridEvery ST_DecimalNumber} -doNotUseMarginsForDrawingGridOrigin {w:doNotUseMarginsForDrawingGridOrigin CT_OnOff} -drawingGridHorizontalOrigin {w:drawingGridHorizontalOrigin ST_TwipsMeasure} -drawingGridVerticalOrigin {w:drawingGridVerticalOrigin ST_TwipsMeasure} -doNotShadeFormData {w:doNotShadeFormData CT_OnOff} -noPunctuationKerning {w:noPunctuationKerning CT_OnOff} -characterSpacingControl {w:characterSpacingControl ST_CharacterSpacing} -printTwoOnOne {w:printTwoOnOne CT_OnOff} -strictFirstAndLastChars {w:strictFirstAndLastChars CT_OnOff} / w:noLineBreaksAfter / w:noLineBreaksBefore -savePreviewPicture {w:savePreviewPicture CT_OnOff} -doNotValidateAgainstSchema {w:doNotValidateAgainstSchema CT_OnOff} -saveInvalidXml {w:saveInvalidXml CT_OnOff} -ignoreMixedContent {w:ignoreMixedContent CT_OnOff} -alwaysShowPlaceholderText {w:alwaysShowPlaceholderText CT_OnOff} -doNotDemarcateInvalidXml {w:doNotDemarcateInvalidXml CT_OnOff} -saveXmlDataOnly {w:saveXmlDataOnly CT_OnOff} -useXSLTWhenSaving {w:useXSLTWhenSaving CT_OnOff} -saveThroughXslt {w:saveThroughXslt CT_OnOff} -showXMLTags {w:showXMLTags CT_OnOff} -alwaysMergeEmptyNamespace {w:alwaysMergeEmptyNamespace CT_OnOff} -updateFields {w:updateFields CT_OnOff} / w:hdrShapeDefaults / w:footnotePr / w:endnotePr / w:compat / w:docVars / w:rsids / m:mathPr / w:attachedSchema / w:themeFontLang / w:clrSchemeMapping -doNotIncludeSubdocsInStats {w:doNotIncludeSubdocsInStats CT_OnOff} -doNotAutoCompressPictures {w:doNotAutoCompressPictures CT_OnOff} / w:forceUpgrade / w:captions / w:readModeInkLockDown / w:smartTagType / sl:schemaLibrary / w:shapeDefaults -doNotEmbedSmartTags {w:doNotEmbedSmartTags CT_OnOff} -decimalSymbol {w:decimalSymbol NoCheck} -listSeparator {w:listSeparator NoCheck} } set properties(table1) { -style {w:tblStyle TStyle} -width {w:tblW { type ST_TblWidth {value w} ST_MeasurementOrPercent}} -align {w:jc ST_JcTable} } set properties(table2) { -layout {w:tblLayout { type ST_TblLayoutType}} } set properties(table3) { -look {w:tblLook { firstRow CT_OnOff lastRow CT_OnOff firstColumn CT_OnOff lastColumn CT_OnOff noHBand CT_OnOff noVBand CT_OnOff }} -caption {w:tblCaption NoCheck} } set properties(xfrm) { -dimension {a:ext { {width -cx} ST_Emu {height -cy} ST_Emu }} } # This creates # properties(paragraphBorders) # properties(sectionBorders) # properties(tableBorders) # properties(cellBorders) set BorderOpts { color ST_HexColor {borderwidth sz} ST_EighthPointMeasure space ST_PointMeasure {type val} ST_Border } foreach {property borderOptions} { paragraphBorders {top left bottom right between bar} sectionBorders {top left bottom right} tableBorders {top start left bottom end right insideH insideV} cellBorders {top start left bottom end right insideH insideV tl2br tr2bl} } { foreach option $borderOptions { lappend properties($property) \ -${option}Border [list w:$option $BorderOpts] } } foreach {name xml} { [Content_Types].xml { } _rels/.rels { } word/_rels/document.xml.rels { } docProps/app.xml { } docProps/core.xml { } word/fontTable.xml { } word/settings.xml { } word/styles.xml { } } { set staticDocx($name) $xml } foreach tag { w:abstractNum w:abstractNumId w:active w:activeRecord w:activeWritingStyle w:addressFieldName w:adjustLineHeightInTable w:adjustRightInd w:alias w:aliases w:alignBordersAndEdges w:alignTablesRowByRow w:allowPNG w:allowSpaceOfSameStyleInTable w:altChunk w:altChunkPr w:altName w:alwaysMergeEmptyNamespace w:alwaysShowPlaceholderText w:annotationRef w:applyBreakingRules w:attachedSchema w:attachedTemplate w:attr w:autoCaption w:autoCaptions w:autofitToFirstFixedWidthCell w:autoFormatOverride w:autoHyphenation w:autoRedefine w:autoSpaceDE w:autoSpaceDN w:autoSpaceLikeWord95 w:b w:background w:balanceSingleByteDoubleByteWidth w:bar w:basedOn w:bCs w:bdo w:bdr w:behavior w:behaviors w:between w:bibliography w:bidi w:bidiVisual w:blockQuote w:body w:bodyDiv w:bookFoldPrinting w:bookFoldPrintingSheets w:bookFoldRevPrinting w:bookmarkEnd w:bookmarkStart w:bordersDoNotSurroundFooter w:bordersDoNotSurroundHeader w:bottom w:br w:cachedColBalance w:calcOnExit w:calendar w:cantSplit w:caps w:caption w:captions w:category w:cellDel w:cellIns w:cellMerge w:characterSpacingControl w:charset w:checkBox w:checked w:checkErrors w:citation w:clickAndTypeStyle w:clrSchemeMapping w:cnfStyle w:col w:colDelim w:color w:cols w:column w:comboBox w:comment w:commentRangeEnd w:commentRangeStart w:commentReference w:comments w:compat w:compatSetting w:connectString w:consecutiveHyphenLimit w:contentPart w:contextualSpacing w:continuationSeparator w:control w:convMailMergeEsc w:cr w:cs w:customXml w:customXmlDelRangeEnd w:customXmlDelRangeStart w:customXmlInsRangeEnd w:customXmlInsRangeStart w:customXmlMoveFromRangeEnd w:customXmlMoveFromRangeStart w:customXmlMoveToRangeEnd w:customXmlMoveToRangeStart w:customXmlPr w:dataBinding w:dataSource w:dataType w:date w:dateFormat w:dayLong w:dayShort w:ddList w:decimalSymbol w:default w:defaultTableStyle w:defaultTabStop w:del w:delInstrText w:delText w:description w:destination w:dir w:dirty w:displayBackgroundShape w:displayHangulFixedWidth w:displayHorizontalDrawingGridEvery w:displayVerticalDrawingGridEvery w:div w:divBdr w:divId w:divs w:divsChild w:docDefaults w:docGrid w:docPart w:docPartBody w:docPartCategory w:docPartGallery w:docPartList w:docPartObj w:docPartPr w:docParts w:docPartUnique w:document w:documentProtection w:documentType w:docVar w:docVars w:doNotAutoCompressPictures w:doNotAutofitConstrainedTables w:doNotBreakConstrainedForcedTable w:doNotBreakWrappedTables w:doNotDemarcateInvalidXml w:doNotDisplayPageBoundaries w:doNotEmbedSmartTags w:doNotExpandShiftReturn w:doNotHyphenateCaps w:doNotIncludeSubdocsInStats w:doNotLeaveBackslashAlone w:doNotOrganizeInFolder w:doNotRelyOnCSS w:doNotSaveAsSingleFile w:doNotShadeFormData w:doNotSnapToGridInCell w:doNotSuppressBlankLines w:doNotSuppressIndentation w:doNotSuppressParagraphBorders w:doNotTrackFormatting w:doNotTrackMoves w:doNotUseEastAsianBreakRules w:doNotUseHTMLParagraphAutoSpacing w:doNotUseIndentAsNumberingTabStop w:doNotUseLongFileNames w:doNotUseMarginsForDrawingGridOrigin w:doNotValidateAgainstSchema w:doNotVertAlignCellWithSp w:doNotVertAlignInTxbx w:doNotWrapTextWithPunct w:drawing w:drawingGridHorizontalOrigin w:drawingGridHorizontalSpacing w:drawingGridVerticalOrigin w:drawingGridVerticalSpacing w:dropDownList w:dstrike w:dynamicAddress w:eastAsianLayout w:effect w:em w:embedBold w:embedBoldItalic w:embedItalic w:embedRegular w:embedSystemFonts w:embedTrueTypeFonts w:emboss w:enabled w:encoding w:end w:endnote w:endnoteRef w:endnoteReference w:endnotes w:entryMacro w:equation w:evenAndOddHeaders w:exitMacro w:family w:ffData w:fHdr w:fieldMapData w:fitText w:flatBorders w:fldChar w:fldData w:fldSimple w:font w:fonts w:footerReference w:footnote w:footnoteLayoutLikeWW8 w:footnoteRef w:footnoteReference w:footnotes w:forceUpgrade w:forgetLastTabAlignment w:format w:formProt w:formsDesign w:frame w:frameLayout w:framePr w:frameset w:framesetSplitbar w:ftr w:gallery w:glossaryDocument w:gridAfter w:gridBefore w:gridCol w:gridSpan w:group w:growAutofit w:guid w:gutterAtTop w:hdr w:hdrShapeDefaults w:header w:headerReference w:headers w:headerSource w:helpText w:hidden w:hideGrammaticalErrors w:hideMark w:hideSpellingErrors w:highlight w:hMerge w:hps w:hpsBaseText w:hpsRaise w:hyperlink w:hyphenationZone w:i w:iCs w:id w:ignoreMixedContent w:ilvl w:imprint w:ind w:ins w:insideH w:insideV w:instrText w:isLgl w:jc w:keepLines w:keepNext w:kern w:kinsoku w:label w:lang w:lastRenderedPageBreak w:latentStyles w:layoutRawTableWidth w:layoutTableRowsApart w:left w:legacy w:lid w:lineWrapLikeWord6 w:link w:linkedToFile w:linkStyles w:linkToQuery w:listEntry w:listItem w:listSeparator w:lnNumType w:lock w:locked w:longDesc w:lsdException w:lvl w:lvlJc w:lvlOverride w:lvlPicBulletId w:lvlRestart w:lvlText w:mailAsAttachment w:mailMerge w:mailSubject w:mainDocumentType w:mappedName w:marBottom w:marH w:marLeft w:marRight w:marTop w:marW w:matchSrc w:maxLength w:mirrorIndents w:mirrorMargins w:monthLong w:monthShort w:moveFrom w:moveFromRangeEnd w:moveFromRangeStart w:moveTo w:moveToRangeEnd w:moveToRangeStart w:movie w:multiLevelType w:mwSmallCaps w:name w:next w:noBorder w:noBreakHyphen w:noColumnBalance w:noEndnote w:noExtraLineSpacing w:noLeading w:noLineBreaksAfter w:noLineBreaksBefore w:noProof w:noPunctuationKerning w:noResizeAllowed w:noSpaceRaiseLower w:noTabHangInd w:notTrueType w:noWrap w:nsid w:num w:numbering w:numberingChange w:numFmt w:numId w:numIdMacAtCleanup w:numPicBullet w:numRestart w:numStart w:numStyleLink w:object w:objectEmbed w:objectLink w:odso w:oMath w:optimizeForBrowser w:outline w:outlineLvl w:overflowPunct w:p w:pageBreakBefore w:panose1 w:paperSrc w:permEnd w:permStart w:personal w:personalCompose w:personalReply w:pgBorders w:pgMar w:pgNum w:pgNumType w:pgSz w:pict w:picture w:pitch w:pixelsPerInch w:placeholder w:pos w:position w:pPrChange w:pPrDefault w:printBodyTextBeforeHeader w:printColBlack w:printerSettings w:printFormsData w:printFractionalCharacterWidth w:printPostScriptOverText w:printTwoOnOne w:proofErr w:proofState w:pStyle w:ptab w:qFormat w:query w:r w:readModeInkLockDown w:recipientData w:recipients w:relyOnVML w:removeDateAndTime w:removePersonalInformation w:result w:revisionView w:rFonts w:richText w:right w:rPrChange w:rPrDefault w:rsid w:rsidRoot w:rsids w:rStyle w:rt w:rtl w:rtlGutter w:ruby w:rubyAlign w:rubyBase w:rubyPr w:saveFormsData w:saveInvalidXml w:savePreviewPicture w:saveSmartTagsAsXml w:saveSubsetFonts w:saveThroughXslt w:saveXmlDataOnly w:scrollbar w:sdt w:sdtContent w:sdtEndPr w:sdtPr w:sectPr w:sectPrChange w:selectFldWithFirstOrLastChar w:semiHidden w:separator w:settings w:shadow w:shapeDefaults w:shapeLayoutLikeWW8 w:shd w:showBreaksInFrames w:showEnvelope w:showingPlcHdr w:showXMLTags w:sig w:size w:sizeAuto w:smallCaps w:smartTag w:smartTagPr w:smartTagType w:snapToGrid w:softHyphen w:sourceFileName w:spaceForUL w:spacing w:spacingInWholePoints w:specVanish w:splitPgBreakAndParaMark w:src w:start w:startOverride w:statusText w:storeMappedDataAs w:strictFirstAndLastChars w:strike w:style w:styleLink w:styleLockQFSet w:styleLockTheme w:stylePaneFormatFilter w:stylePaneSortMethod w:styles w:subDoc w:subFontBySize w:suff w:summaryLength w:suppressAutoHyphens w:suppressBottomSpacing w:suppressLineNumbers w:suppressOverlap w:suppressSpacingAtTopOfPage w:suppressSpBfAfterPgBrk w:suppressTopSpacing w:suppressTopSpacingWP w:swapBordersFacingPages w:sym w:sz w:szCs w:t w:tab w:tabIndex w:table w:tag w:targetScreenSz w:tbl w:tblCaption w:tblCellSpacing w:tblDescription w:tblGrid w:tblGridChange w:tblHeader w:tblInd w:tblLayout w:tblLook w:tblOverlap w:tblPr w:tblpPr w:tblPrChange w:tblPrEx w:tblPrExChange w:tblStyle w:tblStyleColBandSize w:tblStylePr w:tblStyleRowBandSize w:tblW w:tc w:tcFitText w:tcPrChange w:tcW w:temporary w:text w:textAlignment w:textboxTightWrap w:textDirection w:textInput w:themeFontLang w:title w:titlePg w:tl2br w:tmpl w:top w:topLinePunct w:tr w:tr2bl w:trackRevisions w:trHeight w:trPrChange w:truncateFontHeightsLikeWP6 w:txbxContent w:type w:types w:u w:udl w:uiPriority w:ulTrailSpace w:underlineTabInNumList w:unhideWhenUsed w:uniqueTag w:updateFields w:useAltKinsokuLineBreakRules w:useAnsiKerningPairs w:useFELayout w:useNormalStyleForList w:usePrinterMetrics w:useSingleBorderforContiguousCells w:useWord97LineBreakRules w:useWord2002TableStyleRules w:useXSLTWhenSaving w:vAlign w:vanish w:vertAlign w:view w:viewMergedData w:vMerge w:w w:wAfter w:wBefore w:webHidden w:webSettings w:widowControl w:wordWrap w:wpJustification w:wpSpaceWidth w:wrapTrailSpaces w:writeProtection w:yearLong w:yearShort w:zoom } { dom createNodeCmd -tagName $tag -namespace $xmlns(w) elementNode Tag_$tag } foreach tag { w:footnotePr w:endnotePr w:numPr w:pBdr w:pPr w:rPr w:tabs w:tblBorders w:tblCellMar w:tcBorders w:tcMar w:tcPr w:trPr } { dom createNodeCmd -tagName $tag -namespace $xmlns(w) -notempty elementNode Tag_$tag } foreach tag { Relationships Relationship } { dom createNodeCmd -tagName $tag -namespace $xmlns(rel) elementNode Tag_$tag } foreach tag { wp:align wp:anchor wp:cNvGraphicFramePr wp:docPr wp:effectExtent wp:extent wp:inline wp:positionH wp:positionV wp:posOffset wp:simplePos wp:wrapNone wp:wrapSquare wp:wrapTopAndBottom } { dom createNodeCmd -tagName $tag -namespace $xmlns(wp) elementNode Tag_$tag } foreach tag { a:avLst a:blip a:ext a:fillRect a:graphic a:graphicData a:graphicFrameLocks a:off a:picLocks a:prstGeom a:stretch a:xfrm } { dom createNodeCmd -tagName $tag -namespace $xmlns(a) elementNode Tag_$tag } foreach tag { pic:pic pic:blipFill pic:nvPicPr pic:cNvPr pic:cNvPicPr pic:spPr } { dom createNodeCmd -tagName $tag -namespace $xmlns(pic) elementNode Tag_$tag } foreach tag { wps:bodyPr wps:cNvSpPr wps:spPr wps:txbx wps:wsp } { dom createNodeCmd -tagName $tag -namespace $xmlns(wps) elementNode Tag_$tag } foreach tag { Default Override } { dom createNodeCmd -tagName $tag -namespace $xmlns(ct) elementNode Tag_$tag } dom createNodeCmd textNode Text namespace export Tag_* Text } oo::class create ooxml::docx::docx { constructor { args } { my variable docs my variable body my variable context my variable binparts my variable ignorable my variable setuproot my variable pagesetup my variable sectionsetup my variable impPagesetup my variable tablecontext my variable bookmarks my variable id my variable valPrefix variable ::ooxml::docx::xmlns variable ::ooxml::docx::staticDocx variable ::ooxml::docx::prefixnslist namespace import ::ooxml::docx::lib::* namespace import ::ooxml::docx::Tag_* ::ooxml::docx::Text # Setup defaults/initial values # # Sensible default according to field set ignorable "w14 wp14 wpg wps" set context document set valPrefix w set pagesetup "" set sectionsetup "" set impPagesetup "" set tablecontext "" # Since the "general page setup" (WordprocessingML does not # really have a concept for that) is a child of w:body after # the last paragraph it seems handy to not reallyq insert that # into the tree at the moment the user calls pagesetup but # just before serializing - as the user consecutive add # content we can just append to the w:body without looking at # every place if there is already a page setup child and we # have to insert new content before that element. The current # pagesetup/sectionsetup user definition is stored in # according variables to be applied later. To give the user # error feedback at the place he provides commands an # auxiliary document is used and the definition is "tested" # with that. set setupdoc [dom createDocumentNS $xmlns(w) w:umbrella] set setuproot [$setupdoc documentElement] foreach ns {o m r v w w10 wp wps wpg mc wp14 w14} { $setuproot setAttributeNS "" xmlns:$ns $xmlns($ns) } if {[llength $args] % 2} { # User gave a docx file name to start from set startdocx [lindex $args end] set args [lrange $args 0 end-1] my InitFromDocx $startdocx } else { # Create a docx from scratch # Ensure that we can use our prefixes for XPath queries foreach auxFile [array names staticDocx] { set docs($auxFile) [dom parse $staticDocx($auxFile)] $docs($auxFile) selectNodesNamespaces $prefixnslist } set document [dom createDocumentNS $xmlns(w) w:document] set docs(word/document.xml) $document $docs(word/document.xml) selectNodesNamespaces $prefixnslist $document documentElement root foreach ns {o m r v w10 wp wps wpg mc wp14 w14} { $root setAttributeNS "" xmlns:$ns $xmlns($ns) } $root appendFromScript Tag_w:body set body [$root firstChild] my Ignorable } my configure {*}$args } destructor { my variable docs my variable setuproot foreach part [array names docs] { $docs($part) delete } [$setuproot ownerDocument] delete } method Add2Content_Types {file} { my variable docs variable ::ooxml::docx::xmlns if {[string index $file 0] ne "/"} { error "file paths to be added to \[ContentType\].xml must start\ with a slash (/)" } set ctRoot [$docs(\[Content_Types\].xml) documentElement] if {[$ctRoot selectNodes {count(ct:Override[@PartName=$file])}] > 0} { return } if {[string range $file 0 11] eq "/word/media/"} { set suffix [string tolower [string range [file extension $file] 1 end]] if {[$ctRoot selectNodes { count(ct:Default[@Extension=$suffix]) }] > 0} { return } } switch -glob $file { "/_rels/.rels" { set type "application/vnd.openxmlformats-package.relationships+xml" } "/docProps/core.xml" { set type "application/vnd.openxmlformats-package.core-properties+xml" } "/docProps/app.xml" { set type "application/vnd.openxmlformats-officedocument.extended-properties+xml" } "/word/_rels/document.xml.rels" { set type "application/vnd.openxmlformats-package.relationships+xml" } "/word/comments.xml" { set type "application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml" } "/word/document.xml" { set type "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml" } "/word/endnotes.xml" { set type "application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml" } "/word/fontTable.xml" { set type "application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml" } "/word/footnotes.xml" { set type "application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml" } "/word/footer*.xml" { set type "application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml" } "/word/header*.xml" { set type "application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml" } "/word/media/*" { set contentType [MimeType $suffix] $ctRoot insertBeforeFromScript { Tag_Default Extension $suffix ContentType $contentType } [$ctRoot selectNodes {ct:Override[1]}] return } "/word/numbering.xml" { set type "application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml" } "/word/settings.xml" { set type "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml" } "/word/styles.xml" { set type "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml" } "/word/stylesWithEffects.xml" { set type "application/vnd.ms-word.stylesWithEffects+xml" } "/word/theme/theme1.xml" { set type "application/vnd.openxmlformats-officedocument.theme+xml" } "/word/webSettings.xml" { set type "application/vnd.openxmlformats-officedocument.wordprocessingml.webSettings+xml" } default { error "cannot find the ContentType for '$file'" } } $ctRoot appendFromScript { Tag_Override PartName $file ContentType $type } } method Add2Relationships {type target} { my variable docs my variable context variable ::ooxml::docx::xmlns set thisfile "word/_rels/$context.xml.rels" if {![info exists docs($thisfile)]} { set docs($thisfile) [dom parse { }] } set relsRoot [$docs($thisfile) documentElement] # If there is already an entry for this type and target just # return the rId set fqtype http://schemas.openxmlformats.org/officeDocument/2006/relationships/$type set result [$relsRoot selectNodes -namespaces "rel $xmlns(rel)" { string(rel:Relationship[@Type=$fqtype and @Target=$target]/@Id) }] if {$result ne ""} { return $result } # Find the maximum numeric part of any existing rId in this relationships part set nr 0 foreach rel [$relsRoot childNodes] { set id [$rel @Id ""] if {[regexp {^rId([0-9]+)$} $id -> n]} { if {$n > $nr} { set nr $n } } } incr nr set attlist [list \ Id rId$nr \ Type http://schemas.openxmlformats.org/officeDocument/2006/relationships/$type \ Target $target] if {$type eq "hyperlink"} { lappend attlist TargetMode External } $relsRoot appendFromScript { Tag_Relationship {*}$attlist } if {$type eq "hyperlink"} { return rId$nr } my Add2Content_Types "/word/$target" return rId$nr } method Anchor {name} { my Prepare 1 # Defaults array set anchorAtts { behindDoc 0 distT 0 distB 0 distL 0 distR 0 hidden 0 locked 0 layoutInCell 0 allowOverlap 1 relativeHeight 1 simplePos 0 } # Updated by optional user provided values array set anchorAtts [my CheckedAttlist [my EatOption -anchorData] { -behindDoc CT_Boolean -distT ST_Emu -distB ST_Emu -distL ST_Emu -distR ST_Emu -hidden CT_Boolean -locked CT_Boolean -layoutInCell CT_Boolean -allowOverlap CT_Boolean -relativeHeight CT_UnsignedInt } -anchorData] Tag_wp:anchor [array get anchorAtts] { Tag_wp:simplePos x 0 y 0 Tag_wp:positionH [my Option -positionH relativeFrom ST_RelFromH "column"] { lassign [my OneOff {-alignH ST_AlignH} {-posOffsetH ST_Emu}] \ alignH posOffsetH if {$alignH eq "" && $posOffsetH eq ""} { set alignH "center" } foreach value [list $alignH $posOffsetH] tag {Tag_wp:align Tag_wp:posOffset} { if {$value ne ""} { $tag {Text $value} break } } } Tag_wp:positionV [my Option -positionV relativeFrom ST_RelFromV "paragraph"] { lassign [my OneOff {-alignV ST_AlignV} {-posOffsetV ST_Emu}] \ alignV posOffsetV if {$alignV eq "" && $posOffsetV eq ""} { set alignV "center" } foreach value [list $alignV $posOffsetV] tag {Tag_wp:align Tag_wp:posOffset} { if {$value ne ""} { $tag {Text $value} break } } } set thisOptionValue [my PeekOption -dimension] set attlist [my CheckedAttlist $thisOptionValue { {width -cx} ST_Emu {height -cy} ST_Emu } -dimension] if {[llength $attlist] != 4} { error "the -dimension option expects both keys \"width\" and\ \"height\" to be given" } Tag_wp:extent {*}$attlist Tag_wp:effectExtent l 0 t 0 r 0 b 0 set wrapMode [my EatOption -wrapMode] switch $wrapMode { "" - "none" { if {[my EatOption -wrapData] ne ""} { error "the option \"-wrapMode none does not expect \"-wrapData\"" } Tag_wp:wrapNone } "square" { set attlist [my CheckedAttlist [my EatOption -wrapData] { -wrapText ST_WrapText -distT ST_Emu -distB ST_Emu -distL ST_Emu -distR ST_Emu } -wrapData] Tag_wp:wrapSquare {*}$attlist } "topBottom" { Tag_wp:wrapTopAndBottom } default { error "unknown -wrapMode option value \"$wrapMode\", expect\ one of [AllowedValues {none square topBottom}]" } } Tag_wp:docPr id [my NextId docPr] name $name Tag_wp:cNvGraphicFramePr { Tag_a:graphicFrameLocks noChangeAspect 1 } set anchor [dom fromScriptContext] } return $anchor } method CallType {type value errtext} { # A few value checks need access to the docx object internal # data and therefor are implemented as object methods. The # bulk of the type checks are "static" procs in the # ooxml::docx namespace. set error 0 if {[catch {set ooxmlvalue [$type $value]} errMsg]} { if {![llength [info procs ::ooxml::docx::lib::$type]]} { if {[catch {set ooxmlvalue [my $type $value]} errMsg]} { set error 1 } } else { set error 1 } if {$error} { if {[info exists ::ooxml::docx::docgen] && $::ooxml::docx::docgen} { error "===$type=== $errMsg" } else { error "$errtext: $errMsg" } } } return $ooxmlvalue } method CheckedAttlist {optionValue attdefs option} { variable valPrefix set attlist "" if {[catch {array set atts $optionValue}]} { set keys "" foreach {attdata type} $attdefs { lappend keys [string trimleft [lindex $attdata 0] -] } error "the value \"$optionValue\" given to the \"$option\" \ option is invalid, expected is a key value pairs\ list with keys out of [AllowedValues $keys]" } foreach {attdata typedata} $attdefs { if {[llength $attdata] == 2} { lassign $attdata key attname } else { if {[string index $attdata 0] eq "-"} { set key [string range $attdata 1 end] } else { set key $attdata } set attname $attdata } lassign $typedata type flags default if {![info exists atts($key)]} { if {$flags eq "!"} { if {[llength $typedata] == 2} { error "the argument \"$optionValue\" given to the\ \"$option\" option is invalid: the mandatory\ key \"$key\" in the argument\ is invalid" } else { set atts($key) $default } } else { continue } } set ooxmlvalue [my CallType $type $atts($key) \ "the argument \"$optionValue\" given to the\ \"$option\" option is invalid: the value\ given to the key \"$key\" invalid"] if {[string index $attname 0] eq "-"} { lappend attlist [string range $attname 1 end] $ooxmlvalue } else { lappend attlist ${valPrefix}:$attname $ooxmlvalue } unset atts($key) } # Check if there are unknown keys left in the key # values list set remainigKeys [array names atts] if {[llength $remainigKeys] != 0} { set keys "" foreach {attdata type} $attdefs { lappend keys [lindex $attdata 0] } if {[llength $remainigKeys] == 1} { error "unknown key \"[lindex $remainigKeys 0]\" in\ the value \"$optionValue\" of the option\ \"$option\", the expected keys are\ [AllowedValues $keys]" } else { error "unknown keys [AllowedValues $remainigKeys and] in\ the value \"$optionValue\" of the option\ \"$option\", the expected keys are\ [AllowedValues $keys]" } } return $attlist } method CheckRemainingOpts {} { my Prepare set nrRemainigOpts [llength [array names opts]] if {$nrRemainigOpts == 0} return if {$nrRemainigOpts == 1} { set text "unknown option: [lindex [array names opts] 0]" } else { set text "unknown options: [AllowedValues [array names opts] and]" } set knownOps [lsort [array names optsknown]] set knownOpsLen [llength $knownOps] if {$knownOpsLen} { if {$knownOpsLen > 1} { append text ", known options are [AllowedValues $knownOps and]" } else { append text ", known option is $knownOps" } } uplevel [list error $text] } method CheckrId {type rId} { my variable docs variable ::ooxml::docx::xmlns set relsRoot [$docs(word/_rels/document.xml.rels) documentElement] set type "$xmlns(r)/$type" if {![$relsRoot selectNodes -namespaces "rel $xmlns(rel)" { count(rel:Relationship[@Id=$rId and @Type=$type]) }]} { error "invalid rId $rId" } } method ControlChar {c {n 1}} { set p [my LastParagraph] for {set i 0} {$i<$n} {incr i} { $p appendFromScript { Tag_w:r { Tag_w:$c } } } } method Create switchActionList { variable valPrefix my Prepare foreach {opt optdata} $switchActionList { # If the opt is just / then this is a placeholder for an # element which currently cannot be created by an option. # The optdata gives the element name. if {$opt eq "/"} { continue } # If the option description starts with a + then this # describes not an option which would create a child with # one or several attributes. It describes a child (with # the opt value stripped by the leading + as name) with # child nodes and the optdata are the ordinary description # of the options to create those children with values in # attributes. if {[string index $opt 0] eq "+"} { Tag_[string range $opt 1 end] { my Create $optdata } continue } # If the opt is just | then optdata is a list of mutually # exclusive usual option descriptions. if {$opt eq "|"} { # We check the last child of the context to see if the # option group has created something (and so at least # one option of this group was given). set lastChild [[dom fromScriptContext] lastChild] set seen 0 set groupOptions [list] foreach desc $optdata { array unset startOptsknown array set startOptsknown [array get optsknown] my Create $desc set thisopts [list] foreach thisopt [array names optsknown] { if {![info exists startOptsknown($thisopt)]} { lappend thisopts $thisopt } } lappend groupOptions [lsort $thisopts] set thisLast [[dom fromScriptContext] lastChild] if {$lastChild ne $thisLast} { incr seen set lastChild $thisLast } } if {$seen > 1} { error "The options [join $groupOptions " and "] are\ mutually exclusive." } continue } # The "normal" cases set optsknown($opt) "" if {![info exists opts($opt)]} { continue } set value $opts($opt) switch [llength $optdata] { 2 { lassign $optdata tags attdefs if {[llength $attdefs] == 1} { # An element with just w:val as attribute and # the attdefs gives the value type. set ooxmlvalue [my CallType $attdefs $value \ "the value \"$value\" given to\ the \"$opt\" option is invalid"] foreach tag $tags { Tag_$tag ${valPrefix}:val $ooxmlvalue } unset opts($opt) continue } # This handles the (rare) case of tags with just one # attribute to set and that attribute is not w:val if {[llength $attdefs] == 2} { lassign $attdefs attname atttype set ooxmlvalue [my CallType $atttype $value \ "the value \"$value\" given to the \"$opt\"\ option is invalid"] if {[string index $attname 0] eq "-"} { set attname [string range $attname 1 end] } else { set attname ${valPrefix}:$attname } foreach tag $tags { Tag_$tag $attname $ooxmlvalue } unset opts($opt) continue } # For now the code assumes always several atts # and therefore the value to the option is always # handled as a key value pairs list. set attlist [my CheckedAttlist $value $attdefs $opt] foreach tag $tags { Tag_$tag {*}$attlist } unset opts($opt) } 3 { my [lindex $optdata 2] $value unset opts($opt) } default { error "invalid properties value" } } } } method CreateComment {{commentID ""}} { my variable docs my variable ignorable variable ::ooxml::docx::xmlns variable ::ooxml::docx::prefixnslist my Prepare if {![info exists docs(word/comments.xml)]} { my Add2Relationships comments comments.xml set document [dom createDocumentNS $xmlns(w) w:comments] set docs(word/comments.xml) $document $docs(word/comments.xml) selectNodesNamespaces $prefixnslist $document documentElement commentsroot foreach ns {o m r v w10 wp wps wpg mc wp14 w14} { $commentsroot setAttributeNS {} xmlns:$ns $xmlns($ns) } my Ignorable word/comments.xml } set comments [$docs(word/comments.xml) documentElement] if {$commentID eq ""} { set commentID [my NextId comments] } $comments appendFromScript { set author [my EatOption -author NoCheck "Unknown"] Tag_w:comment w:id $commentID \ w:date [my EatOption -date ST_DateTime] \ w:author $author \ w:initials [my EatOption -initials NoCheck] } return [list [$comments lastChild] $commentID] } method EatOption {option {type ""} {default ""} {deleteOption 1}} { my Prepare set optsknown($option) "" if {[info exists opts($option)]} { set value $opts($option) if {$type ne ""} { set value [my CallType $type $value "option $option"] } if {$deleteOption} { unset opts($option) } return $value } return $default } method FootnoteEndnote {type refstyle script} { my variable docs my variable body my variable ignorable my variable id variable ::ooxml::docx::xmlns variable ::ooxml::docx::prefixnslist set types "${type}s" set notePart "word/$types.xml" if {![info exists docs($notePart)]} { my Add2Relationships $types $types.xml set document [dom createDocumentNS $xmlns(w) w:$types] set docs($notePart) $document $docs($notePart) selectNodesNamespaces $prefixnslist $document documentElement notesroot foreach ns {o m r v w10 wp wps wpg mc wp14 w14} { $notesroot setAttributeNS {} xmlns:$ns $xmlns($ns) } my Ignorable $notePart foreach {thisid sepType} { 0 separator 1 continuationSeparator } { $notesroot appendFromScript { Tag_w:$type w:type $sepType w:id $thisid { Tag_w:p { Tag_w:r { Tag_w:$sepType } } } } } set id($types) 1 } else { set notesroot [$docs($notePart) documentElement] } set thisid [my NextId $types] $notesroot appendFromScript { Tag_w:$type w:id $thisid } set savedbody $body set body [$notesroot lastChild] set objectId [my GetObjectId $types $body] if {[catch {uplevel 2 [list eval $script]} errMsg errVals]} { set body $savedbody my ProcessErrorinfo $type return -code error $errMsg } set firstp [$body selectNodes {w:p[1]}] if {$firstp eq ""} { $body appendFromScript Tag_w:p set firstp [$notesroot lastChild] } $firstp insertBeforeFromScript { Tag_w:r { if {$refstyle ne ""} { Tag_w:rPr { Tag_w:rStyle w:val $refstyle } } Tag_w:${type}Ref } } [$firstp selectNodes {w:r[1]}] set body $savedbody return [list $thisid $objectId] } method GetDocDefault {styles} { # styles has the content model sequence: # docDefaults? latentStyles? styles* set docDefaults [$styles firstChild] if {$docDefaults == "" || [$docDefaults localName] ne "docDefaults"} { set nextNode $docDefaults $styles insertBeforeFromScript Tag_w:docDefaults $nextNode set docDefaults [$styles firstChild] } return $docDefaults } method HeaderFooter {what script} { my variable docs my variable body my variable context my variable ignorable variable ::ooxml::docx::xmlns variable ::ooxml::docx::prefixnslist set have [lsort -dictionary [array names docs word/$what*]] if {![llength $have]} { set nr 1 } else { set last [string range [lindex $have end] 0 end-4] set nr [string range $last [expr {5 + [string length $what]}] end] incr nr } set rId [my Add2Relationships $what $what$nr.xml] if {$what eq "header"} { set elnName "hdr" } else { set elnName "ftr" } set document [dom createDocumentNS $xmlns(w) w:$elnName] set partName "word/$what$nr.xml" set docs($partName) $document $docs($partName) selectNodesNamespaces $prefixnslist $document documentElement root foreach ns {o m r v w10 wp wps wpg mc wp14 w14} { $root setAttributeNS {} xmlns:$ns $xmlns($ns) } my Ignorable $partName set savedbody $body set savedcontext $context set body $root set context $what$nr if {[catch {uplevel 2 [list eval $script]} errMsg errVals]} { set body $savedbody set context $savedcontext my ProcessErrorinfo $what return -code error $errMsg } set objectId [my GetObjectId $what $body $rId] set body $savedbody set context $savedcontext return [list $rId $objectId] } method Ignorable {{file ""}} { my variable docs my variable ignorable variable ::ooxml::docx::xmlns if {$file eq ""} { set files [array names docs word/*.xml] } else { set files [list $file] } foreach doc $files { set thisdoc $docs($doc) set storedprefixns [$thisdoc selectNodesNamespaces] $thisdoc selectNodesNamespaces "" set thisroot [$thisdoc documentElement] if {[catch {$thisroot selectNodes mc:*}]} { # XML namespace prefix mc not defined $thisdoc selectNodesNamespaces $storedprefixns continue } $thisdoc selectNodesNamespaces $storedprefixns array unset prefixlookup array set prefixlookup [join [$thisroot selectNodes namespace::*]] set knownprefixes "" foreach prefix $ignorable { if {[info exists prefixlookup(xmlns:$prefix)]} { lappend knownprefixes $prefix } } if {![llength $knownprefixes]} { if {[$thisroot hasAttributeNS $xmlns(mc) Ignorable]} { $thisroot removeAttributeNS $xmlns(mc) Ignorable } continue } $thisroot setAttributeNS \ $xmlns(mc) mc:Ignorable $knownprefixes } } method Image_anchor {rId file} { my Prepare set anchor [my Anchor [file tail $file]] $anchor appendFromScript { my Image_graphic $rId $file } } method Image_graphic {rId file} { my Prepare Tag_a:graphic { Tag_a:graphicData uri "http://schemas.openxmlformats.org/drawingml/2006/picture" { Tag_pic:pic { Tag_pic:nvPicPr { Tag_pic:cNvPr id [my NextId pic] name [file rootname [file tail $file]] Tag_pic:cNvPicPr { Tag_a:picLocks noChangeAspect 1 noChangeArrowheads 1 } } Tag_pic:blipFill { Tag_a:blip r:embed $rId Tag_a:stretch { Tag_a:fillRect } } Tag_pic:spPr {*}[my Option -bwMode bwMode ST_BlackWhiteMode "auto"] { my SpPr_Content } } } } } method Image_inline {rId file} { my Prepare Tag_wp:inline { set thisOptionValue [my PeekOption -dimension] set attlist [my CheckedAttlist $thisOptionValue { {width -cx} ST_Emu {height -cy} ST_Emu } -dimension] if {[llength $attlist] != 4} { error "the -dimension option expects both keys \"width\" and\ \"height\" to be given" } Tag_wp:extent {*}$attlist Tag_wp:docPr id [my NextId docPr] name [file tail $file] my Image_graphic $rId $file } } method InitFromDocx {docxfile} { my variable docs my variable body my variable binparts my variable impPagesetup my variable id variable ::ooxml::docx::prefixnslist if {[catch {::ooxml::ZipOpen $docxfile} errMsg]} { return -code error "Cannot open '$docxfile': $errMsg" } set id(image) 0 foreach part [::ooxml::ZipMembers] { if {[catch {set docs($part) [::ooxml::ZipReadParse $part]}]} { # Non XML file; add to binparts set binparts($part) [::ooxml::ZipReadBinaryFile $part] } if {[regexp {^word/media/image(\d+)} $part -> n]} { if {$id(image) < $n} { set id(image) $n } } } ::ooxml::ZipClose # Check that (by the spec) required parts of the docx are # actually exist (the implementation expects them as present). foreach musthave { [Content_Types].xml word/document.xml word/_rels/document.xml.rels } { if {![info exists docs($musthave)]} { return -code error "Invalid ooxml docx file '$docxfile':\ missing required part '$musthave'" } } # Ensure that a word/styles.xml is there if {![info exists docs(word/styles.xml)]} { variable ::ooxml::docx::staticDocx set docs(word/styles.xml) [dom parse $staticDocx(word/styles.xml)] } # Ensure that we can use our prefixes for XPath queries foreach xmlpart [array names docs] { $docs($xmlpart) selectNodesNamespaces $prefixnslist } # Move a present sectPr elemet away (to restore it at write # time, if the user has not specified another page setup). set body [$docs(word/document.xml) selectNodes {w:document/w:body[last()]}] if {$body eq ""} { return -code error "Invalid ooxml docx file '$docxfile':\ no body element in word/document.xml" } set lastElm [$body selectNodes {w:*[last()]}] if {[$lastElm localName] eq "sectPr"} { set impPagesetup $lastElm $body removeChild $lastElm } # Seed index counters foreach key {docPr pic bookmarks textboxes comments footnotes endnotes} { set id($key) 0 } foreach part [array names docs "word/*.xml"] { foreach {key tag att} { docPr wp:docPr id pic pic:cNvPr id bookmarks w:bookmarkStart w:id } { foreach attribute [$docs($part) selectNodes //$tag/@$att] { lassign $attribute name v if {[string is integer -strict $v] && $v > $id($key)} { set id($key) $v } } } foreach attribute [$docs($part) selectNodes //wp:docPr/@name] { lassign $attribute name value if {[regexp {^Textbox\s+(\d+)$} $value -> n] && $n > $id(textboxes)} { set id(textboxes) $n } } } foreach {key part tag} { comments word/comments.xml w:comment footnotes word/footnotes.xml w:footnote endnotes word/endnotes.xml w:endnote } { if {![info exists docs($part)]} continue foreach attribute [$docs($part) selectNodes //$tag/@w:id] { lassign $attribute name v if {[string is integer -strict $v] && $v > $id($key)} { set id($key) $v } } } } method LastParagraph {{create 0}} { my variable body set p [$body lastChild] while {$p ne ""} { if {[$p nodeType] ne "ELEMENT_NODE"} { set p [$p previousSibling] continue } if {[$p nodeName] ne "w:p"} { # Perhaps it would be more wise to raise error in this # situation or to create a new one? set p [$p previousSibling] continue } break } if {$p eq ""} { if {!$create} { error "no paragraph to append to in the document" } $body appendFromScript { Tag_w:p } set p [$body lastChild] } return $p } method NextId {domain} { my variable id # Return the next unique id return [incr id($domain)] } method GetObjectId {domain node {thisid ""}} { my variable id my variable objectId if {$thisid eq ""} { set thisid $id($domain) } set objectId($domain$thisid) $node return $domain$thisid } method OneOff {opta optb} { my Prepare lassign $opta optiona typea lassign $optb optionb typeb set a [my EatOption $optiona $typea] set b [my EatOption $optionb $typeb] if {$a ne "" && $b ne ""} { error "the options $optiona and $optionb are mutually exclusive" } return [list $a $b] } method OneOffOptions {args} { my Prepare set count 0 foreach option $args { incr count [info exists opts($option)] } if {$count > 1} { return -code error "the options [AllowedValues $args and] are\ mutually exclusive" } } method Option {option attname type {default ""}} { my Prepare set optsknown($option) "" if {[info exists opts($option)]} { set ooxmlvalue [my CallType $type $opts($option) \ "the value given to the \"$option\" option\ is invalid"] unset opts($option) } else { set ooxmlvalue $default } return [list $attname $ooxmlvalue] } method PeekOption {option {type ""} {default ""}} { my Prepare return [my EatOption $option $type $default 0] } method Prepare {{properties 0}} { set script "upvar opts opts; upvar optsknown optsknown;" if {$properties} { append script "variable ::ooxml::docx::properties" } uplevel [list eval $script] } method ProcessErrorinfo {what} { upvar errMsg errMsg upvar errVals errVals set errorinfo [dict get $errVals -errorinfo] set ind [string first "(\"eval\" body line " $errorinfo] if {$ind > -1} { set errMsg [string range $errorinfo 0 $ind-1] if {[regexp {(\d+)} [string range $errorinfo $ind end] --> linenr]} { append errMsg "($what script body line $linenr)" } } } method PPr {} { my Prepare 1 my OneOffOptions -shading -background Tag_w:pPr { my Create $properties(paragraph1) Tag_w:pBdr { my Create $properties(paragraphBorders) } my Create $properties(paragraph2) set value [my EatOption -background ST_HexColor] if {$value ne ""} { Tag_w:shd w:val "clear" w:fill $value } Tag_w:tabs { my Tabs [my EatOption -tabs] } my Create $properties(paragraph3) } } method PStyle {value} { return [my StyleCheck paragraph $value] } method RFonts {value} { Tag_w:rFonts \ w:ascii $value \ w:hAnsi $value \ w:eastAsia $value \ w:cs $value } method RPr {} { my Prepare 1 Tag_w:rPr { my Create $properties(run) } } method RStyle {value} { return [my StyleCheck character $value] } method SectionCommon {} { my Prepare 1 Tag_w:sectPr { foreach what {Header Footer} { foreach type {even default first} { set value [my EatOption -$type$what] if {$value eq ""} { continue } if {$type eq "even"} { my settings -evenAndOddHeaders on } my CheckrId [string tolower $what] $value Tag_w:[string tolower $what]Reference w:type $type r:id $value } } my Create $properties(sectionsetup1) Tag_w:pgBorders { my Create $properties(sectionBorders) } my Create $properties(sectionsetup2) } } method SpPr_Content {} { my Prepare 1 Tag_a:xfrm { Tag_a:off x 0 y 0 my Create $properties(xfrm) } Tag_a:prstGeom prst "rect" { Tag_a:avLst } } method StyleCheck {type value} { my variable docs set styles [$docs(word/styles.xml) documentElement] set style [$styles selectNodes { w:style[@w:type=$type and @w:styleId=$value] }] if {![llength $style]} { set style [$styles selectNodes { w:style[@w:type=$type][w:name[@w:val=$value]] }] } if {![llength $style]} { error "unknown $type style \"$value\"" } return [[lindex $style 0] selectNodes string(@w:styleId)] } method Tabs {tabsdata} { foreach tabstop $tabsdata { if {[llength $tabstop] == 1} { OptVal [list -tabs [list pos $tabstop type "start"]] } else { OptVal [list -tabs [list $tabstop]] } my Create { -tabs {w:tab { leader ST_TabTlc pos ST_SignedTwipsMeasure {type val} ST_TabJc }} } unset opts } } method TblPr {} { my Prepare 1 Tag_w:tblPr { my Create $properties(table1) Tag_w:tblBorders { my Create $properties(tableBorders) } my Create $properties(table2) Tag_w:tblCellMar { my Create $properties(cellMargins) } my Create $properties(table3) } } method TblStylePr {conditionData} { set values { wholeTable firstRow lastRow firstCol lastCol band1Vert band2Vert band1Horz band2Horz neCell nwCell seCell swCell } foreach {types styledata} $conditionData { foreach type $types { if {$type ni $values} { error "unknown table overwrite style \"$type\", expected\ one of [AllowedValues $values]" } OptVal $styledata "" "" "invalid value to the -conditional option value key $type, expected:" array unset optsknown Tag_w:tblStylePr w:type $type { my PPr my RPr my TblPr my TrPr my TcPr } my CheckRemainingOpts } } } method TcPr {} { my Prepare 1 my OneOffOptions -shading -background Tag_w:tcPr { my Create $properties(cell1) Tag_w:tcBorders { my Create $properties(cellBorders) } my Create $properties(cell2) set value [my EatOption -background ST_HexColor] if {$value ne ""} { Tag_w:shd w:val "clear" w:fill $value } Tag_w:tcMar { my Create $properties(cellMargins) } my Create $properties(cell3) } } method TrPr {} { my Prepare 1 Tag_w:trPr { my Create $properties(row) } } method TStyle {value} { return [my StyleCheck table $value] } method Wt {text} { # Just not exactly that easy. # Handle at least \n \r \t and \f special set pos 0 set end [string length $text] foreach part [split $text "\n\r\t\f"] { set len [string length $part] if {$len} { set atts "" if {[string index $part 0] eq " " || [string index $part end] eq " "} { lappend atts xml:space preserve } Tag_w:t $atts { Text [dom clearString -replace $part] } } incr pos $len switch [string index $text $pos] { "\n" Tag_w:br "\r" Tag_w:cr "\t" Tag_w:tab "\f" {Tag_w:br w:type "page"} } incr pos } } method addXML {node xmlstr} { set doc [dom parse [subst -nocommands -nobackslashes {$xmlstr}]] foreach child [[$doc documentElement] childNodes] { $node appendChild $child } $doc delete } method append {text args} { if {[catch { OptVal $args "text" set p [my LastParagraph] $p appendFromScript { Tag_w:r { my RPr my Wt $text } } my CheckRemainingOpts } errMsg]} { return -code error $errMsg } } method appendTo {id script} { my variable body my variable objectId my variable tablecontext if {![info exists objectId($id)]} { return -code error "Unknown object id '$id'." } set savedbody $body set body $objectId($id) switch [$body localName] { tbl { set savedTablecontext $tablecontext set tablecontext "table" } tc { set savedTablecontext $tablecontext set tablecontext "" } tr { set savedTablecontext $tablecontext set tablecontext "row" } } try { $body appendFromScript { uplevel [list eval $script] } } on error {errMsg opts} { return -code error $errMsg } finally { switch [$body localName] { tbl - tc - tr { set tablecontext $savedTablecontext } } set body $savedbody } } method br {{n 1}} { my ControlChar br $n } method comment {args} { my variable body my variable context if {[catch { OptVal [lrange $args 0 end-1] "" "" lassign [my CreateComment] comment id my CheckRemainingOpts set script [lindex $args end] set savedbody $body set savedcontext $context set body $comment # The nested catch is needed to ensure body is set back if {[catch { uplevel [list eval $script] } errMsg errVals]} { set body $savedbody set context $savedcontext my ProcessErrorinfo "comment" error $errMsg } } errMsg]} { return -code error $errMsg } set body $savedbody set context $savedcontext # Add the comment mark to the document set p [my LastParagraph 1] $p appendFromScript { Tag_w:r { Tag_w:commentReference w:id $id } } return [my GetObjectId comments $comment $id] } method commentrangeend {id args} { my variable body my variable context my variable commentranges if {[catch { OptVal [lrange $args 0 end-1] id script if {![info exists commentranges($id)]} { error "no open comment range with the id '$id'" } lassign [my CreateComment $id] comment id my CheckRemainingOpts set script [lindex $args end] set savedbody $body set savedcontext $context set body $comment # The nested catch is needed to ensure body is set back if {[catch { uplevel [list eval $script] } errMsg errVals]} { set body $savedbody set context $savedcontext my ProcessErrorinfo "commentend" error $errMsg } } errMsg]} { return -code error $errMsg } set body $savedbody set context $savedcontext # Add the comment mark to the document set p [my LastParagraph 1] $p appendFromScript { Tag_w:commentRangeEnd w:id $id Tag_w:r { Tag_w:commentReference w:id $id } } unset commentranges($id) return [my GetObjectId comments $comment $id] } method commentrangestart {{returnvar ""}} { my variable body my variable context my variable commentranges if {$returnvar ne ""} { upvar $returnvar id } set id [my NextId comments] # Add the comment range start mark to the document set p [my LastParagraph 1] $p appendFromScript { Tag_w:commentRangeStart w:id $id } set commentranges($id) "" return $id } method configure {args} { my variable docs my variable ignorable if {[catch { OptVal $args # We need to look if -ignorable was given to be able to # handle the empty string as value. if {[info exists opts(-ignorable)]} { set ignorable [my EatOption -ignorable] my Ignorable } set coreroot [$docs(docProps/core.xml) documentElement] $coreroot appendFromScript { foreach elem { cp:category cp:contentStatus dcterms:created dc:creator dc:description dc:identifier cp:keywords dc:language cp:lastModifiedBy cp:lastPrinted dcterms:modified cp:revision dc:subject dc:title cp:version } { # Hm. According to opc-coreProperties.xsd # cp:keywords should have value elements as # children, but I don't see this in what # libreoffice generates. lassign [split $elem :] prefix option set value [my EatOption -$option] if {$value ne ""} { set attlist "" if {$prefix eq "dcterms"} { set value [W3CDTF $value] lappend attlist xsi:type dcterms:W3CDTF } foreach currentnode [$coreroot selectNodes {*[local-name()=$option]}] { $currentnode delete } ::tdom::fsnewNode $elem $attlist {Text $value} } } } my CheckRemainingOpts } errMsg]} { return -code error $errMsg } } method endnote {args} { if {[catch { set script [lindex $args end] OptVal [lrange $args 0 end-1] "" "script" lassign [my FootnoteEndnote endnote \ [my EatOption -refstyle RStyle] $script] \ id objectId set p [my LastParagraph 1] $p appendFromScript { Tag_w:r { my RPr Tag_w:endnoteReference w:id $id } } my CheckRemainingOpts } errMsg]} { return -code error $errMsg } return $objectId } method field {field {switches ""} args} { my variable docs if {[catch { set nfield [string toupper $field] set values { AUTHOR CREATEDATE DATE FILESIZE NUMPAGES PAGE REF SAVEDATE SECTION SEQ TIME TITLE TOC USERNAME } if {$nfield ni $values} { return -code error "Unknown field type '$field', expected one\ out of [AllowedValues $values]" } set dirtyAttrib "" if {$nfield in {REF SEQ TOC}} { set dirtyAttrib {w:dirty "true"} } if {$switches ne ""} { set nfield "$nfield $switches" } OptVal $args "field switches" set p [my LastParagraph 1] $p appendFromScript { Tag_w:r { my RPr Tag_w:fldChar w:fldCharType "begin" {*}$dirtyAttrib } Tag_w:r { OptVal $args my RPr Tag_w:instrText xml:space preserve { Text "$nfield" } } Tag_w:r { OptVal $args my RPr Tag_w:fldChar w:fldCharType "separate" } Tag_w:r { OptVal $args my RPr Tag_w:fldChar w:fldCharType "end" } } my CheckRemainingOpts } errMsg]} { return -code error $errMsg } } method footer {script {returnvar ""} {objectIdVar ""}} { if {$returnvar ne ""} { upvar $returnvar result } if {$objectIdVar ne ""} { upvar $objectIdVar objectId } if {[catch { lassign [my HeaderFooter footer $script] result objectId } errMsg]} { return -code error $errMsg } return $result } method footnote {args} { if {[catch { set script [lindex $args end] OptVal [lrange $args 0 end-1] "" "script" lassign [my FootnoteEndnote footnote \ [my EatOption -refstyle RStyle] $script] \ id objectId set p [my LastParagraph 1] $p appendFromScript { Tag_w:r { my RPr Tag_w:footnoteReference w:id $id } } my CheckRemainingOpts } errMsg]} { return -code error $errMsg } return $objectId } method header {script {returnvar ""} {objectIdVar ""}} { if {$returnvar ne ""} { upvar $returnvar result } if {$objectIdVar ne ""} { upvar $objectIdVar objectId } if {[catch { lassign [my HeaderFooter header $script] result objectId } errMsg]} { return -code error $errMsg } return $result } method image {file type args} { my variable binparts if {[catch { OptVal $args "file type" if {![file isfile $file] || ![file readable $file]} { error "cannot read file \"$file\"" } if {$type ni {inline anchor}} { error "invalid image type \"$type\" (expected \"inline\" or \"anchor\")" } set imagename image[my NextId image] append imagename [string tolower [file extension $file]] set fd [open $file rb] set binparts(word/media/$imagename) [read $fd] close $fd set rId [my Add2Relationships image media/$imagename] set p [my LastParagraph 1] $p appendFromScript { Tag_w:r { Tag_w:drawing { my Image_$type $rId $file } } } my CheckRemainingOpts } errMsg]} { return -code error $errMsg } } method import {what docxfile} { my variable docs variable ::ooxml::docx::xmlns ::ooxml::ZipOpen $docxfile set rId "" try { switch -glob $what { "styles" { set what "word/styles.xml" } "numbering" { set what "word/numbering.xml" } "header*" - "footer*" { set what "word/$what.xml" } } set thisdoc [::ooxml::ZipReadParse $what] if {$thisdoc eq ""} { return -code error "Part $what not found" } set target [string range $what 5 end] if {[info exists docs($what)]} { $docs($what) delete if {[string range $what 0 4] eq "word/"} { set relsRoot [$docs(word/_rels/document.xml.rels) documentElement] set rId [$relsRoot selectNodes -namespaces [list r $xmlns(rel)] { string(r:Relationship[@Target=$target]) }] } } elseif {[string range $what 0 4] eq "word/"} { set thisrels [::ooxml::ZipReadParse "word/_rels/document.xml.rels"] set relsroot [$thisrels documentElement] set typeurl [$relsroot selectNodes -namespaces [list r $xmlns(rel)] { string(r:Relationship[@Target=$target]/@Type) }] # The typeurl starts with # http://schemas.openxmlformats.org/officeDocument/2006/relationships/ set rId [my Add2Relationships [string range $typeurl 68 end] $target] $thisrels delete } set docs($what) $thisdoc } finally { ::ooxml::ZipClose } return $rId } method jumpto {text name args} { my variable bookmarks if {[catch { OptVal $args "text mark" set p [my LastParagraph 1] $p appendFromScript { Tag_w:hyperlink w:anchor $name { Tag_w:r { my RPr my Wt $text } } } my CheckRemainingOpts } errMsg]} { return -code error $errMsg } if {![info exists bookmarks($name)]} { set bookmarks($name) 0 } } method mark {name} { if {[catch { my markstart $name my markend $name } errMsg]} { return -code error $errMsg } } method markend {name} { my variable bookmarks if {![info exists bookmarks($name)] || $bookmarks($name) == 0} { return -code error "A mark span with the name \"$name\" is\ not started." } if {$bookmarks($name) < 0} { return -code error "The mark with the name \"$name\" is\ already ended." } set p [my LastParagraph 1] $p appendFromScript { Tag_w:bookmarkEnd w:id $bookmarks($name) } set bookmarks($name) "-$bookmarks($name)" } method markstart {name} { my variable bookmarks if {[info exists bookmarks($name)] && $bookmarks($name) > 0} { return -code error "mark \"$name\" is not unique" } set p [my LastParagraph 1] set thisid [my NextId bookmarks] $p appendFromScript { Tag_w:bookmarkStart w:id $thisid w:name $name } set bookmarks($name) $thisid } method numbering {cmd args} { my variable docs variable ::ooxml::docx::properties variable ::ooxml::docx::prefixnslist if {![info exists docs(word/numbering.xml)]} { if {$cmd in {"abstractNumIds" "delete"}} { return } if {$cmd ne "abstractNum"} { return -code error "invalid subcommand \"$cmd\"" } my Add2Relationships numbering numbering.xml set docs(word/numbering.xml) [dom parse { }] $docs(word/numbering.xml) selectNodesNamespaces $prefixnslist } set numbering [$docs(word/numbering.xml) documentElement] switch $cmd { "abstractNum" { if {[llength $args] != 2} { return -code error "wrong # of arguments, expecting abstractNumId " } lassign $args id levelData set style [$numbering selectNodes { w:abstractNum[@w:abstractNumId=$id] }] if {$style ne ""} { error "abstractNum style id $id already exists" } if {[catch { $numbering insertBeforeFromScript { Tag_w:abstractNum w:abstractNumId $id { set levelnr 0 foreach level $levelData { array unset optsknown OptVal $level "option" Tag_w:lvl w:ilvl $levelnr { set start [my EatOption -start] if {$start ne ""} { ST_DecimalNumber $start } else { set start 1 } Tag_w:start w:val $start my Create $properties(abstractNumStyle) my PPr my RPr } if {[catch {my CheckRemainingOpts} errMsg]} { error "level definition $levelnr: $errMsg" } incr levelnr } } } [$numbering selectNodes {w:num[1]}] $numbering appendFromScript { Tag_w:num w:numId $id { Tag_w:abstractNumId w:val $id } } } errMsg]} { return -code error $errMsg } } "abstractNumIds" { return [lsort -integer \ [$numbering selectNodes -list { w:abstractNum string(@w:abstractNumId) }]] } "delete" { if {[llength $args] != 2} { return -code error "wrong number of arguments\ for the subcommand \"delete\", expected\ the numbering type and the ID" } lassign $args type id if {$type ni {abstractNum num}} { return -code error "unknown numbering type \"$type\"" } switch $type { "abstractNum" { foreach node [$numbering selectNodes { w:abstractNum[@w:abstractNumId=$id] }] { $node delete } } "num" { foreach node [$numbering selectNodes { w:num[@w:numId=$id] }] { $node delete } } } } default { return -code error "invalid subcommand \"$cmd\"" } } } method pagebreak {} { my variable body $body appendFromScript { Tag_w:p { Tag_w:r { Tag_w:br w:type "page" } } } } # WordprocessingML has no concept of a page. Rather it groups # paragraphs (the main building block) into "sections". The page # setup of a section is located within the w:p subtree of the last # paragraph of the section. And that settings reach out back over # all w:p subtrees without page setup. method pagesetup {args} { my variable body my variable setuproot my variable pagesetup if {[catch { OptVal $args $setuproot appendFromScript { my SectionCommon } my CheckRemainingOpts } errMsg]} { return -code error $errMsg } [$setuproot lastChild] delete set pagesetup $args } method paragraph {text args} { my variable body if {[catch { OptVal $args "text" $body appendFromScript { Tag_w:p { my PPr Tag_w:r { my RPr my Wt $text } } } my CheckRemainingOpts } errMsg]} { return -code error $errMsg } } method readpart {what file} { my variable docs set fd [::tdom::xmlOpenFile $file] if {[catch {set doc [dom parse -channel $fd]} errMsg]} { close $fd error $errMsg } close $fd if {[info exists docs($what)]} { $docs($what) delete } $doc selectNodesNamespaces $::ooxml::docx::prefixnslist set docs($what) $doc } method replace {from to {where ""}} { my variable docs if {$where eq ""} { set parts [array names docs] } else { set parts "" foreach this $where { if {[info exists docs($this)]} { lappend parts $this } else { lappend parts {*}[array names docs $this] } } } foreach part $parts { set doc $docs($part) foreach text [$doc selectNodes {//w:t/text()[contains(.,$from)]}] { $text nodeValue [string map [list $from $to] [$text nodeValue]] } } } method sectionend {} { my variable body my variable sectionsetup if {$sectionsetup eq ""} { return -code error "no section started" } if {[catch { OptVal $sectionsetup $body appendFromScript { Tag_w:p { Tag_w:pPr { my SectionCommon } } } } errMsg]} { return -code error $errMsg } set sectionsetup "" } method sectionstart {args} { my variable body my variable pagesetup my variable sectionsetup my variable setuproot if {[catch { # This way in any case a (maybe empty) w:sectPr tag (via # SectionCommon) will be created which helps to keep things # sane in case there was no pagesetup and no other section # before. if {$sectionsetup ne ""} { OptVal $sectionsetup } elseif {$pagesetup ne ""} { OptVal $pagesetup } else { OptVal "" } $body appendFromScript { Tag_w:p { Tag_w:pPr { my SectionCommon } } } # No need for CheckRemainingOpts here because only the # already validated options stored in # pagesetup/sectionsetup are used. } errMsg]} { return -code error $errMsg } # Instead of just storing the arguments actually "evaluate" it # her for test to have the error message pointing to the line # with the error and not at the place the given arguments are # evaluated. if {[catch { OptVal $args $setuproot appendFromScript { my SectionCommon } my CheckRemainingOpts } errMsg]} { return -code error $errMsg } foreach child [$setuproot childNodes] { $child delete } set sectionsetup $args } method selectNodes {xpath {part ""} args} { my variable docs if {$part eq ""} { set doc $docs(word/document.xml) } else { if {[info exists docs($part)]} { set doc $docs($part) } elseif {[info exists docs(word/$part)]} { set doc $docs(word/$part) } elseif {[info exists docs(word/$part.xml)]} { set doc $docs(word/$part.xml) } else { return -code error "unknown docx part '$part'" } } $doc documentElement root if {[catch { set result [$root selectNodes {*}$args $xpath] } errMsg]} { return -code error $errMsg } return $result } method settings {args} { my variable docs variable ::ooxml::docx::properties variable ::ooxml::docx::xmlns if {[catch { OptVal $args set create 0 set reset [my EatOption -reset CT_OnOff 0] if {![info exists docs(word/settings.xml)]} { my Add2Relationships settings settings.xml set create 1 } else { if {$reset} { $docs(word/settings.xml) delete set create 1 } } if {$create} { set docs(word/settings.xml) [dom parse { }] $docs(word/settings.xml) selectNodesNamespaces $::ooxml::docx::prefixnslist } set settings [$docs(word/settings.xml) documentElement] $settings lastChild lastchild $settings appendFromScript { my Create $properties(settings) } my CheckRemainingOpts } errMsg]} { return -code error $errMsg } # We only have to rearrange the settings children if there has # been children and new children were appended. # nc = new child if {$lastchild ne "" && [$lastchild nextSibling nc] ne ""} { foreach {opt optdata} $properties(settings) { set tag [lindex $optdata 0] lassign [split [lindex $optdata 0] :] prefix localname set tags($xmlns($prefix):$localname) [incr 1] } # cc = current child $settings firstChild cc # Find the first known child while {$cc ne $nc} { set fqcc [$cc namespaceURI]:[$cc localName] if {[info exists tags($fqcc)]} { set ccind $tags($fqcc) break } $cc nextSibling cc } if {$cc eq $nc} return while {$nc ne ""} { $nc nextSibling nextnc set ncind $tags([$nc namespaceURI]:[$nc localName]) while {$ccind < $ncind && $cc ne $nc} { $cc nextSibling cc set fqcc [$cc namespaceURI]:[$cc localName] if {[info exists tags($fqcc)]} { set cclastind $ccind set ccind $tags($fqcc) if {$ccind < $cclastind} { return -code error "invalid word/settings.xml:\ children are not in order" } } } if {$cc eq $nc} return if {$ccind == $ncind} { # TODO this doesn't handle the cases of multiple # child elements nicely (activeWritingStyle, # attachedSchema and smartTagType) $settings replaceChild $nc $cc } else { $settings insertBefore $nc $cc } set cc $nc set ccind $ncind set nc $nextnc } } } method simplecomment {text args} { if {[catch { OptVal $args "text" lassign [my CreateComment] comment id $comment appendFromScript { Tag_w:p { my PPr Tag_w:r { my RPr my Wt $text } } } my CheckRemainingOpts } errMsg]} { return -code error $errMsg } # Add the comment mark to the document set p [my LastParagraph 1] $p appendFromScript { Tag_w:r { Tag_w:commentReference w:id $id } } } method simplecommentrangeend {id text args} { my variable commentranges if {[catch { OptVal $args "id text" if {![info exists commentranges($id)]} { error "no open comment range with the id '$id'" } lassign [my CreateComment $id] comment $comment appendFromScript { Tag_w:p { my PPr Tag_w:r { my RPr my Wt $text } } } my CheckRemainingOpts } errMsg]} { return -code error $errMsg } # Add the comment mark to the document set p [my LastParagraph 1] $p appendFromScript { Tag_w:commentRangeEnd w:id $id Tag_w:r { Tag_w:commentReference w:id $id } } unset commentranges($id) } method simpletable {tabledata args} { my variable body if {[catch { OptVal $args "tabledata" set firstStyle [my EatOption -firstStyle] set lastStyle [my EatOption -lastStyle] $body appendFromScript { Tag_w:tbl { my TblPr Tag_w:tblGrid { foreach width [my EatOption -columnwidths] { Tag_w:gridCol w:w [ST_TwipsMeasure $width] } } set lastrow [expr {[llength $tabledata] - 1}] for {set i 0} {$i <= $lastrow} {incr i} { set row [lindex $tabledata $i] Tag_w:tr { foreach cell $row { Tag_w:tc { Tag_w:p { if {$i == 0 && $firstStyle ne ""} { Tag_w:pPr { Tag_w:pStyle w:val $firstStyle } } elseif {$i == $lastrow && $lastStyle ne ""} { Tag_w:pPr { Tag_w:pStyle w:val $lastStyle } } Tag_w:r {my Wt $cell} } } } } } } } my CheckRemainingOpts } errMsg]} { return -code error $errMsg } } method style {cmd args} { my variable docs set result "" if {[catch { set styles [$docs(word/styles.xml) documentElement] switch $cmd { "paragraphdefault" { set docDefaults [my GetDocDefault $styles] set pdefault [$docDefaults selectNodes { w:pPrDefault | w:rPrDefault }] foreach this $pdefault { $this delete } # docDefaults has two children in the order: # rPrDefault pPrDefault OptVal $args "paragraphdefault" $docDefaults appendFromScript { Tag_w:rPrDefault { my RPr } Tag_w:pPrDefault { my PPr } } my CheckRemainingOpts } "characterdefault" { set docDefaults [my GetDocDefault $styles] set rdefault [$docDefaults selectNodes w:rPrDefault] foreach this $rdefault { $this delete } # docDefaults has two children in the order: # rPrDefault pPrDefault OptVal $args "characterdefault" $docDefaults insertBeforeFromScript { Tag_w:rPrDefault { my RPr } } [$docDefaults firstChild] my CheckRemainingOpts } "character" - "paragraph" - "table" { if {![llength $args]} { error "missing the style name argument" } set name [lindex $args 0] OptVal [lrange $args 1 end] "$cmd name" # Check for duplicate by display name set style [$styles selectNodes { w:style[@w:type=$cmd][w:name[@w:val=$name]] }] if {$style ne ""} { error "$cmd style \"$name\" already exists" } # Derive styleId: use -styleid if given, otherwise # strip non-alphanumeric characters from the name set styleid [my EatOption -styleid] if {$styleid eq ""} { set styleid [regsub -all {[^[:alnum:]]} $name ""] } if {$styleid eq ""} { error "cannot derive a non-empty styleId from\ \"$name\"; use the -styleid option" } # Check for styleId collision set clash [$styles selectNodes { w:style[@w:type=$cmd and @w:styleId=$styleid] }] if {$clash ne ""} { error "$cmd style with styleId \"$styleid\" already\ exists; use the -styleid option to specify\ a unique ID" } # Resolve -basedon to a valid parent styleId set basedon [my EatOption -basedon] if {$basedon ne ""} { set basedon [my StyleCheck $cmd $basedon] } $styles appendFromScript { Tag_w:style w:type $cmd w:styleId $styleid { Tag_w:name w:val $name if {$basedon ne ""} { Tag_w:basedOn w:val $basedon } if {$cmd in {paragraph table}} { my PPr } my RPr if {$cmd eq "table"} { my TblPr my TrPr my TcPr my TblStylePr [my EatOption -conditional] } } } my CheckRemainingOpts } "ids" { if {[llength $args] != 1} { error "wrong number of arguments, expected the style type" } set type [lindex $args 0] set result [$styles selectNodes -list { w:style[@w:type=$type] string(@w:styleId) }] } "names" { if {[llength $args] != 1} { error "wrong number of arguments, expected the style type" } set type [lindex $args 0] set result [$styles selectNodes -list { w:style[@w:type=$type] string(w:name/@w:val) }] } "deleteByName" - "delete" { if {[llength $args] == 1} { lassign $args type if {$type ni {paragraphdefault characterdefault}} { error "unknown default style type \"$type\"" } } elseif {[llength $args] == 2} { lassign $args type name if {$type ni {paragraph character table}} { error "unknown style type \"type\"" } } else { error "wrong number of arguments for the subcommand \"delete\", expected\ the style type and - if not a default type - the style ID" } switch $type { "paragraphdefault" { foreach node [$styles selectNodes w:docDefaults/w:pPrDefault] { $node delete } } "characterdefault" { foreach node [$styles selectNodes w:docDefaults/w:rPrDefault] { $node delete } } default { if {$cmd eq "delete"} { set nodes [$styles selectNodes { w:style[@w:type=$type and @w:styleId=$name] }] } else { set nodes [$styles selectNodes { w:style[@w:type=$type][w:name[@w:val=$name]] }] } foreach node $nodes { $node delete } } } } default { error "invalid subcommand \"$cmd\"" } } } errMsg]} { return -code error $errMsg } return $result } method tab {{n 1}} { my ControlChar tab $n } method table {args} { my variable body my variable tablecontext set script [lindex $args end] set tablecontext "table" if {[catch { OptVal [lrange $args 0 end-1] "" "script" $body appendFromScript { Tag_w:tbl { my TblPr Tag_w:tblGrid { foreach width [my EatOption -columnwidths] { Tag_w:gridCol w:w [ST_TwipsMeasure $width] } } uplevel [list eval $script] my NextId tables set objectId [my GetObjectId tables [dom fromScriptContext]] } } my CheckRemainingOpts } errMsg]} { set tablecontext "" return -code error $errMsg } set tablecontext "" return $objectId } method tablecell {args} { my variable body my variable tablecontext if {$tablecontext ne "row"} { error "method tablecell called outside of table row script context" } set script [lindex $args end] OptVal [lrange $args 0 end-1] "" "script" set tablecontext "" if {[catch { Tag_w:tc { my TcPr my CheckRemainingOpts set savedbody $body set body [dom fromScriptContext] if {[catch { uplevel [list eval $script] } errMsg errVals]} { set body $savedbody set tablecontext "row" my ProcessErrorinfo "tablecell" error $errMsg } my NextId tablecells set objectId [my GetObjectId tablecells $body] set body $savedbody } } errMsg]} { set tablecontext "row" return -code error $errMsg } set tablecontext "row" return $objectId } method tablerow {args} { my variable tablecontext if {$tablecontext ne "table"} { return -code error "method tablerow called outside\ of table script context" } set tablecontext "row" set script [lindex $args end] OptVal [lrange $args 0 end-1] "" "script" if {[catch { Tag_w:tr { my TrPr my CheckRemainingOpts if {[catch { uplevel [list eval $script] } errMsg errVals]} { my ProcessErrorinfo "tablerow" error $errMsg } my NextId tablerows set objectId [my GetObjectId tablerows [dom fromScriptContext]] } } errMsg]} { set tablecontext "table" return -code error $errMsg } set tablecontext "table" return $objectId } method textbox {args} { my variable body set p [my LastParagraph 1] set script [lindex $args end] if {[catch { OptVal [lrange $args 0 end-1] "" "script" set name [my EatOption -name] if {$name eq ""} { set name "Textbox [my NextId textboxes]" } $p appendFromScript { Tag_w:r { Tag_w:drawing { set anchor [my Anchor $name] } } } $anchor appendFromScript { Tag_a:graphic { Tag_a:graphicData uri "http://schemas.microsoft.com/office/word/2010/wordprocessingShape" { Tag_wps:wsp { Tag_wps:cNvSpPr txBox 1 Tag_wps:spPr { my SpPr_Content } # Optional: # wps:style # wps:extLst Tag_wps:txbx { Tag_w:txbxContent { set savedbody $body set body [dom fromScriptContext] # The nested catch is needed to ensure body is set back if {[catch {uplevel [list eval $script]} errMsg errVals]} { set body $savedbody my ProcessErrorinfo "textbox" error $errMsg } set objectId [my GetObjectId comments $body $name] set body $savedbody } } # Defaults array set bodyPrAtts { rot 0 spcFirstLastPara 0 vertOverflow "overflow" horzOverflow "overflow" vert "horz" wrap "square" lIns 0 tIns 0 rIns 0 bIns 0 numCol 1 spcCol 0 rtlCol 0 fromWordArt 0 anchor "t" anchorCtr 0 forceAA 0 compatLnSpc "1" } array set bodyPrAtts [my CheckedAttlist [my EatOption -bodyAtts] { -rot ST_DecimalNumber -spcFirstLastPara CT_Boolean -vertOverflow ST_TextVertOverflowType -horzOverflow ST_TextHorzOverflowType -vert ST_TextVerticalType -wrap ST_TextWrappingType -lIns ST_Emu -tIns ST_Emu -rIns ST_Emu -bIns ST_Emu -numCol ST_DecimalNumber -spcCol ST_Emu -rtlCol CT_Boolean -fromWordArt CT_Boolean -anchor ST_TextAnchoringType -anchorCtr CT_Boolean -forceAA CT_Boolean -compatLnSpc CT_Boolean } -bodyAtts] Tag_wps:bodyPr {*}[array get bodyPrAtts] } } } } my CheckRemainingOpts } errMsg]} { return -code error $errMsg } return $objectId } method url {text url args} { set rId [my Add2Relationships hyperlink $url] set p [my LastParagraph 1] if {[catch { OptVal $args "text url" $p appendFromScript { Tag_w:hyperlink r:id $rId { Tag_w:r { my RPr my Wt $text } } } my CheckRemainingOpts } errMsg]} { return -code error $errMsg } } method write {file} { my variable body my variable docs my variable binparts my variable pagesetup my variable sectionsetup my variable impPagesetup variable ::ooxml::docx::xmlns # Finalize section and do pagesetup if {$sectionsetup ne ""} { OptVal $sectionsetup if {[catch { $body appendFromScript { Tag_w:p { Tag_w:pPr { my SectionCommon } } } } errMsg]} { return -code error $errMsg } } set sectionsetup "" if {$pagesetup ne ""} { OptVal $pagesetup if {[catch { $body appendFromScript { my SectionCommon } } errMsg]} { return -code error $errMsg } set appendedPageSetup [$body lastChild] } else { if {$impPagesetup ne ""} { $body appendChild $impPagesetup } else { # This keeps things sane in case there was no pagesetup # but sections inbetween. $body appendFromScript { Tag_w:sectPr } } set appendedPageSetup [$body lastChild] } # Initialize zip file set file [string trim $file] if {$file eq {}} { set file {document.docx} } if {[file extension $file] ne {.docx}} { append file .docx } if {[catch {open $file wb} zf]} { error "cannot open file $file for writing" } foreach part [array names docs] { ::ooxml::Dom2zip $zf $docs($part) $part cd count } foreach part [array names binparts] { append cd [::ooxml::add_str_to_archive $zf $part $binparts($part) "" 1] incr count } # Cleanup the appendedPageSetup node in case that after the # document was written more content will be added and than # written again. if {$pagesetup eq "" && $impPagesetup ne ""} { # Detach but preserve for potential re-write $body removeChild $appendedPageSetup } else { $appendedPageSetup delete } # Finalize zip. set cdoffset [tell $zf] set endrec [binary format a4ssssiis PK\05\06 0 0 $count $count [string length $cd] $cdoffset 0] puts -nonewline $zf $cd puts -nonewline $zf $endrec close $zf return } method writepart {what file} { my variable docs if {![info exists docs($what)]} { error "unknown part $what" } set fd [open $file w+] fconfigure $fd -encoding utf-8 $docs($what) asXML -channel $fd close $fd } method xmlparts {{pattern ""}} { my variable docs if {$pattern eq ""} { set pattern * } return [lsort [array names docs $pattern]] } method xpath {xpath {part ""} args} { if {[catch { set result [my selectNodes $xpath $part {*}$args] } errMsg]} { return -code error $errMsg } return $result } } # Include the OOML related methods. source [file join [file dir [info script]] ooxml-docx-math.tcl] package provide ooxml::docx 0.6 ooxml/Makefile.in000644 000765 000024 00000011742 15221541353 014363 0ustar00alexstaff000000 000000 # Makefile.in -- # # If ths is "Makefile.in" then it is a template for a Makefile; to generate # the actual Makefile, run "./configure", which is a configuration script # generated by the "autoconf" program (constructs like "@foo@" will get # replaced in the actual Makefile. # # Copyright (C) 2019 Alexander Schoepe, Bochum, DE # #======================================================================== # Nothing of the variables below this line need to be changed. #======================================================================== SHELL = @SHELL@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ datarootdir = @datarootdir@ libdir = @libdir@ mandir = @mandir@ bindir = @bindir@ DESTDIR = pkglibdir = $(libdir)/@PACKAGE_NAME@@PACKAGE_VERSION@ top_builddir = @abs_top_builddir@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ CYGPATH = @CYGPATH@ #======================================================================== # TCLLIBPATH seeds the auto_path in Tcl's init.tcl so we can test our # package without installing. The other environment variables allow us # to test against an uninstalled Tcl. Add special env vars that you # require for testing here (like TCLX_LIBRARY). #======================================================================== TCL_BIN_DIR = @TCL_BIN_DIR@ TCL_SRC_DIR = @TCL_SRC_DIR@ EXTRA_PATH = $(top_builddir):$(TCL_BIN_DIR) TCLLIBPATH = $(top_builddir) TCLSH_ENV = TCL_LIBRARY=`@CYGPATH@ $(TCL_SRC_DIR)/library` PKG_ENV = LD_LIBRARY_PATH="$(EXTRA_PATH):$(@LD_LIBRARY_PATH_VAR@)" \ PATH="$(EXTRA_PATH):$(PATH)" \ TCLLIBPATH="$(TCLLIBPATH)" TCLSH_PROG = @TCLSH_PROG@ TCLSH = $(PKG_ENV) $(TCLSH_ENV) $(TCLSH_PROG) PKG_TCL_SOURCES = @PKG_TCL_SOURCES@ manifest.txt CONFIG_CLEAN_FILES = Makefile pkgIndex.tcl manifest.txt CLEANFILES = @CLEANFILES@ HAVE_PANDOC = @HAVE_PANDOC@ #======================================================================== # Start of user-definable TARGETS section #======================================================================== # Keep the generated build files in sync with their templates, so that # e.g. a version bump in configure.ac propagates automatically before # any target is built (GNU make re-executes itself after remaking the # Makefile). configure: configure.ac autoconf config.status: configure ./config.status --recheck Makefile: Makefile.in config.status ./config.status Makefile pkgIndex.tcl: pkgIndex.tcl.in config.status ./config.status pkgIndex.tcl manifest.txt: manifest manifest.uuid tools/mkversion.tcl configure.ac $(TCLSH) tools/mkversion.tcl > $@ havepandoc: @if test "${HAVE_PANDOC}" != "yes" ; then \ echo "No pandoc found in the path. Pandoc is needed to" ;\ echo "build the nroff and html versions of the documentation." ;\ fi doc/ooxml.html: doc/ooxml.md @if test "${HAVE_PANDOC}" = "yes" ; then \ pandoc --template doc/ooxml-default.html -f markdown -t html doc/ooxml.md \ --css tcl-docs.css -o doc/ooxml.html;\ fi doc/ooxml.n: doc/ooxml.md @if test "${HAVE_PANDOC}" = "yes" ; then \ pandoc --standalone -f markdown -t man doc/ooxml.md -o doc/ooxml.n ;\ fi doc/ooxml-docx.html: doc/ooxml-docx.md @if test "${HAVE_PANDOC}" = "yes" ; then \ pandoc --template doc/ooxml-default.html -f markdown -t html doc/ooxml-docx.md \ --css tcl-docs.css -o doc/ooxml-docx.html;\ fi doc/ooxml-docx.n: doc/ooxml-docx.md @if test "${HAVE_PANDOC}" = "yes" ; then \ pandoc --standalone -f markdown -t man doc/ooxml-docx.md \ -o doc/ooxml-docx.n ;\ fi doc: havepandoc doc/ooxml.html doc/ooxml.n doc/ooxml-docx.html doc/ooxml-docx.n all: havepandoc manifest.txt doc/ooxml.html doc/ooxml.n install: all $(TCLSH) `@CYGPATH@ $(srcdir)/helper.tcl` cp $(PKG_TCL_SOURCES) pkgIndex.tcl $(pkglibdir) test: $(TCLSH) `@CYGPATH@ $(srcdir)/tests/all.tcl` $(TESTFLAGS) \ -load "package ifneeded ${PACKAGE_NAME} ${PACKAGE_VERSION} [list source [file join `@CYGPATH@ $(srcdir)` $(PACKAGE_NAME).tcl]]" archive: manifest.txt pkgIndex.tcl sh tools/archive.sh @PACKAGE_NAME@ @PACKAGE_VERSION@ $(PKG_TCL_SOURCES) release: archive @echo "" @echo "Release packages for $(PACKAGE_NAME) $(PACKAGE_VERSION) created in uv/:" @ls -l uv/$(PACKAGE_NAME)$(PACKAGE_VERSION)*.zip uv/$(PACKAGE_NAME)$(PACKAGE_VERSION)*.tar.gz @echo "Publish them with: make publish" publish: fossil uv add uv/$(PACKAGE_NAME)$(PACKAGE_VERSION).zip --as $(PACKAGE_NAME)$(PACKAGE_VERSION).zip fossil uv add uv/$(PACKAGE_NAME)$(PACKAGE_VERSION).tar.gz --as $(PACKAGE_NAME)$(PACKAGE_VERSION).tar.gz fossil uv add uv/$(PACKAGE_NAME)$(PACKAGE_VERSION)-src.tar.gz --as $(PACKAGE_NAME)$(PACKAGE_VERSION)-src.tar.gz fossil uv add uv/download.html --as download.html fossil uv sync fossil uv list clean: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) -rm -rf doc/ooxml.html doc/ooxml.n doc/ooxml-docx.html doc/ooxml-docx.n distclean: clean -rm -f $(CONFIG_CLEAN_FILES) -rm -rf autom4te.cache -rm -f config.cache config.log config.status .PHONY: install test archive release publish clean distclean ooxml/aclocal.m4000644 000765 000024 00000000224 14764622263 014162 0ustar00alexstaff000000 000000 # # Include the TEA standard macro set # builtin(include,tclconfig/tcl.m4) # # Add here whatever m4 macros you want to define for your package # ooxml/CLAUDE.md000664 000765 000024 00000013040 15221557734 013602 0ustar00alexstaff000000 000000 # ooxml - ECMA-376 Office Open XML File Formats ## Project Overview Pure Tcl extension for ECMA-376 Office Open XML: reads and writes `.xlsx` spreadsheets (Excel 2007+) and creates `.docx` word processing documents. Version 1.13. Developed by Alexander Schoepe, with contributions by Rolf Ade, Harald Oehlmann and Miguel Bañón. The docx subsystem was developed by Rolf Ade. Repository hosted on Fossil at https://fossil.sowaswie.de/ooxml (not Git). ## Tech Stack - **Language:** Tcl 8.6.7+ - **Dependencies:** tdom >= 0.9.0 (the docx writer requires tdom >= 0.9.6). Reading xlsx/docx uses a built-in zip reader based on Tcl's core `zlib` command — no external package needed; Tcl 9 `zipfs`, tcllib `zipfile::decode` or tclvfs `vfs::zip >= 1.0.4` serve only as fallbacks for archives the built-in reader cannot handle (ZIP64, encrypted) - **Build system:** TEA (Tcl Extension Architecture) via autoconf - **Documentation:** Pandoc (Markdown -> HTML/man) ## Project Structure - `ooxml.tcl` — xlsx source (package `ooxml`): all xlsx procs and OO methods, plus the shared zip read/write layer (`::ooxml::Zip*`) - `ooxml-docx.tcl` / `ooxml-docx-lib.tcl` / `ooxml-docx-math.tcl` — docx writer (packages `ooxml::docx` and `ooxml::docx::lib`, both versioned separately, currently 0.6); the math file holds the OMML methods - `pkgIndex.tcl.in` — Tcl package index template (`pkgIndex.tcl` is generated by configure) - `configure.ac` / `Makefile.in` — TEA build configuration; `Makefile`, `pkgIndex.tcl` and `manifest.txt` are regenerated automatically when their sources change - `doc/ooxml.md` — xlsx reference (Pandoc markdown, complete command/method reference) - `doc/ooxml-docx.md` — docx reference; `doc/ooxml-docx-dev.md` — developer notes - `examples/` — `xlsx-*.tcl` and `docx-example*.tcl` example scripts, each annotated with the features it covers - `tests/` — tcltest suite (28 `.test` files, `xlsx-*` and `docx-*`, ~570 tests + fixtures), entry point `tests/all.tcl` - `tools/` — Helper scripts; see `tools/BUILD-PACKAGE.md` for the release workflow, `tools/mkversion.tcl` (build info), `tools/archive.sh` (packaging), `tools/createTypeCode.tcl` (XSD enum -> Tcl type check procs) - `claude/skills/ooxml/SKILL.md` — Claude skill covering both subsystems; keep in sync with API changes - `uv/` — HTML download templates and locally built release artifacts (not versioned) - `manifest` / `manifest.uuid` — Fossil SCM manifest (requires `fossil settings manifest on`) ## Key API xlsx (package `ooxml`): - `::ooxml::xl_sheets file` — List sheets in an xlsx file - `::ooxml::xl_read file ?args?` — Read xlsx into a Tcl array - `::ooxml::xl_write new ?args?` — Create spreadsheet object with methods: `numberformat`, `font`, `fill`, `border`, `style`, `worksheet`, `column`, `row`, `cell`, `autofilter`, `freeze`, `printarea`, `merge`, `rowheight`, `pageSetup`, `pageMargins`, `view`, `presetstyles`, `presetsheets`, `write` - `::ooxml::tablelist_to_xl` — Export Tk tablelist widget to xlsx - Helpers: `arrayDeleteSheet`, `RowColumnToString`, `StringToRowColumn`, `Column`, `CalcColumnWidth`, `Default` docx (package `ooxml::docx`): - `::ooxml::docx::docx new ?options? ?template.docx?` — Create document object; methods for paragraphs, character/paragraph styles, tables, images, headers/footers, footnotes/endnotes, comments, fields, hyperlinks/bookmarks, numbering, textboxes, OMML math, settings, plus power tools `appendTo`, `addXML`, `replace`, `import`, `xmlparts`, `selectNodes`/`xpath` ## Build, Test & Release ```sh ./configure make test # Run tcltest suite make install # Install to Tcl lib path (respects ./configure --prefix) make doc # Generate HTML + man pages for both references (requires pandoc) make release # Build the download packages into uv/ (resolves all prerequisites) make publish # Upload the packages to the Fossil unversioned space (fossil uv) ``` Release workflow: see `tools/BUILD-PACKAGE.md`. Version bump = two places: `AC_INIT` in `configure.ac` and `package provide ooxml` in `ooxml.tcl` (the docx subpackage versions live in `ooxml-docx.tcl`, `ooxml-docx-lib.tcl` and `pkgIndex.tcl.in`). Write an `ANNOUNCE` (bilingual EN/DE, changes since the previous release tag from the Fossil timeline). ## Fossil Specifics - Check-ins: short English commit texts; tickets referenced as `[ticket-id]`, check-ins as `[checkin-id]` (auto-linked) - Wiki pages (Markdown mimetype): `ooxml` (start page), `man-xlsx` (from `doc/ooxml.md`, strip the Pandoc `%` title line), `man-docx` (from `doc/ooxml-docx.md`), `examples`, `tools` — update via `fossil wiki commit -M markdown`, then `fossil sync` (wiki commits do not reliably autosync) - Tickets: `fossil ticket show/history/change`; append comments with `+comment` using the `
alex added on UTC:
` header convention - Release artifacts live in the unversioned space (`fossil uv add --as `, `fossil uv sync`); keep only the current version's packages there ## Conventions - Indices (row, column, sheet) are zero-based throughout the API - Colors accept named colors, RGB/ARGB hex, or numeric indices 0-65 - Cell references use Excel-style notation (e.g., "A1") convertible via `RowColumnToString`/`StringToRowColumn` - xlsx changes go into `ooxml.tcl`, docx changes into the `ooxml-docx*.tcl` files - docx option values are type checked; type check procs for XSD enums are generated with `tools/createTypeCode.tcl` - After API changes: update `doc/ooxml.md` / `doc/ooxml-docx.md`, the wiki pages and `claude/skills/ooxml/SKILL.md` - BSD 3-clause license ooxml/doc/ooxml-docx.html000644 000765 000024 00000125032 15221547620 016043 0ustar00alexstaff000000 000000 ooxml-docx(n) | ooxml user documentation

ooxml-docx(n) | ooxml user documentation

NAME

::ooxml::docx - Create ECMA-376 Office Open XML writer documents (the .docx format)

SYNOPSIS

package require ooxml::docx
::ooxml::docx::docx new *?-option value ...?* ?docx-file?

DESCRIPTION

The command ::ooxml::docx creates a new docx object.

Without the optional file argument the object represents an almost minimal empty document.

If the last argument is an ECMA-376 Office Open XML WordprocessingML document (vulgo a .docx file) the inital document is a copy of this .docx.

The object has methods to append and style content as text, tables, pictures or textboxes. The .docx file created by the object can be read by word processing programs as libreOffice or Word.

A simple “Hello, World” example is:

set docx [ooxml::docx::docx new]
$docx paragraph "Hello, World!"
$docx write hello.docx
$docx destroy

The style and appearance of the content is determined in order by local setting, by referencing to a defined style or finally by the default settings.

The methods of a docx object typically expect, if ever, a few arguments required in order and after that option value pairs. The options may appear in any order. An unknown option is reported as error. If an option is given more than one time then the last one wins.

The value of an option is - depending on the option - either a single value or a key value list. In the second case the key value pairs may be in any order. If a key is given more than one time then the last one wins. An unknown key is reported as error. In almost all cases the value given to the option or key will be type checked.

Content to the document is added top down.

The created docx object commands currently support the following methods:

append text ?-option value …?

Appends text to the last paragraph of the content of the document. The option/value pairs control the appearance of the text within the paragraph. See CHARACTER OPTIONS for the valid options and the type of their value.

appendTo objectId creatingScript

This method appends content to an already created table, table row table cell, footer, header, footnote, endnote, comment or textbox. The objectId has to be the id returned by the method which created the object. The creatingScript is evaluated and creates the appended object content. The resulting document is the same as if the creatingScript would have been appended to the creatingScript of the method which created the object.

br ?n?

Inserts a line break into the current paragraph. The optional argument n (default 1) specifies the number of breaks to insert.

comment ?-option value …? creatingScript

This method creates a comment to the current point in the document with comment content created by the creatingScript and returns the object id of the created comment. Although the standard allows much more rich content most word processor support only basic text formatting for comments.

The allowed options are

  -author string

  -date <xsd datetime>

  -initials string
commentrangeend id ?-option value …? creatingScript

This method marks the end of a range of content in the document and creates a comment to this content range with comment content created by the creatingScript and returns the object id of the created comment. The id argument must be the id returned by the corresponding commentrangestart call. For the allowed options see the method comment.

commentrangestart ?returnvar?

This method marks the start of a range of content in the document for which a comment should be added. The method returns the id of the range and stores the id additionally in the variable with the name resultvar, if the optional argument is given.

destroy

Destroys the docx object and releases all associated DOM documents and resources. Inherited from TclOO.

configure ?-option value …?

Set certain document properties. The recognized options are:

  -category

  -contentStatus

  -created

  -creator

  -description

  -identifier

  -ignorable prefixList: Set the MC Ignorable prefixes (e.g. "w14 wp14").

  -keywords

  -language

  -lastModifiedBy

  -lastPrinted

  -modified

  -revision

  -subject

  -title

  -version
endnote ?-option value …? creatingScript

Creates an endnote with content produced by creatingScript and returns the object id of the created endnote. A reference mark is inserted at the current position in the document. The allowed options are:

-refstyle styleRef: Character style applied to the reference mark. The value may be either the internal style ID (w:styleId) or the display name (w:name).

The other -option value pairs allows formatting of the (whole) endnote value. See CHARACTER OPTIONS for the valid options and the type of their value.

field field-type ?switches? ?-option value …?

Appends the given field type to the last paragraph. Recognized field types are

      AUTHOR
      CREATEDATE
      DATE
      FILESIZE
      PAGE
      NUMPAGES
      SAVEDATE
      SECTION
      TIME
      TITLE
      USERNAME

If the optional argument switches is given its value will be appended as the field switches to the field-type name. The following optional -option value pairs allows formatting of the (whole) inserted field value. See CHARACTER OPTIONS for the valid options and the type of their value.

footnote ?-option value …? creatingScript

Creates a footnote with content produced by creatingScript and returns the object id of the created footnote. A reference mark is inserted at the current position in the document. The allowed options are:

  -refstyle styleRef: Character style applied to the reference
  mark. The value may be either the internal style ID (*w:styleId*)
  or the display name (*w:name*).

footer creatingScript ?returnvar? ?objectIdvar? header creatingScript ?returnvar? ?objectIdvar?

: Creates a new footer or header by evaluating the creating script. The id of the created footer or header is returned and, if given, stored in the returnvar. This is the id to refer to the footer or header to be used with the options -defaultHeader, -firstHeader, -evenHeader, -defaultFooter, -firstFooter and -evenFooter of the methods pagesetup and sectionstart. The object id of the created footer or header is stored in the objectIdvar, if given. This is the id to use with the method appendTo.

image file anchor|inline ?-option value …?

An inline image is part of the text, like a character (and therefore may change the line height). An anchor image is also anchored at an exact place within the text (which determines the page at which the image is shown) but can be freely placed at the page.

Both types of images share the following options:

 -dimension *keyValueList*: Required. Sets the image size. Keys:
     width (EMU), height (EMU).

 -bwMode *(auto|black|blackGray|blackWhite|clr|gray|grayWhite|
     hidden|invGray|ltGray|white)*: Black-and-white mode
     (default "auto").

Anchor images additionally accept:

 -anchorData *keyValueList*: Anchor attributes. Keys: behindDoc,
 distT, distB, distL, distR, hidden, locked, layoutInCell,
 allowOverlap, relativeHeight.

 -positionH *relativeFrom*: Horizontal position reference
 (column, character, insideMargin, leftMargin, margin, outsideMargin,
 page, rightMargin). Default "column".

 -alignH *(left|right|center|inside|outside)*: Horizontal alignment
 (mutually exclusive with -posOffsetH).

 -posOffsetH *EMU*: Horizontal offset (mutually exclusive with
 -alignH).

 -positionV *relativeFrom*: Vertical position reference (insideMargin,
 line, margin, outsideMargin, page, paragraph, topMargin,
 bottomMargin). Default "paragraph".

 -alignV *(inline|top|center|bottom|inside|outside)*: Vertical
 alignment (mutually exclusive with -posOffsetV).

 -posOffsetV *EMU*: Vertical offset (mutually exclusive with -alignV).

 -wrapMode *(none|square|topBottom)*: Text wrapping mode (default
 "none").

 -wrapData *keyValueList*: Wrap attributes (only with -wrapMode
 square). Keys: wrapText, distT, distB, distL, distR.
import part docx

Imports the given part from the file docx into the docx object, replacing what the object had for that part of the docx zip archive.

The shortcut “styles” may be used for word/styles.xml and “numbering” for word/numbering.xml.

jumpto text markid ?-option value …?

Appends the text text to the last paragraph and if the text is clicked as link (typically Ctrl-Button-1) the text processor jumps to the mark with the id markid inside the document.

The option/value pairs control locally the appearance of the text within the paragraph. See CHARACTER OPTIONS for the valid options and the type of their argument.

mark markid

Sets the mark markid at the end of the last paragraph.

markstart name

Starts a named bookmark span at the current position. The bookmark name must be unique within the document. Use markend to close the span.

markend name

Ends the bookmark span previously opened by markstart with the same name.

math ?-option value …? creatingScript

Creates a math zone. The creatingScript creates the math content using the math methods described below. By default the math is inline within the current paragraph. Options:

     -display *onOffValue*: If on, the math is rendered as a display
     equation on its own paragraph.

     -jc *(left|center|right|centerGroup)*: Justification of a display
     equation. Ignored when -display is off.

Inside the creatingScript, the following math methods are available. All math methods must be called from within the creatingScript of a math call; calling them outside a math zone raises a Tcl error. Invalid option values also raise a Tcl error.

mrun ?-option value …? text

Creates a math run (text within a math zone). Options:

  -lit *onOffValue*: Literal (non-italic) text.

  -sty *(p|b|i|bi)*: Math style (plain, bold, italic, bold-italic).

  -scr *(roman|script|fraktur|double-struck|sans-serif|monospace)*:
  Math font script.

  -nor *onOffValue*: Normal text (non-math font). Mutually exclusive
  with -sty/-scr.

  -aln *onOffValue*: Alignment point.

  -brk *onOffValue*: Line break. -brkAt *integer*: alignment position
  after break.
mfrac ?-option value …? numeratorScript denominatorScript

Creates a fraction. The two scripts create the numerator and denominator content. Options:

     -type *(bar|lin|noBar|skw)*: Fraction type. Defaults to bar (stacked
     with horizontal rule). *lin* gives a linear (inline slash) form,
     *noBar* stacked without bar, *skw* skewed.
msub baseScript subscriptScript

Creates a subscript construct.

msup baseScript superscriptScript

Creates a superscript construct.

msubsup baseScript subscriptScript superscriptScript

Creates a simultaneous sub-superscript construct.

msqrt radicandScript

Creates a square root.

mroot degreeScript radicandScript

Creates an nth-root. The degreeScript produces the root index (e.g. 3 for cube root) and radicandScript the expression under the radical.

mnary ?-option value …? baseScript

Creates an n-ary operator (summation, product, integral, etc.). Options:

  -char *string*: The operator character (e.g. "∑", "∏", "∫").

  -limLoc *(undOvr|subSup)*: Limit placement — under/over or
  sub/superscript position.

  -grow *onOffValue*: Whether the operator grows with its content.

  -sub *script*: Subscript (lower limit) content script.

  -sup *script*: Superscript (upper limit) content script.

  -subHide *onOffValue*: Hide the subscript.

  -supHide *onOffValue*: Hide the superscript.
mfunc nameScript argumentScript

Creates a function application construct (e.g. sin, cos, lim).

mlimlow baseScript lowerLimitScript

Creates a lower-limit construct (limit below the base).

mlimupp baseScript upperLimitScript

Creates an upper-limit construct (limit above the base).

maccent ?-option value …? baseScript

Creates an accent construct — places a diacritical mark (hat, tilde, dot, vector arrow, etc.) above the base expression.

  -char *string*: The accent character. Default is the combining
  circumflex accent (U+0302). Common values:
  U+0303 (tilde), U+0307 (dot), U+0308 (double dot),
  U+20D7 (combining right arrow / vector).
mbar ?-option value …? baseScript

Creates an overline or underline bar above or below the base.

  -pos *top|bot*: Position of the bar (default "top" = overline).
mdelim ?-option value …? script

Creates a delimiter construct — wraps content in matching delimiters such as parentheses, brackets, braces, absolute-value bars, norms, floor/ceiling symbols, etc.

The script body creates the content. For a single argument, math methods in the script create content directly within an m:e element. For multiple arguments separated by the separator character, use mdelimarg within the script.

  -begChr *string*: Opening delimiter character (default "(")
  -endChr *string*: Closing delimiter character (default ")")
  -sepChr *string*: Separator character between arguments (default "|")
  -grow *onOffValue*: Delimiters grow to match content height
  -shp *centered|match*: Delimiter shape
mdelimarg script

Creates a delimiter argument (m:e child) inside an enclosing mdelim. Each call to mdelimarg wraps its script content in a separate m:e element, enabling multi-argument delimiters.

mgroupchr ?-option value …? baseScript

Creates a grouping character construct — an underbrace, overbrace, or similar character that spans the base expression. Commonly used to label parts of an equation.

  -char *string*: The grouping character (default U+23DF = ⏟ bottom
  curly bracket). Use U+23DE for overbrace (⏞).
  -pos *top|bot*: Position of the character (default "bot")
  -vertJc *top|bot*: Vertical justification of the base relative to
  the grouping character
mmatrix ?-option value …? rowScripts

Creates a matrix. The rowScripts argument is a list; each element is a script that creates cells via mmatcell calls. Wrap in mdelim for bracket/parenthesis notation.

  -baseJc *top|center|bottom*: Vertical alignment of the matrix
  relative to the math baseline
  -mcJc *left|center|right*: Column justification
  -count *integer*: Number of adjacent columns sharing the
  justification (1–255)
mmatcell script

Creates a matrix cell (m:e child) inside a matrix row. Each call wraps its script content in a separate m:e element.

numbering subcmd args

Manages numbering definitions (lists, outlines).

The supported subcommands are:

abstractNum id levelDefinitions: Creates an abstract numbering definition with the given integer id. The levelDefinitions argument is a list; each element defines one level using option/value pairs:

  -numberFormat *format*: Numbering format (decimal, upperRoman,
  lowerRoman, upperLetter, lowerLetter, bullet, etc.)
  -levelText *string*: Level text template (e.g. "%1." or "%1.%2")
  -align *alignment*: Number alignment (start, center, end, etc.)
  -start *integer*: Starting number (default 1)

Paragraph and character options may also be given per level to style the number and the paragraph.

A corresponding w:num entry is automatically created with the same numId as the abstractNumId.

Example:

   $doc numbering abstractNum 0 {
       {-numberFormat decimal -levelText "%1." -align start}
       {-numberFormat lowerLetter -levelText "%2)" -align start}
   }

abstractNumIds: Returns a sorted list of all abstractNum IDs.

delete type id: Deletes a numbering definition. type is either abstractNum or num; id is the integer ID.

pagebreak

Appends a page break to the document.

pagesetup ?-option value …?

The allowed options are:

  -margins keyValueList

  -paperSource keyValueList

  -sizeAndOrientation keyValueList

  -defaultHeader id
  -defaultFooter id
  -firstHeader id
  -firstFooter id
  -evenHeader id
  -evenFooter id

The last block of options set the respectively header or footer. The id has to be returned from a header or footer method call.

   -border

   -pageNumbering

  -sectionType *(continuous|evenPage|nextColumn|nextPage|oddPage)*

Specifies the type of the current section break. The default is nextPage. Use continuous to start a new section on the same page (e.g. for switching between single and multi-column layout).

  -docGrid *keyValueList*

Configures the document grid for the section, controlling line pitch and character spacing for CJK and other layout needs. The accepted keys are:

  type        Grid type: "default", "lines", "linesAndChars",
              or "snapToChars".
  linePitch   Distance between lines (integer, in twips).
  charSpace   Additional character pitch (integer, in 4096ths
              of a point).

  -vAlign *(top|center|bottom|both)*

Vertical alignment of text on the page. The value both distributes text evenly between the top and bottom margins (justified).

paragraph text ?-pstyle style? ?-cstyle style? ?-option value …?

Appends text as paragraph to the content of the document. If the -pstyle option is given, the referenced paragraph style will be used. If the -cstyle option is given the referenced character style will be used. Style values may be given either as the internal style ID (w:styleId) or as the display name (w:name). Resolution prefers an exact style-ID match and falls back to the display name. The other options may locally overwrite a style setting or add more properties. See PARAGRAPH OPTIONS and CHARACTER OPTIONS for the valid options and the type of their argument.

readpart part filename

Replaces the named XML part in the docx object with the contents of filename. The file is parsed as XML and replaces the in-memory DOM for that part. Example:

$doc readpart word/settings.xml mysettings.xml
replace from to ?part_list?

Replaces every from substring in any text with to, Only uniformly styled text is replaced (if from spans over more than one text part it will not be recognized). Without the optional part list argument all parts of the document (the main documentbody, footnotes, comments pp.) will be processed. If the argument is given then only the named parts will be processed. The elements of the part list may be a Tcl glob expression. Part names given by the part list argument which are currently not exists in the object will be silently ignored.

sectionend

Ends the current section, emitting the stored section properties as a w:sectPr inside the last paragraph. Must be preceded by a sectionstart call; raises an error otherwise.

sectionstart ?-option value …?

Starts a new section in the document. If a previous section was already started (and not ended), it is implicitly ended first. The allowed options are the same as for pagesetup: -margins, -sizeAndOrientation, -sectionType, -docGrid, -vAlign, -border, -pageNumbering, header/footer references, etc.

settings ?-option value …?

Modifies the document settings (word/settings.xml). Settings may be called multiple times; each call updates or adds the specified settings without affecting those set by earlier calls.

Special option:

      -reset *onOffValue*: If on, resets all settings to defaults before
      applying the remaining options.

Commonly used settings:

     -defaultTabStop *integer*: Default tab stop distance in twips.
     -autoHyphenation *onOffValue*: Enable automatic hyphenation.
     -evenAndOddHeaders *onOffValue*: Use different headers/footers for
     even and odd pages.
     -hideSpellingErrors *onOffValue*: Hide red squiggly underlines.
     -hideGrammaticalErrors *onOffValue*: Hide grammar error marks.
     -trackRevisions *onOffValue*: Enable revision tracking.
     -mirrorMargins *onOffValue*: Mirror left/right margins for
     facing pages.
     -embedTrueTypeFonts *onOffValue*: Embed TrueType fonts.
     -documentProtection *keyValueList*: Protect the document.
     Keys: edit (readOnly|comments|trackedChanges|forms|none),
     enforcement (on|off), formatting (on|off), plus optional
     cryptographic parameters.

Many more settings are available. On/off settings use onOffValue. Refer to the property table in the source for the complete list.

selectNodes xpath ?part? ?selectNodes options?

Returns the result of the xpath expression. If no other argument is given the context node will be the document element node of the word/document.xml part of the docx. If the part argument is given the context node of the expression will be the document element of the docx part identified by this argument. If part is a relative path inside the docx zip (example: _rels/.rels) then this is used. All parts of the docx inside the word directory may specified without the directory part and the .xml suffix. The optional selectNodes options are routed throw.

All documents accessible by this have the following prefix namespace mappings predefined:

Prefix Namespace
a http://schemas.openxmlformats.org/drawingml/2006/main|
ct http://schemas.openxmlformats.org/package/2006/content-types|
m http://schemas.openxmlformats.org/officeDocument/2006/math|
mc http://schemas.openxmlformats.org/markup-compatibility/2006|
o urn:schemas-microsoft-com:office:office|
pic http://schemas.openxmlformats.org/drawingml/2006/picture|
r http://schemas.openxmlformats.org/officeDocument/2006/relationships|
rel http://schemas.openxmlformats.org/package/2006/relationships|
sl http://schemas.openxmlformats.org/schemaLibrary/2006/main|
v urn:schemas-microsoft-com:vml|
w http://schemas.openxmlformats.org/wordprocessingml/2006/main|
w10 urn:schemas-microsoft-com:office:word|
w14 http://schemas.microsoft.com/office/word/2010/wordml|
wp http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing|
wp14 http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing|
wpg http://schemas.microsoft.com/office/word/2010/wordprocessingGroup|
wps http://schemas.microsoft.com/office/word/2010/wordprocessingShape|
simplecomment comment ?-option value …?

This method creates a comment to the current point in the document. The text content of the comment will be what is given by the argument comment. For the allowed options see the method comment. Additionally to this options all PARAGRAPH OPTIONS and CHARACTER OPTIONS are allowed. If given they are applied to format the comment text.

simplecommentrangeend id comment ?-option value …?

This method marks the end of a range of content in the document and creates a comment to this content range with comment content given by the comment argument. The id argument must be the id returned by the corresponding commentrangestart call. For the allowed options see the method comment. Additionally to this options all PARAGRAPH OPTIONS and CHARACTER OPTIONS are allowed. If given they are applied to format the comment text.

simpletable tabledata ?-option value …?

Creates a table from a nested list. Each element of tabledata is a row; each element within a row is a cell’s text content.

Example: $doc simpletable {{A1 B1 C1} {A2 B2 C2}}

Options:

  -columnwidths *list*: Column widths (measurements).
  -firstStyle *styleName*: Character style for the first row.
  -lastStyle *styleName*: Character style for the last row.

Table-level options (-style, -width, -align, -layout, -look, -tableBorders, cell margins) are also accepted — see table.

style subcommand args

The supported subcommands are:

  paragraphdefault ?-option value ...?

  characterdefault ?-option value ...?

  paragraph name ?-option value ...?

  character name ?-option value ...?

  table name ?-option value ...?

The *name* argument is the display name of the style. The
internal style ID (w:styleId) is derived from the name by
stripping non-alphanumeric characters. Use the **-styleid**
option to set the internal ID explicitly if the derived ID
would be empty or ambiguous. Both display name and derived ID
must be unique within the style type.

Additional style creation options:

   -basedon styleRef:

Parent style to inherit from. Accepts
either an internal style ID or a display name (resolved to a
style ID internally). The parent must be the same type as the
style being created.

  -conditional keyValueList:

(Table styles only.) Conditional formatting for table regions such as firstRow, lastRow, firstColumn, lastColumn, band1Vert, band1Horz, etc.

All methods and options that reference a style (such as
**-pstyle**, **-cstyle**, **-style**, **-basedon**,
**-refstyle**) accept either the internal style ID (preferred,
tried first) or the display name (fallback).

  ids styletype

  names styletype

  delete styletype name
tab ?n?

Inserts a tab character into the current paragraph. The optional argument n (default 1) specifies the number of tabs to insert.

table ?-option value …? creatingScript

Creates a table by defining every row and cell individually by the creatingScript and returns the object id of the created table. The recognized options are:

  -columnwidths *list*: List of column widths (measurements).

  -style *styleRef*: Table style reference (style ID or display name).

  -width *keyValueList*: Table width. Keys: type (auto|dxa|pct|nil),
  value (measurement or percentage).

  -align *(center|end|left|right|start)*: Table alignment.

  -layout *keyValueList*: Table layout. Keys: type (autofit|fixed).

  -look *keyValueList*: Table conditional formatting flags. Keys:
  firstRow, lastRow, firstColumn, lastColumn, noHBand, noVBand
  (all on/off).

  -caption *string*: Table caption for accessibility.

  -tableBorders: Table border options. For each border position
  (top, left, bottom, right, insideH, insideV), use
  `-<position>Border {type <borderType> color <hex> borderwidth <eighthPts> space <pts>}`.

  -cellMarginTop, -cellMarginStart, -cellMarginLeft,
  -cellMarginBottom, -cellMarginEnd, -cellMarginRight:
  Default cell margins. Each takes a *keyValueList* with keys
  type and value.
tablecell ?-option value …? creatingScript

Creates a table cell within a tablerow script and returns the object id of the created table cell. The creatingScript creates the cell content (paragraphs, nested tables, etc.).

Options:

  -cellWidth *keyValueList*: Cell width. Keys: type (auto|dxa|pct|nil),
  value (measurement or percentage).

  -span *integer*: Number of grid columns this cell spans.

  -hspan *(restart|continue)*: Horizontal merge state.

  -vspan *(restart|continue)*: Vertical merge state.

  -vAlign *(top|center|bottom|both)*: Vertical alignment of cell
  content.

  -textDirection *direction*: Text direction within the cell.

  -shading *keyValueList*: Cell shading pattern. Keys: type, color,
  fill (same as paragraph shading). The options -shading and
  -background are mutually exclusive.

  -background *RRGGBB*: Shorthand for a solid background fill color.
  The options -shading and -background are mutually exclusive.

  -tcFitText *onOffValue*: Shrink text to fit cell width.

Cell border options (-topBorder, -leftBorder, -bottomBorder, -rightBorder, -tl2brBorder, -tr2blBorder) and cell margin options are also accepted.

tablerow ?-option value …? creatingScript

Creates a table row within a table script and returns the object id of the created table row. The creatingScript creates cells via tablecell calls.

Options:

  -rowHeight *keyValueList*: Row height. Keys: value (measurement),
  hRule (auto|exact|atLeast).

  -headerrow *onOffValue*: Mark this row as a header row that repeats
  on each page.

  -cantSplit *onOffValue*: Prevent the row from splitting across
  pages.

  -align *(center|end|left|right|start)*: Row alignment (overrides
  table alignment).

  -cellSpacing *keyValueList*: Cell spacing within the row. Keys:
  type, value.

  -wBefore, -wAfter *keyValueList*: Width before/after the row
  (for indented rows). Keys: type, value.
textbox ?-option value …? creatingScript

Creates an anchored text box at the current position and returns the object id of the created text box. The creatingScript creates the text box content (paragraphs, tables, etc.) inside the box.

Options:

   -name *string*: Display name for the text box shape. Auto-generated
   if omitted.

   -dimension *keyValueList*: Required. Sets the text box size. Keys:
   width (EMU), height (EMU).

   -bodyAtts *keyValueList*: Text body attributes. Keys: wrap
   (none|square), numCol (integer), and other wps:bodyPr attributes.

Anchor positioning options (-anchorData, -positionH, -alignH, -posOffsetH, -positionV, -alignV, -posOffsetV, -wrapMode, -wrapData, -bwMode) are also accepted — see image anchor options.

url text url ?-option value …?

Append text to the current paragrah and make that text an hypherlink to uri. The option/value pairs control the appearance of the text within the paragraph. See CHARACTER OPTIONS for the valid options and the type of their value.

write ?filename?

Writes the object as WordprocessingML docx file to filename. If the argument is omitted then document.docx will be used. If the filename does not have a suffix, then the suffix .docx will be appended.

writepart part filename

Writes a single XML part from the docx object to filename. Raises an error if the part does not exist in the object.

xpath xpath ?part? ?selectNodes options?

An alias for the method selectNodes. See there for the meaning of the arguments.

xmlparts ?pattern?

Returns the paths of the xml parts of the docx object. If the optional argument pattern is given only the xml parts of the docx docx object which match the pattern using glob style matching are returned.

CHARACTER OPTIONS

-bold onOffValue

-color auto|RRGGBB hex value

-cstyle styleRef

-dstrike onOffValue

-emboss onOffValue

-font font familiy name

-fontsize measure

If the value has no unit the integer means twentieths of a point.

-highlight (black|blue|cyan|green|magenta|red|yellow|white|darkBlue|darkCyan|darkGreen|darkMagenta|darkRed|darkYellow|darkGray|lightGray|none)

-italic onOffValue

-noProof onOffValue

-rtl onOffValue

-strike onOffValue

Toggles strikethrough on the text.

-underline kind

The allowed kind values are:

single
words
double
thick
dotted
dottedHeavy
dash
dashedHeavy
dashLong
dashLongHeavy
dotDash
dashDotHeavy
dotDotDash
dashDotDotHeavy
wave
wavyHeavy
wavyDouble
none

-verticalAlign *(baseline|superscript|subscript)

PARAGRAPH OPTIONS

-align kind

The allowed kind values are:

start
center
end
both
mediumKashida
distribute
numTab
highKashida
lowKashida
thaiDistribute
left
right

-background RRGGBB hex value

Sets a solid background fill color on the paragraph. This is a shorthand for -shading {type clear fill RRGGBB}.

-bidi onOffValue

Right-to-left paragraph direction.

-indentation keyValueList

Sets the paragraph indentation. The accepted keys are:

start           Left/start indentation (measurement).
startChars      Left/start indentation in character units.
end             Right/end indentation (measurement).
endChars        Right/end indentation in character units.
firstLine       First line additional indent (measurement).
firstLineChars  First line indent in character units.
hanging         Hanging indent (measurement).
hangingChars    Hanging indent in character units.

-keepLines onOffValue

Keep all lines of the paragraph on the same page.

-keepNext onOffValue

Keep the paragraph on the same page as the next paragraph.

-level integer

Numbering level (used with -numberingStyle). Zero-based.

-numberingStyle integer

Numbering definition ID to apply to this paragraph.

-pageBreakBefore onOffValue

Start the paragraph on a new page.

-shading keyValueList

Sets the paragraph shading pattern. The accepted keys are:

type    Shading pattern (required). Common values: clear, solid,
        horzStripe, vertStripe, diagStripe, diagCross, pct10,
        pct20, pct25, pct50, pct75, etc.
color   Foreground pattern color (RRGGBB hex or "auto").
fill    Background fill color (RRGGBB hex or "auto").

Example: -shading {type clear fill FFFF00} for a yellow background.

-spacing keyValueList

The value to the option must be a Tcl list of keyword measurement pairs and defines the space before, after and between the lines of the paragraph. The space values are given as measurement

The accepted keys are:

after       Space after the paragraph.
before      Space before the paragraph.
line        Line spacing within the paragraph.
lineRule    How "line" is interpreted: "auto" (default, value
            is in 240ths of a line), "exact" (value is in
            twips), or "atLeast" (minimum, value is in twips).

-suppressLineNumbers onOffValue

Suppress line numbers for this paragraph.

-textframe keyValueList

Configures the paragraph as a text frame. Keys: width, height, wrap, vAnchor, hAnchor, xAlign, yAlign, dropCap, lines, vSpace, hSpace, hrule, anchorLock.

-widowControl onOffValue

Enable widow/orphan control for this paragraph.

OPTION VALUE TYPES

Several option values share the same value types. This types are:

MEASUREMENT

A measurement is given either as integer value without unit or as integer immediately followed by a unit. If the value is just a number then what distance is specified by the number depends on the option and is documented with the option. The allowed units are:

mm
     Millimeter
cm
     Centimeter
in
     Inch (1in = 2.54cm)
pt
     Point (1pt = 1/72in)
pc
     Pica (1pc = 12pt)
pi
     The same as pc: Pica (1pi = 12pt)

DEPENDENCIES

Tcl >= 8.6.7
tdom >= 0.9.6

Reading an existing .docx file (as template or for imports) uses the zlib command built into Tcl and needs no additional package. Only if an archive cannot be handled by the built-in reader, one of the optional fallback backends is used: the Tcl 9 zipfs, tcllib’s zipfile::decode or tclvfs vfs::zip >= 1.0.4.

ooxml/doc/tcl-docs.css000664 000765 000024 00000032434 15213015413 015302 0ustar00alexstaff000000 000000 /* ── Tcl Reference Manual — Documentation Stylesheet ───────────────────────── * * Designed for HTML pages generated from the Tcl Pandoc Markdown sources. * Markdown span/div attributes map to CSS classes: * * Tcl command syntax * .synopsis fenced div wrapping the whole synopsis block * .cmd Tcl command name [string]{.cmd} * .sub subcommand [cat]{.sub} * .arg required argument [string]{.arg} * .optarg optional argument [string1]{.optarg} * .optdot repeating / trailing arg [arg]{.optdot} * .lit literal keyword [-length]{.lit} * .optlit optional literal [-nocase]{.optlit} * * C API syntax * .ret return type [void *]{.ret} * .ccmd C function name [Tcl_Alloc]{.ccmd} * .cargs C argument list [size]{.cargs} * .ins in / out / in-out tag * * Structural * .classhierarchy OO class tree block * ────────────────────────────────────────────────────────────────────────── */ /* ── Design tokens ────────────────────────────────────────────── */ :root { --font-sans: system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; --font-mono: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace; --bg: #ffffff; --surface: #f6f8fa; --border: #d0d7de; --text: #1f2328; --muted: #656d76; --link: #0969da; --link-hover: #0550ae; /* Syntax palette — light mode */ --cmd: #b91c1c; /* command name — red */ --sub: #9a3412; /* subcommand — rust */ --arg: #1d4ed8; /* argument — blue */ --lit: #047857; /* literal flag — green */ --ret: #7c3aed; /* C return type — violet */ --ccmd: #b91c1c; /* C function name — red */ --cargs: #1d4ed8; /* C arg list — blue */ /* Synopsis box */ --syn-bg: #161b22; --syn-fg: #e6edf3; --radius: 6px; --max-width: 860px; } /* ── Reset ────────────────────────────────────────────────────── */ *, *::before, *::after { box-sizing: border-box; } /* ── Base ─────────────────────────────────────────────────────── */ html { font-size: 16px; scroll-behavior: smooth; } body { font-family: var(--font-sans); background: var(--bg); color: var(--text); line-height: 1.7; margin: 0; padding: 0; } /* ── Top bar ──────────────────────────────────────────────────── */ body > nav, .topbar { background: var(--syn-bg); color: #8b949e; font-size: 0.82rem; padding: 0.55rem 2rem; display: flex; align-items: center; gap: 1.4rem; letter-spacing: 0.03em; } body > nav a, .topbar a { color: #79c0ff; text-decoration: none; } body > nav a:hover, .topbar a:hover { text-decoration: underline; } /* ── Page content wrapper ─────────────────────────────────────── */ main, article, .content { max-width: var(--max-width); margin: 0 auto; padding: 2.2rem 2rem 5rem; } /* ── Headings ─────────────────────────────────────────────────── */ h1, h2, h3, h4 { font-weight: 600; line-height: 1.25; margin: 2rem 0 0.5rem; } h1 { font-size: 1.9rem; border-bottom: 2px solid var(--border); padding-bottom: 0.35rem; margin-top: 1.2rem; } h2 { font-size: 1.3rem; border-bottom: 1px solid var(--border); padding-bottom: 0.2rem; margin-top: 2.4rem; } h3 { font-size: 1.1rem; } h4 { font-size: 0.97rem; color: var(--muted); } /* ── Paragraphs ───────────────────────────────────────────────── */ p { margin: 0.75rem 0; } /* ── Links ────────────────────────────────────────────────────── */ a { color: var(--link); text-decoration: none; } a:hover { color: var(--link-hover); text-decoration: underline; } /* ── ════════════════════════════════════════════ SYNOPSIS BLOCK Pandoc converts ::: {.synopsis} to
═══════════════════════════════════════════ */ div.synopsis { background: var(--syn-bg); color: var(--syn-fg); font-family: var(--font-mono); font-size: 0.9rem; line-height: 2; padding: 1.1rem 1.5rem; border-radius: var(--radius); margin: 1rem 0 1.8rem; overflow-x: auto; } /* Span colours inside the dark synopsis box */ div.synopsis .cmd, div.synopsis .ccmd { color: #ff7b72; } div.synopsis .sub { color: #ffa657; } div.synopsis .arg { color: #79c0ff; font-style: italic; } div.synopsis .optarg { color: #79c0ff; font-style: italic; } div.synopsis .optarg::before { content: "?"; color: #8b949e; } div.synopsis .optarg::after { content: "?"; color: #8b949e; } div.synopsis .lit { color: #7ee787; font-weight: 600; } div.synopsis .optlit { color: #7ee787; font-weight: 600; } div.synopsis .optlit::before { content: "?"; color: #8b949e; } div.synopsis .optlit::after { content: "?"; color: #8b949e; } div.synopsis .optdot { color: #8b949e; font-style: italic; } div.synopsis .optdot::after { content: " \2026"; } /* … */ div.synopsis .ret { color: #d2a8ff; font-style: italic; } div.synopsis .ret::after { content: " "; } div.synopsis .cargs { color: #79c0ff; font-style: italic; } div.synopsis .cargs::before { content: "("; color: #8b949e; } div.synopsis .cargs::after { content: ")"; color: #8b949e; } /* ── ════════════════════════════════════════════ INLINE SYNTAX SPANS (body text & definition terms) ═══════════════════════════════════════════ */ /* Command name */ span.cmd { font-family: var(--font-mono); font-weight: 700; color: var(--cmd); } /* Subcommand */ span.sub { font-family: var(--font-mono); font-weight: 600; color: var(--sub); } /* Required argument */ span.arg { font-family: var(--font-mono); font-style: italic; color: var(--arg); } /* Optional argument — wrapped in Tcl's ?…? convention */ span.optarg { font-family: var(--font-mono); font-style: italic; color: var(--arg); } span.optarg::before { content: "?"; color: var(--muted); font-style: normal; } span.optarg::after { content: "?"; color: var(--muted); font-style: normal; } /* Repeating / ellipsis placeholder */ span.optdot { font-family: var(--font-mono); font-style: italic; color: var(--muted); } span.optdot::after { content: " \2026"; } /* Literal keyword that must appear verbatim, e.g. -length */ span.lit { font-family: var(--font-mono); font-weight: 600; color: var(--lit); } /* Optional literal, e.g. -nocase */ span.optlit { font-family: var(--font-mono); font-weight: 600; color: var(--lit); } span.optlit::before { content: "?"; color: var(--muted); font-weight: normal; } span.optlit::after { content: "?"; color: var(--muted); font-weight: normal; } /* ── C API spans ──────────────────────────────────────────────── */ /* Return type */ span.ret { font-family: var(--font-mono); font-style: italic; color: var(--ret); } span.ret::after { content: "\00a0"; } /* non-breaking space */ /* C function name */ span.ccmd { font-family: var(--font-mono); font-weight: 700; color: var(--ccmd); } /* C argument list */ span.cargs { font-family: var(--font-mono); font-style: italic; color: var(--cargs); } span.cargs::before { content: "("; color: var(--muted); font-style: normal; } span.cargs::after { content: ")"; color: var(--muted); font-style: normal; } /* in / out / in-out annotation in argument tables */ span.ins { display: inline-block; font-family: var(--font-mono); font-size: 0.71rem; font-style: italic; color: var(--muted); background: var(--surface); border: 1px solid var(--border); border-radius: 3px; padding: 0 0.3em; vertical-align: middle; margin: 0 0.15em; line-height: 1.4; } /* ── Class hierarchy ──────────────────────────────────────────── */ div.classhierarchy, span.classhierarchy { display: block; font-family: var(--font-mono); font-size: 0.88rem; background: var(--surface); border-left: 3px solid var(--border); padding: 0.8rem 1.2rem; margin: 1rem 0; white-space: pre; overflow-x: auto; border-radius: 0 var(--radius) var(--radius) 0; } /* ── Definition lists (option / argument descriptions) ────────── */ dl { margin: 0.8rem 0; } dt { font-family: var(--font-mono); font-size: 0.93rem; font-weight: 600; margin-top: 1.2rem; padding: 0.35rem 0.6rem; background: var(--surface); border-left: 3px solid var(--border); border-radius: 0 var(--radius) var(--radius) 0; line-height: 1.6; } dd { margin: 0.3rem 0 0.8rem 1.4rem; } dd > p:first-child { margin-top: 0.25rem; } dd > p:last-child { margin-bottom: 0; } /* ── Inline code & code blocks ────────────────────────────────── */ code { font-family: var(--font-mono); font-size: 0.87em; background: var(--surface); border: 1px solid var(--border); border-radius: 3px; padding: 0.1em 0.35em; } pre { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 1rem 1.2rem; overflow-x: auto; font-family: var(--font-mono); font-size: 0.87rem; line-height: 1.6; margin: 0.9rem 0; } pre code { background: none; border: none; padding: 0; font-size: inherit; } /* ── Blockquotes / notes ──────────────────────────────────────── */ blockquote { border-left: 3px solid var(--link); background: #dbeafe22; margin: 1rem 0; padding: 0.4rem 1rem; border-radius: 0 var(--radius) var(--radius) 0; } /* ── Tables ───────────────────────────────────────────────────── */ table { border-collapse: collapse; width: 100%; margin: 1.2rem 0; font-size: 0.92rem; } th, td { border: 1px solid var(--border); padding: 0.45rem 0.8rem; text-align: left; vertical-align: top; } thead th { background: var(--surface); font-weight: 600; } tbody tr:nth-child(even) td { background: #fafbfc; } /* ── Horizontal rule ──────────────────────────────────────────── */ hr { border: none; border-top: 1px solid var(--border); margin: 2rem 0; } /* ── Footer ───────────────────────────────────────────────────── */ footer { margin-top: 3rem; padding: 1.2rem 2rem; font-size: 0.8rem; color: var(--muted); border-top: 1px solid var(--border); text-align: center; } /* ── Responsive ───────────────────────────────────────────────── */ @media (max-width: 640px) { main, article, .content { padding: 1rem 1rem 3rem; } h1 { font-size: 1.45rem; } h2 { font-size: 1.15rem; } div.synopsis { font-size: 0.78rem; padding: 0.8rem 1rem; } } /* ── Print ────────────────────────────────────────────────────── */ @media print { body { font-size: 11pt; } div.synopsis { background: #111; color: #eee; -webkit-print-color-adjust: exact; } a { color: inherit; text-decoration: underline; } pre, blockquote, dt { break-inside: avoid; } body > nav { display: none; } } ooxml/doc/ooxml.md000644 000765 000024 00000103171 15221547440 014544 0ustar00alexstaff000000 000000 % ooxml(n) | ooxml user documentation # NAME ::ooxml::xl_sheets, ::ooxml::xl_read, ::ooxml::xl_write, ::ooxml::tablelist_to_xl - Read and create ECMA-376 Office Open XML Spreadsheets (the .xlsx format) # SYNOPSIS package require ooxml ::ooxml::xl_sheets file ::ooxml::xl_read file ?-option value ...? ::ooxml::xl_write new ?-option value ...? ::ooxml::tablelist_to_xl tablelist ?-option value ...? # DESCRIPTION The commands of this package read or create ECMA-376 Office Open XML Spreadsheets (LibreOffice and Excel ".xlsx" files). The three most important are: ::ooxml::xl_read - imports a .xlsx spreadsheet file into a Tcl array ::ooxml::xl_write - creates a spreadsheet object command ::ooxml::tablelist_to_xl - exports a Tcl tablelist to a .xlsx spreadsheet In this documentation the term workbook means a whole spreadsheet with all its tables. The term worksheet means a specific table of the workbook it belongs to. All row, column and sheet indices used by this package are zero-based. Cell positions may be given numerically as *row,column* or in Excel notation; see [CELL INDEX](#cell-index). The package provides the following commands: **::ooxml::arrayDeleteSheet** *arrayName* *sheetId* *?-sheetname?* : Deletes one worksheet from an array read with *::ooxml::xl_read* and renumbers the remaining sheets. The array is passed by name (without `$`). By default *sheetId* is the zero-based sheet index; with the **-sheetname** option it is the worksheet name. ::ooxml::arrayDeleteSheet workbook 0 ::ooxml::arrayDeleteSheet workbook "Sheet1" -sheetname **::ooxml::CalcColumnWidth** *numberOfCharacters* *?maximumDigitWidth?* *?pixelPadding?* : Returns the column width value (for the **column** method **-width** option) that fits the given number of characters. The optional arguments *maximumDigitWidth* (default 7) and *pixelPadding* (default 5) describe the metrics of the standard font. ::ooxml::CalcColumnWidth 16 ;# -> 16.7109375 **::ooxml::Column** *column* : Converts the zero-based *column* number into the column name in Excel notation (0 -> A, 1 -> B, 26 -> AA, ...). **::ooxml::Default** *name* *value* : Sets a package wide default. The only currently supported *name* is *path*: the default directory of written files (used e.g. by *::ooxml::tablelist_to_xl* if no **-path** is given). An empty *value* resets it to the current directory. **::ooxml::RowColumnToString** *rowcol* : Converts a numerical cell index (*row,column*, zero-based) into Excel notation (0,0 -> A1). **::ooxml::StringToRowColumn** *name* : Converts a cell position in Excel notation into the numerical form (A1 -> 0,0). **::ooxml::tablelist_to_xl** *tablelist* *?-option value ...?* : Exports the content of the Tk tablelist widget *tablelist* to a .xlsx file. The recognized options are: -callback command: Command to be called once per workbook and once per column, to customize styles and column properties. See below for the arguments. Default is the built-in callback ::ooxml::tablelist_to_xl_callback. -path path: Directory of the output file. -file filename: Name of the output file (a .xlsx suffix is appended if missing). -creator name: Creator property of the spreadsheet. -name name: Name of the (single) worksheet. -rootonly: Export only the root level of the tablelist (no child items). -addtimestamp: Add a timestamp to the output file name. -globalstyle: Write the cells with the column styles set by the callback. The callback is called with the arguments spreadsheet sheet maxcol column title width align sortmode hide where *spreadsheet* is the spreadsheet object, *sheet* the worksheet handle and *maxcol* the number of columns. It is called once with *column* = -1 for the whole workbook (for example to set the default date style) and then once per column with the tablelist column properties *title*, *width*, *align*, *sortmode* and *hide*. proc myCallback {spreadsheet sheet maxcol column title width align sortmode hide} { if {$column == -1} { set datestyle [$spreadsheet style -numfmt [$spreadsheet numberformat -datetime]] $spreadsheet defaultdatestyle $datestyle } elseif {$align eq "right"} { $spreadsheet column $sheet -index $column -style [$spreadsheet style -horizontal right] } } **::ooxml::xl_read** *file* *?-option value ...?* : Reads the given .xlsx *file* and returns its contents as a flat Tcl array (to be caught with `array set`). See [RESULT ARRAY](#result-array) for the keys of the returned array. The recognized options are: -valuesonly: Read only the cell values, no formatting, formulas or sheet properties. -keylist: Additionally build the S,k key (see RESULT ARRAY), a dictionary of the non-empty columns per row. -sheets pattern: Read only the worksheets whose zero-based sheet index matches the glob pattern. -sheetnames pattern: Read only the worksheets whose name matches the glob pattern. If neither -sheets nor -sheetnames is given all worksheets are read. -datefmt format: [clock format] string used to convert date cells into the value keys (default "%Y-%m-%d %H:%M:%S"). -as array: Format of the return value. Currently array is the only supported value. A simple example: array set workbook [::ooxml::xl_read file.xlsx] foreach key [lsort -dictionary [array names workbook 0,v,*]] { lassign [split $key ,] sheet tag row col puts "$row,$col = $workbook($key)" } **::ooxml::xl_sheets** *file* : Returns information about the worksheets of the given .xlsx *file* without reading any cell data. The result is a Tcl list with two elements per worksheet: the zero-based sheet index and a dictionary with the keys *sheetId* (the internal sheet id), *name* (the display name of the worksheet) and *rId* (the internal relationship id). foreach {index info} [::ooxml::xl_sheets file.xlsx] { puts "$index: [dict get $info name]" } **::ooxml::xl_write** **new** *?-option value ...?* : Creates a spreadsheet object command to build a workbook from scratch: set spreadsheet [::ooxml::xl_write new ?-option value ...?] The recognized options are: -creator name: The creator property of the spreadsheet. -created timestamp: The creation time property of the spreadsheet. The value is either an integer (seconds, as returned by [clock seconds]) or a date string in local time. -modifiedby name: The modified-by property of the spreadsheet. -modified timestamp: The modification time property of the spreadsheet. For the value see -created. -application name: The application property of the spreadsheet. The created spreadsheet object commands currently support the following methods: **autofilter** *sheet* *indexFrom* *indexTo* : Adds an autofilter (filter and sort controls on the header row) to the worksheet, spanning from cell *indexFrom* to cell *indexTo* (see [CELL INDEX](#cell-index)). $spreadsheet autofilter $sheet 0,0 0,5 **border** *?-option value ...?* : Defines a border style for the current workbook and returns an ID (BORDERID) to refer to that style. The recognized options are: -list: Returns the list of currently defined border styles instead of a BORDERID. -leftstyle BORDERLINESTYLE -rightstyle BORDERLINESTYLE -topstyle BORDERLINESTYLE -bottomstyle BORDERLINESTYLE -diagonalstyle BORDERLINESTYLE See BORDERLINESTYLE for the valid values. -leftcolor COLOR -rightcolor COLOR -topcolor COLOR -bottomcolor COLOR -diagonalcolor COLOR See COLOR for the valid values. -diagonaldirection (up|down) -tag tagname: Gives the border style a name. This name may be used instead of the returned BORDERID. : See [BORDERLINESTYLE](#borderlinestyle) and [COLOR](#color) for the valid option values. **cell** *sheet* *?data?* *?-option value ...?* : Writes the value *data* into a cell of the worksheet *sheet* and returns the position of the written cell as *row,column*. Without the **-index** option the cell is placed in the current row at the next column (see [CELL INDEX](#cell-index) for the autoincrement behaviour). The recognized options are: -index index: Position of the cell, either as row,column or in Excel notation. Also accepts a bare column number to place the cell in the current row with columns skipped. -style STYLEID: Style of the cell, from the method style. -formula formula: Enter an Excel formula (e.g. "A1+B1"). The data argument is usually empty then, the application computes the value. -formulaidx integer: Shared formula index. A cell defining a shared formula gives -formula, -formularef and -formulaidx; the dependent cells give only -formulaidx. -formularef range: The range the shared formula spans, either in Excel notation (C3:C5) or numerically (2,2:4,2). -string: Store the value as string in any case. -nostring: Override a column-level -string setting for this cell. -nozero: Do not output the value if it is zero. -zero: Override a column-level -nozero setting for this cell. -globalstyle: Apply the column style to this cell. -height height: Sets the row height of the current row. -hyperlink url: Makes the cell a hyperlink to url. -tooltip text: Tooltip for the hyperlink (only used together with -hyperlink). **column** *sheet* *?-option value ...?* : Defines the properties of a column of the worksheet *sheet* and returns the column number. Without the **-index** option the next column is used. The recognized options are: -index index: Column number. -to index: Last column number, if the definition should span a range of columns. -width width: Column width in characters of the standard font (may be fractional, see also ::ooxml::CalcColumnWidth). -style STYLEID: Default style for the cells of the column. Note that a cell only uses it if written with -globalstyle. -bestfit: Sets the bestFit flag of the column. -customwidth: Sets the customWidth flag of the column. -string: Store the values of the cells of this column as string in any case (a cell may override this with -nostring). -nozero: Do not output zero values in this column (a cell may override this with -zero). -calcfit: Calculates the column width from the length of the longest value written to the column (via ::ooxml::CalcColumnWidth) if that is wider than a given -width. **defaultdatestyle** *STYLEID* : Sets the default style for date cells. Values recognized as dates are formatted with this style if the cell does not have an explicit **-style**. set datestyle [$spreadsheet style -numfmt [$spreadsheet numberformat -datetime]] $spreadsheet defaultdatestyle $datestyle **fill** *?-option value ...?* : Defines a fill style for the current workbook and returns an ID (FILLID) to refer to that style. The recognized options are: -list: Returns the list of currently defined fills instead of a FILLID. -patterntype PATTERNTYPE: See PATTERNTYPE for the usual values (default "none"). -fgcolor COLOR: Foreground (pattern) color. See COLOR for the valid values. -bgcolor COLOR: Background color. See COLOR for the valid values. -tag tagname: Gives the fill a name. This name may be used instead of the returned FILLID. : See [PATTERNTYPE](#patterntype) and [COLOR](#color) for the valid option values. **font** *?-option value ...?* : Defines a font for the current workbook and returns an ID (FONTID) to refer to that font. The recognized options are: -list: Returns the list of currently defined fonts instead of a FONTID. -name name: Font name (default "Calibri"). -family family: Font family number (default 2). -size size: Font size in points (default 12). -color COLOR: See COLOR for the valid values. -scheme scheme: Font scheme (default "minor"). -bold: Bold text. -italic: Italic text. -underline: Underlined text. -tag tagname: Gives the font a name. This name may be used instead of the returned FONTID. : See [COLOR](#color) for the valid **-color** values. **freeze** *sheet* *index* : Freezes the panes above and left of the given cell *index* (see [CELL INDEX](#cell-index)), so they stay visible while scrolling. $spreadsheet freeze $sheet 1,0 ;# freeze the first row **merge** *sheet* *indexFrom* *indexTo* : Merges the cell range with the corners *indexFrom* and *indexTo* (see [CELL INDEX](#cell-index)) into one cell. $spreadsheet merge $sheet 40,0 40,2 $spreadsheet merge $sheet A42 A44 **numberformat** *?-option value ...?* : Defines a number format for the current workbook and returns an ID (NUMFMTID) to refer to that format. The recognized options are: -format format: Any Excel format string (e.g. {#,##0.00 "€"}). -general: Excel general format. -date: Date format. -time: Time format. -datetime: Date/time format. -iso8601: Date/time in ISO 8601 notation. -number: Integer. -decimal: Decimal number with 2 decimal places. -red: Color negative values red (may be combined with -number and -decimal). -separator: Thousands separators (may be combined with -number and -decimal). -fraction: Fractions. -scientific: Scientific notation. -percent: Percentage. -text, -string: Text format. -tag tagname: Gives the format a name. This name may be used instead of the returned NUMFMTID. **pageMargins** *sheet* *?-option value ...?* : Sets the page margins of the worksheet *sheet*. The recognized options are: -left -right -top -bottom -header -footer All options expect a floating point value in inch. If some page margins of a worksheet are set with this method then all margins of that worksheet are set, either from the options given in the method call or from the current **pageMarginsDefault** values, if a margin was not in the method call. **pageMarginsDefault** *?-option value ...?* : Sets the page margins of all worksheets which do not have individual margin settings. The options are the same as for **pageMargins**. The default margins are: Margin Inch -------- ------- left 0.75 right 0.75 top 1 bottom 1 header 0.5 footer 0.5 **pageSetup** *sheet* *?-option value ...?* : Sets the page setup of the worksheet *sheet*. **Caveat**: If no page setup properties at all are set for a sheet, applications use defaults derived from other sources. But if at least one page setup property is explicitly set with this method, the other properties not set will get the default value from the specification, which may be another value than without any page setup at all. For example if you only set the **-orientation** of a sheet then this may also result in another page size (because the application page size default may differ from the default recommended by the specification, which is Letter paper). The recognized options are: -blackAndWhite boolean: Print black and white. Default: false. -cellComments (none|asDisplayed|atEnd): How to print cell comments. Default: none. -copies integer: Number of copies to print. Default: 1. -draft boolean: Print without graphics. Default: false. -errors (displayed|blank|dash|NA): How to print cell values of cells with errors. Default: displayed. -firstPageNumber integer: Page number of the first printed page; see -useFirstPageNumber. Default: 1. -fitToHeight integer: Number of vertical pages to fit on. Default: 1. -fitToWidth integer: Number of horizontal pages to fit on. Default: 1. -horizontalDpi integer: Horizontal print resolution of the device. Default: 600. -orientation (default|portrait|landscape): Orientation of the page. Default: default. -pageOrder (downThenOver|overThenDown): Order of the printed pages. Default: downThenOver. -paperHeight height: Height of custom paper as a number immediately followed by a unit identifier (as 297mm or 11in). No default. -paperWidth width: Width of custom paper as a number immediately followed by a unit identifier (as 210mm or 8.5in). No default. The specification says that when -paperHeight and -paperWidth are specified, the rendering application shall ignore -paperSize. -paperSize paperSizeID: Specifies the paper size. Default: 1 (Letter). See PAPER SIZE IDS for the defined values; the behaviour for other values is implementation-defined. -scale integer: Print scaling in percent. The rendering application may respect only values ranging from 10 to 400. Overridden when -fitToWidth and/or -fitToHeight are in use. Default: 100. -useFirstPageNumber boolean: Use the -firstPageNumber value for the first page number and do not auto number the pages. Default: false. -usePrinterDefaults boolean: Use the printer defaults (or the defaults of the print job). -verticalDpi integer: Vertical print resolution of the device. Default: 600. : See [PAPER SIZE IDS](#paper-size-ids) for the possible **-paperSize** values. **presetsheets** *arrayName* : Creates worksheets from an array previously read with *::ooxml::xl_read*, including their data. The array is passed by name (without `$`). The sheets are created in their original order. The method adds the key *sheetmap* to the array: a dict mapping the original sheet index to the newly created worksheet handle. Usually combined with **presetstyles**: array set workbook [::ooxml::xl_read original.xlsx] set spreadsheet [::ooxml::xl_write new] $spreadsheet presetstyles workbook $spreadsheet presetsheets workbook **presetstyles** *arrayName* : Takes over the style definitions (number formats, fonts, fills, borders and cell styles) from an array previously read with *::ooxml::xl_read*. The array is passed by name (without `$`). **printarea** *sheet* *indexFrom* *indexTo* : Sets the print area of the worksheet *sheet*, spanning from cell *indexFrom* to cell *indexTo* (see [CELL INDEX](#cell-index)). $spreadsheet printarea $sheet A1 C3 $spreadsheet printarea $sheet 1,1 2,2 **row** *sheet* *?-option value ...?* : Starts a new row in the worksheet *sheet* and returns the row number. Without the **-index** option the next row is used; the column autoincrement is reset (see [CELL INDEX](#cell-index)). The recognized options are: -index index: Row number to jump to. -height height: Row height in points. **rowheight** *sheet* *row* *height* : Sets the height of the given *row* (zero-based) of the worksheet *sheet* to *height* points, independently of writing cells. $spreadsheet rowheight $sheet 33 20 **style** *?-option value ...?* : Defines a cell style for the current workbook and returns an ID (STYLEID) to refer to that style. The recognized options are: -list: Returns the list of currently defined styles instead of a STYLEID. -numfmt NUMFMTID: From the method numberformat. -font FONTID: From the method font. -fill FILLID: From the method fill. -border BORDERID: From the method border. -xf XFID: Base cell format record to derive from. -horizontal alignment: Horizontal alignment of the cell content (e.g. left, center, right). -vertical alignment: Vertical alignment of the cell content (e.g. top, center, bottom). -rotate degree: Rotation of the cell content in degrees. -wrap: Enables text wrapping within the cell. -tag tagname: Gives the style a name. This name may be used instead of the returned STYLEID. **view** *?-option value ...?* : Sets the workbook view properties. The recognized options are: -activetab tab: Zero-based index of the worksheet shown when the file is opened. -x twips -y twips: Position of the workbook window. -width twips -height twips: Size of the workbook window. -list: Returns the current view settings instead of setting them. **worksheet** *name* : Creates a new worksheet with the given *name* and returns the sheet handle (SHEETID) used as first argument by the cell related methods. The characters `: \ / ? *` in the name are replaced and the name is truncated to the 31 characters allowed by the format. **write** *filename* : Writes the spreadsheet to the file *filename*. If the filename does not have the suffix .xlsx then it is appended. If *filename* is empty, spreadsheetml.xlsx is used. # RESULT ARRAY *::ooxml::xl_read* returns a flat array. In the following key table *S* stands for the zero-based sheet index and *R*,*C* for the zero-based row and column index: Key Content --------------- ------------------------------------------------------ sheets List of the sheet indices that have been read S,n Worksheet name S,max_row Largest used row index of the worksheet S,max_column Largest used column index of the worksheet S,v,R,C Cell value (present for every non-empty cell) S,d,R,C Raw date/time serial if the cell is a date cell S,s,R,C Style id of the cell S,t,R,C Cell type (*s* = shared string) S,c,R,C Cell position in Excel notation (e.g. B7) S,f,R,C Formula dict: keys *f* (formula), *i* (shared formula index), *r* (shared formula range) S,l,IDX Hyperlink dict: keys *l* (target), *t* (tooltip) S,k Dict row -> list of non-empty columns (only with the -keylist option) S,filter Autofilter ranges S,freeze Freeze pane position S,merge List of merged cell ranges S,printarea Print area range S,rowheight Row height settings S,cols Number of column definitions S,col,N Dict with the properties of column definition *N* S,pageMargins Page margin settings S,pageSetup Page setup settings view Workbook view settings s,... Style metadata (s,@ s,styles,N s,fonts,N s,fills,N s,borders,N s,numFmts,N s,numFmtsIds), consumed by **presetstyles** and **presetsheets** With the **-valuesonly** option only the *sheets*, *S,n*, *S,max_row*, *S,max_column* and *S,v,R,C* keys are present. # CELL INDEX Methods and options expecting a cell position accept it in two equivalent forms: numerically as *row,column* with zero-based row and column numbers, or in Excel notation (column letters followed by the one-based row number). 0,0 and A1 describe the same cell, 3,2 and C4 also. The methods **row**, **column** and **cell** work with an autoincrement mechanism: without an explicit **-index** option **row** starts the next row, **cell** writes to the next column of the current row and **column** defines the next column. An explicit **-index** repositions; the autoincrement continues from there. $spreadsheet row $sheet $spreadsheet cell $sheet A ;# 0,0 $spreadsheet cell $sheet B -index 4 ;# 0,4 (columns 1-3 stay empty) $spreadsheet cell $sheet C ;# 0,5 $spreadsheet row $sheet -index 3 ;# jump to row 3 $spreadsheet cell $sheet D ;# 3,0 For writing prefer the autoincrement wherever possible: call `$spreadsheet row $sheet` once per row and write the cells in order without **-index**. This avoids off-by-one and index bookkeeping errors. # OPTION VALUE TYPES Several option values share the same value types. These types are: ## COLOR There are several kinds of valid values: The value may be *auto* or *none*. If not, the value may be the index number of a predefined color (an integer between 0 and 65 including). See the list below. If not, the value may be the name of a predefined color. Case is ignored. See the list below. If not, the value may be a 6 digit hexadecimal number, which is then used as RGB value. The list of predefined colors is: Color ID Name (A)RGB -------- --------------- -------- 0 Black 00000000 1 White 00FFFFFF 2 Red 00FF0000 3 Lime 0000FF00 4 Blue 000000FF 5 Yellow 00FFFF00 6 Fuchsia 00FF00FF 7 Aqua 0000FFFF 8 Black 00000000 9 White 00FFFFFF 10 Red 00FF0000 11 Lime 0000FF00 12 Blue 000000FF 13 Yellow 00FFFF00 14 Fuchsia 00FF00FF 15 Aqua 0000FFFF 16 Maroon 00800000 17 Green 00008000 18 Navy 00000080 19 Olive 00808000 20 Purple 00800080 21 Teal 00008080 22 Silver 00C0C0C0 23 Gray 00808080 24 Portage 009999FF 25 Lipstick 00993366 26 Cream 00FFFFCC 27 LightCyan 00CCFFFF 28 Purple 00660066 29 LightCoral 00FF8080 30 NavyBlue 000066CC 31 LavenderBlue 00CCCCFF 32 Navy 00000080 33 Fuchsia 00FF00FF 34 Yellow 00FFFF00 35 Aqua 0000FFFF 36 Purple 00800080 37 Maroon 00800000 38 Teal 00008080 39 Blue 000000FF 40 DeepSkyBlue 0000CCFF 41 LightCyan 00CCFFFF 42 BlueRomance 00CCFFCC 43 Canary 00FFFF99 44 LightSkyBlue 0099CCFF 45 CarnationPink 00FF99CC 46 Mauve 00CC99FF 47 PeachOrange 00FFCC99 48 RoyalBlue 003366FF 49 MediumTurquoise 0033CCCC 50 Citrus 0099CC00 51 TangerineYellow 00FFCC00 52 OrangePeel 00FF9900 53 SafetyOrange 00FF6600 54 Scampi 00666699 55 Nobel 00969696 56 PrussianBlue 00003366 57 Eucalyptus 00339966 58 Myrtle 00003300 59 Karaka 00333300 60 SaddleBrown 00993300 61 Lipstick 00993366 62 DarkSlateBlue 00333399 63 NightRider 00333333 64 SystemForeground n/a 65 SystemBackground n/a ## BORDERLINESTYLE The list of possible values is: dashDot dashDotDot dashed dotted double hair medium mediumDashDot mediumDashDotDot none slantDashDot thick thin ## PATTERNTYPE An ECMA-376 fill pattern type. The usual values are: none solid darkDown darkGray darkGrid darkHorizontal darkTrellis darkUp darkVertical gray0625 gray125 lightDown lightGray lightGrid lightHorizontal lightTrellis lightUp lightVertical mediumGray ## PAPER SIZE IDS The possible **-paperSize** values and their meaning are: Paper Size ID Paper Size ------------- ------------------ 1 Letter paper (8.5 in. by 11 in.) 2 Letter small paper (8.5 in. by 11 in.) 3 Tabloid paper (11 in. by 17 in.) 4 Ledger paper (17 in. by 11 in.) 5 Legal paper (8.5 in. by 14 in.) 6 Statement paper (5.5 in. by 8.5 in.) 7 Executive paper (7.25 in. by 10.5 in.) 8 A3 paper (297 mm by 420 mm) 9 A4 paper (210 mm by 297 mm) 10 A4 small paper (210 mm by 297 mm) 11 A5 paper (148 mm by 210 mm) 12 B4 paper (250 mm by 353 mm) 13 B5 paper (176 mm by 250 mm) 14 Folio paper (8.5 in. by 13 in.) 15 Quarto paper (215 mm by 275 mm) 16 Standard paper (10 in. by 14 in.) 17 Standard paper (11 in. by 17 in.) 18 Note paper (8.5 in. by 11 in.) 19 #9 envelope (3.875 in. by 8.875 in.) 20 #10 envelope (4.125 in. by 9.5 in.) 21 #11 envelope (4.5 in. by 10.375 in.) 22 #12 envelope (4.75 in. by 11 in.) 23 #14 envelope (5 in. by 11.5 in.) 24 C paper (17 in. by 22 in.) 25 D paper (22 in. by 34 in.) 26 E paper (34 in. by 44 in.) 27 DL envelope (110 mm by 220 mm) 28 C5 envelope (162 mm by 229 mm) 29 C3 envelope (324 mm by 458 mm) 30 C4 envelope (229 mm by 324 mm) 31 C6 envelope (114 mm by 162 mm) 32 C65 envelope (114 mm by 229 mm) 33 B4 envelope (250 mm by 353 mm) 34 B5 envelope (176 mm by 250 mm) 35 B6 envelope (176 mm by 125 mm) 36 Italy envelope (110 mm by 230 mm) 37 Monarch envelope (3.875 in. by 7.5 in.). 38 6 3/4 envelope (3.625 in. by 6.5 in.) 39 US standard fanfold (14.875 in. by 11 in.) 40 German standard fanfold (8.5 in. by 12 in.) 41 German legal fanfold (8.5 in. by 13 in.) 42 ISO B4 (250 mm by 353 mm) 43 Japanese double postcard (200 mm by 148 mm) 44 Standard paper (9 in. by 11 in.) 45 Standard paper (10 in. by 11 in.) 46 Standard paper (15 in. by 11 in.) 47 Invite envelope (220 mm by 220 mm) 50 Letter extra paper (9.275 in. by 12 in.) 51 Legal extra paper (9.275 in. by 15 in.) 52 Tabloid extra paper (11.69 in. by 18 in.) 53 A4 extra paper (236 mm by 322 mm) 54 Letter transverse paper (8.275 in. by 11 in.) 55 A4 transverse paper (210 mm by 297 mm) 56 Letter extra transverse paper (9.275 in. by 12 in.) 57 SuperA/SuperA/A4 paper (227 mm by 356 mm) 58 SuperB/SuperB/A3 paper (305 mm by 487 mm) 59 Letter plus paper (8.5 in. by 12.69 in.) 60 A4 plus paper (210 mm by 330 mm) 61 A5 transverse paper (148 mm by 210 mm) 62 JIS B5 transverse paper (182 mm by 257 mm) 63 A3 extra paper (322 mm by 445 mm) 64 A5 extra paper (174 mm by 235 mm) 65 ISO B5 extra paper (201 mm by 276 mm) 66 A2 paper (420 mm by 594 mm) 67 A3 transverse paper (297 mm by 420 mm) 68 A3 extra transverse paper (322 mm by 445 mm) 69 Japanese Double Postcard (200 mm x 148 mm) 70 A6 (105 mm x 148 mm) 71 Japanese Envelope Kaku #2 72 Japanese Envelope Kaku #3 73 Japanese Envelope Chou #3 74 Japanese Envelope Chou #4 75 Letter Rotated (11 in x 8.5 in) 76 A3 Rotated (420 mm x 297 mm) 77 A4 Rotated (297 mm x 210 mm) 78 A5 Rotated (210 mm x 148 mm) 79 B4 (JIS) Rotated (364 mm x 257 mm) 80 B5 (JIS) Rotated (257 mm x 182 mm) 81 Japanese Postcard Rotated (148 mm x 100 mm) 82 Double Japanese Postcard Rotated (148 mm x 200 mm) 83 A6 Rotated (148 mm x 105 mm) 84 Japanese Envelope Kaku #2 Rotated 85 Japanese Envelope Kaku #3 Rotated 86 Japanese Envelope Chou #3 Rotated 87 Japanese Envelope Chou #4 Rotated 88 B6 (JIS) (128 mm x 182 mm) 89 B6 (JIS) Rotated (182 mm x 128 mm) 90 (12 in x 11 in) 91 Japanese Envelope You #4 92 Japanese Envelope You #4 Rotated 93 PRC 16K (146 mm x 215 mm) 94 PRC 32K (97 mm x 151 mm) 95 PRC 32K(Big) (97 mm x 151 mm) 96 PRC Envelope #1 (102 mm x 165 mm) 97 PRC Envelope #2 (102 mm x 176 mm) 98 PRC Envelope #3 (125 mm x 176 mm) 99 PRC Envelope #4 (110 mm x 208 mm) 100 PRC Envelope #5 (110 mm x 220 mm) 101 PRC Envelope #6 (120 mm x 230 mm) 102 PRC Envelope #7 (160 mm x 230 mm) 103 PRC Envelope #8 (120 mm x 309 mm) 104 PRC Envelope #9 (229 mm x 324 mm) 105 PRC Envelope #10 (324 mm x 458 mm) 106 PRC 16K Rotated 107 PRC 32K Rotated 108 PRC 32K(Big) Rotated 109 PRC Envelope #1 Rotated (165 mm x 102 mm) 110 PRC Envelope #2 Rotated (176 mm x 102 mm) 111 PRC Envelope #3 Rotated (176 mm x 125 mm) 112 PRC Envelope #4 Rotated (208 mm x 110 mm) 113 PRC Envelope #5 Rotated (220 mm x 110 mm) 114 PRC Envelope #6 Rotated (230 mm x 120 mm) 115 PRC Envelope #7 Rotated (230 mm x 160 mm) 116 PRC Envelope #8 Rotated (309 mm x 120 mm) 117 PRC Envelope #9 Rotated (324 mm x 229 mm) 118 PRC Envelope #10 Rotated (458 mm x 324 mm) # DEPENDENCIES Tcl >= 8.6.7 tdom >= 0.9.0 Reading .xlsx files uses the zlib command built into Tcl and needs no additional package. Only if an archive cannot be handled by the built-in reader (e.g. ZIP64), one of the optional fallback backends is used: the Tcl 9 zipfs, tcllib's zipfile::decode or tclvfs vfs::zip >= 1.0.4. ooxml/doc/ooxml-docx.md000664 000765 000024 00000110751 15221547477 015515 0ustar00alexstaff000000 000000 % ooxml-docx(n) | ooxml user documentation # NAME ::ooxml::docx - Create ECMA-376 Office Open XML writer documents (the .docx format) # SYNOPSIS package require ooxml::docx ::ooxml::docx::docx new *?-option value ...?* ?docx-file? # DESCRIPTION The command *::ooxml::docx* creates a new docx object. Without the optional file argument the object represents an almost minimal empty document. If the last argument is an ECMA-376 Office Open XML WordprocessingML document (vulgo a .docx file) the inital document is a copy of this .docx. The object has methods to append and style content as text, tables, pictures or textboxes. The .docx file created by the object can be read by word processing programs as libreOffice or Word. A simple "Hello, World" example is: set docx [ooxml::docx::docx new] $docx paragraph "Hello, World!" $docx write hello.docx $docx destroy The style and appearance of the content is determined in order by local setting, by referencing to a defined style or finally by the default settings. The methods of a docx object typically expect, if ever, a few arguments required in order and after that option value pairs. The options may appear in any order. An unknown option is reported as error. If an option is given more than one time then the last one wins. The value of an option is - depending on the option - either a single value or a key value list. In the second case the key value pairs may be in any order. If a key is given more than one time then the last one wins. An unknown key is reported as error. In almost all cases the value given to the option or key will be type checked. Content to the document is added top down. The created docx object commands currently support the following methods: **append** *text* *?-option value ...?* : Appends *text* to the last paragraph of the content of the document. The option/value pairs control the appearance of the *text* within the paragraph. See [CHARACTER OPTIONS](#character-options) for the valid options and the type of their value. **appendTo** *objectId* *creatingScript* : This method appends content to an already created table, table row table cell, footer, header, footnote, endnote, comment or textbox. The *objectId* has to be the id returned by the method which created the object. The *creatingScript* is evaluated and creates the appended object content. The resulting document is the same as if the *creatingScript* would have been appended to the *creatingScript* of the method which created the object. **br** *?n?* : Inserts a line break into the current paragraph. The optional argument *n* (default 1) specifies the number of breaks to insert. **comment** *?-option value ...?* *creatingScript* : This method creates a comment to the current point in the document with comment content created by the *creatingScript* and returns the object id of the created comment. Although the standard allows much more rich content most word processor support only basic text formatting for comments. The allowed options are -author string -date -initials string **commentrangeend** *id* *?-option value ...?* *creatingScript* : This method marks the end of a range of content in the document and creates a comment to this content range with comment content created by the *creatingScript* and returns the object id of the created comment. The *id* argument must be the id returned by the corresponding *commentrangestart* call. For the allowed options see the method *comment*. **commentrangestart** ?returnvar? : This method marks the start of a range of content in the document for which a comment should be added. The method returns the id of the range and stores the id additionally in the variable with the name *resultvar*, if the optional argument is given. **destroy** : Destroys the docx object and releases all associated DOM documents and resources. Inherited from TclOO. **configure** *?-option value ...?* : Set certain document properties. The recognized options are: -category -contentStatus -created -creator -description -identifier -ignorable prefixList: Set the MC Ignorable prefixes (e.g. "w14 wp14"). -keywords -language -lastModifiedBy -lastPrinted -modified -revision -subject -title -version **endnote** *?-option value ...?* *creatingScript* : Creates an endnote with content produced by *creatingScript* and returns the object id of the created endnote. A reference mark is inserted at the current position in the document. The allowed options are: -refstyle *styleRef*: Character style applied to the reference mark. The value may be either the internal style ID (*w:styleId*) or the display name (*w:name*). The other *-option value* pairs allows formatting of the (whole) endnote value. See [CHARACTER OPTIONS](#character-options) for the valid options and the type of their value. **field** *field-type* ?*switches*? *?-option value ...?* : Appends the given field type to the last paragraph. Recognized field types are AUTHOR CREATEDATE DATE FILESIZE PAGE NUMPAGES SAVEDATE SECTION TIME TITLE USERNAME If the optional argument *switches* is given its value will be appended as the field switches to the field-type name. The following optional *-option value* pairs allows formatting of the (whole) inserted field value. See [CHARACTER OPTIONS](#character-options) for the valid options and the type of their value. **footnote** *?-option value ...?* *creatingScript* : Creates a footnote with content produced by *creatingScript* and returns the object id of the created footnote. A reference mark is inserted at the current position in the document. The allowed options are: -refstyle styleRef: Character style applied to the reference mark. The value may be either the internal style ID (*w:styleId*) or the display name (*w:name*). **footer** *creatingScript* ?returnvar? ?objectIdvar? **header** *creatingScript* ?returnvar? ?objectIdvar? : Creates a new footer or header by evaluating the creating script. The id of the created footer or header is returned and, if given, stored in the *returnvar*. This is the id to refer to the footer or header to be used with the options *-defaultHeader*, *-firstHeader*, *-evenHeader*, *-defaultFooter*, *-firstFooter* and *-evenFooter* of the methods *pagesetup* and *sectionstart*. The object id of the created footer or header is stored in the *objectIdvar*, if given. This is the id to use with the method *appendTo*. **image** *file* *anchor|inline* *?-option value ...?* : An *inline* image is part of the text, like a character (and therefore may change the line height). An *anchor* image is also anchored at an exact place within the text (which determines the page at which the image is shown) but can be freely placed at the page. : Both types of images share the following options: -dimension *keyValueList*: Required. Sets the image size. Keys: width (EMU), height (EMU). -bwMode *(auto|black|blackGray|blackWhite|clr|gray|grayWhite| hidden|invGray|ltGray|white)*: Black-and-white mode (default "auto"). : Anchor images additionally accept: -anchorData *keyValueList*: Anchor attributes. Keys: behindDoc, distT, distB, distL, distR, hidden, locked, layoutInCell, allowOverlap, relativeHeight. -positionH *relativeFrom*: Horizontal position reference (column, character, insideMargin, leftMargin, margin, outsideMargin, page, rightMargin). Default "column". -alignH *(left|right|center|inside|outside)*: Horizontal alignment (mutually exclusive with -posOffsetH). -posOffsetH *EMU*: Horizontal offset (mutually exclusive with -alignH). -positionV *relativeFrom*: Vertical position reference (insideMargin, line, margin, outsideMargin, page, paragraph, topMargin, bottomMargin). Default "paragraph". -alignV *(inline|top|center|bottom|inside|outside)*: Vertical alignment (mutually exclusive with -posOffsetV). -posOffsetV *EMU*: Vertical offset (mutually exclusive with -alignV). -wrapMode *(none|square|topBottom)*: Text wrapping mode (default "none"). -wrapData *keyValueList*: Wrap attributes (only with -wrapMode square). Keys: wrapText, distT, distB, distL, distR. **import** *part* *docx* : Imports the given *part* from the file *docx* into the docx object, replacing what the object had for that part of the docx zip archive. : The shortcut "styles" may be used for word/styles.xml and "numbering" for word/numbering.xml. **jumpto** *text* *markid* *?-option value ...?* : Appends the text *text* to the last paragraph and if the text is clicked as link (typically Ctrl-Button-1) the text processor jumps to the mark with the id *markid* inside the document. : The option/value pairs control locally the appearance of the *text* within the paragraph. See [CHARACTER OPTIONS](#character-options) for the valid options and the type of their argument. **mark** *markid* : Sets the mark *markid* at the end of the last paragraph. **markstart** *name* : Starts a named bookmark span at the current position. The bookmark name must be unique within the document. Use **markend** to close the span. **markend** *name* : Ends the bookmark span previously opened by **markstart** with the same *name*. **math** *?-option value ...?* *creatingScript* : Creates a math zone. The *creatingScript* creates the math content using the math methods described below. By default the math is inline within the current paragraph. Options: -display *onOffValue*: If on, the math is rendered as a display equation on its own paragraph. -jc *(left|center|right|centerGroup)*: Justification of a display equation. Ignored when -display is off. Inside the *creatingScript*, the following math methods are available. All math methods must be called from within the *creatingScript* of a **math** call; calling them outside a math zone raises a Tcl error. Invalid option values also raise a Tcl error. **mrun** *?-option value ...?* *text* : Creates a math run (text within a math zone). Options: -lit *onOffValue*: Literal (non-italic) text. -sty *(p|b|i|bi)*: Math style (plain, bold, italic, bold-italic). -scr *(roman|script|fraktur|double-struck|sans-serif|monospace)*: Math font script. -nor *onOffValue*: Normal text (non-math font). Mutually exclusive with -sty/-scr. -aln *onOffValue*: Alignment point. -brk *onOffValue*: Line break. -brkAt *integer*: alignment position after break. **mfrac** *?-option value ...?* *numeratorScript* *denominatorScript* : Creates a fraction. The two scripts create the numerator and denominator content. Options: -type *(bar|lin|noBar|skw)*: Fraction type. Defaults to bar (stacked with horizontal rule). *lin* gives a linear (inline slash) form, *noBar* stacked without bar, *skw* skewed. **msub** *baseScript* *subscriptScript* : Creates a subscript construct. **msup** *baseScript* *superscriptScript* : Creates a superscript construct. **msubsup** *baseScript* *subscriptScript* *superscriptScript* : Creates a simultaneous sub-superscript construct. **msqrt** *radicandScript* : Creates a square root. **mroot** *degreeScript* *radicandScript* : Creates an nth-root. The *degreeScript* produces the root index (e.g. 3 for cube root) and *radicandScript* the expression under the radical. **mnary** *?-option value ...?* *baseScript* : Creates an n-ary operator (summation, product, integral, etc.). Options: -char *string*: The operator character (e.g. "∑", "∏", "∫"). -limLoc *(undOvr|subSup)*: Limit placement — under/over or sub/superscript position. -grow *onOffValue*: Whether the operator grows with its content. -sub *script*: Subscript (lower limit) content script. -sup *script*: Superscript (upper limit) content script. -subHide *onOffValue*: Hide the subscript. -supHide *onOffValue*: Hide the superscript. **mfunc** *nameScript* *argumentScript* : Creates a function application construct (e.g. sin, cos, lim). **mlimlow** *baseScript* *lowerLimitScript* : Creates a lower-limit construct (limit below the base). **mlimupp** *baseScript* *upperLimitScript* : Creates an upper-limit construct (limit above the base). **maccent** *?-option value ...?* *baseScript* : Creates an accent construct — places a diacritical mark (hat, tilde, dot, vector arrow, etc.) above the base expression. -char *string*: The accent character. Default is the combining circumflex accent (U+0302). Common values: U+0303 (tilde), U+0307 (dot), U+0308 (double dot), U+20D7 (combining right arrow / vector). **mbar** *?-option value ...?* *baseScript* : Creates an overline or underline bar above or below the base. -pos *top|bot*: Position of the bar (default "top" = overline). **mdelim** *?-option value ...?* *script* : Creates a delimiter construct — wraps content in matching delimiters such as parentheses, brackets, braces, absolute-value bars, norms, floor/ceiling symbols, etc. : The *script* body creates the content. For a single argument, math methods in the script create content directly within an m:e element. For multiple arguments separated by the separator character, use **mdelimarg** within the script. -begChr *string*: Opening delimiter character (default "(") -endChr *string*: Closing delimiter character (default ")") -sepChr *string*: Separator character between arguments (default "|") -grow *onOffValue*: Delimiters grow to match content height -shp *centered|match*: Delimiter shape **mdelimarg** *script* : Creates a delimiter argument (m:e child) inside an enclosing mdelim. Each call to mdelimarg wraps its script content in a separate m:e element, enabling multi-argument delimiters. **mgroupchr** *?-option value ...?* *baseScript* : Creates a grouping character construct — an underbrace, overbrace, or similar character that spans the base expression. Commonly used to label parts of an equation. -char *string*: The grouping character (default U+23DF = ⏟ bottom curly bracket). Use U+23DE for overbrace (⏞). -pos *top|bot*: Position of the character (default "bot") -vertJc *top|bot*: Vertical justification of the base relative to the grouping character **mmatrix** *?-option value ...?* *rowScripts* : Creates a matrix. The *rowScripts* argument is a list; each element is a script that creates cells via **mmatcell** calls. Wrap in **mdelim** for bracket/parenthesis notation. -baseJc *top|center|bottom*: Vertical alignment of the matrix relative to the math baseline -mcJc *left|center|right*: Column justification -count *integer*: Number of adjacent columns sharing the justification (1–255) **mmatcell** *script* : Creates a matrix cell (m:e child) inside a matrix row. Each call wraps its script content in a separate m:e element. **numbering** *subcmd* *args* : Manages numbering definitions (lists, outlines). : The supported subcommands are: **abstractNum** *id* *levelDefinitions*: Creates an abstract numbering definition with the given integer *id*. The *levelDefinitions* argument is a list; each element defines one level using option/value pairs: -numberFormat *format*: Numbering format (decimal, upperRoman, lowerRoman, upperLetter, lowerLetter, bullet, etc.) -levelText *string*: Level text template (e.g. "%1." or "%1.%2") -align *alignment*: Number alignment (start, center, end, etc.) -start *integer*: Starting number (default 1) Paragraph and character options may also be given per level to style the number and the paragraph. A corresponding w:num entry is automatically created with the same numId as the abstractNumId. Example: $doc numbering abstractNum 0 { {-numberFormat decimal -levelText "%1." -align start} {-numberFormat lowerLetter -levelText "%2)" -align start} } **abstractNumIds**: Returns a sorted list of all abstractNum IDs. **delete** *type* *id*: Deletes a numbering definition. *type* is either **abstractNum** or **num**; *id* is the integer ID. **pagebreak** : Appends a page break to the document. **pagesetup** *?-option value ...?* : The allowed options are: -margins keyValueList -paperSource keyValueList -sizeAndOrientation keyValueList -defaultHeader id -defaultFooter id -firstHeader id -firstFooter id -evenHeader id -evenFooter id The last block of options set the respectively header or footer. The id has to be returned from a header or footer method call. -border -pageNumbering -sectionType *(continuous|evenPage|nextColumn|nextPage|oddPage)* Specifies the type of the current section break. The default is *nextPage*. Use *continuous* to start a new section on the same page (e.g. for switching between single and multi-column layout). -docGrid *keyValueList* Configures the document grid for the section, controlling line pitch and character spacing for CJK and other layout needs. The accepted keys are: type Grid type: "default", "lines", "linesAndChars", or "snapToChars". linePitch Distance between lines (integer, in twips). charSpace Additional character pitch (integer, in 4096ths of a point). -vAlign *(top|center|bottom|both)* Vertical alignment of text on the page. The value *both* distributes text evenly between the top and bottom margins (justified). **paragraph** *text* *?-pstyle style? ?-cstyle style? ?-option value ...?* : Appends *text* as paragraph to the content of the document. If the *-pstyle* option is given, the referenced paragraph style will be used. If the *-cstyle* option is given the referenced character style will be used. Style values may be given either as the internal style ID (*w:styleId*) or as the display name (*w:name*). Resolution prefers an exact style-ID match and falls back to the display name. The other options may locally overwrite a style setting or add more properties. See [PARAGRAPH OPTIONS](#paragraph-options) and [CHARACTER OPTIONS](#character-options) for the valid options and the type of their argument. **readpart** *part* *filename* : Replaces the named XML *part* in the docx object with the contents of *filename*. The file is parsed as XML and replaces the in-memory DOM for that part. Example: $doc readpart word/settings.xml mysettings.xml **replace** *from* *to* *?part_list?* : Replaces every *from* substring in any text with *to*, Only uniformly styled text is replaced (if *from* spans over more than one text part it will not be recognized). Without the optional *part list* argument all parts of the document (the main documentbody, footnotes, comments pp.) will be processed. If the argument is given then only the named parts will be processed. The elements of the part list may be a Tcl glob expression. Part names given by the *part list* argument which are currently not exists in the object will be silently ignored. **sectionend** : Ends the current section, emitting the stored section properties as a w:sectPr inside the last paragraph. Must be preceded by a **sectionstart** call; raises an error otherwise. **sectionstart** *?-option value ...?* : Starts a new section in the document. If a previous section was already started (and not ended), it is implicitly ended first. The allowed options are the same as for **pagesetup**: -margins, -sizeAndOrientation, -sectionType, -docGrid, -vAlign, -border, -pageNumbering, header/footer references, etc. **settings** *?-option value ...?* : Modifies the document settings (word/settings.xml). Settings may be called multiple times; each call updates or adds the specified settings without affecting those set by earlier calls. Special option: -reset *onOffValue*: If on, resets all settings to defaults before applying the remaining options. Commonly used settings: -defaultTabStop *integer*: Default tab stop distance in twips. -autoHyphenation *onOffValue*: Enable automatic hyphenation. -evenAndOddHeaders *onOffValue*: Use different headers/footers for even and odd pages. -hideSpellingErrors *onOffValue*: Hide red squiggly underlines. -hideGrammaticalErrors *onOffValue*: Hide grammar error marks. -trackRevisions *onOffValue*: Enable revision tracking. -mirrorMargins *onOffValue*: Mirror left/right margins for facing pages. -embedTrueTypeFonts *onOffValue*: Embed TrueType fonts. -documentProtection *keyValueList*: Protect the document. Keys: edit (readOnly|comments|trackedChanges|forms|none), enforcement (on|off), formatting (on|off), plus optional cryptographic parameters. Many more settings are available. On/off settings use *onOffValue*. Refer to the property table in the source for the complete list. **selectNodes** *xpath* ?*part*? *?selectNodes options?* : Returns the result of the *xpath* expression. If no other argument is given the context node will be the document element node of the word/document.xml part of the docx. If the *part* argument is given the context node of the expression will be the document element of the docx part identified by this argument. If *part* is a relative path inside the docx zip (example: _rels/.rels) then this is used. All parts of the docx inside the word directory may specified without the directory part and the .xml suffix. The optional *selectNodes options* are routed throw. All documents accessible by this have the following prefix namespace mappings predefined: Prefix Namespace ------ --------- a http://schemas.openxmlformats.org/drawingml/2006/main| ct http://schemas.openxmlformats.org/package/2006/content-types| m http://schemas.openxmlformats.org/officeDocument/2006/math| mc http://schemas.openxmlformats.org/markup-compatibility/2006| o urn:schemas-microsoft-com:office:office| pic http://schemas.openxmlformats.org/drawingml/2006/picture| r http://schemas.openxmlformats.org/officeDocument/2006/relationships| rel http://schemas.openxmlformats.org/package/2006/relationships| sl http://schemas.openxmlformats.org/schemaLibrary/2006/main| v urn:schemas-microsoft-com:vml| w http://schemas.openxmlformats.org/wordprocessingml/2006/main| w10 urn:schemas-microsoft-com:office:word| w14 http://schemas.microsoft.com/office/word/2010/wordml| wp http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing| wp14 http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing| wpg http://schemas.microsoft.com/office/word/2010/wordprocessingGroup| wps http://schemas.microsoft.com/office/word/2010/wordprocessingShape| **simplecomment** *comment* *?-option value ...?* : This method creates a comment to the current point in the document. The text content of the comment will be what is given by the argument *comment*. For the allowed options see the method *comment*. Additionally to this options all [PARAGRAPH OPTIONS](#paragraph-options) and [CHARACTER OPTIONS](#character-options) are allowed. If given they are applied to format the comment text. **simplecommentrangeend** *id* *comment* *?-option value ...?* : This method marks the end of a range of content in the document and creates a comment to this content range with comment content given by the *comment* argument. The *id* argument must be the id returned by the corresponding *commentrangestart* call. For the allowed options see the method *comment*. Additionally to this options all [PARAGRAPH OPTIONS](#paragraph-options) and [CHARACTER OPTIONS](#character-options) are allowed. If given they are applied to format the comment text. **simpletable** *tabledata* *?-option value ...?* : Creates a table from a nested list. Each element of *tabledata* is a row; each element within a row is a cell's text content. Example: `$doc simpletable {{A1 B1 C1} {A2 B2 C2}}` Options: -columnwidths *list*: Column widths (measurements). -firstStyle *styleName*: Character style for the first row. -lastStyle *styleName*: Character style for the last row. Table-level options (-style, -width, -align, -layout, -look, -tableBorders, cell margins) are also accepted — see **table**. **style** *subcommand* *args* : The supported subcommands are: paragraphdefault ?-option value ...? characterdefault ?-option value ...? paragraph name ?-option value ...? character name ?-option value ...? table name ?-option value ...? The *name* argument is the display name of the style. The internal style ID (w:styleId) is derived from the name by stripping non-alphanumeric characters. Use the **-styleid** option to set the internal ID explicitly if the derived ID would be empty or ambiguous. Both display name and derived ID must be unique within the style type. Additional style creation options: -basedon styleRef: Parent style to inherit from. Accepts either an internal style ID or a display name (resolved to a style ID internally). The parent must be the same type as the style being created. -conditional keyValueList: (Table styles only.) Conditional formatting for table regions such as firstRow, lastRow, firstColumn, lastColumn, band1Vert, band1Horz, etc. All methods and options that reference a style (such as **-pstyle**, **-cstyle**, **-style**, **-basedon**, **-refstyle**) accept either the internal style ID (preferred, tried first) or the display name (fallback). ids styletype names styletype delete styletype name **tab** *?n?* : Inserts a tab character into the current paragraph. The optional argument *n* (default 1) specifies the number of tabs to insert. **table** *?-option value ...?* *creatingScript* : Creates a table by defining every row and cell individually by the *creatingScript* and returns the object id of the created table. The recognized options are: -columnwidths *list*: List of column widths (measurements). -style *styleRef*: Table style reference (style ID or display name). -width *keyValueList*: Table width. Keys: type (auto|dxa|pct|nil), value (measurement or percentage). -align *(center|end|left|right|start)*: Table alignment. -layout *keyValueList*: Table layout. Keys: type (autofit|fixed). -look *keyValueList*: Table conditional formatting flags. Keys: firstRow, lastRow, firstColumn, lastColumn, noHBand, noVBand (all on/off). -caption *string*: Table caption for accessibility. -tableBorders: Table border options. For each border position (top, left, bottom, right, insideH, insideV), use `-Border {type color borderwidth space }`. -cellMarginTop, -cellMarginStart, -cellMarginLeft, -cellMarginBottom, -cellMarginEnd, -cellMarginRight: Default cell margins. Each takes a *keyValueList* with keys type and value. **tablecell** *?-option value ...?* *creatingScript* : Creates a table cell within a **tablerow** script and returns the object id of the created table cell. The *creatingScript* creates the cell content (paragraphs, nested tables, etc.). Options: -cellWidth *keyValueList*: Cell width. Keys: type (auto|dxa|pct|nil), value (measurement or percentage). -span *integer*: Number of grid columns this cell spans. -hspan *(restart|continue)*: Horizontal merge state. -vspan *(restart|continue)*: Vertical merge state. -vAlign *(top|center|bottom|both)*: Vertical alignment of cell content. -textDirection *direction*: Text direction within the cell. -shading *keyValueList*: Cell shading pattern. Keys: type, color, fill (same as paragraph shading). The options -shading and -background are mutually exclusive. -background *RRGGBB*: Shorthand for a solid background fill color. The options -shading and -background are mutually exclusive. -tcFitText *onOffValue*: Shrink text to fit cell width. Cell border options (-topBorder, -leftBorder, -bottomBorder, -rightBorder, -tl2brBorder, -tr2blBorder) and cell margin options are also accepted. **tablerow** *?-option value ...?* *creatingScript* : Creates a table row within a **table** script and returns the object id of the created table row. The *creatingScript* creates cells via **tablecell** calls. Options: -rowHeight *keyValueList*: Row height. Keys: value (measurement), hRule (auto|exact|atLeast). -headerrow *onOffValue*: Mark this row as a header row that repeats on each page. -cantSplit *onOffValue*: Prevent the row from splitting across pages. -align *(center|end|left|right|start)*: Row alignment (overrides table alignment). -cellSpacing *keyValueList*: Cell spacing within the row. Keys: type, value. -wBefore, -wAfter *keyValueList*: Width before/after the row (for indented rows). Keys: type, value. **textbox** *?-option value ...?* *creatingScript* : Creates an anchored text box at the current position and returns the object id of the created text box. The *creatingScript* creates the text box content (paragraphs, tables, etc.) inside the box. Options: -name *string*: Display name for the text box shape. Auto-generated if omitted. -dimension *keyValueList*: Required. Sets the text box size. Keys: width (EMU), height (EMU). -bodyAtts *keyValueList*: Text body attributes. Keys: wrap (none|square), numCol (integer), and other wps:bodyPr attributes. Anchor positioning options (-anchorData, -positionH, -alignH, -posOffsetH, -positionV, -alignV, -posOffsetV, -wrapMode, -wrapData, -bwMode) are also accepted — see **image** anchor options. **url** *text* *url* *?-option value ...?* : Append *text* to the current paragrah and make that text an hypherlink to *uri*. The option/value pairs control the appearance of the *text* within the paragraph. See [CHARACTER OPTIONS](#character-options) for the valid options and the type of their value. **write** *?filename?* : Writes the object as WordprocessingML docx file to *filename*. If the argument is omitted then document.docx will be used. If the filename does not have a suffix, then the suffix .docx will be appended. **writepart** *part* *filename* : Writes a single XML part from the docx object to *filename*. Raises an error if the part does not exist in the object. **xpath** *xpath* *?part?* *?selectNodes options?* : An alias for the method *selectNodes*. See there for the meaning of the arguments. **xmlparts** *?pattern?* : Returns the paths of the xml parts of the docx object. If the optional argument *pattern* is given only the xml parts of the docx docx object which match the *pattern* using glob style matching are returned. # CHARACTER OPTIONS **-bold** *onOffValue* **-color** *auto|RRGGBB hex value* **-cstyle** *styleRef* **-dstrike** *onOffValue* **-emboss** *onOffValue* **-font** *font familiy name* **-fontsize** *measure* If the value has no unit the integer means twentieths of a point. **-highlight** (black|blue|cyan|green|magenta|red|yellow|white|darkBlue|darkCyan|darkGreen|darkMagenta|darkRed|darkYellow|darkGray|lightGray|none) **-italic** *onOffValue* **-noProof** *onOffValue* **-rtl** *onOffValue* **-strike** *onOffValue* Toggles strikethrough on the text. **-underline** *kind* The allowed *kind* values are: single words double thick dotted dottedHeavy dash dashedHeavy dashLong dashLongHeavy dotDash dashDotHeavy dotDotDash dashDotDotHeavy wave wavyHeavy wavyDouble none **-verticalAlign** *(baseline|superscript|subscript) # PARAGRAPH OPTIONS **-align** *kind* The allowed *kind* values are: start center end both mediumKashida distribute numTab highKashida lowKashida thaiDistribute left right **-background** *RRGGBB hex value* Sets a solid background fill color on the paragraph. This is a shorthand for `-shading {type clear fill RRGGBB}`. **-bidi** *onOffValue* Right-to-left paragraph direction. **-indentation** *keyValueList* Sets the paragraph indentation. The accepted keys are: start Left/start indentation (measurement). startChars Left/start indentation in character units. end Right/end indentation (measurement). endChars Right/end indentation in character units. firstLine First line additional indent (measurement). firstLineChars First line indent in character units. hanging Hanging indent (measurement). hangingChars Hanging indent in character units. **-keepLines** *onOffValue* Keep all lines of the paragraph on the same page. **-keepNext** *onOffValue* Keep the paragraph on the same page as the next paragraph. **-level** *integer* Numbering level (used with **-numberingStyle**). Zero-based. **-numberingStyle** *integer* Numbering definition ID to apply to this paragraph. **-pageBreakBefore** *onOffValue* Start the paragraph on a new page. **-shading** *keyValueList* Sets the paragraph shading pattern. The accepted keys are: type Shading pattern (required). Common values: clear, solid, horzStripe, vertStripe, diagStripe, diagCross, pct10, pct20, pct25, pct50, pct75, etc. color Foreground pattern color (RRGGBB hex or "auto"). fill Background fill color (RRGGBB hex or "auto"). Example: `-shading {type clear fill FFFF00}` for a yellow background. **-spacing** *keyValueList* The value to the option must be a Tcl list of keyword measurement pairs and defines the space before, after and between the lines of the paragraph. The space values are given as [measurement](#measurement) The accepted keys are: after Space after the paragraph. before Space before the paragraph. line Line spacing within the paragraph. lineRule How "line" is interpreted: "auto" (default, value is in 240ths of a line), "exact" (value is in twips), or "atLeast" (minimum, value is in twips). **-suppressLineNumbers** *onOffValue* Suppress line numbers for this paragraph. **-textframe** *keyValueList* Configures the paragraph as a text frame. Keys: width, height, wrap, vAnchor, hAnchor, xAlign, yAlign, dropCap, lines, vSpace, hSpace, hrule, anchorLock. **-widowControl** *onOffValue* Enable widow/orphan control for this paragraph. # OPTION VALUE TYPES Several option values share the same value types. This types are: ## MEASUREMENT A measurement is given either as integer value without unit or as integer immediately followed by a unit. If the value is just a number then what distance is specified by the number depends on the option and is documented with the option. The allowed units are: mm Millimeter cm Centimeter in Inch (1in = 2.54cm) pt Point (1pt = 1/72in) pc Pica (1pc = 12pt) pi The same as pc: Pica (1pi = 12pt) # DEPENDENCIES Tcl >= 8.6.7 tdom >= 0.9.6 Reading an existing .docx file (as template or for imports) uses the zlib command built into Tcl and needs no additional package. Only if an archive cannot be handled by the built-in reader, one of the optional fallback backends is used: the Tcl 9 zipfs, tcllib's zipfile::decode or tclvfs vfs::zip >= 1.0.4. ooxml/doc/main.css000644 000765 000024 00000011632 14764622263 014532 0ustar00alexstaff000000 000000 @import url('https://fonts.googleapis.com/css2?family=Comfortaa:wght@300;400;500&family=Montserrat:ital,wght@0,100;0,200;0,300;1,100;1,200;1,300&family=Roboto+Condensed:ital,wght@0,300;1,300&family=Roboto+Mono:ital,wght@0,100;0,200;1,100;1,200&family=Roboto:ital,wght@0,100;0,300;0,400;1,100;1,300;1,400&display=swap'); :root { /* Fonts */ --font-primary: 'Roboto', sans-serif; --font-secondary: 'Montserrat', sans-serif; --font-tertiary: 'Comfortaa', cursive; --font-mono: 'Roboto Mono', monospace; --font-condensed: 'Roboto Condensed', monospace; /* Primary Color Palette */ --primary-color1: #00618a; --primary-color2: #70becf; --primary-color3: #bcbec0; /* Secondary Color Palette */ --secondary-color1: #414042; --secondary-color2: #bcbec0; --secondary-color3: #bcbec0; --glow: #03E9F4; } body { font-family: var(--font-primary); } h6, .h6, h5, .h5, h4, .h4, h3, .h3, h2, .h2, h1, .h1 { font-family: var(--font-condensed); color: white; background-color: var(--primary-color1); padding-left: 2rem; border-left: 0.5rem solid var(--primary-color2); font-weight: 400; line-height: 2; } p { font-family: var(--font-tertiary); color: var(--secondary-color1); } .hover-effect { transition: 0.3s; position: relative; } .hover-effect::before, .hover-effect::after { content: ''; position: relative; top: 0; opacity: 0; transition: 0.3s; } .hover-effect::before { content: '['; left: -3px; /* Position the brackets correctly */ } .hover-effect::after { content: ']'; right: -3px; /* Position the brackets correctly */ } .hover-effect:hover::before, .hover-effect:hover::after { opacity: 1; } .nav-item { font-family: var(--font-primary); text-transform: uppercase; transition: 0.5s; } .nav-item:hover { color: #fff; text-shadow: 0 0 5px #03e9f4, 0 0 25px #03e9f4, 0 0 50px #03e9f4, 0 0 100px #03e9f4; } #searchi { } #searchb { font-family: var(--font-tertiary); text-transform: uppercase; } .btn .btn-border-color { color: var(--primary-color2); } .code-container { position: relative; } .copy-button { position: absolute; top: 30px; /* Adjust this value to move the button up/down */ right: 10px; /* Adjust this value to move the button left/right */ z-index: 1; } footer { box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.12); box-sizing: border-box; width: 100%; text-align: left; font: bold 16px sans-serif; padding: 55px 50px; margin-top: 80px; bottom: 0; color: #fff; } .footer-navigation a.webmaster { color: #fff; text-decoration: none; } .footer-navigation h3 { margin: 0; font: normal 36px Cookie, cursive; margin-bottom: 20px; color: #fff; } .footer-navigation p.links a { font-family: var(--font-primary); text-transform: uppercase; transition: 0.5s; color: #fff; text-decoration: none; font-weight: 400; } .footer-navigation a:hover { color: #fff; text-shadow: 0 0 5px var(--glow), 0 0 25px var(--glow), 0 0 50px var(--glow), 0 0 100px var(--glow); } .footer-navigation p.company-name { color: var(--secondary-color3); font-size: 14px; font-weight: normal; margin-top: 40px; } span.new-line-span { display: block; font-weight: normal; display: block; font-weight: normal; font-size: 14px; line-height: 2; } .footer-about h4 { display: block; color: #fff; font-size: 14px; font-weight: bold; margin-bottom: 20px; } .footer-about p { line-height: 20px; color: #92999f; font-size: 13px; font-weight: normal; margin: 0; } div.social-links { margin-top: 20px; color: #fff; } .social-links a { display: inline-block; width: 35px; height: 35px; cursor: pointer; background-color: #33383b; border-radius: 2px; font-size: 20px; color: #ffffff; text-align: center; line-height: 35px; margin-right: 5px; margin-bottom: 5px; } .container ul { list-style: none; /* removes the default bullets */ } .container ul li::before { content: '\F270'; /* using a checkmark for bullet points */ font-family: "bootstrap-icons"; /* ensure this matches the exact font family of your icon set */ display: inline-block; /* necessary to position the pseudo-element */ margin-right: 8px; /* space between the bullet and the list item */ color: var(--primary-color1); } /* Style.adp */ .square { width: 100px; height: 100px; margin: 10px; } #square1 { background-color: var(--primary-color1); } #square2 { background-color: var(--primary-color2); } #square3 { background-color: var(--primary-color3); } #square4 { background-color: var(--secondary-color1); } #square5 { background-color: var(--secondary-color2); } #square6 { background-color: var(--secondary-color3); } #pritext { font-family: var(--font-primary); } #sectext { font-family: var(--font-secondary); } #tertext { font-family: var(--font-tertiary); } #monotext { font-family: var(--font-mono); } #condtext { font-family: var(--font-condensed); } ooxml/doc/ooxml-docx.n000644 000765 000024 00000114230 15221547620 015332 0ustar00alexstaff000000 000000 '\" t .\" Automatically generated by Pandoc 3.10 .\" .TH "ooxml\-docx" "n" "" "" "ooxml user documentation" .SH NAME ::ooxml::docx \- Create ECMA\-376 Office Open XML writer documents (the \&.docx format) .SH SYNOPSIS .IP .EX package require ooxml::docx ::ooxml::docx::docx new *?\-option value ...?* ?docx\-file? .EE .SH DESCRIPTION The command \f[I]::ooxml::docx\f[R] creates a new docx object. .PP Without the optional file argument the object represents an almost minimal empty document. .PP If the last argument is an ECMA\-376 Office Open XML WordprocessingML document (vulgo a .docx file) the inital document is a copy of this \&.docx. .PP The object has methods to append and style content as text, tables, pictures or textboxes. The .docx file created by the object can be read by word processing programs as libreOffice or Word. .PP A simple \(lqHello, World\(rq example is: .IP .EX set docx [ooxml::docx::docx new] $docx paragraph \(dqHello, World!\(dq $docx write hello.docx $docx destroy .EE .PP The style and appearance of the content is determined in order by local setting, by referencing to a defined style or finally by the default settings. .PP The methods of a docx object typically expect, if ever, a few arguments required in order and after that option value pairs. The options may appear in any order. An unknown option is reported as error. If an option is given more than one time then the last one wins. .PP The value of an option is \- depending on the option \- either a single value or a key value list. In the second case the key value pairs may be in any order. If a key is given more than one time then the last one wins. An unknown key is reported as error. In almost all cases the value given to the option or key will be type checked. .PP Content to the document is added top down. .PP The created docx object commands currently support the following methods: .TP \f[B]append\f[R] \f[I]text\f[R] \f[I]?\-option value \&...?\f[R] Appends \f[I]text\f[R] to the last paragraph of the content of the document. The option/value pairs control the appearance of the \f[I]text\f[R] within the paragraph. See CHARACTER OPTIONS for the valid options and the type of their value. .TP \f[B]appendTo\f[R] \f[I]objectId\f[R] \f[I]creatingScript\f[R] This method appends content to an already created table, table row table cell, footer, header, footnote, endnote, comment or textbox. The \f[I]objectId\f[R] has to be the id returned by the method which created the object. The \f[I]creatingScript\f[R] is evaluated and creates the appended object content. The resulting document is the same as if the \f[I]creatingScript\f[R] would have been appended to the \f[I]creatingScript\f[R] of the method which created the object. .TP \f[B]br\f[R] \f[I]?n?\f[R] Inserts a line break into the current paragraph. The optional argument \f[I]n\f[R] (default 1) specifies the number of breaks to insert. .TP \f[B]comment\f[R] \f[I]?\-option value \&...?\f[R] \f[I]creatingScript\f[R] This method creates a comment to the current point in the document with comment content created by the \f[I]creatingScript\f[R] and returns the object id of the created comment. Although the standard allows much more rich content most word processor support only basic text formatting for comments. .RS .PP The allowed options are .IP .EX \-author string \-date \-initials string .EE .RE .TP \f[B]commentrangeend\f[R] \f[I]id\f[R] \f[I]?\-option value \&...?\f[R] \f[I]creatingScript\f[R] This method marks the end of a range of content in the document and creates a comment to this content range with comment content created by the \f[I]creatingScript\f[R] and returns the object id of the created comment. The \f[I]id\f[R] argument must be the id returned by the corresponding \f[I]commentrangestart\f[R] call. For the allowed options see the method \f[I]comment\f[R]. .TP \f[B]commentrangestart\f[R] ?returnvar? This method marks the start of a range of content in the document for which a comment should be added. The method returns the id of the range and stores the id additionally in the variable with the name \f[I]resultvar\f[R], if the optional argument is given. .TP \f[B]destroy\f[R] Destroys the docx object and releases all associated DOM documents and resources. Inherited from TclOO. .TP \f[B]configure\f[R] \f[I]?\-option value \&...?\f[R] Set certain document properties. The recognized options are: .RS .IP .EX \-category \-contentStatus \-created \-creator \-description \-identifier \-ignorable prefixList: Set the MC Ignorable prefixes (e.g. \(dqw14 wp14\(dq). \-keywords \-language \-lastModifiedBy \-lastPrinted \-modified \-revision \-subject \-title \-version .EE .RE .TP \f[B]endnote\f[R] \f[I]?\-option value \&...?\f[R] \f[I]creatingScript\f[R] Creates an endnote with content produced by \f[I]creatingScript\f[R] and returns the object id of the created endnote. A reference mark is inserted at the current position in the document. The allowed options are: .RS .PP \-refstyle \f[I]styleRef\f[R]: Character style applied to the reference mark. The value may be either the internal style ID (\f[I]w:styleId\f[R]) or the display name (\f[I]w:name\f[R]). .PP The other \f[I]\-option value\f[R] pairs allows formatting of the (whole) endnote value. See CHARACTER OPTIONS for the valid options and the type of their value. .RE .TP \f[B]field\f[R] \f[I]field\-type\f[R] ?\f[I]switches\f[R]? \f[I]?\-option value \&...?\f[R] Appends the given field type to the last paragraph. Recognized field types are .RS .IP .EX AUTHOR CREATEDATE DATE FILESIZE PAGE NUMPAGES SAVEDATE SECTION TIME TITLE USERNAME .EE .PP If the optional argument \f[I]switches\f[R] is given its value will be appended as the field switches to the field\-type name. The following optional \f[I]\-option value\f[R] pairs allows formatting of the (whole) inserted field value. See CHARACTER OPTIONS for the valid options and the type of their value. .RE .TP \f[B]footnote\f[R] \f[I]?\-option value \&...?\f[R] \f[I]creatingScript\f[R] Creates a footnote with content produced by \f[I]creatingScript\f[R] and returns the object id of the created footnote. A reference mark is inserted at the current position in the document. The allowed options are: .RS .IP .EX \-refstyle styleRef: Character style applied to the reference mark. The value may be either the internal style ID (*w:styleId*) or the display name (*w:name*). .EE .RE .PP \f[B]footer\f[R] \f[I]creatingScript\f[R] ?returnvar? ?objectIdvar? \f[B]header\f[R] \f[I]creatingScript\f[R] ?returnvar? ?objectIdvar? .PP : Creates a new footer or header by evaluating the creating script. The id of the created footer or header is returned and, if given, stored in the \f[I]returnvar\f[R]. This is the id to refer to the footer or header to be used with the options \f[I]\-defaultHeader\f[R], \f[I]\-firstHeader\f[R], \f[I]\-evenHeader\f[R], \f[I]\-defaultFooter\f[R], \f[I]\-firstFooter\f[R] and \f[I]\-evenFooter\f[R] of the methods \f[I]pagesetup\f[R] and \f[I]sectionstart\f[R]. The object id of the created footer or header is stored in the \f[I]objectIdvar\f[R], if given. This is the id to use with the method \f[I]appendTo\f[R]. .TP \f[B]image\f[R] \f[I]file\f[R] \f[I]anchor|inline\f[R] \f[I]?\-option value \&...?\f[R] An \f[I]inline\f[R] image is part of the text, like a character (and therefore may change the line height). An \f[I]anchor\f[R] image is also anchored at an exact place within the text (which determines the page at which the image is shown) but can be freely placed at the page. .RS .PP Both types of images share the following options: .IP .EX \-dimension *keyValueList*: Required. Sets the image size. Keys: width (EMU), height (EMU). \-bwMode *(auto|black|blackGray|blackWhite|clr|gray|grayWhite| hidden|invGray|ltGray|white)*: Black\-and\-white mode (default \(dqauto\(dq). .EE .PP Anchor images additionally accept: .IP .EX \-anchorData *keyValueList*: Anchor attributes. Keys: behindDoc, distT, distB, distL, distR, hidden, locked, layoutInCell, allowOverlap, relativeHeight. \-positionH *relativeFrom*: Horizontal position reference (column, character, insideMargin, leftMargin, margin, outsideMargin, page, rightMargin). Default \(dqcolumn\(dq. \-alignH *(left|right|center|inside|outside)*: Horizontal alignment (mutually exclusive with \-posOffsetH). \-posOffsetH *EMU*: Horizontal offset (mutually exclusive with \-alignH). \-positionV *relativeFrom*: Vertical position reference (insideMargin, line, margin, outsideMargin, page, paragraph, topMargin, bottomMargin). Default \(dqparagraph\(dq. \-alignV *(inline|top|center|bottom|inside|outside)*: Vertical alignment (mutually exclusive with \-posOffsetV). \-posOffsetV *EMU*: Vertical offset (mutually exclusive with \-alignV). \-wrapMode *(none|square|topBottom)*: Text wrapping mode (default \(dqnone\(dq). \-wrapData *keyValueList*: Wrap attributes (only with \-wrapMode square). Keys: wrapText, distT, distB, distL, distR. .EE .RE .TP \f[B]import\f[R] \f[I]part\f[R] \f[I]docx\f[R] Imports the given \f[I]part\f[R] from the file \f[I]docx\f[R] into the docx object, replacing what the object had for that part of the docx zip archive. .RS .PP The shortcut \(lqstyles\(rq may be used for word/styles.xml and \(lqnumbering\(rq for word/numbering.xml. .RE .TP \f[B]jumpto\f[R] \f[I]text\f[R] \f[I]markid\f[R] \f[I]?\-option value \&...?\f[R] Appends the text \f[I]text\f[R] to the last paragraph and if the text is clicked as link (typically Ctrl\-Button\-1) the text processor jumps to the mark with the id \f[I]markid\f[R] inside the document. .RS .PP The option/value pairs control locally the appearance of the \f[I]text\f[R] within the paragraph. See CHARACTER OPTIONS for the valid options and the type of their argument. .RE .TP \f[B]mark\f[R] \f[I]markid\f[R] Sets the mark \f[I]markid\f[R] at the end of the last paragraph. .TP \f[B]markstart\f[R] \f[I]name\f[R] Starts a named bookmark span at the current position. The bookmark name must be unique within the document. Use \f[B]markend\f[R] to close the span. .TP \f[B]markend\f[R] \f[I]name\f[R] Ends the bookmark span previously opened by \f[B]markstart\f[R] with the same \f[I]name\f[R]. .TP \f[B]math\f[R] \f[I]?\-option value \&...?\f[R] \f[I]creatingScript\f[R] Creates a math zone. The \f[I]creatingScript\f[R] creates the math content using the math methods described below. By default the math is inline within the current paragraph. Options: .RS .IP .EX \-display *onOffValue*: If on, the math is rendered as a display equation on its own paragraph. \-jc *(left|center|right|centerGroup)*: Justification of a display equation. Ignored when \-display is off. .EE .PP Inside the \f[I]creatingScript\f[R], the following math methods are available. All math methods must be called from within the \f[I]creatingScript\f[R] of a \f[B]math\f[R] call; calling them outside a math zone raises a Tcl error. Invalid option values also raise a Tcl error. .RE .TP \f[B]mrun\f[R] \f[I]?\-option value \&...?\f[R] \f[I]text\f[R] Creates a math run (text within a math zone). Options: .RS .IP .EX \-lit *onOffValue*: Literal (non\-italic) text. \-sty *(p|b|i|bi)*: Math style (plain, bold, italic, bold\-italic). \-scr *(roman|script|fraktur|double\-struck|sans\-serif|monospace)*: Math font script. \-nor *onOffValue*: Normal text (non\-math font). Mutually exclusive with \-sty/\-scr. \-aln *onOffValue*: Alignment point. \-brk *onOffValue*: Line break. \-brkAt *integer*: alignment position after break. .EE .RE .TP \f[B]mfrac\f[R] \f[I]?\-option value \&...?\f[R] \f[I]numeratorScript\f[R] \f[I]denominatorScript\f[R] Creates a fraction. The two scripts create the numerator and denominator content. Options: .RS .IP .EX \-type *(bar|lin|noBar|skw)*: Fraction type. Defaults to bar (stacked with horizontal rule). *lin* gives a linear (inline slash) form, *noBar* stacked without bar, *skw* skewed. .EE .RE .TP \f[B]msub\f[R] \f[I]baseScript\f[R] \f[I]subscriptScript\f[R] Creates a subscript construct. .TP \f[B]msup\f[R] \f[I]baseScript\f[R] \f[I]superscriptScript\f[R] Creates a superscript construct. .TP \f[B]msubsup\f[R] \f[I]baseScript\f[R] \f[I]subscriptScript\f[R] \f[I]superscriptScript\f[R] Creates a simultaneous sub\-superscript construct. .TP \f[B]msqrt\f[R] \f[I]radicandScript\f[R] Creates a square root. .TP \f[B]mroot\f[R] \f[I]degreeScript\f[R] \f[I]radicandScript\f[R] Creates an nth\-root. The \f[I]degreeScript\f[R] produces the root index (e.g.\ 3 for cube root) and \f[I]radicandScript\f[R] the expression under the radical. .TP \f[B]mnary\f[R] \f[I]?\-option value \&...?\f[R] \f[I]baseScript\f[R] Creates an n\-ary operator (summation, product, integral, etc.). Options: .RS .IP .EX \-char *string*: The operator character (e.g. \(dq∑\(dq, \(dq∏\(dq, \(dq∫\(dq). \-limLoc *(undOvr|subSup)*: Limit placement \(em under/over or sub/superscript position. \-grow *onOffValue*: Whether the operator grows with its content. \-sub *script*: Subscript (lower limit) content script. \-sup *script*: Superscript (upper limit) content script. \-subHide *onOffValue*: Hide the subscript. \-supHide *onOffValue*: Hide the superscript. .EE .RE .TP \f[B]mfunc\f[R] \f[I]nameScript\f[R] \f[I]argumentScript\f[R] Creates a function application construct (e.g.\ sin, cos, lim). .TP \f[B]mlimlow\f[R] \f[I]baseScript\f[R] \f[I]lowerLimitScript\f[R] Creates a lower\-limit construct (limit below the base). .TP \f[B]mlimupp\f[R] \f[I]baseScript\f[R] \f[I]upperLimitScript\f[R] Creates an upper\-limit construct (limit above the base). .TP \f[B]maccent\f[R] \f[I]?\-option value \&...?\f[R] \f[I]baseScript\f[R] Creates an accent construct \(em places a diacritical mark (hat, tilde, dot, vector arrow, etc.) above the base expression. .RS .IP .EX \-char *string*: The accent character. Default is the combining circumflex accent (U+0302). Common values: U+0303 (tilde), U+0307 (dot), U+0308 (double dot), U+20D7 (combining right arrow / vector). .EE .RE .TP \f[B]mbar\f[R] \f[I]?\-option value \&...?\f[R] \f[I]baseScript\f[R] Creates an overline or underline bar above or below the base. .RS .IP .EX \-pos *top|bot*: Position of the bar (default \(dqtop\(dq = overline). .EE .RE .TP \f[B]mdelim\f[R] \f[I]?\-option value \&...?\f[R] \f[I]script\f[R] Creates a delimiter construct \(em wraps content in matching delimiters such as parentheses, brackets, braces, absolute\-value bars, norms, floor/ceiling symbols, etc. .RS .PP The \f[I]script\f[R] body creates the content. For a single argument, math methods in the script create content directly within an m:e element. For multiple arguments separated by the separator character, use \f[B]mdelimarg\f[R] within the script. .IP .EX \-begChr *string*: Opening delimiter character (default \(dq(\(dq) \-endChr *string*: Closing delimiter character (default \(dq)\(dq) \-sepChr *string*: Separator character between arguments (default \(dq|\(dq) \-grow *onOffValue*: Delimiters grow to match content height \-shp *centered|match*: Delimiter shape .EE .RE .TP \f[B]mdelimarg\f[R] \f[I]script\f[R] Creates a delimiter argument (m:e child) inside an enclosing mdelim. Each call to mdelimarg wraps its script content in a separate m:e element, enabling multi\-argument delimiters. .TP \f[B]mgroupchr\f[R] \f[I]?\-option value \&...?\f[R] \f[I]baseScript\f[R] Creates a grouping character construct \(em an underbrace, overbrace, or similar character that spans the base expression. Commonly used to label parts of an equation. .RS .IP .EX \-char *string*: The grouping character (default U+23DF = ⏟ bottom curly bracket). Use U+23DE for overbrace (⏞). \-pos *top|bot*: Position of the character (default \(dqbot\(dq) \-vertJc *top|bot*: Vertical justification of the base relative to the grouping character .EE .RE .TP \f[B]mmatrix\f[R] \f[I]?\-option value \&...?\f[R] \f[I]rowScripts\f[R] Creates a matrix. The \f[I]rowScripts\f[R] argument is a list; each element is a script that creates cells via \f[B]mmatcell\f[R] calls. Wrap in \f[B]mdelim\f[R] for bracket/parenthesis notation. .RS .IP .EX \-baseJc *top|center|bottom*: Vertical alignment of the matrix relative to the math baseline \-mcJc *left|center|right*: Column justification \-count *integer*: Number of adjacent columns sharing the justification (1\(en255) .EE .RE .TP \f[B]mmatcell\f[R] \f[I]script\f[R] Creates a matrix cell (m:e child) inside a matrix row. Each call wraps its script content in a separate m:e element. .TP \f[B]numbering\f[R] \f[I]subcmd\f[R] \f[I]args\f[R] Manages numbering definitions (lists, outlines). .RS .PP The supported subcommands are: .PP \f[B]abstractNum\f[R] \f[I]id\f[R] \f[I]levelDefinitions\f[R]: Creates an abstract numbering definition with the given integer \f[I]id\f[R]. The \f[I]levelDefinitions\f[R] argument is a list; each element defines one level using option/value pairs: .IP .EX \-numberFormat *format*: Numbering format (decimal, upperRoman, lowerRoman, upperLetter, lowerLetter, bullet, etc.) \-levelText *string*: Level text template (e.g. \(dq%1.\(dq or \(dq%1.%2\(dq) \-align *alignment*: Number alignment (start, center, end, etc.) \-start *integer*: Starting number (default 1) .EE .PP Paragraph and character options may also be given per level to style the number and the paragraph. .PP A corresponding w:num entry is automatically created with the same numId as the abstractNumId. .PP Example: .IP .EX $doc numbering abstractNum 0 { {\-numberFormat decimal \-levelText \(dq%1.\(dq \-align start} {\-numberFormat lowerLetter \-levelText \(dq%2)\(dq \-align start} } .EE .PP \f[B]abstractNumIds\f[R]: Returns a sorted list of all abstractNum IDs. .PP \f[B]delete\f[R] \f[I]type\f[R] \f[I]id\f[R]: Deletes a numbering definition. \f[I]type\f[R] is either \f[B]abstractNum\f[R] or \f[B]num\f[R]; \f[I]id\f[R] is the integer ID. .RE .TP \f[B]pagebreak\f[R] Appends a page break to the document. .TP \f[B]pagesetup\f[R] \f[I]?\-option value \&...?\f[R] The allowed options are: .RS .IP .EX \-margins keyValueList \-paperSource keyValueList \-sizeAndOrientation keyValueList \-defaultHeader id \-defaultFooter id \-firstHeader id \-firstFooter id \-evenHeader id \-evenFooter id .EE .PP The last block of options set the respectively header or footer. The id has to be returned from a header or footer method call. .IP .EX \-border \-pageNumbering \-sectionType *(continuous|evenPage|nextColumn|nextPage|oddPage)* .EE .PP Specifies the type of the current section break. The default is \f[I]nextPage\f[R]. Use \f[I]continuous\f[R] to start a new section on the same page (e.g.\ for switching between single and multi\-column layout). .IP .EX \-docGrid *keyValueList* .EE .PP Configures the document grid for the section, controlling line pitch and character spacing for CJK and other layout needs. The accepted keys are: .IP .EX type Grid type: \(dqdefault\(dq, \(dqlines\(dq, \(dqlinesAndChars\(dq, or \(dqsnapToChars\(dq. linePitch Distance between lines (integer, in twips). charSpace Additional character pitch (integer, in 4096ths of a point). \-vAlign *(top|center|bottom|both)* .EE .PP Vertical alignment of text on the page. The value \f[I]both\f[R] distributes text evenly between the top and bottom margins (justified). .RE .TP \f[B]paragraph\f[R] \f[I]text\f[R] \f[I]?\-pstyle style? ?\-cstyle style? ?\-option value \&...?\f[R] Appends \f[I]text\f[R] as paragraph to the content of the document. If the \f[I]\-pstyle\f[R] option is given, the referenced paragraph style will be used. If the \f[I]\-cstyle\f[R] option is given the referenced character style will be used. Style values may be given either as the internal style ID (\f[I]w:styleId\f[R]) or as the display name (\f[I]w:name\f[R]). Resolution prefers an exact style\-ID match and falls back to the display name. The other options may locally overwrite a style setting or add more properties. See PARAGRAPH OPTIONS and CHARACTER OPTIONS for the valid options and the type of their argument. .TP \f[B]readpart\f[R] \f[I]part\f[R] \f[I]filename\f[R] Replaces the named XML \f[I]part\f[R] in the docx object with the contents of \f[I]filename\f[R]. The file is parsed as XML and replaces the in\-memory DOM for that part. Example: .RS .IP .EX $doc readpart word/settings.xml mysettings.xml .EE .RE .TP \f[B]replace\f[R] \f[I]from\f[R] \f[I]to\f[R] \f[I]?part_list?\f[R] Replaces every \f[I]from\f[R] substring in any text with \f[I]to\f[R], Only uniformly styled text is replaced (if \f[I]from\f[R] spans over more than one text part it will not be recognized). Without the optional \f[I]part list\f[R] argument all parts of the document (the main documentbody, footnotes, comments pp.) will be processed. If the argument is given then only the named parts will be processed. The elements of the part list may be a Tcl glob expression. Part names given by the \f[I]part list\f[R] argument which are currently not exists in the object will be silently ignored. .TP \f[B]sectionend\f[R] Ends the current section, emitting the stored section properties as a w:sectPr inside the last paragraph. Must be preceded by a \f[B]sectionstart\f[R] call; raises an error otherwise. .TP \f[B]sectionstart\f[R] \f[I]?\-option value \&...?\f[R] Starts a new section in the document. If a previous section was already started (and not ended), it is implicitly ended first. The allowed options are the same as for \f[B]pagesetup\f[R]: \-margins, \-sizeAndOrientation, \-sectionType, \-docGrid, \-vAlign, \-border, \-pageNumbering, header/footer references, etc. .TP \f[B]settings\f[R] \f[I]?\-option value \&...?\f[R] Modifies the document settings (word/settings.xml). Settings may be called multiple times; each call updates or adds the specified settings without affecting those set by earlier calls. .RS .PP Special option: .IP .EX \-reset *onOffValue*: If on, resets all settings to defaults before applying the remaining options. .EE .PP Commonly used settings: .IP .EX \-defaultTabStop *integer*: Default tab stop distance in twips. \-autoHyphenation *onOffValue*: Enable automatic hyphenation. \-evenAndOddHeaders *onOffValue*: Use different headers/footers for even and odd pages. \-hideSpellingErrors *onOffValue*: Hide red squiggly underlines. \-hideGrammaticalErrors *onOffValue*: Hide grammar error marks. \-trackRevisions *onOffValue*: Enable revision tracking. \-mirrorMargins *onOffValue*: Mirror left/right margins for facing pages. \-embedTrueTypeFonts *onOffValue*: Embed TrueType fonts. \-documentProtection *keyValueList*: Protect the document. Keys: edit (readOnly|comments|trackedChanges|forms|none), enforcement (on|off), formatting (on|off), plus optional cryptographic parameters. .EE .PP Many more settings are available. On/off settings use \f[I]onOffValue\f[R]. Refer to the property table in the source for the complete list. .RE .TP \f[B]selectNodes\f[R] \f[I]xpath\f[R] ?\f[I]part\f[R]? \f[I]?selectNodes options?\f[R] Returns the result of the \f[I]xpath\f[R] expression. If no other argument is given the context node will be the document element node of the word/document.xml part of the docx. If the \f[I]part\f[R] argument is given the context node of the expression will be the document element of the docx part identified by this argument. If \f[I]part\f[R] is a relative path inside the docx zip (example: _rels/.rels) then this is used. All parts of the docx inside the word directory may specified without the directory part and the .xml suffix. The optional \f[I]selectNodes options\f[R] are routed throw. .RS .PP All documents accessible by this have the following prefix namespace mappings predefined: .PP .TS tab(@); l l. T{ Prefix T}@T{ Namespace T} _ T{ a T}@T{ http://schemas.openxmlformats.org/drawingml/2006/main| T} T{ ct T}@T{ http://schemas.openxmlformats.org/package/2006/content\-types| T} T{ m T}@T{ http://schemas.openxmlformats.org/officeDocument/2006/math| T} T{ mc T}@T{ http://schemas.openxmlformats.org/markup\-compatibility/2006| T} T{ o T}@T{ urn:schemas\-microsoft\-com:office:office| T} T{ pic T}@T{ http://schemas.openxmlformats.org/drawingml/2006/picture| T} T{ r T}@T{ http://schemas.openxmlformats.org/officeDocument/2006/relationships| T} T{ rel T}@T{ http://schemas.openxmlformats.org/package/2006/relationships| T} T{ sl T}@T{ http://schemas.openxmlformats.org/schemaLibrary/2006/main| T} T{ v T}@T{ urn:schemas\-microsoft\-com:vml| T} T{ w T}@T{ http://schemas.openxmlformats.org/wordprocessingml/2006/main| T} T{ w10 T}@T{ urn:schemas\-microsoft\-com:office:word| T} T{ w14 T}@T{ http://schemas.microsoft.com/office/word/2010/wordml| T} T{ wp T}@T{ http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing| T} T{ wp14 T}@T{ http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing| T} T{ wpg T}@T{ http://schemas.microsoft.com/office/word/2010/wordprocessingGroup| T} T{ wps T}@T{ http://schemas.microsoft.com/office/word/2010/wordprocessingShape| T} .TE .RE .TP \f[B]simplecomment\f[R] \f[I]comment\f[R] \f[I]?\-option value \&...?\f[R] This method creates a comment to the current point in the document. The text content of the comment will be what is given by the argument \f[I]comment\f[R]. For the allowed options see the method \f[I]comment\f[R]. Additionally to this options all PARAGRAPH OPTIONS and CHARACTER OPTIONS are allowed. If given they are applied to format the comment text. .TP \f[B]simplecommentrangeend\f[R] \f[I]id\f[R] \f[I]comment\f[R] \f[I]?\-option value \&...?\f[R] This method marks the end of a range of content in the document and creates a comment to this content range with comment content given by the \f[I]comment\f[R] argument. The \f[I]id\f[R] argument must be the id returned by the corresponding \f[I]commentrangestart\f[R] call. For the allowed options see the method \f[I]comment\f[R]. Additionally to this options all PARAGRAPH OPTIONS and CHARACTER OPTIONS are allowed. If given they are applied to format the comment text. .TP \f[B]simpletable\f[R] \f[I]tabledata\f[R] \f[I]?\-option value \&...?\f[R] Creates a table from a nested list. Each element of \f[I]tabledata\f[R] is a row; each element within a row is a cell\(cqs text content. .RS .PP Example: \f[CR]$doc simpletable {{A1 B1 C1} {A2 B2 C2}}\f[R] .PP Options: .IP .EX \-columnwidths *list*: Column widths (measurements). \-firstStyle *styleName*: Character style for the first row. \-lastStyle *styleName*: Character style for the last row. .EE .PP Table\-level options (\-style, \-width, \-align, \-layout, \-look, \-tableBorders, cell margins) are also accepted \(em see \f[B]table\f[R]. .RE .TP \f[B]style\f[R] \f[I]subcommand\f[R] \f[I]args\f[R] The supported subcommands are: .RS .IP .EX paragraphdefault ?\-option value ...? characterdefault ?\-option value ...? paragraph name ?\-option value ...? character name ?\-option value ...? table name ?\-option value ...? The *name* argument is the display name of the style. The internal style ID (w:styleId) is derived from the name by stripping non\-alphanumeric characters. Use the **\-styleid** option to set the internal ID explicitly if the derived ID would be empty or ambiguous. Both display name and derived ID must be unique within the style type. Additional style creation options: \-basedon styleRef: Parent style to inherit from. Accepts either an internal style ID or a display name (resolved to a style ID internally). The parent must be the same type as the style being created. \-conditional keyValueList: .EE .PP (Table styles only.) Conditional formatting for table regions such as firstRow, lastRow, firstColumn, lastColumn, band1Vert, band1Horz, etc. .IP .EX All methods and options that reference a style (such as **\-pstyle**, **\-cstyle**, **\-style**, **\-basedon**, **\-refstyle**) accept either the internal style ID (preferred, tried first) or the display name (fallback). ids styletype names styletype delete styletype name .EE .RE .TP \f[B]tab\f[R] \f[I]?n?\f[R] Inserts a tab character into the current paragraph. The optional argument \f[I]n\f[R] (default 1) specifies the number of tabs to insert. .TP \f[B]table\f[R] \f[I]?\-option value \&...?\f[R] \f[I]creatingScript\f[R] Creates a table by defining every row and cell individually by the \f[I]creatingScript\f[R] and returns the object id of the created table. The recognized options are: .RS .IP .EX \-columnwidths *list*: List of column widths (measurements). \-style *styleRef*: Table style reference (style ID or display name). \-width *keyValueList*: Table width. Keys: type (auto|dxa|pct|nil), value (measurement or percentage). \-align *(center|end|left|right|start)*: Table alignment. \-layout *keyValueList*: Table layout. Keys: type (autofit|fixed). \-look *keyValueList*: Table conditional formatting flags. Keys: firstRow, lastRow, firstColumn, lastColumn, noHBand, noVBand (all on/off). \-caption *string*: Table caption for accessibility. \-tableBorders: Table border options. For each border position (top, left, bottom, right, insideH, insideV), use \(ga\-Border {type color borderwidth space }\(ga. \-cellMarginTop, \-cellMarginStart, \-cellMarginLeft, \-cellMarginBottom, \-cellMarginEnd, \-cellMarginRight: Default cell margins. Each takes a *keyValueList* with keys type and value. .EE .RE .TP \f[B]tablecell\f[R] \f[I]?\-option value \&...?\f[R] \f[I]creatingScript\f[R] Creates a table cell within a \f[B]tablerow\f[R] script and returns the object id of the created table cell. The \f[I]creatingScript\f[R] creates the cell content (paragraphs, nested tables, etc.). .RS .PP Options: .IP .EX \-cellWidth *keyValueList*: Cell width. Keys: type (auto|dxa|pct|nil), value (measurement or percentage). \-span *integer*: Number of grid columns this cell spans. \-hspan *(restart|continue)*: Horizontal merge state. \-vspan *(restart|continue)*: Vertical merge state. \-vAlign *(top|center|bottom|both)*: Vertical alignment of cell content. \-textDirection *direction*: Text direction within the cell. \-shading *keyValueList*: Cell shading pattern. Keys: type, color, fill (same as paragraph shading). The options \-shading and \-background are mutually exclusive. \-background *RRGGBB*: Shorthand for a solid background fill color. The options \-shading and \-background are mutually exclusive. \-tcFitText *onOffValue*: Shrink text to fit cell width. .EE .PP Cell border options (\-topBorder, \-leftBorder, \-bottomBorder, \-rightBorder, \-tl2brBorder, \-tr2blBorder) and cell margin options are also accepted. .RE .TP \f[B]tablerow\f[R] \f[I]?\-option value \&...?\f[R] \f[I]creatingScript\f[R] Creates a table row within a \f[B]table\f[R] script and returns the object id of the created table row. The \f[I]creatingScript\f[R] creates cells via \f[B]tablecell\f[R] calls. .RS .PP Options: .IP .EX \-rowHeight *keyValueList*: Row height. Keys: value (measurement), hRule (auto|exact|atLeast). \-headerrow *onOffValue*: Mark this row as a header row that repeats on each page. \-cantSplit *onOffValue*: Prevent the row from splitting across pages. \-align *(center|end|left|right|start)*: Row alignment (overrides table alignment). \-cellSpacing *keyValueList*: Cell spacing within the row. Keys: type, value. \-wBefore, \-wAfter *keyValueList*: Width before/after the row (for indented rows). Keys: type, value. .EE .RE .TP \f[B]textbox\f[R] \f[I]?\-option value \&...?\f[R] \f[I]creatingScript\f[R] Creates an anchored text box at the current position and returns the object id of the created text box. The \f[I]creatingScript\f[R] creates the text box content (paragraphs, tables, etc.) inside the box. .RS .PP Options: .IP .EX \-name *string*: Display name for the text box shape. Auto\-generated if omitted. \-dimension *keyValueList*: Required. Sets the text box size. Keys: width (EMU), height (EMU). \-bodyAtts *keyValueList*: Text body attributes. Keys: wrap (none|square), numCol (integer), and other wps:bodyPr attributes. .EE .PP Anchor positioning options (\-anchorData, \-positionH, \-alignH, \-posOffsetH, \-positionV, \-alignV, \-posOffsetV, \-wrapMode, \-wrapData, \-bwMode) are also accepted \(em see \f[B]image\f[R] anchor options. .RE .TP \f[B]url\f[R] \f[I]text\f[R] \f[I]url\f[R] \f[I]?\-option value \&...?\f[R] Append \f[I]text\f[R] to the current paragrah and make that text an hypherlink to \f[I]uri\f[R]. The option/value pairs control the appearance of the \f[I]text\f[R] within the paragraph. See CHARACTER OPTIONS for the valid options and the type of their value. .TP \f[B]write\f[R] \f[I]?filename?\f[R] Writes the object as WordprocessingML docx file to \f[I]filename\f[R]. If the argument is omitted then document.docx will be used. If the filename does not have a suffix, then the suffix .docx will be appended. .TP \f[B]writepart\f[R] \f[I]part\f[R] \f[I]filename\f[R] Writes a single XML part from the docx object to \f[I]filename\f[R]. Raises an error if the part does not exist in the object. .TP \f[B]xpath\f[R] \f[I]xpath\f[R] \f[I]?part?\f[R] \f[I]?selectNodes options?\f[R] An alias for the method \f[I]selectNodes\f[R]. See there for the meaning of the arguments. .TP \f[B]xmlparts\f[R] \f[I]?pattern?\f[R] Returns the paths of the xml parts of the docx object. If the optional argument \f[I]pattern\f[R] is given only the xml parts of the docx docx object which match the \f[I]pattern\f[R] using glob style matching are returned. .SH CHARACTER OPTIONS \f[B]\-bold\f[R] \f[I]onOffValue\f[R] .PP \f[B]\-color\f[R] \f[I]auto|RRGGBB hex value\f[R] .PP \f[B]\-cstyle\f[R] \f[I]styleRef\f[R] .PP \f[B]\-dstrike\f[R] \f[I]onOffValue\f[R] .PP \f[B]\-emboss\f[R] \f[I]onOffValue\f[R] .PP \f[B]\-font\f[R] \f[I]font familiy name\f[R] .PP \f[B]\-fontsize\f[R] \f[I]measure\f[R] .PP If the value has no unit the integer means twentieths of a point. .PP \f[B]\-highlight\f[R] (black|blue|cyan|green|magenta|red|yellow|white|darkBlue|darkCyan|darkGreen|darkMagenta|darkRed|darkYellow|darkGray|lightGray|none) .PP \f[B]\-italic\f[R] \f[I]onOffValue\f[R] .PP \f[B]\-noProof\f[R] \f[I]onOffValue\f[R] .PP \f[B]\-rtl\f[R] \f[I]onOffValue\f[R] .PP \f[B]\-strike\f[R] \f[I]onOffValue\f[R] .PP Toggles strikethrough on the text. .PP \f[B]\-underline\f[R] \f[I]kind\f[R] .PP The allowed \f[I]kind\f[R] values are: .IP .EX single words double thick dotted dottedHeavy dash dashedHeavy dashLong dashLongHeavy dotDash dashDotHeavy dotDotDash dashDotDotHeavy wave wavyHeavy wavyDouble none .EE .PP \f[B]\-verticalAlign\f[R] *(baseline|superscript|subscript) .SH PARAGRAPH OPTIONS \f[B]\-align\f[R] \f[I]kind\f[R] .PP The allowed \f[I]kind\f[R] values are: .IP .EX start center end both mediumKashida distribute numTab highKashida lowKashida thaiDistribute left right .EE .PP \f[B]\-background\f[R] \f[I]RRGGBB hex value\f[R] .PP Sets a solid background fill color on the paragraph. This is a shorthand for \f[CR]\-shading {type clear fill RRGGBB}\f[R]. .PP \f[B]\-bidi\f[R] \f[I]onOffValue\f[R] .PP Right\-to\-left paragraph direction. .PP \f[B]\-indentation\f[R] \f[I]keyValueList\f[R] .PP Sets the paragraph indentation. The accepted keys are: .IP .EX start Left/start indentation (measurement). startChars Left/start indentation in character units. end Right/end indentation (measurement). endChars Right/end indentation in character units. firstLine First line additional indent (measurement). firstLineChars First line indent in character units. hanging Hanging indent (measurement). hangingChars Hanging indent in character units. .EE .PP \f[B]\-keepLines\f[R] \f[I]onOffValue\f[R] .PP Keep all lines of the paragraph on the same page. .PP \f[B]\-keepNext\f[R] \f[I]onOffValue\f[R] .PP Keep the paragraph on the same page as the next paragraph. .PP \f[B]\-level\f[R] \f[I]integer\f[R] .PP Numbering level (used with \f[B]\-numberingStyle\f[R]). Zero\-based. .PP \f[B]\-numberingStyle\f[R] \f[I]integer\f[R] .PP Numbering definition ID to apply to this paragraph. .PP \f[B]\-pageBreakBefore\f[R] \f[I]onOffValue\f[R] .PP Start the paragraph on a new page. .PP \f[B]\-shading\f[R] \f[I]keyValueList\f[R] .PP Sets the paragraph shading pattern. The accepted keys are: .IP .EX type Shading pattern (required). Common values: clear, solid, horzStripe, vertStripe, diagStripe, diagCross, pct10, pct20, pct25, pct50, pct75, etc. color Foreground pattern color (RRGGBB hex or \(dqauto\(dq). fill Background fill color (RRGGBB hex or \(dqauto\(dq). .EE .PP Example: \f[CR]\-shading {type clear fill FFFF00}\f[R] for a yellow background. .PP \f[B]\-spacing\f[R] \f[I]keyValueList\f[R] .PP The value to the option must be a Tcl list of keyword measurement pairs and defines the space before, after and between the lines of the paragraph. The space values are given as measurement .PP The accepted keys are: .IP .EX after Space after the paragraph. before Space before the paragraph. line Line spacing within the paragraph. lineRule How \(dqline\(dq is interpreted: \(dqauto\(dq (default, value is in 240ths of a line), \(dqexact\(dq (value is in twips), or \(dqatLeast\(dq (minimum, value is in twips). .EE .PP \f[B]\-suppressLineNumbers\f[R] \f[I]onOffValue\f[R] .PP Suppress line numbers for this paragraph. .PP \f[B]\-textframe\f[R] \f[I]keyValueList\f[R] .PP Configures the paragraph as a text frame. Keys: width, height, wrap, vAnchor, hAnchor, xAlign, yAlign, dropCap, lines, vSpace, hSpace, hrule, anchorLock. .PP \f[B]\-widowControl\f[R] \f[I]onOffValue\f[R] .PP Enable widow/orphan control for this paragraph. .SH OPTION VALUE TYPES Several option values share the same value types. This types are: .SS MEASUREMENT A measurement is given either as integer value without unit or as integer immediately followed by a unit. If the value is just a number then what distance is specified by the number depends on the option and is documented with the option. The allowed units are: .IP .EX mm Millimeter cm Centimeter in Inch (1in = 2.54cm) pt Point (1pt = 1/72in) pc Pica (1pc = 12pt) pi The same as pc: Pica (1pi = 12pt) .EE .SH DEPENDENCIES .IP .EX Tcl >= 8.6.7 tdom >= 0.9.6 .EE .PP Reading an existing .docx file (as template or for imports) uses the zlib command built into Tcl and needs no additional package. Only if an archive cannot be handled by the built\-in reader, one of the optional fallback backends is used: the Tcl 9 zipfs, tcllib\(cqs zipfile::decode or tclvfs vfs::zip >= 1.0.4. ooxml/doc/ooxml-default.html000664 000765 000024 00000002515 15217572310 016533 0ustar00alexstaff000000 000000 $for(author-meta)$ $endfor$ $if(date-meta)$ $endif$ $if(keywords)$ $endif$ $if(title-prefix)$$title-prefix$ – $endif$$pagetitle$ $for(css)$ $endfor$ $if(math)$ $math$ $endif$ $for(header-includes)$ $header-includes$ $endfor$
$for(include-before)$ $include-before$ $endfor$ $if(title)$

$title$

$if(subtitle)$

$subtitle$

$endif$ $for(author)$

$author$

$endfor$ $if(date)$

$date$

$endif$
$endif$ $if(toc)$ $endif$ $body$ $for(include-after)$ $include-after$ $endfor$
ooxml/doc/ooxml-docx-dev.md000664 000765 000024 00000012351 15213015413 016243 0ustar00alexstaff000000 000000 # RESOURCES There is indeed an official and free available standard for WordprocessingML: and look for the ISO/IEC 29500 documents. You for sure will need the pdf document with a titel as "INTERNATIONAL STANDARD ISO/IEC 29500-1 Fourth edition 2016-11-01 Part 1: Fundamentals and Markup Language Reference". The file name is something crude as C071691e.pdf. A web version of the same content can be found at . Very helpful (indispensable perhaps) is also wml.xsd For introductional material to WordprocessingML see Microsoft has Other libraries do similar things. For python see . For C# and .net see Good Tcl level is required. And tDOM knowledge is helpful, or course. # BASICS Working with Tcl is mostly a pleasure. Working with tDOM hopefully is and working with this Tcl docx framework hopefully will be too. Working with WordprocessingML is not always a pleasure. In some hindsight it looks more like the translation of a binary format into XML than as a well-designed document markup. At least it is a voluminous beast - which is kind of inevitable (to some degree) for a powerful layout markup language. Almost all WordprocessingML elements have no text content. Values and options are carried out by attributes. That attributes are namespaced (for no obvious or good reason). Some elements can have a meaning just by their precence, without any attribute or content. These elements are switches. For example there is an element which switches bold text on if it is not and off if it is. This package does not use this WordprocessingML feature; all of this elements have a *w:val* attribute to explicitly set the switch (and this is used). Most attribute values are some measurement (dimension, size, etc) or a symbol out of a certain list. # GETTING STARTED Looking at the XML data of an unzipped document will be more or less unavoidable part of the work of enhancing or debbuging the library. To help with this a kind of pretty printing tool is part of the source distribution. Look at tools/pp.tcl and read the comment on top. Tcl 9 is required to run the tool. Call it just with the .docx you want to unpack: ``` tclsh9 tools/pp.tcl my.docx ``` One way to get information which WordprocessingML is needed to implement a certain feature is to create a (typically as simple as possible) document with a wordprocessing programm as Libreoffic or Word and to look at the generated XML. The usual next steps are to look up the elements needed in the specification PDF and the xsd file. The next step will be to implement a ooxml::docx interface to create that WordprocessingML content at the right place. It also typically works well to zip an unzipped document back into an .docx. This can be helpful to see what elements and attributes are more or less "noice" for the feature your implementing or to see (by copying parts of the XML from a processor created docx into the docx generated by the ooxml::docx) what additional content is needed for a certain effect. The inserted indentataion by pp.tcl doesn't provide trouble here. At the top level of the unzipped docx do something like: ``` zip -r ../my-rezipped.docx . ``` # GENERATING ELEMENTS AND ATTRIBUTES ON USER INPUT In a lot of cases with the method Create it is possible to create WordprocessingML content directly from option values given by the user. This method expects a list of opion value pairs as argument. The value of an option (as -bold, -margins etc.) must be a Tcl list with at least two elements. The first element of that list is the list of elements to create. The second argument is a list with information about the attributes to set and how the values for the attributes are extracted from the value given to the option and the types of that value. If the second argument has only one element and that element itself is not a list with more than 1 element then the name of the attribute to create is *w:val* and this element is the type callback for the value. Otherwise every element of the second argument list itself is threated as a list. If the second argument list has one element then the name of created attribute will be the first element of that element and the value, after calling the as second element given type callback. will be the value of the option. Otherwise - which means that this option may set more than one attribute at once - the value to the option is seen as a keyword value list. If the list element has two members then the name of the keyword and the name of the attribute to create is the first element of the list and the second argument the type callback. If the list element has three members then the the first element of that list is the keyword, the second element is the name of the attribute to create and the third element is the type callback. If the list the option name points to has three elements then the second list element will be ignored and the processing is done by the specialized procedure given with the third element. If the second argument has two elements then ooxml/doc/ooxml.html000644 000765 000024 00000142242 15221547620 015112 0ustar00alexstaff000000 000000 ooxml(n) | ooxml user documentation

ooxml(n) | ooxml user documentation

NAME

::ooxml::xl_sheets, ::ooxml::xl_read, ::ooxml::xl_write, ::ooxml::tablelist_to_xl - Read and create ECMA-376 Office Open XML Spreadsheets (the .xlsx format)

SYNOPSIS

package require ooxml
::ooxml::xl_sheets file
::ooxml::xl_read file ?-option value ...?
::ooxml::xl_write new ?-option value ...?
::ooxml::tablelist_to_xl tablelist ?-option value ...?

DESCRIPTION

The commands of this package read or create ECMA-376 Office Open XML Spreadsheets (LibreOffice and Excel “.xlsx” files). The three most important are:

::ooxml::xl_read - imports a .xlsx spreadsheet file into a Tcl array
::ooxml::xl_write - creates a spreadsheet object command
::ooxml::tablelist_to_xl - exports a Tcl tablelist to a .xlsx spreadsheet

In this documentation the term workbook means a whole spreadsheet with all its tables. The term worksheet means a specific table of the workbook it belongs to.

All row, column and sheet indices used by this package are zero-based. Cell positions may be given numerically as row,column or in Excel notation; see CELL INDEX.

The package provides the following commands:

::ooxml::arrayDeleteSheet arrayName sheetId ?-sheetname?

Deletes one worksheet from an array read with ::ooxml::xl_read and renumbers the remaining sheets. The array is passed by name (without $). By default sheetId is the zero-based sheet index; with the -sheetname option it is the worksheet name.

  ::ooxml::arrayDeleteSheet workbook 0
  ::ooxml::arrayDeleteSheet workbook "Sheet1" -sheetname
::ooxml::CalcColumnWidth numberOfCharacters ?maximumDigitWidth? ?pixelPadding?

Returns the column width value (for the column method -width option) that fits the given number of characters. The optional arguments maximumDigitWidth (default 7) and pixelPadding (default 5) describe the metrics of the standard font.

  ::ooxml::CalcColumnWidth 16   ;# -> 16.7109375
::ooxml::Column column

Converts the zero-based column number into the column name in Excel notation (0 -> A, 1 -> B, 26 -> AA, …).

::ooxml::Default name value

Sets a package wide default. The only currently supported name is path: the default directory of written files (used e.g. by ::ooxml::tablelist_to_xl if no -path is given). An empty value resets it to the current directory.

::ooxml::RowColumnToString rowcol

Converts a numerical cell index (row,column, zero-based) into Excel notation (0,0 -> A1).

::ooxml::StringToRowColumn name

Converts a cell position in Excel notation into the numerical form (A1 -> 0,0).

::ooxml::tablelist_to_xl tablelist ?-option value …?

Exports the content of the Tk tablelist widget tablelist to a .xlsx file. The recognized options are:

  -callback command: Command to be called once per workbook and
  once per column, to customize styles and column properties.
  See below for the arguments. Default is the built-in callback
  ::ooxml::tablelist_to_xl_callback.

  -path path: Directory of the output file.

  -file filename: Name of the output file (a .xlsx suffix is
  appended if missing).

  -creator name: Creator property of the spreadsheet.

  -name name: Name of the (single) worksheet.

  -rootonly: Export only the root level of the tablelist (no
  child items).

  -addtimestamp: Add a timestamp to the output file name.

  -globalstyle: Write the cells with the column styles set by
  the callback.

The callback is called with the arguments

  spreadsheet sheet maxcol column title width align sortmode hide

where spreadsheet is the spreadsheet object, sheet the worksheet handle and maxcol the number of columns. It is called once with column = -1 for the whole workbook (for example to set the default date style) and then once per column with the tablelist column properties title, width, align, sortmode and hide.

  proc myCallback {spreadsheet sheet maxcol column title width align sortmode hide} {
      if {$column == -1} {
          set datestyle [$spreadsheet style -numfmt [$spreadsheet numberformat -datetime]]
          $spreadsheet defaultdatestyle $datestyle
      } elseif {$align eq "right"} {
          $spreadsheet column $sheet -index $column -style [$spreadsheet style -horizontal right]
      }
  }
::ooxml::xl_read file ?-option value …?

Reads the given .xlsx file and returns its contents as a flat Tcl array (to be caught with array set). See RESULT ARRAY for the keys of the returned array. The recognized options are:

  -valuesonly: Read only the cell values, no formatting,
  formulas or sheet properties.

  -keylist: Additionally build the S,k key (see
  RESULT ARRAY), a dictionary of the non-empty columns per row.

  -sheets pattern: Read only the worksheets whose zero-based
  sheet index matches the glob pattern.

  -sheetnames pattern: Read only the worksheets whose name
  matches the glob pattern.

  If neither -sheets nor -sheetnames is given all worksheets
  are read.

  -datefmt format: [clock format] string used to convert date
  cells into the value keys (default "%Y-%m-%d %H:%M:%S").

  -as array: Format of the return value. Currently array is
  the only supported value.

A simple example:

  array set workbook [::ooxml::xl_read file.xlsx]
  foreach key [lsort -dictionary [array names workbook 0,v,*]] {
      lassign [split $key ,] sheet tag row col
      puts "$row,$col = $workbook($key)"
  }
::ooxml::xl_sheets file

Returns information about the worksheets of the given .xlsx file without reading any cell data. The result is a Tcl list with two elements per worksheet: the zero-based sheet index and a dictionary with the keys sheetId (the internal sheet id), name (the display name of the worksheet) and rId (the internal relationship id).

  foreach {index info} [::ooxml::xl_sheets file.xlsx] {
      puts "$index: [dict get $info name]"
  }
::ooxml::xl_write new ?-option value …?

Creates a spreadsheet object command to build a workbook from scratch:

  set spreadsheet [::ooxml::xl_write new ?-option value ...?]

The recognized options are:

  -creator name: The creator property of the spreadsheet.

  -created timestamp: The creation time property of the
  spreadsheet. The value is either an integer (seconds, as
  returned by [clock seconds]) or a date string in local time.

  -modifiedby name: The modified-by property of the
  spreadsheet.

  -modified timestamp: The modification time property of the
  spreadsheet. For the value see -created.

  -application name: The application property of the
  spreadsheet.

The created spreadsheet object commands currently support the following methods:

autofilter sheet indexFrom indexTo

Adds an autofilter (filter and sort controls on the header row) to the worksheet, spanning from cell indexFrom to cell indexTo (see CELL INDEX).

  $spreadsheet autofilter $sheet 0,0 0,5
border ?-option value …?

Defines a border style for the current workbook and returns an ID (BORDERID) to refer to that style. The recognized options are:

  -list: Returns the list of currently defined border styles
  instead of a BORDERID.

  -leftstyle BORDERLINESTYLE
  -rightstyle BORDERLINESTYLE
  -topstyle BORDERLINESTYLE
  -bottomstyle BORDERLINESTYLE
  -diagonalstyle BORDERLINESTYLE

  See BORDERLINESTYLE for the valid values.

  -leftcolor COLOR
  -rightcolor COLOR
  -topcolor COLOR
  -bottomcolor COLOR
  -diagonalcolor COLOR

  See COLOR for the valid values.

  -diagonaldirection (up|down)

  -tag tagname: Gives the border style a name. This name may be
  used instead of the returned BORDERID.

See BORDERLINESTYLE and COLOR for the valid option values.

cell sheet ?data? ?-option value …?

Writes the value data into a cell of the worksheet sheet and returns the position of the written cell as row,column. Without the -index option the cell is placed in the current row at the next column (see CELL INDEX for the autoincrement behaviour). The recognized options are:

  -index index: Position of the cell, either as row,column or
  in Excel notation. Also accepts a bare column number to place
  the cell in the current row with columns skipped.

  -style STYLEID: Style of the cell, from the method style.

  -formula formula: Enter an Excel formula (e.g. "A1+B1"). The
  data argument is usually empty then, the application
  computes the value.

  -formulaidx integer: Shared formula index. A cell defining a
  shared formula gives -formula, -formularef and -formulaidx;
  the dependent cells give only -formulaidx.

  -formularef range: The range the shared formula spans, either
  in Excel notation (C3:C5) or numerically (2,2:4,2).

  -string: Store the value as string in any case.

  -nostring: Override a column-level -string setting for this
  cell.

  -nozero: Do not output the value if it is zero.

  -zero: Override a column-level -nozero setting for this cell.

  -globalstyle: Apply the column style to this cell.

  -height height: Sets the row height of the current row.

  -hyperlink url: Makes the cell a hyperlink to url.

  -tooltip text: Tooltip for the hyperlink (only used together
  with -hyperlink).
column sheet ?-option value …?

Defines the properties of a column of the worksheet sheet and returns the column number. Without the -index option the next column is used. The recognized options are:

  -index index: Column number.

  -to index: Last column number, if the definition should span
  a range of columns.

  -width width: Column width in characters of the standard font
  (may be fractional, see also ::ooxml::CalcColumnWidth).

  -style STYLEID: Default style for the cells of the column.
  Note that a cell only uses it if written with -globalstyle.

  -bestfit: Sets the bestFit flag of the column.

  -customwidth: Sets the customWidth flag of the column.

  -string: Store the values of the cells of this column as
  string in any case (a cell may override this with -nostring).

  -nozero: Do not output zero values in this column (a cell may
  override this with -zero).

  -calcfit: Calculates the column width from the length of the
  longest value written to the column (via
  ::ooxml::CalcColumnWidth) if that is wider than a given
  -width.
defaultdatestyle STYLEID

Sets the default style for date cells. Values recognized as dates are formatted with this style if the cell does not have an explicit -style.

  set datestyle [$spreadsheet style -numfmt [$spreadsheet numberformat -datetime]]
  $spreadsheet defaultdatestyle $datestyle
fill ?-option value …?

Defines a fill style for the current workbook and returns an ID (FILLID) to refer to that style. The recognized options are:

  -list: Returns the list of currently defined fills instead of
  a FILLID.

  -patterntype PATTERNTYPE: See PATTERNTYPE for the usual
  values (default "none").

  -fgcolor COLOR: Foreground (pattern) color. See COLOR for the
  valid values.

  -bgcolor COLOR: Background color. See COLOR for the valid
  values.

  -tag tagname: Gives the fill a name. This name may be used
  instead of the returned FILLID.

See PATTERNTYPE and COLOR for the valid option values.

font ?-option value …?

Defines a font for the current workbook and returns an ID (FONTID) to refer to that font. The recognized options are:

  -list: Returns the list of currently defined fonts instead of
  a FONTID.

  -name name: Font name (default "Calibri").

  -family family: Font family number (default 2).

  -size size: Font size in points (default 12).

  -color COLOR: See COLOR for the valid values.

  -scheme scheme: Font scheme (default "minor").

  -bold: Bold text.

  -italic: Italic text.

  -underline: Underlined text.

  -tag tagname: Gives the font a name. This name may be used
  instead of the returned FONTID.

See COLOR for the valid -color values.

freeze sheet index

Freezes the panes above and left of the given cell index (see CELL INDEX), so they stay visible while scrolling.

  $spreadsheet freeze $sheet 1,0   ;# freeze the first row
merge sheet indexFrom indexTo

Merges the cell range with the corners indexFrom and indexTo (see CELL INDEX) into one cell.

  $spreadsheet merge $sheet 40,0 40,2
  $spreadsheet merge $sheet A42 A44
numberformat ?-option value …?

Defines a number format for the current workbook and returns an ID (NUMFMTID) to refer to that format. The recognized options are:

  -format format: Any Excel format string (e.g. {#,##0.00 "€"}).

  -general: Excel general format.

  -date: Date format.

  -time: Time format.

  -datetime: Date/time format.

  -iso8601: Date/time in ISO 8601 notation.

  -number: Integer.

  -decimal: Decimal number with 2 decimal places.

  -red: Color negative values red (may be combined with -number
  and -decimal).

  -separator: Thousands separators (may be combined with
  -number and -decimal).

  -fraction: Fractions.

  -scientific: Scientific notation.

  -percent: Percentage.

  -text, -string: Text format.

  -tag tagname: Gives the format a name. This name may be used
  instead of the returned NUMFMTID.
pageMargins sheet ?-option value …?

Sets the page margins of the worksheet sheet. The recognized options are:

  -left -right -top -bottom -header -footer

  All options expect a floating point value in inch.

If some page margins of a worksheet are set with this method then all margins of that worksheet are set, either from the options given in the method call or from the current pageMarginsDefault values, if a margin was not in the method call.

pageMarginsDefault ?-option value …?

Sets the page margins of all worksheets which do not have individual margin settings. The options are the same as for pageMargins. The default margins are:

Margin Inch
left 0.75
right 0.75
top 1
bottom 1
header 0.5
footer 0.5
pageSetup sheet ?-option value …?

Sets the page setup of the worksheet sheet.

Caveat: If no page setup properties at all are set for a sheet, applications use defaults derived from other sources. But if at least one page setup property is explicitly set with this method, the other properties not set will get the default value from the specification, which may be another value than without any page setup at all. For example if you only set the -orientation of a sheet then this may also result in another page size (because the application page size default may differ from the default recommended by the specification, which is Letter paper).

The recognized options are:

  -blackAndWhite boolean: Print black and white. Default:
  false.

  -cellComments (none|asDisplayed|atEnd): How to print cell
  comments. Default: none.

  -copies integer: Number of copies to print. Default: 1.

  -draft boolean: Print without graphics. Default: false.

  -errors (displayed|blank|dash|NA): How to print cell values
  of cells with errors. Default: displayed.

  -firstPageNumber integer: Page number of the first printed
  page; see -useFirstPageNumber. Default: 1.

  -fitToHeight integer: Number of vertical pages to fit on.
  Default: 1.

  -fitToWidth integer: Number of horizontal pages to fit on.
  Default: 1.

  -horizontalDpi integer: Horizontal print resolution of the
  device. Default: 600.

  -orientation (default|portrait|landscape): Orientation of the
  page. Default: default.

  -pageOrder (downThenOver|overThenDown): Order of the printed
  pages. Default: downThenOver.

  -paperHeight height: Height of custom paper as a number
  immediately followed by a unit identifier (as 297mm or 11in).
  No default.

  -paperWidth width: Width of custom paper as a number
  immediately followed by a unit identifier (as 210mm or
  8.5in). No default.

  The specification says that when -paperHeight and -paperWidth
  are specified, the rendering application shall ignore
  -paperSize.

  -paperSize paperSizeID: Specifies the paper size. Default: 1
  (Letter). See PAPER SIZE IDS for the defined values; the
  behaviour for other values is implementation-defined.

  -scale integer: Print scaling in percent. The rendering
  application may respect only values ranging from 10 to 400.
  Overridden when -fitToWidth and/or -fitToHeight are in use.
  Default: 100.

  -useFirstPageNumber boolean: Use the -firstPageNumber value
  for the first page number and do not auto number the pages.
  Default: false.

  -usePrinterDefaults boolean: Use the printer defaults (or the
  defaults of the print job).

  -verticalDpi integer: Vertical print resolution of the
  device. Default: 600.

See PAPER SIZE IDS for the possible -paperSize values.

presetsheets arrayName

Creates worksheets from an array previously read with ::ooxml::xl_read, including their data. The array is passed by name (without $). The sheets are created in their original order. The method adds the key sheetmap to the array: a dict mapping the original sheet index to the newly created worksheet handle. Usually combined with presetstyles:

  array set workbook [::ooxml::xl_read original.xlsx]
  set spreadsheet [::ooxml::xl_write new]
  $spreadsheet presetstyles workbook
  $spreadsheet presetsheets workbook
presetstyles arrayName

Takes over the style definitions (number formats, fonts, fills, borders and cell styles) from an array previously read with ::ooxml::xl_read. The array is passed by name (without $).

printarea sheet indexFrom indexTo

Sets the print area of the worksheet sheet, spanning from cell indexFrom to cell indexTo (see CELL INDEX).

  $spreadsheet printarea $sheet A1 C3
  $spreadsheet printarea $sheet 1,1 2,2
row sheet ?-option value …?

Starts a new row in the worksheet sheet and returns the row number. Without the -index option the next row is used; the column autoincrement is reset (see CELL INDEX). The recognized options are:

  -index index: Row number to jump to.

  -height height: Row height in points.
rowheight sheet row height

Sets the height of the given row (zero-based) of the worksheet sheet to height points, independently of writing cells.

  $spreadsheet rowheight $sheet 33 20
style ?-option value …?

Defines a cell style for the current workbook and returns an ID (STYLEID) to refer to that style. The recognized options are:

  -list: Returns the list of currently defined styles instead
  of a STYLEID.

  -numfmt NUMFMTID: From the method numberformat.

  -font FONTID: From the method font.

  -fill FILLID: From the method fill.

  -border BORDERID: From the method border.

  -xf XFID: Base cell format record to derive from.

  -horizontal alignment: Horizontal alignment of the cell
  content (e.g. left, center, right).

  -vertical alignment: Vertical alignment of the cell content
  (e.g. top, center, bottom).

  -rotate degree: Rotation of the cell content in degrees.

  -wrap: Enables text wrapping within the cell.

  -tag tagname: Gives the style a name. This name may be used
  instead of the returned STYLEID.
view ?-option value …?

Sets the workbook view properties. The recognized options are:

  -activetab tab: Zero-based index of the worksheet shown when
  the file is opened.

  -x twips -y twips: Position of the workbook window.

  -width twips -height twips: Size of the workbook window.

  -list: Returns the current view settings instead of setting
  them.
worksheet name

Creates a new worksheet with the given name and returns the sheet handle (SHEETID) used as first argument by the cell related methods. The characters : \ / ? * in the name are replaced and the name is truncated to the 31 characters allowed by the format.

write filename

Writes the spreadsheet to the file filename. If the filename does not have the suffix .xlsx then it is appended. If filename is empty, spreadsheetml.xlsx is used.

RESULT ARRAY

::ooxml::xl_read returns a flat array. In the following key table S stands for the zero-based sheet index and R,C for the zero-based row and column index:

Key Content
sheets List of the sheet indices that have been read
S,n Worksheet name
S,max_row Largest used row index of the worksheet
S,max_column Largest used column index of the worksheet
S,v,R,C Cell value (present for every non-empty cell)
S,d,R,C Raw date/time serial if the cell is a date cell
S,s,R,C Style id of the cell
S,t,R,C Cell type (s = shared string)
S,c,R,C Cell position in Excel notation (e.g. B7)
S,f,R,C Formula dict: keys f (formula), i (shared formula index), r (shared formula range)
S,l,IDX Hyperlink dict: keys l (target), t (tooltip)
S,k Dict row -> list of non-empty columns (only with the -keylist option)
S,filter Autofilter ranges
S,freeze Freeze pane position
S,merge List of merged cell ranges
S,printarea Print area range
S,rowheight Row height settings
S,cols Number of column definitions
S,col,N Dict with the properties of column definition N
S,pageMargins Page margin settings
S,pageSetup Page setup settings
view Workbook view settings
s,… Style metadata (s,@ s,styles,N s,fonts,N s,fills,N s,borders,N s,numFmts,N s,numFmtsIds), consumed by presetstyles and presetsheets

With the -valuesonly option only the sheets, S,n, S,max_row, S,max_column and S,v,R,C keys are present.

CELL INDEX

Methods and options expecting a cell position accept it in two equivalent forms: numerically as row,column with zero-based row and column numbers, or in Excel notation (column letters followed by the one-based row number). 0,0 and A1 describe the same cell, 3,2 and C4 also.

The methods row, column and cell work with an autoincrement mechanism: without an explicit -index option row starts the next row, cell writes to the next column of the current row and column defines the next column. An explicit -index repositions; the autoincrement continues from there.

$spreadsheet row $sheet
$spreadsheet cell $sheet A           ;# 0,0
$spreadsheet cell $sheet B -index 4  ;# 0,4 (columns 1-3 stay empty)
$spreadsheet cell $sheet C           ;# 0,5
$spreadsheet row $sheet -index 3     ;# jump to row 3
$spreadsheet cell $sheet D           ;# 3,0

For writing prefer the autoincrement wherever possible: call $spreadsheet row $sheet once per row and write the cells in order without -index. This avoids off-by-one and index bookkeeping errors.

OPTION VALUE TYPES

Several option values share the same value types. These types are:

COLOR

There are several kinds of valid values:

The value may be auto or none.

If not, the value may be the index number of a predefined color (an integer between 0 and 65 including). See the list below.

If not, the value may be the name of a predefined color. Case is ignored. See the list below.

If not, the value may be a 6 digit hexadecimal number, which is then used as RGB value.

The list of predefined colors is:

Color ID Name (A)RGB
0 Black 00000000
1 White 00FFFFFF
2 Red 00FF0000
3 Lime 0000FF00
4 Blue 000000FF
5 Yellow 00FFFF00
6 Fuchsia 00FF00FF
7 Aqua 0000FFFF
8 Black 00000000
9 White 00FFFFFF
10 Red 00FF0000
11 Lime 0000FF00
12 Blue 000000FF
13 Yellow 00FFFF00
14 Fuchsia 00FF00FF
15 Aqua 0000FFFF
16 Maroon 00800000
17 Green 00008000
18 Navy 00000080
19 Olive 00808000
20 Purple 00800080
21 Teal 00008080
22 Silver 00C0C0C0
23 Gray 00808080
24 Portage 009999FF
25 Lipstick 00993366
26 Cream 00FFFFCC
27 LightCyan 00CCFFFF
28 Purple 00660066
29 LightCoral 00FF8080
30 NavyBlue 000066CC
31 LavenderBlue 00CCCCFF
32 Navy 00000080
33 Fuchsia 00FF00FF
34 Yellow 00FFFF00
35 Aqua 0000FFFF
36 Purple 00800080
37 Maroon 00800000
38 Teal 00008080
39 Blue 000000FF
40 DeepSkyBlue 0000CCFF
41 LightCyan 00CCFFFF
42 BlueRomance 00CCFFCC
43 Canary 00FFFF99
44 LightSkyBlue 0099CCFF
45 CarnationPink 00FF99CC
46 Mauve 00CC99FF
47 PeachOrange 00FFCC99
48 RoyalBlue 003366FF
49 MediumTurquoise 0033CCCC
50 Citrus 0099CC00
51 TangerineYellow 00FFCC00
52 OrangePeel 00FF9900
53 SafetyOrange 00FF6600
54 Scampi 00666699
55 Nobel 00969696
56 PrussianBlue 00003366
57 Eucalyptus 00339966
58 Myrtle 00003300
59 Karaka 00333300
60 SaddleBrown 00993300
61 Lipstick 00993366
62 DarkSlateBlue 00333399
63 NightRider 00333333
64 SystemForeground n/a
65 SystemBackground n/a

BORDERLINESTYLE

The list of possible values is:

dashDot
dashDotDot
dashed
dotted
double
hair
medium
mediumDashDot
mediumDashDotDot
none
slantDashDot
thick
thin

PATTERNTYPE

An ECMA-376 fill pattern type. The usual values are:

none
solid
darkDown
darkGray
darkGrid
darkHorizontal
darkTrellis
darkUp
darkVertical
gray0625
gray125
lightDown
lightGray
lightGrid
lightHorizontal
lightTrellis
lightUp
lightVertical
mediumGray

PAPER SIZE IDS

The possible -paperSize values and their meaning are:

Paper Size ID Paper Size
1 Letter paper (8.5 in. by 11 in.)
2 Letter small paper (8.5 in. by 11 in.)
3 Tabloid paper (11 in. by 17 in.)
4 Ledger paper (17 in. by 11 in.)
5 Legal paper (8.5 in. by 14 in.)
6 Statement paper (5.5 in. by 8.5 in.)
7 Executive paper (7.25 in. by 10.5 in.)
8 A3 paper (297 mm by 420 mm)
9 A4 paper (210 mm by 297 mm)
10 A4 small paper (210 mm by 297 mm)
11 A5 paper (148 mm by 210 mm)
12 B4 paper (250 mm by 353 mm)
13 B5 paper (176 mm by 250 mm)
14 Folio paper (8.5 in. by 13 in.)
15 Quarto paper (215 mm by 275 mm)
16 Standard paper (10 in. by 14 in.)
17 Standard paper (11 in. by 17 in.)
18 Note paper (8.5 in. by 11 in.)
19 #9 envelope (3.875 in. by 8.875 in.)
20 #10 envelope (4.125 in. by 9.5 in.)
21 #11 envelope (4.5 in. by 10.375 in.)
22 #12 envelope (4.75 in. by 11 in.)
23 #14 envelope (5 in. by 11.5 in.)
24 C paper (17 in. by 22 in.)
25 D paper (22 in. by 34 in.)
26 E paper (34 in. by 44 in.)
27 DL envelope (110 mm by 220 mm)
28 C5 envelope (162 mm by 229 mm)
29 C3 envelope (324 mm by 458 mm)
30 C4 envelope (229 mm by 324 mm)
31 C6 envelope (114 mm by 162 mm)
32 C65 envelope (114 mm by 229 mm)
33 B4 envelope (250 mm by 353 mm)
34 B5 envelope (176 mm by 250 mm)
35 B6 envelope (176 mm by 125 mm)
36 Italy envelope (110 mm by 230 mm)
37 Monarch envelope (3.875 in. by 7.5 in.).
38 6 3/4 envelope (3.625 in. by 6.5 in.)
39 US standard fanfold (14.875 in. by 11 in.)
40 German standard fanfold (8.5 in. by 12 in.)
41 German legal fanfold (8.5 in. by 13 in.)
42 ISO B4 (250 mm by 353 mm)
43 Japanese double postcard (200 mm by 148 mm)
44 Standard paper (9 in. by 11 in.)
45 Standard paper (10 in. by 11 in.)
46 Standard paper (15 in. by 11 in.)
47 Invite envelope (220 mm by 220 mm)
50 Letter extra paper (9.275 in. by 12 in.)
51 Legal extra paper (9.275 in. by 15 in.)
52 Tabloid extra paper (11.69 in. by 18 in.)
53 A4 extra paper (236 mm by 322 mm)
54 Letter transverse paper (8.275 in. by 11 in.)
55 A4 transverse paper (210 mm by 297 mm)
56 Letter extra transverse paper (9.275 in. by 12 in.)
57 SuperA/SuperA/A4 paper (227 mm by 356 mm)
58 SuperB/SuperB/A3 paper (305 mm by 487 mm)
59 Letter plus paper (8.5 in. by 12.69 in.)
60 A4 plus paper (210 mm by 330 mm)
61 A5 transverse paper (148 mm by 210 mm)
62 JIS B5 transverse paper (182 mm by 257 mm)
63 A3 extra paper (322 mm by 445 mm)
64 A5 extra paper (174 mm by 235 mm)
65 ISO B5 extra paper (201 mm by 276 mm)
66 A2 paper (420 mm by 594 mm)
67 A3 transverse paper (297 mm by 420 mm)
68 A3 extra transverse paper (322 mm by 445 mm)
69 Japanese Double Postcard (200 mm x 148 mm)
70 A6 (105 mm x 148 mm)
71 Japanese Envelope Kaku #2
72 Japanese Envelope Kaku #3
73 Japanese Envelope Chou #3
74 Japanese Envelope Chou #4
75 Letter Rotated (11 in x 8.5 in)
76 A3 Rotated (420 mm x 297 mm)
77 A4 Rotated (297 mm x 210 mm)
78 A5 Rotated (210 mm x 148 mm)
79 B4 (JIS) Rotated (364 mm x 257 mm)
80 B5 (JIS) Rotated (257 mm x 182 mm)
81 Japanese Postcard Rotated (148 mm x 100 mm)
82 Double Japanese Postcard Rotated (148 mm x 200 mm)
83 A6 Rotated (148 mm x 105 mm)
84 Japanese Envelope Kaku #2 Rotated
85 Japanese Envelope Kaku #3 Rotated
86 Japanese Envelope Chou #3 Rotated
87 Japanese Envelope Chou #4 Rotated
88 B6 (JIS) (128 mm x 182 mm)
89 B6 (JIS) Rotated (182 mm x 128 mm)
90 (12 in x 11 in)
91 Japanese Envelope You #4
92 Japanese Envelope You #4 Rotated
93 PRC 16K (146 mm x 215 mm)
94 PRC 32K (97 mm x 151 mm)
95 PRC 32K(Big) (97 mm x 151 mm)
96 PRC Envelope #1 (102 mm x 165 mm)
97 PRC Envelope #2 (102 mm x 176 mm)
98 PRC Envelope #3 (125 mm x 176 mm)
99 PRC Envelope #4 (110 mm x 208 mm)
100 PRC Envelope #5 (110 mm x 220 mm)
101 PRC Envelope #6 (120 mm x 230 mm)
102 PRC Envelope #7 (160 mm x 230 mm)
103 PRC Envelope #8 (120 mm x 309 mm)
104 PRC Envelope #9 (229 mm x 324 mm)
105 PRC Envelope #10 (324 mm x 458 mm)
106 PRC 16K Rotated
107 PRC 32K Rotated
108 PRC 32K(Big) Rotated
109 PRC Envelope #1 Rotated (165 mm x 102 mm)
110 PRC Envelope #2 Rotated (176 mm x 102 mm)
111 PRC Envelope #3 Rotated (176 mm x 125 mm)
112 PRC Envelope #4 Rotated (208 mm x 110 mm)
113 PRC Envelope #5 Rotated (220 mm x 110 mm)
114 PRC Envelope #6 Rotated (230 mm x 120 mm)
115 PRC Envelope #7 Rotated (230 mm x 160 mm)
116 PRC Envelope #8 Rotated (309 mm x 120 mm)
117 PRC Envelope #9 Rotated (324 mm x 229 mm)
118 PRC Envelope #10 Rotated (458 mm x 324 mm)

DEPENDENCIES

Tcl >= 8.6.7
tdom >= 0.9.0

Reading .xlsx files uses the zlib command built into Tcl and needs no additional package. Only if an archive cannot be handled by the built-in reader (e.g. ZIP64), one of the optional fallback backends is used: the Tcl 9 zipfs, tcllib’s zipfile::decode or tclvfs vfs::zip >= 1.0.4.

ooxml/doc/ooxml.n000644 000765 000024 00000104545 15221547620 014407 0ustar00alexstaff000000 000000 '\" t .\" Automatically generated by Pandoc 3.10 .\" .TH "ooxml" "n" "" "" "ooxml user documentation" .SH NAME ::ooxml::xl_sheets, ::ooxml::xl_read, ::ooxml::xl_write, ::ooxml::tablelist_to_xl \- Read and create ECMA\-376 Office Open XML Spreadsheets (the .xlsx format) .SH SYNOPSIS .IP .EX package require ooxml ::ooxml::xl_sheets file ::ooxml::xl_read file ?\-option value ...? ::ooxml::xl_write new ?\-option value ...? ::ooxml::tablelist_to_xl tablelist ?\-option value ...? .EE .SH DESCRIPTION The commands of this package read or create ECMA\-376 Office Open XML Spreadsheets (LibreOffice and Excel \(lq.xlsx\(rq files). The three most important are: .IP .EX ::ooxml::xl_read \- imports a .xlsx spreadsheet file into a Tcl array ::ooxml::xl_write \- creates a spreadsheet object command ::ooxml::tablelist_to_xl \- exports a Tcl tablelist to a .xlsx spreadsheet .EE .PP In this documentation the term workbook means a whole spreadsheet with all its tables. The term worksheet means a specific table of the workbook it belongs to. .PP All row, column and sheet indices used by this package are zero\-based. Cell positions may be given numerically as \f[I]row,column\f[R] or in Excel notation; see CELL INDEX. .PP The package provides the following commands: .TP \f[B]::ooxml::arrayDeleteSheet\f[R] \f[I]arrayName\f[R] \f[I]sheetId\f[R] \f[I]?\-sheetname?\f[R] Deletes one worksheet from an array read with \f[I]::ooxml::xl_read\f[R] and renumbers the remaining sheets. The array is passed by name (without \f[CR]$\f[R]). By default \f[I]sheetId\f[R] is the zero\-based sheet index; with the \f[B]\-sheetname\f[R] option it is the worksheet name. .RS .IP .EX ::ooxml::arrayDeleteSheet workbook 0 ::ooxml::arrayDeleteSheet workbook \(dqSheet1\(dq \-sheetname .EE .RE .TP \f[B]::ooxml::CalcColumnWidth\f[R] \f[I]numberOfCharacters\f[R] \f[I]?maximumDigitWidth?\f[R] \f[I]?pixelPadding?\f[R] Returns the column width value (for the \f[B]column\f[R] method \f[B]\-width\f[R] option) that fits the given number of characters. The optional arguments \f[I]maximumDigitWidth\f[R] (default 7) and \f[I]pixelPadding\f[R] (default 5) describe the metrics of the standard font. .RS .IP .EX ::ooxml::CalcColumnWidth 16 ;# \-> 16.7109375 .EE .RE .TP \f[B]::ooxml::Column\f[R] \f[I]column\f[R] Converts the zero\-based \f[I]column\f[R] number into the column name in Excel notation (0 \-> A, 1 \-> B, 26 \-> AA, \&...). .TP \f[B]::ooxml::Default\f[R] \f[I]name\f[R] \f[I]value\f[R] Sets a package wide default. The only currently supported \f[I]name\f[R] is \f[I]path\f[R]: the default directory of written files (used e.g.\ by \f[I]::ooxml::tablelist_to_xl\f[R] if no \f[B]\-path\f[R] is given). An empty \f[I]value\f[R] resets it to the current directory. .TP \f[B]::ooxml::RowColumnToString\f[R] \f[I]rowcol\f[R] Converts a numerical cell index (\f[I]row,column\f[R], zero\-based) into Excel notation (0,0 \-> A1). .TP \f[B]::ooxml::StringToRowColumn\f[R] \f[I]name\f[R] Converts a cell position in Excel notation into the numerical form (A1 \-> 0,0). .TP \f[B]::ooxml::tablelist_to_xl\f[R] \f[I]tablelist\f[R] \f[I]?\-option value \&...?\f[R] Exports the content of the Tk tablelist widget \f[I]tablelist\f[R] to a \&.xlsx file. The recognized options are: .RS .IP .EX \-callback command: Command to be called once per workbook and once per column, to customize styles and column properties. See below for the arguments. Default is the built\-in callback ::ooxml::tablelist_to_xl_callback. \-path path: Directory of the output file. \-file filename: Name of the output file (a .xlsx suffix is appended if missing). \-creator name: Creator property of the spreadsheet. \-name name: Name of the (single) worksheet. \-rootonly: Export only the root level of the tablelist (no child items). \-addtimestamp: Add a timestamp to the output file name. \-globalstyle: Write the cells with the column styles set by the callback. .EE .PP The callback is called with the arguments .IP .EX spreadsheet sheet maxcol column title width align sortmode hide .EE .PP where \f[I]spreadsheet\f[R] is the spreadsheet object, \f[I]sheet\f[R] the worksheet handle and \f[I]maxcol\f[R] the number of columns. It is called once with \f[I]column\f[R] = \-1 for the whole workbook (for example to set the default date style) and then once per column with the tablelist column properties \f[I]title\f[R], \f[I]width\f[R], \f[I]align\f[R], \f[I]sortmode\f[R] and \f[I]hide\f[R]. .IP .EX proc myCallback {spreadsheet sheet maxcol column title width align sortmode hide} { if {$column == \-1} { set datestyle [$spreadsheet style \-numfmt [$spreadsheet numberformat \-datetime]] $spreadsheet defaultdatestyle $datestyle } elseif {$align eq \(dqright\(dq} { $spreadsheet column $sheet \-index $column \-style [$spreadsheet style \-horizontal right] } } .EE .RE .TP \f[B]::ooxml::xl_read\f[R] \f[I]file\f[R] \f[I]?\-option value \&...?\f[R] Reads the given .xlsx \f[I]file\f[R] and returns its contents as a flat Tcl array (to be caught with \f[CR]array set\f[R]). See RESULT ARRAY for the keys of the returned array. The recognized options are: .RS .IP .EX \-valuesonly: Read only the cell values, no formatting, formulas or sheet properties. \-keylist: Additionally build the S,k key (see RESULT ARRAY), a dictionary of the non\-empty columns per row. \-sheets pattern: Read only the worksheets whose zero\-based sheet index matches the glob pattern. \-sheetnames pattern: Read only the worksheets whose name matches the glob pattern. If neither \-sheets nor \-sheetnames is given all worksheets are read. \-datefmt format: [clock format] string used to convert date cells into the value keys (default \(dq%Y\-%m\-%d %H:%M:%S\(dq). \-as array: Format of the return value. Currently array is the only supported value. .EE .PP A simple example: .IP .EX array set workbook [::ooxml::xl_read file.xlsx] foreach key [lsort \-dictionary [array names workbook 0,v,*]] { lassign [split $key ,] sheet tag row col puts \(dq$row,$col = $workbook($key)\(dq } .EE .RE .TP \f[B]::ooxml::xl_sheets\f[R] \f[I]file\f[R] Returns information about the worksheets of the given .xlsx \f[I]file\f[R] without reading any cell data. The result is a Tcl list with two elements per worksheet: the zero\-based sheet index and a dictionary with the keys \f[I]sheetId\f[R] (the internal sheet id), \f[I]name\f[R] (the display name of the worksheet) and \f[I]rId\f[R] (the internal relationship id). .RS .IP .EX foreach {index info} [::ooxml::xl_sheets file.xlsx] { puts \(dq$index: [dict get $info name]\(dq } .EE .RE .TP \f[B]::ooxml::xl_write\f[R] \f[B]new\f[R] \f[I]?\-option value \&...?\f[R] Creates a spreadsheet object command to build a workbook from scratch: .RS .IP .EX set spreadsheet [::ooxml::xl_write new ?\-option value ...?] .EE .PP The recognized options are: .IP .EX \-creator name: The creator property of the spreadsheet. \-created timestamp: The creation time property of the spreadsheet. The value is either an integer (seconds, as returned by [clock seconds]) or a date string in local time. \-modifiedby name: The modified\-by property of the spreadsheet. \-modified timestamp: The modification time property of the spreadsheet. For the value see \-created. \-application name: The application property of the spreadsheet. .EE .RE .PP The created spreadsheet object commands currently support the following methods: .TP \f[B]autofilter\f[R] \f[I]sheet\f[R] \f[I]indexFrom\f[R] \f[I]indexTo\f[R] Adds an autofilter (filter and sort controls on the header row) to the worksheet, spanning from cell \f[I]indexFrom\f[R] to cell \f[I]indexTo\f[R] (see CELL INDEX). .RS .IP .EX $spreadsheet autofilter $sheet 0,0 0,5 .EE .RE .TP \f[B]border\f[R] \f[I]?\-option value \&...?\f[R] Defines a border style for the current workbook and returns an ID (BORDERID) to refer to that style. The recognized options are: .RS .IP .EX \-list: Returns the list of currently defined border styles instead of a BORDERID. \-leftstyle BORDERLINESTYLE \-rightstyle BORDERLINESTYLE \-topstyle BORDERLINESTYLE \-bottomstyle BORDERLINESTYLE \-diagonalstyle BORDERLINESTYLE See BORDERLINESTYLE for the valid values. \-leftcolor COLOR \-rightcolor COLOR \-topcolor COLOR \-bottomcolor COLOR \-diagonalcolor COLOR See COLOR for the valid values. \-diagonaldirection (up|down) \-tag tagname: Gives the border style a name. This name may be used instead of the returned BORDERID. .EE .PP See BORDERLINESTYLE and COLOR for the valid option values. .RE .TP \f[B]cell\f[R] \f[I]sheet\f[R] \f[I]?data?\f[R] \f[I]?\-option value \&...?\f[R] Writes the value \f[I]data\f[R] into a cell of the worksheet \f[I]sheet\f[R] and returns the position of the written cell as \f[I]row,column\f[R]. Without the \f[B]\-index\f[R] option the cell is placed in the current row at the next column (see CELL INDEX for the autoincrement behaviour). The recognized options are: .RS .IP .EX \-index index: Position of the cell, either as row,column or in Excel notation. Also accepts a bare column number to place the cell in the current row with columns skipped. \-style STYLEID: Style of the cell, from the method style. \-formula formula: Enter an Excel formula (e.g. \(dqA1+B1\(dq). The data argument is usually empty then, the application computes the value. \-formulaidx integer: Shared formula index. A cell defining a shared formula gives \-formula, \-formularef and \-formulaidx; the dependent cells give only \-formulaidx. \-formularef range: The range the shared formula spans, either in Excel notation (C3:C5) or numerically (2,2:4,2). \-string: Store the value as string in any case. \-nostring: Override a column\-level \-string setting for this cell. \-nozero: Do not output the value if it is zero. \-zero: Override a column\-level \-nozero setting for this cell. \-globalstyle: Apply the column style to this cell. \-height height: Sets the row height of the current row. \-hyperlink url: Makes the cell a hyperlink to url. \-tooltip text: Tooltip for the hyperlink (only used together with \-hyperlink). .EE .RE .TP \f[B]column\f[R] \f[I]sheet\f[R] \f[I]?\-option value \&...?\f[R] Defines the properties of a column of the worksheet \f[I]sheet\f[R] and returns the column number. Without the \f[B]\-index\f[R] option the next column is used. The recognized options are: .RS .IP .EX \-index index: Column number. \-to index: Last column number, if the definition should span a range of columns. \-width width: Column width in characters of the standard font (may be fractional, see also ::ooxml::CalcColumnWidth). \-style STYLEID: Default style for the cells of the column. Note that a cell only uses it if written with \-globalstyle. \-bestfit: Sets the bestFit flag of the column. \-customwidth: Sets the customWidth flag of the column. \-string: Store the values of the cells of this column as string in any case (a cell may override this with \-nostring). \-nozero: Do not output zero values in this column (a cell may override this with \-zero). \-calcfit: Calculates the column width from the length of the longest value written to the column (via ::ooxml::CalcColumnWidth) if that is wider than a given \-width. .EE .RE .TP \f[B]defaultdatestyle\f[R] \f[I]STYLEID\f[R] Sets the default style for date cells. Values recognized as dates are formatted with this style if the cell does not have an explicit \f[B]\-style\f[R]. .RS .IP .EX set datestyle [$spreadsheet style \-numfmt [$spreadsheet numberformat \-datetime]] $spreadsheet defaultdatestyle $datestyle .EE .RE .TP \f[B]fill\f[R] \f[I]?\-option value \&...?\f[R] Defines a fill style for the current workbook and returns an ID (FILLID) to refer to that style. The recognized options are: .RS .IP .EX \-list: Returns the list of currently defined fills instead of a FILLID. \-patterntype PATTERNTYPE: See PATTERNTYPE for the usual values (default \(dqnone\(dq). \-fgcolor COLOR: Foreground (pattern) color. See COLOR for the valid values. \-bgcolor COLOR: Background color. See COLOR for the valid values. \-tag tagname: Gives the fill a name. This name may be used instead of the returned FILLID. .EE .PP See PATTERNTYPE and COLOR for the valid option values. .RE .TP \f[B]font\f[R] \f[I]?\-option value \&...?\f[R] Defines a font for the current workbook and returns an ID (FONTID) to refer to that font. The recognized options are: .RS .IP .EX \-list: Returns the list of currently defined fonts instead of a FONTID. \-name name: Font name (default \(dqCalibri\(dq). \-family family: Font family number (default 2). \-size size: Font size in points (default 12). \-color COLOR: See COLOR for the valid values. \-scheme scheme: Font scheme (default \(dqminor\(dq). \-bold: Bold text. \-italic: Italic text. \-underline: Underlined text. \-tag tagname: Gives the font a name. This name may be used instead of the returned FONTID. .EE .PP See COLOR for the valid \f[B]\-color\f[R] values. .RE .TP \f[B]freeze\f[R] \f[I]sheet\f[R] \f[I]index\f[R] Freezes the panes above and left of the given cell \f[I]index\f[R] (see CELL INDEX), so they stay visible while scrolling. .RS .IP .EX $spreadsheet freeze $sheet 1,0 ;# freeze the first row .EE .RE .TP \f[B]merge\f[R] \f[I]sheet\f[R] \f[I]indexFrom\f[R] \f[I]indexTo\f[R] Merges the cell range with the corners \f[I]indexFrom\f[R] and \f[I]indexTo\f[R] (see CELL INDEX) into one cell. .RS .IP .EX $spreadsheet merge $sheet 40,0 40,2 $spreadsheet merge $sheet A42 A44 .EE .RE .TP \f[B]numberformat\f[R] \f[I]?\-option value \&...?\f[R] Defines a number format for the current workbook and returns an ID (NUMFMTID) to refer to that format. The recognized options are: .RS .IP .EX \-format format: Any Excel format string (e.g. {#,##0.00 \(dq€\(dq}). \-general: Excel general format. \-date: Date format. \-time: Time format. \-datetime: Date/time format. \-iso8601: Date/time in ISO 8601 notation. \-number: Integer. \-decimal: Decimal number with 2 decimal places. \-red: Color negative values red (may be combined with \-number and \-decimal). \-separator: Thousands separators (may be combined with \-number and \-decimal). \-fraction: Fractions. \-scientific: Scientific notation. \-percent: Percentage. \-text, \-string: Text format. \-tag tagname: Gives the format a name. This name may be used instead of the returned NUMFMTID. .EE .RE .TP \f[B]pageMargins\f[R] \f[I]sheet\f[R] \f[I]?\-option value \&...?\f[R] Sets the page margins of the worksheet \f[I]sheet\f[R]. The recognized options are: .RS .IP .EX \-left \-right \-top \-bottom \-header \-footer All options expect a floating point value in inch. .EE .PP If some page margins of a worksheet are set with this method then all margins of that worksheet are set, either from the options given in the method call or from the current \f[B]pageMarginsDefault\f[R] values, if a margin was not in the method call. .RE .TP \f[B]pageMarginsDefault\f[R] \f[I]?\-option value \&...?\f[R] Sets the page margins of all worksheets which do not have individual margin settings. The options are the same as for \f[B]pageMargins\f[R]. The default margins are: .RS .PP .TS tab(@); l l. T{ Margin T}@T{ Inch T} _ T{ left T}@T{ 0.75 T} T{ right T}@T{ 0.75 T} T{ top T}@T{ 1 T} T{ bottom T}@T{ 1 T} T{ header T}@T{ 0.5 T} T{ footer T}@T{ 0.5 T} .TE .RE .TP \f[B]pageSetup\f[R] \f[I]sheet\f[R] \f[I]?\-option value \&...?\f[R] Sets the page setup of the worksheet \f[I]sheet\f[R]. .RS .PP \f[B]Caveat\f[R]: If no page setup properties at all are set for a sheet, applications use defaults derived from other sources. But if at least one page setup property is explicitly set with this method, the other properties not set will get the default value from the specification, which may be another value than without any page setup at all. For example if you only set the \f[B]\-orientation\f[R] of a sheet then this may also result in another page size (because the application page size default may differ from the default recommended by the specification, which is Letter paper). .PP The recognized options are: .IP .EX \-blackAndWhite boolean: Print black and white. Default: false. \-cellComments (none|asDisplayed|atEnd): How to print cell comments. Default: none. \-copies integer: Number of copies to print. Default: 1. \-draft boolean: Print without graphics. Default: false. \-errors (displayed|blank|dash|NA): How to print cell values of cells with errors. Default: displayed. \-firstPageNumber integer: Page number of the first printed page; see \-useFirstPageNumber. Default: 1. \-fitToHeight integer: Number of vertical pages to fit on. Default: 1. \-fitToWidth integer: Number of horizontal pages to fit on. Default: 1. \-horizontalDpi integer: Horizontal print resolution of the device. Default: 600. \-orientation (default|portrait|landscape): Orientation of the page. Default: default. \-pageOrder (downThenOver|overThenDown): Order of the printed pages. Default: downThenOver. \-paperHeight height: Height of custom paper as a number immediately followed by a unit identifier (as 297mm or 11in). No default. \-paperWidth width: Width of custom paper as a number immediately followed by a unit identifier (as 210mm or 8.5in). No default. The specification says that when \-paperHeight and \-paperWidth are specified, the rendering application shall ignore \-paperSize. \-paperSize paperSizeID: Specifies the paper size. Default: 1 (Letter). See PAPER SIZE IDS for the defined values; the behaviour for other values is implementation\-defined. \-scale integer: Print scaling in percent. The rendering application may respect only values ranging from 10 to 400. Overridden when \-fitToWidth and/or \-fitToHeight are in use. Default: 100. \-useFirstPageNumber boolean: Use the \-firstPageNumber value for the first page number and do not auto number the pages. Default: false. \-usePrinterDefaults boolean: Use the printer defaults (or the defaults of the print job). \-verticalDpi integer: Vertical print resolution of the device. Default: 600. .EE .PP See PAPER SIZE IDS for the possible \f[B]\-paperSize\f[R] values. .RE .TP \f[B]presetsheets\f[R] \f[I]arrayName\f[R] Creates worksheets from an array previously read with \f[I]::ooxml::xl_read\f[R], including their data. The array is passed by name (without \f[CR]$\f[R]). The sheets are created in their original order. The method adds the key \f[I]sheetmap\f[R] to the array: a dict mapping the original sheet index to the newly created worksheet handle. Usually combined with \f[B]presetstyles\f[R]: .RS .IP .EX array set workbook [::ooxml::xl_read original.xlsx] set spreadsheet [::ooxml::xl_write new] $spreadsheet presetstyles workbook $spreadsheet presetsheets workbook .EE .RE .TP \f[B]presetstyles\f[R] \f[I]arrayName\f[R] Takes over the style definitions (number formats, fonts, fills, borders and cell styles) from an array previously read with \f[I]::ooxml::xl_read\f[R]. The array is passed by name (without \f[CR]$\f[R]). .TP \f[B]printarea\f[R] \f[I]sheet\f[R] \f[I]indexFrom\f[R] \f[I]indexTo\f[R] Sets the print area of the worksheet \f[I]sheet\f[R], spanning from cell \f[I]indexFrom\f[R] to cell \f[I]indexTo\f[R] (see CELL INDEX). .RS .IP .EX $spreadsheet printarea $sheet A1 C3 $spreadsheet printarea $sheet 1,1 2,2 .EE .RE .TP \f[B]row\f[R] \f[I]sheet\f[R] \f[I]?\-option value \&...?\f[R] Starts a new row in the worksheet \f[I]sheet\f[R] and returns the row number. Without the \f[B]\-index\f[R] option the next row is used; the column autoincrement is reset (see CELL INDEX). The recognized options are: .RS .IP .EX \-index index: Row number to jump to. \-height height: Row height in points. .EE .RE .TP \f[B]rowheight\f[R] \f[I]sheet\f[R] \f[I]row\f[R] \f[I]height\f[R] Sets the height of the given \f[I]row\f[R] (zero\-based) of the worksheet \f[I]sheet\f[R] to \f[I]height\f[R] points, independently of writing cells. .RS .IP .EX $spreadsheet rowheight $sheet 33 20 .EE .RE .TP \f[B]style\f[R] \f[I]?\-option value \&...?\f[R] Defines a cell style for the current workbook and returns an ID (STYLEID) to refer to that style. The recognized options are: .RS .IP .EX \-list: Returns the list of currently defined styles instead of a STYLEID. \-numfmt NUMFMTID: From the method numberformat. \-font FONTID: From the method font. \-fill FILLID: From the method fill. \-border BORDERID: From the method border. \-xf XFID: Base cell format record to derive from. \-horizontal alignment: Horizontal alignment of the cell content (e.g. left, center, right). \-vertical alignment: Vertical alignment of the cell content (e.g. top, center, bottom). \-rotate degree: Rotation of the cell content in degrees. \-wrap: Enables text wrapping within the cell. \-tag tagname: Gives the style a name. This name may be used instead of the returned STYLEID. .EE .RE .TP \f[B]view\f[R] \f[I]?\-option value \&...?\f[R] Sets the workbook view properties. The recognized options are: .RS .IP .EX \-activetab tab: Zero\-based index of the worksheet shown when the file is opened. \-x twips \-y twips: Position of the workbook window. \-width twips \-height twips: Size of the workbook window. \-list: Returns the current view settings instead of setting them. .EE .RE .TP \f[B]worksheet\f[R] \f[I]name\f[R] Creates a new worksheet with the given \f[I]name\f[R] and returns the sheet handle (SHEETID) used as first argument by the cell related methods. The characters \f[CR]: \(rs / ? *\f[R] in the name are replaced and the name is truncated to the 31 characters allowed by the format. .TP \f[B]write\f[R] \f[I]filename\f[R] Writes the spreadsheet to the file \f[I]filename\f[R]. If the filename does not have the suffix .xlsx then it is appended. If \f[I]filename\f[R] is empty, spreadsheetml.xlsx is used. .SH RESULT ARRAY \f[I]::ooxml::xl_read\f[R] returns a flat array. In the following key table \f[I]S\f[R] stands for the zero\-based sheet index and \f[I]R\f[R],\f[I]C\f[R] for the zero\-based row and column index: .PP .TS tab(@); l l. T{ Key T}@T{ Content T} _ T{ sheets T}@T{ List of the sheet indices that have been read T} T{ S,n T}@T{ Worksheet name T} T{ S,max_row T}@T{ Largest used row index of the worksheet T} T{ S,max_column T}@T{ Largest used column index of the worksheet T} T{ S,v,R,C T}@T{ Cell value (present for every non\-empty cell) T} T{ S,d,R,C T}@T{ Raw date/time serial if the cell is a date cell T} T{ S,s,R,C T}@T{ Style id of the cell T} T{ S,t,R,C T}@T{ Cell type (\f[I]s\f[R] = shared string) T} T{ S,c,R,C T}@T{ Cell position in Excel notation (e.g.\ B7) T} T{ S,f,R,C T}@T{ Formula dict: keys \f[I]f\f[R] (formula), \f[I]i\f[R] (shared formula index), \f[I]r\f[R] (shared formula range) T} T{ S,l,IDX T}@T{ Hyperlink dict: keys \f[I]l\f[R] (target), \f[I]t\f[R] (tooltip) T} T{ S,k T}@T{ Dict row \-> list of non\-empty columns (only with the \-keylist option) T} T{ S,filter T}@T{ Autofilter ranges T} T{ S,freeze T}@T{ Freeze pane position T} T{ S,merge T}@T{ List of merged cell ranges T} T{ S,printarea T}@T{ Print area range T} T{ S,rowheight T}@T{ Row height settings T} T{ S,cols T}@T{ Number of column definitions T} T{ S,col,N T}@T{ Dict with the properties of column definition \f[I]N\f[R] T} T{ S,pageMargins T}@T{ Page margin settings T} T{ S,pageSetup T}@T{ Page setup settings T} T{ view T}@T{ Workbook view settings T} T{ s,\&... T}@T{ Style metadata (s,\(at s,styles,N s,fonts,N s,fills,N s,borders,N s,numFmts,N s,numFmtsIds), consumed by \f[B]presetstyles\f[R] and \f[B]presetsheets\f[R] T} .TE .PP With the \f[B]\-valuesonly\f[R] option only the \f[I]sheets\f[R], \f[I]S,n\f[R], \f[I]S,max_row\f[R], \f[I]S,max_column\f[R] and \f[I]S,v,R,C\f[R] keys are present. .SH CELL INDEX Methods and options expecting a cell position accept it in two equivalent forms: numerically as \f[I]row,column\f[R] with zero\-based row and column numbers, or in Excel notation (column letters followed by the one\-based row number). 0,0 and A1 describe the same cell, 3,2 and C4 also. .PP The methods \f[B]row\f[R], \f[B]column\f[R] and \f[B]cell\f[R] work with an autoincrement mechanism: without an explicit \f[B]\-index\f[R] option \f[B]row\f[R] starts the next row, \f[B]cell\f[R] writes to the next column of the current row and \f[B]column\f[R] defines the next column. An explicit \f[B]\-index\f[R] repositions; the autoincrement continues from there. .IP .EX $spreadsheet row $sheet $spreadsheet cell $sheet A ;# 0,0 $spreadsheet cell $sheet B \-index 4 ;# 0,4 (columns 1\-3 stay empty) $spreadsheet cell $sheet C ;# 0,5 $spreadsheet row $sheet \-index 3 ;# jump to row 3 $spreadsheet cell $sheet D ;# 3,0 .EE .PP For writing prefer the autoincrement wherever possible: call \f[CR]$spreadsheet row $sheet\f[R] once per row and write the cells in order without \f[B]\-index\f[R]. This avoids off\-by\-one and index bookkeeping errors. .SH OPTION VALUE TYPES Several option values share the same value types. These types are: .SS COLOR There are several kinds of valid values: .PP The value may be \f[I]auto\f[R] or \f[I]none\f[R]. .PP If not, the value may be the index number of a predefined color (an integer between 0 and 65 including). See the list below. .PP If not, the value may be the name of a predefined color. Case is ignored. See the list below. .PP If not, the value may be a 6 digit hexadecimal number, which is then used as RGB value. .PP The list of predefined colors is: .PP .TS tab(@); l l l. T{ Color ID T}@T{ Name T}@T{ (A)RGB T} _ T{ 0 T}@T{ Black T}@T{ 00000000 T} T{ 1 T}@T{ White T}@T{ 00FFFFFF T} T{ 2 T}@T{ Red T}@T{ 00FF0000 T} T{ 3 T}@T{ Lime T}@T{ 0000FF00 T} T{ 4 T}@T{ Blue T}@T{ 000000FF T} T{ 5 T}@T{ Yellow T}@T{ 00FFFF00 T} T{ 6 T}@T{ Fuchsia T}@T{ 00FF00FF T} T{ 7 T}@T{ Aqua T}@T{ 0000FFFF T} T{ 8 T}@T{ Black T}@T{ 00000000 T} T{ 9 T}@T{ White T}@T{ 00FFFFFF T} T{ 10 T}@T{ Red T}@T{ 00FF0000 T} T{ 11 T}@T{ Lime T}@T{ 0000FF00 T} T{ 12 T}@T{ Blue T}@T{ 000000FF T} T{ 13 T}@T{ Yellow T}@T{ 00FFFF00 T} T{ 14 T}@T{ Fuchsia T}@T{ 00FF00FF T} T{ 15 T}@T{ Aqua T}@T{ 0000FFFF T} T{ 16 T}@T{ Maroon T}@T{ 00800000 T} T{ 17 T}@T{ Green T}@T{ 00008000 T} T{ 18 T}@T{ Navy T}@T{ 00000080 T} T{ 19 T}@T{ Olive T}@T{ 00808000 T} T{ 20 T}@T{ Purple T}@T{ 00800080 T} T{ 21 T}@T{ Teal T}@T{ 00008080 T} T{ 22 T}@T{ Silver T}@T{ 00C0C0C0 T} T{ 23 T}@T{ Gray T}@T{ 00808080 T} T{ 24 T}@T{ Portage T}@T{ 009999FF T} T{ 25 T}@T{ Lipstick T}@T{ 00993366 T} T{ 26 T}@T{ Cream T}@T{ 00FFFFCC T} T{ 27 T}@T{ LightCyan T}@T{ 00CCFFFF T} T{ 28 T}@T{ Purple T}@T{ 00660066 T} T{ 29 T}@T{ LightCoral T}@T{ 00FF8080 T} T{ 30 T}@T{ NavyBlue T}@T{ 000066CC T} T{ 31 T}@T{ LavenderBlue T}@T{ 00CCCCFF T} T{ 32 T}@T{ Navy T}@T{ 00000080 T} T{ 33 T}@T{ Fuchsia T}@T{ 00FF00FF T} T{ 34 T}@T{ Yellow T}@T{ 00FFFF00 T} T{ 35 T}@T{ Aqua T}@T{ 0000FFFF T} T{ 36 T}@T{ Purple T}@T{ 00800080 T} T{ 37 T}@T{ Maroon T}@T{ 00800000 T} T{ 38 T}@T{ Teal T}@T{ 00008080 T} T{ 39 T}@T{ Blue T}@T{ 000000FF T} T{ 40 T}@T{ DeepSkyBlue T}@T{ 0000CCFF T} T{ 41 T}@T{ LightCyan T}@T{ 00CCFFFF T} T{ 42 T}@T{ BlueRomance T}@T{ 00CCFFCC T} T{ 43 T}@T{ Canary T}@T{ 00FFFF99 T} T{ 44 T}@T{ LightSkyBlue T}@T{ 0099CCFF T} T{ 45 T}@T{ CarnationPink T}@T{ 00FF99CC T} T{ 46 T}@T{ Mauve T}@T{ 00CC99FF T} T{ 47 T}@T{ PeachOrange T}@T{ 00FFCC99 T} T{ 48 T}@T{ RoyalBlue T}@T{ 003366FF T} T{ 49 T}@T{ MediumTurquoise T}@T{ 0033CCCC T} T{ 50 T}@T{ Citrus T}@T{ 0099CC00 T} T{ 51 T}@T{ TangerineYellow T}@T{ 00FFCC00 T} T{ 52 T}@T{ OrangePeel T}@T{ 00FF9900 T} T{ 53 T}@T{ SafetyOrange T}@T{ 00FF6600 T} T{ 54 T}@T{ Scampi T}@T{ 00666699 T} T{ 55 T}@T{ Nobel T}@T{ 00969696 T} T{ 56 T}@T{ PrussianBlue T}@T{ 00003366 T} T{ 57 T}@T{ Eucalyptus T}@T{ 00339966 T} T{ 58 T}@T{ Myrtle T}@T{ 00003300 T} T{ 59 T}@T{ Karaka T}@T{ 00333300 T} T{ 60 T}@T{ SaddleBrown T}@T{ 00993300 T} T{ 61 T}@T{ Lipstick T}@T{ 00993366 T} T{ 62 T}@T{ DarkSlateBlue T}@T{ 00333399 T} T{ 63 T}@T{ NightRider T}@T{ 00333333 T} T{ 64 T}@T{ SystemForeground T}@T{ n/a T} T{ 65 T}@T{ SystemBackground T}@T{ n/a T} .TE .SS BORDERLINESTYLE The list of possible values is: .IP .EX dashDot dashDotDot dashed dotted double hair medium mediumDashDot mediumDashDotDot none slantDashDot thick thin .EE .SS PATTERNTYPE An ECMA\-376 fill pattern type. The usual values are: .IP .EX none solid darkDown darkGray darkGrid darkHorizontal darkTrellis darkUp darkVertical gray0625 gray125 lightDown lightGray lightGrid lightHorizontal lightTrellis lightUp lightVertical mediumGray .EE .SS PAPER SIZE IDS The possible \f[B]\-paperSize\f[R] values and their meaning are: .PP .TS tab(@); l l. T{ Paper Size ID T}@T{ Paper Size T} _ T{ 1 T}@T{ Letter paper (8.5 in. by 11 in.) T} T{ 2 T}@T{ Letter small paper (8.5 in. by 11 in.) T} T{ 3 T}@T{ Tabloid paper (11 in. by 17 in.) T} T{ 4 T}@T{ Ledger paper (17 in. by 11 in.) T} T{ 5 T}@T{ Legal paper (8.5 in. by 14 in.) T} T{ 6 T}@T{ Statement paper (5.5 in. by 8.5 in.) T} T{ 7 T}@T{ Executive paper (7.25 in. by 10.5 in.) T} T{ 8 T}@T{ A3 paper (297 mm by 420 mm) T} T{ 9 T}@T{ A4 paper (210 mm by 297 mm) T} T{ 10 T}@T{ A4 small paper (210 mm by 297 mm) T} T{ 11 T}@T{ A5 paper (148 mm by 210 mm) T} T{ 12 T}@T{ B4 paper (250 mm by 353 mm) T} T{ 13 T}@T{ B5 paper (176 mm by 250 mm) T} T{ 14 T}@T{ Folio paper (8.5 in. by 13 in.) T} T{ 15 T}@T{ Quarto paper (215 mm by 275 mm) T} T{ 16 T}@T{ Standard paper (10 in. by 14 in.) T} T{ 17 T}@T{ Standard paper (11 in. by 17 in.) T} T{ 18 T}@T{ Note paper (8.5 in. by 11 in.) T} T{ 19 T}@T{ #9 envelope (3.875 in. by 8.875 in.) T} T{ 20 T}@T{ #10 envelope (4.125 in. by 9.5 in.) T} T{ 21 T}@T{ #11 envelope (4.5 in. by 10.375 in.) T} T{ 22 T}@T{ #12 envelope (4.75 in. by 11 in.) T} T{ 23 T}@T{ #14 envelope (5 in. by 11.5 in.) T} T{ 24 T}@T{ C paper (17 in. by 22 in.) T} T{ 25 T}@T{ D paper (22 in. by 34 in.) T} T{ 26 T}@T{ E paper (34 in. by 44 in.) T} T{ 27 T}@T{ DL envelope (110 mm by 220 mm) T} T{ 28 T}@T{ C5 envelope (162 mm by 229 mm) T} T{ 29 T}@T{ C3 envelope (324 mm by 458 mm) T} T{ 30 T}@T{ C4 envelope (229 mm by 324 mm) T} T{ 31 T}@T{ C6 envelope (114 mm by 162 mm) T} T{ 32 T}@T{ C65 envelope (114 mm by 229 mm) T} T{ 33 T}@T{ B4 envelope (250 mm by 353 mm) T} T{ 34 T}@T{ B5 envelope (176 mm by 250 mm) T} T{ 35 T}@T{ B6 envelope (176 mm by 125 mm) T} T{ 36 T}@T{ Italy envelope (110 mm by 230 mm) T} T{ 37 T}@T{ Monarch envelope (3.875 in. by 7.5 in.). T} T{ 38 T}@T{ 6 3/4 envelope (3.625 in. by 6.5 in.) T} T{ 39 T}@T{ US standard fanfold (14.875 in. by 11 in.) T} T{ 40 T}@T{ German standard fanfold (8.5 in. by 12 in.) T} T{ 41 T}@T{ German legal fanfold (8.5 in. by 13 in.) T} T{ 42 T}@T{ ISO B4 (250 mm by 353 mm) T} T{ 43 T}@T{ Japanese double postcard (200 mm by 148 mm) T} T{ 44 T}@T{ Standard paper (9 in. by 11 in.) T} T{ 45 T}@T{ Standard paper (10 in. by 11 in.) T} T{ 46 T}@T{ Standard paper (15 in. by 11 in.) T} T{ 47 T}@T{ Invite envelope (220 mm by 220 mm) T} T{ 50 T}@T{ Letter extra paper (9.275 in. by 12 in.) T} T{ 51 T}@T{ Legal extra paper (9.275 in. by 15 in.) T} T{ 52 T}@T{ Tabloid extra paper (11.69 in. by 18 in.) T} T{ 53 T}@T{ A4 extra paper (236 mm by 322 mm) T} T{ 54 T}@T{ Letter transverse paper (8.275 in. by 11 in.) T} T{ 55 T}@T{ A4 transverse paper (210 mm by 297 mm) T} T{ 56 T}@T{ Letter extra transverse paper (9.275 in. by 12 in.) T} T{ 57 T}@T{ SuperA/SuperA/A4 paper (227 mm by 356 mm) T} T{ 58 T}@T{ SuperB/SuperB/A3 paper (305 mm by 487 mm) T} T{ 59 T}@T{ Letter plus paper (8.5 in. by 12.69 in.) T} T{ 60 T}@T{ A4 plus paper (210 mm by 330 mm) T} T{ 61 T}@T{ A5 transverse paper (148 mm by 210 mm) T} T{ 62 T}@T{ JIS B5 transverse paper (182 mm by 257 mm) T} T{ 63 T}@T{ A3 extra paper (322 mm by 445 mm) T} T{ 64 T}@T{ A5 extra paper (174 mm by 235 mm) T} T{ 65 T}@T{ ISO B5 extra paper (201 mm by 276 mm) T} T{ 66 T}@T{ A2 paper (420 mm by 594 mm) T} T{ 67 T}@T{ A3 transverse paper (297 mm by 420 mm) T} T{ 68 T}@T{ A3 extra transverse paper (322 mm by 445 mm) T} T{ 69 T}@T{ Japanese Double Postcard (200 mm x 148 mm) T} T{ 70 T}@T{ A6 (105 mm x 148 mm) T} T{ 71 T}@T{ Japanese Envelope Kaku #2 T} T{ 72 T}@T{ Japanese Envelope Kaku #3 T} T{ 73 T}@T{ Japanese Envelope Chou #3 T} T{ 74 T}@T{ Japanese Envelope Chou #4 T} T{ 75 T}@T{ Letter Rotated (11 in x 8.5 in) T} T{ 76 T}@T{ A3 Rotated (420 mm x 297 mm) T} T{ 77 T}@T{ A4 Rotated (297 mm x 210 mm) T} T{ 78 T}@T{ A5 Rotated (210 mm x 148 mm) T} T{ 79 T}@T{ B4 (JIS) Rotated (364 mm x 257 mm) T} T{ 80 T}@T{ B5 (JIS) Rotated (257 mm x 182 mm) T} T{ 81 T}@T{ Japanese Postcard Rotated (148 mm x 100 mm) T} T{ 82 T}@T{ Double Japanese Postcard Rotated (148 mm x 200 mm) T} T{ 83 T}@T{ A6 Rotated (148 mm x 105 mm) T} T{ 84 T}@T{ Japanese Envelope Kaku #2 Rotated T} T{ 85 T}@T{ Japanese Envelope Kaku #3 Rotated T} T{ 86 T}@T{ Japanese Envelope Chou #3 Rotated T} T{ 87 T}@T{ Japanese Envelope Chou #4 Rotated T} T{ 88 T}@T{ B6 (JIS) (128 mm x 182 mm) T} T{ 89 T}@T{ B6 (JIS) Rotated (182 mm x 128 mm) T} T{ 90 T}@T{ (12 in x 11 in) T} T{ 91 T}@T{ Japanese Envelope You #4 T} T{ 92 T}@T{ Japanese Envelope You #4 Rotated T} T{ 93 T}@T{ PRC 16K (146 mm x 215 mm) T} T{ 94 T}@T{ PRC 32K (97 mm x 151 mm) T} T{ 95 T}@T{ PRC 32K(Big) (97 mm x 151 mm) T} T{ 96 T}@T{ PRC Envelope #1 (102 mm x 165 mm) T} T{ 97 T}@T{ PRC Envelope #2 (102 mm x 176 mm) T} T{ 98 T}@T{ PRC Envelope #3 (125 mm x 176 mm) T} T{ 99 T}@T{ PRC Envelope #4 (110 mm x 208 mm) T} T{ 100 T}@T{ PRC Envelope #5 (110 mm x 220 mm) T} T{ 101 T}@T{ PRC Envelope #6 (120 mm x 230 mm) T} T{ 102 T}@T{ PRC Envelope #7 (160 mm x 230 mm) T} T{ 103 T}@T{ PRC Envelope #8 (120 mm x 309 mm) T} T{ 104 T}@T{ PRC Envelope #9 (229 mm x 324 mm) T} T{ 105 T}@T{ PRC Envelope #10 (324 mm x 458 mm) T} T{ 106 T}@T{ PRC 16K Rotated T} T{ 107 T}@T{ PRC 32K Rotated T} T{ 108 T}@T{ PRC 32K(Big) Rotated T} T{ 109 T}@T{ PRC Envelope #1 Rotated (165 mm x 102 mm) T} T{ 110 T}@T{ PRC Envelope #2 Rotated (176 mm x 102 mm) T} T{ 111 T}@T{ PRC Envelope #3 Rotated (176 mm x 125 mm) T} T{ 112 T}@T{ PRC Envelope #4 Rotated (208 mm x 110 mm) T} T{ 113 T}@T{ PRC Envelope #5 Rotated (220 mm x 110 mm) T} T{ 114 T}@T{ PRC Envelope #6 Rotated (230 mm x 120 mm) T} T{ 115 T}@T{ PRC Envelope #7 Rotated (230 mm x 160 mm) T} T{ 116 T}@T{ PRC Envelope #8 Rotated (309 mm x 120 mm) T} T{ 117 T}@T{ PRC Envelope #9 Rotated (324 mm x 229 mm) T} T{ 118 T}@T{ PRC Envelope #10 Rotated (458 mm x 324 mm) T} .TE .SH DEPENDENCIES .IP .EX Tcl >= 8.6.7 tdom >= 0.9.0 .EE .PP Reading .xlsx files uses the zlib command built into Tcl and needs no additional package. Only if an archive cannot be handled by the built\-in reader (e.g.\ ZIP64), one of the optional fallback backends is used: the Tcl 9 zipfs, tcllib\(cqs zipfile::decode or tclvfs vfs::zip >= 1.0.4. ooxml/examples/docx-example9.tcl000775 000765 000024 00000002633 15217572310 017325 0ustar00alexstaff000000 000000 #!/bin/sh #\ exec tclsh "$0" "$@" cd [file dirname [info script]] source ../ooxml.tcl source ../ooxml-docx.tcl source strings.tcl namespace import ::ooxml::docx::docx set docx [docx new] featuresCovered "OMML related methods." # Title $docx paragraph "OMML" # Inline: E = m c^2 $docx paragraph "" $docx math { $docx mrun "E = m" $docx msup { $docx mrun "c" } { $docx mrun "2" } } # Display: Sum_{i=1}^{n} i^2 $docx math -display 1 -jc center { $docx mnary -char "∑" -limLoc undOvr \ -sub { $docx mrun "i=1" } \ -sup { $docx mrun "n" } { $docx msup { $docx mrun "i" } { $docx mrun "2" } } } # Display: lim_{x->0} (sin x)/x $docx math -display 1 { $docx mlimlow { $docx mrun "lim" } { $docx mrun "x→0" } $docx mrun " " $docx mfrac -type bar { $docx mfunc { $docx mrun "sin" } { $docx mrun "x" } } { $docx mrun "x" } } # Display: integral_0^π sin x dx $docx math -display 1 { $docx mnary -char "∫" -limLoc subSup \ -sub { $docx mrun "0" } \ -sup { $docx mrun "π" } { $docx mrun "sin " $docx mrun "x " $docx mrun "dx" } } # Display: nth-root(sin x) $docx math -display 1 { $docx mroot { $docx mrun "n" } { $docx mfunc { $docx mrun "sin" } { $docx mrun "x" } } } # Display: lim^{n→∞} $docx math -display 1 { $docx mlimupp { $docx mrun "lim" } { $docx mrun "n→∞" } } $docx write docx-example9.docx $docx destroy ooxml/examples/xlsx-writeRowsIndex.tcl000755 000765 000024 00000002375 15217572310 020640 0ustar00alexstaff000000 000000 #!/bin/sh #\ exec tclsh "$0" "$@" set auto_path [linsert $auto_path 0 ..] if {[catch {package require ooxml}]} { source ../ooxml.tcl } source array.tcl set spreadsheet [::ooxml::xl_write new -creator {Alexander Schöpe}] if {[set sheet [$spreadsheet worksheet {Tabelle 1}]] > -1} { set center [$spreadsheet style -horizontal center] set date [$spreadsheet style -numfmt [$spreadsheet numberformat -datetime]] set decimal [$spreadsheet style -numfmt [$spreadsheet numberformat -decimal -separator]] set text [$spreadsheet style -numfmt [$spreadsheet numberformat -string]] $spreadsheet column $sheet $spreadsheet column $sheet -width 30 $spreadsheet column $sheet $spreadsheet column $sheet $spreadsheet column $sheet -style $decimal $spreadsheet column $sheet -style $date -width [::ooxml::CalcColumnWidth 16] $spreadsheet column $sheet $spreadsheet autofilter $sheet 0,0 0,6 $spreadsheet freeze $sheet 1,2 foreach {name value} [array get data] { lassign [split $name ,] row col switch -- $col { 2 { $spreadsheet cell $sheet $value -index $name -string } default { $spreadsheet cell $sheet $value -index $name -globalstyle } } } } $spreadsheet write writeRowIndex.xlsx Index.xlsx $spreadsheet destroy ooxml/examples/book.jpg000664 000765 000024 00000320771 15213015413 015571 0ustar00alexstaff000000 000000 JFIFHH22ExifII*JR(1 Z2fzHHGIMP 2.10.82019:02:04 18:42:08C1JFIFC    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?̛ AJlO4@pzBO#׵Ij%s1d`Px}3XUPGcjArQGY9#;*S;=s+HR252TkprA ,ac/$t5T{!q(NOבDW@IJK7Lj :LJ\g?*tJq VG܃9MD@ FI}F%BճS# fBHʞҴT/ʈ;}/.C(G'yPama!{u/.r~bj ܞ?sIdLo#mkP\E' h|̫'>k 0 RnppD*0ƒ]i Q,rqNa>fCTU^LDL7~^$ ⤉2m>VXb'+)Y3²d?6zY+ /ֱ(ϑ8AȊΊ#*3*{PI*܏­"A$I%W$_jEa)2sT$`vRXg89*Vى8ڿ8Q _$NnK`kv^OG_\U?19a @횻5̆&<3~F}+[1?JwZ, ^CQ WbOB"̠$3sV/NFz=E bV]U;G$Eq,-ݶs)|xH hd5Zw8e?!P=;khmuJj@,sIoVR˷T[W2\*Z knqݱ  y=hռV޻p}jZ{xh ',oTn7KUNU{ʮAh]20O8?PJJ2쐓f68UYeIDBlA.~~\ i 7v֙2HA^5$36L4.$?Ҙs<( ǏX0cs1dEP.w9*Ӝ>KP\O$ÌN@Fq4CFPz{5qKla/*oGRٙnJ OҪ:ǐ;8Uf 5-6rb0m?*?ҫoRTzc V@5Rx!sM7cjIkp1VVPr>G;āa*hym" M wRCXF!7jKhkq9yY!׋;c=<$0;qGJtђUOE9ޙ4\*)UxUQD(ΎMx1a{F?Qɣ^>w;ߍH u˷-NzFSJ;WwX$N9>=%ԒdJstpgfN.TK6Rѻa֪7(OOz`FYq,0VHF1O?9A*2s١n20 aۿ}inNw(]$),BCH܊iuRJ<01-k*TA9#-pT=pG^!W8\7y!P]'O‡+kqtF 8f(Oh"Oy"DVEWP i'LE9RB }rsRK"* #&K$1̪vԎ8~d#x='קUR[ C#6XviZRd1b,=E{6;t[*t­-4.~eǸY;fhpG9\4(ǵC}#>\WDسnAfy$uN4Tt|w@C: 9R})81R-sy3twvڢcЂG^?EC[r9;v9{UXذg6OZYԬ8!\g#V|ePGAW"F[@&9"(PMLR7*d|u*fw'& .«ªOa{s y02&8L$T gl"f6se)ʷ9EHAi{-,=Me69 }*Z[+@l}7IaLK''h|.>8?˭J4S%.Ѽq}?(iPI48w (X\])Z2F̏v@&wמei*-x&LzcF̥@lMI74SЩz]a߳>eɆ|W>jupw%ZgvrryiR`baQBz׬xrA`iV P|#/N8ֺ[}> ,6"BqQ.< &;u ?:k+fiAI D^HT`WCjz0i>H5p3(RJc?ҾQHTimyNq(?wܟQ#n2;+))i=`.Q!YO}X=g^i-kNZM:щa_a-x9#*6ކ6,3å}9/tiH*9$'?e;A.I^<ԽK JrC-C֚M\Te sWwv7\wP, nV8KsqY͐?ƵϽzZE^LbZ Lh1M%O?4f{T~)'1 +N; qI𫇜T!R |ĺN1w(7oXϝy+?X/'S3`tfF +zfT\_=+H`t=*RI qޥK eXԓ .&9$  )8,r) &ț#5e.cmDX|›q2śԭK\SRȥH#r*< ֈiirr]f4F4VHMmR$y'A '_87I)֖C*PӒySӧT+,.ُ^)R| c%=UP}sS])Ș`P1H8?g#JmLc?@ϽY;∞M1i9Ić^Ք*r$c^fPz3nY& c\cz5r^a o`=O1FK:C򎵥9'#,$cn?Zʳ<szrZqf@7 m^N,&s=?HS\"Kt\6 zOb˒NO?@f% ƪJ۰ďn 0ݒ9;9,-wϵV_݆b9ƫJ;!%$y?K|G+IB{.rC#psYI>bLI%;~t#1XF cГ˅#Uey X#8=smlsJ]vDF&dMXyUc@Ja?7#4-NBZK3=ic֤̬35z-{S+[65F8]fC2[Y#,'^Ylm᱐LJ-J΁IlEP1:dI YvV$3}On;ӺV@x Aϗ|#bz2N:TfNVmrlq_N"*0նyL8kqި'hz~*hp3{PM  tHq#G'q[xen\A}k>#hj`DIJ)ŷszק);Z5d!~x? x[] G sߚ5`ANKz!5 qX:6!X67ςz/fX;dgڣf9=*ܓ!=E3'8=Cs)=WS[Gɟ+4_\ӌ?ܮCh fKsyMT+8_k?jȌ>V9TN('֔dHNəpT U ھW=rN \PL}O4:#?OP`mgps֪K",x:Υ 8ʆ<_ƐT&R:Io>h9Dg?Uْ4,I؜sSG8xc99v** H?) 8lG+Ry5 Ѧd`n"ELJI62i&H Q|`j-Vy{`ʺia=K*)N1´aQ&wwk* Ibsz (X _#}*LQ9#\* ±h AVT a2#'ـ88y)DExTW*0a +ۏ;W6y]* % .\c#ɑیa`쁇O,r.) y?ݫW\{Vl|mrnlrKtm'm*=Z0wĝF9pGvM=flt@~Q#JѢgDab胦:UAݸ#KP5-;xy\H=VtF~RMO 0Wd<3{T@dc8ݎJ)F6YW)lݙ6F*s# ͒џJ`\7ZǷuX+F-?Q\7*/]Fv 3FUrbryKUHd'2r[(L=>1Sh֚BPqؕ"n7qb Pq.=с<ӑ̊wNqލt(S(\46\ԱRpHbqC!rG ~t֕|4q_JD`e$c;ec2Y?J[$878Hޟ֒oc\oXHpso?aubf$ 9tEBPD{X0*1epY?Jvݞ:{^ 0(J=ne:}*WQ0Hw rRF+#3zXȠȧbQl\3+מ幅2c&?ONnq뚂~T぀jHYr*Nܑ?)!'I~W;Ϡ]?t;rNHfZ>Y՘l_2`& 7Fq^j5+|89LKp!LT@r88jpA*y2[ā̌0b'Plfᔂ:z%Z&_h$*HBr+ss%*_LʎWE1x|Rr03yOf ĩOM8- dhGȱ?W.?u:GHЫSTb`6?6zlU9VbVcNUۃOژ.y8<8ԯ km8LF">e|8B8g{ۭ  $x=䌏%#ُ\H݉E J6$J~\Lnj8BLcoɸ\r=bf%J5f)" 0GOLą7rYU@$6321)#nmۀ=G=j)c.c`_In7?wYO 8h?oX3)|]004jrj)/ʳs1τbdDUUFCy{$N[ ;F >?ZbU,a?`(vEYg&ߔlfȶVytelqssQ+Z؁~WM2@~*FH$R; rjHd,H1sanG#{Զn16dU$;z/z~W,B8< ͚# bO#ݪ#F0p=hV}N+ >s9>(2ŽұUI==%=ƺU%O'P):dXՉX09y{Q{0؁&_N~aQUz8[$)J@8~ܴ3t D1M4=??]F[kЫ[׺"}[kЫmzUiRʹ˒jx4JdR? r?8?H 8m¦Yd4ya#Ž*^N~[~d*MC) ?rZeŴ8CW#8.[ZI hs:AJ0rr8"5OOw5Lz H6ARU袓DPDօ$&/RTI])"qE7HOqRx,1W37DK(Tڞ-.2iq"OeAm&lM TKePgSfԱ)I;U?)s=+6i廿 o'g'Y#{ˆ\c|j?"ɶgmM@PC@bIfȌ3߯LQ'YAp10OHj3R{Sja0 Ǿ)RQ @3~~aP HNI0XDy0*:S%nP ~Q; l081B֬ K+t`Pʮ h]nӭBΫ88#ֳN±js`wkE z7(5AJ5gQ5',U??& aU?K #ţaG8} <O]]?Z3'M.`x5* x:UY|eYnlgGUllu{oYUֵ[;A3T$Ih7=Yƃ& qj1czPP0x7+s@+HqP|-ҴmjUaEuܙq_kWZֿBU+MFT(񟉔qH2+udrO ske~[?֗1V>j?4k`+o'ͻO&WGZVc-8,7&GH, \'?xQ.N~5>SzJ\I! In@ɨX2z%CO0eaj&$r@)'}I0 sJIl8uF`19P@r3F3r>!I\8 S o*NCЇ~tO=CHAPw*刦aSʰ ޣ `)Tg#PG>J9#h* '}hp_C֌dz҅h1ic 4j_: z9y^8⟘G:dP@zQr( )ۆNsSF  PA {S1zeKsAyx'Ҹ ݸ`ƆQ5,Q4#6O@>LCe%z-e0ڠdq8M#+}Gz̶Јeta B$Hbh?t+u@3|A^IEÌg ޕM4@,8q-GИ }M?v8f$h8'ҏF18n*=1M8BA@3h;@44 2;JQr7}[`7{q P[nhہSp \sMnh2}8\ n)n'ri\1q1 =G*(LnjӋ"Ƭ"/$jUh@IhX֍zҪv%LRa{E =A9PR oqTdXho-@W BH?{⚫A}iXHe<րgcҬq\kwJI89-'qA/ x?UJoŒ~t n#7O#cHCpOJ[xqRE J6G;G8ԛ7~T]Nճ֏@-DJp|'iׅ7y;bj;[2,NH9y6aa#!sֱwR%[xc#S]Z43:Ln=V,F$]Cr'iܥޅY8HN c~Rʒ4lB6)`rqS dުVēHHc8P93{ӣ*[h#>]I?UmE5BA>U6_i׽K)gB||5ƸԑgΦ:-DC     C    k-CAGV 78VoSdT6?sKjTj[ҳSiFfgk!-1_[c8Oexg[p-\l6gqHuQ%]8V1RpXbh^zڗP\=]8]i1-,&?S>iem[1hK:55Uw$]C$zǜuuKLTENud܀1f-~K} 59eIWBLkKceZ$P Hzj:0(+܌YrGurczwRI 5YԏgXıL_G$1ZEc?5~|ݣ =tf0Cf9L5nR!AQ@A{;T ƗYpV 34؅dVok#45g/cKulNm9> vBr٤ ̊k+KjaGUj=8 t*iVIt+b͎9̿Cly~ޕY .mb1#ѮO+ ]-(].KOQu41 m2IVlW<:PI]^kk7Œz'ҝZa})YW:i>VYo20BRZۄ_ ZRiO{ufnXZzw"*I ;չƴ8].{АCg6hN4v/?|z⭊\0k0h R=%9=azxi|jY'1a`T'7G oҦth1͚=ub8˜ˁ9YEYvh5j3e=)-w gZ\q+ }Gq*Wbg ЛX edI2NieaM M$)WCYٹHwi-A| kzϞC|(Ѷ4G ]o;FYX, XW07[fކr2+g(OF2zL!tY; H "Dٍ xoξ^r>o{]˫ѓԶ.rQ0IS=4Uy~,炍ET4!w5ъGdvAS@*&pҵ>C(r:o֟z>:37]rӑg*wtJvDU mLPZΗG :\Smo6C(ϥr\^B)0,>b\+q3|wB+.SQ/K1ٹrhZh;ÔJrne0,\K3D)G8Sl (mUJ0}X^{LŜBBd\*{٥*psl~ݘhoz-CVXAa 2%V9pV 4 ]8he(%T~A>kˠ9'0pc) }g'խ7k0. 9C@ Z=HQԳ\]xSUF߱ogўߍFb.ȪȰ%>Hbm6Hsy&ϜB$s3C 9.U&c(.28U:!2RPH9|ŋLְMi[|8L&bCɬ pp:t_#ƨ֍fE)c*ۣ*ݨ~Qg!D#4/Cv{BsFt5t@t!oƮQߠ+xlfi8C>X3Fj( D!kX!3;Kxs^Z;ŖYf'a%>G'ƨ /r8S[5XCdT kGYJ-7׀2BHX,:TuħA*~_-dُpfiF1;tG(Z_MQPO;-sY|x]Aҙ+鲄3pSWBz(ݙD2Ei+pI`#@szW1{mBztN1hidya,3U]/[8$UA;tn,oMzC4\XIM)q5#E 1/S/MjλG{ouix.;"G(9ifOxɡψjvl&JrgQg(QzX\YԖLp[!aiZP|"6PT@TPeEBw+|uQhrEd>QbRDBZW8YjTNf: 6\:=<|]uslmdMUS8) (4uMZYW?!9 1 iWI3G}- ,U#Jr3g 9  ɜeja,97`oaӞ5Zs;c-K;K$|@,7lO9<3YsXu(o[Й`jGWee 9Z`둦4 ,#;/Z{埮z\j)ȧь5/d "B$,?lO3+4gRť7Ld蹉GUcq5fnbRԋs2NtюEOsd~^,$Q uD#U3&DH];5^OW&MĘԋњ$&d$%>ETMI|hpI/cXoqIF&UqGٕCA 0Ci'@0t 0&$0z0(@4Tgzm )e( @Dq6JiFHGs8OMh#IB٥U3螬OUeŜ( MrvM:ӄga}#R4SYhhԺ&u`",!t@UUmϕo&嗶!MB+iv9Ns*eh*&Q\dD'P.:l'K7Y[A4Tɦ˧dG<"iq5ᑜ0Z]5,ȫBB'SeO9e~z!ve# ]9M `=#ҍ$HhYfF!!(HxͧJk>sC坾YcdC ^әv>f S#TPSevNΜ+qivـd\vv)S ]:"ÐP4,TM*1Nt1Zcu@-9 XΪ Ӂ٠ŚՓ);aMt'>4ҩz7;i6Q)6I$%*8Tj|Q'ajMx=(!Iut gН8^Z ڒd4f]C & 7C* taGa:2\LS9jLh/4! pwjx|[y9k=p1Sp8zU^Hf(T(3&p*Sb]7)xJCg.捎sU*/,!;PQ6їVia۬0mRZrSRMݟAqz5^,!");˰\ed!| 6"O*s;:>2Kpa(HM\M0e-(ט8ɳ" C,S Bo ]~djBEq`rNwIwN˵"ZC3oyhi"wd%>NQ3Cb*ߝLdT% Ѣz,E@U+6FG!d-,Y$͕Kg6*ZQZzhWEd.BiGO*H[\G@i)2mtY66tubhK%[,+T Vp*"!:a 2`̨SaS2J2 ewP&3JCm, fM{(ݑVHrJV%VLVT2*BU B"Tn,J2E^&K* ae@a'* fBWLYLѺҫNQ%XP1DQS!,j:d 2w\. (థ(,yV*tS"n#ppY) UuiQJpbyUYF5VGtnQD. "r盻c3J:Bҍ*56CuJvJY>jQ  e&UK%VYHm*6he^S 'd!d2iU")G1:FΒ3iVp]am.9R{,Xl Gk4ꥄp(INUE[VC,T'R+"vJCG's7әgiU˽4+|T_ZU!VY<ҝrXkB UE8 *SV2O"&sm5ԅt?󛶏B^>N^˜ѩ%]\bvGGmU 'D͙C[;]*\ [mdָD OVU*zBĹz;ygsFV2}z\:_ڹt^NeQ}BVzuL-&xYlmnd=h[F24#vK{IK{ɤwJ=qNp,49pQf6+}i[෯ݢ)Fv31ŗ<%cLohqɴSkƟz;Uϋz#.NdDb}#YsR*0rj`1k+AW T̀n4tFdjIPӐkO#kinR4]qMޏL~?SLa<\=外ͥG,+D4>KbBأ`҇yH؛ma=CIKm;-I *E$"3s b6{YЪ-'IT%siiiqKC~825sN6^/^ezcijeRqăi)AĐ%vd_Iu䒷UbD=T3rmpa->K4RL/ӓ[vn^ ;~{)'j{V)ȸ>@0ZцzǂQ=ڦY%➦Y)A]xpE5";E;SR2jD)i)}'1;~)YMII_xCKr#wJ'yZ=zKwjS|,Oq$[;kѪkz) ֱX[Ia淜]z# G$/}م/ʘ]¶#g! I0u'9Zzc{+Ir9Zi$;VZ $VII&z帤B$R]s51mQJd$fM1y fi$Z2_'+?-Du-|`h7rVK5@>CV*tm싮hAd-J]HL4)" Lx7_#xoBFE6vyIg̲N]dz3Owd]"PU-- M ~o/zŗN7 w~+jY. j1deXBV'&Z'(Fn3DJO V" /bH<f9}rx*h:JZ?QfجKolȸI V3r*k#7Iɸ$jhdXB ަ0=K [YIm<8h@%іhj燋I'tCP4k{7嵇 R$Zr.8!c7$)>޾4(%tDhQM# FzR4lA$<6JO$52&䡫8xa(Pox' 2^{$EpJKx"]UU ɥt }n3ਸ'-"ēRG>)RqE:;/|B~%1ꍹ+ךɐrܼe1Cn-66Me~+kzb_+J j2$ ~Ry~Ș1.@EtR:ky.Rzp~0_Qt8Wʩyid>#éص/~>!Y+(R>BDq{J xcfi8giĈgr16s$|ss\}3H$⑦o1XW$(9h䘰-YrM|&t7]lg5Բ'6#D6اWXiyOjgZ?sT}}3CV|.;Ss┆Y|RU' Ud㐢gvu[}eCŔF̮TFM N[7ZP`i'ȡyR(A}ᰟP2̲(.IWLG8{xi>8GڵDl[-Zmג(Ťa$? ť28Iy$k|dαE(фIGQ8[X!^]5KxѼF4Nъ{]z R+;qL8w`2Dxk|Ы$}3<m\*He}m`zmA_0_u)z\]#Ih?>2.hV@nhIqQfk!3ӗQ3'>mi>7_EV0;B&0zU:\F4JbA1imڟ2~>~ 5u K4c-B9K$o"#ťAKE%i#QX("K'8BySU f^LE-hr.1:(v]Q\4R\\?~.h8 TdDcms[r@tfm-+=i6{TY #*fh i.]$ej;z*f[ɑ2RM>߬H.5,'b(Z_X\~oӕb:cTϭ-os+GQƷ )a(Y@Bp V2&? "Abp2tC^@ ;$:0)Ƅؐ+Yblo/O>;XʪKsR#+i-09a}KOy&Q@a|bVh' vIgG5k "2 }<,ԴGtm@.aO;~cnM0BԬ 1k,9wė\$|!:y j#WN7eDD{t_'RۉIgF-"x5?AF$`w՚.FHkF?ɚ&~.bU-E$0ME-2ZH ڬFC-?,q#(Е#c%b鋣m5m&7hLmTj.%@5lʲG, "[qQ>3 6FԨ!^CܚG֯E/K`w57cӷjO蟆?a#7+q#$܇<,;R4Y~] \ n"\rWQiIssr 1&ФT\6u n#ݑ @o`Vj_+j+[}E*)---%- >$Q}I>o?Tuo°@TҊ-mB͂B=C(qu=?KQx?R$KjrO,r8G=ugPIꦛ뾴'՝^ZDk> nKVJ_zpXY?Zu57]M麵SM%fYi~& 1'#-49GdczYu4~՚ڿocb|hkqEx@mciDn|>{cGbT= |؟|{~ze5 AIG__/>=Ш$ՐhD{ ,p(kkހb'>LJG<{x*M QMGVqD ҍ &F,-FcEtON*mYj?{oO DV({Q]j$ aJ)$PΩOڝVc, ֙;Mn7PdVw6SBxXRPec16hv%uՉϏcXxc#h3D߼rʱX(b*9+r<#O!ZIv5ݫ We MǹWu7IkԧV*(Zi5(8=FzƴR, syyξ1G(&Wze=YX"~Ƴ/+NsXJ){eo\JYtS,k~cՕ(*]4Clb Cc;Vq^;R՚#ڏs dմJ(E-lci#v8+d1Dʂj E|r(]-PMj+jap*!zEǩ΢)¯ E="4!$@ڇ`j$g pǩR>)$}IyޒI 8Hur3DkY{Ԟ3aL5rs]ds4ݞ2AJk^HB(\!w'> rE>Bյ߾sd#RLGCQ=Tղb!,RGye?T6Q¹VǧኴkHޛf¯D}Iozl( kڀ,BeJG g' VAKxbAGܳ$MHwJCK bfn+"JU #9W3԰&S.ZEɛXv ڋOfFӝfT#'}a4޲ݨ <E2wsaʄWlgFRκHWؑ*Ɩ3WNQZU5hO3II;D&c+-cVaFz:$jJ>jOou6c$u*=vTfk>R" #lͶRrUGNr('Ndg rGp+8Пթ|H)kD ?'D>vDrN jg!,g',c qٶ:BsWTwV8#(Q93QP$^>(wXݩcCrEjNe3Oթ1RN !qB*$2AL#PZTA-ۻ@t1$MHВ7g=S٣vh*Ū|z5q'צfʪ#lb鎌ɱ DVQ>] ݩwOfRiGSNrLtlUH/%|ZCN,{:GTٲ[*p>L&\<]`o4I9qӢ⊿Bٲ,vLjdTUObJL3 P8{0$vD9&tp&D{ݛi 0쑆0*d"գ&$D30%ٻ4ӳhp+"7Ux"H\qc%828uǶL*o 6UZa18geP (סU N !њj7d:0 RiT@?.:+RST,xήD8`CijBqݚjMz~T|(#2*%J3-ZJ''bdFOOү|h"tEX$Ad2, mxQ|8ng_&"/, (<50W.=SY?g&rbI$I$I6nzu^^ PP&i&ҍp%>Gпd(w$I$KUEBQUELl 4% JKj),P̏ς=:*cwOnxB]GcuGmU^G/Ŝ jԸeLlVXBDjm L-7#wBu8v/NL8W;2)2d[C,۸(vG2wu8'eVBW_*6NJ=F1jD4Gթ],BnGy ;|ҳMbhx+ycc/22dɖe:V2\WRaݳt6-ZPrFF*}3bǯgED+&$Pmhp!@jݜQ]S qŧ(~3"J?ED9I$ICLNkQܱ*{d= Hd64C2C{8N0Qj*'`A,Y( {_BP4:S-4K*0`_3:JQ&I'>ovoW~tqg$Ĉ6Œk] |7w_VL.LegybO;!vlo|$%ɞ|2EM1*{1"(1=_/R4rBU~ڡ7*% m H%;&mٛSLv~:j8 QյjV b۷ب x+QއD+1ZŲzBvӳP=&w)qD}􄜣0 gvd~Qy+** =y4ݠ>/Ur{9T&'b'N y1#Anjhnگ!|gfh(;wjUvJV?/ `~:&м"kŃVGC, uMD^oOAAy$S[Y>;߇pR έ Ւ~P{|Pҽ5a+Inklȯ3z#ݒ,|~]#JXC֍DRǻESzJ+^b YZ|'~ *|jGL㢧'FМU[ҥz㗂+?'.WTXUJ>؟)Zۄ5ȋSE[%iѦ:7e`xaMQ^E 8ݟv5)%SSKZ .d+~Gi`\S%''rFGjJ91GeIx-U+|JHiKJIIwQ|[J,ER|{;9RXDRG&'}U2}kWQžʬ#KmznD5N9RrCmOo(r$#>/ Sr$OO|^MW:x5?)x>R',┴esK$zeDB%$dVGUZ&rGĢ%4#ej,,!r>ۜ] >Peo+_ƥȌ-8jݟOR_ΎJX8pp4tք }y0ȿ #˓}m_7)ʑ\Q7C/wNMd՛twhi1i2 N|>y) _E٦C&ԗy87yŎUS~ՑsXI#PJ}ȎejE7CVvR%?mE"1QfE`?M,58&qiaR8q䩘CK.T<sOmUi2?y!+m2qV%%-bU6X%:DX>RkL_U&핉RfWQu{K?Q*O$dt4d3#j"gℨy#- e$ "TK1;$Хf>M9s齹{J&CʿJuDӤKRP&ok%hdHJqk%B٩o(OϢm,"B9.OלI\|N ҏ->KIԺn9Ɠe%*<[%ڟL)~r/#vMf!::G.κdܒ,ҍ&iMjH^v{$NZ.FQy#I8Fޞ{Xc[ONI]| ?༜c,nk4lՆ9l~1a42 z5'FrSi:B_& IEd\A_y'&=^QTْz:s|dG/U'*#VhiudF6bU.J/fmWb:Z|##SIiK >hd'/k+:J-.2S CU?(=]O?+B~=>Y]y =HEe:KZj%,~II9"wчЕv=?4k#ݚqk#ԮAz#.k8![[uiֆyďX,GQt=H*~ȡ9d4$"˥1ꆭS>|GE}ɻcS~ӆI\[:zFj|Q(CC:|eV?j*_2FMb"^Ue'uEmQ> rrJ1?M)e/0X$MKӨO|CC#^jϽtG9>tD_G/*cQ+?#)/l1,_'~RY9٭lRx#G}iKO#OQjGrTqkͧTjMiRoiq|{>U4h#&ZK%%DqnSu&-5EC}dfYv}ST|)>LZSIVM-W 5(MA{ư5/>S:Q^9X}ȉcȑ))>(b/4q(ݼU NݢzՐZƟ$}G=c#ׯ"zԏ(T# vw| O&.MiKn(Xfq⿸.]jm35OZk]Q'쭪+6N44(|l9>r! "efeST5+]1M% }Wa+49򒥺} (?Լ+W&Nlx[Q|x% 6U }T9ATF$vB$Eo[ע_GGlfxLMGޮ<B%Kgջ?Сmkl#+$h+% mu,e(Pҋ_-}m__i3"۔d!O[5gے~)/rgecdh?"FBBُv^]GLPZeraG"_"у (]"> .f?+$2t+/B(PyBzc-`D[1u,;Ǐيmoi9>Zia9.ɧjH$oϯ?zGG PDE>$.Q솦bSjQGq^}J"دϥ~ 0`ꐨXɄ`Y^"-e[5q sFshzm,!鰩/˝̙2d bɯ3MDkCN1p*NT9I.IˇD/qEq+eϣ>}D9Eҗ8qi#IZ\GYXQe8*4^8O8ܹ9eD%Y!<1|l^1 30`1V4hIF*4HQ2KR0]Y%bE&͌+Rgu/t[2'!F=𐐢G3wr[K8^Q IJ7FK1od#!l3b2d[V]TJOHء^NN%W]MRNCQHS6о(~iK 'vIuN ,ZBhY9'$HR>U6^gDOO1`?RTϣ=ע=7bu &#<8[9ti)3Wc#Be3cѥ$šch/=bc\RbH5QRW/~]l8`cPh_贼0W]{6b)j jz,Z{!loNP"fȕ3fZ-+5/Z9TQ}> rEɔNЫ!%.ѓ;g{DDGpVli7>:=%C>N쯑=ޝBq[/EʄD/U} $hDknhGG| B"aJIv{*=șj9f[5_-Aq՟΄@ivTkc]exx$GU"##:~.^.Tg࿔I~h<^ۢF!%GG{\Y%LBJD%1|H|w˳HR8k؝xMKy.H䬬]lB"Cqe%?3]]PyR*k"xhw[/N=8hD.eǁ] v] =+(j~ Öw kzX3S!oe4IxBZaE58j?^2]1j;"]lxW]L⪏ o_vfǓRz>'-vq$.^KRt"RkUEcٗb̉7%j#3vő gVdu^をiBPȅUc,1Nq_1./j)wGc^D.ҭ؅]^1ezJEw#Ԉ,c7o~}c=̪ڇO~O\ף9G3r9YG9|ɜlI:xIZ)3*^:ڋϮ?Ezݍ:x{W'=k9|;ĽN-lѱejMz&c]t?ECoiYky/Č(/(W!+'>Ik{ eBwhd{ސצ\|([tv/_SUifzJ ZMmw-_*(MW.Sଡ଼c,"*ŷt+[N|]6ۏkg;__QmG%B?DSv(}9Qb^lVMG Kf siʝIDq}D$9j7ёoVt2]`䌏NHC/ȳJKoZBJۡnbtX%涫gCQY)Gq;X?9*m'[#]՗R/dTM)IYJ΋^|:ny*% 6u$-De,_oe kE'MMU-Oժdr55S5K_n{ےߝ;DSEНPѝv-MYu[Ϧ"#V{$iI!>~vq_81UY(տM]):9?#j!j(dcpSdk{,;>cDx:D' ~БO>۽)vqsm#OO5T/=UR"q]HOΎJ%4!$6^ڜigݒvuimd۾~GBT)t, my0퐏ՔIqE՜"[I)*dje9)KKjj? ]o(i#NUBG!1A"Qa2q #3BRr4bs$0@5ScCD?][;٠ku.V5ӛuRlWRX-%HX]!FPt Ű8 >JyuC^+PlN[YI+;VZU8f(?⧮e9YI`C:W? M%ͺ{{(AW-o$*u]-4V57Est]hn=nŧ k2V'RU@I._\ 1pϴ2Vpwrv;#SPۻ EKoX7x*!{ꃋ3$oXD4ŮfұXGf9#U 4vl;pF'TBUp#d5pU m꧸ĠGX7_"_4[xfUXGnz|.$)i-Kk 8Ҙľ *2MT=태G]ݏ2'Lp׊#|![r.0IqFg ڧة9ToTh7෕`F)-g $v{Mht,<ËϜ'0g, /5{apy%LM$> nT<)~vNW*d0vq$ x!Sr X\n*]4T^3r8UjeLz/-43\U#R6p>LpPOrhh*Q3 l$f8#:+ M;Y(6A5§OdRrSKF*p0 Pp)6&vcc'y[FI.5l9dEĭ0EӃ6R淰ys cnasʛdTܨn_4J8洟^bqN#GEH#E120ݥb@Ow4RCމl@&W.ޙ |2\ V&4fKHf63+|."WW%vt♋\Iy)9쩑VW]UOQkEh!m+Տp)w_ Pw 梮W}BuLl\(bMs]xzf&.Vvva;OX_izח,ީlib]hSÚ\2@AY65ƈ Mc\\i98X* E=Ŭ(v4kMq:[ݯ.ۦTjc#P..J\PkC5; eF̔lܭ 5bb[?ʁ~q1pNHs8-vh-4؁Ǭ)a:*dnm0SVG XX0si»rUj8Nq-1R AUpFvGa8dҺ {K9]E1]MR6#7Nhh-'zNPqS2ӑW! s uQTpVkXSNGLP,QS&OjТa TevKO5I˩yԏE!i$«"- :rXdh.<Ŗogi#܈Rl8❅b2Uc70n4U^0-* j(28\1:EE؃f#[☌Co1-0~f''6a7z;aׅ)e/Wj.yY8RbZwm^l޲o^?w)Ú֢К]Fkx>67⮡ B2rȠ!@TCx9~SP-=teb<M0މMcW9բs&tC"8Έ2t4eFk"f\rQ0*fsC[3{ZJ]SU'#,Nfw9~)gѹT{:+#F.S3-LsAf&UTbhZ:;2dO ^s|BSFf#)^T76W+*Z3T\h`eLPoDoA 6D#չ1p, 66ISbj#`蠴ose4 ]:ޮ gΨ8 m]V( }'%L > Z-]ʛMp. ;-y1q*bY$pahшP8#8CrmFrRvZrFX) .#D).`7t-ˑaq FK~!ٮ/rn08''E١6%un (s5k!YSMG$\&ibGWQr(c?oxH"t.2=|ٺ?IS'!y)/H 0h"y6J4!\)SI B ķ*~7Ja++bvPs>hHDY>Oi:d줈~O֞K ;0%S-`qMf no-ڛڻ@潤7uavN\oFlaa_Q=n[$c>JJCYx~}_ _a}KH+ > Rz+t(F; ÉWu q i⃣2>+jպ&+vH6]GxY\޻m~* f\ ;Yy ! %3f'kj,g@nc .iٸ V'1qy٬28Μ3tMGc|ָLJ)2 uBa4T;jhyoN9 JsֈF0=!i7D8P ,'RT_Dsp:4,I\ c(Ԫ81 8w,]-qu'dgN hl * 鈝:l|Ja{HS ޛ ] v_ +6%@Eth+Sl}PѮ̖_6]Jt)T8\3~8"@֑&H'g&!0hED eQPWh.SP@H 2LofPI;z_6sB[P) e[l+-n)w~?Uq35M?4'd \|UWF?#Li*|l:*A TT|˅ZURi/sVØ 3 i"92uB6]3 dc4# g'U쐛O3䷜\y!<_?%S݄ۢ?fs`{ `P7/STBsWϞIф|IRwD_2oNUxR`JH/WQ vn=񋉊VWˣCt^IaqDA8u 4{b"~kͻ^o!`ը 0pU) + A dkwuqD殦|~if/!)㭪N)ՑtۇǹtIq# XΧ#94je "@[Aaw9L!N^W]7PL.k#A2z.%77%ETQ7 :Pnp-1 DD;WLd(e[<9No~]N(+ D 9oټ,PDloϬBDi މoP걼HMP@3}m;* 0BW6x5EkaOXY֎gօla~k fw/&ug\d&G?@SO \ x4]!A^ېl]+:'8pbkEb:Ӱ9t!SSy掓~m$6=&iH_X'K"zHSñ$E/0'$7ڀyyt߼@Hb WnF%eQp=Ubd02-'tl?>O; EOXdX_@bA;ܐvhy|o/[&ĬJIsN)%S7*LN]3~(C>Ӽ`]9i%GKOXsX3i8:ܫ(<@CxYzNpJ'[M,'v87t߼PiUWY2uA {fvj{=ȏawpcH7yv $q4Ngьu{04 JLX!z8 24\vZzTNjwVcP: mGHKBWSg9?mL'BheW8i8bGw v{ _VP.m.w.ar|/ n Ns۪.ə$B˦oH(g>[~Km S-~[ߒ[ԹH4+jo le& 0 5Ui85vg5I e|T7 ,hof)s:s3QG=0UVA:X$hh$4I.$*hA@;7z ;Uxhщ)ӆ'KVvONAhd2D2 lngpM[gH/oC]Kd۶5@hOnV(4=jP NJp8ӊ ~7OthT,G}"CIƞOIqvNd(8MJ]=SG>p]C#~+8)#, #.5oEaKrqcccMh\xPnh4:@9\_L88:X^/su}k;b1ꛘnS&WN:wTj;*M0T7_P'3rMLgVq=+4Rֈ&Յ dqG; rn7QAP~(Cu_M|HY0ڱ6^늓afV3I݉ہM")tz<'fd)D~Yx{[~b(!nዷPa<P4t3 cbtkȣQo8SLh4 ×4ޯM a+=坿oV8'RkZ9.;6jyiH ZǓ~5kQc4\z".T*^&ahr9ߒ+X~Z[JݤG-Mm榦#᪾#g˽zFyN(eNFAxI6JĎON䷱W\6V'N8֌&hh=D8_{4u-n(ӌd `n8jobU&>*}Ӿ5[.;9 Lf)ԶjMu;ܖ`wl⥤ɲWG^?vVȁѦݠt`ܴ_Uﲤty)߳RjRz=$+t^ OG#_?4#[Is vk`ޝ&-c@Y"~j*+ \yN4@55cMSjm. pD 9h6z6~We\0#M 4;[?sbxUȲs94CO̬QL+Kuz'~HaN]6O\ gǽ7ŀ6̩L|V 1Ho xl~($I. A9|rG Ě$&AE;?4]M^*ӑM`qF1L􌭞j(k*= U=Å)DGz;FWr2P##@]7XH+~(F0*!~jL4_R_nQܺ7ܳ?5vQ$8 *qӰ5?tDRN*'+uM]o ?ԗS'8Zn3M{z>k [ 5N1LhRy)p &Հ|8d 9>(,Jë'5WaY$GͶ ߂@ΚG?39,U<"V(!^.y4ncFa㳢~H3k{gv@7'b5QxLi:Td|i#.hF\"YtBC"d "Dz 7({ HF 4 0R`6"k:`D9#N:#4r^$SvXu&4:',cD',Tƒ!hJnýSz9"[)խ98S(vO[QNn!z2UB: SZ7Bo5 E%7EZS\g\TQd'V'{S} Zxhk{^Js{2cj;[ϞgqsN5:zWV#TI+!f[F%+я l_z{(rjwXp0`g9+B4(Qrk c%@b8tON|%;??ܻqƜA=n$4pQ3*m:5R~(< ]/n:'"|[/ܔx?xWRʜl.& Spslh0[UlΈjU1T\D{7s)NPCZ] 8Aee9y,{IdzV܏5t7":6&)ЏpLIk}չ:7w~6K.6fb#t9ł0M\d!jJ:)*8XhCe)WC'YF-Mq.0\&m!}I_Qo?_ ?= [tn>?Y!a7 }nu{C/!Wk-ޓne}j{3x_]/I5?o__GWP*#_ttWAtYo>osR3W*eO?}uo28'7f-Bw kVBDJbF^Imy;g6 T,rEFʴ\_ȟ܈$Q2TY( F/ܧtq!v}нW{HYvATw8* #heNZU#dJ- -"4T-l[2{(ider})2p2T(# A=U8bv~9. Cxw0s"rIdW\vT OgERlT[m Pwi,b/6kNߡTζ|(\ 6٢%Ip@̮@ tawmu-'u*3D)-P'5'mHF&ȬG7O.6vxR- $A[c;Ӫ5`Tz@AlwX uQwU"Q 6 ;;TkF  )* Nܼvc$W<0Q La0Ճ2UeB$wAf^gP\_ *FBYlSQGazMcZMȀRAUb꺏,bs&>e^В/QyZ'7[YzOPye\ʭz` iVE_AՔ g2]5_G9%ݸ87m\8BH-s*olNOqOǺj\`q; #q9q,'  !LxSne#$cf#Ϧ^9h |yKz[vS-A"G%y2e,EOv9!EJUJnwK.8ML ET2KtT>U1&uݥK*F`%qzl}!Pň2jF)VTxʁ mE8.ȶou#(Plq+pl#Q43ʡ]^%`mשcaGXdgFr+`ά٦.dںa[XUw+⮪+-) ʵ5"́2=Llq)0X!7O'e m t4M8O57w<3g_n*.)27Cp5C x ћd>Vz`Vqјo)|Ei u^(eMxu#l~0̌5 JTlMcm5,]%3bЪ>CKBS\+pC|f,u_O*$N=`,ʼǾM82 ~<{İ4jb,ԳU(7bB.XcPhA&)A _rw-*PWzG 0K>3QSPE=LQnE{5)o1(h=`b @xs*Wi`yr86 wmGm>EVnO8KKQ\csqFCf!sl]|Q;q(6t03kהO*^P^4dVp!2 YZcg%/Ϧ ÏJʥS4WĪȡ|ZwN_l%.[9+MQ0Έ@s@%B {rŢU% YX~ISGܰ1V_ 0d/9%?il [*QsJY]EՊyj&pr<8XF - e94gq^ƅvKg)S/H6n$9E)h$lZ^[xAːqӶ5 #']@SWTǓZ/@s.kQ V55,*NaжNcN,6~زNRWQ/uj< .!`%Qޕp%̹?ƫ2ح>!yBU0PC9| .AGF/smL&h6׫L W0=  p)C̓o%xXipIl8@N+N(& f%5A`;;r-s?H(AeAP8xUr Pa8`ؑPYW+ޮ79}Wn~<~ɓb X94vb! J*4%~.+-Fr_i%X#m'<ʜ  Ԯwz1hY{Uw4v?5K[-| JqW.\ESbxoo(J9[]%}̳vJsxTv8: ̀u8]oJ=\^My 0W3A̵r_ +6 $\c)@M D\|rPxpFiM{q{30f`5ggciR.QVqaWAs[ 7E+3T`zϘ 8z,9s/?H(ͳ»RX&L0>o^J .MTK]MMb4$,b}s,i'k|ވ3\},rbEf ?8þ7 s,P#2s!=0-fiT.20/jN&xp'1 -Y|Ӯ.ȷR#saR{^9=n0<ƴy^7x }&O2_PXC?y'J_Q0g?(qPf~/ݧ J ȱU-ɨr#D2Nt oeܰ@ B":G^)/{Ѵ8'pWhr;[n|0@lW]zEHQE ^\c#Bc9e+v^ YS幪 h͸xp\gDAR_ ybG~IO*j,'s5inḏϦYGs?0o 4<[FVdJ(ASDc\^ws5tHNsʘɫ?jB-C3aw,*.a:._rJ$m .";;@Y`sV7zGTyHP5RpJ =k ~Ϲrodtr37/'$hNXٛD.2F`|\jb%}f;ƿ9 Y@'ٕsZ*¿O> eG\>дz54޼{3ߟQY .ʿ䑞q(+l+ M%eJ-a6f8b&[C|/7JyskuU1B$ m%P^!LGe\kqU ECJӗSXNhVyU3 S򂿏̀VVxΡVҪP`g([s80L̢p`jY*%]uk}Y18/`ew5QۑY1,., {|eYi0nيa$J5)^"%%!__3믇c+b˦j(x0,` ^\6["XjEXa ,PhLqhDb_X{'؟jכU\ޣt{α}XoRfvULC-gp'?Iic j'īlkOKg1|P9}eAԿ{2~峬hQQg1P!kcx"Uj:LOX}dKL͢Z@4j#6c]QDiE9#4-_Ra2`2uT.H9YSA>Q8&Z6 u1^_٩Cn`~2KLW? "Ǩ \7U[K3;AQhi]Fi14e)Q(G4"Qi6͑.cЯlme`Y+gmoeUr("%[K nQcln; 80-|4Q*_Ft$bMX0oIg籋tb8t79e=kGBъIL_!O?{(u-s#7{$!|A" \r &P~ F@_.i]ou:b[AxNH%&#FĸŅy w?s|w1XRrV%c-ph7C/ Aw{s>>r/D|W T>lb \S ʸ%^=cgOO ;(;׵sRlQ:^%CNZeեߩJ@a .\JgDP_xE80%s7?!M^Av5HL/ =BJ,jBg41@Ly6(l݂>P(]75Dy)iew I̡YsFxcDpM>Jze1T/LBfk5 +w V 6L@M|078hMmb##dg3è3>ߙB^>P96xG.XqH|M9LGq׽[VUJ_6C~[PŁQ]o r)ɚ_ Ɓ[D5y} 7Wq,Ϩ9R:/̶1n RYB+XB|\ZK$ul.h`{I,Mu ^ǔU\Ixb|7F|EFYKn7q]4B'!lsw>x g}:+RVɹ<'m)+>PܹR4>U }b1>X*VJN_ߨTr3>7dj(rܒըӈ= g q:l[FN -S'LopY^Y[e:)$th\)|ͩ,?G43`~!InOq AiP몎C@z_@PR>lgbt k)BV?X0uXGQ7}(:pg.­PcX\0BcjdQ L̥TNpKfNCT^\߹*瘢P9nh_bAA a%cFO&YjcRŏvẋZTURyBgBjb4*y3>W _!>S3ۓAY^E ĘEh'_E]O ~~ v "шRPSvMX/D U9Ÿ<*r 3:㐈j6lʛC E#õAīiBm븖S7RY%\8Z!PgulguB/~_dK|wo]a& SPR Um ĮW@jjT4e@Dǃ?xeR|7o(d >Ly엂 Ͷex(MG$Xvj >CڋL禍4Lp KO moIK>Q6ˉq7gx>߰+FߏZ/`޼Šgӌ& T_31y] L[u|oϨ/y$EEB.\{c1[7Z0iKʋg&"vYe3AVޮ)B`m:[֒CѠr-cxܒf5VW h'+w3.{ Zx \L mq;Vj4aFө2z%a :Z "ʞI"ZyFy{gs$\7R-o% jSjz{*xWMx`]2y)'+#T St~gZ?w] E}e>e|rs-g ԵF_x*-EIE,*Ƚ6/-d* YMn9nG[`.iַ0%GA{37>c(*˚[p40⥅^T֯,Êe&-{9hrA0''Ÿ#̨Xl8whjsʶ5rs-DVR u 94_M!rڋݚ#ζoTLo*LKWg1`HLM˘eprR]׳q+VEf hڞ'B&Ϭm !AL#ܲ0^T wN!h4^eKRt|QG*ӹa\OǙw?qb'`*nuPWz}D%I&eZ2@4kMVGܥen:J (H*P ɑB-cy 9F QA/a;X!AE+~_7l (U#Wi[hzܰKVS\*X2sWx>-qrCA/ξJ^%+ït˦`! ,b6Em`sTM%ʽ1&/ gA @',O8 Qp<)ݵ(mV9^flYfX[a vEuM+4hC~ٺc0 P*8AEߖ!m1.xhwA4.pV0C t@OvÁ~"c/o/׺ dM[絗Ќ o]Vϙ)j5]-Nqv1M1-N`т`XLx+OO*4!X.`3Q5!c1B*Uw|ƈ!KF R@9tg8C; Z(UQOt9pZsD&bjY0לqoR=o^BĠȡw05'%j}wk|LK-#;yW>Rp0z^{+CU\['1n![?퓮`sKA){ˀLVFcf ~긵) M.i࿍U̶0P1j-{ (K>S%-aw+ Xci/eLtshg_ 7)$R"=͒u3u [CIvۧP!gBd)ER MQf/QٺUXf[(`ÆuC׿ (_W(+52< m>;ʴP6ѮnS#VzD9KJBR4E$Bk5e7†o£TlU._U p{^ ޲c)yrvTpS?翀뉔,9Ms#Ʌ׎Aj#@s]nXuP|WfuRMiH֦2U/6]r`}ƺ W\~~-.*YMm fgWrڰ}뙙z>Qh2.Ks(/̿i}nv \{#s&%8L7ǁHT큷< 耚=jlƻ`ĸ.c{|uBf GUB_k`Azڧ pxir#iC<|#) qmbLN)NƬ9G ]k_)p@4.F5](%FTÎZ)gN&y}2/4p׭\մR_g_).>s9u`-,WS vKt]ahS6ۋn˿Q3D៽ - /@z[ڟ>+Jx/S7oe{sŇ.LIP~~ˀsPNmEAzm;bϾg^c" t8ˮ4::w|?y%7nP[*c?pKĶKC̞厤N %q RN̔>/SXfy\W3#3,$CY]g0p嬭8.%8`䒣1`Z9Jxa ·=HYCZT!8˅ܵE%ZӑN`>eXe٪$!8WYcit9Ч u:řQ}ZAȾmSPfHi%+BAycM>}Y09V} 2d*4ZA\qoiٻ#a" |fD2j_ Pn_g3h!l=fsaXčj1L~qR|ʡAom,l8`(/Sr-]յcv>$w6#p_9W[s78^ (ًɧ8b9>Q(øAk1o3~sbq ^C|YvUQΆC _`1/ޣͦ nMB.-%2\jU_/xM~>Д 5ᙺsPZPXg?m@dfQ-ܽ](Z*ϩaE&xN=x uO0nU,*h^_L~bq\{k[ zY0>QdUeqx# YaM2B-KP u $LN-c#rqm1ġL`_S>gΡbw^8_J:5UuE ooGa,\8"Z:]~s -wJcFUճW-+ʯ\6ܭwmLL:'9i5fˬb-Ϙ-'P i!zʃK 0ޢ*lSPpPMQ?9u9w*tα)&h@؅a+ % ̬<ɿ4ysPyb`UB;^L=AFM/3\<5t?W/)K Qt91gCg2n♁Ad*"FgD.Q6:g` Usb5y)aY"j ƹ}]. NS۞",[e0QN"upϰ Vˈ`'Nʼnd 2>\yf͖kܹڋp`Z_72ۿHiZEe/J2\5*!MP?.Za׹t>EKdP+Y[yc_U(CzԔxK@)H=@l {d9R uQs tu6ƍ@ CdX cR),%{ʅ%yI??u)x1Du$2kS=R$оໂ$>k24 T `ԥm<;RIw^{ O ?ûIv(`*p~B/U2ZZjaP{bi3 63q,%o0ҼtF^jlM:w\.i8ciRl;3A8/|6P9 (qr?xi^.i{?b@^9fE[W 70RE~ds/\>t  "/O-s6g?\Ѿh6w׆#]dd}QveA, KhorRReXRt΅ .e5AB33*qE .\(@Jջb1SaW1:>O| Q\g|Yږɜ'}b".a pe@d-d8adž?т/oL|+ %{c0p_5%l073>+ÿV՘30,{h9SO&OWAESwއ`1_켷 ?qR%vJO^/ 03N|z?\H8я_}æ7l NRPGHv!KM7ocxsrfF<ҪfFz:Ijq7VbeTC0SKRA{&r0e e~^'~bb:̕eql0ŽLtb>їf"q| K`[l'ib 7O151c*:|FJ $-V. LTy _l8C;*TkQCLs$<}s,7n >ToB]KTRVreW[Pfܦh;lO\lɚ_ Q3ˣI95CZTf^~ FyǯN"%At ^DZqd%.xVw͑!L<ʆɩL@&bcWuv[=*(}Fvn&^GR԰:"L1r6jRsK;Q^_Qѽ8UhxZ}?3QE`&4s"ܢ w4&.wX-V^ "7_xY9eYgَ'Ne[u5JYy9usy|K:07X%es LoRϺ첎ƼEF~֖~e5(R<|Z75KEN  n>hnZ 211L,L|V4,n]m!J gI$[)c\ GoXP1O!(ǨQ5:'N ubr9AurP-ƒZj -|Kt3q>YS(7QAsJYRpVUr)H\߸8 jwQ$`3+%^F,P&XkAioq @^aXwX+GqH6|vN n CJN|ƕqܭ]kWII@K?+]>`nxGDnƮfpLh9A^D7.`6 Uԫ:nf-!׿A!(`Anׯ94 4RPs;9_(GYQ}}Kss8 ]{jS`a2J<斒yb%xV-q'Mp[%EKTN0j}d?V+^ozPpi0r"HBѷ }w)DhAFIW3^ܡ\B3A[ݽEaZzܯ,Ojfe ZFTz8sHf0k{!# `B +53=50AE,Sr,34~e0<ب#u~&ݔL,pT=Z2>|C+ _qy#n`F=0reS9 ˛ -8wc[2LG7Bw3bNuq[D2lBa ز~(=Av+zMzcYww)ch+ɦثڣ_x%C\`())Kڪ@%,Y vCCܥL'fK$5B*Υ+\uGSyE*iƌ`e6w3g X_"$oqM+EBpdKJ̄JN} 0F7-F؀1Y0UͲ#EiM 7us5nCh i*L¯nuf|zqNO U;1.i_jlyVҤ`_xf3d%p{!ơ̦ PvBJ(}ȱ}*fX<^UBʢp9f.`P&`1j jS1 qNr:0Og9/C,зhZ6V i#b ^^[ MP{26 y2, =ˠ%m|J aj4ιIR7 cR|x:A繎 h,CaP,2r.mvԭ0&g9K`صz w,hQ7;73-xiÈEb%6\he&k<~E ւ/Yl;C@rszt&x~;R$6\&?$ʖoΖ)")S ؃x%={nTt%)>]هؿq`#w*%AB2Wi<=P p,O// X$+@Xk=n:MTexC9wnL 5@]\RQ$iKPw9qw7 x1 GȈ("3| Tq[#jͩq ѯ ?T>u5h$ʳ<4f#/ﷄM)){rVS^ B'8@5Co<{nYu)ϿGx5J!c^xS,C-$}˛,>U?yp0RKHM]`ŝМSyhe\lmHgoT8Ra cNp.c \ e/zspC1T|024"+S뒨,d-"NpWgT ԉy MY, ^=P@)2>ڻ6#:Y6?bOtq\H(Nbȍk~COYcϔUTJ6g29WEg h9(77̘^hX2a)sTULER* ‰W~cpK Tb~I#vG[z$jz\A_YyQٌ>,"UXЇʕј˴ECmcDp}K=mMD <*yғNa/{M; Wjwx4 A͗Fg_vE%6PO ƇƇW'xJhBIqUs 3iP7ʗ9ʜW$i&BTl :V~T UȱUz_(&Hdfp:Giߟ;:ay|Ur뉭1q0(y#|d7ei]r%KoiB+<``;t4fjaC0o_^LڅAIiD=aDoFj5 -~v5D)C2"KtO%M%'5g]mG w)MI[,}AL ()f8+k0UhpB¬WX \$-Cfӟ ߪsB=q =BA۝xS3_pl)Z#o!Џ]@*M軱%gwfB> BPusK5! ݒL` C/=l=`t1f[Ύ uXpHNZs'{`S>^} 0 HƲa2O~À`d9`rQב{%{š'LI`.:{>?DɟPg\NJQo$SLgxiH="0-W :% |^=4EgՓ1zxv ^?Ln5]_ri>kgd!9(-] 'o>*K ~^GMߩ,Ћ,dD>?./,bҞ*rZv `}-_F}#  6h,l=,!1{?|a0y+Xf$ПXZ 9́IN$`1 3 r8X{pdc#^]' s_VK}?wl$3h^Sa9[0S J }dP&t)X?"\gYP*g<BV0}8w̯{nC-:0=n/eLpgƒ0vb^}ɰi'0ݼ7svc9rÏu͗y&=aonNAW _dQ?Bѣ@Þ'O/|k=[o}#ak\}I9l,<xٜ,KZ!tauP|7}tat9aq٘HBVNdѿDIT B"[:yĞ߅C(7Ÿiȗ=1/cAۿV Dz.`3mK }5?c!,s씂Zy};`_BѴ7Nԋe4vzZcapyb1y g!pHA-_usr uN9e-NCv>'`a$='S^)#{ߐпMݷݸq6}a1d)m%79ey/ !ʿN%iCFÉ}N ؎r3- % ! HN e}9pwL\0I1rtbzk#gMcjOlfD\Les<p >Kݞ ۧ?)nn-?ŨɤoIpmeOlτoQ;%_?'&BNo=Y~N;/\?SX|=0d<]h{`?Z!f`pCz,y'T06m Vn3z'%։Tr0C^[%A}[,? cym nRs6p^NoǾ[^78}ILͯl(C;`g:G[C~Al=msƻ}x8z8s98\?ܟO~HDgS7m=.9yl$m>`d6>`}ǟ eaqmGbdHYn~$=Y1vז_m_oqf/_D;r$K7fC4Id[#ۙ9vv.ﶼٞzs~?.dsamhsg?gۯ\7l4j/] cY'}JӳÓqsXf#y(!1%mPgK~=Obm.\stfZ~J/<8Ya umۿ! ./2ʻЎ2.F- aG%qϬ>3߆Wwnr7lwn]}qÈ> X2?|YͲ CP𷕝G!]dDz?GE'>,?l߸osn\v5F+OLJ|!_Saѻ䜝fZksȶrN [uq?ogc~9rPw7<ז)ոt/_ϟȋbČ0GB/c.냐!ߍ]o6?v4gn!۷Mg =HqLvf|O7>HZl6乁%;Ձ-dc?>n\('a}Jy8>fOC2{toXVks/E-0H34Y<|P5yl:ݺj\9)k&'IaxY&[ A? ܝ B NXg'2eBϭ# dIbga/MQ3?ݟݏvh{ap_lmvٟ'%[FMc~}}ܹϝʙ}x7m$q1Ãb_},oɏϨe?G?G7Iz9<pfXvxG,` ܀@nG?xHëZP ?y"3؎ ܺB=-x|UKu#B쮬xG]Al'p4/Nhՙ^G"PwDc#Ĩr8 a>3/Ls {gg l#Nkwwu{ f0{aϞ|fn+9=Vi7|18HZ&|]cvn\ۑג} KP6?gȏ/жO`(I_Gϥvzl=kvZcv|'[\ x ÛjD< Q.?~^{@igǤ~9?os۟0|`ʪܾABy~׈˗>y|wTЖ>>ˏ-@wlđ=O $˗.\2-ǒϬr΃et|/$7V/3$_ I81 ߇^oi>ݝ-cKK2`\~vNپg|g#<ȉ\`r[c;;:uo`ŅxC`y eϨ˗"->I&goaصWaoIys>y9hܹ sn>(9)tYr _vI2ݟg|^%CTAO  @$8ϟiH nZ_mYY ۥ|r77 ^N16+#hdN=\a ݍ0 VN/{a`|%oɍsˑ}|Y]m̈{f ; GKrGoc8gLa#89լe׶Zo~O'>&ͼ{j؞Bp;ycl9_?~!I?b@.lo g=3>[[ F -^]ۋ>Ͽ. !l,',,'/c#g>>zP'bwb#ƶa/209oY49+8ʆ,\c<#> /P,lll` ,o3h/6MPCݶݷ=2z`ٯNdlBA񍗏RkaLdxI?!Hyńpܕ:k`KMw0dp5:Mzl |_0!؛qˍP|nO]]Y~Rkr<'?ďv2[7+DYokc}Y(3גL|gπ ,6 z|2;Gόj8LI?@칍 =3 ?lFwpCo}Hbɱaaas m_vQX.~|mko?~z?τ?y9r3o{|gw\^[b2 ˃l-- >wP81ƒ./l|ojO?'.Їl$O!xٿ\<>5O~?nǟd la7g?|/9`#R寤 ~ ?PdoOl2b_Dmώ$KCauy&|.6m,a<^ZZ>X=+t@$cFt:0Ho cvlܸ۫oS `1ߍ}.->1fyj?b|q(\5g-[_,1$cMss_4ݐx@J}_Qn{w~6?~8v in̟'%/ߩIMSf[ܽg{&;>>3oY"1ˆ弃 r_߃Mɶ׏m!qNhNv{ [ :1"Kqg ?Vƽee^-z`6_!߇{ݸvunޗCzپKNgI-- c_|v3>^YnOmmr]6/ w4dl~ڳjɹ=a{s6؈wd_ݸvv[0>:}7Cm@k;=vSAv&X7p&`W`@b-n,y&3ErSm9in9k!߄~r:,v$#deduylv}Χ  l>ϑ7EE?%I6gL tm0ܟfp wK~` saѓ  &!6CDBw&L>o-ϨEdB>J-'2ȃ8,yٞ3$\]&{ߊM䵛96ׄ0/]),1;<v-߄,.}~ (!1AQaq 0?Mp{|i(ye*NhANF~YJ@B ts(\ P)~lM0[Xd ~>V)Bsڼʈl?R#Nmo'$m05oU> 0b/ 80me*0(bÝpwqO>`&4OXLY~A(M2X(ZMF( 3oDCR뼴B:VnP\d}W/_? ¦7XgAv/ghkߴYxby.\?ڍU%C\P@P_QoԾ PL6G8,軻]JPbT]Be"r)jd.`&xepl8 B]Kၰ` F)-gz6x9GXaZ -ۘ]U̸qj!+hin8!د<^?,PӉuy 7)U/)wa)8JF1A* = '3Vʭv9x]lE.c"\o#ױ?oܠBqaFj$jn[h^.= 6t0}x m{W^dYjd (L&N{)eZ1x 7h Xpx;Ą`Æ,w/gC7J2g~pJ5&wǒVwĔCG*tUEUx!ٿsP Jބ#7ĵ ]9by!@Cط/6q(o*'2 ̙}ѾiFVe e()Jڻej0om;ˌ nVTٳ5lj}UuYsqbso# fR5oV$Vpsy/P~j2nvp D]bR[dBC&W;p^L{6/ |I2YFBɽǡS|;|ŬFlJ"~~_n v\*V`X_L70]m/eM@Vmfr*R^!p_+SKG$U {2yT  *;c`[ {"pgPw%}3.7.*j(h`ǘKc&k5+%?-@v!̪йr+LK囎ȝ#RVOr jq ba).S_OTQ+iGU H(PSPsK=t]-3hJS!U1E`z0.(~(;|_l+^ݦjJZ0%.3%;A&e1 ,EZS|O~Ѳ)fi`[v^PTs@ Ogp.b;/9uJ\UAU>Uea ]&G' \])ܽؤ-=΁[E_Xvc_qٮ8|^EƟhw-*i&*et-,Χh~nbGD4q;P"ٜ*؀M=&~L.,0V᫕WES+Q64l!&JhЌX) VlfUn< nE[|ŕYvX}e^EŃGBB+.Ch^bj!Ĭ)z7,R#7TZ\w@߲;@F*$R\ ,"JJ=:iiXnf4`G* OLK\bq2%=sN] ccoኮ>q /29fi,6i0:;}M9{\ U鉪`7 9˴|:.1~60$\^󫗅`r0Nz*[UjQ󃶘._ij:뾔S8L#K0ezdCJ FAXeŰ|4rh!7wX_ +ߴ Sc4$qlpj:І8؆xKjSO5 K'e*6bCtA )Q[F33= hg(G3[i5/Aˎa.cYr6s 7*G1ܴīT s6]HzO6JlX%\Pn+FTc c'ÝWh :W 4\tWbG!kn(SX]OB4!L[F̽ KrSLT,PXHsxٙQ].`Z,R 'IS,«bU`˅HjCgff,}v LBz%sLZpG&ł9-D6aSLwRе"ޒ-#|R[32ެf)LW>kOѱs >7@e*U\Y#%.f{eFʏGv.و珃igq1I}l}f,q/_03cqStKPmQM˅(1ժ:aС҉0P]F( z03P{@S ń\J%WUJ鞌R3vX@HeZ ĭј6\q :etK8nQWoiln73]oD--*B¢4;'bmFXLf(ALFQ-ovAgP-}efKHƉ],1ҸDS,ØyЋfTݔn\/r)bn"~1h9.x &QLesƯJ*^i/7191Y!W11վԛre`dQ(R/JbXK.\˗-ZULSu ed%G$%U5 gnÂlɊjfF#8So76c_ WJf.{cqffg}^c AHu/b.P\(1 X5L$%mBR0z)3yFXz1 4nc 8U.a,KKEqc9 u+HsC^(~E"K% s :u(X̹} 3x|K,Z}] ⧼3 d 6D.!Xʖ7hKn( Tʩt5*?ED&e^zf oiԢ*K!N`fY[%s #D\ܫ(MfX]73qUwgw_JaU-43~> d [)*( VS3k1J=8@_q#fXW7+(ܨ,bl\32jw1F\e%EtRHۮlj C=(ƆD]Ɯ& 6wCǻƽaX#e>X)DMB70Ki!j mkQʈev'0Iu.-tZKYb9,X`Uq MS3#o9*![ !D7$k9Ey.'A*`QXnVӘVm1e6c?9eH e LJ%[EB00yEtA4eˈX`^mx "~ӴK\q2DUE@Z)|g16't>11^{}o=ReMˈ,i[x7}+ϝXlwbtz(*e^xN!*]4 )P̹hfD }f9ii_ t|&!1AQaq?66jake5qRqpʾȉB,4Ϥ)wYM `C`k-;dE^=C44:z Tqg]Q8%! s=\=(YKAp?=a}1%?ȁFgP>2uX4hOPBh}?8D'Pׂo a#"rv"[I։IQh-YwctiY.T ȎNdաM,^켷&CE\nԚ}rU yHA7pzQAsƊbPC kS~qs^ ZL?k3 {9|\hm|7y _p+J1SñНy[fN ,<W}=m߼n{w`^wVJ,7.e8;TAn/^6[笼 ȗ8^8>q wG` < f]7B4592́D[@y))Q^0>A:xwi 'k*8F>y€z QoYqڲ 55Jzǣ$%(yFv|X<Bħ(Ӂ^ Lh`Qj|?XS"T* SӐ;W;=Oٳ n~̺mi}EODR{^G-/BØM` '|8T]c(+V9HF"^SRȨ|yYNx0+M `\٫5H#_\E }A͖ @-oH j t!-Pj$xDC6Գ.˺{=W ?:CmEXuy:=X&`:B?3tx^ifO T2 )|,K J x09x 9j;Ҥ>V0{&KM|`UB /Vuf \c<ۡ`%ӯǐ*Η>0DIc5r\H2rޟ++ e㉌$ v~̢;~1:KIN7}| tCtfn!Kgɂ LUEMi`_bk8ˀlf)MGӰv~z*BQ0d+A O'JFpr&wC=J q 5Ü!OK)B(4:H{sG=>x2 h _69^EGu c=[CsY2mژPFx]ap7 ) c0>Kh5 :7u%kڙ%KP< mqDZoFAyXx_;`w|{fv'Ox|D[KGRxPwg<$tEXb˚8笹jTy/d|M?\cpzPoY\ljr!4x&h;MkdB]p @TEb4>X ڧ %zoh^oH`lScq'gG8'!ȺNowF:#r]1rH}sAe߳q Cu#vGLK.&_K-Hѥ0m%:pƪߌ..5Pk>F{6@{k:@_.IiWF^ |XG~qZ(+lDlV2%B{XM Fz67! Zf:]<5ƌηtK{5 \Q6zI 6*#"{;Sj1ʄрxtOe6b~#CwL 0v)RB\ GX ލ9qoHtp5PGͶ7X ؠ(ӄS.l/._kHf78=}1aW3dN^L]__ `r9 ܿ=|Q`B+kz+T7Xo|`Pb;OwUd|>3qЃA4X}ذ0@#ߞ1޵ Qx7PX 1ۗC9[%X;aÅDs󯼦yP@\QaNs5y$˅E|?y%YʇO J,xҐzBoN<Ӈ5Դ %tr| 8Z\L0)>b ឱQO$Ȇ\?8! st i/ŕ9wIK:So rpFWMSO&`?3:xقO %2J?8TԜB l HdPࠉaHI&WQ4 s>ho9٬8  ԨbG_fK( _|)/#74hNd_h xUzc]ѐ- 7ϜwtthyU*AĝqBT Ms Xk9_p5޳g^'ſiTXwb]z:oZufՉۆE7b9Iy0>dt6x) (6@v5CG'QY-9E6&T /Rbb!]v0@}k(^}'n4J3§791ާXꢣ0n3G?L*MNH$G^sNf@="(BڊF7>.E(}+^c')o)CR֪t;xQLD>1-x ^(%زA.W~)Br"<:f*.?>A%̀T&@* ӚjjN??4q ]KEƞnqP Nx@>_yL Ω_͛Hm[[ش}63n Mk8@p|af<> ZF9}|3OY8Z~OX8{xKU:HyqAVVI/uVV\/S[[vC~yЛ<8ɖEDu=`*ߕA< =O6ˆ5¯>1vhɲ4<AS}ُLІߍ{ŸˍN[O)ؿ*o 4Rvr c}w,;̅~)R1@ٽ'ֳY y{8q{ﳏa߬tkGͼ7>gkS=y7x?&WJ;˶]J{ŏE'/f@CYd)|dKeFLQc*mKt쎔~ D Kr#m=|rTE$Mc=i+?;3P`^cOWx RiA0 R%; áW V#kA6C* &ѹpm'NncڄsDhFI*-cF{2Jgp1%^M:F up$~݅<, `L3zt*;}gs5́'R@ (6ub$_9AIL5:| ʅS2=X+~3D!Hv{Ӷ, F|xDG~|d-/o[}:Ш&>rgÂ\d=q*e=o ݛً0l -)Kȧx1B`ڴ/9ߣ;@|tt{s$\mI9(W15a`Iٝo4OB妹/^1E a<# <ӔEx1}a,$8lXE UώHʵxx`M˧N@K+^7B | 왷mױF2e䮣:?mX#NXTXi"')PBٔG@jaF]*Z7wab]ԌF; o 5It0 iχM-b+XiQ,?"0 cb}c8%"~,(*=8Q<4(oЫm^?"O=ǀ/0WO%I&1}hݿ2Kύ=Y#{_oNGR7'XI*d&1gU`\M(0JZzp[o 0}LZ ɂw1jASP!T*jy,zPCק?X5E8"{xw\v8;+(]h<+Z}߬5ssZ+WYl: ,ZxȹxM>2)@] K#Ȭof6P+j(4Z)8N7w3i|4tC髿_t0pA Z(_(6.9{a [f a n $=#]Ad+ NǍ,ąQ)n󄤭^S-p $HV˗&y9f')ۼc[b)+q ]]ّf)̷ 3,&w?8U^pk^rۡ=89 l5A +1Q9$er?-| 5?y5VՄtw +JNu{Y7OgqIEw}v2듉} uK^n^r}@>A y#L *-f B=.ot6"R[]7¶kV15s4Q9ssu윙7rr8ɷ>1hZbD 9W2CoYXc1G1zyo&rY\UƍN*| EX7TonB=FkO?;0{F(P`o :L-Cn\'5M8XoO4z&6hNH?MQ}|᧩oQǏSˬ㫉] 4m'M(&}o5`BގaMiF͑ /qiBulXEVןG(-ImoOZӞ]GGJ(S8\@pOOQgU['Bzz߬5a'+ȈqVELS[rJs@K0`U9*2NYAhGэ%rXy %6cG#UuZ^CG,OKh6ӛ& ~Xg&Wcʪ6OÊhsCT_91xk5BA Mlˮ 7tƒ.UN2PLu-Ypp3vNY< $y`pZb@|P$jݧ$eAQx90Q16ͯƅƖl9 lÓӈ0ַ0 4C³ aL R q1xbS`n-$JyʦcF $]Wӏx!ZٿHt>6' c`Zu@I1aĬqL+p ?84W|ǀeP埬 5(zQ=р8"1xB5M cn4a2k@dx) օMH(J#P\iIS޳zpT|uźV9x?ܠݛ:hۊHromGc$g-5ݪhi5\Z6=f]B|EG@}x$bԐkqe*6'&Ra$˕_VjFѵwL"[457勒myM7^p:F8 j/8i%tQm[#&fh~X"Rn4ef})8w8GX (p(Fs񖇗Yh#w;6{!s̽[8Z^V8`IK<,pMk)A'qhǖ*@LRh뚔4Hƹ\zs4)8aQAtMTTGK2YvY>ףUs~ Uу^5<ܸ*+NSÈZ"pW4jS_~ vj&jyVI@6"I0v\l5,%B@6viHJx()Eb>8uHR&eTb_%Xk~&x2y~1XOxGE@={Y|`-nrÞy9<|1dQ'06>D#?l[%:2.["Y<80GI߶%4ËP h- }^Lj㙗f:Azs!U(~x*7^>O8?@:XoH{,˗T7lJfsoA%Ͱ3n?#N QANE G'Ϝ(z6~%14ߎ˄qsoxv}PYFf\i"s5ex`Pp[:9y!ǟ*[?K8$_Ss}0CT4!d1덟^APDH/mٖ)>W %]<.00Bє6kx5<Ό׉Ybt'F !D:_J9E3FC:\ d l1Rvn,k뜀]X*{:skqk9\p0!r?S{2Xvf~!]!4%-./g_;féQX!#?|?˭| +Hp_I\a_G(9=U2{Qxr O&!NjL>K98P|p¢"btSے (נ? ,bǃy 狴nN{& m̿alxpJh n}hBRگ>ȜjѦdrP;jpv5w﷣5`/C+"u: Mᯟ$fW7"7IagWc4@aCDv [7qh5RKpz6槓fx7{2F"r?9d_v邻)F;wWRBb i|Ē)4"y r[BB'{=pbGEw '.iŒëkMBb{X!4 =pfˇP֛˴ק9f6V`=|"c@Ɲt ]QF;ǿ3t]m- o: ;運 ;Y0-*%Xb G"#%^qA'FCVPdeJtu*zM xZ;n)Jfqi@yܘ߼ދQSS|a`jPc>3I_4Wp{?Ki <;|;*6Ak驔Lh/f_ k0z6аCn-?d#5GɊ-Sw<ʕ 0OԈC-8}9F)A!4T)speьò+{Ȥixi/pt׿4TCZ˛^nγib Xk<}A7 \'ypѦx.Cɿ-@UZlnʓTK;a# rCAYUY0WpIJOTmvs5 !{*+VR lxF y߼J&DXK\WL]i (TwoI8N[׎ X,20iÚT#N8ty|]-(n#>mXg~mݡ2o .v>%<\ 㶋G/.!rp_xWm_ `F 3`47@pxȵ1[8%$І7 hp< Gg󄽸d`{匕Pѝ=D6[{Bv׬(414i6qJIi^lpb9_!“=HufXtG|!NIW$wggl\47,]K'<,<Ϭ/G*__r Wg>KwBW QHKݦ3z(l]z./X)F0HJ #56Eu>WV^. "^0wp&&NѷjN0&٥u~\tH*pOYJM5'׷+&rnX yg^}aP:zMyqW!ﳑr{jy }޲Zl{V+0!6U+WYz/J3`w{ocP]j6 #3Q'"\Xekn(F pVrɡ,.@gRrcb: OD+ 0Uҗdӥ Tab:ŖY]FɊsݟW/Ft R#[qGs~ce#*W߿ ٔhSCrDh I[gK^EMXV"Td<@SiͽIdk&Y7QXr4OD:@4bBg@V _-Q *v C 77<"HI:JaM{!4ѢCjzMtv[1(hgюP!iN25I! }`{kvTi- GXy4\ %}\6$awW:w$+`g<*gosqt?xX`45hnr%a@cQ^d ]oaEM(bAE`qN!ʵ-NԂh~fw1wLO/?>]~B+l( tosDFҋ2 (W&GK!>NSvho!BӈֲTCQ V+Dk@=5|OdF k w7 +Ni]3 UV^է=kK~=3mUk#@;O -=$!@x Th {nÌy_@n WJ0c=D<-!rl`#2 ҁs b|N;,pWn5B6~rc(Sw5 W(_їWX~h?X8w0AJ&/!"M?/!*o6I“NijBjpǛn(svW5ud,4G;Co60h+] <:}"/;°Rhosg*V(i;bAu6~}+Ϟ~.g3[{ ꍸP^޸t09] m߳MtUeߚtyª"w7*ľ>sZi`. %S|b`J͘6|AWK~[5D ׼ظ+L8 >ȫa_h2qԽlV@ğ{@ P~O\~Lnvbӣ S(X6 B~q=a˧vO498߼F(X6(J zZiD T*..߃H3D7 NM6.ۗBI'ТXhzmq50-|UOU֘?C 0`]pJvE%G[B45羨 42QǃمҬyѿ)24|PEx)|x ˖cœ+q`-4[D;p5#j(Kص;C[5%frn()D^X뗌*a$]_&L.߂,z.)hv Q>E$>4||h@qahqG㞌7k8(y&mhaR|`3q'7'O5e)d tk ?zĔ4w !xx lOc 0NqUb˔x߬>;<7ur:ChGƯoUi99M6'".N ή5Dn"}LW@8xA):SS3`PoiI}9X%p_`[df D@q@po֩u^zHT &keڭM9x`ppIƼpfQdAWG>D׫p(3%~)=`ګjt(}D 6K5^2 UmŠ,<_yWBƹ"aahj`Sdۭ]qȖܟ0Gmwjs\uDXv@tlT4pcYuش456.pGwmk/l%':|`||95)[AvTD]0 KO;ְ`Ʊ4|;r5 Pm+%BA:48ѪET,]L5ܖ踆24Jו :].Hbfx\2ޚ׫nj8r0DM.r$g/XD 1|;U?$+@\Vb d?RUtshGwrb%hg5;m/ ^s8Dq ^2J+Kqb׊)jɽA[EqW0D&p zxĀ;^Xߗ:ޖ!a ,Bl;=4$ᾱUJ<堶QT5wTP:$뻢V@.b=]ưcįd^A/_:ASϗY|_ 8Ei0 $"l{Ϝ;'lQK҇no{D:!U|Q@Ge[s>)&u PHXp9o@jZ&>nOwc>4lAUZP,s!(DCGU6ൢ!p{yewP=$z͈ǁLR$N5:O*3KS"8\qzdK2k+Jn>ϻ\=x$ ИLT|s,x}rOʘw9Wh1ֱCkjȷ(j$DA2hbMÅ=- \:Xh _͚iPL8ZA.a7)>[CPКͦK]F\[[Eۻ1Rͼ$_BDtfl2bDJv^~6%<mݾ/:ĐY{i(EzTIƼbm;Md x)^޵0X2;cTVtT0#c_oj:k_X6gf}ףk˗AÉ50DZ u3*͚h>{k|j͹pjhN|b8!)62|L;=7"`Z[1?vzy@*Ɩy}xs87^삳B96DmE4/j!#u7.=TNT񍆈AT-Q4S^9Uv倁AShQ1JDn9w䎜_b5ZUkl@E#+nF$XԥW Q(,UՏXcOܞr\]gs#V[5Y XDc&.(~x5ίv$ѽjzQ?Y\ cfL;yX<ӜNieqgYG|_ Kۍ0nñH #ʬB;[ 0S7:@aʊ& Z HgiߏЀ``ݟ\o kC>&x'jQmzklk J;9.3Sw^Z"'M*f7M$rT[68Č4'%f~#Vk+ϐ ݲ·!-۬BgȄ|tz@Y:ˤ׎8I(+C$mInBִ:u-x-=qY8)}2ljLOAu@`QiÜ 8_2kAq[eXx3`8!t [@qAXl,VfL}$-FϮ1eo=xbx:=a#2 4A0:guG5fſ$4h/$y'B>dL>•kץ. )GrUFjs /{oǍ :~r4 b7SuO/逹6L紅 m.qCti9sVœk=2V#{tGMĥu&|;"qPӑg(y3m]Xup&e\eC# q@+t8d0:Hv/>4 t>|?ߘ\sZ Y7ȩGEHkv6J@QzA=1堘Ԡ6S'h]h*y7¸3lq4?Xc\ؑ2cQWծD=^tOu8uDej+'X[DqZ*5 \MT3i?:rnjz4L\)BC2DK:;1m0Q}@L>MqafPAqlO1E7-wh14tr]3A"n"$lڰMyuQ/QAVCe -Vy$"u.892AC<P+I4{ 7*izv6aT'.S rZ"kƼf8m;OF4:ō:N zb 0;,F; /{Yר?iq =˱PIMM_+h! }A}(5<%%-9 rk3Ҏ"QC bO^0F4#M5 ( `I*9o҆:.c錪P]fμqRs^1Y$}e"L՝7ߌaO'kL#6.jxޘ@ *hlh[;^@P @- HhZ# #Mݯ?lp7ʛbd"<:?ÈFTݧ?=9mCvk6/q ">2)>jWj 9z&Ë^>@*bĠc.7/esw A}#e׼SX?yȎWSrqkP o$4y-#0o 0󃬸?Yg yx7q-Cmߌ*i\Yj$/Fq1_x0Cs.OX\^غhp.{aQhLevܲ@h2㏓K +q)P8 n9nE$޿W x&6xVmX\XOr >_%ShӅQ9~qIbd+7 ?yfs3 | )wǗLO|&_XD2!7TM hk|n l$`gSv[tY&hY=wҵ n0@>APioBؗv ?8 b1gOӚSi|.-f}>#L"1k<Ⓙd2_>ӆCyC!7yg9~2&+ǑHߜP!qU1'rP6jnSH4q`q@Џad&WN*Bo@}Yi%MPk}OWN~N`m3y?9$̀px=M͘su9cz& +ǜ[GA>4Oq p]F-uyXG[ 13j{sq_XfN2z*ܸ*M_€[}o0 ``9ًˌz, !|oؓ}bp_?`\O[]3Ub:е]|ij5ͺIWOiet4p1loAaMx y XQtj ?C_9'@E2^l\,z :*ܡ _aJF 8KMJLj\OY|X-`yq[o.&䝭ŗU}8sAYF)4Lƞ0݇XЀ!onTPqN߹2 xH !rU8J'sz4Gq"W&X` ?_۝|bzcZDkZK@Ur!6` A/X;YE^=qJ!rְ)E/ B3n \ b"mpkvY`dryn7s Q >}b18Z^7f1y 4@ڒ8'Ae >NLdsZ|1BRY_/0abOA5-e)[ٷ(u{>LX R:L"q+Ȉ8niw 3Yc mĸoh`W|/qzS v9U:xsZvqDXb<9F\tkUGIc.RX=bbirJߌ1 #[&w3~|bWX؞q凂q|w#|O&UkXS#tzKY>r@(u#|ak}wR}`A"񕺄PݪTa:(QʳIx͎FIk"C4#t3Cyx9kU%r#~q@HX°ɨx8[~@W z5*` ZT]N2` th0:popaRC3񂒶!+7#c|cN|q)7yȄbC <`Gtn cʧႂ]`S^WhmWU^rH-=Ӎ}P0R AɓoXf٬J +[\1??.Pb#P,27|C40e'FsRD߬D@RyJ|4H$9nk 5)JF6Ãy' i [r \ ?]E;_z?WN$!(0]ɂZ_ bz.GNn+rJZ1pAnk+"Ř_lA61 2 Dx~>ÄFh5 F=2Pu*2HhZL paHpp`{@o㸠l2j^ˊ,;# U-hcRAHw B_yeMnJlˆX"l%m&c90 pey-'an('iVvd:,gt 9s4\t (r=9*|`=yV)!Z=b2jF;VTL|\jODEcIr Gx0"v'ߌy\1Ceҽ9@096ee֕*Tq3hoY 0uvL5q Сx0 Ƭaχy*th~yͭCa!=Dk "c񜻬IK8pR 3Zz:q[ `3 x`=U(1D}!h& mG?8rq 2/ <n *HߌG9ᡊ;_A"a<?\p(Aef(61 J y)#i|d'S߼@hCXAY񎺵ɳ'Fh .X;NL\xƂ фgcsdoSA)#J` 53-& ). Hbm9bBU@ GjUcY<qyh *% FY}1 ,o8o)!`H1Y4{0U8@}p ep 8z~2 >2-74`0y^9l+x8@]ߌ7m~Ŭ2L69e)_8k۰ag%j`6}`nXlB7IJ;$+6!A46yΨ[bqG=Pڼdw D=|DCw^r#NY߳s- W.5۔02 jsdU)- BD k]8I06Q'?>rS+((%KcKߌJte>\xrTw"tvpe‰eq)xdM,:~x3Z?A͉Ҿfҟ] snBe($׼FQ\0$mI;<ℑxtIuʺqd8"]>qdE%iĎ y ;`;-ȭ|__ 8:Z8#/q09))jvqtYJόp!g9_.G>@e8QIr&J?w o3tt`q6c@ 4 7R+ iB/8qJ 19^\09h>\kܸ(B"vz=yƣz_ D:<`oϜ3(A]?"F1J)r.a)󉝋\W6ċ5vNZ0˒at^O(Y}fx Rp'iHG:l.$ S1`b7|M)+~[= 'KL䆱kSOF&V8_E aUDx$4"MU{m y  W9~\Ymw(+a$!9Jlw0f5&, ċ·wpd1b~۔5h0&fzTq[M5^w{pl|atX`2l6xrws ooxml/examples/docx-example8.tcl000775 000765 000024 00000001215 15217572310 017317 0ustar00alexstaff000000 000000 #!/bin/sh #\ exec tclsh "$0" "$@" cd [file dirname [info script]] source ../ooxml.tcl source ../ooxml-docx.tcl source strings.tcl namespace import ::ooxml::docx::docx set docx [docx new -creator foo -created 2025-02-10] featuresCovered "Footnotes." $docx pagesetup -fn_numFmt lowerLetter $docx paragraph $loreipsum $docx footnote -verticalAlign subscript { $docx paragraph " My first footnote." } $docx append " $loreipsum" $docx paragraph $loreipsum $docx footnote -verticalAlign subscript { $docx paragraph " My " $docx append "second" -underline double $docx append " footnote." } $docx write docx-example8.docx $docx destroy ooxml/examples/original_excel.xlsx000644 000765 000024 00000025353 14764622263 020056 0ustar00alexstaff000000 000000 PK!,lok[Content_Types].xml (N0 HC+jq@a&1 $-M8fcBBQv&]c-Ζl\XV:deU8 %j{-?pF`㟂e<0H{$OL!ƽIϹ[ 4yM-2pNoy msOBӐv5ɑC{(Pbo P!q=8ck٣>bMr5 ?R? kj4=;ё 2D&V['e͚BX͖5?Cǩ8Y_Fc 6v9.rj( z*ϳ1oȳ?PK!9~xl/workbook.xmlSn0 ?7%EnX.C0YX$z<?Zbt"E=qu}r ɔ3+⊳EȯVǂ)5K!8 J~MG4T8ͅFX2(gN/7A,>L3:`}<+Bʁr L57[,gV2 _RlPmn[c*R.(X ,m{LYM&bZ %76A*}"U_3F}ɗB+*TUfmIA<&l+չ =WAdo"jӣvY̧1 i\x4U >ǽ`u*r~-ye>K81I֏Ȧw^ ¦xN+~?.f4z݆@&lG PK!>6xxl/sharedStrings.xml|UR0wﰣ&RBn03LGX KcǾEߤOR9.tFr,}ohTHx@cVc P:j9f_.O;Cʸ lM'oߌ%pghuE6ͱණWܗ[m N,#23#R!~FAKEc7`P*Y dddDʅ'G!%,xIQKGW+`|JQ"l}nn8Q(ww>B4`Qt^\l`PC!4{}aMMGyF!MM0pzi؟Ey.aG 9Y=6eC߇+OhЃ (`$4~9MVN:@v+fʙKܢyN8( (K>ִέ9"Hv`%j`E WZTδd7^%ɓ?cvt-'~"/򆾓B{!4}dѳUan 2-RmtQQXrgnJV>m̓k$5R, J]LV,03{oߗA} qj $ƎFGg]cMPK!pxl/theme/theme1.xmlYo6@N4 c[6H=-D6u.vaVvl述GRŘW[92{QW !)ZAr-@$ yD.H*E񌴂1߻TBR>k$Jk 2e,/dnEB$Mbb()3Ґ\$Y>eE^ռCb^]#Xv@(}rİT_~uDL͡_AWD{fOM͒05vng8 AS+KgRoOxV@qw֬5\|Ҍ̫vZb}lWjˍEo@ߜ7β7 _.7\%f{3h^^BWR+SDC]z!ԼXK.z@͐dCNb^#.rfId(hZ9{WϟWϟ=|vGhy97pW _~ٟ_x_O~s?2h*ы/ɋ>*OS"mrvx ø8E?ԡ cõk{x}u7#E=;LR9ks5MWQ7*n}9rtlI#6Ù1ɈB#ģ}JnPpɇ ݧ$}:piJtOgpc{͙OM"!!0'1u0U&$8ͽ2,b?{msoq7Co%O/wi4 f$VG;nib) <|&Yg5OtLO6Ya)0lNa8߫бEń_PK!"++ xl/styles.xmlY_o6@(ÞHr,.hIu0eEOZ^yIv$%[Iu)ww8|d LtdyH򈦳.{N#𔌬ɭb9!D0IK34/2\Nbrݎ0M-0`> grNiBJaY7gxKC:Ya4xcq c ҂i&r"#gU]HyV:m uHv=u]r?'^#LPFg;g_wN_3Q4AA0.ǟr*9.l: IxOnۥtd)>NyA \quxX_N/ÈOq" T33!BYbnXM,c]ٽΙo׺/ox:W],= (# M-ٿ,|F҄PK!3rgxl/worksheets/sheet1.xmlYYH ~_iC9n[ڕF3{SAB2q ?'缒vwOqzcZ:qI[_+ )'u; U;v&-/MdT|ܱ~Vz Im.CMڴ:TvQmgXjRpU|MXң\XXԎ5˝/{QV|Vk*!CÄDŽEmWXv u+^R60C3v}mܵґv|N%jy3MSŠ2A>*Ώ08O E6LW/)OR}K+QhǤkװ"sSݸZ)jf)E[0ߠU-V>(VA&]ZWLU;]Y~FOpq ;aO-[O w} 1^38hݐj045DϙBi fgBpt.҃>dą{:)jC^0JmjʒАy:+u$| g4?axdUVI[n(ԺdjkKmR&mJ#fũOf:*潊HE7ԭ!XTIڤMZi$]?+`u6I ]ѥO\P.aD Ex[qaxjjy);OO ~=Axx(ɝ-v)p=pc(\]YwTtO(X@m [PK!]`_{docProps/core.xml (AN0DH!>qFI* $@,HlvII r6U %sD BsZ(JN+%!G{hVeLL7JqlIҦLhN1l5wH/YcM+]N(zk jbu`j@ p{;ٜɽdl&jF] CW5TduW!dE[|_,3ʪwe)s[&ÿXGMbGit}Z"4$$L!x6ˏ6zQ8!i<_PK!Zmƹxl/calcChain.xml< 1D{{{g!"I{[M  f1fIJ,l`FPľ,JťdCnwɟ@hm=! e%ͣZDY+EQ x`Wu@~T%ZPK!eLt!docProps/app.xml (n0 n(@VѦzXI{gd:&KɞolɟܷuY:+v%:Y"pXLR}"Wd0lR"[H,>@9;hEG(. ]Y8qgM+{9 Uh|Kugt@G>5^b&3c4tPT5X\PׂE׷-:#K_^9g[H؃hQdmHUܢOD]2|W!HS΍!OH`ϧ=\[ b)p<ҷ! q} |YiQXw8.Xy&B[_wRoPK-!,lok[Content_Types].xmlPK-!U0#L _rels/.relsPK-!?xl/_rels/workbook.xml.relsPK-!9~ xl/workbook.xmlPK-!>6x/ xl/sharedStrings.xmlPK-!p xl/theme/theme1.xmlPK-!"++ xl/styles.xmlPK-!3rgPxl/worksheets/sheet1.xmlPK-!]`_{!docProps/core.xmlPK-!Zmƹ$xl/calcChain.xmlPK-!eLt!G%docProps/app.xmlPK (ooxml/examples/xlsx-formula.tcl000755 000765 000024 00000002705 15217572310 017305 0ustar00alexstaff000000 000000 #!/bin/sh #\ exec tclsh "$0" "$@" set auto_path [linsert $auto_path 0 ..] if {[catch {package require ooxml}]} { source ../ooxml.tcl } source array.tcl set spreadsheet [::ooxml::xl_write new -creator {Alexander Schöpe}] if {[set sheet [$spreadsheet worksheet {Tabelle 1}]] > -1} { # single formula autoincrement column index $spreadsheet row $sheet $spreadsheet cell $sheet 3 $spreadsheet cell $sheet 5 $spreadsheet cell $sheet {} -formula A1+B1 # vertical shared formula C3 to C5 $spreadsheet cell $sheet 1 -index 2,0 $spreadsheet cell $sheet 2 -index 2,1 $spreadsheet cell $sheet {} -index 2,2 -formula {A3+B3} -formularef C3:C5 -formulaidx 0 $spreadsheet cell $sheet 2 -index 3,0 $spreadsheet cell $sheet 3 -index 3,1 $spreadsheet cell $sheet {} -index 3,2 -formulaidx 0 $spreadsheet cell $sheet 3 -index A5 $spreadsheet cell $sheet 4 -index B5 $spreadsheet cell $sheet {} -index C5 -formulaidx 0 # horizontal shared formula A9 to C9 $spreadsheet cell $sheet 1 -index 6,0 $spreadsheet cell $sheet 2 -index 7,0 $spreadsheet cell $sheet {} -index A9 -formula {A7+A8} -formularef 8,0:8,2 -formulaidx 1 $spreadsheet cell $sheet 2 -index 6,1 $spreadsheet cell $sheet 3 -index 7,1 $spreadsheet cell $sheet {} -index 8,1 -formulaidx 1 $spreadsheet cell $sheet 3 -index C7 $spreadsheet cell $sheet 4 -index C8 $spreadsheet cell $sheet {} -index C9 -formulaidx 1 } $spreadsheet write formula.xlsx $spreadsheet destroy ooxml/examples/docx-example4-in.docx000664 000765 000024 00000012104 15213015413 020056 0ustar00alexstaff000000 000000 PK aZ _rels/.relsJA CVfC;?dFo .E$'|t?bаiZPL.OT$O.eUwB0nSnbP'CO2b"sq۶(?=y {uxK8 ΰs("s!KDuj"q$# u󇢩[s`.#QJKDWI4W|üFuOUoPK DPK aZdocProps/core.xmlRN0 d%'*!Qfmjv_4ig_g{UG[N6@$IQ7B@/y|"n4ʫ O1`#(7Z{o(ƎA1䪱m _ V`06#:Z >Z;1Ԡ@{IBI*wAǜ)9Nn&4O5]TF(<(оNsTfiv8%4$S_[>nlٲ'b[i|aOH\3]mK?5s~. BnhGsgJyl?^I#l[vOྟg!Чg,PK˒^PK aZdocProps/app.xmln0EbKlR 9F}+"5@wȵUb[AuF]֫3WgKS'gp^IJPZtm:^%]g,'}c/*hOcYѸ(]qj@2p %ȱ큨#.PiD;Wyؚ` .TlӽJ/ۭ$hrXi20 _ &dtRga-yםMR^o7NzvOq;.B95U-3>ʳm֫(o`PK:gy.PK aZword/_rels/document.xml.rels 0E~EM""M݈VtA2rn2$_]tCg,IQL#`_n X|x% , %rK΃jQːX&kI wRe|s=dJVo[םµU'D@CtAp{dxsq/ b:$Dm ) $~_Cy rÊPK|PK aZword/document.xmlTn0+mIIB\940`(ʊ%";3+RoJFNtkfJ?-V$rHuI<'GCk`]'Cx_q.Rvni{j[x4NO5~u~RQ+ Iw!DݜmNKߠ3RRDfnqV/R+K4p`pQQ-mx6p Ay/PK0PK aZword/styles.xmlUN0|߯^RbQE@.v sXC _ii.xi9񜙉{r(Eq'(S IԺ<܇Zr>ږֶ̱w}-CmISjmlZtCq;ұ6`"R$}:kx}tƓ8ad@cxlZMS.:U0JNg|'jdu߂Wָ//|gN ~slꊡUDW5.(We:,bsTjh> mg-[Ydy?nT` Ļ[#ޒ!R܈t7PKƽA9aUPK aZword/settings.xmle=n0 ?#rKPd: DuO_FOwsq5l75T-u.^4|_*lbg4`4,9RH.hZ:Acv2g3y##YKwRjPKk}oPK aZ[Content_Types].xmlN0E[@%(kړ?d{i*4-̽8I>ݨ:Y\fcFH]eސdϷ|d%(3cAc4NwV)7:idCVuH6x㢜$w*,X:? \k.melzRZ=j U,+,KjqN Hf̅'IhvyH38//SFh}:Д+ #ƉvǢWn82 bRa[? ^JΟ Q"uE@h6?'PKb9`PK aZ D _rels/.relsPK aZ˒^docProps/core.xmlPK aZ:gy.docProps/app.xmlPK aZ|word/_rels/document.xml.relsPK aZ0?word/document.xmlPK aZrK- word/styles.xmlPK aZuVm word/numbering.xmlPK aZƽA9aUA word/fontTable.xmlPK aZk}oword/settings.xmlPK aZb9`[Content_Types].xmlPK |ooxml/examples/xlsx-aLotOfFormats.tcl000755 000765 000024 00000027243 15217572310 020364 0ustar00alexstaff000000 000000 #!/bin/sh #\ exec tclsh "$0" "$@" set auto_path [linsert $auto_path 0 ..] if {[catch {package require ooxml}]} { source ../ooxml.tcl } set spreadsheet [::ooxml::xl_write new -creator {Alexander Schöpe}] if {[set sheet [$spreadsheet worksheet {Blatt 1}]] > -1} { set bold [$spreadsheet style -font [$spreadsheet font -bold]] set italic [$spreadsheet style -font [$spreadsheet font -italic]] set underline [$spreadsheet style -font [$spreadsheet font -underline]] set red [$spreadsheet style -font [$spreadsheet font -color Red]] set font9 [$spreadsheet style -font [$spreadsheet font -size 9]] set font18 [$spreadsheet style -font [$spreadsheet font -size 18]] set rotate90 [$spreadsheet style -rotate 90 -horizontal center] set rotate45 [$spreadsheet style -rotate 45] set left [$spreadsheet style -horizontal left] set center [$spreadsheet style -horizontal center] set right [$spreadsheet style -horizontal right] set top [$spreadsheet style -vertical top] set vcenter [$spreadsheet style -vertical center] set bottom [$spreadsheet style -vertical bottom] set hvcenter [$spreadsheet style -horizontal center -vertical center] set yellow [$spreadsheet style -fill [$spreadsheet fill -fgcolor FFFFFF00 -bgcolor 64 -patterntype solid]] set bLeft [$spreadsheet style -border [$spreadsheet border -leftstyle thin]] set bBottom [$spreadsheet style -border [$spreadsheet border -bottomstyle thin]] set bBottom2 [$spreadsheet style -border [$spreadsheet border -bottomstyle double]] set bBottomB [$spreadsheet style -border [$spreadsheet border -bottomstyle medium]] set bBottomD [$spreadsheet style -border [$spreadsheet border -bottomstyle dashed]] set bDiagonal [$spreadsheet style -border [$spreadsheet border -diagonalstyle medium -diagonaldirection up]] set dec2 [$spreadsheet style -numfmt [$spreadsheet numberformat -decimal]] set dec2t [$spreadsheet style -numfmt [$spreadsheet numberformat -decimal -separator]] set dec3 [$spreadsheet style -numfmt [$spreadsheet numberformat -format {#,##0.000}]] set dec3t [$spreadsheet style -numfmt [$spreadsheet numberformat -format {#,##0.000_ ;[Red]\-#,##0.000\ }]] set currency [$spreadsheet style -numfmt [$spreadsheet numberformat -format {#,##0.00\ "€"}]] set iso8601 [$spreadsheet style -numfmt [$spreadsheet numberformat -iso8601]] set date [$spreadsheet style -numfmt [$spreadsheet numberformat -date]] set date2 [$spreadsheet style -numfmt [$spreadsheet numberformat -format {[$-F800]dddd\,\ mmmm\ dd\,\ yyyy}]] set date3 [$spreadsheet style -numfmt [$spreadsheet numberformat -format {[$-407]d/\ mmmm\ yyyy;@}]] set date4 [$spreadsheet style -numfmt [$spreadsheet numberformat -format {d/m/yy\ h:mm;@}]] set time [$spreadsheet style -numfmt [$spreadsheet numberformat -time]] set time2 [$spreadsheet style -numfmt [$spreadsheet numberformat -format {[$-F400]h:mm:ss\ AM/PM}]] set percent [$spreadsheet style -numfmt [$spreadsheet numberformat -percent]] set percent2 [$spreadsheet style -numfmt [$spreadsheet numberformat -format {0.00%}]] set scientific [$spreadsheet style -numfmt [$spreadsheet numberformat -scientific]] set fraction [$spreadsheet style -numfmt [$spreadsheet numberformat -fraction]] set fraction2 [$spreadsheet style -numfmt [$spreadsheet numberformat -format {# ??/??}]] set text [$spreadsheet style -numfmt [$spreadsheet numberformat -string]] set wrap [$spreadsheet style -wrap] $spreadsheet column $sheet -index 0 -width 17.33203125 -bestfit $spreadsheet column $sheet -index 1 -width 20.5 -bestfit $spreadsheet column $sheet -index 4 -width 31.1640625 -bestfit $spreadsheet column $sheet -index 7 -width 11.1640625 -bestfit ;# -style 19 $spreadsheet column $sheet -index 8 ;# -style 15 $spreadsheet cell $sheet Standard -index 0,0 -string $spreadsheet cell $sheet 3.1415 -index 0,1 $spreadsheet cell $sheet 1 -index 0,8 ;# -style 15 $spreadsheet cell $sheet Standard -index 1,0 -string $spreadsheet cell $sheet Text -index 1,1 -string $spreadsheet cell $sheet {Zahl 2} -index 2,0 -string $spreadsheet cell $sheet 3.1415 -index 2,1 -style $dec2 $spreadsheet cell $sheet 1 -index 2,2 $spreadsheet cell $sheet 2 -index 2,3 $spreadsheet cell $sheet 0.00 -index 2,4 -string ;# -style 15 $spreadsheet cell $sheet {Zahl 2 T} -index 3,0 -string $spreadsheet cell $sheet 3.1415 -index 3,1 -style $dec2t $spreadsheet cell $sheet 2 -index 3,2 $spreadsheet cell $sheet 4 -index 3,3 $spreadsheet cell $sheet #,##0.00 -index 3,4 -string $spreadsheet cell $sheet {2018-02-09 16:17:00} -index 3,7 -style $date4 $spreadsheet cell $sheet {Zahl 3} -index 4,0 -string $spreadsheet cell $sheet 3.1415 -index 4,1 -style $dec3 $spreadsheet cell $sheet 17 -index 4,2 $spreadsheet cell $sheet 174 -index 4,3 $spreadsheet cell $sheet #,##0.000 -index 4,4 -string $spreadsheet cell $sheet {Zahl 3 C} -index 5,0 -string $spreadsheet cell $sheet -3.1415 -index 5,1 -style $dec3t $spreadsheet cell $sheet 16 -index 5,2 $spreadsheet cell $sheet 173 -index 5,3 $spreadsheet cell $sheet {#,##0.000_ ;[Red]\-#,##0.000\ } -index 5,4 -string $spreadsheet cell $sheet Währung -index 6,0 -string $spreadsheet cell $sheet 3.1415 -index 6,1 -style $currency $spreadsheet cell $sheet 3 -index 6,2 $spreadsheet cell $sheet 166 -index 6,3 $spreadsheet cell $sheet {#,##0.00\ "€"} -index 6,4 -string $spreadsheet cell $sheet tt.mm.jj -index 7,0 -string $spreadsheet cell $sheet {2018-02-09 16:17:00} -index 7,1 -style $date $spreadsheet cell $sheet 4 -index 7,2 $spreadsheet cell $sheet 14 -index 7,3 $spreadsheet cell $sheet mm-dd-yy -index 7,4 -string $spreadsheet cell $sheet {tttt, t.mmmm.jj} -index 8,0 -string $spreadsheet cell $sheet {2018-02-09 16:17:00} -index 8,1 -style $date2 $spreadsheet cell $sheet 5 -index 8,2 $spreadsheet cell $sheet 167 -index 8,3 $spreadsheet cell $sheet {[$-F800]dddd\,\ mmmm\ dd\,\ yyyy} -index 8,4 -string $spreadsheet cell $sheet t.mmmm.jjjj -index 9,0 -string $spreadsheet cell $sheet {2018-02-09 16:17:00} -index 9,1 -style $date3 $spreadsheet cell $sheet 6 -index 9,2 $spreadsheet cell $sheet 168 -index 9,3 $spreadsheet cell $sheet {[$-407]d/\ mmmm\ yyyy;@} -index 9,4 -string $spreadsheet cell $sheet hh:mm:ss -index 10,0 -string $spreadsheet cell $sheet {2018-02-09 16:17:00} -index 10,1 -style $time2 $spreadsheet cell $sheet 7 -index 10,2 $spreadsheet cell $sheet 169 -index 10,3 $spreadsheet cell $sheet {[$-F400]h:mm:ss\ AM/PM} -index 10,4 -string $spreadsheet cell $sheet hh:mm -index 11,0 -string $spreadsheet cell $sheet {2018-02-09 16:17:00} -index 11,1 -style $time $spreadsheet cell $sheet 8 -index 11,2 $spreadsheet cell $sheet 170 -index 11,3 $spreadsheet cell $sheet {h:mm;@} -index 11,4 -string $spreadsheet cell $sheet {jjjj-mm-tt hh:mm:ss} -index 12,0 -string $spreadsheet cell $sheet {2018-02-09 16:17:00} -index 12,1 -style $iso8601 $spreadsheet cell $sheet 9 -index 12,2 $spreadsheet cell $sheet 171 -index 12,3 $spreadsheet cell $sheet {yyyy\-mm\-dd\ hh:mm:ss;@} -index 12,4 -string $spreadsheet cell $sheet {Prozent 2} -index 13,0 -string $spreadsheet cell $sheet 3.1415 -index 13,1 -style $percent2 $spreadsheet cell $sheet 10 -index 13,2 $spreadsheet cell $sheet 10 -index 13,3 $spreadsheet cell $sheet 0.00% -index 13,4 -string $spreadsheet cell $sheet {Bruch 1} -index 14,0 -string $spreadsheet cell $sheet 3.1415 -index 14,1 -style $fraction $spreadsheet cell $sheet 12 -index 14,2 $spreadsheet cell $sheet 12 -index 14,3 $spreadsheet cell $sheet {# ?/?} -index 14,4 -string $spreadsheet cell $sheet {Bruch 2} -index 15,0 -string $spreadsheet cell $sheet 3.1415 -index 15,1 -style $fraction2 $spreadsheet cell $sheet 13 -index 15,2 $spreadsheet cell $sheet 13 -index 15,3 $spreadsheet cell $sheet {# ??/??} -index 15,4 -string $spreadsheet cell $sheet {Wissenschaftl. 2} -index 16,0 -string $spreadsheet cell $sheet 3.1415 -index 16,1 -style $scientific $spreadsheet cell $sheet 14 -index 16,2 $spreadsheet cell $sheet 11 -index 16,3 $spreadsheet cell $sheet 0.00E+00 -index 16,4 -string $spreadsheet cell $sheet Text -index 17,0 -string $spreadsheet cell $sheet 3,1415 -index 17,1 -string -style $text $spreadsheet cell $sheet 15 -index 17,2 $spreadsheet cell $sheet 49 -index 17,3 $spreadsheet cell $sheet @ -index 17,4 -string $spreadsheet cell $sheet {Filter A} -index 19,5 -string ;# -style 19 $spreadsheet cell $sheet {Filter B} -index 19,6 -string ;# -style 15 $spreadsheet cell $sheet unten -index 20,0 -string $spreadsheet cell $sheet {} -index 20,1 -style $bBottom $spreadsheet cell $sheet links -index 21,0 -string $spreadsheet cell $sheet {} -index 21,1 -style $bLeft $spreadsheet cell $sheet fett -index 21,4 -string -style $bold $spreadsheet cell $sheet {unten doppelt} -index 22,0 -string $spreadsheet cell $sheet {} -index 22,1 -style $bBottom2 $spreadsheet cell $sheet kursiv -index 22,4 -string -style $italic $spreadsheet cell $sheet {unten mittel} -index 23,0 -string $spreadsheet cell $sheet {} -index 23,1 -style $bBottomB $spreadsheet cell $sheet unterstrichen -index 23,4 -string -style $underline $spreadsheet cell $sheet {diagonal mittel} -index 24,0 -string $spreadsheet cell $sheet {} -index 24,1 -style $bDiagonal $spreadsheet cell $sheet {unten gestrichelt} -index 25,0 -string $spreadsheet cell $sheet {} -index 25,1 -style $bBottomD $spreadsheet cell $sheet {vorne rot} -index 27,0 -string $spreadsheet cell $sheet rot -index 27,1 -string -style $red $spreadsheet cell $sheet {hinten gelb} -index 28,0 -string $spreadsheet cell $sheet gelb -index 28,1 -string -style $yellow $spreadsheet cell $sheet links -index 30,0 -string $spreadsheet cell $sheet links -index 30,1 -string -style $left $spreadsheet cell $sheet mitte -index 31,0 -string $spreadsheet cell $sheet mitte -index 31,1 -string -style $center $spreadsheet cell $sheet rechts -index 32,0 -string $spreadsheet cell $sheet rechts -index 32,1 -string -style $right $spreadsheet cell $sheet oben -index 33,0 -string $spreadsheet cell $sheet oben -index 33,1 -string -style $top $spreadsheet cell $sheet mitte -index 34,0 -string $spreadsheet cell $sheet mitte -index 34,1 -string -style $vcenter $spreadsheet cell $sheet {Calibri 9} -index 34,4 -string -style $font9 $spreadsheet cell $sheet unten -index 35,0 -string $spreadsheet cell $sheet unten -index 35,1 -string -style $bottom $spreadsheet cell $sheet {Text 90} -index 38,0 -string -style $rotate90 $spreadsheet cell $sheet {Text 45} -index 38,1 -string -style $rotate45 $spreadsheet cell $sheet {Calibri 18} -index 38,4 -string -style $font18 $spreadsheet cell $sheet {12 Zellen} -index 39,3 -string -style $hvcenter $spreadsheet cell $sheet {3 Spalten} -index 40,0 -string $spreadsheet cell $sheet {3 Zeilen} -index 41,1 -string $spreadsheet cell $sheet {this text will be automatically wrapped by excel} -index H27 -style $wrap $spreadsheet cell $sheet a -index F21 -style $center $spreadsheet cell $sheet a -index F22 -style $center $spreadsheet cell $sheet b -index F23 -style $center $spreadsheet cell $sheet 1 -index G21 -style $center $spreadsheet cell $sheet 2 -index G22 -style $center $spreadsheet cell $sheet 2 -index G23 -style $center $spreadsheet row $sheet -index 10 $spreadsheet cell $sheet 3 -index G $spreadsheet cell $sheet 5 $spreadsheet cell $sheet {} -formula G11+H11 $spreadsheet freeze $sheet 20,5 $spreadsheet autofilter $sheet 19,5 19,6 $spreadsheet rowheight $sheet 33 20 $spreadsheet rowheight $sheet 34 20 $spreadsheet rowheight $sheet 35 20 $spreadsheet merge $sheet 40,0 40,2 $spreadsheet merge $sheet 41,1 43,1 $spreadsheet merge $sheet 39,3 42,5 } $spreadsheet write aLotOfFormats.xlsx $spreadsheet destroy ooxml/examples/xlsx-defaultDateStyle.tcl000755 000765 000024 00000001036 15217572310 021077 0ustar00alexstaff000000 000000 #!/bin/sh #\ exec tclsh "$0" "$@" set auto_path [linsert $auto_path 0 ..] if {[catch {package require ooxml}]} { source ../ooxml.tcl } set spreadsheet [::ooxml::xl_write new -creator {Alexander Schöpe}] if {[set sheet [$spreadsheet worksheet {Tabelle 1}]] > -1} { set date [$spreadsheet style -numfmt [$spreadsheet numberformat -datetime]] $spreadsheet defaultdatestyle $date # 2018-03-02 17:39 -> 43161.73542 $spreadsheet cell $sheet "2018-03-02 17:39" -index 0,0 } $spreadsheet write defaultDateStyle.xlsx $spreadsheet destroy ooxml/examples/xlsx-printArea.tcl000755 000765 000024 00000001602 15217572310 017560 0ustar00alexstaff000000 000000 #!/bin/sh #\ exec tclsh "$0" "$@" set auto_path [linsert $auto_path 0 ..] if {[catch {package require ooxml}]} { source ../ooxml.tcl } set spreadsheet [::ooxml::xl_write new -creator {Creator Name}] for {set s 1} {$s <= 4} {incr s} { if {[set sheet [$spreadsheet worksheet "Sheet$s"]] > -1} { for {set r 1} {$r < 6} {incr r} { $spreadsheet row $sheet for {set c 1} {$c < 6} {incr c} { $spreadsheet cell $sheet $s,$c,$r } } switch -- $s { 1 { $spreadsheet printarea $sheet A1 C3 } 2 { #$spreadsheet printarea $sheet B2 C3 $spreadsheet printarea $sheet 1,1 2,2 } 4 { $spreadsheet printarea $sheet A3 A4 } } } } $spreadsheet write printArea.xlsx $spreadsheet destroy ooxml/examples/xlsx-hyperlinksTooltips.tcl000755 000765 000024 00000001336 15217572310 021565 0ustar00alexstaff000000 000000 #!/bin/sh #\ exec tclsh "$0" "$@" set auto_path [linsert $auto_path 0 ..] if {[catch {package require ooxml}]} { source ../ooxml.tcl } source array.tcl set spreadsheet [::ooxml::xl_write new -creator {Steve Landers}] if {[set sheet [$spreadsheet worksheet {Table 1}]] > -1} { $spreadsheet row $sheet $spreadsheet cell $sheet {} -hyperlink {https://fossil.sowaswie.de/ooxml/timeline} $spreadsheet row $sheet $spreadsheet cell $sheet {ooXML Home} -hyperlink {https://fossil.sowaswie.de/ooxml/} $spreadsheet row $sheet $spreadsheet cell $sheet {check tooltip} -hyperlink {https://fossil.sowaswie.de/ooxml/wiki?name=man-page} -tooltip {ooXML Manual Page} } $spreadsheet write hyperlinksTooltips.xlsx $spreadsheet destroy ooxml/examples/strings.tcl000664 000765 000024 00000001072 15217572310 016330 0ustar00alexstaff000000 000000 set loreipsum {Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed eiusmod tempor incidunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquid ex ea commodi consequat. Quis aute iure reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint obcaecat cupiditat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.} proc featuresCovered {text} { uplevel "\$docx paragraph \"Features covered: $text\" -bold 1 -spacing {after 1.5cm}" } ooxml/examples/docx-example11.tcl000775 000765 000024 00000001722 15217572310 017374 0ustar00alexstaff000000 000000 #!/bin/sh #\ exec tclsh "$0" "$@" cd [file dirname [info script]] source ../ooxml.tcl source ../ooxml-docx.tcl source strings.tcl namespace import ::ooxml::docx::docx set docx [docx new] featuresCovered "Comment ranges." $docx paragraph "Some text " $docx commentrangestart mycommentid $docx append "read more" $docx commentrangestart mycommentid2 $docx append " about this" $docx commentrangeend $mycommentid -author foo { $docx paragraph "What do you mean?" } $docx append " even more text" $docx commentrangeend $mycommentid2 -author bar { $docx paragraph "Two " $docx append "overlapping" -italic on $docx append " comments" } $docx append " and again even more text " $docx commentrangestart mycommentid3 $docx append "and again even more text" $docx simplecommentrangeend $mycommentid3 "A bit repititive?" -bold on -author bar -initials b -date "2025-11-15T03:00:00" $docx append " and again even more text " $docx write docx-example11 $docx destroy ooxml/examples/docx-example10.tcl000775 000765 000024 00000001226 15217572310 017372 0ustar00alexstaff000000 000000 #!/bin/sh #\ exec tclsh "$0" "$@" cd [file dirname [info script]] source ../ooxml.tcl source ../ooxml-docx.tcl source strings.tcl namespace import ::ooxml::docx::docx set docx [docx new] featuresCovered "The replace method." set docxname [file join [file dir [info script]] docx-example10] $docx paragraph $loreipsum $docx simplecomment $loreipsum $docx footnote { $docx paragraph $loreipsum } $docx write $docxname $docx destroy set docx [docx new $docxname.docx] $docx replace e ! $docx write $docxname-1 $docx destroy set docx [docx new $docxname.docx] $docx replace e ! {word/document.xml word/footnotes.xml} $docx write $docxname-2 $docx destroy ooxml/examples/docx-example12.tcl000775 000765 000024 00000007273 15217572310 017404 0ustar00alexstaff000000 000000 #!/bin/sh #\ exec tclsh "$0" "$@" cd [file dirname [info script]] source ../ooxml.tcl source ../ooxml-docx.tcl source strings.tcl namespace import ::ooxml::docx::docx set docx [docx new] featuresCovered "The appendTo method." $docx paragraph $loreipsum set tableToAppend [$docx table { set rowToAppend [$docx tablerow { $docx tablecell -vspan continue { $docx paragraph "3.1" } set cellToAppend [$docx tablecell { $docx paragraph "3.2" }] $docx tablecell { $docx paragraph "3.3" } }] }] $docx paragraph "Next paragraph " set comment1 [$docx comment { $docx paragraph "Comment started." }] $docx append $loreipsum $docx appendTo $tableToAppend { $docx tablerow { $docx tablecell { $docx paragraph "Later" } $docx tablecell { $docx paragraph " added " } $docx tablecell { $docx paragraph "row" } } } $docx paragraph "Append to " $docx commentrangestart commentrange $docx append "document" set comment2 [$docx commentrangeend $commentrange { $docx paragraph "Another comment started." }] $docx append " $loreipsum" $docx appendTo $rowToAppend { $docx tablecell { $docx paragraph "Later added cell to row." } } $docx paragraph "A second table:" $docx table { $docx tablerow { set cell2 [$docx tablecell { $docx paragraph "We append later to this cell." }] $docx tablecell { $docx paragraph "foo" } } $docx tablerow { $docx tablecell { $docx paragraph "bar" } $docx tablecell { $docx paragraph "and grill" } } } $docx paragraph "Append" set footnote1 [$docx footnote { $docx paragraph "Footnote one." }] $docx append " to" set footnote2 [$docx footnote { $docx paragraph "Footnote two." }] $docx append " document" set endnote1 [$docx endnote { $docx paragraph "Endnote one." }] $docx append " $loreipsum" $docx appendTo $endnote1 { $docx paragraph "Added to endnote." } $docx appendTo $footnote2 { $docx paragraph "Added to footnote two." } $docx appendTo $footnote1 { $docx paragraph "Added to footnote one." } $docx appendTo $comment2 { $docx paragraph "Later added" } $docx appendTo $comment1 { $docx paragraph "Later added" } $docx appendTo $cell2 { $docx paragraph "This was added later" -italic 1 } $docx appendTo $cellToAppend { $docx append " Later added text" $docx paragraph "Later added paragraph." } $docx appendTo $cellToAppend { $docx append " Later added text" $docx paragraph "Later added paragraph." } $docx header { $docx paragraph "This header" } defaultHeader defaultHeaderObjId $docx footer { $docx field page } defaultFooter defaultFooterObjId $docx pagesetup -defaultHeader $defaultHeader \ -defaultFooter $defaultFooter $docx paragraph "Append to document $loreipsum" $docx appendTo $defaultHeaderObjId { $docx append " later on added to header" } $docx appendTo $defaultFooterObjId { $docx append " later added to footer" -bold 1 } $docx pagebreak set textbox1 [$docx textbox -dimension {width 3cm height 3cm} \ -anchorData {distL 1cm distR 1cm distT 1cm} \ -positionH page \ -posOffsetH 6cm \ -positionV page \ -posOffsetV 6cm \ -wrapMode square \ -wrapData {wrapText bothSides} { $docx paragraph "Second paragraph in a textbox" -align center }] $docx paragraph $loreipsum $docx appendTo $textbox1 { $docx paragraph "Later added paragraph to the textbox" -spacing {before 0} } $docx write docx-example12.docx $docx destroy ooxml/examples/array.tcl000644 000765 000024 00000002574 14764622263 015774 0ustar00alexstaff000000 000000 array set data { 0,0 item 0,1 {article description} 0,2 {order number} 0,3 supplier 0,4 price 0,5 date 0,6 quantity 1,0 9719 1,1 tube 1,2 {4915 500 0828} 1,3 STIHL 1,4 38.19 1,5 {2017-07-15 10:59:57} 1,6 0 2,0 9718 2,1 {tightrope 6x50m} 2,2 300527 2,3 Teupen 2,4 268.07 2,5 {2017-05-15 00:00:00} 2,6 0 3,0 9717 3,1 {tightrope 6x35m} 3,2 3020/0011 3,3 Teupen 3,4 229.41 3,5 {2017-05-15 00:00:00} 3,6 0 4,0 9716 4,1 {tire 4,80/4,00-8/4PR groove} 4,2 1-337 4,3 Ratioparts 4,4 18.239999999999998 4,5 {2017-03-16 00:00:00} 4,6 1 5,0 9715 5,1 {Keiltasche Ochsenkopf} 5,2 177-368 5,3 Ratioparts 5,4 17.14 5,5 {2017-06-13 11:20:50} 5,6 0 6,0 9231 6,1 {v-belt mower 12,7x2096} 6,2 57270172 6,3 Fricke 6,4 39.5 6,5 {2017-02-18 08:54:54} 6,6 0 7,0 9714 7,1 {TIGER refill pack 30x3,3 mm sticks} 7,2 855-10 7,3 Tiger 7,4 9.9 8,0 9383 8,1 {TIGER gap brush big (36 threads) bis 30 ccm, NW 12,0 cm, 400 g, 3,3 mm} 8,2 TIG856 8,3 Tiger 8,4 79.900000000000006 8,5 {2017-03-16 00:00:00} 8,6 7 9,0 9712 9,1 {TIGER gap brush big NW 12 cm, ab 30ccm, nylon thread mit 30x3,3 mm sticks} 9,2 856TIG 9,3 Tiger 9,4 79.900000000000006 9,5 {2018-01-20 00:00:00} 9,6 -2 10,0 9711 10,1 {carburettor Walbro WT-194} 10,2 LA81801 10,3 Lagros 10,4 62.1 10,5 {2017-03-29 00:00:00} 10,6 0 } ooxml/examples/xlsx-searchAndReplace.tcl000755 000765 000024 00000006466 15217572310 021034 0ustar00alexstaff000000 000000 #!/bin/sh #\ exec tclsh "$0" "$@" set auto_path [linsert $auto_path 0 ..] if {[catch {package require ooxml}]} { source ../ooxml.tcl } array set workbook [ooxml::xl_read form8.xlsx] set data(NAME) {Erika Mustermann} set data(ANSCHRIFT) {Heidestrasse 17} set data(PLZORT) {51147 Köln} set data(positionen) 3 set data(0,BEZEICHUNG) {Kopierpapier 80g 500 Blatt} set data(0,MENGE) 5 set data(1,BEZEICHUNG) {Ordner A4 breit} set data(1,MENGE) 1 set data(2,BEZEICHUNG) {Haftnotizen 5x5cm 40 Blatt} set data(2,MENGE) 2 foreach name {NAME ANSCHRIFT PLZORT POSITION BEZEICHUNG MENGE} { set position($name) {} } foreach {name value} [array get workbook 0,v,*] { if {[set value [string trim $value]] in {NAME ANSCHRIFT PLZORT POSITION BEZEICHUNG MENGE}} { lassign [split $name ,] sheet tag row column set position($value) [list sheet $sheet row $row column $column] } } if 0 { set workbook([dict get $position(NAME) sheet],v,[dict get $position(NAME) row],[dict get $position(NAME) column]) $data(NAME) set workbook([dict get $position(ANSCHRIFT) sheet],v,[dict get $position(ANSCHRIFT) row],[dict get $position(ANSCHRIFT) column]) $data(ANSCHRIFT) set workbook([dict get $position(PLZORT) sheet],v,[dict get $position(PLZORT) row],[dict get $position(PLZORT) column]) $data(PLZORT) for {set i 0} {$i < $data(positionen)} {incr i} { set workbook([dict get $position(POSITION) sheet],v,[expr {[dict get $position(POSITION) row] + $i}],[dict get $position(POSITION) column]) [expr {$i + 1}] set workbook([dict get $position(BEZEICHUNG) sheet],v,[expr {[dict get $position(BEZEICHUNG) row] + $i}],[dict get $position(BEZEICHUNG) column]) $data($i,BEZEICHUNG) set workbook([dict get $position(MENGE) sheet],v,[expr {[dict get $position(MENGE) row] + $i}],[dict get $position(MENGE) column]) $data($i,MENGE) } } proc Cell { *workbook *position item } { upvar ${*workbook} workbook upvar ${*position} position return [dict get $workbook(sheetmap) [dict get $position($item) sheet]] } proc Options { *workbook *position item {rowoffset 0} } { upvar ${*workbook} workbook upvar ${*position} position set sheet [dict get $position($item) sheet] set row [expr {[dict get $position($item) row] + $rowoffset}] set column [dict get $position($item) column] set options [list -index $row,$column] if {[info exists workbook($sheet,s,$row,$column)]} { lappend options -style $workbook($sheet,s,$row,$column) } return $options } set spreadsheet [::ooxml::xl_write new] $spreadsheet presetstyles workbook $spreadsheet presetsheets workbook if 1 { $spreadsheet cell [Cell workbook position NAME] $data(NAME) {*}[Options workbook position NAME] $spreadsheet cell [Cell workbook position ANSCHRIFT] $data(ANSCHRIFT) {*}[Options workbook position ANSCHRIFT] $spreadsheet cell [Cell workbook position PLZORT] $data(PLZORT) {*}[Options workbook position PLZORT] for {set i 0} {$i < $data(positionen)} {incr i} { $spreadsheet cell [Cell workbook position POSITION] [expr {$i + 1}] {*}[Options workbook position POSITION $i] $spreadsheet cell [Cell workbook position BEZEICHUNG] $data($i,BEZEICHUNG) {*}[Options workbook position BEZEICHUNG $i] $spreadsheet cell [Cell workbook position MENGE] $data($i,MENGE) {*}[Options workbook position MENGE $i] } } $spreadsheet write searchAndReplace.xlsx $spreadsheet destroy ooxml/examples/docx-example3.tcl000775 000765 000024 00000017734 15217572310 017327 0ustar00alexstaff000000 000000 #!/bin/sh #\ exec tclsh "$0" "$@" cd [file dirname [info script]] source ../ooxml.tcl source ../ooxml-docx.tcl source strings.tcl namespace import ::ooxml::docx::docx set docx [docx new] featuresCovered "Simple and complex tables, styling of tables." $docx settings -zoom {type bestFit percent 50%} set simpledata {{a b c} {1 2 3} {I II III}} set simpledata2 { {a b c e f} {1 2 3 4 5} {I II III IV V} {one two three four five} {foo bar baz grill boo} } # Set a default style $docx style paragraphdefault -spacing {before 240 after 120} $docx paragraph "Covered simple tables." $docx paragraph "A very simple table:" $docx simpletable $simpledata -columnwidths {30pt 40pt 50pt} -layout fixed $docx paragraph "Something more verbose please." set table [list] lappend table [list "Less words" "Also" $loreipsum] lappend table [list "Less words" $loreipsum "Also"] lappend table [list $loreipsum "Also" "Less words" ] $docx simpletable $table $docx paragraph "I want borders." $docx paragraph "Sure thing:" $docx simpletable $simpledata \ -insideVBorder {type single space 8} -insideHBorder {type single space 8} $docx paragraph "I meant outside." $docx simpletable $simpledata \ -topBorder {type double} \ -bottomBorder {type double} \ -startBorder {type double} \ -endBorder {type double} $docx style table myTable \ -topBorder {type single borderwidth 320} \ -bottomBorder {type single borderwidth 320} \ -startBorder {type single borderwidth 320} \ -endBorder {type single borderwidth 320} $docx paragraph "A table with -style" $docx simpletable $simpledata -style myTable -width {type measure value 100pt} $docx style paragraph tableFirstRow -align center -bold on $docx style paragraph tableLastRow -align end $docx paragraph "A simple table with other style in first and last row." $docx simpletable $simpledata -firstStyle tableFirstRow \ -lastStyle tableLastRow $docx pagebreak $docx paragraph "A first start of a complex table" $docx table -width {type dxa value 9638} -columnwidths {4819 4819} { $docx tablerow { $docx tablecell -cellWidth {type dxa value 4819} { $docx paragraph "A normal paragraph with all paragraph styling" -fontsize 18pt $docx paragraph $loreipsum -spacing {before 240} -underline double } $docx tablecell -cellWidth {type dxa value 4819} { $docx paragraph "Fill grid" } } $docx tablerow { $docx tablecell -cellWidth {type dxa value 4819} { $docx simpletable $simpledata -width {type measure value 1000} \ -columnwidths {2354 2355} \ -layout fixed $docx paragraph "" } $docx tablecell -cellWidth {type dxa value 4819} { $docx paragraph "Another cell" -underline single $docx image book.jpg anchor -anchorData {layoutInCell 1} -dimension {width 3cm height 3cm} -bwMode black } } } $docx paragraph "The same with table defaults" $docx table { $docx tablerow { $docx tablecell { $docx paragraph "A normal paragraph with all paragraph styling" -fontsize 18pt } $docx tablecell { $docx paragraph "Fill grid" } } $docx tablerow { $docx tablecell { $docx simpletable $simpledata $docx paragraph "" } $docx tablecell { $docx paragraph "Another cell" -underline single $docx image book.jpg anchor -anchorData {layoutInCell 1} -dimension {width 3cm height 3cm} -bwMode black } } } $docx paragraph "" $docx pagebreak $docx paragraph "Horizontal cell spanning" $docx table { $docx tablerow { $docx tablecell { $docx paragraph "A normal paragraph with all paragraph styling" -fontsize 18pt } $docx tablecell { $docx paragraph "Fill grid" } $docx tablecell { $docx paragraph "Fill grid" } } $docx tablerow { $docx tablecell { $docx paragraph "" } $docx tablecell -span 2 { $docx paragraph "Another cell spaning acroll cells $loreipsum" \ -underline single } # You must not provide the spanned cell values to make the # span in place # $docx tablecell { # $docx paragraph "Fill grid" # } } } $docx paragraph "Vertical cell spanning" proc createrow {docx nr} { $docx tablerow { $docx tablecell { $docx paragraph "$nr.1" } $docx tablecell { $docx paragraph "$nr.2" } $docx tablecell { $docx paragraph "$nr.3" } } } $docx table { createrow $docx 1 $docx tablerow { $docx tablecell -vspan restart { $docx paragraph "2.1" } $docx tablecell { $docx paragraph "2.2" } $docx tablecell { $docx paragraph "2.3" } } $docx tablerow { $docx tablecell -vspan continue { $docx paragraph "3.1" } $docx tablecell { $docx paragraph "3.2" } $docx tablecell { $docx paragraph "3.3" } } createrow $docx 4 } $docx paragraph "Horizontal and vertical cell spanning combined" proc createrow {docx nr} { $docx tablerow { $docx tablecell { $docx paragraph "$nr.1" } $docx tablecell { $docx paragraph "$nr.2" } $docx tablecell { $docx paragraph "$nr.3" } } } $docx table { createrow $docx 1 $docx tablerow { $docx tablecell -vspan restart -hspan restart { $docx paragraph "2.1" } $docx tablecell -hspan continue { $docx paragraph "2.2" } $docx tablecell { $docx paragraph "2.3" } } $docx tablerow { $docx tablecell -vspan continue { $docx paragraph "3.1" } $docx tablecell { $docx paragraph "3.2" } $docx tablecell { $docx paragraph "3.3" } } createrow $docx 4 } $docx paragraph "Complex table inside cell of complex table" $docx table { createrow $docx 1 $docx tablerow { $docx tablecell { $docx table { $docx tablerow { $docx tablecell { $docx paragraph "sub 1.1" } $docx tablecell { $docx paragraph "sub 1.2" } } $docx tablerow { $docx tablecell { $docx paragraph "sub 2.1" } $docx tablecell { $docx paragraph "sub 2.2" } } } $docx paragraph "" } $docx tablecell { $docx paragraph "2.2" } $docx tablecell { $docx paragraph "2.3" } } } $docx paragraph "Back to normal context addition" $docx simpletable $simpledata -align center -width {type measure value 100pt} $docx paragraph "" $docx style table tableBase \ -topBorder {type single borderwidth 10} \ -bottomBorder {type single borderwidth 10} $docx style table myTable1 -basedon tableBase \ -cellMarginStart {type percent value 140%} $docx simpletable $simpledata -style myTable1 -width {type measure value 100pt} $docx paragraph "" $docx style table myTable2 \ -bold true \ -conditional { firstCol { -color ffff00 -bold off -background ff0000 } lastCol { -color 00ffff } firstRow { -color ff0000 } lastRow { -bold off }} $docx simpletable $simpledata2 -style myTable2 \ -look {lastRow true} if {[lsearch [$docx style names paragraph] tableFirstRow] < 0} { error "miss tableFirstRow style" } $docx write docx-example3.docx $docx destroy ooxml/examples/xlsx-tablelist.tcl000755 000765 000024 00000004676 15217572310 017634 0ustar00alexstaff000000 000000 #!/bin/sh #\ exec wish "$0" "$@" package require Tk package require tablelist set auto_path [linsert $auto_path 0 ..] if {[catch {package require ooxml}]} { source ../ooxml.tcl } source array.tcl # build Tablelist from array set lb .lb tablelist::tablelist $lb -height 16 -width 100 -showseparators 1 -titlecolumns 3 -labelcommand tablelist::sortByColumn grid $lb -row 0 -column 0 -sticky nwse ttk::scrollbar .x -orient horizontal -command [list $lb xview] $lb configure -xscrollcommand [list .x set] grid .x -row 1 -column 0 -sticky we ttk::scrollbar .y -orient vertical -command [list $lb yview] $lb configure -yscrollcommand [list .y set] grid .y -row 0 -column 1 -sticky ns grid columnconfigure . 0 -weight 1 grid rowconfigure . 0 -weight 1 ttk::button .export -text Export -command [list ::ooxml::tablelist_to_xl $lb -file tablelist.xlsx -globalstyle] grid .export -row 2 -column 0 set list {} set cols -1 foreach name [lsort -dictionary [array names data]] { lassign [split $name ,] row col if {$row == 0} { switch -- $data($name) { {order number} { set justify center } item - price { set justify right } default { set justify left } } $lb insertcolumns end 0 $data($name) $justify incr cols } elseif {$row > 0} { lappend rows $row } } foreach row [lsort -integer -unique $rows] { set list {} for {set col 0} {$col <= $cols} {incr col} { if {[info exists data($row,$col)]} { lappend list $data($row,$col) } else { lappend list {} } } $lb insert end $list } # this sample callback is the default source code if nothing else is set proc TablelistToXlCallback { spreadsheet sheet maxcol column title width align sortmode hide } { set left 0 set center [$spreadsheet style -horizontal center] set right [$spreadsheet style -horizontal right] set date [$spreadsheet style -numfmt [$spreadsheet numberformat -datetime]] set decimal [$spreadsheet style -numfmt [$spreadsheet numberformat -decimal -red]] set text [$spreadsheet style -numfmt [$spreadsheet numberformat -string]] if {$column == -1} { $spreadsheet defaultdatestyle $date } else { switch -- $align { center { $spreadsheet column $sheet -index $column -style $center } right { $spreadsheet column $sheet -index $column -style $right } default { $spreadsheet column $sheet -index $column -style $left } } } } ooxml/examples/docx-example2.tcl000775 000765 000024 00000006372 15217572310 017322 0ustar00alexstaff000000 000000 #!/bin/sh #\ exec tclsh "$0" "$@" cd [file dirname [info script]] source ../ooxml.tcl source ../ooxml-docx.tcl source strings.tcl namespace import ::ooxml::docx::docx set docx [docx new] featuresCovered "Page and section setup, header and footer, fields and textboxes." # The rId returned by the header/footer methods is needed later. You # may store it like: set defaultHeader [$docx header { $docx field page }] # Or you use the optional last argument pointing to a variable to # store the rId into: $docx header { $docx paragraph "even page " -align end $docx field page } evenHeader $docx footer { $docx paragraph "footer default " -align center $docx field page $docx append " " $docx image book.jpg inline -dimension {width 1cm height 1cm} $docx append " " $docx field numpages } defaultFooter # Set a default style $docx style paragraphdefault -spacing {before 240 after 120} # And a heading style $docx style paragraph Heading1 -fontsize 28 -spacing {before 480 after 240} # Set the margins #$docx pagesetup $docx pagesetup -sizeAndOrientation {width 15840 height 12240} \ -margins {left 1cm right 1cm top 1cm bottom 1cm} \ -topBorder {type dashed borderwidth 10} \ -defaultHeader $defaultHeader \ -evenHeader $evenHeader \ -firstHeader $defaultHeader \ -defaultFooter $defaultFooter $docx paragraph "Chapter one" -pstyle Heading1 # Add two paragraphs $docx paragraph "A very simple monoton paragraph: $loreipsum" $docx paragraph "The next paragraph: $loreipsum" # Start a new section with different page setup $docx sectionstart -sizeAndOrientation {width 12240 height 15840} \ -margins {left 3cm right 3cm top 4cm bottom 4cm} \ -leftBorder {type thick borderwidth 20 color 00ff00 space 20} \ -pageNumbering {fmt upperRoman start 222} $docx paragraph "Chapter two" -pstyle Heading1 # Add some paragraphs $docx paragraph "A very simple monoton paragraph: $loreipsum" for {set i 0} {$i < 8} {incr i} { $docx paragraph "The next paragraph: $loreipsum" } # End the section $docx sectionend # We are back to the pagesetup $docx paragraph "Chapter three" -pstyle Heading1 # Add two paragraphs $docx paragraph "A very simple monoton paragraph: $loreipsum" $docx paragraph "The next paragraph: $loreipsum" $docx pagebreak $docx paragraph "The next paragraph: $loreipsum" $docx pagebreak $docx paragraph "The next paragraph: $loreipsum" $docx pagebreak $docx paragraph "The next paragraph: $loreipsum" $docx header { $docx paragraph "Header with textbox" $docx textbox -name myTextBox -dimension {width 3cm height 3cm} \ -positionH margin \ -posOffsetH 3cm \ -positionV margin \ -posOffsetV 3cm \ -wrapMode square \ -wrapData {wrapText bothSides} { $docx paragraph "First paragraph in a textbox" -spacing {before 0} $docx paragraph "Second paragraph in a textbox" -align center } } headerWithAnchoredTextbox $docx pagebreak $docx sectionstart \ -defaultHeader $headerWithAnchoredTextbox \ -evenHeader $headerWithAnchoredTextbox $docx paragraph "$loreipsum" $docx paragraph "$loreipsum" $docx paragraph "$loreipsum" $docx paragraph "$loreipsum" $docx paragraph "$loreipsum" $docx sectionend $docx write docx-example2.docx $docx destroy ooxml/examples/bench.tcl000644 000765 000024 00000002015 14764622263 015723 0ustar00alexstaff000000 000000 if 0 { if {[catch { package require ooxml } errMsg]} { if {[catch { source [file join [file dirname [info script]] ../ooxml.tcl] } err2]} { puts $err2 error $errMsg } } } source ../ooxml.tcl proc doit {rows cols} { set spreadsheet [::ooxml::xl_write new -creator "ich"] set sheet [$spreadsheet worksheet "Meine Daten"] set row 0 while {$row < $rows} { set col 0 while {$col < $cols} { $spreadsheet cell $sheet "Cell $row,$col" incr col } $spreadsheet row $sheet incr row } $spreadsheet write "$rows-$cols.xlsx" $spreadsheet destroy } # 10 10 # 100 10 # 500 10 foreach {rows cols} { 1000 10 3000 10 5000 10 } { set msec [lindex [time {doit $rows $cols}] 0] set nrcells [expr {$rows * $cols}] set perCell [expr {$msec / $nrcells}] set seconds [format "%.3f" [expr {double($msec)/1000000}]] puts "$rows/$cols: $nrcells cells, $seconds seconds, $perCell per cell" } ooxml/examples/docx-example1.tcl000775 000765 000024 00000013066 15217572310 017317 0ustar00alexstaff000000 000000 #!/bin/sh #\ exec tclsh "$0" "$@" cd [file dirname [info script]] source ../ooxml.tcl source ../ooxml-docx.tcl source strings.tcl namespace import ::ooxml::docx::docx set docx [docx new] featuresCovered "Text and paragraph formatting." # Set a default style $docx style paragraphdefault -spacing {before 240 after 120} # Add two paragraphs $docx paragraph "A very simple monoton paragraph: $loreipsum" $docx paragraph "The next paragraph: $loreipsum" # What about headings and such? Well, WordprocessingML doesn't really # has a basic concept for that. They are (for now) just another # paragraph with special settings. Let's define a style for heading1: $docx style paragraph Heading1 -fontsize 28 -spacing {before 480 after 240} $docx paragraph "Looks like a Heading" -pstyle Heading1 # Add two paragraphs $docx paragraph "A very simple monoton paragraph: $loreipsum" $docx paragraph "The next paragraph: $loreipsum" # Next Heading $docx paragraph "The next Heading" -pstyle Heading1 # Certain parts of a paragraph may have local formating. This is done # by starting a paragraph and then append to that. $docx paragraph "The start of a paragraph. " $docx append "Another chunk of the paragraph, just with the same formating. " $docx append "This chunk of the paragraph is obviously locally formated." \ -color 0000ff $docx append "You have certain effects already on your hand " foreach textOnOff { bold dstrike italic strike } { $docx append "$textOnOff " -$textOnOff on } $docx append "color " -color 00ff00 foreach text {Serveral kinds of underline} underline { single words double thick dotted } { $docx append "$text $text " -underline $underline } $docx append " or fontsize " -fontsize 18pt $docx append " or highlight color " -highlight green $docx append " superscript " -verticalAlign superscript $docx append " normal text " $docx append " subscript " -verticalAlign subscript $docx append " normal text " $docx append " emboss text " -emboss true $docx append " and you can freely combine them " -fontsize 15pt \ -underline double -color ff0000 $docx append " which isn't so important because using them all would be ugly.\ $loreipsum " $docx mark mymark $docx append "At the start of this sentence is a jump mark. " $docx markstart mymark1 $docx append "The whole sentence is a mark." $docx markend mymark1 # Style heritage: $docx style paragraph Base -color 101010 -fontsize 12pt -font "Arial" $docx style paragraph H1 -basedon Base -fontsize 18pt $docx style paragraph H2 -basedon Base -fontsize 16pt $docx paragraph "Toplevel Heading" -pstyle H1 $docx paragraph "Second Level Heading 1" -pstyle H2 $docx paragraph $loreipsum -pstyle Base $docx paragraph "Second Level Heading 2" -pstyle H2 $docx paragraph $loreipsum -pstyle Base $docx simplecomment "This is ridiculous." -color 00ff00 \ -date 2025-05-29T14:20:00 \ -author "Rolf Ade" $docx paragraph $loreipsum -align both \ -indentation {firstLine 3cm hanging 2cm start 1cm end 4cm} \ -spacing {before 240 after 120} $docx paragraph $loreipsum -leftBorder {type thick borderwidth 20 color 00ff00 space 20} $docx style paragraph withBorder -rightBorder {type thick borderwidth 20 color 00ff00 space 20} $docx paragraph $loreipsum -pstyle withBorder $docx paragraph $loreipsum -pstyle withBorder $docx paragraph "Tabs test $loreipsum" -tabs {3cm 6cm 9cm 12cm} $docx url "link to core.tcl-lang.org" https://core.tcl-lang.org -underline single $docx comment -author "Document Creator" \ -date [clock format [clock seconds] -format %Y-%m-%dT%H:%M:%SZ] \ -initials "dc" { $docx paragraph "You have " $docx append "every" -bold 1 $docx append " local formating at hand to format the comment text." $docx paragraph "Or several paragraphs. Though no tables. Even if the xsd allows them (if I read it right) neither libreoffice nor word grok this (and doesn't allow it via GUI)." -spacing {before 240} } $docx append " " $docx jumpto "This is a link to a place inside the document." mymark -underline double $docx append " " $docx url "The url method also allows mailto links." mailto:pointsman@gmx.net -color 0000ff $docx append " " $docx url "The url method also allows mailto links with pre-set subject." "mailto:pointsman@gmx.net?subject=Feeback to your silly example document" -color 0000ff $docx append " " $docx jumpto "This is a link to a bookmark content inside the document." mymark1 -underline double $docx append " " $docx paragraph "This is a text frame. $loreipsum" -textframe { width 3500 vSpace 300 hSpace 300 wrap auto vAnchor text hAnchor text xAlign inside yAlign inside } $docx style paragraph my_p_style -align both \ -indentation {firstLine 3cm hanging 2cm start 1cm end 4cm} \ -spacing {before 240 after 120} $docx style character my_c_style -highlight green \ -fontsize 15pt \ -underline double \ -color ff0000 $docx paragraph $loreipsum -pstyle my_p_style -cstyle my_c_style $docx pagebreak $docx paragraph "$loreipsum" $docx textbox -dimension {width 3cm height 3cm} \ -anchorData {distL 1cm distR 1cm distT 1cm} \ -positionH page \ -posOffsetH 6cm \ -positionV page \ -posOffsetV 6cm \ -wrapMode square \ -wrapData {wrapText bothSides} { $docx paragraph "First paragraph in a textbox" -spacing {before 0} $docx paragraph "Second paragraph in a textbox" -align center } $docx paragraph "$loreipsum" $docx paragraph "$loreipsum" $docx paragraph "$loreipsum" $docx paragraph "$loreipsum" $docx write docx-example1.docx $docx destroy ooxml/examples/xlsx-complexReadWrite.tcl000755 000765 000024 00000000561 15217572310 021114 0ustar00alexstaff000000 000000 #!/bin/sh #\ exec tclsh "$0" "$@" set auto_path [linsert $auto_path 0 ..] if {[catch {package require ooxml}]} { source ../ooxml.tcl } array set workbook [ooxml::xl_read original_excel.xlsx] set spreadsheet [::ooxml::xl_write new] $spreadsheet presetstyles workbook $spreadsheet presetsheets workbook $spreadsheet write complexReadWrite.xlsx $spreadsheet destroy ooxml/examples/docx-example5.tcl000775 000765 000024 00000004357 15217572310 017326 0ustar00alexstaff000000 000000 #!/bin/sh #\ exec tclsh "$0" "$@" cd [file dirname [info script]] source ../ooxml.tcl source ../ooxml-docx.tcl source strings.tcl namespace import ::ooxml::docx::docx set docx [docx new] featuresCovered "Import numbering styles from another .docx file, defining numbering styles." # Importing numbering definition from another docx $docx import numbering docx-example4-in.docx # Some other random paragraph style definition $docx style paragraph mystyle -color 00FF00 -fontsize 8pt # Use the imported style $docx paragraph "First" -numberingStyle 1 $docx paragraph "Second" -numberingStyle 1 -level 0 $docx paragraph "Sub Second frist" -numberingStyle 1 -level 1 $docx paragraph "Sub Second second" -numberingStyle 1 -level 1 -pstyle mystyle $docx paragraph "Third" -numberingStyle 1 -level 0 # Add some space $docx paragraph "" $docx paragraph "" # Create a numbering definition from scratch $docx numbering abstractNum 3 { { -numberFormat upperRoman -levelText "%1." -start 3 -align start -indentation {start 2cm hanging 0.5cm} -fontsize 18pt } { -numberFormat chicago -levelText "%2" -indentation {start 3cm hanging 0.5cm} -fontsize 8pt } } puts [$docx numbering abstractNumIds] # Use it $docx paragraph "First" -numberingStyle 3 $docx paragraph "Second" -numberingStyle 3 -level 0 $docx paragraph "Sub Second first" -numberingStyle 3 -level 1 #$docx paragraph "Sub Second second" -numberingStyle 3 -level 1 -pstyle mystyle $docx paragraph "Sub Second second" -numberingStyle 3 -level 1 $docx paragraph "Third" -numberingStyle 3 -level 0 $docx numbering abstractNum 4 { { -numberFormat bullet -levelText "" -start 3 -indentation {start 1cm hanging 1.5cm} -font Symbol } { -numberFormat bullet -levelText "/" -indentation {start 2cm hanging 0.5cm} } } $docx paragraph "First $loreipsum" -numberingStyle 4 $docx paragraph "Second" -numberingStyle 4 -level 0 $docx paragraph "Sub Second frist" -numberingStyle 4 -level 1 $docx paragraph "Sub Second second" -numberingStyle 4 -level 1 -pstyle mystyle $docx paragraph "Third" -numberingStyle 4 -level 0 $docx write docx-example5.docx $docx destroy ooxml/examples/docx-example4.tcl000775 000765 000024 00000000573 15217572310 017321 0ustar00alexstaff000000 000000 #!/bin/sh #\ exec tclsh "$0" "$@" cd [file dirname [info script]] source ../ooxml.tcl source ../ooxml-docx.tcl source strings.tcl namespace import ::ooxml::docx::docx set docx [docx new] featuresCovered "Inport styles" $docx import styles docx-example4-in.docx $docx paragraph "Heading" -pstyle "Heading" $docx paragraph $loreipsum $docx write docx-example4.docx $docx destroy ooxml/examples/docx-example6.tcl000775 000765 000024 00000003563 15217572310 017325 0ustar00alexstaff000000 000000 #!/bin/sh #\ exec tclsh "$0" "$@" cd [file dirname [info script]] source ../ooxml.tcl source ../ooxml-docx.tcl source strings.tcl namespace import ::ooxml::docx::docx set docx [docx new] featuresCovered "Images, placing, text flow around." $docx paragraph $loreipsum $docx image book.jpg anchor -anchorData {distL 3cm} -dimension {width 3cm height 3cm} -wrapMode square -wrapData {wrapText bothSides} $docx paragraph $loreipsum $docx image book.jpg anchor -dimension {width 3cm height 3cm} -wrapMode square -wrapData {wrapText left distR 8cm} $docx paragraph $loreipsum $docx image book.jpg anchor -dimension {width 3cm height 3cm} -wrapMode square -wrapData {wrapText right distR 8cm} $docx paragraph $loreipsum $docx image book.jpg anchor -dimension {width 3cm height 3cm} -wrapMode square -wrapData {wrapText largest distR 8cm} $docx append $loreipsum $docx pagebreak $docx paragraph $loreipsum $docx image book.jpg anchor -dimension {width 3cm height 3cm} \ -positionH page \ -posOffsetH 0cm \ -positionV page \ -posOffsetV 0cm \ -wrapMode square \ -wrapData {wrapText bothSides} $docx append $loreipsum $docx image book.jpg anchor -dimension {width 3cm height 3cm} \ -positionH page \ -posOffsetH 3cm \ -positionV page \ -posOffsetV 3cm \ -wrapMode square \ -wrapData {wrapText bothSides} $docx append $loreipsum $docx image book.jpg anchor -dimension {width 3cm height 3cm} \ -positionH page \ -posOffsetH 6cm \ -positionV page \ -posOffsetV 6cm \ -wrapMode square \ -wrapData {wrapText bothSides} $docx append $loreipsum $docx pagebreak $docx paragraph $loreipsum $docx image book.jpg inline -dimension {width 1cm height 1cm} $docx append $loreipsum $docx image book.jpg inline -dimension {width 1cm height 1cm} $docx append $loreipsum $docx write docx-example6.docx $docx destroy ooxml/examples/form8.xlsx000644 000765 000024 00000021254 14764622263 016121 0ustar00alexstaff000000 000000 PK!bh^[Content_Types].xml (N0EHC-Jܲ@5*Q>ēƪc[iiBj7{2hnmƻR U^7/%rZY@1__fqR4DAJh>Vƹ Z9NV8ʩji){^-I"{v^P!XS)bRrKs(3`c07M4ZƐk+|\|z(P6h_-[@!Pk2n}?L %ddN"m,ǞDO97*~ɸ8Oc|nEB!$};{[2PK!U0#L _rels/.rels (MO0 HݐBKwAH!T~I$ݿ'TG~xl/_rels/workbook.xml.rels (RMK0 0wvt/"Uɴ)&!3~*]XK/oyv5+zl;obG s>,8(%"D҆4j0u2jsMY˴S쭂 )fCy I< y!+EfMyk K5=|t G)s墙UtB),fPK!Bxl/workbook.xmlTn0?;d%X bE EqE"Um*MK"rpgfRX'NixPZ\}J>8uΕѐ38z<{s ]JK1'J05hVchxJ_)U\j#$-(k# A,(|W hx \GT5B줒܁RRdBڧp2 t%5X_+a°- ࡗ«Eor!O Cs~ئ^5Ra6 0,{ƒ (& p:]Dv%RF{W. Cnk#-`SeKr$U)e3Ĝl^(_ZsђfȺ@lAҲ QS:8Q<إe˔F ~3k<l_aY{5DnC iǔEc-ڹLJc?9-qDeJ8xlƓQ<_Dy @4Yt kүݽzZP},5`/Zx J>4;=[^j_"J5t)Uծ Fwf LylXeb)bt"IO.fxF]D'.Fx30åJiP 7Q!Kڐ#Nf_yO?GͭUYr;(r~WI>&_שx퓗O?zIw {7Y t؏$"@Cu_FQm2.]%q|5-cøW\dꞜMM\swQb?n-3oPH4 bXB,gMwxD.+rC\.!Ԗon{F]# QCL-7^Fsb!]$# >2q}!!SLc!\29U`w"\C]ĘnfD&3q)L{!‒M7- WӤύ`Wb]Av f"wRvO{'gMAԭԅSI^#PA8r]#ވuvg6{ Kbk &fp-XEԹNi0@ad;1IX({q0gPORvN8p ':gW5Uj6Z漖9e\o_l.[>B\P+tGx{,YM92gs"͠5TΩTO7c:FzX7Q ݺ48t˪P 8tdJNuui=dU DuF蕝M ~eWVQWn^[~dhAy>VqJi79%2H7V[D2H7# #xβleyH-+!7V$rhb2M_p2B?1|g;Bu!: fq!{HD5lGIW@!ڶr5 A' ZJ!;s~Ar8( [Y'vͫ(C8e'I)\ƒ:`}QZ/BVOKyXY᰽5/ϳCx+Ef05mőbJվ[-[0u[•.m6h vydhLIk!Xm$O]CJoe=~3HUD4X~XV,S0zxҤBXD4yșRp'Q:gN3,v~˙,hEs*I$3W(l"cT\rU^pLg$E4gxv'oZJ58hD&MÀz3wL,?Lp+b'JRK K> @$VTdYDsIxM:۝۱̙SM!%TF,/."p5y& =)p>I.B=M ;~=JX׹yu,(aKJ%6|yPTR x]ƣ*e5" \]O?9C&S0SY5c# 6Р }҂:" Ta{*P9vfcm) n06u誜"a-׾Al$ 9d`kӭ ƔgX핁k b{PQםcJ9Ӕ|Z(GMtZK/-8MV_kG>MVʮΠT]Ҳ]WAK~Յj?J5QBd"qc ;8A]? 6m,LwnR#lO $%+~/.)-aTJ[ͤY_fęfVmn޼&PK!QdocProps/core.xml (QK0C{t2K=9(v 6II2MۭV&crr%|/Z( @1ͅy g(*N+ Gh^\^dN6ht '):G[c˶ CyFRfkKpSGq 끈Hd3U C8bu`uSFN)ܡqlzqpMDʹuuU jwg)3@6J0.]PAs`26PK!8ַ docProps/app.xml (n0 n(@VѦzXI{gd:&Kɞolɟ7.0 Y.2& quCdKpc!HRV1"eS!jv!%Y}RƝ Ue ؠgy=qgM`z>zU:k-51P8c={NiJk4AJNS6pF uЯo6V/:4bF_Zȶ@؃hsd]KUܢeں'fJQilА`I)ƲCS )0B8ǙSiehZ$vneE!bcAݦuFכ,k;,_z _x?_oyzIMׯPK-!bh^[Content_Types].xmlPK-!U0#L _rels/.relsPK-!>xl/_rels/workbook.xml.relsPK-!Bxl/workbook.xmlPK-!|;r^ xl/sharedStrings.xmlPK-!X7N w xl/theme/theme1.xmlPK-!L7 xl/styles.xmlPK-!:1 Xxl/worksheets/sheet1.xmlPK-!QdocProps/core.xmlPK-!8ַ GdocProps/app.xmlPK  ooxml/examples/xlsx-writeRowsAutoIncr.tcl000755 000765 000024 00000002430 15217572310 021305 0ustar00alexstaff000000 000000 #!/bin/sh #\ exec tclsh "$0" "$@" set auto_path [linsert $auto_path 0 ..] if {[catch {package require ooxml}]} { source ../ooxml.tcl } source array.tcl set spreadsheet [::ooxml::xl_write new -creator {Alexander Schöpe}] if {[set sheet [$spreadsheet worksheet {Tabelle 1}]] > -1} { set center [$spreadsheet style -horizontal center] set date [$spreadsheet style -numfmt [$spreadsheet numberformat -datetime]] set decimal [$spreadsheet style -numfmt [$spreadsheet numberformat -decimal -separator -red]] set text [$spreadsheet style -numfmt [$spreadsheet numberformat -string]] $spreadsheet column $sheet -width 30 -index 1 $spreadsheet column $sheet -style $decimal -index 4 $spreadsheet column $sheet -style $date -width [::ooxml::CalcColumnWidth 16] $spreadsheet autofilter $sheet 0,0 0,6 $spreadsheet freeze $sheet C2 set lastRow -1 foreach name [lsort -dictionary [array names data]] { lassign [split $name ,] row col if {$row != $lastRow} { set lastRow $row $spreadsheet row $sheet } switch -- $col { 2 { $spreadsheet cell $sheet $data($name) -index $col -string } default { $spreadsheet cell $sheet $data($name) -index $col -globalstyle } } } } $spreadsheet write writeRowsAutoIncr.xlsx $spreadsheet destroy ooxml/examples/docx-example7.tcl000775 000765 000024 00000001660 15217572310 017322 0ustar00alexstaff000000 000000 #!/bin/sh #\ exec tclsh "$0" "$@" cd [file dirname [info script]] source ../ooxml.tcl source ../ooxml-docx.tcl source strings.tcl namespace import ::ooxml::docx::docx set docx [docx new -creator foo -created 2025-02-10] featuresCovered "Fields (page number, author etc.), document configuration." set fields { author createdate date filesize page savedate section time title username } $docx sectionstart $docx paragraph $loreipsum\n foreach field $fields { $docx append "\n" $docx append "$field " $docx field $field } $docx append $loreipsum\n $docx sectionstart $docx paragraph "$loreipsum" $docx field PAGE $docx field SECTION $docx pagebreak $docx paragraph "$loreipsum" $docx field page $docx append " " $docx field date "DATE \\@ \"yyyy-MM-dd\"" -bold 1 -color 0B24F8 $docx configure -creator bar -title "ooxml-docx Example File" $docx write docx-example7.docx $docx destroy ooxml/docxtest_tmp/test_10.docx000644 000765 000024 00000006103 15221665126 017171 0ustar00alexstaff000000 000000 PKN\:j< _rels/.relsMKA !nDH7LvwA&DхR=͛慥;X6-69-l#HkL>Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\ۋrkword/document.xmlN0 y*[ZNmAN'6 vQ;QϿ5'ͤPGEߞwh_0T&6*Q!ƚ'z),cPFB@ _-  ž27 "y(ڻ!)ܥlzCYS8J.m[;^ qMh mPsf4sp"#(ciem k(:ъh['Q+71e"e3ITpsÙsI\ IZYYSOXΛ ~ukh-qV9vYhjmxp:ENz_͟سĴMaxzp/PKN\i~word/_rels/document.xml.rels 0E~EM "M݈Vt6 (|Pąy{].|c$Vht%oKXgtznP^I:LJ:ItRd| L+]oaln:wiD{Q Iєc7B/<;/ |mvPKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tUܝ #WNn|d vNY7i} adpC vk=Ȫ7PKN\nword/styles.xml0 OAz1w}1.Nw![r TE vK~ݝb5g)xk!X=4J.kn#1a3R9ihž,q1B1P(R* |XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\:j< _rels/.relsPKN\ۋrk word/document.xmlPKN\i~ word/_rels/document.xml.relsPKN\ docProps/app.xmlPKN\OabH QdocProps/core.xmlPKN\D Eword/fontTable.xmlPKN\< [Content_Types].xmlPKN\n word/styles.xmlPKN\4Qn word/settings.xmlPK < ooxml/docxtest_tmp/test_47.docx000644 000765 000024 00000007021 15221665127 017204 0ustar00alexstaff000000 000000 PKN\OG9}?word/header1.xmlMn0=>P ?pV޾6M % {>y#֟@VYLXZ`)u[w>kJ^m>gs&c+P.рkRH!`G6OXqوuPRZBʰ5U9K6(:MǺfе;m_N4nTa-?x&?ȓ1=PSob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\uword/document.xmlN0 y*[:!!bYAN)ABӸߎ}7m ْ-9JK0ae_(';6f`Cїـa>L&6C Yr-y,v ۀPPBF{OTk#˰ЪdVWe;F D~\PKN\~0word/_rels/document.xml.rels 0E~EM""nDVt6 ( ]y{dt-;(Zѕ}/`V;l%_7ֳ.9NXԡSI UJuIϹ{Óe )FƨSDpO}>8JW! (?24ryhE,z$ o~{lHep# PKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tU:0i69nO+B.Kn,`= ?ZG# t|PKN\nword/styles.xml0 OAz1w}1.Nw![r TE vK~ݝb5g)xk!X=4J.kn#1a3R9ihž,q1B1P(R* |XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\OG9}? word/header1.xmlPKN\:j< m_rels/.relsPKN\u mword/document.xmlPKN\~0 word/_rels/document.xml.relsPKN\ docProps/app.xmlPKN\OabH docProps/core.xmlPKN\D word/fontTable.xmlPKN\Q@Gw [Content_Types].xmlPKN\n word/styles.xmlPKN\4Qn e word/settings.xmlPK z ooxml/docxtest_tmp/test_30.docx000644 000765 000024 00000006124 15221665127 017177 0ustar00alexstaff000000 000000 PKN\:j< _rels/.relsMKA !nDH7LvwA&DхR=͛慥;X6-69-l#HkL>Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\KH|pword/document.xmlo W4k,Kceo&nRڒGb s;ŗс32&$A!t,ykm&#s&cj:*n d$ϱB٣N{D `t*fP$BV! A.󭲵0v.qPrkf冦"5B ͏$ceeϛ%gmM i}W9-ZEsoBnj?GQT6^8xҷJҝ(S?KrvP5`l]DMz2#LrįJ!rN._۵ع\@[hH1Z\o.˙`ӕG PKN\i~word/_rels/document.xml.rels 0E~EM "M݈Vt6 (|Pąy{].|c$Vht%oKXgtznP^I:LJ:ItRd| L+]oaln:wiD{Q Iєc7B/<;/ |mvPKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tUܝ #WNn|d vNY7i} adpC vk=Ȫ7PKN\nword/styles.xml0 OAz1w}1.Nw![r TE vK~ݝb5g)xk!X=4J.kn#1a3R9ihž,q1B1P(R* |XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\:j< _rels/.relsPKN\KH|p word/document.xmlPKN\i~ word/_rels/document.xml.relsPKN\ docProps/app.xmlPKN\OabH bdocProps/core.xmlPKN\D Vword/fontTable.xmlPKN\< [Content_Types].xmlPKN\n word/styles.xmlPKN\4Qn word/settings.xmlPK < ooxml/docxtest_tmp/test_67.docx000644 000765 000024 00000006042 15221665127 017210 0ustar00alexstaff000000 000000 PKN\:j< _rels/.relsMKA !nDH7LvwA&DхR=͛慥;X6-69-l#HkL>Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\kJword/document.xmlJ0}-HY;x'ilrI7G'H.z69|~&:tFuL"9RWxZ=m~xvo62R;gRJ-bv Fh?W*'V, zjmSŤ&2ҢNJI`t+*\ ءl|j m]=BR9#🉃ju]/B:GSߝ&gdvO$>̈V]G{Fht|[5!1b/鎽YTrw.ㅃW<}4 7"#uT$k1& ;Cž+iJ˙PKN\i~word/_rels/document.xml.rels 0E~EM "M݈Vt6 (|Pąy{].|c$Vht%oKXgtznP^I:LJ:ItRd| L+]oaln:wiD{Q Iєc7B/<;/ |mvPKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tUܝ #WNn|d vNY7i} adpC vk=Ȫ7PKN\nword/styles.xml0 OAz1w}1.Nw![r TE vK~ݝb5g)xk!X=4J.kn#1a3R9ihž,q1B1P(R* |XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\:j< _rels/.relsPKN\kJ word/document.xmlPKN\i~ yword/_rels/document.xml.relsPKN\ wdocProps/app.xmlPKN\OabH 0docProps/core.xmlPKN\D $word/fontTable.xmlPKN\< g[Content_Types].xmlPKN\n word/styles.xmlPKN\4Qn word/settings.xmlPK < ooxml/docxtest_tmp/test_71.docx000644 000765 000024 00000006040 15221665127 017201 0ustar00alexstaff000000 000000 PKN\:j< _rels/.relsMKA !nDH7LvwA&DхR=͛慥;X6-69-l#HkL>Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\ NHword/document.xmln0 { ; L4B/զ&{4F e}%Ij8/+͗j@+A$]%$C)usD6ݺJE@۬I(}TOiX.<$yIMF CXI`r1AUI.ePK>lGӱ x-E˜6؉vj}},h7v0Kv}{JDy2ƶaF̴6 BgΣKU ?;3~{JwE:^kپ9(%X{(a5!` 4CVptq*,PKN\i~word/_rels/document.xml.rels 0E~EM "M݈Vt6 (|Pąy{].|c$Vht%oKXgtznP^I:LJ:ItRd| L+]oaln:wiD{Q Iєc7B/<;/ |mvPKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tUܝ #WNn|d vNY7i} adpC vk=Ȫ7PKN\nword/styles.xml0 OAz1w}1.Nw![r TE vK~ݝb5g)xk!X=4J.kn#1a3R9ihž,q1B1P(R* |XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\:j< _rels/.relsPKN\ NH word/document.xmlPKN\i~ wword/_rels/document.xml.relsPKN\ udocProps/app.xmlPKN\OabH .docProps/core.xmlPKN\D "word/fontTable.xmlPKN\< e[Content_Types].xmlPKN\n word/styles.xmlPKN\4Qn word/settings.xmlPK < ooxml/docxtest_tmp/test_26.docx000644 000765 000024 00000006154 15221665126 017206 0ustar00alexstaff000000 000000 PKN\:j< _rels/.relsMKA !nDH7LvwA&DхR=͛慥;X6-69-l#HkL>Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\ word/document.xmlTQK0~WomEDAP@fm0ɅK:I۬ځYȅ|w;ۻO%G+@$_f$A%t]ܭ.n*]-4Ι"M-kv k* z>%,N4Pu1r,`n@ -fS.Rƒ㵮$x. rI6ȶ1˳ 2)VHVapNPҗ1ݳx<6#Bket(~&(f(6B ʯW\+j H7%:oj,Yjv 6IW1?EX@0bu1+W(#ֈ~s)m0=tVϭtb1*^˙{!q'~?oPKN\i~word/_rels/document.xml.rels 0E~EM "M݈Vt6 (|Pąy{].|c$Vht%oKXgtznP^I:LJ:ItRd| L+]oaln:wiD{Q Iєc7B/<;/ |mvPKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tUܝ #WNn|d vNY7i} adpC vk=Ȫ7PKN\nword/styles.xml0 OAz1w}1.Nw![r TE vK~ݝb5g)xk!X=4J.kn#1a3R9ihž,q1B1P(R* |XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\:j< _rels/.relsPKN\  word/document.xmlPKN\i~ word/_rels/document.xml.relsPKN\ docProps/app.xmlPKN\OabH zdocProps/core.xmlPKN\D nword/fontTable.xmlPKN\< [Content_Types].xmlPKN\n word/styles.xmlPKN\4Qn word/settings.xmlPK < ooxml/docxtest_tmp/test_7.docx000644 000765 000024 00000006232 15221665126 017122 0ustar00alexstaff000000 000000 PKN\:j< _rels/.relsMKA !nDH7LvwA&DхR=͛慥;X6-69-l#HkL>Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\Z/Pword/document.xmln ),*NMw} o 7ۢ `3F+Er`rP9Z-1JPrUnq6n۬H\,M-$v )#KS-RZϓ"]c|J0ƨl`,$,݂` Ә!c^ܧ׺zB yl͵iϊ8H1Ƶ+Qn0픡c=w?$ce ew[&Mg>T+ymtpLV\p>Z]LܳB%+ȃ,U@f OT$mv Jv=IOnD6\ݍ"Ϩ#8n3RQ/dFph+;CQ`Fƻs6D ;@{ΔcίufJZ^_ { -N??PKN\i~word/_rels/document.xml.rels 0E~EM "M݈Vt6 (|Pąy{].|c$Vht%oKXgtznP^I:LJ:ItRd| L+]oaln:wiD{Q Iєc7B/<;/ |mvPKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tUܝ #WNn|d vNY7i} adpC vk=Ȫ7PKN\nword/styles.xml0 OAz1w}1.Nw![r TE vK~ݝb5g)xk!X=4J.kn#1a3R9ihž,q1B1P(R* |XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\:j< _rels/.relsPKN\Z/P word/document.xmlPKN\i~ word/_rels/document.xml.relsPKN\ docProps/app.xmlPKN\OabH docProps/core.xmlPKN\D word/fontTable.xmlPKN\< [Content_Types].xmlPKN\n Lword/styles.xmlPKN\4Qn , word/settings.xmlPK <H ooxml/docxtest_tmp/test_6.docx000644 000765 000024 00000006122 15221665126 017117 0ustar00alexstaff000000 000000 PKN\:j< _rels/.relsMKA !nDH7LvwA&DхR=͛慥;X6-69-l#HkL>Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\izword/document.xmlQo0)Hߵ,Bf\4PKf\ oA[$_S/UE@+Ad6I$4\"%,yk%|I9Pjy)S0Bb-`nTE*&51u3&Jr ;7$2Ԙ)˾a[Wbηʖ؁'QrCӎfL9Gϻ<,Xԗ(7/x%3D+n x|Z6cVV;᧢fUuٳxO^ ȶHE:o Z| qٛs>Κ\wnI*s l#]iaT^@M8Tjn%EX{ɾPKN\i~word/_rels/document.xml.rels 0E~EM "M݈Vt6 (|Pąy{].|c$Vht%oKXgtznP^I:LJ:ItRd| L+]oaln:wiD{Q Iєc7B/<;/ |mvPKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tUܝ #WNn|d vNY7i} adpC vk=Ȫ7PKN\nword/styles.xml0 OAz1w}1.Nw![r TE vK~ݝb5g)xk!X=4J.kn#1a3R9ihž,q1B1P(R* |XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\:j< _rels/.relsPKN\iz word/document.xmlPKN\i~ word/_rels/document.xml.relsPKN\ docProps/app.xmlPKN\OabH `docProps/core.xmlPKN\D Tword/fontTable.xmlPKN\< [Content_Types].xmlPKN\n word/styles.xmlPKN\4Qn word/settings.xmlPK < ooxml/docxtest_tmp/test_27.docx000644 000765 000024 00000006056 15221665126 017210 0ustar00alexstaff000000 000000 PKN\:j< _rels/.relsMKA !nDH7LvwA&DхR=͛慥;X6-69-l#HkL>Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\sHword/document.xmlN0} `1d,LJFӜޖGgbv)p~wK5A3c ͡lM[%|i9Rjy-k0B\ X0\Xyq|O H:+%9ҭ8Rr1,cZrd7HuK!(UƎMT3%viSY"@Sr&?I)g1ӪhF˗t~&8f(7>JSue0xӗJ}#2AQPCKrPjB\64}Vp8jPKN\i~word/_rels/document.xml.rels 0E~EM "M݈Vt6 (|Pąy{].|c$Vht%oKXgtznP^I:LJ:ItRd| L+]oaln:wiD{Q Iєc7B/<;/ |mvPKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tUܝ #WNn|d vNY7i} adpC vk=Ȫ7PKN\nword/styles.xml0 OAz1w}1.Nw![r TE vK~ݝb5g)xk!X=4J.kn#1a3R9ihž,q1B1P(R* |Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\ NHword/document.xmln0 { ; L4B/զ&{4F e}%Ij8/+͗j@+A$]%$C)usD6ݺJE@۬I(}TOiX.<$yIMF CXI`r1AUI.ePK>lGӱ x-E˜6؉vj}},h7v0Kv}{JDy2ƶaF̴6 BgΣKU ?;3~{JwE:^kپ9(%X{(a5!` 4CVptq*,PKN\i~word/_rels/document.xml.rels 0E~EM "M݈Vt6 (|Pąy{].|c$Vht%oKXgtznP^I:LJ:ItRd| L+]oaln:wiD{Q Iєc7B/<;/ |mvPKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tUܝ #WNn|d vNY7i} adpC vk=Ȫ7PKN\nword/styles.xml0 OAz1w}1.Nw![r TE vK~ݝb5g)xk!X=4J.kn#1a3R9ihž,q1B1P(R* |XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\:j< _rels/.relsPKN\ NH word/document.xmlPKN\i~ wword/_rels/document.xml.relsPKN\ udocProps/app.xmlPKN\OabH .docProps/core.xmlPKN\D "word/fontTable.xmlPKN\< e[Content_Types].xmlPKN\n word/styles.xmlPKN\4Qn word/settings.xmlPK < ooxml/docxtest_tmp/test_66.docx000644 000765 000024 00000006161 15221665127 017211 0ustar00alexstaff000000 000000 PKN\:j< _rels/.relsMKA !nDH7LvwA&DхR=͛慥;X6-69-l#HkL>Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\q'word/document.xmlώ0w-lfC/f76qjɴQ7=0M~~3.WY Z%$$u&T;Y/64%(xq9Sjy ٹ6|.([,h139XyaF% U<0fRpVnƵu 2*=$x+G> A󭲥0v5j%'<ۘ{C=-V6LçqDGPKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tUܝ #WNn|d vNY7i} adpC vk=Ȫ7PKN\nword/styles.xml0 OAz1w}1.Nw![r TE vK~ݝb5g)xk!X=4J.kn#1a3R9ihž,q1B1P(R* |XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\:j< _rels/.relsPKN\q' word/document.xmlPKN\@@ word/_rels/document.xml.relsPKN\ docProps/app.xmlPKN\OabH docProps/core.xmlPKN\D sword/fontTable.xmlPKN\< [Content_Types].xmlPKN\n #word/styles.xmlPKN\4Qn  word/settings.xmlPK < ooxml/docxtest_tmp/test_31.docx000644 000765 000024 00000026241 15221665127 017202 0ustar00alexstaff000000 000000 PKN\:j< _rels/.relsMKA !nDH7LvwA&DхR=͛慥;X6-69-l#HkL>Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\Dword/fontTable.xmlN0<;uBQ qB=wXO51}{\'PPox񬷟F=)g+\Gܭc8%2V + ٢Zm5O":켓Ȟx壍5AB Lot, V ado΀ق'hz/ .;0JT4+5^VbϦvz5)IQߢzU5\6ۣWM|~--o]d`i.qTxPKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\%"Uword/_rels/document.xml.relsR0>vtƩ dJ~&I괙.'p r/ Z$O3*5.vF%%xri7ϔ\ (\hkjXe5IM{ʼng+d}0p*Q‹.w?A?Б|A9EBObWZ5۴0]{q J>& XR!&D9O ڏ9ɶBmGC_3i,5="*vp ӎ~PKO1!@ Bȳ ?K#^ 2D=9S{<5!_z~^俴PKN\kʹCword/numbering.xmlSKN0s ĉEMBZ'K 8'QJ73ًN5%ӌ$`mٔi%b158T_ %نz}j[0=[ym`]:+{TjEYPͥ!klk0K\QBJQ,">p/nG!5W k؍eD{Fq~qsvu9ugQN)G_OW՘ۙ4 D7YƦ2:PKN\Mword/endnotes.xmln0} ]CTEZ%JC.I^3UL=FƨH-33!G2c6$8mk s!@Klltv$j^& FmXM7{\U?y ?AاQ,/ Nx/V@/݃Z2&[RmŔmŖ|uD7:yD%y:krj;: A&q#b' MMd)ϻ n"yn0&lޟ5Ŧ(ib^AgO~PKN\nut<Bword/styles.xmlr0} FXabgOzfZZ$O_ -a:G\"hCd,K*s9:7vˈtaz*kU "y+9nװTZbbL8Q2(()ȕ`ɡ\(&M)w{7Wu8>'GF]z YZPF "ZH F&ӎ5sUNUHFZf@O~FSՓ_0ho½SI{9RdRpZS^n5[ sgDQ{ʑi= 0?>}~Ȏ'AI~|.KړڥyvI^loDs`Tdƿhc~H -D2@#BD7t>M j,Ҷގ+/F?#W25[gj)A ߱/M0eYnz. ")6}%V {o( l^>?kZ.չ  a?MwePKN\9[Content_Types].xmlN0E|E-Jܲ@5(kړ"~vK6B̽ȉ2mel:UQb U1IgӋbg%ث\78I] (JVPF+ W5aZyP>#N'[pIwb@Tb^d 4My)[[vZb{W94u`⵽E}MYZDU~Ssͥ3-Z{?JK1C_R)ecEHDz=B}ёv_EqAih whgϧy8 yҘGyFZ6V\ҭ341b'G۬^utZ_cTYdC?uE}ܝV<ƻu   [^rOr.L`8:hfRLpSNG\fBޙ7@ L@LE P~`FVÄÄ▛DDG8kZPKN\@ :-3@[lO(*`3k$`1Z*9Zh$0Y%΄l4H)a}}oS3m< #!1APY!擤 )$Je{wgWHݿnt7Iۛ0 c&~jypoɞ/$d& R{Hxq7b!Um C9t&BS 腁uBʣVJF4^ܓB~pO cO"l69N!gl(#"%"Y@5Jx2jEB 7l5%w^┢*aF*:[zٔnJyzM NbX ][#Tgn:[v| #!"Qp,W i~6`d7~뀵o?99eT'&=Ӧmr)QN%NFTRO3INMh\ϳ}nt inV㞚;5,$IH|IׄL 8+!b\y009Nh=aHSk?YJK~͞}( ]{yZt =Ԇ- 1y/Yݝ7Ve::sOx$.6[Ǟ{\GD0$s>qTD z ygF?è҇ӹ>U)eSBmexǺ!#;7db(L19fW$QL9V+cr#*Uj0,U1 ԛ[OVv©`M.PxTaAl4p:`1?xmk*+m|kxB 6#O"MMa´FB:(>mI\ c8 }& '̮Y!I2V#'CP0 &a X5@92?OO,֮У_BW{YcWkg&y)tw@zwW D_F~ F%a3iifɉ= c"&ĭyem5cH >C.-lքb҃\ t j.̽ |c#Rsi^4fggfh44oiKn vIFIpgADDlG@OD$" O?+m cGv䔳_÷'{3AKW14ul(`Ya=lWkKfԟçj8=YU^m˓U 9`H|]NvD!1߿H{3O X#q'rD =7 ȍYOM6)ZSrc[&B@ x q:>W)J MŹ15f e jΌ׻ϡ(k>vW n3]e@Ac&qgvJ+SrوG̑}Ecti[賨vLd. RgR, .u*E@33keu>郝W&gCKh8ǿHy!ŘdqXCJV6ؚ͜V?jjw*Pa+nosRք8^֚ة*֩3gw1VDji_l-S G kc3&w6`䊛_c9z5sbq n5ם5"bd;O}sWJ)E&*Rla۰,jqs Kƽ1>|\okn,_v?3DS]1NsÝ|ՀSP34(Ỏqv!@KkYC ) :P vC.1x*}=yԏ=eF *22RXʈ xLSUx##%!qD ऊ0[+C{1Ni-ﮏM@ X/Bcj>7 M{sɫBjP+6ə/N$om7T. ?x$,ʖjJ_9讚~tO]$'Xx>àn_7\~~(umavuM5gʠ$$;d,` ui#rdw{S\./+͔[QF)΢xWs rg-"ڴ!ŋaa`o awT#PzZŁ`]QyKHf-;!̑IK{e(Ť_SZ5f_;4Fy/e kdI1rJxgCnٯ?un į^6m$/JTfEyUe:_EZ^Xo@X&'dtKᆫ ׿XaЦ3j;Sskly%c^IrUfƕļ&@M!ԢMz;Bs|K}lP/Qm J:DH/D_sˍGJpe+`yA" Ӥ^5( @D 8*oe@D$jm3իʫw!^xhM.Y 񱥏v].!OGOW'd E:DgIPKN\( word/footer1.xmlTn0}W *B%mԇV-h셤__& %j}9cՓl 2c\6]Z:r,usIニ,Ð98Iw8Q#h?iPKN\Rpword/footnotes.xmln0} B.Q\ƀUҼ}mF-I 柱}{riʴ%tJoOh/CI;mJ} >b"\]g2t@Ibb h%3/)w e}7C=qVSʹӿ8~lCihK"F>\ϩ߽8Dr2GJيq+ϴco.[+t9 6Mƭ8^Tg>^x-c/KA$"Cmrr%U4l2fgث`+.`"^ld|uV"^}p "}oQqOKy@jZ41]I#qZ qoPKN\¨O?Dword/media/image1.png sb``p Ҍ $0)nOǐ[30331_Z ftsYPKN\¨O?Dword/media/image2.png sb``p Ҍ $0)nOǐ[30331_Z ftsYPKN\:j< _rels/.relsPKN\D word/fontTable.xmlPKN\ CdocProps/app.xmlPKN\%"U word/_rels/document.xml.relsPKN\kʹC word/numbering.xmlPKN\M word/endnotes.xmlPKN\lמ word/settings.xmlPKN\7x- word/header1.xmlPKN\nut<B l word/styles.xmlPKN\9 [Content_Types].xmlPKN\S. word/comments.xmlPKN\@Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\L?*eword/document.xmlj0 {{d1B^ʶ u_NҾףּCdf{"XUuθ*zAaęd>AٸIP霉1dص6Ly_ÀZϓ?3+4`t*PXINA[2y)1C.)ܧcYWLGeKnHkbkpAЦ Dh1SΙh 'k/chx^^%1l@WfZ-]ҭ$UvbƯwYTtk/i/r,A)gQ뤳K{"X5 K응.N7x K,pZBl#,}f_7~PKN\i~word/_rels/document.xml.rels 0E~EM "M݈Vt6 (|Pąy{].|c$Vht%oKXgtznP^I:LJ:ItRd| L+]oaln:wiD{Q Iєc7B/<;/ |mvPKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tUܝ #WNn|d vNY7i} adpC vk=Ȫ7PKN\d`(word/styles.xmlAN0E"uRBQ.ݱ8Xk45$̟?_^o߭ IXYFb/ϻnCIhe*ևKI ZW.Z@+Bl`"iUr+c)Y-ڰ`9jE>U֤+bE"Z ˬ,Q ǫN$tGWI64~g9# %O/Ov}Ag `vXLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\:j< _rels/.relsPKN\L?*e word/document.xmlPKN\i~ word/_rels/document.xml.relsPKN\ docProps/app.xmlPKN\OabH KdocProps/core.xmlPKN\D ?word/fontTable.xmlPKN\< [Content_Types].xmlPKN\d`( word/styles.xmlPKN\4Qn D word/settings.xmlPK <` ooxml/docxtest_tmp/test_11.docx000644 000765 000024 00000006112 15221665126 017172 0ustar00alexstaff000000 000000 PKN\:j< _rels/.relsMKA !nDH7LvwA&DхR=͛慥;X6-69-l#HkL>Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\R,rword/document.xml]O0[c`QLJF2[l6=o'/ͤP0G)yֳ;uJRq*gƨcM = .cZB@_- U Ž1㌀233"y(ڥO9mYucMC\21*]0{!v03mPS?}9r12Hie J WKLsL٫زfQTps}㹋$|΅d[YِG~X[~le^w ]Cʅv/K.BUAeӎz:|2<8)17PKN\i~word/_rels/document.xml.rels 0E~EM "M݈Vt6 (|Pąy{].|c$Vht%oKXgtznP^I:LJ:ItRd| L+]oaln:wiD{Q Iєc7B/<;/ |mvPKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tUܝ #WNn|d vNY7i} adpC vk=Ȫ7PKN\nword/styles.xml0 OAz1w}1.Nw![r TE vK~ݝb5g)xk!X=4J.kn#1a3R9ihž,q1B1P(R* |XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\:j< _rels/.relsPKN\R,r word/document.xmlPKN\i~ word/_rels/document.xml.relsPKN\ docProps/app.xmlPKN\OabH XdocProps/core.xmlPKN\D Lword/fontTable.xmlPKN\< [Content_Types].xmlPKN\n word/styles.xmlPKN\4Qn word/settings.xmlPK < ooxml/docxtest_tmp/test_50.docx000644 000765 000024 00000007007 15221665127 017202 0ustar00alexstaff000000 000000 PKN\:j< _rels/.relsMKA !nDH7LvwA&DхR=͛慥;X6-69-l#HkL>Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\֫7x j߆2ci%J 3XD'Rm:<_xɢ}4Фq@gK 8XNO~7~^ҜG~5&"?:?wfcNLZ"1E%rܺ`QF9PSNvgP;hP*RdFZ(݌ttOf|VNzϚ@U9f g3tSpZ 㐔<@e‘MW;Vx1C_C9?Y%bXr1w 6D&c=q-/ Qӂ'Ӌ>}O-Nf'Ƣ%2PKN\^Ѽword/_rels/document.xml.rels݊0}06ʲ7R 4F\ɜ11TE qZ~ºqބKz<LrJePKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tUEۋ Y/\_u#ig>PKN\nword/styles.xml0 OAz1w}1.Nw![r TE vK~ݝb5g)xk!X=4J.kn#1a3R9ihž,q1B1P(R* |XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\¨O?Dword/media/image1.png sb``p Ҍ $0)nOǐ[30331_Z ftsYPKN\:j< _rels/.relsPKN\Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\L?*eword/document.xmlj0 {{d1B^ʶ u_NҾףּCdf{"XUuθ*zAaęd>AٸIP霉1dص6Ly_ÀZϓ?3+4`t*PXINA[2y)1C.)ܧcYWLGeKnHkbkpAЦ Dh1SΙh 'k/chx^^%1l@WfZ-]ҭ$UvbƯwYTtk/i/r,A)gQ뤳K{"X5 K응.N7x K,pZBl#,}f_7~PKN\i~word/_rels/document.xml.rels 0E~EM "M݈Vt6 (|Pąy{].|c$Vht%oKXgtznP^I:LJ:ItRd| L+]oaln:wiD{Q Iєc7B/<;/ |mvPKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tUܝ #WNn|d vNY7i} adpC vk=Ȫ7PKN\d`(word/styles.xmlAN0E"uRBQ.ݱ8Xk45$̟?_^o߭ IXYFb/ϻnCIhe*ևKI ZW.Z@+Bl`"iUr+c)Y-ڰ`9jE>U֤+bE"Z ˬ,Q ǫN$tGWI64~g9# %O/Ov}Ag `vXLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\:j< _rels/.relsPKN\L?*e word/document.xmlPKN\i~ word/_rels/document.xml.relsPKN\ docProps/app.xmlPKN\OabH KdocProps/core.xmlPKN\D ?word/fontTable.xmlPKN\< [Content_Types].xmlPKN\d`( word/styles.xmlPKN\4Qn D word/settings.xmlPK <` ooxml/docxtest_tmp/test_61.docx000644 000765 000024 00000007034 15221665127 017204 0ustar00alexstaff000000 000000 PKN\zA]word/comments.xmlN0 2VJ0 jt9Ե`|MjICX4Oi};A%* &"JN,]Pnh1,ZYڟw׷͙ 2b1=Pg>Ӛh:s-[R3cGRYTvw] W,i4X :4 ~Ê\T :x:x-m} T@ ƗyN?]PKN\:j< _rels/.relsMKA !nDH7LvwA&DхR=͛慥;X6-69-l#HkL>Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\\word/document.xmln0 { {iB^MM[i| }9-['M=ۉWj'HI$47UF>ϋ'V]Z*}ڥ]FjmJP-}<~BE;ÅsS GԤǘӞPq nTjRr/C%i}=@Zylum_{ $Qnha-u?뛳s"?Qee(K Gͬhm0ϩV1jmţFITp˞] xZil׈ ( T8`Lq V`a`pE)TD]* [B93ioPKN\~word/_rels/document.xml.relsMj09},'-ل=*miRWM1]x9o4}f}`Y,VZV[uZ¡XKJOb}diFqUFyӸ`$2Ku-m0P`?ޮi£SW&"xǘeh|Y>]2q*4(x ?ʙyPKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tUXLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\zA] word/comments.xmlPKN\:j< _rels/.relsPKN\\ word/document.xmlPKN\~ word/_rels/document.xml.relsPKN\ 'docProps/app.xmlPKN\OabH docProps/core.xmlPKN\D word/fontTable.xmlPKN\<ͯ\Gz [Content_Types].xmlPKN\n word/styles.xmlPKN\4Qn o word/settings.xmlPK { ooxml/docxtest_tmp/test_77.docx000644 000765 000024 00000006050 15221665127 017210 0ustar00alexstaff000000 000000 PKN\:j< _rels/.relsMKA !nDH7LvwA&DхR=͛慥;X6-69-l#HkL>Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\jrPword/document.xmln0 { {iB^MMiđK(} %&ͻj@+Ag$Y$C!uח=7.-Jhm.#s&Z(f`w%bo`aTCWq|G H: %9-8Rr1,c$i]=BR9*[KcG"$Qnh9Z >k׷ˉh 2^PvO${Кhj÷ք?l;OT}e0x]پ(%X{(a5`0.9%kޚ}WZN9PKN\i~word/_rels/document.xml.rels 0E~EM "M݈Vt6 (|Pąy{].|c$Vht%oKXgtznP^I:LJ:ItRd| L+]oaln:wiD{Q Iєc7B/<;/ |mvPKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tUܝ #WNn|d vNY7i} adpC vk=Ȫ7PKN\nword/styles.xml0 OAz1w}1.Nw![r TE vK~ݝb5g)xk!X=4J.kn#1a3R9ihž,q1B1P(R* |XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\:j< _rels/.relsPKN\jrP word/document.xmlPKN\i~ word/_rels/document.xml.relsPKN\ }docProps/app.xmlPKN\OabH 6docProps/core.xmlPKN\D *word/fontTable.xmlPKN\< m[Content_Types].xmlPKN\n word/styles.xmlPKN\4Qn word/settings.xmlPK < ooxml/docxtest_tmp/test_20.docx000644 000765 000024 00000006133 15221665126 017175 0ustar00alexstaff000000 000000 PKN\:j< _rels/.relsMKA !nDH7LvwA&DхR=͛慥;X6-69-l#HkL>Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\l eword/document.xmlN0 }| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tUܝ #WNn|d vNY7i} adpC vk=Ȫ7PKN\nword/styles.xml0 OAz1w}1.Nw![r TE vK~ݝb5g)xk!X=4J.kn#1a3R9ihž,q1B1P(R* |XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\:j< _rels/.relsPKN\l e word/document.xmlPKN\i~ word/_rels/document.xml.relsPKN\ docProps/app.xmlPKN\OabH idocProps/core.xmlPKN\D ]word/fontTable.xmlPKN\< [Content_Types].xmlPKN\n word/styles.xmlPKN\4Qn word/settings.xmlPK < ooxml/docxtest_tmp/test_1.docx000644 000765 000024 00000006040 15221665126 017111 0ustar00alexstaff000000 000000 PKN\:j< _rels/.relsMKA !nDH7LvwA&DхR=͛慥;X6-69-l#HkL>Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\ NHword/document.xmln0 { ; L4B/զ&{4F e}%Ij8/+͗j@+A$]%$C)usD6ݺJE@۬I(}TOiX.<$yIMF CXI`r1AUI.ePK>lGӱ x-E˜6؉vj}},h7v0Kv}{JDy2ƶaF̴6 BgΣKU ?;3~{JwE:^kپ9(%X{(a5!` 4CVptq*,PKN\i~word/_rels/document.xml.rels 0E~EM "M݈Vt6 (|Pąy{].|c$Vht%oKXgtznP^I:LJ:ItRd| L+]oaln:wiD{Q Iєc7B/<;/ |mvPKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tUܝ #WNn|d vNY7i} adpC vk=Ȫ7PKN\nword/styles.xml0 OAz1w}1.Nw![r TE vK~ݝb5g)xk!X=4J.kn#1a3R9ihž,q1B1P(R* |XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\:j< _rels/.relsPKN\ NH word/document.xmlPKN\i~ wword/_rels/document.xml.relsPKN\ udocProps/app.xmlPKN\OabH .docProps/core.xmlPKN\D "word/fontTable.xmlPKN\< e[Content_Types].xmlPKN\n word/styles.xmlPKN\4Qn word/settings.xmlPK < ooxml/docxtest_tmp/test_49.png000644 000765 000024 00000000104 15221665127 017030 0ustar00alexstaff000000 000000 PNG  IHDR  IDATxc}IENDB`ooxml/docxtest_tmp/test_57.docx000644 000765 000024 00000007072 15221665127 017213 0ustar00alexstaff000000 000000 PKN\:j< _rels/.relsMKA !nDH7LvwA&DхR=͛慥;X6-69-l#HkL>Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\]word/document.xmln0 { {iB^MM[iđJKZ>!M=ۖכj@+Ag$Y$C!ulu[%|i9Rjy-K0B{_ X0\Xy8~IMz dEBT e)!BI|  x-EÜo_ $Qnha-uۋs"?Q>S}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tUP U7]4ǀUl&ګZ WKL+ߘrWvQTxn4y+$hX()cPvgMbe&4r.OQ)o7CV6GE0ix;mO\Lb`] N{dPKN\4Qnword/settings.xmlePn0 +#[zv`J$G)~aq{ӷhId4%|ί8/ǩȜ1KIB+!ѪGUpcAE&2fSP# C=%LlS7\*y/>XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\:j< _rels/.relsPKN\] word/document.xmlPKN\:Y word/_rels/document.xml.relsPKN\ docProps/app.xmlPKN\OabH UdocProps/core.xmlPKN\D Iword/fontTable.xmlPKN\G| [Content_Types].xmlPKN\n word/styles.xmlPKN\cPx word/footnotes.xmlPKN\4Qn word/settings.xmlPK | ooxml/docxtest_tmp/test_16.docx000644 000765 000024 00000010066 15221665126 017202 0ustar00alexstaff000000 000000 PKN\:j< _rels/.relsMKA !nDH7LvwA&DхR=͛慥;X6-69-l#HkL>Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\@b!word/document.xmln0 { {ZMӄ Tvh0đJKZhNP{bmˋN5J)McXH]c4ydn%Vv6RV;gέAv+T'UC* k=O5|\R)kI'=c X@`YJ1D1!^4󭲵4vm*b# M;E1B ʻoL'S//@Y|{sgZu홰5ъ1ժ>[:f(6n(,jv˞] W"y4Ri euT,bN 5܂`tS":ޠ{ Q"es/^=PKN\&word/_rels/document.xml.relsj0} ZNC)s)\!6!y ڤN w$|j>:`EBr\u(_`]ܭ[IWbZut-6fIaho6y+O MU<Ǜsn? ɍcL64(,3f~Kp fE.-(SB,M\)9!? g匠xPKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tU6ٴ L IU֪cC+& A1bhA{%nAJe8: \)jLzJp@aWDE)oCX\&VD_ Ѭ&Ie*@;QC^G jɠ&};'hWDV^G{Шhm)w^s{oje<&ϥM5K~:gJwM?V&\ahbA#y.Mypwa<~R˦zů yz/!كCg}PKN\SP[Content_Types].xmlN0E|E-J\X vc ]52Hl3-3n!ԔGLf;qUSgKh+E18uR6NO/ oUe]u .SZsIgDP (UM{=mBsHJ% y3GiA(#0I!LvӪM +2 i6E*Њ bBPLXZ뎺-\i5^F Kc EIXN5(삂H(8eksJ6@j{!ĺ]+38zkhƸ~ic#4פ߭oN3C2B'8^Mx(v44jZ:gZAwƔ==vEϏ>xAR&ȁΙ=eV&\ahbA#y.Oypwa|]S˦w& =q9!Vl낡w-.&PKN\4Qnword/settings.xmlePn0 +#[zv`J$G)~aq{ӷhId4%|ί8/ǩȜ1KIB+!ѪGUpcAE&2fSP# C=%LlS7\*y/>XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\:j< _rels/.relsPKN\@b! word/document.xmlPKN\& word/_rels/document.xml.relsPKN\ docProps/app.xmlPKN\OabH edocProps/core.xmlPKN\D Yword/fontTable.xmlPKN\dv word/endnotes.xmlPKN\SP A[Content_Types].xmlPKN\n word/styles.xmlPKN\r4w word/footnotes.xmlPKN\4Qn I word/settings.xmlPK e ooxml/docxtest_tmp/test_41.docx000644 000765 000024 00000007021 15221665127 017176 0ustar00alexstaff000000 000000 PKN\OG9}?word/header1.xmlMn0=>P ?pV޾6M % {>y#֟@VYLXZ`)u[w>kJ^m>gs&c+P.рkRH!`G6OXqوuPRZBʰ5U9K6(:MǺfе;m_N4nTa-?x&?ȓ1=PSob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\uword/document.xmlN0 y*[:!!bYAN)ABӸߎ}7m ْ-9JK0ae_(';6f`Cїـa>L&6C Yr-y,v ۀPPBF{OTk#˰ЪdVWe;F D~\PKN\~0word/_rels/document.xml.rels 0E~EM""nDVt6 ( ]y{dt-;(Zѕ}/`V;l%_7ֳ.9NXԡSI UJuIϹ{Óe )FƨSDpO}>8JW! (?24ryhE,z$ o~{lHep# PKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tU:0i69nO+B.Kn,`= ?ZG# t|PKN\nword/styles.xml0 OAz1w}1.Nw![r TE vK~ݝb5g)xk!X=4J.kn#1a3R9ihž,q1B1P(R* |XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\OG9}? word/header1.xmlPKN\:j< m_rels/.relsPKN\u mword/document.xmlPKN\~0 word/_rels/document.xml.relsPKN\ docProps/app.xmlPKN\OabH docProps/core.xmlPKN\D word/fontTable.xmlPKN\Q@Gw [Content_Types].xmlPKN\n word/styles.xmlPKN\4Qn e word/settings.xmlPK z ooxml/docxtest_tmp/test_40.docx000644 000765 000024 00000007021 15221665127 017175 0ustar00alexstaff000000 000000 PKN\OG9}?word/header1.xmlMn0=>P ?pV޾6M % {>y#֟@VYLXZ`)u[w>kJ^m>gs&c+P.рkRH!`G6OXqوuPRZBʰ5U9K6(:MǺfе;m_N4nTa-?x&?ȓ1=PSob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\uword/document.xmlN0 y*[:!!bYAN)ABӸߎ}7m ْ-9JK0ae_(';6f`Cїـa>L&6C Yr-y,v ۀPPBF{OTk#˰ЪdVWe;F D~\PKN\~0word/_rels/document.xml.rels 0E~EM""nDVt6 ( ]y{dt-;(Zѕ}/`V;l%_7ֳ.9NXԡSI UJuIϹ{Óe )FƨSDpO}>8JW! (?24ryhE,z$ o~{lHep# PKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tU:0i69nO+B.Kn,`= ?ZG# t|PKN\nword/styles.xml0 OAz1w}1.Nw![r TE vK~ݝb5g)xk!X=4J.kn#1a3R9ihž,q1B1P(R* |XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\OG9}? word/header1.xmlPKN\:j< m_rels/.relsPKN\u mword/document.xmlPKN\~0 word/_rels/document.xml.relsPKN\ docProps/app.xmlPKN\OabH docProps/core.xmlPKN\D word/fontTable.xmlPKN\Q@Gw [Content_Types].xmlPKN\n word/styles.xmlPKN\4Qn e word/settings.xmlPK z ooxml/docxtest_tmp/test_17.docx000644 000765 000024 00000007042 15221665126 017203 0ustar00alexstaff000000 000000 PKN\'̩aword/comments.xmln0 (0Mӄ դjnwx4Frlo?r:iB!6dt*#I+ |?m.)Rrlʦ}FjLE\Rj$u*54"O6mG EFH *)hKt.K"ǐfSob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\RD^word/document.xmln  4MSԤ6n(! ZȐf}AsA"F`7ODV:NH$4B*#o;ͯ6]Zo.ڦ]FjLJP`P1X0\XyIrK H:+%9ҭ8Rr1,cZ Ǵ!x.EÜo#_Ռuд),Z gws&?IFe e(N~^kfL.="fzZZ5c?^6OϢ7ݳxO* ȈEA7,`8TDohQ *.^BNjtY3}:OrPKN\~word/_rels/document.xml.relsMj09},'-ل=*miRWM1]x9o4}f}`Y,VZV[uZ¡XKJOb}diFqUFyӸ`$2Ku-m0P`?ޮi£SW&"xǘeh|Y>]2q*4(x ?ʙyPKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tUXLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\'̩a word/comments.xmlPKN\:j< _rels/.relsPKN\RD^ word/document.xmlPKN\~ word/_rels/document.xml.relsPKN\ -docProps/app.xmlPKN\OabH docProps/core.xmlPKN\D word/fontTable.xmlPKN\<ͯ\Gz [Content_Types].xmlPKN\n word/styles.xmlPKN\4Qn u word/settings.xmlPK { ooxml/docxtest_tmp/test_56.docx000644 000765 000024 00000007072 15221665127 017212 0ustar00alexstaff000000 000000 PKN\:j< _rels/.relsMKA !nDH7LvwA&DхR=͛慥;X6-69-l#HkL>Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\]word/document.xmln0 { {iB^MM[iđJKZ>!M=ۖכj@+Ag$Y$C!ulu[%|i9Rjy-K0B{_ X0\Xy8~IMz dEBT e)!BI|  x-EÜo_ $Qnha-uۋs"?Q>S}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tUP U7]4ǀUl&ګZ WKL+ߘrWvQTxn4y+$hX()cPvgMbe&4r.OQ)o7CV6GE0ix;mO\Lb`] N{dPKN\4Qnword/settings.xmlePn0 +#[zv`J$G)~aq{ӷhId4%|ί8/ǩȜ1KIB+!ѪGUpcAE&2fSP# C=%LlS7\*y/>XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\:j< _rels/.relsPKN\] word/document.xmlPKN\:Y word/_rels/document.xml.relsPKN\ docProps/app.xmlPKN\OabH UdocProps/core.xmlPKN\D Iword/fontTable.xmlPKN\G| [Content_Types].xmlPKN\n word/styles.xmlPKN\cPx word/footnotes.xmlPKN\4Qn word/settings.xmlPK | ooxml/docxtest_tmp/test_21.docx000644 000765 000024 00000006111 15221665126 017172 0ustar00alexstaff000000 000000 PKN\:j< _rels/.relsMKA !nDH7LvwA&DхR=͛慥;X6-69-l#HkL>Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\qKword/document.xmln0 { {iB@/զ&U!F>ҾIjD $hÕLQQ$UU>_W/h=$]\( &mcCk&Y+ͤ+b*)(4(ʌq<0|ƂpJQ 2+)(JJĪ,9e3Ē y,kB5ĺQk35qEvЦ Dh5˩oϛ3AN2NvOq(kLjttIwĴ;7ܞgQ}gv{%a)rsrArUY;dZos7Л`mvLwBo sNױ} $P{q]l= _~PKN\i~word/_rels/document.xml.rels 0E~EM "M݈Vt6 (|Pąy{].|c$Vht%oKXgtznP^I:LJ:ItRd| L+]oaln:wiD{Q Iєc7B/<;/ |mvPKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tUܝ #WNn|d vNY7i} adpC vk=Ȫ7PKN\nword/styles.xml0 OAz1w}1.Nw![r TE vK~ݝb5g)xk!X=4J.kn#1a3R9ihž,q1B1P(R* |XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\:j< _rels/.relsPKN\qK word/document.xmlPKN\i~ word/_rels/document.xml.relsPKN\ docProps/app.xmlPKN\OabH WdocProps/core.xmlPKN\D Kword/fontTable.xmlPKN\< [Content_Types].xmlPKN\n word/styles.xmlPKN\4Qn word/settings.xmlPK < ooxml/docxtest_tmp/test_76.docx000644 000765 000024 00000006044 15221665127 017212 0ustar00alexstaff000000 000000 PKN\:j< _rels/.relsMKA !nDH7LvwA&DхR=͛慥;X6-69-l#HkL>Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\IsLword/document.xmlMn0=P Uv1b56}mM % |~7_tHhuN>ޟ')}V. f}NLFP̮*@ŜbM{ pa穖'#ULj2b 'ldJr 9 Jr1SZr)e;Juk!(ZUNET;dAsY"DLg+/c,{x^\fLo tZZ31[tǡYTpKϮ+j ȉEA,)Cy Cp (]Ӱ"q8fwHS>_h PKN\i~word/_rels/document.xml.rels 0E~EM "M݈Vt6 (|Pąy{].|c$Vht%oKXgtznP^I:LJ:ItRd| L+]oaln:wiD{Q Iєc7B/<;/ |mvPKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tUܝ #WNn|d vNY7i} adpC vk=Ȫ7PKN\nword/styles.xml0 OAz1w}1.Nw![r TE vK~ݝb5g)xk!X=4J.kn#1a3R9ihž,q1B1P(R* |XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\:j< _rels/.relsPKN\IsL word/document.xmlPKN\i~ {word/_rels/document.xml.relsPKN\ ydocProps/app.xmlPKN\OabH 2docProps/core.xmlPKN\D &word/fontTable.xmlPKN\< i[Content_Types].xmlPKN\n word/styles.xmlPKN\4Qn word/settings.xmlPK < ooxml/docxtest_tmp/test_60.docx000644 000765 000024 00000007005 15221665127 017201 0ustar00alexstaff000000 000000 PKN\Qz7word/header1.xmlMn0=>P ?pcMho1ҦRB|~Fl?u$:&g:a4Jeꜽ=ضYSbDg5,hn Vګ5uAH6Ic͕a#r֡FJ++:RBT\|,ف4~7/l\h8v:קɂvChs]bDw gk1=P&g׆[yў:;V,VslH(Ukhd*yf^jϱޔ A|ҳ+PKN\:j< _rels/.relsMKA !nDH7LvwA&DхR=͛慥;X6-69-l#HkL>Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\)xqword/document.xmlj0 QMcln$fiַ%0Jw9O$y7m ْ-9JKr?f7U_(';6f`CїـaL_EL;rS E߻~yy$_ȃ9([?xύp=ajΧyV:ٳxiF:JF,#Sؚk>>L&oߊdq}| 2r{ʡ]YV%ÍZ2>[ED~PKN\~0word/_rels/document.xml.rels 0E~EM""nDVt6 ( ]y{dt-;(Zѕ}/`V;l%_7ֳ.9NXԡSI UJuIϹ{Óe )FƨSDpO}>8JW! (?24ryhE,z$ o~{lHep# PKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tU:0i69nO+B.Kn,`= ?ZG# t|PKN\nword/styles.xml0 OAz1w}1.Nw![r TE vK~ݝb5g)xk!X=4J.kn#1a3R9ihž,q1B1P(R* |XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\Qz7 word/header1.xmlPKN\:j< e_rels/.relsPKN\)xq eword/document.xmlPKN\~0 word/_rels/document.xml.relsPKN\ docProps/app.xmlPKN\OabH docProps/core.xmlPKN\D word/fontTable.xmlPKN\Q@Gw [Content_Types].xmlPKN\n y word/styles.xmlPKN\4Qn Y word/settings.xmlPK zu ooxml/docxtest_tmp/test_37.docx000644 000765 000024 00000006262 15221665127 017211 0ustar00alexstaff000000 000000 PKN\:j< _rels/.relsMKA !nDH7LvwA&DхR=͛慥;X6-69-l#HkL>Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\L?*eword/document.xmlj0 {{d1B^ʶ u_NҾףּCdf{"XUuθ*zAaęd>AٸIP霉1dص6Ly_ÀZϓ?3+4`t*PXINA[2y)1C.)ܧcYWLGeKnHkbkpAЦ Dh1SΙh 'k/chx^^%1l@WfZ-]ҭ$UvbƯwYTtk/i/r,A)gQ뤳K{"X5 K응.N7x K,pZBl#,}f_7~PKN\i~word/_rels/document.xml.rels 0E~EM "M݈Vt6 (|Pąy{].|c$Vht%oKXgtznP^I:LJ:ItRd| L+]oaln:wiD{Q Iєc7B/<;/ |mvPKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tUܝ #WNn|d vNY7i} adpC vk=Ȫ7PKN\d`(word/styles.xmlAN0E"uRBQ.ݱ8Xk45$̟?_^o߭ IXYFb/ϻnCIhe*ևKI ZW.Z@+Bl`"iUr+c)Y-ڰ`9jE>U֤+bE"Z ˬ,Q ǫN$tGWI64~g9# %O/Ov}Ag `vXLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\:j< _rels/.relsPKN\L?*e word/document.xmlPKN\i~ word/_rels/document.xml.relsPKN\ docProps/app.xmlPKN\OabH KdocProps/core.xmlPKN\D ?word/fontTable.xmlPKN\< [Content_Types].xmlPKN\d`( word/styles.xmlPKN\4Qn D word/settings.xmlPK <` ooxml/docxtest_tmp/test_18.docx000644 000765 000024 00000007074 15221665126 017211 0ustar00alexstaff000000 000000 PKN\Fm`word/comments.xmln0 { {iB^Mv!@$PCt4qH6Yo: YkMA>ޟWOdSޭR\{avy_{'c-W`ƽIzsS2ODQɈtV#c+LC] $>luAַ^ \Rr0n+t冦"Yw}{ܜ$#FcyYz{k3b3Ѳ%*j?;:fp{! Eeu0xF{ (CH9_E7SQG;ZxA%p4`|u>kk;f9]PKN\:j< _rels/.relsMKA !nDH7LvwA&DхR=͛慥;X6-69-l#HkL>Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\[Gybword/document.xmlo0WkaY&2?VZq,1FB{]igYG;@+H2I\2#_'͚4|+A(63)W jʯ%sKh jz}?RɄ"Fgd*)8j 7Z(n#%ېe'OBj|l%isEd5I|AisYs߿]_CeLx[W@+oޚK &t؈ZATpqϮㅍ<]J#Ԑ:oJX2k}M0?f4{T kEM*rh =81e!pS @#()-pt[ /PKN\~word/_rels/document.xml.relsMj09},'-ل=*miRWM1]x9o4}f}`Y,VZV[uZ¡XKJOb}diFqUFyӸ`$2Ku-m0P`?ޮi£SW&"xǘeh|Y>]2q*4(x ?ʙyPKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tUXLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\Fm` word/comments.xmlPKN\:j< _rels/.relsPKN\[Gyb word/document.xmlPKN\~ 7word/_rels/document.xml.relsPKN\ GdocProps/app.xmlPKN\OabH docProps/core.xmlPKN\D word/fontTable.xmlPKN\<ͯ\Gz 7[Content_Types].xmlPKN\n word/styles.xmlPKN\4Qn word/settings.xmlPK { ooxml/docxtest_tmp/test_3.docx000644 000765 000024 00000006040 15221665126 017113 0ustar00alexstaff000000 000000 PKN\:j< _rels/.relsMKA !nDH7LvwA&DхR=͛慥;X6-69-l#HkL>Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\ NHword/document.xmln0 { ; L4B/զ&{4F e}%Ij8/+͗j@+A$]%$C)usD6ݺJE@۬I(}TOiX.<$yIMF CXI`r1AUI.ePK>lGӱ x-E˜6؉vj}},h7v0Kv}{JDy2ƶaF̴6 BgΣKU ?;3~{JwE:^kپ9(%X{(a5!` 4CVptq*,PKN\i~word/_rels/document.xml.rels 0E~EM "M݈Vt6 (|Pąy{].|c$Vht%oKXgtznP^I:LJ:ItRd| L+]oaln:wiD{Q Iєc7B/<;/ |mvPKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tUܝ #WNn|d vNY7i} adpC vk=Ȫ7PKN\nword/styles.xml0 OAz1w}1.Nw![r TE vK~ݝb5g)xk!X=4J.kn#1a3R9ihž,q1B1P(R* |XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\:j< _rels/.relsPKN\ NH word/document.xmlPKN\i~ wword/_rels/document.xml.relsPKN\ udocProps/app.xmlPKN\OabH .docProps/core.xmlPKN\D "word/fontTable.xmlPKN\< e[Content_Types].xmlPKN\n word/styles.xmlPKN\4Qn word/settings.xmlPK < ooxml/docxtest_tmp/test_59.docx000644 000765 000024 00000007005 15221665127 017211 0ustar00alexstaff000000 000000 PKN\Qz7word/header1.xmlMn0=>P ?pcMho1ҦRB|~Fl?u$:&g:a4Jeꜽ=ضYSbDg5,hn Vګ5uAH6Ic͕a#r֡FJ++:RBT\|,ف4~7/l\h8v:קɂvChs]bDw gk1=P&g׆[yў:;V,VslH(Ukhd*yf^jϱޔ A|ҳ+PKN\:j< _rels/.relsMKA !nDH7LvwA&DхR=͛慥;X6-69-l#HkL>Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\)xqword/document.xmlj0 QMcln$fiַ%0Jw9O$y7m ْ-9JKr?f7U_(';6f`CїـaL_EL;rS E߻~yy$_ȃ9([?xύp=ajΧyV:ٳxiF:JF,#Sؚk>>L&oߊdq}| 2r{ʡ]YV%ÍZ2>[ED~PKN\~0word/_rels/document.xml.rels 0E~EM""nDVt6 ( ]y{dt-;(Zѕ}/`V;l%_7ֳ.9NXԡSI UJuIϹ{Óe )FƨSDpO}>8JW! (?24ryhE,z$ o~{lHep# PKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tU:0i69nO+B.Kn,`= ?ZG# t|PKN\nword/styles.xml0 OAz1w}1.Nw![r TE vK~ݝb5g)xk!X=4J.kn#1a3R9ihž,q1B1P(R* |XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\Qz7 word/header1.xmlPKN\:j< e_rels/.relsPKN\)xq eword/document.xmlPKN\~0 word/_rels/document.xml.relsPKN\ docProps/app.xmlPKN\OabH docProps/core.xmlPKN\D word/fontTable.xmlPKN\Q@Gw [Content_Types].xmlPKN\n y word/styles.xmlPKN\4Qn Y word/settings.xmlPK zu ooxml/docxtest_tmp/test_22.docx000644 000765 000024 00000006040 15221665126 017174 0ustar00alexstaff000000 000000 PKN\:j< _rels/.relsMKA !nDH7LvwA&DхR=͛慥;X6-69-l#HkL>Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\WHword/document.xmln {.˲jo.[( o?Z.YL{AKAs ͡.~"ng%N "mqdZ ~T_iX.<$yIMF CXI`r1AUI.iPK.>lGӵ x-E˜6؉vjs},(7v0Kv}{ڜ,ceeK [ÌimgΜ[˗T~v&8f|+8>JnSuuxųZ}+rAQPC%X{(a6!`InMg8ܽ"Nt~7PKN\i~word/_rels/document.xml.rels 0E~EM "M݈Vt6 (|Pąy{].|c$Vht%oKXgtznP^I:LJ:ItRd| L+]oaln:wiD{Q Iєc7B/<;/ |mvPKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tUܝ #WNn|d vNY7i} adpC vk=Ȫ7PKN\nword/styles.xml0 OAz1w}1.Nw![r TE vK~ݝb5g)xk!X=4J.kn#1a3R9ihž,q1B1P(R* |XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\:j< _rels/.relsPKN\WH word/document.xmlPKN\i~ wword/_rels/document.xml.relsPKN\ udocProps/app.xmlPKN\OabH .docProps/core.xmlPKN\D "word/fontTable.xmlPKN\< e[Content_Types].xmlPKN\n word/styles.xmlPKN\4Qn word/settings.xmlPK < ooxml/docxtest_tmp/test_75.docx000644 000765 000024 00000006045 15221665127 017212 0ustar00alexstaff000000 000000 PKN\:j< _rels/.relsMKA !nDH7LvwA&DхR=͛慥;X6-69-l#HkL>Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\}D%}Mword/document.xmlJ0}-HY;x'ilrI7G'H.zB_ lTZ :#:& |?6tiUB7hv3)B1#_+s+ k=O56bRiQc$GPBYJ.aPK>㱮!x)EÜؑvA5. MfY#ߩN3AN2^`x^jfL=#fZĭbٚWt,*Nyf+T:_*YF GCĆP>+{EOt~7PKN\i~word/_rels/document.xml.rels 0E~EM "M݈Vt6 (|Pąy{].|c$Vht%oKXgtznP^I:LJ:ItRd| L+]oaln:wiD{Q Iєc7B/<;/ |mvPKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tUܝ #WNn|d vNY7i} adpC vk=Ȫ7PKN\nword/styles.xml0 OAz1w}1.Nw![r TE vK~ݝb5g)xk!X=4J.kn#1a3R9ihž,q1B1P(R* |XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\:j< _rels/.relsPKN\}D%}M word/document.xmlPKN\i~ |word/_rels/document.xml.relsPKN\ zdocProps/app.xmlPKN\OabH 3docProps/core.xmlPKN\D 'word/fontTable.xmlPKN\< j[Content_Types].xmlPKN\n word/styles.xmlPKN\4Qn word/settings.xmlPK < ooxml/docxtest_tmp/test_63.docx000644 000765 000024 00000007067 15221665127 017214 0ustar00alexstaff000000 000000 PKN\:j< _rels/.relsMKA !nDH7LvwA&DхR=͛慥;X6-69-l#HkL>Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\O\word/document.xmln0 (m zSmݴuAN(/i9 MmQ6 2,ciH6ݺK [ E>@ٴHI)RPWjOh09Xy8~ EzH* )8jKZ,"ėm/yHB|l-h8f%rC3Ghߟ]^A2^F_yI^35hj%ք?h; D%ݳxa/ dăΛ?~8|G-X= A .EFVi+^~_2i/PKN\yword/_rels/document.xml.rels˪0)m9L݈VtzvQ x r]?byZqBK I آJ._~a,jOBݸ 52;bK_IAW('i:π)6) mY6W;$`!_Z }V'dHz+Sb:9޲-lHY<"ȷ]PKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tUPKN\JHz[Content_Types].xmlN0E|E-J\X vc ]52Hl3-3n !ԔGLf=wNѲmDU ƺi%' *f3p#% qUďq*oj r0;G9%1,V%pY.M_BUBX2U巺 ..\<Oh dcQl'_C' E(d/FaD9׵%c1`dh,^?C4wr5 G*7Ҫ^|ȉzm~qwD9:|ucyAPKN\nword/styles.xml0 OAz1w}1.Nw![r TE vK~ݝb5g)xk!X=4J.kn#1a3R9ihž,q1B1P(R* |XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\:j< _rels/.relsPKN\O\ word/document.xmlPKN\y word/_rels/document.xml.relsPKN\ docProps/app.xmlPKN\OabH SdocProps/core.xmlPKN\D Gword/fontTable.xmlPKN\%Ix word/endnotes.xmlPKN\JHz 1[Content_Types].xmlPKN\n word/styles.xmlPKN\4Qn word/settings.xmlPK { ooxml/docxtest_tmp/test_34.docx000644 000765 000024 00000026262 15221665127 017210 0ustar00alexstaff000000 000000 PKN\:j< _rels/.relsMKA !nDH7LvwA&DхR=͛慥;X6-69-l#HkL>Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\Dword/fontTable.xmlN0<;uBQ qB=wXO51}{\'PPox񬷟F=)g+\Gܭc8%2V + ٢Zm5O":켓Ȟx壍5AB Lot, V ado΀ق'hz/ .;0JT4+5^VbϦvz5)IQߢzU5\6ۣWM|~--o]d`i.qTxPKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\%"Uword/_rels/document.xml.relsR0>vtƩ dJ~&I괙.'p r/ Z$O3*5.vF%%xri7ϔ\ (\hkjXe5IM{ʼng+d}0p*Q‹.w?A?Б|A9EBObWZ5۴0]{q J>& XR!&D9O ڏ9ɶBmGC_3i,5="*vp ӎ~PKO1!@ Bȳ ?K#^ 2D=9S{<5!_z~^俴PKN\kʹCword/numbering.xmlSKN0s ĉEMBZ'K 8'QJ73ًN5%ӌ$`mٔi%b158T_ %نz}j[0=[ym`]:+{TjEYPͥ!klk0K\QBJQ,">p/nG!5W k؍eD{Fq~qsvu9ugQN)G_OW՘ۙ4 D7YƦ2:PKN\Mword/endnotes.xmln0} ]CTEZ%JC.I^3UL=FƨH-33!G2c6$8mk s!@Klltv$j^& FmXM7{\U?y ?AاQ,/ Nx/V@/݃Z2&[RmŔmŖ|uD7:yD%y:krj;: A&q#b' MMd)ϻ n"yn0&lޟ5Ŧ(ib^AgO~PKN\nut<Bword/styles.xmlr0} FXabgOzfZZ$O_ -a:G\"hCd,K*s9:7vˈtaz*kU "y+9nװTZbbL8Q2(()ȕ`ɡ\(&M)w{7Wu8>'GF]z YZPF "ZH F&ӎ5sUNUHFZf@O~FSՓ_0ho½SI{9RdRpZS^n5[ sgDQ{ʑi= 0?>}~Ȏ'AI~|.KړڥyvI^loDs`Tdƿhc~H -D2@#BD7t>M j,Ҷގ+/F?#W25[gj)A ߱/M0eYnz. ")6}%V {o( l^>?kZ.չ  a?MwePKN\9[Content_Types].xmlN0E|E-Jܲ@5(kړ"~vK6B̽ȉ2mel:UQb U1IgӋbg%ث\78I] (JVPF+ W5aZyP>#N'[pIwb@Tb^d 4My)[[vZb{W94u`⵽E}MYZDU~Ssͥ3-Z{?JK1C_R)ecEHDz=B}ёv_EqAih whgϧy8 yҘGyFZ6V\ҭ341b'G۬^utZ_cTYdC?uE}ܝV<ƻu   [^rOr.L`8:hfRLpSNG\fBޙ7@ L@LE P~`FVÄÄ▛DDG8kZPKN\@ :-3@[lO(*`3k$`1Z*9Zh$0Y%΄l4H)a}}oS3m< #!1APY!擤 )$Je{wgWHݿnt7Iۛ0 c&~jypoɞ/$d& R{Hxq7b!Um C9t&BS 腁uBʣVJF4^ܓB~pO cO"l69N!gl(#"%"Y@5Jx2jEB 7l5%w^┢*aF*:[zٔnJyzM NbX ][#Tgn:[v| #!"Qp,W i~6`d7~뀵o?99eT'&=Ӧmr)QN%NFTRO3INMh\ϳ}nt inV㞚;5,$IH|IׄL 8+!b\y009Nh=aHSk?YJK~͞}( ]{yZt =Ԇ- 1y/Yݝ7Ve::sOx$.6[Ǟ{\GD0$s>qTD z ygF?è҇ӹ>U)eSBmexǺ!#;7db(L19fW$QL9V+cr#*Uj0,U1 ԛ[OVv©`M.PxTaAl4p:`1?xmk*+m|kxB 6#O"MMa´FB:(>mI\ c8 }& '̮Y!I2V#'CP0 &a X5@92?OO,֮У_BW{YcWkg&y)tw@zwW D_F~ F%a3iifɉ= c"&ĭyem5cH >C.-lքb҃\ t j.̽ |c#Rsi^4fggfh44oiKn vIFIpgADDlG@OD$" O?+m cGv䔳_÷'{3AKW14ul(`Ya=lWkKfԟçj8=YU^m˓U 9`H|]NvD!1߿H{3O X#q'rD =7 ȍYOM6)ZSrc[&B@ x q:>W)J MŹ15f e jΌ׻ϡ(k>vW n3]e@Ac&qgvJ+SrوG̑}Ecti[賨vLd. RgR, .u*E@33keu>郝W&gCKh8ǿHy!ŘdqXCJV6ؚ͜V?jjw*Pa+nosRք8^֚ة*֩3gw1VDji_l-S G kc3&w6`䊛_c9z5sbq n5ם5"bd;O}sWJ)E&*Rla۰,jqs Kƽ1>|\okn,_v?3DS]1NsÝ|ՀSP34(Ỏqv!@KkYC ) :P vC.1x*}=yԏ=eF *22RXʈ xLSUx##%!qD ऊ0[+C{1Ni-ﮏM@ X/Bcj>7 M{sɫBjP+6ə/N$om7T. ?x$,ʖjJ_9讚~tO]$'Xx>àn_7\~~(umavuM5gʠ$$;d,` ui#rdw{S\./+͔[QF)΢xWs rg-"ڴ!ŋaa`o awT#PzZŁ`]QyKHf-;!̑IK{e(Ť_SZ5f_;4Fy/e kdI1rJxgCnٯ?un į^6m$/JTfEyUe:_EZ^Xo@X&'dtKᆫ ׿XaЦ3j;Sskly%c^IrUfƕļ&@M!ԢMz;Bs|K}lP/Qm J:DH/D_sˍGJpe+`yA" Ӥ^5( @D 8*oe@D$jm3իʫw!^xhM.Y 񱥏v].!OGOW'd 򗋾V/`yq$CW4wUհqFgOPKN\( word/footer1.xmlTn0}W *B%mԇV-h셤__& %j}9cՓl 2c\6]Z:r,usIニ,Ð98Iw8Q#h?iPKN\Rpword/footnotes.xmln0} B.Q\ƀUҼ}mF-I 柱}{riʴ%tJoOh/CI;mJ} >b"\]g2t@Ibb h%3/)w e}7C=qVSʹӿ8~lCihK"F>\ϩ߽8Dr2GJيq+ϴco.[+t9 6Mƭ8^Tg>^x-c/KA$"Cmrr%U4l2fgث`+.`"^ld|uV"^}p "}oQqOKy@jZ41]I#qZ qoPKN\¨O?Dword/media/image1.png sb``p Ҍ $0)nOǐ[30331_Z ftsYPKN\¨O?Dword/media/image2.png sb``p Ҍ $0)nOǐ[30331_Z ftsYPKN\:j< _rels/.relsPKN\D word/fontTable.xmlPKN\ CdocProps/app.xmlPKN\%"U word/_rels/document.xml.relsPKN\kʹC word/numbering.xmlPKN\M word/endnotes.xmlPKN\lמ word/settings.xmlPKN\7x- word/header1.xmlPKN\nut<B l word/styles.xmlPKN\9 [Content_Types].xmlPKN\S. word/comments.xmlPKN\@Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\sHword/document.xmlN0} `1d,LJFӜޖGgbv)p~wK5A3c ͡lM[%|i9Rjy-k0B\ X0\Xyq|O H:+%9ҭ8Rr1,cZrd7HuK!(UƎMT3%viSY"@Sr&?I)g1ӪhF˗t~&8f(7>JSue0xӗJ}#2AQPCKrPjB\64}Vp8jPKN\i~word/_rels/document.xml.rels 0E~EM "M݈Vt6 (|Pąy{].|c$Vht%oKXgtznP^I:LJ:ItRd| L+]oaln:wiD{Q Iєc7B/<;/ |mvPKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tUܝ #WNn|d vNY7i} adpC vk=Ȫ7PKN\d`(word/styles.xmlAN0E"uRBQ.ݱ8Xk45$̟?_^o߭ IXYFb/ϻnCIhe*ևKI ZW.Z@+Bl`"iUr+c)Y-ڰ`9jE>U֤+bE"Z ˬ,Q ǫN$tGWI64~g9# %O/Ov}Ag `vXLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\:j< _rels/.relsPKN\sH word/document.xmlPKN\i~ wword/_rels/document.xml.relsPKN\ udocProps/app.xmlPKN\OabH .docProps/core.xmlPKN\D "word/fontTable.xmlPKN\< e[Content_Types].xmlPKN\d`( word/styles.xmlPKN\4Qn ' word/settings.xmlPK <C ooxml/docxtest_tmp/test_14.docx000644 000765 000024 00000007122 15221665126 017177 0ustar00alexstaff000000 000000 PKN\:j< _rels/.relsMKA !nDH7LvwA&DхR=͛慥;X6-69-l#HkL>Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\kLword/document.xmln  ei-s{%+r@;~\tzC[8?|h/J K]f}=y"ݼIs;%|i9Rjy%1\X07\Xy$yIMZ dd:m%9M8Br])eJuUk!(jUv_EUݭkɈri}#4G֜ir _^Fee)7M.x1h;ӷV1ܙZñA6U] W<})5 "#u>dCM[%ZixipMIQ<#3Be7EMW<>ɦŰPKN\:Yword/_rels/document.xml.relsj0} XNJ(s)\VH}iI g%` *[[+*;JhZD|cٽKL 9"k[(7i&SKXAgTU2?=Z~`!HԾFVp~}E }`B.2]N[S"lO71J!PKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tU{ TqB//>@Ld$L}{ bGi{`dwKTiA(#0IaeZf7&L2I֪cCK& A1|9hA;77Je8< \)L:Lp@ngDy)^}"OYeїB4u2%Wmjb+> jJMj</PFn)G#޺$hu' VKt+rCQuUgv/^乐GR@Ι=eGV$v\ahbA#w7)8fwu$\#=q>"Wdwsdnϖ +st07PKN\4Qnword/settings.xmlePn0 +#[zv`J$G)~aq{ӷhId4%|ί8/ǩȜ1KIB+!ѪGUpcAE&2fSP# C=%LlS7\*y/>XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\:j< _rels/.relsPKN\kL word/document.xmlPKN\:Y word/_rels/document.xml.relsPKN\ docProps/app.xmlPKN\OabH cdocProps/core.xmlPKN\D Wword/fontTable.xmlPKN\G| [Content_Types].xmlPKN\n word/styles.xmlPKN\ ' word/footnotes.xmlPKN\4Qn word/settings.xmlPK | ooxml/docxtest_tmp/test_82.xml000644 000765 000024 00000001745 15221665127 017055 0ustar00alexstaff000000 000000 Test ooxml/docxtest_tmp/test_55.docx000644 000765 000024 00000006040 15221665127 017203 0ustar00alexstaff000000 000000 PKN\:j< _rels/.relsMKA !nDH7LvwA&DхR=͛慥;X6-69-l#HkL>Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\ NHword/document.xmln0 { ; L4B/զ&{4F e}%Ij8/+͗j@+A$]%$C)usD6ݺJE@۬I(}TOiX.<$yIMF CXI`r1AUI.ePK>lGӱ x-E˜6؉vj}},h7v0Kv}{JDy2ƶaF̴6 BgΣKU ?;3~{JwE:^kپ9(%X{(a5!` 4CVptq*,PKN\i~word/_rels/document.xml.rels 0E~EM "M݈Vt6 (|Pąy{].|c$Vht%oKXgtznP^I:LJ:ItRd| L+]oaln:wiD{Q Iєc7B/<;/ |mvPKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tUܝ #WNn|d vNY7i} adpC vk=Ȫ7PKN\nword/styles.xml0 OAz1w}1.Nw![r TE vK~ݝb5g)xk!X=4J.kn#1a3R9ihž,q1B1P(R* |XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\:j< _rels/.relsPKN\ NH word/document.xmlPKN\i~ wword/_rels/document.xml.relsPKN\ udocProps/app.xmlPKN\OabH .docProps/core.xmlPKN\D "word/fontTable.xmlPKN\< e[Content_Types].xmlPKN\n word/styles.xmlPKN\4Qn word/settings.xmlPK < ooxml/docxtest_tmp/test_79.docx000644 000765 000024 00000006060 15221665127 017213 0ustar00alexstaff000000 000000 PKN\:j< _rels/.relsMKA !nDH7LvwA&DхR=͛慥;X6-69-l#HkL>Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\I8XYword/document.xmlMn0=>ҨP Uv1b56}m"ɂg>yƬx+PeJ^_fdݬ$Hl IڔT$ f+VJj+a kƍqb߹3ro]k8Ov/}PKN\i~word/_rels/document.xml.rels 0E~EM "M݈Vt6 (|Pąy{].|c$Vht%oKXgtznP^I:LJ:ItRd| L+]oaln:wiD{Q Iєc7B/<;/ |mvPKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tUܝ #WNn|d vNY7i} adpC vk=Ȫ7PKN\nword/styles.xml0 OAz1w}1.Nw![r TE vK~ݝb5g)xk!X=4J.kn#1a3R9ihž,q1B1P(R* |XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\:j< _rels/.relsPKN\I8XY word/document.xmlPKN\i~ word/_rels/document.xml.relsPKN\ docProps/app.xmlPKN\OabH >docProps/core.xmlPKN\D 2word/fontTable.xmlPKN\< u[Content_Types].xmlPKN\n word/styles.xmlPKN\4Qn word/settings.xmlPK < ooxml/docxtest_tmp/test_80.docx000644 000765 000024 00000006064 15221665127 017207 0ustar00alexstaff000000 000000 PKN\:j< _rels/.relsMKA !nDH7LvwA&DхR=͛慥;X6-69-l#HkL>Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\\word/document.xmln0E }bHӪB@6Q*}mM"ɂg\cՇÕLQ4Q$U9e^gh$m+&m UcC+&+ͤ[+b+UkPxƋ0ǂpzJQ23)( ;JĪ(8e0T)Jֽa[[ &Ye*@NC^+9]_G<ʘ;}RFZy TGKt+7;Qlyk|-Sue<ƛR* ۚȁ΅=ebmU|2辳 J]{{Fܻ_s p7qPKN\i~word/_rels/document.xml.rels 0E~EM "M݈Vt6 (|Pąy{].|c$Vht%oKXgtznP^I:LJ:ItRd| L+]oaln:wiD{Q Iєc7B/<;/ |mvPKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tUܝ #WNn|d vNY7i} adpC vk=Ȫ7PKN\nword/styles.xml0 OAz1w}1.Nw![r TE vK~ݝb5g)xk!X=4J.kn#1a3R9ihž,q1B1P(R* |XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\:j< _rels/.relsPKN\\ word/document.xmlPKN\i~ word/_rels/document.xml.relsPKN\ docProps/app.xmlPKN\OabH BdocProps/core.xmlPKN\D 6word/fontTable.xmlPKN\< y[Content_Types].xmlPKN\n word/styles.xmlPKN\4Qn word/settings.xmlPK < ooxml/docxtest_tmp/test_38.docx000644 000765 000024 00000007021 15221665127 017204 0ustar00alexstaff000000 000000 PKN\OG9}?word/header1.xmlMn0=>P ?pV޾6M % {>y#֟@VYLXZ`)u[w>kJ^m>gs&c+P.рkRH!`G6OXqوuPRZBʰ5U9K6(:MǺfе;m_N4nTa-?x&?ȓ1=PSob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\uword/document.xmlN0 y*[:!!bYAN)ABӸߎ}7m ْ-9JK0ae_(';6f`Cїـa>L&6C Yr-y,v ۀPPBF{OTk#˰ЪdVWe;F D~\PKN\~0word/_rels/document.xml.rels 0E~EM""nDVt6 ( ]y{dt-;(Zѕ}/`V;l%_7ֳ.9NXԡSI UJuIϹ{Óe )FƨSDpO}>8JW! (?24ryhE,z$ o~{lHep# PKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tU:0i69nO+B.Kn,`= ?ZG# t|PKN\nword/styles.xml0 OAz1w}1.Nw![r TE vK~ݝb5g)xk!X=4J.kn#1a3R9ihž,q1B1P(R* |XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\OG9}? word/header1.xmlPKN\:j< m_rels/.relsPKN\u mword/document.xmlPKN\~0 word/_rels/document.xml.relsPKN\ docProps/app.xmlPKN\OabH docProps/core.xmlPKN\D word/fontTable.xmlPKN\Q@Gw [Content_Types].xmlPKN\n word/styles.xmlPKN\4Qn e word/settings.xmlPK z ooxml/docxtest_tmp/test_39.docx000644 000765 000024 00000007021 15221665127 017205 0ustar00alexstaff000000 000000 PKN\OG9}?word/header1.xmlMn0=>P ?pV޾6M % {>y#֟@VYLXZ`)u[w>kJ^m>gs&c+P.рkRH!`G6OXqوuPRZBʰ5U9K6(:MǺfе;m_N4nTa-?x&?ȓ1=PSob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\uword/document.xmlN0 y*[:!!bYAN)ABӸߎ}7m ْ-9JK0ae_(';6f`Cїـa>L&6C Yr-y,v ۀPPBF{OTk#˰ЪdVWe;F D~\PKN\~0word/_rels/document.xml.rels 0E~EM""nDVt6 ( ]y{dt-;(Zѕ}/`V;l%_7ֳ.9NXԡSI UJuIϹ{Óe )FƨSDpO}>8JW! (?24ryhE,z$ o~{lHep# PKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tU:0i69nO+B.Kn,`= ?ZG# t|PKN\nword/styles.xml0 OAz1w}1.Nw![r TE vK~ݝb5g)xk!X=4J.kn#1a3R9ihž,q1B1P(R* |XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\OG9}? word/header1.xmlPKN\:j< m_rels/.relsPKN\u mword/document.xmlPKN\~0 word/_rels/document.xml.relsPKN\ docProps/app.xmlPKN\OabH docProps/core.xmlPKN\D word/fontTable.xmlPKN\Q@Gw [Content_Types].xmlPKN\n word/styles.xmlPKN\4Qn e word/settings.xmlPK z ooxml/docxtest_tmp/test_81.docx000644 000765 000024 00000006040 15221665127 017202 0ustar00alexstaff000000 000000 PKN\:j< _rels/.relsMKA !nDH7LvwA&DхR=͛慥;X6-69-l#HkL>Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\ NHword/document.xmln0 { ; L4B/զ&{4F e}%Ij8/+͗j@+A$]%$C)usD6ݺJE@۬I(}TOiX.<$yIMF CXI`r1AUI.ePK>lGӱ x-E˜6؉vj}},h7v0Kv}{JDy2ƶaF̴6 BgΣKU ?;3~{JwE:^kپ9(%X{(a5!` 4CVptq*,PKN\i~word/_rels/document.xml.rels 0E~EM "M݈Vt6 (|Pąy{].|c$Vht%oKXgtznP^I:LJ:ItRd| L+]oaln:wiD{Q Iєc7B/<;/ |mvPKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tUܝ #WNn|d vNY7i} adpC vk=Ȫ7PKN\nword/styles.xml0 OAz1w}1.Nw![r TE vK~ݝb5g)xk!X=4J.kn#1a3R9ihž,q1B1P(R* |XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\:j< _rels/.relsPKN\ NH word/document.xmlPKN\i~ wword/_rels/document.xml.relsPKN\ udocProps/app.xmlPKN\OabH .docProps/core.xmlPKN\D "word/fontTable.xmlPKN\< e[Content_Types].xmlPKN\n word/styles.xmlPKN\4Qn word/settings.xmlPK < ooxml/docxtest_tmp/test_78.docx000644 000765 000024 00000006054 15221665127 017215 0ustar00alexstaff000000 000000 PKN\:j< _rels/.relsMKA !nDH7LvwA&DхR=͛慥;X6-69-l#HkL>Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\OT-word/document.xmln e1inɶJ&rjCs~|C7UG{VH2I$4\2#/;^]-4(] MیTΙR+9?ŒAZS5]-ULjc # g̔ 7R( E? jǒM/y8UυVJ;5W&vi 3Ehg7͑h!O2^FvG${#И)* ;YKwE%7ypR]-2AQPC?KVa ?ф! (YҰ"vGVp[8_PKN\i~word/_rels/document.xml.rels 0E~EM "M݈Vt6 (|Pąy{].|c$Vht%oKXgtznP^I:LJ:ItRd| L+]oaln:wiD{Q Iєc7B/<;/ |mvPKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tUܝ #WNn|d vNY7i} adpC vk=Ȫ7PKN\nword/styles.xml0 OAz1w}1.Nw![r TE vK~ݝb5g)xk!X=4J.kn#1a3R9ihž,q1B1P(R* |XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\:j< _rels/.relsPKN\OT- word/document.xmlPKN\i~ word/_rels/document.xml.relsPKN\ docProps/app.xmlPKN\OabH :docProps/core.xmlPKN\D .word/fontTable.xmlPKN\< q[Content_Types].xmlPKN\n word/styles.xmlPKN\4Qn word/settings.xmlPK < ooxml/docxtest_tmp/test_54.docx000644 000765 000024 00000006040 15221665127 017202 0ustar00alexstaff000000 000000 PKN\:j< _rels/.relsMKA !nDH7LvwA&DхR=͛慥;X6-69-l#HkL>Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\ NHword/document.xmln0 { ; L4B/զ&{4F e}%Ij8/+͗j@+A$]%$C)usD6ݺJE@۬I(}TOiX.<$yIMF CXI`r1AUI.ePK>lGӱ x-E˜6؉vj}},h7v0Kv}{JDy2ƶaF̴6 BgΣKU ?;3~{JwE:^kپ9(%X{(a5!` 4CVptq*,PKN\i~word/_rels/document.xml.rels 0E~EM "M݈Vt6 (|Pąy{].|c$Vht%oKXgtznP^I:LJ:ItRd| L+]oaln:wiD{Q Iєc7B/<;/ |mvPKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tUܝ #WNn|d vNY7i} adpC vk=Ȫ7PKN\nword/styles.xml0 OAz1w}1.Nw![r TE vK~ݝb5g)xk!X=4J.kn#1a3R9ihž,q1B1P(R* |XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\:j< _rels/.relsPKN\ NH word/document.xmlPKN\i~ wword/_rels/document.xml.relsPKN\ udocProps/app.xmlPKN\OabH .docProps/core.xmlPKN\D "word/fontTable.xmlPKN\< e[Content_Types].xmlPKN\n word/styles.xmlPKN\4Qn word/settings.xmlPK < ooxml/docxtest_tmp/test_51.png000644 000765 000024 00000000104 15221665127 017021 0ustar00alexstaff000000 000000 PNG  IHDR  IDATxc}IENDB`ooxml/docxtest_tmp/test_15.docx000644 000765 000024 00000007067 15221665126 017210 0ustar00alexstaff000000 000000 PKN\:j< _rels/.relsMKA !nDH7LvwA&DхR=͛慥;X6-69-l#HkL>Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\O\word/document.xmln0 (m zSmݴuAN(/i9 MmQ6 2,ciH6ݺK [ E>@ٴHI)RPWjOh09Xy8~ EzH* )8jKZ,"ėm/yHB|l-h8f%rC3Ghߟ]^A2^F_yI^35hj%ք?h; D%ݳxa/ dăΛ?~8|G-X= A .EFVi+^~_2i/PKN\yword/_rels/document.xml.rels˪0)m9L݈VtzvQ x r]?byZqBK I آJ._~a,jOBݸ 52;bK_IAW('i:π)6) mY6W;$`!_Z }V'dHz+Sb:9޲-lHY<"ȷ]PKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tUPKN\JHz[Content_Types].xmlN0E|E-J\X vc ]52Hl3-3n !ԔGLf=wNѲmDU ƺi%' *f3p#% qUďq*oj r0;G9%1,V%pY.M_BUBX2U巺 ..\<Oh dcQl'_C' E(d/FaD9׵%c1`dh,^?C4wr5 G*7Ҫ^|ȉzm~qwD9:|ucyAPKN\nword/styles.xml0 OAz1w}1.Nw![r TE vK~ݝb5g)xk!X=4J.kn#1a3R9ihž,q1B1P(R* |XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\:j< _rels/.relsPKN\O\ word/document.xmlPKN\y word/_rels/document.xml.relsPKN\ docProps/app.xmlPKN\OabH SdocProps/core.xmlPKN\D Gword/fontTable.xmlPKN\%Ix word/endnotes.xmlPKN\JHz 1[Content_Types].xmlPKN\n word/styles.xmlPKN\4Qn word/settings.xmlPK { ooxml/docxtest_tmp/test_42.docx000644 000765 000024 00000006262 15221665127 017205 0ustar00alexstaff000000 000000 PKN\:j< _rels/.relsMKA !nDH7LvwA&DхR=͛慥;X6-69-l#HkL>Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\L?*eword/document.xmlj0 {{d1B^ʶ u_NҾףּCdf{"XUuθ*zAaęd>AٸIP霉1dص6Ly_ÀZϓ?3+4`t*PXINA[2y)1C.)ܧcYWLGeKnHkbkpAЦ Dh1SΙh 'k/chx^^%1l@WfZ-]ҭ$UvbƯwYTtk/i/r,A)gQ뤳K{"X5 K응.N7x K,pZBl#,}f_7~PKN\i~word/_rels/document.xml.rels 0E~EM "M݈Vt6 (|Pąy{].|c$Vht%oKXgtznP^I:LJ:ItRd| L+]oaln:wiD{Q Iєc7B/<;/ |mvPKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tUܝ #WNn|d vNY7i} adpC vk=Ȫ7PKN\d`(word/styles.xmlAN0E"uRBQ.ݱ8Xk45$̟?_^o߭ IXYFb/ϻnCIhe*ևKI ZW.Z@+Bl`"iUr+c)Y-ڰ`9jE>U֤+bE"Z ˬ,Q ǫN$tGWI64~g9# %O/Ov}Ag `vXLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\:j< _rels/.relsPKN\L?*e word/document.xmlPKN\i~ word/_rels/document.xml.relsPKN\ docProps/app.xmlPKN\OabH KdocProps/core.xmlPKN\D ?word/fontTable.xmlPKN\< [Content_Types].xmlPKN\d`( word/styles.xmlPKN\4Qn D word/settings.xmlPK <` ooxml/docxtest_tmp/test_35.docx000644 000765 000024 00000007722 15221665127 017211 0ustar00alexstaff000000 000000 PKN\:word/header1.xmlMn0=>P ?pcMho1ҦR=߼7OFNYNX$R:go-n6}֔^>g6c'[*@=bE9B6MXse؈uhJ 8JΠkK>@tZ? BPSJQMMt;dA!.1Z";qDt5(K3kíSob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\.9$~Hword/document.xmlݎ  N*+JU6aЀ;8vJ{6o o'hb-E^7~ O |Zt)Jʨ;p*n1ɩğB 12}Y~NY/f b _͌0b6]Mc5âpk_$%mBЫĭ qW˺qW(77kR_돗1@^ml\Daޮ|ީ7Z6!\V)5ܱ[qM\=xy㝮Z=ԂAEvǡ'#sCC: M3&h;A5ːX&vj{IQz͝TW7ʀGm] V}h: Qz$`I~_[CpN0B}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tUTUU@6Qq Xkl}6*,x捼|6%:`YHeꂽVOlSޭ^`6O'JCk~NE9B6ODse؄uhJ 8JΡkK>lAtZ?BPSJQʹ&z,]nTa= ~;qLt'1٘) kíhkr6F,#f1aŤ8 횐 rdu`hRZKNw~5]si N5n$g]Q9Z 1SCvWFHv2RnwB]T $㯑3so]PKN\nword/styles.xml0 OAz1w}1.Nw![r TE vK~ݝb5g)xk!X=4J.kn#1a3R9ihž,q1B1P(R* |XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\: word/header1.xmlPKN\:j< h_rels/.relsPKN\.9$~H hword/document.xmlPKN\M9  word/_rels/document.xml.relsPKN\ 0docProps/app.xmlPKN\OabH docProps/core.xmlPKN\D word/fontTable.xmlPKN\B,R9 word/footer1.xmlPKN\$xP [Content_Types].xmlPKN\n  word/styles.xmlPKN\4Qn word/settings.xmlPK  ooxml/docxtest_tmp/test_62.docx000644 000765 000024 00000007034 15221665127 017205 0ustar00alexstaff000000 000000 PKN\zA]word/comments.xmlN0 2VJ0 jt9Ե`|MjICX4Oi};A%* &"JN,]Pnh1,ZYڟw׷͙ 2b1=Pg>Ӛh:s-[R3cGRYTvw] W,i4X :4 ~Ê\T :x:x-m} T@ ƗyN?]PKN\:j< _rels/.relsMKA !nDH7LvwA&DхR=͛慥;X6-69-l#HkL>Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\\word/document.xmln0 { {iB^MM[i| }9-['M=ۉWj'HI$47UF>ϋ'V]Z*}ڥ]FjmJP-}<~BE;ÅsS GԤǘӞPq nTjRr/C%i}=@Zylum_{ $Qnha-u?뛳s"?Qee(K Gͬhm0ϩV1jmţFITp˞] xZil׈ ( T8`Lq V`a`pE)TD]* [B93ioPKN\~word/_rels/document.xml.relsMj09},'-ل=*miRWM1]x9o4}f}`Y,VZV[uZ¡XKJOb}diFqUFyӸ`$2Ku-m0P`?ޮi£SW&"xǘeh|Y>]2q*4(x ?ʙyPKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tUXLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\zA] word/comments.xmlPKN\:j< _rels/.relsPKN\\ word/document.xmlPKN\~ word/_rels/document.xml.relsPKN\ 'docProps/app.xmlPKN\OabH docProps/core.xmlPKN\D word/fontTable.xmlPKN\<ͯ\Gz [Content_Types].xmlPKN\n word/styles.xmlPKN\4Qn o word/settings.xmlPK { ooxml/docxtest_tmp/test_53.xml000644 000765 000024 00000000264 15221665127 017046 0ustar00alexstaff000000 000000 ooxml/docxtest_tmp/test_74.docx000644 000765 000024 00000006062 15221665127 017210 0ustar00alexstaff000000 000000 PKN\:j< _rels/.relsMKA !nDH7LvwA&DхR=͛慥;X6-69-l#HkL>Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\zZword/document.xmln0 { { L4B/U&u{4 đK(&pğVVODVILH$4.u≬Uq`E>A۬IزZ(j`{%bw 0a&OXQɀP!X(݂ʠ,%2f9O)AX#hVZ;5qPxKfPO7͉h!2^vO4jjDn=#}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tUܝ #WNn|d vNY7i} adpC vk=Ȫ7PKN\nword/styles.xml0 OAz1w}1.Nw![r TE vK~ݝb5g)xk!X=4J.kn#1a3R9ihž,q1B1P(R* |XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\:j< _rels/.relsPKN\zZ word/document.xmlPKN\i~ word/_rels/document.xml.relsPKN\ docProps/app.xmlPKN\OabH @docProps/core.xmlPKN\D 4word/fontTable.xmlPKN\< w[Content_Types].xmlPKN\n word/styles.xmlPKN\4Qn word/settings.xmlPK < ooxml/docxtest_tmp/test_23.docx000644 000765 000024 00000006050 15221665126 017176 0ustar00alexstaff000000 000000 PKN\:j< _rels/.relsMKA !nDH7LvwA&DхR=͛慥;X6-69-l#HkL>Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\iTPword/document.xmln0 { {iB^NMiđK(&pğVVODVHI$4B*#oYw.-Jhm.#s&Z(f`{%bbE; pa穆#ULj2` #-t`,JR(KŰjNSfS;AWS:] PKN\i~word/_rels/document.xml.rels 0E~EM "M݈Vt6 (|Pąy{].|c$Vht%oKXgtznP^I:LJ:ItRd| L+]oaln:wiD{Q Iєc7B/<;/ |mvPKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tUܝ #WNn|d vNY7i} adpC vk=Ȫ7PKN\nword/styles.xml0 OAz1w}1.Nw![r TE vK~ݝb5g)xk!X=4J.kn#1a3R9ihž,q1B1P(R* |XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\:j< _rels/.relsPKN\iTP word/document.xmlPKN\i~ word/_rels/document.xml.relsPKN\ }docProps/app.xmlPKN\OabH 6docProps/core.xmlPKN\D *word/fontTable.xmlPKN\< m[Content_Types].xmlPKN\n word/styles.xmlPKN\4Qn word/settings.xmlPK < ooxml/docxtest_tmp/test_58.docx000644 000765 000024 00000007072 15221665127 017214 0ustar00alexstaff000000 000000 PKN\:j< _rels/.relsMKA !nDH7LvwA&DхR=͛慥;X6-69-l#HkL>Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\]word/document.xmln0 { {iB^MM[iđJKZ>!M=ۖכj@+Ag$Y$C!ulu[%|i9Rjy-K0B{_ X0\Xy8~IMz dEBT e)!BI|  x-EÜo_ $Qnha-uۋs"?Q>S}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tUP U7]4ǀUl&ګZ WKL+ߘrWvQTxn4y+$hX()cPvgMbe&4r.OQ)o7CV6GE0ix;mO\Lb`] N{dPKN\4Qnword/settings.xmlePn0 +#[zv`J$G)~aq{ӷhId4%|ί8/ǩȜ1KIB+!ѪGUpcAE&2fSP# C=%LlS7\*y/>XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\:j< _rels/.relsPKN\] word/document.xmlPKN\:Y word/_rels/document.xml.relsPKN\ docProps/app.xmlPKN\OabH UdocProps/core.xmlPKN\D Iword/fontTable.xmlPKN\G| [Content_Types].xmlPKN\n word/styles.xmlPKN\cPx word/footnotes.xmlPKN\4Qn word/settings.xmlPK | ooxml/docxtest_tmp/test_19.docx000644 000765 000024 00000007722 15221665126 017212 0ustar00alexstaff000000 000000 PKN\:word/header1.xmlMn0=>P ?pcMho1ҦR=߼7OFNYNX$R:go-n6}֔^>g6c'[*@=bE9B6MXse؈uhJ 8JΠkK>@tZ? BPSJQMMt;dA!.1Z";qDt5(K3kíSob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\.9$~Hword/document.xmlݎ  N*+JU6aЀ;8vJ{6o o'hb-E^7~ O |Zt)Jʨ;p*n1ɩğB 12}Y~NY/f b _͌0b6]Mc5âpk_$%mBЫĭ qW˺qW(77kR_돗1@^ml\Daޮ|ީ7Z6!\V)5ܱ[qM\=xy㝮Z=ԂAEvǡ'#sCC: M3&h;A5ːX&vj{IQz͝TW7ʀGm] V}h: Qz$`I~_[CpN0B}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tUTUU@6Qq Xkl}6*,x捼|6%:`YHeꂽVOlSޭ^`6O'JCk~NE9B6ODse؄uhJ 8JΡkK>lAtZ?BPSJQʹ&z,]nTa= ~;qLt'1٘) kíhkr6F,#f1aŤ8 횐 rdu`hRZKNw~5]si N5n$g]Q9Z 1SCvWFHv2RnwB]T $㯑3so]PKN\nword/styles.xml0 OAz1w}1.Nw![r TE vK~ݝb5g)xk!X=4J.kn#1a3R9ihž,q1B1P(R* |XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\: word/header1.xmlPKN\:j< h_rels/.relsPKN\.9$~H hword/document.xmlPKN\M9  word/_rels/document.xml.relsPKN\ 0docProps/app.xmlPKN\OabH docProps/core.xmlPKN\D word/fontTable.xmlPKN\B,R9 word/footer1.xmlPKN\$xP [Content_Types].xmlPKN\n  word/styles.xmlPKN\4Qn word/settings.xmlPK  ooxml/docxtest_tmp/test_2.docx000644 000765 000024 00000006040 15221665126 017112 0ustar00alexstaff000000 000000 PKN\:j< _rels/.relsMKA !nDH7LvwA&DхR=͛慥;X6-69-l#HkL>Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\ NHword/document.xmln0 { ; L4B/զ&{4F e}%Ij8/+͗j@+A$]%$C)usD6ݺJE@۬I(}TOiX.<$yIMF CXI`r1AUI.ePK>lGӱ x-E˜6؉vj}},h7v0Kv}{JDy2ƶaF̴6 BgΣKU ?;3~{JwE:^kپ9(%X{(a5!` 4CVptq*,PKN\i~word/_rels/document.xml.rels 0E~EM "M݈Vt6 (|Pąy{].|c$Vht%oKXgtznP^I:LJ:ItRd| L+]oaln:wiD{Q Iєc7B/<;/ |mvPKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tUܝ #WNn|d vNY7i} adpC vk=Ȫ7PKN\nword/styles.xml0 OAz1w}1.Nw![r TE vK~ݝb5g)xk!X=4J.kn#1a3R9ihž,q1B1P(R* |XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\:j< _rels/.relsPKN\ NH word/document.xmlPKN\i~ wword/_rels/document.xml.relsPKN\ udocProps/app.xmlPKN\OabH .docProps/core.xmlPKN\D "word/fontTable.xmlPKN\< e[Content_Types].xmlPKN\n word/styles.xmlPKN\4Qn word/settings.xmlPK < ooxml/docxtest_tmp/test_45.docx000644 000765 000024 00000007015 15221665127 017205 0ustar00alexstaff000000 000000 PKN\OG9}?word/header1.xmlMn0=>P ?pV޾6M % {>y#֟@VYLXZ`)u[w>kJ^m>gs&c+P.рkRH!`G6OXqوuPRZBʰ5U9K6(:MǺfе;m_N4nTa-?x&?ȓ1=PSob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\)xqword/document.xmlj0 QMcln$fiַ%0Jw9O$y7m ْ-9JKr?f7U_(';6f`CїـaL_EL;rS E߻~yy$_ȃ9([?xύp=ajΧyV:ٳxiF:JF,#Sؚk>>L&oߊdq}| 2r{ʡ]YV%ÍZ2>[ED~PKN\~0word/_rels/document.xml.rels 0E~EM""nDVt6 ( ]y{dt-;(Zѕ}/`V;l%_7ֳ.9NXԡSI UJuIϹ{Óe )FƨSDpO}>8JW! (?24ryhE,z$ o~{lHep# PKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tU:0i69nO+B.Kn,`= ?ZG# t|PKN\nword/styles.xml0 OAz1w}1.Nw![r TE vK~ݝb5g)xk!X=4J.kn#1a3R9ihž,q1B1P(R* |XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\OG9}? word/header1.xmlPKN\:j< m_rels/.relsPKN\)xq mword/document.xmlPKN\~0 word/_rels/document.xml.relsPKN\ docProps/app.xmlPKN\OabH docProps/core.xmlPKN\D word/fontTable.xmlPKN\Q@Gw [Content_Types].xmlPKN\n word/styles.xmlPKN\4Qn a word/settings.xmlPK z} ooxml/docxtest_tmp/test_12.docx000644 000765 000024 00000006246 15221665126 017203 0ustar00alexstaff000000 000000 PKN\:j< _rels/.relsMKA !nDH7LvwA&DхR=͛慥;X6-69-l#HkL>Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\Euz\word/document.xmlN0 }| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tUܝ #WNn|d vNY7i} adpC vk=Ȫ7PKN\7R%word/styles.xmlQO  14kdO?R\r{Y&nd8rj &)mee%6vxOl]ޭ܇Q>C\ι蔍^"+u|@jT40>M9m=\۰VK5FY: A_nFH6`_!{U'Ht$\ϒ6{^Vav'$JotɎr' &|mצ?ǢHҼLLE'`/IϹFwD4Uw|PKN\4Qnword/settings.xmlePn0 +#[zv`J$G)~aq{ӷhId4%|ί8/ǩȜ1KIB+!ѪGUpcAE&2fSP# C=%LlS7\*y/>XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\:j< _rels/.relsPKN\Euz\ word/document.xmlPKN\i~ word/_rels/document.xml.relsPKN\ docProps/app.xmlPKN\OabH BdocProps/core.xmlPKN\D 6word/fontTable.xmlPKN\< y[Content_Types].xmlPKN\7R% word/styles.xmlPKN\4Qn 8 word/settings.xmlPK <T ooxml/docxtest_tmp/test_9.docx000644 000765 000024 00000006126 15221665126 017126 0ustar00alexstaff000000 000000 PKN\:j< _rels/.relsMKA !nDH7LvwA&DхR=͛慥;X6-69-l#HkL>Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\E9~word/document.xmln0E }bB,.R0ƀU@5&U",0sޱf#Jf` >*2mMVIi&B:Ђ bJ3e n 9ne8(?cADFEQ]Q%Bea+Ē}n<[!JbݨLi5(Ǽ&m6U%BS ͟N}rv2w(f3-%nJ(^r{ϢT6^{T@EȁV { JTzlWhCwB u5aP3,mKS%&wWsO:%ւ[L'$}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tUܝ #WNn|d vNY7i} adpC vk=Ȫ7PKN\nword/styles.xml0 OAz1w}1.Nw![r TE vK~ݝb5g)xk!X=4J.kn#1a3R9ihž,q1B1P(R* |XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\:j< _rels/.relsPKN\E9~ word/document.xmlPKN\i~ word/_rels/document.xml.relsPKN\ docProps/app.xmlPKN\OabH ddocProps/core.xmlPKN\D Xword/fontTable.xmlPKN\< [Content_Types].xmlPKN\n word/styles.xmlPKN\4Qn word/settings.xmlPK < ooxml/docxtest_tmp/test_28.docx000644 000765 000024 00000006124 15221665127 017206 0ustar00alexstaff000000 000000 PKN\:j< _rels/.relsMKA !nDH7LvwA&DхR=͛慥;X6-69-l#HkL>Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\KB|word/document.xml]O0`1dD?+#ܿ|Dö N{Ү֟}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tUܝ #WNn|d vNY7i} adpC vk=Ȫ7PKN\nword/styles.xml0 OAz1w}1.Nw![r TE vK~ݝb5g)xk!X=4J.kn#1a3R9ihž,q1B1P(R* |XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\:j< _rels/.relsPKN\KB| word/document.xmlPKN\i~ word/_rels/document.xml.relsPKN\ docProps/app.xmlPKN\OabH bdocProps/core.xmlPKN\D Vword/fontTable.xmlPKN\< [Content_Types].xmlPKN\n word/styles.xmlPKN\4Qn word/settings.xmlPK < ooxml/docxtest_tmp/test_69.docx000644 000765 000024 00000006050 15221665127 017211 0ustar00alexstaff000000 000000 PKN\:j< _rels/.relsMKA !nDH7LvwA&DхR=͛慥;X6-69-l#HkL>Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\iTPword/document.xmln0 { {iB^NMiđK(&pğVVODVHI$4B*#oYw.-Jhm.#s&Z(f`{%bbE; pa穆#ULj2` #-t`,JR(KŰjNSfS;AWS:] PKN\i~word/_rels/document.xml.rels 0E~EM "M݈Vt6 (|Pąy{].|c$Vht%oKXgtznP^I:LJ:ItRd| L+]oaln:wiD{Q Iєc7B/<;/ |mvPKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tUܝ #WNn|d vNY7i} adpC vk=Ȫ7PKN\nword/styles.xml0 OAz1w}1.Nw![r TE vK~ݝb5g)xk!X=4J.kn#1a3R9ihž,q1B1P(R* |XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\:j< _rels/.relsPKN\iTP word/document.xmlPKN\i~ word/_rels/document.xml.relsPKN\ }docProps/app.xmlPKN\OabH 6docProps/core.xmlPKN\D *word/fontTable.xmlPKN\< m[Content_Types].xmlPKN\n word/styles.xmlPKN\4Qn word/settings.xmlPK < ooxml/docxtest_tmp/test_5.docx000644 000765 000024 00000006025 15221665126 017120 0ustar00alexstaff000000 000000 PKN\:j< _rels/.relsMKA !nDH7LvwA&DхR=͛慥;X6-69-l#HkL>Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\䈗=word/document.xmln .˲jo-[( o?X.YL{!p>?aRmth%蜤qB"9R9x^=Mqxv/6s8g2J-ob6#_sk k=O>IbRtX),TnAePU0Mjc6Huk!(Z|TN&iڹ,Z";8YFe'aF̴6 BgέK* ߊl;Ϣ҇T]fvohkٮ9hP?b<Św+{ ?Mt7PKN\i~word/_rels/document.xml.rels 0E~EM "M݈Vt6 (|Pąy{].|c$Vht%oKXgtznP^I:LJ:ItRd| L+]oaln:wiD{Q Iєc7B/<;/ |mvPKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tUܝ #WNn|d vNY7i} adpC vk=Ȫ7PKN\nword/styles.xml0 OAz1w}1.Nw![r TE vK~ݝb5g)xk!X=4J.kn#1a3R9ihž,q1B1P(R* |XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\:j< _rels/.relsPKN\䈗= word/document.xmlPKN\i~ lword/_rels/document.xml.relsPKN\ jdocProps/app.xmlPKN\OabH #docProps/core.xmlPKN\D word/fontTable.xmlPKN\< Z[Content_Types].xmlPKN\n word/styles.xmlPKN\4Qn word/settings.xmlPK < ooxml/docxtest_tmp/test_24.docx000644 000765 000024 00000012561 15221665126 017203 0ustar00alexstaff000000 000000 PKN\:j< _rels/.relsMKA !nDH7LvwA&DхR=͛慥;X6-69-l#HkL>Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\Dword/fontTable.xmlN0<;uBQ qB=wXO51}{\'PPox񬷟F=)g+\Gܭc8%2V + ٢Zm5O":켓Ȟx壍5AB Lot, V ado΀ق'hz/ .;0JT4+5^VbϦvz5)IQߢzU5\6ۣWM|~--o]d`i.qTxPKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\PJvword/_rels/document.xml.relsN0E|E=qRTI7>8?d({Bh" /gƾW] ηFg,luzv:t7>c }𱱠iRRjn<*IM5X>ӌeܾLYT-\mhgOՀt?_WFc!;89k-  .)v,܆Ѐ( uĿ SP/ס~n᧵d>Hu>L@tғFS&A&!1#>/PKN\4Qnword/settings.xmlePn0 +#[zv`J$G)~aq{ӷhId4%|ί8/ǩȜ1KIB+!ѪGUpcAE&2fSP# C=%LlS7\*y/>XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\h=word/header1.xmlMn0=>P ?pcMho1ҦRY?ycotH2uWl[l)1e}mN4Rs+ U{bE9B6MXse؈uhJ 8JΠoڡ|ܲiito&^ ArO)FY7qOvy#ߩ'mX@!^^nV_G{BZZ!1KثV:W] "{ ߷2g;> zS6]YR&8_ PKN\fZeword/styles.xmlN0F>~(20 L(@cA|z e|_N9_JS\ VupĞE¹Цg5LkMASBI.p=ϖV@h/v,Ji!ũ7Q$TXjHF$w?)_.3S_:'xtͭA[H>>]uC^7`AFW;WPKN\c[Content_Types].xml=O0w~E%NBM;1B2#c_C[ϹI#P>'tUud9I@s#^eސbY j_*{K(3cAc4N?݊Z U_Sntd6?T|Pb|tUM1XUu!c9{_Sx)BiW5$HX+لΆk xcDYdM|zZ4Yƶc^g@&$h 3 픓r%v~?A`$"dp M9MWu7Y]*k[:1h\Nбxr: ^qy=' śNِcVl+_Nrߐc•hX%tUf\ǖiup h Әbg6aЀ;iS7o`mKt L8e4{ۭئ[y1Cm$N4Rs*@= NE9B6ODse؄uhJ 8JΡoޡ|ܲii|of^ ArO)FY7u;tA!#ߩog<وTH!^^^nVF{F쩵bIGgCbZW_cgSm.3ER@oew$5}l KlK\'aG+PKN\yword/footnotes.xmln0 { { T4B/զ] $P*0Jlj# S sYkxEi&` \4IZ`lh1!(&-uG]t4Pf/ %1Fˤg, vAA$P5d9O)`em5@jbV í!81mPs5i/<?F(G޶"icw WKL+nWLUyTXWS |4,E)cPvgmbE&4rWH<)r5xvAO\N#76U,B7J]L PKN\:j< _rels/.relsPKN\D word/fontTable.xmlPKN\ CdocProps/app.xmlPKN\PJv word/_rels/document.xml.relsPKN\4Qn Tword/settings.xmlPKN\h= pword/header1.xmlPKN\fZe word/styles.xmlPKN\c #[Content_Types].xmlPKN\Yh  word/comments.xmlPKN\OabH N docProps/core.xmlPKN\lOG B word/document.xmlPKN\=5= word/footer1.xmlPKN\y {word/footnotes.xmlPK 7$ooxml/docxtest_tmp/test_73.docx000644 000765 000024 00000006040 15221665127 017203 0ustar00alexstaff000000 000000 PKN\:j< _rels/.relsMKA !nDH7LvwA&DхR=͛慥;X6-69-l#HkL>Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\WHword/document.xmln {.˲jo.[( o?Z.YL{AKAs ͡.~"ng%N "mqdZ ~T_iX.<$yIMF CXI`r1AUI.iPK.>lGӵ x-E˜6؉vjs},(7v0Kv}{ڜ,ceeK [ÌimgΜ[˗T~v&8f|+8>JnSuuxųZ}+rAQPC%X{(a6!`InMg8ܽ"Nt~7PKN\i~word/_rels/document.xml.rels 0E~EM "M݈Vt6 (|Pąy{].|c$Vht%oKXgtznP^I:LJ:ItRd| L+]oaln:wiD{Q Iєc7B/<;/ |mvPKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tUܝ #WNn|d vNY7i} adpC vk=Ȫ7PKN\nword/styles.xml0 OAz1w}1.Nw![r TE vK~ݝb5g)xk!X=4J.kn#1a3R9ihž,q1B1P(R* |XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\:j< _rels/.relsPKN\WH word/document.xmlPKN\i~ wword/_rels/document.xml.relsPKN\ udocProps/app.xmlPKN\OabH .docProps/core.xmlPKN\D "word/fontTable.xmlPKN\< e[Content_Types].xmlPKN\n word/styles.xmlPKN\4Qn word/settings.xmlPK < ooxml/docxtest_tmp/test_65.docx000644 000765 000024 00000007722 15221665127 017214 0ustar00alexstaff000000 000000 PKN\:word/header1.xmlMn0=>P ?pcMho1ҦR=߼7OFNYNX$R:go-n6}֔^>g6c'[*@=bE9B6MXse؈uhJ 8JΠkK>@tZ? BPSJQMMt;dA!.1Z";qDt5(K3kíSob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\.9$~Hword/document.xmlݎ  N*+JU6aЀ;8vJ{6o o'hb-E^7~ O |Zt)Jʨ;p*n1ɩğB 12}Y~NY/f b _͌0b6]Mc5âpk_$%mBЫĭ qW˺qW(77kR_돗1@^ml\Daޮ|ީ7Z6!\V)5ܱ[qM\=xy㝮Z=ԂAEvǡ'#sCC: M3&h;A5ːX&vj{IQz͝TW7ʀGm] V}h: Qz$`I~_[CpN0B}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tUTUU@6Qq Xkl}6*,x捼|6%:`YHeꂽVOlSޭ^`6O'JCk~NE9B6ODse؄uhJ 8JΡkK>lAtZ?BPSJQʹ&z,]nTa= ~;qLt'1٘) kíhkr6F,#f1aŤ8 횐 rdu`hRZKNw~5]si N5n$g]Q9Z 1SCvWFHv2RnwB]T $㯑3so]PKN\nword/styles.xml0 OAz1w}1.Nw![r TE vK~ݝb5g)xk!X=4J.kn#1a3R9ihž,q1B1P(R* |XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\: word/header1.xmlPKN\:j< h_rels/.relsPKN\.9$~H hword/document.xmlPKN\M9  word/_rels/document.xml.relsPKN\ 0docProps/app.xmlPKN\OabH docProps/core.xmlPKN\D word/fontTable.xmlPKN\B,R9 word/footer1.xmlPKN\$xP [Content_Types].xmlPKN\n  word/styles.xmlPKN\4Qn word/settings.xmlPK  ooxml/docxtest_tmp/test_64.docx000644 000765 000024 00000006605 15221665127 017212 0ustar00alexstaff000000 000000 PKN\:j< _rels/.relsMKA !nDH7LvwA&DхR=͛慥;X6-69-l#HkL>Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\mύlword/numbering.xmlU͎ &.PHݙ,f<Rƒp^QnNgl!TE L;[-웏TO:fpt)5Que,|i>L3|hhWY9J㠡Ly)H~dow+`ђdh(3IDl*ͭjePڛDΣmU Q3g!ϗ:'X> ?6wk.PKN\ Lword/document.xml]K0%[Zv7CilrIoC'H.rB>Γl_dHhUF>Wdl*]MΙRk]ڟ9ĊvAZS {d@FZX),nAPa3ԒO)AG^ A0筲4v+⠚^ MfY߮N3AN2^PvO$>̈V]G{BhZZ51[tǾYTrws.+>W:*?,Cq Cp.N %+{Eo?oPKN\uword/_rels/document.xml.rels 0E~EM""nDp+b:}` EހoqL=by;5$Fٲ5]`[$Ŗд. sTZ:4^K k4r'۔̀x۪j:j4%t5[DG}WP!/q3@)ܕ_>QSz@˯PKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tU Cv%1xqrrTXb%{xI{2#ρh I HE:-hEoџ:wr#K>:A?1B7 kBVbJ[w:5sz GNPKN\nword/styles.xml0 OAz1w}1.Nw![r TE vK~ݝb5g)xk!X=4J.kn#1a3R9ihž,q1B1P(R* |XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\:j< _rels/.relsPKN\mύl word/numbering.xmlPKN\ L word/document.xmlPKN\u word/_rels/document.xml.relsPKN\ docProps/app.xmlPKN\OabH FdocProps/core.xmlPKN\D :word/fontTable.xmlPKN\hڈI| }[Content_Types].xmlPKN\n word/styles.xmlPKN\4Qn word/settings.xmlPK | ooxml/docxtest_tmp/test_33.xml000644 000765 000024 00000000667 15221665127 017053 0ustar00alexstaff000000 000000 ooxml/docxtest_tmp/test_72.docx000644 000765 000024 00000006040 15221665127 017202 0ustar00alexstaff000000 000000 PKN\:j< _rels/.relsMKA !nDH7LvwA&DхR=͛慥;X6-69-l#HkL>Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\WHword/document.xmln {.˲jo.[( o?Z.YL{AKAs ͡.~"ng%N "mqdZ ~T_iX.<$yIMF CXI`r1AUI.iPK.>lGӵ x-E˜6؉vjs},(7v0Kv}{ڜ,ceeK [ÌimgΜ[˗T~v&8f|+8>JnSuuxųZ}+rAQPC%X{(a6!`InMg8ܽ"Nt~7PKN\i~word/_rels/document.xml.rels 0E~EM "M݈Vt6 (|Pąy{].|c$Vht%oKXgtznP^I:LJ:ItRd| L+]oaln:wiD{Q Iєc7B/<;/ |mvPKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tUܝ #WNn|d vNY7i} adpC vk=Ȫ7PKN\nword/styles.xml0 OAz1w}1.Nw![r TE vK~ݝb5g)xk!X=4J.kn#1a3R9ihž,q1B1P(R* |XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\:j< _rels/.relsPKN\WH word/document.xmlPKN\i~ wword/_rels/document.xml.relsPKN\ udocProps/app.xmlPKN\OabH .docProps/core.xmlPKN\D "word/fontTable.xmlPKN\< e[Content_Types].xmlPKN\n word/styles.xmlPKN\4Qn word/settings.xmlPK < ooxml/docxtest_tmp/test_25.docx000644 000765 000024 00000006174 15221665126 017207 0ustar00alexstaff000000 000000 PKN\:j< _rels/.relsMKA !nDH7LvwA&DхR=͛慥;X6-69-l#HkL>Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\+ޤword/document.xmlTn0}W 'ZUڷJc Nh;\TE-6˙3gۻW/HI& 4]EWRy/4[A_kAG`q`񴢻}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tUܝ #WNn|d vNY7i} adpC vk=Ȫ7PKN\nword/styles.xml0 OAz1w}1.Nw![r TE vK~ݝb5g)xk!X=4J.kn#1a3R9ihž,q1B1P(R* |XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\:j< _rels/.relsPKN\+ޤ word/document.xmlPKN\i~ word/_rels/document.xml.relsPKN\ docProps/app.xmlPKN\OabH docProps/core.xmlPKN\D ~word/fontTable.xmlPKN\< [Content_Types].xmlPKN\n .word/styles.xmlPKN\4Qn  word/settings.xmlPK <* ooxml/docxtest_tmp/test_4.docx000644 000765 000024 00000006041 15221665126 017115 0ustar00alexstaff000000 000000 PKN\:j< _rels/.relsMKA !nDH7LvwA&DхR=͛慥;X6-69-l#HkL>Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\qc mIword/document.xmlMn =>bggW&6*0hqscm*UV`xF_Z%{N)HLI" J .oV]^o0> ]AmN- v5+sM{4d@AZ4Xha\ Ә\|L k}3BR |5ҺV.KgM;e9B+d9nNDy 2{JeaVL:BkOs ?[[?OT{v/6^6lDA(Bp k !6B)X#?Hc&f PKN\i~word/_rels/document.xml.rels 0E~EM "M݈Vt6 (|Pąy{].|c$Vht%oKXgtznP^I:LJ:ItRd| L+]oaln:wiD{Q Iєc7B/<;/ |mvPKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tUܝ #WNn|d vNY7i} adpC vk=Ȫ7PKN\nword/styles.xml0 OAz1w}1.Nw![r TE vK~ݝb5g)xk!X=4J.kn#1a3R9ihž,q1B1P(R* |XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\:j< _rels/.relsPKN\qc mI word/document.xmlPKN\i~ xword/_rels/document.xml.relsPKN\ vdocProps/app.xmlPKN\OabH /docProps/core.xmlPKN\D #word/fontTable.xmlPKN\< f[Content_Types].xmlPKN\n word/styles.xmlPKN\4Qn word/settings.xmlPK < ooxml/docxtest_tmp/test_48.docx000644 000765 000024 00000006744 15221665127 017220 0ustar00alexstaff000000 000000 PKN\OG9}?word/header1.xmlMn0=>P ?pV޾6M % {>y#֟@VYLXZ`)u[w>kJ^m>gs&c+P.рkRH!`G6OXqوuPRZBʰ5U9K6(:MǺfе;m_N4nTa-?x&?ȓ1=PSob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\sHword/document.xmlN0} `1d,LJFӜޖGgbv)p~wK5A3c ͡lM[%|i9Rjy-k0B\ X0\Xyq|O H:+%9ҭ8Rr1,cZrd7HuK!(UƎMT3%viSY"@Sr&?I)g1ӪhF˗t~&8f(7>JSue0xӗJ}#2AQPCKrPjB\64}Vp8jPKN\~0word/_rels/document.xml.rels 0E~EM""nDVt6 ( ]y{dt-;(Zѕ}/`V;l%_7ֳ.9NXԡSI UJuIϹ{Óe )FƨSDpO}>8JW! (?24ryhE,z$ o~{lHep# PKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tU:0i69nO+B.Kn,`= ?ZG# t|PKN\nword/styles.xml0 OAz1w}1.Nw![r TE vK~ݝb5g)xk!X=4J.kn#1a3R9ihž,q1B1P(R* |XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\OG9}? word/header1.xmlPKN\:j< m_rels/.relsPKN\sH mword/document.xmlPKN\~0 word/_rels/document.xml.relsPKN\ docProps/app.xmlPKN\OabH docProps/core.xmlPKN\D word/fontTable.xmlPKN\Q@Gw [Content_Types].xmlPKN\n X word/styles.xmlPKN\4Qn 8 word/settings.xmlPK zT ooxml/docxtest_tmp/test_68.docx000644 000765 000024 00000006040 15221665127 017207 0ustar00alexstaff000000 000000 PKN\:j< _rels/.relsMKA !nDH7LvwA&DхR=͛慥;X6-69-l#HkL>Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\WHword/document.xmln {.˲jo.[( o?Z.YL{AKAs ͡.~"ng%N "mqdZ ~T_iX.<$yIMF CXI`r1AUI.iPK.>lGӵ x-E˜6؉vjs},(7v0Kv}{ڜ,ceeK [ÌimgΜ[˗T~v&8f|+8>JnSuuxųZ}+rAQPC%X{(a6!`InMg8ܽ"Nt~7PKN\i~word/_rels/document.xml.rels 0E~EM "M݈Vt6 (|Pąy{].|c$Vht%oKXgtznP^I:LJ:ItRd| L+]oaln:wiD{Q Iєc7B/<;/ |mvPKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tUܝ #WNn|d vNY7i} adpC vk=Ȫ7PKN\nword/styles.xml0 OAz1w}1.Nw![r TE vK~ݝb5g)xk!X=4J.kn#1a3R9ihž,q1B1P(R* |XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\:j< _rels/.relsPKN\WH word/document.xmlPKN\i~ wword/_rels/document.xml.relsPKN\ udocProps/app.xmlPKN\OabH .docProps/core.xmlPKN\D "word/fontTable.xmlPKN\< e[Content_Types].xmlPKN\n word/styles.xmlPKN\4Qn word/settings.xmlPK < ooxml/docxtest_tmp/test_29.docx000644 000765 000024 00000006103 15221665127 017204 0ustar00alexstaff000000 000000 PKN\:j< _rels/.relsMKA !nDH7LvwA&DхR=͛慥;X6-69-l#HkL>Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\o| kword/document.xmln0 { { L4B/զ*u{RQ`}%|n4-mf)xPmT(,SzBn&ZPiW MҦV%ahHE6kPTֽ2lAJ8}=3 2+G" 8+Ē yV#D_ єcFe*Hkj|<тvЦ Dhqm?3\ 'k'ch8^Vt^4jZ-YҭV~bʭ"gS,*~M̮ 49M^3{ ܇Cq^y;\Iy$NQm)iC!':FP痨]7ZZ\|Wuo:+PKN\i~word/_rels/document.xml.rels 0E~EM "M݈Vt6 (|Pąy{].|c$Vht%oKXgtznP^I:LJ:ItRd| L+]oaln:wiD{Q Iєc7B/<;/ |mvPKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tUܝ #WNn|d vNY7i} adpC vk=Ȫ7PKN\nword/styles.xml0 OAz1w}1.Nw![r TE vK~ݝb5g)xk!X=4J.kn#1a3R9ihž,q1B1P(R* |XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\:j< _rels/.relsPKN\o| k word/document.xmlPKN\i~ word/_rels/document.xml.relsPKN\ docProps/app.xmlPKN\OabH QdocProps/core.xmlPKN\D Eword/fontTable.xmlPKN\< [Content_Types].xmlPKN\n word/styles.xmlPKN\4Qn word/settings.xmlPK < ooxml/docxtest_tmp/test_52.docx000644 000765 000024 00000006075 15221665127 017210 0ustar00alexstaff000000 000000 PKN\:j< _rels/.relsMKA !nDH7LvwA&DхR=͛慥;X6-69-l#HkL>Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\Keword/document.xmln0 { {iBJUiI 8rBYK(}Hj8C5A3,c ͡U[%|i9Rjy-K0B{_ X0\Xyq|O H: %9-8Rr1,c$i]=BR9*[KcG"uI<дs#@}ϮoOΉh 2^PvO$̈V]G{Bhy|N{kBnj^6'Qu~2^sپ(%X{(a5`0.+ނ~+{7ju)3# Ӆa4xZ>v c::] PKN\i~word/_rels/document.xml.rels 0E~EM "M݈Vt6 (|Pąy{].|c$Vht%oKXgtznP^I:LJ:ItRd| L+]oaln:wiD{Q Iєc7B/<;/ |mvPKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tUܝ #WNn|d vNY7i} adpC vk=Ȫ7PKN\nword/styles.xml0 OAz1w}1.Nw![r TE vK~ݝb5g)xk!X=4J.kn#1a3R9ihž,q1B1P(R* |XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\:j< _rels/.relsPKN\Ke word/document.xmlPKN\i~ word/_rels/document.xml.relsPKN\ docProps/app.xmlPKN\OabH KdocProps/core.xmlPKN\D ?word/fontTable.xmlPKN\< [Content_Types].xmlPKN\n word/styles.xmlPKN\4Qn word/settings.xmlPK < ooxml/docxtest_tmp/test_13.docx000644 000765 000024 00000007104 15221665126 017176 0ustar00alexstaff000000 000000 PKN\:j< _rels/.relsMKA !nDH7LvwA&DхR=͛慥;X6-69-l#HkL>Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\owcword/document.xmln0 { { T4B/զݦ{D#qҾiBG;f{MphaDBU)?6tI\%(t) \&͕2 1'*sȀ!(튁L,1f% y,kB7u2fk(1Mz|N};gdNxq^ϴ63BeK9~OL8FYT|3^R)qsr![gjouPX8:xѭ-D)Y:Fl8+y/PKN\:Yword/_rels/document.xml.relsj0} XNJ(s)\VH}iI g%` *[[+*;JhZD|cٽKL 9"k[(7i&SKXAgTU2?=Z~`!HԾFVp~}E }`B.2]N[S"lO71J!PKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tU 6 fJ{+}>;/D91mtcϋoS0#.1ڻ SU~WQUd)~i*z~f+,ە"!4yǑ OG9ae+OHƙ 4]nzs(u~qhTf q1"O `-D08⼉]\PKN\4Qnword/settings.xmlePn0 +#[zv`J$G)~aq{ӷhId4%|ί8/ǩȜ1KIB+!ѪGUpcAE&2fSP# C=%LlS7\*y/>XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\:j< _rels/.relsPKN\owc word/document.xmlPKN\:Y word/_rels/document.xml.relsPKN\ docProps/app.xmlPKN\OabH [docProps/core.xmlPKN\D Oword/fontTable.xmlPKN\G| [Content_Types].xmlPKN\n word/styles.xmlPKN\V| word/footnotes.xmlPKN\4Qn word/settings.xmlPK | ooxml/docxtest_tmp/test_8.docx000644 000765 000024 00000006151 15221665126 017123 0ustar00alexstaff000000 000000 PKN\:j< _rels/.relsMKA !nDH7LvwA&DхR=͛慥;X6-69-l#HkL>Sob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\word/document.xmlN0E|E}tABbQQqCm3yJ.b+;wYx;Vh8 WL'BeyyݐE|5/DylXF$w΄oY%cmXARĀfZŸ/PlA-c$muFLP` 9d&eJuys! * c;"v֕`@i}"4Z~&x o^eeM#:he{[ӷ VRxۚ1؈B}]AdvcU,|Ȕ)xDUp$ƃɾM=^W;ZD: GꫫcЬpt[*9 zY&k(CwFSo):h6KYp<[ OpcPKN\i~word/_rels/document.xml.rels 0E~EM "M݈Vt6 (|Pąy{].|c$Vht%oKXgtznP^I:LJ:ItRd| L+]oaln:wiD{Q Iєc7B/<;/ |mvPKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tUܝ #WNn|d vNY7i} adpC vk=Ȫ7PKN\nword/styles.xml0 OAz1w}1.Nw![r TE vK~ݝb5g)xk!X=4J.kn#1a3R9ihž,q1B1P(R* |XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\:j< _rels/.relsPKN\ word/document.xmlPKN\i~ word/_rels/document.xml.relsPKN\ docProps/app.xmlPKN\OabH wdocProps/core.xmlPKN\D kword/fontTable.xmlPKN\< [Content_Types].xmlPKN\n word/styles.xmlPKN\4Qn word/settings.xmlPK < ooxml/docxtest_tmp/test_44.docx000644 000765 000024 00000007021 15221665127 017201 0ustar00alexstaff000000 000000 PKN\OG9}?word/header1.xmlMn0=>P ?pV޾6M % {>y#֟@VYLXZ`)u[w>kJ^m>gs&c+P.рkRH!`G6OXqوuPRZBʰ5U9K6(:MǺfе;m_N4nTa-?x&?ȓ1=PSob`RwN4)s!I >ȸj gLs-2)M‹,ZspCGdB a=z΋OѱD9_2Oy[5C wPKN\uword/document.xmlN0 y*[:!!bYAN)ABӸߎ}7m ْ-9JK0ae_(';6f`Cїـa>L&6C Yr-y,v ۀPPBF{OTk#˰ЪdVWe;F D~\PKN\~0word/_rels/document.xml.rels 0E~EM""nDVt6 ( ]y{dt-;(Zѕ}/`V;l%_7ֳ.9NXԡSI UJuIϹ{Óe )FƨSDpO}>8JW! (?24ryhE,z$ o~{lHep# PKN\docProps/app.xml 0л_roS=g{I6md-~atb=А8ky/I&CeY˅9Je@r]j,&.1͊dաi 6`WlWd>}| PKN\OabHdocProps/core.xmlmMK@ad+H MzԂBd,f?ؙ]F=>?T|Pb|tU:0i69nO+B.Kn,`= ?ZG# t|PKN\nword/styles.xml0 OAz1w}1.Nw![r TE vK~ݝb5g)xk!X=4J.kn#1a3R9ihž,q1B1P(R* |XLOߣSb8&ouɒNYLMc 81/5:P$uF_JXMwRlb{] PKN\OG9}? word/header1.xmlPKN\:j< m_rels/.relsPKN\u mword/document.xmlPKN\~0 word/_rels/document.xml.relsPKN\ docProps/app.xmlPKN\OabH docProps/core.xmlPKN\D word/fontTable.xmlPKN\Q@Gw [Content_Types].xmlPKN\n word/styles.xmlPKN\4Qn e word/settings.xmlPK z ooxml/tests/docx_helpers.tcl000664 000765 000024 00000006326 15213015413 016641 0ustar00alexstaff000000 000000 # helpers.tcl -- # # Shared test utilities for ooxml::docx tests. package require tcltest 2.5 namespace eval ::docxtest { variable tmpdir [file join [::tcltest::configure -tmpdir] docxtest_tmp] # Remove stale files from previous runs so the ecma-99.1 sweep # only validates documents produced by the current test run. if {[file isdirectory $tmpdir]} { file delete -force $tmpdir } file mkdir $tmpdir variable counter 0 namespace export newdoc tmpfile xpath countNodes haspart \ writedoc ziplist zipread xmlparse cleanup withDoc \ writeTextFile writeTinyPng } proc ::docxtest::newdoc {args} { return [::ooxml::docx::docx new {*}$args] } proc ::docxtest::tmpfile {{suffix .docx}} { variable tmpdir variable counter incr counter return [file join $tmpdir "test_${counter}${suffix}"] } proc ::docxtest::xpath {doc xpath {part word/document.xml}} { return [$doc xpath $xpath $part] } proc ::docxtest::countNodes {doc xpath {part word/document.xml}} { return [expr {int([$doc xpath "count($xpath)" $part])}] } proc ::docxtest::haspart {doc part} { return [expr {$part in [$doc xmlparts]}] } proc ::docxtest::writedoc {doc} { set f [tmpfile] $doc write $f return $f } proc ::docxtest::ziplist {file} { set result [list] if {![catch {set data [exec unzip -Z1 $file]}]} { foreach entry [split $data \n] { set entry [string trim $entry] if {$entry ne ""} { lappend result $entry } } } else { set fd [open "|unzip -l [list $file]" r] while {[gets $fd line] >= 0} { if {[regexp {\d+\s+\d[\d-]+\s+\d{2}:\d{2}\s+(.+)$} $line -> name]} { lappend result [string trim $name] } } catch {close $fd} } return $result } proc ::docxtest::zipread {file entry} { # Escape glob-special chars so unzip doesn't treat them as wildcards regsub -all {\[} $entry {\\[} entry regsub -all {\]} $entry {\\]} entry return [exec unzip -p $file $entry] } proc ::docxtest::xmlparse {xml} { return [dom parse $xml] } proc ::docxtest::writeTextFile {contents {suffix .xml}} { set f [tmpfile $suffix] set fd [open $f w] try { fconfigure $fd -encoding utf-8 puts -nonewline $fd $contents } finally { close $fd } return $f } proc ::docxtest::writeTinyPng {} { set f [tmpfile .png] set fd [open $f wb] try { # Tcl 9 removed the "binary" encoding alias. Opening the channel in # binary mode is sufficient and keeps the helper compatible with both # Tcl 8.6 and Tcl 9. puts -nonewline $fd [binary decode base64 \ {iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO0PpX0AAAAASUVORK5CYII=}] } finally { close $fd } return $f } proc ::docxtest::cleanup {doc} { catch {$doc destroy} } proc ::docxtest::withDoc {varname body args} { upvar 1 $varname doc set doc [newdoc {*}$args] set code [catch {uplevel 1 $body} result opts] catch {$doc destroy} return -options $opts $result } namespace eval :: { namespace import -force ::docxtest::* } ooxml/tests/docx-misc.test000664 000765 000024 00000030013 15213015413 016233 0ustar00alexstaff000000 000000 # misc.test -- # # Tests for remaining public methods: mark, markstart/markend, # url, jumpto, pagebreak, field, numbering, textbox, configure, # selectNodes/xpath, xmlparts, readpart/replace. package require tcltest 2.5 namespace import ::tcltest::* package require ooxml::docx # ────────────────────────────────────────────────────────────────── # Marks and bookmarks # ────────────────────────────────────────────────────────────────── test misc-1.1 {mark creates bookmarkStart and bookmarkEnd} -body { withDoc doc { $doc paragraph "Text" $doc mark mymark set starts [countNodes $doc {//w:bookmarkStart}] set ends [countNodes $doc {//w:bookmarkEnd}] list $starts $ends } } -result {1 1} test misc-1.2 {markstart/markend span} -body { withDoc doc { $doc paragraph "Before" $doc markstart myspan $doc paragraph "Inside span" $doc markend myspan set starts [countNodes $doc {//w:bookmarkStart}] set ends [countNodes $doc {//w:bookmarkEnd}] list $starts $ends } } -result {1 1} test misc-1.3 {markend without markstart raises error} -body { withDoc doc { $doc paragraph "Text" $doc markend nosuchmark } } -returnCodes error -match glob -result {*not started*} test misc-1.4 {duplicate markstart raises error} -body { withDoc doc { $doc paragraph "Text" $doc markstart dup $doc markstart dup } } -returnCodes error -match glob -result {*not unique*} # ────────────────────────────────────────────────────────────────── # URL (hyperlink) # ────────────────────────────────────────────────────────────────── test misc-2.1 {url creates hyperlink} -body { withDoc doc { $doc paragraph "Click " $doc url "here" "https://example.com" countNodes $doc {//w:hyperlink} } } -result 1 test misc-2.2 {url text content} -body { withDoc doc { $doc paragraph "Click " $doc url "link text" "https://example.com" xpath $doc {string(//w:hyperlink//w:t)} } } -result {link text} # ────────────────────────────────────────────────────────────────── # Jumpto (internal hyperlink) # ────────────────────────────────────────────────────────────────── test misc-3.1 {jumpto creates internal hyperlink} -body { withDoc doc { $doc paragraph "Target" $doc mark target $doc paragraph "Click " $doc jumpto "go to target" target countNodes $doc {//w:hyperlink} } } -result 1 # ────────────────────────────────────────────────────────────────── # Pagebreak # ────────────────────────────────────────────────────────────────── test misc-4.1 {pagebreak creates page break} -body { withDoc doc { $doc paragraph "Page 1" $doc pagebreak $doc paragraph "Page 2" countNodes $doc {//w:br[@w:type='page']} } } -result 1 # ────────────────────────────────────────────────────────────────── # Field # ────────────────────────────────────────────────────────────────── test misc-5.1 {PAGE field} -body { withDoc doc { $doc paragraph "Page " $doc field PAGE countNodes $doc {//w:fldChar} } } -result 3 ;# begin + separate + end test misc-5.2 {NUMPAGES field} -body { withDoc doc { $doc paragraph "Total: " $doc field NUMPAGES set instr [xpath $doc {string(//w:instrText)}] expr {[string match *NUMPAGES* $instr]} } } -result 1 # ────────────────────────────────────────────────────────────────── # Configure # ────────────────────────────────────────────────────────────────── test misc-6.1 {configure sets creator} -body { withDoc doc { $doc configure -creator "Test Author" xpath $doc {string(//*[local-name()='creator'])} docProps/core.xml } } -result {Test Author} test misc-6.2 {configure sets title} -body { withDoc doc { $doc configure -title "Test Document" xpath $doc {string(//*[local-name()='title'])} docProps/core.xml } } -result {Test Document} test misc-6.3 {configure sets description} -body { withDoc doc { $doc configure -description "A test" xpath $doc {string(//*[local-name()='description'])} docProps/core.xml } } -result {A test} # ────────────────────────────────────────────────────────────────── # xmlparts and selectNodes # ────────────────────────────────────────────────────────────────── test misc-7.1 {xmlparts lists all parts} -body { withDoc doc { set parts [$doc xmlparts] expr { "word/document.xml" in $parts && "word/styles.xml" in $parts && "word/settings.xml" in $parts } } } -result 1 test misc-7.2 {xmlparts with pattern} -body { withDoc doc { set parts [$doc xmlparts word/*] # Should include word/ parts but not docProps/ expr { "word/document.xml" in $parts && "docProps/core.xml" ni $parts } } } -result 1 test misc-7.3 {selectNodes works} -body { withDoc doc { $doc paragraph "Test" set result [$doc selectNodes {count(//w:p)}] expr {$result == 1} } } -result 1 # ────────────────────────────────────────────────────────────────── # Numbering # ────────────────────────────────────────────────────────────────── test misc-8.1 {numbering abstractNum creates part} -body { withDoc doc { $doc numbering abstractNum 0 { {-numberFormat decimal -levelText "%1." -align start} } haspart $doc word/numbering.xml } } -result 1 test misc-8.2 {numbering delete abstractNum} -body { withDoc doc { $doc numbering abstractNum 0 { {-numberFormat decimal -levelText "%1." -align start} } $doc numbering delete abstractNum 0 countNodes $doc {//w:abstractNum} word/numbering.xml } } -result 0 # ────────────────────────────────────────────────────────────────── # Section management # ────────────────────────────────────────────────────────────────── test misc-9.1 {pagesetup stores settings} -body { withDoc doc { $doc pagesetup -sizeAndOrientation {orientation landscape} $doc paragraph "Body" set f [writedoc $doc] set xml [zipread $f word/document.xml] expr {[string match *landscape* $xml]} } } -result 1 test misc-9.2 {sectionstart/sectionend} -body { withDoc doc { $doc paragraph "Section 1" $doc sectionstart -sectionType continuous $doc paragraph "Section 2" $doc sectionend $doc paragraph "Section 3" # Should have section break paragraph countNodes $doc {//w:sectPr} } } -result 2 test misc-9.3 {sectionend without sectionstart raises error} -body { withDoc doc { $doc sectionend } } -returnCodes error -match glob -result {*no section started*} # ────────────────────────────────────────────────────────────────── # readpart / replace / textbox # ────────────────────────────────────────────────────────────────── test misc-10.1 {readpart replaces settings part from file} -body { withDoc doc { set f [writeTextFile { }] $doc readpart word/settings.xml $f xpath $doc {string(//w:defaultTabStop/@w:val)} word/settings.xml } } -result 1440 test misc-10.2 {replace updates all matching parts by default} -body { withDoc doc { set hId [$doc header { $doc paragraph "Alpha header" }] $doc pagesetup -defaultHeader $hId $doc paragraph "Alpha body" $doc replace Alpha Beta list \ [xpath $doc {string(//w:p[1]//w:t)}] \ [xpath $doc {string(//w:t)} word/header1.xml] } } -result {{Beta body} {Beta header}} test misc-10.3 {replace can be limited to matching parts} -body { withDoc doc { set hId [$doc header { $doc paragraph "Alpha header" }] $doc pagesetup -defaultHeader $hId $doc paragraph "Alpha body" $doc replace Alpha Beta word/header* list \ [xpath $doc {string(//w:p[1]//w:t)}] \ [xpath $doc {string(//w:t)} word/header1.xml] } } -result {{Alpha body} {Beta header}} test misc-10.4 {textbox creates anchored drawing with content} -body { withDoc doc { $doc textbox \ -name "Callout Box" \ -dimension {width 914400 height 457200} \ -bodyAtts {wrap none numCol 2} { $doc paragraph "Inside box" } list \ [countNodes $doc {//wps:txbx}] \ [xpath $doc {string(//wp:docPr/@name)}] \ [xpath $doc {string(//wps:txbx//w:t)}] \ [xpath $doc {string(//wps:bodyPr/@wrap)}] } } -result {1 {Callout Box} {Inside box} none} # ────────────────────────────────────────────────────────────────── # Destroy # ────────────────────────────────────────────────────────────────── test misc-11.1 {destroy cleans up} -body { set doc [docxtest::newdoc] $doc paragraph "Test" $doc destroy # Object should no longer exist catch {$doc paragraph "After destroy"} err expr {$err ne ""} } -result 1 cleanupTests ooxml/tests/docx-tables.test000664 000765 000024 00000004260 15213015413 016557 0ustar00alexstaff000000 000000 # table.test -- # # Tests for table, tablerow, tablecell, simpletable. package require tcltest 2.5 namespace import ::tcltest::* package require ooxml::docx test table-1.1 {basic table structure} -body { withDoc doc { $doc table { $doc tablerow { $doc tablecell { $doc paragraph "A1" } $doc tablecell { $doc paragraph "B1" } } $doc tablerow { $doc tablecell { $doc paragraph "A2" } $doc tablecell { $doc paragraph "B2" } } } set t [countNodes $doc {//w:tbl}] set r [countNodes $doc {//w:tr}] set c [countNodes $doc {//w:tc}] list $t $r $c } } -result {1 2 4} test table-1.2 {table cell content} -body { withDoc doc { $doc table { $doc tablerow { $doc tablecell { $doc paragraph "Hello" } } } xpath $doc {string(//w:tc//w:t)} } } -result Hello test table-1.3 {table with style} -body { withDoc doc { $doc style table "Grid Table" -styleid GridTable $doc table -style "Grid Table" { $doc tablerow { $doc tablecell { $doc paragraph "Cell" } } } xpath $doc {string(//w:tblPr/w:tblStyle/@w:val)} } } -result GridTable test table-1.4 {cell vertical alignment} -body { withDoc doc { $doc table { $doc tablerow { $doc tablecell -vAlign center { $doc paragraph "Centered" } } } xpath $doc {string(//w:tcPr/w:vAlign/@w:val)} } } -result center test table-1.5 {cell background} -body { withDoc doc { $doc table { $doc tablerow { $doc tablecell -background FF0000 { $doc paragraph "Red" } } } xpath $doc {string(//w:tcPr/w:shd/@w:fill)} } } -result FF0000 test table-2.1 {simpletable} -body { withDoc doc { $doc simpletable {{A1 B1} {A2 B2}} set r [countNodes $doc {//w:tr}] set c [countNodes $doc {//w:tc}] list $r $c } } -result {2 4} cleanupTests ooxml/tests/test_worksheets_xml_missing.xlsx000644 000765 000024 00000016402 14764622263 022257 0ustar00alexstaff000000 000000 PK!bh^[Content_Types].xml (N0EHC-Jܲ@5*Q>ēƪc[iiBj7{2hnmƻR U^7/%rZY@1__fqR4DAJh>Vƹ Z9NV8ʩji){^-I"{v^P!XS)bRrKs(3`c07M4ZƐk+|\|z(P6h_-[@!Pk2n}?L %ddN"m,ǞDO97*~ɸ8Oc|nEB!$};{[2PK!U0#L _rels/.rels (MO0 HݐBKwAH!T~I$ݿ'TG~xl/_rels/workbook.xml.rels (RMK0 0wvt/"Uɴ)&!3~*]XK/oyv5+zl;obG s>,8(%"D҆4j0u2jsMY˴S쭂 )fCy I< y!+EfMyk K5=|t G)s墙UtB),fPK!"Zxl/sharedStrings.xml\A 0Ew "hB;@3.3̢B'2HҴ\R^&WCFr(׫jHba jp37ZoÿBO PK!nXxl/theme/theme1.xmlYϋ7? swkfl/{lg&!䨵eɻ1!PcP^ P%kMiSȿ'#nn -Y27ߓ4/ݍsSNXv*dvop1,mw{i.-;?[FB̶e>f/Nل1pNݘkJPI\'A16vҤ4ާp.F4ݗCaLJU 9B8cvd&` /}'<Ó?f;(_|ٟ_㹎O~s;&[x{W# >$1U|`1Mydc!b@ض^] ju[) xy~sA,#_b+r,y2u lc(1B۟@Ydau8‘!Ɩ&pn%Cr`$Ri -˨m=|d"@B~h.Pl39D1Dd#HG:Dz)sc̹ϵ ={tTC]Ę0Bʙ$B":63yq@p"BptUT$|2O->.a2 $9SONԳtZ;)Z;|?(=4Ocxg ;~^7څPuv7.'}x;4@Vj+72(iT'e#"`_U)MO3cVYm)j08۱VrwGhvm 4]ʼNnyI@'$Lu Ʋw$΅E¢)/C@mX?9j Qr_{PK!@|Ԇ xl/styles.xmlTmo0>iwj!K"Z"UI}u$Vl%w:m{szs=3cVB*u>_`uTUTh2|bߥ֝s fE-LR{OT'1V_a8'r{,DR6AeCqݩH҆P=F3Z;V k^,dI)OkEnZzR*/o~GT%$OK-A*:TޭSo+'9 V'<8fT S47N gٔ?;T9O+NZQSA.S2!~/5R,2 cp!AzOz7âc'_Gvd*Z.W q,B{lwāZTpO⭌/^vDG*, 5}o";p^ZS$)#l-M[ЧoהM͕5PxzS~ $_.>c̋4`NK2;V,+4t"d= 4Rڊ&{pͶV0B)"{huRs2oZ gmB86 }-ʼ`;q6V)ee>]ޟ$+(j%nHぁE;XR]]50T<>Vő{XYC֡Òx1jhVGђ>  J5̝/=.KYb8{汯]lby.y[StWU?Q3pP{dD[]+' Ѯ%n30L\\/fq2_̖wEIeCqq6ֆb鵖PK!-=]docProps/core.xml (N0HC{8RYI*JHqm6}{ A;ή/Z$E(EzݬgJF+(ZW97k VrUHPAi+OdžKL0pHD'#|ڦ ;Lt6)k4aS)[AWƶmv ~[?Ƶn[`^RCU1I;_Ü_KjuV}B:D?+f,nbBb2ߐhwwᆂ<6π2PK! '0docProps/app.xml (n0 n@VQzذq{gd:*KIgomɟqY1 1"CoBeϋ"K<I\ϟ*#YL[TQ26f,{V NVoyjГo=qGM`zPZ֪  \SnYħ׿!{Nɩz)Z:T 8\@]K䩠eƤUG % Zĸ}ۘ kE}7h)mܿDQ~󡁃`aᜳ0W{`G6Sy+ehZ/}[[ |yQw8nXPwzB@ϯfwRSPK-!bh^[Content_Types].xmlPK-!U0#L _rels/.relsPK-!>xl/_rels/workbook.xml.relsPK-!"Zxl/sharedStrings.xmlPK-!nX xl/theme/theme1.xmlPK-!@|Ԇ xl/styles.xmlPK-!_8xl/worksheets/sheet1.xmlPK-!-=]adocProps/core.xmlPK-! '0docProps/app.xmlPK Cooxml/tests/test_sheet1_xml_missing.xlsx000644 000765 000024 00000016461 14764622263 021257 0ustar00alexstaff000000 000000 PK!bh^[Content_Types].xml (N0EHC-Jܲ@5*Q>ēƪc[iiBj7{2hnmƻR U^7/%rZY@1__fqR4DAJh>Vƹ Z9NV8ʩji){^-I"{v^P!XS)bRrKs(3`c07M4ZƐk+|\|z(P6h_-[@!Pk2n}?L %ddN"m,ǞDO97*~ɸ8Oc|nEB!$};{[2PK!U0#L _rels/.rels (MO0 HݐBKwAH!T~I$ݿ'TG~xl/_rels/workbook.xml.rels (RMK0 0wvt/"Uɴ)&!3~*]XK/oyv5+zl;obG s>,8(%"D҆4j0u2jsMY˴S쭂 )fCy I< y!+EfMyk K5=|t G)s墙UtB),fPK!L|4xl/workbook.xmlTn0?zXJR?( p/4SJRޕTn}I^%,9=U|cV) >%΅ڧqa4:r&w6ʦtN<*fǺ;6s85{XnKWI/+bB!1oE!8,5o*P1 m)j;U-p3q]R'҆$>t%VnP^_ !ᩗ̪Id֭r ON~[0M=o BzO+ ɡ`t4axaV5a/Jl 'lg+IcdJ"df{pޞ. ozH/$~pdl,T) rg2t~ľtv0g]HT@JwbZJIf#g%atprf8"A]7_MQ4 Gh2\׫j݌'ÃVasf{BX'z1T ePK!"Zxl/sharedStrings.xml\A 0Ew "hB;@3.3̢B'2HҴ\R^&WCFr(׫jHba jp37ZoÿBO PK!nXxl/theme/theme1.xmlYϋ7? swkfl/{lg&!䨵eɻ1!PcP^ P%kMiSȿ'#nn -Y27ߓ4/ݍsSNXv*dvop1,mw{i.-;?[FB̶e>f/Nل1pNݘkJPI\'A16vҤ4ާp.F4ݗCaLJU 9B8cvd&` /}'<Ó?f;(_|ٟ_㹎O~s;&[x{W# >$1U|`1Mydc!b@ض^] ju[) xy~sA,#_b+r,y2u lc(1B۟@Ydau8‘!Ɩ&pn%Cr`$Ri -˨m=|d"@B~h.Pl39D1Dd#HG:Dz)sc̹ϵ ={tTC]Ę0Bʙ$B":63yq@p"BptUT$|2O->.a2 $9SONԳtZ;)Z;|?(=4Ocxg ;~^7څPuv7.'}x;4@Vj+72(iT'e#"`_U)MO3cVYm)j08۱VrwGhvm 4]ʼNnyI@'$Lu Ʋw$΅E¢)/C@mX?9j Qr_{PK!@|Ԇ xl/styles.xmlTmo0>iwj!K"Z"UI}u$Vl%w:m{szs=3cVB*u>_`uTUTh2|bߥ֝s fE-LR{OT'1V_a8'r{,DR6AeCqݩH҆P=F3Z;V k^,dI)OkEnZzR*/o~GT%$OK-A*:TޭSo+'9 V'<8fT S47N gٔ?;T9O+NZQSA.S2!~/5R,2 cp!AzOz7âc'_Gvd*Z.W q,B{lwāZTpO⭌/^vDG*, 5xl/_rels/workbook.xml.relsPK-!L|4xl/workbook.xmlPK-!"ZP xl/sharedStrings.xmlPK-!nX$ xl/theme/theme1.xmlPK-!@|Ԇ xl/styles.xmlPK-!-=]docProps/core.xmlPK-! '0 docProps/app.xmlPK :ooxml/tests/docx-pkg.test000664 000765 000024 00000017344 15213015413 016075 0ustar00alexstaff000000 000000 # packaging.test -- # # Tests for package structure: content types, relationships, # part presence, and structural validity of generated .docx files. package require tcltest 2.5 namespace import ::tcltest::* package require ooxml::docx # ────────────────────────────────────────────────────────────────── # Minimal document package # ────────────────────────────────────────────────────────────────── test pkg-1.1 {minimal doc has required parts} -body { withDoc doc { $doc paragraph "Test" set f [writedoc $doc] set parts [ziplist $f] set required { {[Content_Types].xml} _rels/.rels word/document.xml word/_rels/document.xml.rels word/styles.xml word/settings.xml word/fontTable.xml docProps/core.xml docProps/app.xml } set missing [list] foreach rp $required { if {$rp ni $parts} { lappend missing $rp } } set missing } } -result {} test pkg-1.2 {core-properties uses package relationship type} -body { withDoc doc { $doc paragraph "Test" set f [writedoc $doc] set xml [zipread $f _rels/.rels] expr {[string match *package/2006/relationships/metadata/core-properties* $xml]} } } -result 1 # ────────────────────────────────────────────────────────────────── # Document with footnotes # ────────────────────────────────────────────────────────────────── test pkg-2.1 {footnotes part in zip} -body { withDoc doc { $doc paragraph "Text" $doc footnote { $doc paragraph "Note." } set f [writedoc $doc] set parts [ziplist $f] expr {"word/footnotes.xml" in $parts} } } -result 1 test pkg-2.2 {footnotes has content type} -body { withDoc doc { $doc paragraph "Text" $doc footnote { $doc paragraph "Note." } set f [writedoc $doc] set ct [zipread $f {[Content_Types].xml}] expr {[string match *footnotes* $ct]} } } -result 1 test pkg-2.3 {footnotes has relationship} -body { withDoc doc { $doc paragraph "Text" $doc footnote { $doc paragraph "Note." } set f [writedoc $doc] set rels [zipread $f word/_rels/document.xml.rels] expr {[string match *footnotes* $rels]} } } -result 1 # ────────────────────────────────────────────────────────────────── # Document with header and footer # ────────────────────────────────────────────────────────────────── test pkg-3.1 {header part in zip} -body { withDoc doc { set hId [$doc header { $doc paragraph "H" }] $doc pagesetup -defaultHeader $hId $doc paragraph "Body" set f [writedoc $doc] set parts [ziplist $f] expr {"word/header1.xml" in $parts} } } -result 1 test pkg-3.2 {header has content type} -body { withDoc doc { set hId [$doc header { $doc paragraph "H" }] $doc pagesetup -defaultHeader $hId $doc paragraph "Body" set f [writedoc $doc] set ct [zipread $f {[Content_Types].xml}] expr {[string match *header* $ct]} } } -result 1 # ────────────────────────────────────────────────────────────────── # Document with comments # ────────────────────────────────────────────────────────────────── test pkg-4.1 {comments part in zip} -body { withDoc doc { $doc paragraph "Text" $doc comment -author "A" { $doc paragraph "Note." } set f [writedoc $doc] set parts [ziplist $f] expr {"word/comments.xml" in $parts} } } -result 1 test pkg-4.2 {comments has content type and relationship} -body { withDoc doc { $doc paragraph "Text" $doc comment -author "A" { $doc paragraph "Note." } set f [writedoc $doc] set ct [zipread $f {[Content_Types].xml}] set rels [zipread $f word/_rels/document.xml.rels] expr {[string match *comments* $ct] && [string match *comments* $rels]} } } -result 1 # ────────────────────────────────────────────────────────────────── # Additional package relationships # ────────────────────────────────────────────────────────────────── test pkg-5.1 {endnotes has part content type and relationship} -body { withDoc doc { $doc paragraph "Text" $doc endnote { $doc paragraph "End note." } set f [writedoc $doc] set parts [ziplist $f] set ct [zipread $f {[Content_Types].xml}] set rels [zipread $f word/_rels/document.xml.rels] expr {"word/endnotes.xml" in $parts && [string match *endnotes* $ct] && [string match *endnotes* $rels]} } } -result 1 test pkg-5.2 {numbering has part content type and relationship} -body { withDoc doc { $doc numbering abstractNum 7 { {-numberFormat decimal -levelText "%1." -align start} } $doc paragraph "List item" set f [writedoc $doc] set parts [ziplist $f] set ct [zipread $f {[Content_Types].xml}] set rels [zipread $f word/_rels/document.xml.rels] expr {"word/numbering.xml" in $parts && [string match *numbering* $ct] && [string match *numbering* $rels]} } } -result 1 test pkg-5.3 {pagesetup writes header and footer references} -body { withDoc doc { set hId [$doc header { $doc paragraph "Header" }] set fId [$doc footer { $doc paragraph "Footer" }] $doc pagesetup -defaultHeader $hId -defaultFooter $fId $doc paragraph "Body" set f [writedoc $doc] set xml [zipread $f word/document.xml] set ddoc [xmlparse $xml] $ddoc selectNodesNamespaces { w http://schemas.openxmlformats.org/wordprocessingml/2006/main r http://schemas.openxmlformats.org/officeDocument/2006/relationships } set headerRef [$ddoc selectNodes {string(//w:sectPr/w:headerReference[@w:type='default']/@r:id)}] set footerRef [$ddoc selectNodes {string(//w:sectPr/w:footerReference[@w:type='default']/@r:id)}] $ddoc delete expr {$headerRef eq $hId && $footerRef eq $fId} } } -result 1 test pkg-5.4 {external hyperlink relationship uses TargetMode External} -body { withDoc doc { $doc paragraph "See " $doc url "example" "https://example.com" set f [writedoc $doc] set rels [zipread $f word/_rels/document.xml.rels] expr {[string match *TargetMode=\"External\"* $rels] && [string match *https://example.com* $rels]} } } -result 1 cleanupTests ooxml/tests/docx-basic.test000664 000765 000024 00000017126 15213015413 016373 0ustar00alexstaff000000 000000 # basic.test -- # # Tests for paragraph, append, br, tab, and basic run formatting. package require tcltest 2.5 namespace import ::tcltest::* package require ooxml::docx # ────────────────────────────────────────────────────────────────── # Paragraph creation # ────────────────────────────────────────────────────────────────── test basic-1.1 {single paragraph} -body { withDoc doc { $doc paragraph "Hello" countNodes $doc {//w:p} } } -result 1 test basic-1.2 {multiple paragraphs} -body { withDoc doc { $doc paragraph "One" $doc paragraph "Two" $doc paragraph "Three" countNodes $doc {//w:p} } } -result 3 test basic-1.3 {paragraph text content} -body { withDoc doc { $doc paragraph "Hello, World!" xpath $doc {string(//w:p[1]//w:t)} } } -result {Hello, World!} test basic-1.4 {empty paragraph} -body { withDoc doc { $doc paragraph "" countNodes $doc {//w:p} } } -result 1 # ────────────────────────────────────────────────────────────────── # Append to paragraph # ────────────────────────────────────────────────────────────────── test basic-2.1 {append creates additional run} -body { withDoc doc { $doc paragraph "Start " $doc append "end" countNodes $doc {//w:p[1]/w:r} } } -result 2 test basic-2.2 {append text content} -body { withDoc doc { $doc paragraph "A" $doc append "B" $doc append "C" xpath $doc {string(//w:p[1]/w:r[3]//w:t)} } } -result C # ────────────────────────────────────────────────────────────────── # Character formatting # ────────────────────────────────────────────────────────────────── test basic-3.1 {bold} -body { withDoc doc { $doc paragraph "Bold" -bold on xpath $doc {string(//w:r/w:rPr/w:b/@w:val)} } } -result 1 test basic-3.2 {italic} -body { withDoc doc { $doc paragraph "Italic" -italic on xpath $doc {string(//w:r/w:rPr/w:i/@w:val)} } } -result 1 test basic-3.3 {color} -body { withDoc doc { $doc paragraph "Red" -color FF0000 xpath $doc {string(//w:r/w:rPr/w:color/@w:val)} } } -result FF0000 test basic-3.4 {fontsize in half-points} -body { withDoc doc { $doc paragraph "Big" -fontsize 28 xpath $doc {string(//w:r/w:rPr/w:sz/@w:val)} } } -result 28 test basic-3.5 {underline single} -body { withDoc doc { $doc paragraph "U" -underline single xpath $doc {string(//w:r/w:rPr/w:u/@w:val)} } } -result single test basic-3.6 {strike} -body { withDoc doc { $doc paragraph "S" -strike on xpath $doc {string(//w:r/w:rPr/w:strike/@w:val)} } } -result 1 test basic-3.7 {multiple formatting options} -body { withDoc doc { $doc paragraph "Combo" -bold on -italic on -color 00FF00 set b [xpath $doc {string(//w:r/w:rPr/w:b/@w:val)}] set i [xpath $doc {string(//w:r/w:rPr/w:i/@w:val)}] set c [xpath $doc {string(//w:r/w:rPr/w:color/@w:val)}] list $b $i $c } } -result {1 1 00FF00} # ────────────────────────────────────────────────────────────────── # Paragraph options # ────────────────────────────────────────────────────────────────── test basic-4.1 {alignment} -body { withDoc doc { $doc paragraph "Centered" -align center xpath $doc {string(//w:p/w:pPr/w:jc/@w:val)} } } -result center test basic-4.2 {spacing} -body { withDoc doc { $doc paragraph "Spaced" -spacing {before 240 after 120} set b [xpath $doc {string(//w:p/w:pPr/w:spacing/@w:before)}] set a [xpath $doc {string(//w:p/w:pPr/w:spacing/@w:after)}] list $b $a } } -result {240 120} test basic-4.3 {paragraph background} -body { withDoc doc { $doc paragraph "Yellow" -background FFFF00 set val [xpath $doc {string(//w:p/w:pPr/w:shd/@w:val)}] set fill [xpath $doc {string(//w:p/w:pPr/w:shd/@w:fill)}] list $val $fill } } -result {clear FFFF00} test basic-4.4 {paragraph shading} -body { withDoc doc { $doc paragraph "Shaded" -shading {type clear color auto fill CCCCCC} xpath $doc {string(//w:p/w:pPr/w:shd/@w:fill)} } } -result CCCCCC # ────────────────────────────────────────────────────────────────── # Break and tab # ────────────────────────────────────────────────────────────────── test basic-5.1 {br inserts break} -body { withDoc doc { $doc paragraph "Before" $doc br countNodes $doc {//w:br} } } -result 1 test basic-5.2 {br with count} -body { withDoc doc { $doc paragraph "Before" $doc br 3 countNodes $doc {//w:br} } } -result 3 test basic-5.3 {tab inserts tab} -body { withDoc doc { $doc paragraph "Before" $doc tab countNodes $doc {//w:tab} } } -result 1 # ────────────────────────────────────────────────────────────────── # Write and basic package structure # ────────────────────────────────────────────────────────────────── test basic-6.1 {write produces file} -body { withDoc doc { $doc paragraph "Test" set f [writedoc $doc] file exists $f } } -result 1 test basic-6.2 {write produces valid zip} -body { withDoc doc { $doc paragraph "Test" set f [writedoc $doc] set parts [ziplist $f] expr { "word/document.xml" in $parts && {[Content_Types].xml} in $parts && "_rels/.rels" in $parts && "word/_rels/document.xml.rels" in $parts } } } -result 1 test basic-6.3 {write sectPr is last child of body} -body { withDoc doc { $doc paragraph "Test" set f [writedoc $doc] set xml [zipread $f word/document.xml] set ddoc [xmlparse $xml] $ddoc selectNodesNamespaces {w http://schemas.openxmlformats.org/wordprocessingml/2006/main} set root [$ddoc documentElement] set body [$root selectNodes w:body] set last [$body lastChild] set result [$last localName] $ddoc delete set result } } -result sectPr cleanupTests ooxml/tests/xlsx-formula.test000644 000765 000024 00000004516 14764622263 017036 0ustar00alexstaff000000 000000 # # Commands covered: simple excel sheet # # # (c) 2021 Alexander Schoepe # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # if {[lsearch [namespace children] ::tcltest] == -1} { package require tcltest 2 namespace import -force ::tcltest::* loadTestedCommands } package require ooxml if {![package vsatisfies [package present Tcl] 9]} { package require vfs::zip } test Formula-1.1 {Write a Simple Excel Sheet} { set cDT {2020-03-07 07:12:23} set mCT $cDT set spreadsheet [::ooxml::xl_write new -creator {User A} -created $cDT -modifiedby {User B} -modified $mCT -application {Tcl Test}] if {[set sheet [$spreadsheet worksheet {Sheet 1}]] > -1} { return 1 } return 0 } 1 test Formula-2.1 {single fomula C1} { upvar #0 ${spreadsheet}::cells cells set cell [$spreadsheet cell $sheet {} -index 0,2 -formula {A1+B1}] return $cells(1,$cell) } {t s f A1+B1} test FormulaVertical-3.1 {vertical shared formula C3} { upvar #0 ${spreadsheet}::cells cells set cell [$spreadsheet cell $sheet {} -index 2,2 -formula {A3+B3} -formularef C3:C5 -formulaidx 0] return $cells(1,$cell) } {t s f A3+B3 fsi 0 fsr C3:C5} test FormulaVertical-3.2 {vertical shared formula C4} { upvar #0 ${spreadsheet}::cells cells set cell [$spreadsheet cell $sheet {} -index 3,2 -formulaidx 0] return $cells(1,$cell) } {t s f {} fsi 0} test FormulaVertical-3.3 {vertical shared formula C5} { upvar #0 ${spreadsheet}::cells cells set cell [$spreadsheet cell $sheet {} -index C5 -formulaidx 0] return $cells(1,$cell) } {t s f {} fsi 0} test FormulaVertical-4.1 {horizontal shared formula A9} { upvar #0 ${spreadsheet}::cells cells set cell [$spreadsheet cell $sheet {} -index A9 -formula {A7+A8} -formularef 8,0:8,2 -formulaidx 1] return $cells(1,$cell) } {t s f A7+A8 fsi 1 fsr A9:C9} test FormulaVertical-4.2 {horizontal shared formula B9} { upvar #0 ${spreadsheet}::cells cells set cell [$spreadsheet cell $sheet {} -index 8,1 -formulaidx 1] return $cells(1,$cell) } {t s f {} fsi 1} test FormulaVertical-4.3 {horizontal shared formula C9} { upvar #0 ${spreadsheet}::cells cells set cell [$spreadsheet cell $sheet {} -index C9 -formulaidx 1] return $cells(1,$cell) } {t s f {} fsi 1} $spreadsheet destroy # cleanup ::tcltest::cleanupTests return ooxml/tests/xlsx-benchmark.test000644 000765 000024 00000003240 15221552110 017272 0ustar00alexstaff000000 000000 # # Commands covered: simple excel sheet # # # (c) 2019 Rolf Ade # (c) 2019 Alexander Schoepe # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # if {[lsearch [namespace children] ::tcltest] == -1} { package require tcltest 2 namespace import -force ::tcltest::* loadTestedCommands } package require ooxml proc doit {rows cols} { set spreadsheet [::ooxml::xl_write new -creator "me"] set sheet [$spreadsheet worksheet "my data"] set row 0 while {$row < $rows} { set col 0 while {$col < $cols} { $spreadsheet cell $sheet "Cell $row,$col" incr col } $spreadsheet row $sheet incr row } $spreadsheet write "$rows-$cols.xlsx" $spreadsheet destroy } test Benchmark-1.1 {benchmark cell generating} { set rc 1 set list {usec per cell} set limit -1 foreach {rows cols} { 500 10 1000 10 3000 10 5000 10 } { set usec [lindex [time {doit $rows $cols}] 0] # Floating point division - integer division would truncate away # the very differences this test is looking for. set perCell [expr {double($usec) / $rows / $cols}] lappend list [format %.2f $perCell] if {$limit == -1} { # Allow 10 percent growth over the first (smallest) run. The per # cell time must stay roughly constant; a superlinear growth with # the number of cells is what this test guards against. set limit [expr {$perCell * 1.10}] } if {$perCell > $limit} { puts $list set rc 0 } } return $rc } 1 file delete -force 500-10.xlsx 1000-10.xlsx 3000-10.xlsx 5000-10.xlsx # cleanup ::tcltest::cleanupTests return ooxml/tests/docx-import.test000664 000765 000024 00000017530 15213015413 016623 0ustar00alexstaff000000 000000 # import.test -- # # Tests for import, recursive .rels handling, binary target # import, subgraph cleanup, and transactional rollback. # # These tests generate their own fixture documents at runtime # so no external .docx files are needed. package require tcltest 2.5 namespace import ::tcltest::* package require ooxml::docx # ────────────────────────────────────────────────────────────────── # Helper: create a source document with specific features # ────────────────────────────────────────────────────────────────── # createSourceWithHeader -- # Create a .docx that contains a header with text. # Returns the file path. proc createSourceWithHeader {} { set src [docxtest::newdoc] set hId [$src header { $src paragraph "Source Header" }] $src pagesetup -defaultHeader $hId $src paragraph "Source body" set f [docxtest::tmpfile .docx] $src write $f $src destroy return $f } # createSourceWithFootnote -- # Create a .docx that contains a footnote. # Returns the file path. proc createSourceWithFootnote {} { set src [docxtest::newdoc] $src paragraph "Source text" $src footnote { $src paragraph "Source footnote." } set f [docxtest::tmpfile .docx] $src write $f $src destroy return $f } # createSourceWithStyles -- # Create a .docx with custom styles. # Returns the file path. proc createSourceWithStyles {} { set src [docxtest::newdoc] $src style paragraph "ImportedHeading" -bold on -fontsize 32 $src style character "ImportedEmphasis" -italic on -color FF0000 $src paragraph "Styled text" -pstyle "ImportedHeading" set f [docxtest::tmpfile .docx] $src write $f $src destroy return $f } # createSourceWithComment -- # Create a .docx with a comment. # Returns the file path. proc createSourceWithComment {} { set src [docxtest::newdoc] $src paragraph "Commented text" $src comment -author "Importer" { $src paragraph "Imported comment." } set f [docxtest::tmpfile .docx] $src write $f $src destroy return $f } # ────────────────────────────────────────────────────────────────── # Basic import # ────────────────────────────────────────────────────────────────── test import-1.1 {import styles from another doc} -body { set srcFile [createSourceWithStyles] withDoc doc { $doc import styles $srcFile set names [$doc style names paragraph] expr {"ImportedHeading" in $names} } } -result 1 test import-1.2 {import styles replaces existing} -body { set srcFile [createSourceWithStyles] withDoc doc { # Create a local style first $doc style paragraph "LocalStyle" -italic on # Import replaces styles.xml entirely $doc import styles $srcFile set names [$doc style names paragraph] # Local style gone, imported present list [expr {"LocalStyle" in $names}] [expr {"ImportedHeading" in $names}] } } -result {0 1} test import-1.3 {import returns rId for word/ parts} -body { set srcFile [createSourceWithHeader] withDoc doc { set rId [$doc import header1 $srcFile] expr {$rId ne ""} } } -result 1 # ────────────────────────────────────────────────────────────────── # Import with relationships # ────────────────────────────────────────────────────────────────── test import-2.1 {imported header available as part} -body { set srcFile [createSourceWithHeader] withDoc doc { $doc import header1 $srcFile docxtest::haspart $doc word/header1.xml } } -result 1 test import-2.2 {imported header content preserved} -body { set srcFile [createSourceWithHeader] withDoc doc { $doc import header1 $srcFile docxtest::xpath $doc {string(//w:t)} word/header1.xml } } -result {Source Header} test import-2.3 {import header twice replaces cleanly} -body { set srcFile [createSourceWithHeader] withDoc doc { $doc import header1 $srcFile # Import again — should replace, not duplicate $doc import header1 $srcFile docxtest::haspart $doc word/header1.xml } } -result 1 # ────────────────────────────────────────────────────────────────── # Import and write integration # ────────────────────────────────────────────────────────────────── test import-3.1 {imported styles survive write} -body { set srcFile [createSourceWithStyles] withDoc doc { $doc import styles $srcFile $doc paragraph "Body" set f [docxtest::writedoc $doc] # Read back and check set xml [docxtest::zipread $f word/styles.xml] expr {[string match *ImportedHeading* $xml]} } } -result 1 test import-3.2 {imported header survives write} -body { set srcFile [createSourceWithHeader] withDoc doc { set rId [$doc import header1 $srcFile] $doc pagesetup -defaultHeader $rId $doc paragraph "Body" set f [docxtest::writedoc $doc] set parts [docxtest::ziplist $f] expr {"word/header1.xml" in $parts} } } -result 1 # ────────────────────────────────────────────────────────────────── # Import error handling / rollback # ────────────────────────────────────────────────────────────────── test import-4.1 {import nonexistent file raises error} -body { withDoc doc { $doc import styles /no/such/file.docx } } -returnCodes error -match glob -result * test import-4.2 {import nonexistent part raises error} -body { set srcFile [createSourceWithStyles] withDoc doc { $doc import header99 $srcFile } } -returnCodes error -match glob -result * test import-4.3 {failed import leaves object usable} -body { withDoc doc { $doc paragraph "Before" catch { $doc import styles /no/such/file.docx } $doc paragraph "After" docxtest::countNodes $doc {//w:p} } } -result 2 # ────────────────────────────────────────────────────────────────── # Content type propagation # ────────────────────────────────────────────────────────────────── test import-5.1 {imported header gets content type} -body { set srcFile [createSourceWithHeader] withDoc doc { $doc import header1 $srcFile $doc paragraph "Body" set f [docxtest::writedoc $doc] set ct [docxtest::zipread $f {[Content_Types].xml}] expr {[string match *header* $ct]} } } -result 1 cleanupTests ooxml/tests/xlsx-simple.test000644 000765 000024 00000010772 14764622263 016663 0ustar00alexstaff000000 000000 # # Commands covered: simple excel sheet # # # (c) 2019 Alexander Schoepe # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # if {[lsearch [namespace children] ::tcltest] == -1} { package require tcltest 2 namespace import -force ::tcltest::* loadTestedCommands } package require ooxml #package require vfs::zip test SimpleExcelWrite-1.1 {Write a Simple Excel Sheet} { set cDT {2019-10-31 15:10:23} set mCT {2019-10-31 17:20:45} set spreadsheet [::ooxml::xl_write new -creator {User A} -created $cDT -modifiedby {User B} -modified $mCT -application {Tcl Test}] if {[set sheet [$spreadsheet worksheet {Sheet 1}]] > -1} { $spreadsheet cell $sheet {Tcl Test - SimpleExcel} -index A1 } if {[set sheet [$spreadsheet worksheet {Sheet 2}]] > -1} { $spreadsheet cell $sheet {Sheet 2} -index B2 } $spreadsheet write simple.xlsx $spreadsheet destroy return [file exists simple.xlsx] } 1 test SimpleExcelRead-1.2 {Read a Simple Excel Sheets} { array set workbook [ooxml::xl_read simple.xlsx] return [llength $workbook(sheets)] } 2 test SimpleExcelRead-1.3 {Read a Simple Excel Sheet1 A1} { return $workbook(0,c,0,0) } A1 test SimpleExcelRead-1.4 {Read a Simple Excel Sheet2 B2} { return $workbook(1,c,1,1) } B2 if {[package vsatisfies [package present Tcl] 9]} { test MountXLSX-2.1 {Mount XLSX File} { catch {zipfs mount simple.xlsx xlsx} mnt } 0 variable zipfs "//zipfs:/" } elseif {$::ooxml::zipAccessMethod eq "tcllib"} { test MountXLSX-2.1 {Mount XLSX File} { catch { ::zipfile::decode::open simple.xlsx variable zipdesc [::zipfile::decode::archive] } } 0 } else { test MountXLSX-2.1 {Mount XLSX File} { catch {vfs::zip::Mount simple.xlsx xlsx} mnt } 0 variable zipfs "" } test DocPropsApp-3.1 {Parse xlsx/docProps/app.xml} { if {$::ooxml::zipAccessMethod eq "tcllib"} { set doc [dom parse [encoding convertfrom utf-8\ [::zipfile::decode::getfile $zipdesc docProps/app.xml]]] } else { set fd [open ${zipfs}xlsx/docProps/app.xml r] fconfigure $fd -encoding utf-8 set doc [dom parse [read $fd]] close $fd } return [set appDoc [string match domDoc* $doc]] } 1 set appXmlNs { x http://schemas.openxmlformats.org/officeDocument/2006/extended-properties vt http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes } testConstraint appCheck $appDoc test DocPropsApp-3.2 {Check Application -application} appCheck { $doc selectNodesNamespaces $appXmlNs $doc selectNodes string(/x:Properties/x:Application) } {Tcl Test} test DocPropsApp-3.3 {Check Sheet Counter} appCheck { $doc selectNodesNamespaces $appXmlNs $doc selectNodes string(/x:Properties/x:HeadingPairs/vt:vector/vt:variant/vt:i4) } $sheet $doc delete test DocPropsCore-4.1 {Parse xlsx/docProps/core.xml} { if {$::ooxml::zipAccessMethod eq "tcllib"} { set doc [dom parse [encoding convertfrom utf-8\ [::zipfile::decode::getfile $zipdesc docProps/core.xml]]] } else { set fd [open ${zipfs}xlsx/docProps/core.xml r] fconfigure $fd -encoding utf-8 set doc [dom parse [read $fd]] close $fd } set coreXmlNs { cp http://schemas.openxmlformats.org/package/2006/metadata/core-properties dc http://purl.org/dc/elements/1.1/ dcterms http://purl.org/dc/terms/ } return [set coreDoc [string match domDoc* $doc]] } 1 testConstraint coreCheck $coreDoc test DocPropsCore-4.2 {Check Creator -creator} coreCheck { $doc selectNodesNamespaces $coreXmlNs $doc selectNodes string(/cp:coreProperties/dc:creator) } {User A} test DocPropsCore-4.3 {Check Modified By -modifiedby} coreCheck { $doc selectNodesNamespaces $coreXmlNs $doc selectNodes string(/cp:coreProperties/cp:lastModifiedBy) } {User B} test DocPropsCore-4.4 {Check Modified By -created} coreCheck { $doc selectNodesNamespaces $coreXmlNs $doc selectNodes string(/cp:coreProperties/dcterms:created) } {2019-10-31T14:10:23Z} test DocPropsCore-4.5 {Check Modified By -modified} coreCheck { $doc selectNodesNamespaces $coreXmlNs $doc selectNodes string(/cp:coreProperties/dcterms:modified) } {2019-10-31T16:20:45Z} $doc delete if {[package vsatisfies [package present Tcl] 9]} { zipfs unmount $mnt } elseif {$::ooxml::zipAccessMethod eq "tcllib"} { ::zipfile::decode::close } else { vfs::zip::Unmount $mnt xlsx } file delete -force simple.xlsx # cleanup ::tcltest::cleanupTests return # Local Variables: # tcl-indent-level: 2 # End: ooxml/tests/xlsx-namedfmts.test000644 000765 000024 00000007577 14764622263 017361 0ustar00alexstaff000000 000000 # # Commands covered: simple excel sheet # # # (c) 2019 Alexander Schoepe # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # if {[lsearch [namespace children] ::tcltest] == -1} { package require tcltest 2 namespace import -force ::tcltest::* loadTestedCommands } package require ooxml #package require vfs::zip test NamedFormats-1.1 {Write a Simple Excel Sheet} { set cDT {2020-03-07 07:12:23} set mCT $cDT set spreadsheet [::ooxml::xl_write new -creator {User A} -created $cDT -modifiedby {User B} -modified $mCT -application {Tcl Test}] if {[set sheet [$spreadsheet worksheet {Sheet 1}]] > -1} { return 1 } return 0 } 1 test NamedFormats-2.1 {numberformat dec2t} { $spreadsheet numberformat -decimal -separator -tag dec2t } 4 test NamedFormats-2.2 {numberformat dec2t} { upvar #0 ${spreadsheet}::tags tags info exists tags(numFmts,dec2t) } 1 test NamedFormats-2.2 {numberformat dec2t} { upvar #0 ${spreadsheet}::tags tags return $tags(numFmts,dec2t) } 4 test NamedFormats-2.3 {style numberformat dec2t} { $spreadsheet style -numfmt dec2t -tag dec2t } 1 test NamedFormats-2.4 {style numberformat dec2t} { upvar #0 ${spreadsheet}::tags tags if {[info exists tags(styles,dec2t)]} { return $tags(styles,dec2t) } return -1 } 1 test NamedFormats-3.1 {numberformat fraction2} { $spreadsheet numberformat -format {# ??/??} -tag fraction2 } 166 test NamedFormats-3.2 {numberformat fraction2} { upvar #0 ${spreadsheet}::tags tags info exists tags(numFmts,fraction2) } 1 test NamedFormats-3.2 {numberformat fraction2} { upvar #0 ${spreadsheet}::tags tags return $tags(numFmts,fraction2) } 166 test NamedFormats-3.3 {style numberformat fraction2} { $spreadsheet style -numfmt fraction2 -tag fraction2 } 2 test NamedFormats-3.4 {style numberformat fraction2} { upvar #0 ${spreadsheet}::tags tags if {[info exists tags(styles,fraction2)]} { return $tags(styles,fraction2) } return -1 } 2 test NamedFormats-4.1 {font font9} { $spreadsheet font -size 9 -tag font9 } 1 test NamedFormats-4.2 {font font9} { upvar #0 ${spreadsheet}::tags tags info exists tags(fonts,font9) } 1 test NamedFormats-4.2 {font font9} { upvar #0 ${spreadsheet}::tags tags return $tags(fonts,font9) } 1 test NamedFormats-4.3 {style font font9} { $spreadsheet style -font font9 -tag font9 } 3 test NamedFormats-4.4 {style font font9} { upvar #0 ${spreadsheet}::tags tags if {[info exists tags(styles,font9)]} { return $tags(styles,font9) } return -1 } 3 test NamedFormats-5.1 {fill yellow} { $spreadsheet fill -fgcolor FFFFFF00 -bgcolor 64 -patterntype solid -tag yellow } 2 test NamedFormats-5.2 {fill yellow} { upvar #0 ${spreadsheet}::tags tags info exists tags(fills,yellow) } 1 test NamedFormats-5.2 {fill yellow} { upvar #0 ${spreadsheet}::tags tags return $tags(fills,yellow) } 2 test NamedFormats-5.3 {style fill yellow} { $spreadsheet style -fill yellow -tag yellow } 4 test NamedFormats-5.4 {style fill yellow} { upvar #0 ${spreadsheet}::tags tags if {[info exists tags(styles,yellow)]} { return $tags(styles,yellow) } return -1 } 4 test NamedFormats-6.1 {border bDiagonal} { $spreadsheet border -diagonalstyle medium -diagonaldirection up -tag bDiagonal } 1 test NamedFormats-6.2 {border bDiagonal} { upvar #0 ${spreadsheet}::tags tags info exists tags(borders,bDiagonal) } 1 test NamedFormats-6.2 {border bDiagonal} { upvar #0 ${spreadsheet}::tags tags return $tags(borders,bDiagonal) } 1 test NamedFormats-6.3 {style border bDiagonal} { $spreadsheet style -border bDiagonal -tag bDiagonal } 5 test NamedFormats-6.4 {style border bDiagonal} { upvar #0 ${spreadsheet}::tags tags if {[info exists tags(styles,bDiagonal)]} { return $tags(styles,bDiagonal) } return -1 } 5 $spreadsheet destroy # cleanup ::tcltest::cleanupTests return ooxml/tests/xlsx-view.test000644 000765 000024 00000007270 15221555007 016331 0ustar00alexstaff000000 000000 # # Commands covered: view -activetab, arrayDeleteSheet, presetsheets # # Regression tests for ticket 3933595861: deleting a sheet from a # workbook read with xl_read and writing it back via presetstyles/ # presetsheets produced a file with an out of range activeTab, which # Excel treats as a corrupted file. Also covers the hyperlink transfer # of presetsheets, which errored out on a wrong dict key. # # # (c) 2026 Alexander Schoepe # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # if {[lsearch [namespace children] ::tcltest] == -1} { package require tcltest 2 namespace import -force ::tcltest::* loadTestedCommands } package require ooxml # Create a workbook with the three worksheets Alpha, Beta and Gamma, # a hyperlink cell on every sheet and the given active tab. proc makeViewTestWorkbook {file activetab} { set spreadsheet [::ooxml::xl_write new -creator {Tcl Test}] foreach name {Alpha Beta Gamma} { set sheet [$spreadsheet worksheet $name] $spreadsheet row $sheet $spreadsheet cell $sheet "Head $name" -string $spreadsheet cell $sheet 42 $spreadsheet row $sheet $spreadsheet cell $sheet link -string -hyperlink https://example.com/ -tooltip tip } $spreadsheet view -activetab $activetab $spreadsheet write $file $spreadsheet destroy } test View-1.1 {view -activetab is written and read back} { makeViewTestWorkbook view-1.xlsx 2 array set wb [::ooxml::xl_read view-1.xlsx] set result [dict get $wb(view) activetab] array unset wb set result } 2 test View-1.2 {out of range activetab is clamped to 0 on write} { set spreadsheet [::ooxml::xl_write new] $spreadsheet worksheet {Sheet 1} $spreadsheet view -activetab 99 $spreadsheet write view-2.xlsx $spreadsheet destroy array set wb [::ooxml::xl_read view-2.xlsx] set result [dict get $wb(view) activetab] array unset wb set result } 0 test View-2.1 {arrayDeleteSheet shifts the active tab} { makeViewTestWorkbook view-1.xlsx 2 array set wb [::ooxml::xl_read view-1.xlsx] ::ooxml::arrayDeleteSheet wb 0 set result [dict get $wb(view) activetab] array unset wb set result } 1 test View-2.2 {arrayDeleteSheet clamps the active tab if the active sheet is removed} { makeViewTestWorkbook view-1.xlsx 2 array set wb [::ooxml::xl_read view-1.xlsx] ::ooxml::arrayDeleteSheet wb 2 set result [dict get $wb(view) activetab] array unset wb set result } 1 test View-3.1 {ticket 3933595861: delete a sheet, preset and write a valid file} { makeViewTestWorkbook view-1.xlsx 2 array set wb [::ooxml::xl_read view-1.xlsx] ::ooxml::arrayDeleteSheet wb 0 set spreadsheet [::ooxml::xl_write new] $spreadsheet presetstyles wb $spreadsheet presetsheets wb $spreadsheet write view-3.xlsx $spreadsheet destroy array unset wb # The written file must reference an existing sheet as active tab # and contain the two remaining sheets in the original order. array set wb [::ooxml::xl_read view-3.xlsx] set result [list [llength $wb(sheets)] $wb(0,n) $wb(1,n) [dict get $wb(view) activetab]] array unset wb set result } {2 Beta Gamma 1} test Preset-1.1 {presetsheets transfers hyperlinks and tooltips} { makeViewTestWorkbook view-1.xlsx 0 array set wb [::ooxml::xl_read view-1.xlsx] set spreadsheet [::ooxml::xl_write new] $spreadsheet presetstyles wb $spreadsheet presetsheets wb $spreadsheet write view-4.xlsx $spreadsheet destroy array unset wb array set wb [::ooxml::xl_read view-4.xlsx] set result $wb(0,l,1,0) array unset wb set result } {l https://example.com/ t tip} file delete -force view-1.xlsx view-2.xlsx view-3.xlsx view-4.xlsx # cleanup ::tcltest::cleanupTests return ooxml/tests/docx-headerfooter.test000664 000765 000024 00000004305 15213015413 017754 0ustar00alexstaff000000 000000 # headerfooter.test -- # # Tests for header and footer creation, relationship scoping, # and transactional rollback. package require tcltest 2.5 namespace import ::tcltest::* package require ooxml::docx test hf-1.1 {header creates part} -body { withDoc doc { set rId [$doc header { $doc paragraph "Header text" }] expr {$rId ne "" && [haspart $doc word/header1.xml]} } } -result 1 test hf-1.2 {header content} -body { withDoc doc { $doc header { $doc paragraph "My Header" } xpath $doc {string(//w:t)} word/header1.xml } } -result {My Header} test hf-1.3 {footer creates part} -body { withDoc doc { set rId [$doc footer { $doc paragraph "Footer text" }] expr {$rId ne "" && [haspart $doc word/footer1.xml]} } } -result 1 test hf-1.4 {multiple headers get unique numbers} -body { withDoc doc { $doc header { $doc paragraph "H1" } $doc header { $doc paragraph "H2" } set h1 [haspart $doc word/header1.xml] set h2 [haspart $doc word/header2.xml] list $h1 $h2 } } -result {1 1} test hf-1.5 {header relationship in document.xml.rels} -body { withDoc doc { set rId [$doc header { $doc paragraph "H" }] set rels [$doc xmlparts word/_rels/document.xml.rels] expr {$rels ne ""} } } -result 1 test hf-2.1 {header rollback on script error} -constraints mutation -body { withDoc doc { catch { $doc header { error "deliberate failure" } } # No orphaned header part should remain expr {![haspart $doc word/header1.xml]} } } -result 1 test hf-2.2 {footer rollback on script error} -constraints mutation -body { withDoc doc { catch { $doc footer { error "deliberate failure" } } expr {![haspart $doc word/footer1.xml]} } } -result 1 test hf-3.1 {pagesetup with header and footer} -body { withDoc doc { set hId [$doc header { $doc paragraph "Header" }] set fId [$doc footer { $doc paragraph "Footer" }] $doc pagesetup -defaultHeader $hId -defaultFooter $fId $doc paragraph "Body" set f [writedoc $doc] file exists $f } } -result 1 cleanupTests ooxml/tests/xlsx-misc.test000644 000765 000024 00000007600 14764622263 016321 0ustar00alexstaff000000 000000 # # Commands covered: internal helper procs # # # (c) 2019 Alexander Schoepe # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # if {[lsearch [namespace children] ::tcltest] == -1} { package require tcltest 2 namespace import -force ::tcltest::* loadTestedCommands } package require ooxml test ScanDateTime-1.1 {ScanDateTime takes args} -body { ::ooxml::ScanDateTime } -returnCodes error -result "wrong # args: should be \"::ooxml::ScanDateTime scan ?iso8601?\"" test ScanDateTime-1.2 {ScanDateTime ole time} { ::ooxml::ScanDateTime {2019-10-31 15:10:23} } 43769.63221064815 test ScanDateTime-1.3 {ScanDateTime iso8601} { ::ooxml::ScanDateTime {2019-10-31 15:10:23} 1 } 2019-10-31T15:10:23 test Column-1.1 {Column takes args} -body { ::ooxml::Column } -returnCodes error -result "wrong # args: should be \"::ooxml::Column col\"" test Column-1.2 {Column 3} { ::ooxml::Column 3 } D test Column-1.3 {Column 33} { ::ooxml::Column 33 } AH if {[package vsatisfies [package present Tcl] 9]} { set result "cannot use non-numeric string \"A\" as left operand of \"%\"" } else { set result "can't use non-numeric string as operand of \"%\"" } test Column-1.4 {Column A} -body { ::ooxml::Column A } -returnCodes error -result $result test RowColumnToString-1.1 {RowColumnToString takes args} -body { ::ooxml::RowColumnToString } -returnCodes error -result "wrong # args: should be \"::ooxml::RowColumnToString rowcol\"" test RowColumnToString-1.2 {RowColumnToString 0,0} { ::ooxml::RowColumnToString 0,0 } A1 test RowColumnToString-1.3 {RowColumnToString 33,33} { ::ooxml::RowColumnToString 33,33 } AH34 test RowColumnToString-1.4 {RowColumnToString A1} -body { ::ooxml::RowColumnToString A1 } -returnCodes error -result "expected integer but got \"A1\"" test RowColumnToString-1.5 {RowColumnToString 0} { ::ooxml::RowColumnToString 0 } 1 test StringToRowColumn-1.1 {StringToRowColumn takes args} -body { ::ooxml::StringToRowColumn } -returnCodes error -result "wrong # args: should be \"::ooxml::StringToRowColumn name\"" test StringToRowColumn-1.2 {StringToRowColumn A1} { ::ooxml::StringToRowColumn A1 } 0,0 test StringToRowColumn-1.3 {StringToRowColumn AH34} { ::ooxml::StringToRowColumn AH34 } 33,33 test StringToRowColumn-1.4 {StringToRowColumn 0} { ::ooxml::StringToRowColumn 0 } -1,-1 test IndexToString-1.1 {IndexToString takes args} -body { ::ooxml::IndexToString } -returnCodes error -result "wrong # args: should be \"::ooxml::IndexToString index\"" test IndexToString-1.2 {IndexToString 0,0} { ::ooxml::IndexToString 0,0 } A1 test IndexToString-1.3 {IndexToString A1} { ::ooxml::IndexToString A1 } A1 test IndexToString-1.4 {IndexToString 1} { ::ooxml::IndexToString 1 } {} test IndexToString-1.5 {IndexToString A} { ::ooxml::IndexToString A } {} test ::ooxml::IndexFix1.1 {IndexFix A1} { ::ooxml::IndexFix A1 } {$A$1} test CalcColumnWidth-1.1 {CalcColumnWidth takes args} -body { ::ooxml::CalcColumnWidth } -returnCodes error -result "wrong # args: should be \"::ooxml::CalcColumnWidth numberOfCharacters ?maximumDigitWidth? ?pixelPadding?\"" test CalcColumnWidth-1.2 {CalcColumnWidth 11} { ::ooxml::CalcColumnWidth 11 } 11.7109375 test Color-1.1 {Color takes args} -body { ::ooxml::Color } -returnCodes error -result "wrong # args: should be \"::ooxml::Color color\"" test color-1.2 {Color {}} { ::ooxml::Color {} } {} test color-1.3 {Color auto} { ::ooxml::Color auto } {auto 1} test color-1.4 {Color none} { ::ooxml::Color none } {none 1} test color-1.5 {Color 6} { ::ooxml::Color 6 } {indexed 6} test color-1.6 {Color Fuchsia} { ::ooxml::Color Fuchsia } {indexed 6} test color-1.7 {Color 00FF00FF} { ::ooxml::Color 00FF00FF } {indexed 6} test color-1.8 {Color 00123456} { ::ooxml::Color 00123456 } {rgb 00123456} # cleanup ::tcltest::cleanupTests return ooxml/tests/xlsx-readerror.test000644 000765 000024 00000002751 14764622263 017355 0ustar00alexstaff000000 000000 # # Commands covered: read errorneous excel sheets # # # (c) 2024 Harald Oehlmann # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # if {[lsearch [namespace children] ::tcltest] == -1} { package require tcltest 2 namespace import -force ::tcltest::* loadTestedCommands } package require ooxml test readerrorxlsx-1 {Error out as the file xl/worksheets.xml is missing} -body { ooxml::xl_read [file join [file dir [info script]] test_worksheets_xml_missing.xlsx] } -returnCodes error -result "No valid xlsx file" test readerrorxlsx-2 {Error out as the file xl/worksheets/sheet1.xml is missing} -body { ooxml::xl_read [file join [file dir [info script]] test_sheet1_xml_missing.xlsx] } -returnCodes error -result "Excel file error: No data for sheet 1" if {[package vsatisfies [package present Tcl] 9]} { test readerrorxlsx-3 {Error out as the file xl/worksheets/sheet1.xml is no utf8} -body { ooxml::xl_read [file join [file dir [info script]] test_sheet1_xml_no_utf8.xlsx] } -returnCodes error -match glob -result "*invalid or incomplete multibyte or wide character" } test readerrorxlsx-4 {Error out as the file xl/worksheets/sheet1.xml is no xml} -body { ooxml::xl_read [file join [file dir [info script]] test_sheet1_xml_no_xml.xlsx] } -returnCodes error -match glob -result "error \"syntax error\" at line 1 character 0*" # cleanup ::tcltest::cleanupTests return # Local Variables: # tcl-indent-level: 2 # End: ooxml/tests/docx-math.test000664 000765 000024 00000021266 15213015413 016243 0ustar00alexstaff000000 000000 # math.test -- # # Tests for math zone entry/exit, math sub-methods, guard, # valPrefix switching, and OMML structure. package require tcltest 2.5 namespace import ::tcltest::* package require ooxml::docx # ────────────────────────────────────────────────────────────────── # Math zone guard # ────────────────────────────────────────────────────────────────── test math-1.1 {mrun outside math raises error} -body { withDoc doc { $doc mrun "x" } } -returnCodes error -match glob -result {*must be called from within a math zone*} test math-1.2 {mfrac outside math raises error} -body { withDoc doc { $doc mfrac { $doc mrun "a" } { $doc mrun "b" } } } -returnCodes error -match glob -result {*must be called from within a math zone*} test math-1.3 {msub outside math raises error} -body { withDoc doc { $doc msub { $doc mrun "x" } { $doc mrun "i" } } } -returnCodes error -match glob -result {*must be called from within a math zone*} test math-1.4 {mdelim outside math raises error} -body { withDoc doc { $doc mdelim { $doc mrun "x" } } } -returnCodes error -match glob -result {*must be called from within a math zone*} test math-1.5 {mmatrix outside math raises error} -body { withDoc doc { $doc mmatrix {{ $doc mmatcell { $doc mrun "1" } }} } } -returnCodes error -match glob -result {*must be called from within a math zone*} test math-1.6 {mlimupp outside math raises error} -body { withDoc doc { $doc mlimupp { $doc mrun "lim" } { $doc mrun "n→∞" } } } -returnCodes error -match glob -result {*must be called from within a math zone*} # ────────────────────────────────────────────────────────────────── # Inline math # ────────────────────────────────────────────────────────────────── test math-2.1 {inline math creates oMath} -body { withDoc doc { $doc paragraph "Equation: " $doc math { $doc mrun "x" } countNodes $doc {//m:oMath} } } -result 1 test math-2.2 {inline math does not create oMathPara} -body { withDoc doc { $doc paragraph "Eq: " $doc math { $doc mrun "y" } countNodes $doc {//m:oMathPara} } } -result 0 # ────────────────────────────────────────────────────────────────── # Display math # ────────────────────────────────────────────────────────────────── test math-3.1 {display math creates oMathPara} -body { withDoc doc { $doc math -display 1 { $doc mrun "E=mc^2" } countNodes $doc {//m:oMathPara} } } -result 1 test math-3.2 {display math with justification} -body { withDoc doc { $doc math -display 1 -jc left { $doc mrun "x" } xpath $doc {string(//m:oMathParaPr/m:jc/@m:val)} } } -result left # ────────────────────────────────────────────────────────────────── # Math structures # ────────────────────────────────────────────────────────────────── test math-4.1 {fraction} -body { withDoc doc { $doc math -display 1 { $doc mfrac { $doc mrun "a" } { $doc mrun "b" } } countNodes $doc {//m:f} } } -result 1 test math-4.2 {subscript} -body { withDoc doc { $doc math -display 1 { $doc msub { $doc mrun "x" } { $doc mrun "i" } } countNodes $doc {//m:sSub} } } -result 1 test math-4.3 {superscript} -body { withDoc doc { $doc math -display 1 { $doc msup { $doc mrun "x" } { $doc mrun "2" } } countNodes $doc {//m:sSup} } } -result 1 test math-4.4 {sub+sup} -body { withDoc doc { $doc math -display 1 { $doc msubsup { $doc mrun "x" } { $doc mrun "i" } { $doc mrun "2" } } countNodes $doc {//m:sSubSup} } } -result 1 test math-4.5 {square root} -body { withDoc doc { $doc math -display 1 { $doc msqrt { $doc mrun "x" } } # degHide must be set xpath $doc {string(//m:rad/m:radPr/m:degHide/@m:val)} } } -result 1 test math-4.6 {nth root} -body { withDoc doc { $doc math -display 1 { $doc mroot { $doc mrun "3" } { $doc mrun "x" } } countNodes $doc {//m:rad} } } -result 1 test math-4.7 {delimiter} -body { withDoc doc { $doc math -display 1 { $doc mdelim { $doc mrun "x+1" } } countNodes $doc {//m:d} } } -result 1 test math-4.8 {delimiter with multiple args} -body { withDoc doc { $doc math -display 1 { $doc mdelim -begChr "\[" -endChr "\]" { $doc mdelimarg { $doc mrun "a" } $doc mdelimarg { $doc mrun "b" } } } countNodes $doc {//m:d/m:e} } } -result 2 test math-4.9 {accent} -body { withDoc doc { $doc math -display 1 { $doc maccent { $doc mrun "x" } } countNodes $doc {//m:acc} } } -result 1 test math-4.10 {bar} -body { withDoc doc { $doc math -display 1 { $doc mbar -pos bot { $doc mrun "x" } } xpath $doc {string(//m:barPr/m:pos/@m:val)} } } -result bot test math-4.11 {grouping character} -body { withDoc doc { $doc math -display 1 { $doc mgroupchr { $doc mrun "a+b" } } countNodes $doc {//m:groupChr} } } -result 1 test math-4.12 {matrix} -body { withDoc doc { $doc math -display 1 { $doc mmatrix { { $doc mmatcell { $doc mrun "1" } $doc mmatcell { $doc mrun "0" } } { $doc mmatcell { $doc mrun "0" } $doc mmatcell { $doc mrun "1" } } } } set mrows [countNodes $doc {//m:mr}] set mcells [countNodes $doc {//m:mr/m:e}] list $mrows $mcells } } -result {2 4} test math-4.13 {matrix requires at least one row} -body { withDoc doc { $doc math -display 1 { $doc mmatrix {} } } } -returnCodes error -match glob -result {*at least one row*} test math-4.14 {function} -body { withDoc doc { $doc math -display 1 { $doc mfunc { $doc mrun "sin" } { $doc mrun "x" } } countNodes $doc {//m:func} } } -result 1 test math-4.15 {nary (summation)} -body { withDoc doc { $doc math -display 1 { $doc mnary -char "\u2211" -sub { $doc mrun "i=1" } -sup { $doc mrun "n" } { $doc mrun "i" } } countNodes $doc {//m:nary} } } -result 1 test math-4.16 {lower limit} -body { withDoc doc { $doc math -display 1 { $doc mlimlow { $doc mrun "lim" } { $doc mrun "x→0" } } countNodes $doc {//m:limLow} } } -result 1 test math-4.17 {upper limit} -body { withDoc doc { $doc math -display 1 { $doc mlimupp { $doc mrun "lim" } { $doc mrun "n→∞" } } countNodes $doc {//m:limUpp} } } -result 1 # ────────────────────────────────────────────────────────────────── # valPrefix restored after math error # ────────────────────────────────────────────────────────────────── test math-5.1 {valPrefix restored after math error} -body { withDoc doc { catch { $doc math { error "boom" } } # After error, normal paragraph should still work $doc paragraph "Still works" -bold on xpath $doc {string(//w:r/w:rPr/w:b/@w:val)} } } -result 1 cleanupTests ooxml/tests/docx-media.test000664 000765 000024 00000002174 15213015413 016366 0ustar00alexstaff000000 000000 # media.test -- # # Tests for image insertion and related package artifacts. package require tcltest 2.5 namespace import ::tcltest::* package require ooxml::docx test media-1.1 {inline image writes media part and relationship} -body { set img [writeTinyPng] withDoc doc { $doc paragraph "Image:" $doc image $img inline -dimension {width 914400 height 914400} set inlineCount [countNodes $doc {//wp:inline}] set embed [xpath $doc {string(//a:blip/@r:embed)}] set f [writedoc $doc] set parts [ziplist $f] set ct [zipread $f {[Content_Types].xml}] set rels [zipread $f word/_rels/document.xml.rels] expr {$inlineCount == 1 && $embed ne "" && "word/media/image1.png" in $parts && [string match *image/png* $ct] && [string match *media/image1.png* $rels]} } } -result 1 test media-1.2 {anchor image creates wp:anchor drawing} -body { set img [writeTinyPng] withDoc doc { $doc image $img anchor -dimension {width 914400 height 914400} list [countNodes $doc {//wp:anchor}] [countNodes $doc {//wp:inline}] } } -result {1 0} cleanupTests ooxml/tests/docx-notes.test000664 000765 000024 00000012435 15213015413 016440 0ustar00alexstaff000000 000000 # notes.test -- # # Tests for footnote and endnote creation, separator entries, # reference marks, and transactional rollback. package require tcltest 2.5 namespace import ::tcltest::* package require ooxml::docx # ────────────────────────────────────────────────────────────────── # Footnote creation # ────────────────────────────────────────────────────────────────── test notes-1.1 {footnote creates note part} -body { withDoc doc { $doc paragraph "Text" $doc footnote { $doc paragraph "Note text." } haspart $doc word/footnotes.xml } } -result 1 test notes-1.2 {footnote has separator entries} -body { withDoc doc { $doc paragraph "Text" $doc footnote { $doc paragraph "Note." } # 2 special (separator + continuationSeparator) + 1 user = 3 countNodes $doc {//w:footnote} word/footnotes.xml } } -result 3 test notes-1.3 {footnote separator has correct type} -body { withDoc doc { $doc paragraph "Text" $doc footnote { $doc paragraph "Note." } set sep [xpath $doc {string(//w:footnote[@w:type='separator']/@w:id)} word/footnotes.xml] set cont [xpath $doc {string(//w:footnote[@w:type='continuationSeparator']/@w:id)} word/footnotes.xml] list $sep $cont } } -result {0 1} test notes-1.4 {footnote reference in document body} -body { withDoc doc { $doc paragraph "Text" $doc footnote { $doc paragraph "Note." } countNodes $doc {//w:footnoteReference} } } -result 1 test notes-1.5 {footnote self-reference mark} -body { withDoc doc { $doc paragraph "Text" $doc footnote { $doc paragraph "Note." } countNodes $doc {//w:footnoteRef} word/footnotes.xml } } -result 1 test notes-1.6 {multiple footnotes get unique IDs} -body { withDoc doc { $doc paragraph "Text" $doc footnote { $doc paragraph "Note 1." } $doc footnote { $doc paragraph "Note 2." } # 2 special + 2 user = 4 countNodes $doc {//w:footnote} word/footnotes.xml } } -result 4 # ────────────────────────────────────────────────────────────────── # Endnote creation # ────────────────────────────────────────────────────────────────── test notes-2.1 {endnote creates note part} -body { withDoc doc { $doc paragraph "Text" $doc endnote { $doc paragraph "End note." } haspart $doc word/endnotes.xml } } -result 1 test notes-2.2 {endnote has separator entries} -body { withDoc doc { $doc paragraph "Text" $doc endnote { $doc paragraph "End note." } countNodes $doc {//w:endnote} word/endnotes.xml } } -result 3 test notes-2.3 {endnote reference in document body} -body { withDoc doc { $doc paragraph "Text" $doc endnote { $doc paragraph "End note." } countNodes $doc {//w:endnoteReference} } } -result 1 # ────────────────────────────────────────────────────────────────── # Footnote/endnote option validation # ────────────────────────────────────────────────────────────────── test notes-3.1 {unknown option rejected in footnote} -body { withDoc doc { $doc paragraph "Text" $doc footnote -bogus xyz { $doc paragraph "Note." } } } -returnCodes error -match glob -result {*unknown*bogus*} test notes-3.2 {unknown option rejected in endnote} -body { withDoc doc { $doc paragraph "Text" $doc endnote -bogus xyz { $doc paragraph "Note." } } } -returnCodes error -match glob -result {*unknown*bogus*} # ────────────────────────────────────────────────────────────────── # Rollback on script error # ────────────────────────────────────────────────────────────────── test notes-4.1 {footnote rollback on script error} -constraints mutation -body { withDoc doc { $doc paragraph "Text" catch { $doc footnote { error "deliberate failure" } } # After rollback, footnotes part should not exist # (or if it existed before, no user note should remain) if {[haspart $doc word/footnotes.xml]} { # Only separator entries, no user note set count [countNodes $doc {//w:footnote[not(@w:type)]} word/footnotes.xml] expr {$count == 0} } else { expr {1} } } } -result 1 cleanupTests ooxml/tests/test_sheet1_xml_no_xml.xlsx000644 000765 000024 00000016724 14764622263 021104 0ustar00alexstaff000000 000000 PK! '0docProps/app.xml (n0 n@VQzذq{gd:*KIgomɟqY1 1"CoBeϋ"K<I\ϟ*#YL[TQ26f,{V NVoyjГo=qGM`zPZ֪  \SnYħ׿!{Nɩz)Z:T 8\@]K䩠eƤUG % Zĸ}ۘ kE}7h)mܿDQ~󡁃`aᜳ0W{`G6Sy+ehZ/}[[ |yQw8nXPwzB@ϯfwRSPK!-=]docProps/core.xml (N0HC{8RYI*JHqm6}{ A;ή/Z$E(EzݬgJF+(ZW97k VrUHPAi+OdžKL0pHD'#|ڦ ;Lt6)k4aS)[AWƶmv ~[?Ƶn[`^RCU1I;_Ü_KjuV}B:D?+f,nbBb2ߐhwwᆂ<6π2PK!"Zxl/sharedStrings.xml\A 0Ew "hB;@3.3̢B'2HҴ\R^&WCFr(׫jHba jp37ZoÿBO PK!@|Ԇ xl/styles.xmlTmo0>iwj!K"Z"UI}u$Vl%w:m{szs=3cVB*u>_`uTUTh2|bߥ֝s fE-LR{OT'1V_a8'r{,DR6AeCqݩH҆P=F3Z;V k^,dI)OkEnZzR*/o~GT%$OK-A*:TޭSo+'9 V'<8fT S47N gٔ?;T9O+NZQSA.S2!~/5R,2 cp!AzOz7âc'_Gvd*Z.W q,B{lwāZTpO⭌/^vDG*, 5f/Nل1pNݘkJPI\'A16vҤ4ާp.F4ݗCaLJU 9B8cvd&` /}'<Ó?f;(_|ٟ_㹎O~s;&[x{W# >$1U|`1Mydc!b@ض^] ju[) xy~sA,#_b+r,y2u lc(1B۟@Ydau8‘!Ɩ&pn%Cr`$Ri -˨m=|d"@B~h.Pl39D1Dd#HG:Dz)sc̹ϵ ={tTC]Ę0Bʙ$B":63yq@p"BptUT$|2O->.a2 $9SONԳtZ;)Z;|?(=4Ocxg ;~^7څPuv7.'}x;4@Vj+72(iT'e#"`_U)MO3cVYm)j08۱VrwGhvm 4]ʼNnyI@'$Lu Ʋw$΅E¢)/C@mX?9j Qr_{PK!L|4xl/workbook.xmlTn0?zXJR?( p/4SJRޕTn}I^%,9=U|cV) >%΅ڧqa4:r&w6ʦtN<*fǺ;6s85{XnKWI/+bB!1oE!8,5o*P1 m)j;U-p3q]R'҆$>t%VnP^_ !ᩗ̪Id֭r ON~[0M=o BzO+ ɡ`t4axaV5a/Jl 'lg+IcdJ"df{pޞ. ozH/$~pdl,T) rg2t~ľtv0g]HT@JwbZJIf#g%atprf8"A]7_MQ4 Gh2\׫j݌'ÃVasf{BX'z1T ePK 6pYHxl/worksheets/sheet1.xmlABCPK!>xl/_rels/workbook.xml.rels (RMK0 0wvt/"Uɴ)&!3~*]XK/oyv5+zl;obG s>,8(%"D҆4j0u2jsMY˴S쭂 )fCy I< y!+EfMyk K5=|t G)s墙UtB),fPK!bh^[Content_Types].xml (N0EHC-Jܲ@5*Q>ēƪc[iiBj7{2hnmƻR U^7/%rZY@1__fqR4DAJh>Vƹ Z9NV8ʩji){^-I"{v^P!XS)bRrKs(3`c07M4ZƐk+|\|z(P6h_-[@!Pk2n}?L %ddN"m,ǞDO97*~ɸ8Oc|nEB!$};{[2PK!U0#L _rels/.rels (MO0 HݐBKwAH!T~I$ݿ'TG~+xl/_rels/workbook.xml.relsPK-!bh^^[Content_Types].xmlPK-!U0#L _rels/.relsPK ooxml/tests/docx-style.test000664 000765 000024 00000014320 15213015413 016443 0ustar00alexstaff000000 000000 # style.test -- # # Tests for style creation, resolution, deletion, inheritance, # duplicate checks, and styleId derivation. package require tcltest 2.5 namespace import ::tcltest::* package require ooxml::docx # ────────────────────────────────────────────────────────────────── # Style creation and styleId derivation # ────────────────────────────────────────────────────────────────── test style-1.1 {create paragraph style} -body { withDoc doc { $doc style paragraph "My Heading" -bold on -fontsize 32 set ids [$doc style ids paragraph] expr {"MyHeading" in $ids} } } -result 1 test style-1.2 {styleId strips non-alnum} -body { withDoc doc { $doc style paragraph "Heading (Level 1)" -bold on set ids [$doc style ids paragraph] expr {"HeadingLevel1" in $ids} } } -result 1 test style-1.3 {explicit -styleid} -body { withDoc doc { $doc style paragraph "My Style" -styleid CustomId01 set ids [$doc style ids paragraph] expr {"CustomId01" in $ids} } } -result 1 test style-1.4 {character style} -body { withDoc doc { $doc style character "Emphasis" -italic on set ids [$doc style ids character] expr {"Emphasis" in $ids} } } -result 1 test style-1.5 {table style} -body { withDoc doc { $doc style table "Plain Table" set ids [$doc style ids table] expr {"PlainTable" in $ids} } } -result 1 # ────────────────────────────────────────────────────────────────── # Style resolution (StyleCheck) # ────────────────────────────────────────────────────────────────── test style-2.1 {resolve by display name} -body { withDoc doc { $doc style paragraph "My Heading" -bold on $doc paragraph "Styled" -pstyle "My Heading" xpath $doc {string(//w:p/w:pPr/w:pStyle/@w:val)} } } -result MyHeading test style-2.2 {resolve by styleId} -body { withDoc doc { $doc style paragraph "My Heading" -bold on $doc paragraph "Styled" -pstyle MyHeading xpath $doc {string(//w:p/w:pPr/w:pStyle/@w:val)} } } -result MyHeading test style-2.3 {unknown style raises error} -body { withDoc doc { $doc paragraph "Test" -pstyle "NoSuchStyle" } } -returnCodes error -match glob -result {*unknown paragraph style*} # ────────────────────────────────────────────────────────────────── # Duplicate checks # ────────────────────────────────────────────────────────────────── test style-3.1 {duplicate display name rejected} -body { withDoc doc { $doc style paragraph "Heading" -bold on $doc style paragraph "Heading" -italic on } } -returnCodes error -match glob -result {*already exists*} test style-3.2 {duplicate styleId rejected} -body { withDoc doc { $doc style paragraph "My Heading" -bold on # "My-Heading" strips to same "MyHeading" $doc style paragraph "My-Heading" -italic on } } -returnCodes error -match glob -result {*styleId*already*} test style-3.3 {explicit styleid collision rejected} -body { withDoc doc { $doc style paragraph "First" -styleid Shared $doc style paragraph "Second" -styleid Shared } } -returnCodes error -match glob -result {*styleId*already*} # ────────────────────────────────────────────────────────────────── # Style inheritance (-basedon) # ────────────────────────────────────────────────────────────────── test style-4.1 {basedon resolves to styleId} -body { withDoc doc { $doc style paragraph "Parent" -bold on $doc style paragraph "Child" -basedon "Parent" -italic on xpath $doc { string(//w:style[@w:styleId='Child']/w:basedOn/@w:val) } word/styles.xml } } -result Parent test style-4.2 {basedon resolves display name to styleId} -body { withDoc doc { $doc style paragraph "Base Style" -bold on $doc style paragraph "Derived" -basedon "Base Style" xpath $doc { string(//w:style[@w:styleId='Derived']/w:basedOn/@w:val) } word/styles.xml } } -result BaseStyle test style-4.3 {basedon with invalid parent raises error} -body { withDoc doc { $doc style paragraph "Orphan" -basedon "NonExistent" } } -returnCodes error -match glob -result {*unknown paragraph style*} # ────────────────────────────────────────────────────────────────── # Style deletion # ────────────────────────────────────────────────────────────────── test style-5.1 {delete by name} -body { withDoc doc { $doc style paragraph "ToDelete" -bold on $doc style delete paragraph "ToDelete" set ids [$doc style ids paragraph] expr {"ToDelete" in $ids} } } -result 0 test style-5.2 {style names subcommand} -body { withDoc doc { $doc style paragraph "Alpha" -bold on $doc style paragraph "Beta" -italic on set names [$doc style names paragraph] expr {"Alpha" in $names && "Beta" in $names} } } -result 1 cleanupTests ooxml/tests/xlsx-printarea.test000644 000765 000024 00000003723 14764622263 017355 0ustar00alexstaff000000 000000 # # Commands covered: definedNames _xlnm.Print_Area # # # (c) 2025 Alexander Schoepe # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # if {[lsearch [namespace children] ::tcltest] == -1} { package require tcltest 2 namespace import -force ::tcltest::* loadTestedCommands } package require ooxml # Begin with a new spreadsheet and a new workbook test newSpreadsheet-1.1 {Create New Spreadsheet} -body { set spreadsheet [::ooxml::xl_write new -creator {Alexander Schöpe}] } -result {::oo::Obj*} -match glob test newWorksheet-1.2 {Create New Worksheet} { set sheet [$spreadsheet worksheet {Blatt 1}] } 1 # *************** Begin here with settings, formats and data *************** test printArea-2.1 {Set Print Area} { $spreadsheet printarea $sheet A1 C3 } 0 # *************** End here with settings, formats and data *************** # Save all data for later comparison foreach item {obj cells fonts numFmts styles fills borders cols view hlinks} { array set w_$item [array get ${spreadsheet}::$item] # parray w_$item } # Write XLSX file and destroy spreadsheet test writeSpreatsheet-3.1 {Write Spreatsheet} { $spreadsheet write printarea.xlsx } 0 test destroySpreatsheet-3.2 {Destroy Spreatsheet} { $spreadsheet destroy } 0 # Read XLSX file for comparison test readWorkbook-4.1 {Read Workbook} { array set workbook [ooxml::xl_read printarea.xlsx] # parray workbook return [llength $workbook(sheets)] } 1 # *************** Begin here with comparison *************** test printArea-5.1 {Check Print Area} { set rc 1 if {![info exists workbook(0,printarea)] || $workbook(0,printarea) ne $w_obj(printarea,1)} { set rc 0 } return $rc } 1 # *************** End here with comparison *************** # Cleanup file delete -force printarea.xlsx ::tcltest::cleanupTests return # Local Variables: # tcl-indent-level: 4 # End: ooxml/tests/ecma376/000755 000765 000024 00000000000 15213015413 014612 5ustar00alexstaff000000 000000 ooxml/tests/docx-comments.test000664 000765 000024 00000013242 15213015413 017132 0ustar00alexstaff000000 000000 # comments.test -- # # Tests for comment, commentrangestart/end, simplecomment, # and transactional rollback. package require tcltest 2.5 namespace import ::tcltest::* package require ooxml::docx # ────────────────────────────────────────────────────────────────── # Basic comment creation # ────────────────────────────────────────────────────────────────── test comment-1.1 {comment creates comments part} -body { withDoc doc { $doc paragraph "Text" $doc comment -author "Tester" { $doc paragraph "A comment." } haspart $doc word/comments.xml } } -result 1 test comment-1.2 {comment content} -body { withDoc doc { $doc paragraph "Text" $doc comment -author "Tester" { $doc paragraph "Review note." } countNodes $doc {//w:comment} word/comments.xml } } -result 1 test comment-1.3 {comment reference in body} -body { withDoc doc { $doc paragraph "Text" $doc comment -author "Tester" { $doc paragraph "Note." } countNodes $doc {//w:commentReference} } } -result 1 test comment-1.4 {comment author attribute} -body { withDoc doc { $doc paragraph "Text" $doc comment -author "John Doe" { $doc paragraph "Note." } xpath $doc {string(//w:comment/@w:author)} word/comments.xml } } -result {John Doe} # ────────────────────────────────────────────────────────────────── # Range comments # ────────────────────────────────────────────────────────────────── test comment-2.1 {comment range start/end} -body { withDoc doc { $doc paragraph "Text" set id [$doc commentrangestart] $doc paragraph "Commented text" $doc commentrangeend $id -author "Reviewer" { $doc paragraph "Range comment." } set starts [countNodes $doc {//w:commentRangeStart}] set ends [countNodes $doc {//w:commentRangeEnd}] set refs [countNodes $doc {//w:commentReference}] list $starts $ends $refs } } -result {1 1 1} # ────────────────────────────────────────────────────────────────── # Simple comments # ────────────────────────────────────────────────────────────────── test comment-3.1 {simplecomment} -body { withDoc doc { $doc paragraph "Text" $doc simplecomment "Quick note" -author "Bot" countNodes $doc {//w:comment} word/comments.xml } } -result 1 test comment-3.2 {simplecommentrangeend} -body { withDoc doc { $doc paragraph "Text" set id [$doc commentrangestart] $doc paragraph "More text" $doc simplecommentrangeend $id "Range note" -author "Bot" set refs [countNodes $doc {//w:commentReference}] set ends [countNodes $doc {//w:commentRangeEnd}] list $refs $ends } } -result {1 1} # ────────────────────────────────────────────────────────────────── # Rollback on error # ────────────────────────────────────────────────────────────────── test comment-4.1 {comment rollback on script error} -constraints mutation -body { withDoc doc { $doc paragraph "Text" catch { $doc comment -author "A" { error "boom" } } # No orphaned comment should remain if {[haspart $doc word/comments.xml]} { countNodes $doc {//w:comment} word/comments.xml } else { expr {0} } } } -result 0 test comment-4.2 {comment rollback on invalid option} -constraints mutation -body { withDoc doc { $doc paragraph "Text" catch { $doc comment -author "A" -bogusOption xyz { $doc paragraph "Should not get here" } } if {[haspart $doc word/comments.xml]} { countNodes $doc {//w:comment} word/comments.xml } else { expr {0} } } } -result 0 test comment-4.3 {simplecomment rollback on error} -constraints mutation -body { withDoc doc { $doc paragraph "Text" catch { # Invalid date triggers error in CreateComment $doc simplecomment "Note" -date "not-a-date" } if {[haspart $doc word/comments.xml]} { countNodes $doc {//w:comment} word/comments.xml } else { expr {0} } } } -result 0 test comment-4.4 {commentrangeend rollback on script error} -constraints mutation -body { withDoc doc { $doc paragraph "Text" set id [$doc commentrangestart] catch { $doc commentrangeend $id -author "A" { error "boom" } } if {[haspart $doc word/comments.xml]} { countNodes $doc {//w:comment} word/comments.xml } else { expr {0} } } } -result 0 cleanupTests ooxml/tests/all.tcl000644 000765 000024 00000002160 15213015413 014720 0ustar00alexstaff000000 000000 # all.tcl -- # # This file contains a top-level script to run all of the Tcl # tests. Execute it by invoking "source all.test" when running tcltest # in this directory. # # Copyright (c) 1998-1999 by Scriptics Corporation. # Copyright (c) 2000 by Ajuba Solutions # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. package prefer latest package require Tcl 8.5- package require tcltest 2.2 namespace import tcltest::* configure {*}$argv -testdir [file dir [info script]] if {[singleProcess]} { interp debug {} -frame 1 } set thisdir [file dirname [file normalize [info script]]] # Run all test files in a single interpreter so that the shared # package load and helper definitions are available to every test. configure {*}$argv \ -testdir $thisdir \ -singleproc 1 # Load the package under test set libdir [file dirname $thisdir] source [file join $libdir ooxml.tcl] source [file join $libdir ooxml-docx.tcl] # Shared test helpers source [file join $thisdir docx_helpers.tcl] testConstraint mutation false runAllTests proc exit args {} ooxml/tests/xlsx-formatcell.test000644 000765 000024 00000064313 15213015413 017501 0ustar00alexstaff000000 000000 # # Commands covered: format cell excel sheet # # # (c) 2019 Alexander Schoepe # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # if {[lsearch [namespace children] ::tcltest] == -1} { package require tcltest 2 namespace import -force ::tcltest::* loadTestedCommands } package require ooxml test FormatCellNewSpreatsheet-1.1 {Create New Spreadsheet} -body { set spreadsheet [::ooxml::xl_write new -creator {Alexander Schöpe}] } -result {::oo::Obj*} -match glob test FormatCellNewWorksheet-1.2 {Create New Worksheet} { set sheet [$spreadsheet worksheet {Blatt 1}] } 1 test FormatCellView-1.3 {Set View} { $spreadsheet view -activetab 0 -x 2200 -y 2760 -height 8140 -width 15140 } {} test FormatCellNewStyle-2.1 {New Style} { set bold [$spreadsheet style -font [$spreadsheet font -bold]] } 1 test FormatCellNewStyle-2.2 {New Style} { set italic [$spreadsheet style -font [$spreadsheet font -italic]] } 2 test FormatCellNewStyle-2.3 {New Style} { set underline [$spreadsheet style -font [$spreadsheet font -underline]] } 3 test FormatCellNewStyle-2.4 {New Style} { set red [$spreadsheet style -font [$spreadsheet font -color Red]] } 4 test FormatCellNewStyle-2.5 {New Style} { set font9 [$spreadsheet style -font [$spreadsheet font -size 9]] } 5 test FormatCellNewStyle-2.6 {New Style} { set font18 [$spreadsheet style -font [$spreadsheet font -size 18]] } 6 test FormatCellNewStyle-2.7 {New Style} { set rotate90 [$spreadsheet style -rotate 90 -horizontal center] } 7 test FormatCellNewStyle-2.8 {New Style} { set rotate45 [$spreadsheet style -rotate 45] } 8 test FormatCellNewStyle-2.9 {New Style} { set left [$spreadsheet style -horizontal left] } 9 test FormatCellNewStyle-2.10 {New Style} { set center [$spreadsheet style -horizontal center] } 10 test FormatCellNewStyle-2.11 {New Style} { set right [$spreadsheet style -horizontal right] } 11 test FormatCellNewStyle-2.12 {New Style} { set top [$spreadsheet style -vertical top] } 12 test FormatCellNewStyle-2.13 {New Style} { set vcenter [$spreadsheet style -vertical center] } 13 test FormatCellNewStyle-2.14 {New Style} { set bottom [$spreadsheet style -vertical bottom] } 14 test FormatCellNewStyle-2.15 {New Style} { set hvcenter [$spreadsheet style -horizontal center -vertical center] } 15 test FormatCellNewStyle-2.16 {New Style} { set yellow [$spreadsheet style -fill [$spreadsheet fill -fgcolor FFFFFF00 -bgcolor 64 -patterntype solid]] } 16 test FormatCellNewStyle-2.17 {New Style} { set bLeft [$spreadsheet style -border [$spreadsheet border -leftstyle thin]] } 17 test FormatCellNewStyle-2.18 {New Style} { set bBottom [$spreadsheet style -border [$spreadsheet border -bottomstyle thin]] } 18 test FormatCellNewStyle-2.19 {New Style} { set bBottom2 [$spreadsheet style -border [$spreadsheet border -bottomstyle double]] } 19 test FormatCellNewStyle-2.20 {New Style} { set bBottomB [$spreadsheet style -border [$spreadsheet border -bottomstyle medium]] } 20 test FormatCellNewStyle-2.21 {New Style} { set bBottomD [$spreadsheet style -border [$spreadsheet border -bottomstyle dashed]] } 21 test FormatCellNewStyle-2.22 {New Style} { set bDiagonal [$spreadsheet style -border [$spreadsheet border -diagonalstyle medium -diagonaldirection up]] } 22 test FormatCellNewStyle-2.23 {New Style} { set dec2 [$spreadsheet style -numfmt [$spreadsheet numberformat -decimal]] } 23 test FormatCellNewStyle-2.24 {New Style} { set dec2t [$spreadsheet style -numfmt [$spreadsheet numberformat -decimal -separator]] } 24 test FormatCellNewStyle-2.25 {New Style} { set dec3 [$spreadsheet style -numfmt [$spreadsheet numberformat -format {#,##0.000}]] } 25 test FormatCellNewStyle-2.26 {New Style} { set dec3t [$spreadsheet style -numfmt [$spreadsheet numberformat -format {#,##0.000_ ;[Red]\-#,##0.000\ }]] } 26 test FormatCellNewStyle-2.27 {New Style} { set currency [$spreadsheet style -numfmt [$spreadsheet numberformat -format {#,##0.00\ "€"}]] } 27 test FormatCellNewStyle-2.28 {New Style} { set iso8601 [$spreadsheet style -numfmt [$spreadsheet numberformat -iso8601]] } 28 test FormatCellNewStyle-2.29 {New Style} { set date [$spreadsheet style -numfmt [$spreadsheet numberformat -date]] } 29 test FormatCellNewStyle-2.30 {New Style} { set date2 [$spreadsheet style -numfmt [$spreadsheet numberformat -format {[$-F800]dddd\,\ mmmm\ dd\,\ yyyy}]] } 30 test FormatCellNewStyle-2.31 {New Style} { set date3 [$spreadsheet style -numfmt [$spreadsheet numberformat -format {[$-407]d/\ mmmm\ yyyy;@}]] } 31 test FormatCellNewStyle-2.32 {New Style} { set date4 [$spreadsheet style -numfmt [$spreadsheet numberformat -format {d/m/yy\ h:mm;@}]] } 32 test FormatCellNewStyle-2.33 {New Style} { set time [$spreadsheet style -numfmt [$spreadsheet numberformat -time]] } 33 test FormatCellNewStyle-2.34 {New Style} { set time2 [$spreadsheet style -numfmt [$spreadsheet numberformat -format {[$-F400]h:mm:ss\ AM/PM}]] } 34 test FormatCellNewStyle-2.35 {New Style} { set percent [$spreadsheet style -numfmt [$spreadsheet numberformat -percent]] } 35 test FormatCellNewStyle-2.36 {New Style} { set percent2 [$spreadsheet style -numfmt [$spreadsheet numberformat -format {0.00%}]] } 36 test FormatCellNewStyle-2.37 {New Style} { set scientific [$spreadsheet style -numfmt [$spreadsheet numberformat -scientific]] } 37 test FormatCellNewStyle-2.38 {New Style} { set fraction [$spreadsheet style -numfmt [$spreadsheet numberformat -fraction]] } 38 test FormatCellNewStyle-2.39 {New Style} { set fraction2 [$spreadsheet style -numfmt [$spreadsheet numberformat -format {# ??/??}]] } 39 test FormatCellNewStyle-2.40 {New Style} { set text [$spreadsheet style -numfmt [$spreadsheet numberformat -string]] } 40 test FormatCellNewStyle-2.41 {New Style} { set wrap [$spreadsheet style -wrap] } 41 test FormatCellColumn-3.1 {Column Setting} { $spreadsheet column $sheet -index 0 -width 17.33203125 -bestfit } 0 test FormatCellColumn-3.2 {Column Setting} { $spreadsheet column $sheet -index 1 -width 20.5 -bestfit } 1 test FormatCellColumn-3.3 {Column Setting} { $spreadsheet column $sheet -index 4 -width 31.1640625 -bestfit } 4 test FormatCellColumn-3.4 {Column Setting} { $spreadsheet column $sheet -index 7 -width 11.1640625 -bestfit ;# -style 19 } 7 test FormatCellColumn-3.5 {Column Setting} { $spreadsheet column $sheet -index 8 ;# -style 15 } 8 test FormatCell-4.1 {Set Cell} { $spreadsheet cell $sheet Standard -index 0,0 -string } 0,0 test FormatCell-4.2 {Set Cell} { $spreadsheet cell $sheet 3.1415 -index 0,1 } 0,1 test FormatCell-4.3 {Set Cell} { $spreadsheet cell $sheet 1 -index 0,8 ;# -style 15 } 0,8 test FormatCell-4.4 {Set Cell} { $spreadsheet cell $sheet Standard -index 1,0 -string } 1,0 test FormatCell-4.5 {Set Cell} { $spreadsheet cell $sheet Text -index 1,1 -string } 1,1 test FormatCell-4.6 {Set Cell} { $spreadsheet cell $sheet {Zahl 2} -index 2,0 -string } 2,0 test FormatCell-4.7 {Set Cell} { $spreadsheet cell $sheet 3.1415 -index 2,1 -style $dec2 } 2,1 test FormatCell-4.8 {Set Cell} { $spreadsheet cell $sheet 1 -index 2,2 } 2,2 test FormatCell-4.9 {Set Cell} { $spreadsheet cell $sheet 2 -index 2,3 } 2,3 test FormatCell-4.10 {Set Cell} { $spreadsheet cell $sheet 0.00 -index 2,4 -string ;# -style 15 } 2,4 test FormatCell-4.11 {Set Cell} { $spreadsheet cell $sheet {Zahl 2 T} -index 3,0 -string } 3,0 test FormatCell-4.12 {Set Cell} { $spreadsheet cell $sheet 3.1415 -index 3,1 -style $dec2t } 3,1 test FormatCell-4.13 {Set Cell} { $spreadsheet cell $sheet 2 -index 3,2 } 3,2 test FormatCell-4.14 {Set Cell} { $spreadsheet cell $sheet 4 -index 3,3 } 3,3 test FormatCell-4.15 {Set Cell} { $spreadsheet cell $sheet #,##0.00 -index 3,4 -string } 3,4 test FormatCell-4.16 {Set Cell} { $spreadsheet cell $sheet {2018-02-09 16:17:00} -index 3,7 -style $date4 } 3,7 test FormatCell-4.17 {Set Cell} { $spreadsheet cell $sheet {Zahl 3} -index 4,0 -string } 4,0 test FormatCell-4.18 {Set Cell} { $spreadsheet cell $sheet 3.1415 -index 4,1 -style $dec3 } 4,1 test FormatCell-4.19 {Set Cell} { $spreadsheet cell $sheet 17 -index 4,2 } 4,2 test FormatCell-4.20 {Set Cell} { $spreadsheet cell $sheet 174 -index 4,3 } 4,3 test FormatCell-4.21 {Set Cell} { $spreadsheet cell $sheet #,##0.000 -index 4,4 -string } 4,4 test FormatCell-4.22 {Set Cell} { $spreadsheet cell $sheet {Zahl 3 C} -index 5,0 -string } 5,0 test FormatCell-4.23 {Set Cell} { $spreadsheet cell $sheet -3.1415 -index 5,1 -style $dec3t } 5,1 test FormatCell-4.24 {Set Cell} { $spreadsheet cell $sheet 16 -index 5,2 } 5,2 test FormatCell-4.25 {Set Cell} { $spreadsheet cell $sheet 173 -index 5,3 } 5,3 test FormatCell-4.26 {Set Cell} { $spreadsheet cell $sheet {#,##0.000_ ;[Red]\-#,##0.000\ } -index 5,4 -string } 5,4 test FormatCell-4.27 {Set Cell} { $spreadsheet cell $sheet Währung -index 6,0 -string } 6,0 test FormatCell-4.28 {Set Cell} { $spreadsheet cell $sheet 3.1415 -index 6,1 -style $currency } 6,1 test FormatCell-4.29 {Set Cell} { $spreadsheet cell $sheet 3 -index 6,2 } 6,2 test FormatCell-4.30 {Set Cell} { $spreadsheet cell $sheet 166 -index 6,3 } 6,3 test FormatCell-4.31 {Set Cell} { $spreadsheet cell $sheet {#,##0.00\ "€"} -index 6,4 -string } 6,4 test FormatCell-4.32 {Set Cell} { $spreadsheet cell $sheet tt.mm.jj -index 7,0 -string } 7,0 test FormatCell-4.33 {Set Cell} { $spreadsheet cell $sheet {2018-02-09 16:17:00} -index 7,1 -style $date } 7,1 test FormatCell-4.34 {Set Cell} { $spreadsheet cell $sheet 4 -index 7,2 } 7,2 test FormatCell-4.35 {Set Cell} { $spreadsheet cell $sheet 14 -index 7,3 } 7,3 test FormatCell-4.36 {Set Cell} { $spreadsheet cell $sheet mm-dd-yy -index 7,4 -string } 7,4 test FormatCell-4.37 {Set Cell} { $spreadsheet cell $sheet {tttt, t.mmmm.jj} -index 8,0 -string } 8,0 test FormatCell-4.38 {Set Cell} { $spreadsheet cell $sheet {2018-02-09 16:17:00} -index 8,1 -style $date2 } 8,1 test FormatCell-4.39 {Set Cell} { $spreadsheet cell $sheet 5 -index 8,2 } 8,2 test FormatCell-4.40 {Set Cell} { $spreadsheet cell $sheet 167 -index 8,3 } 8,3 test FormatCell-4.41 {Set Cell} { $spreadsheet cell $sheet {[$-F800]dddd\,\ mmmm\ dd\,\ yyyy} -index 8,4 -string } 8,4 test FormatCell-4.42 {Set Cell} { $spreadsheet cell $sheet t.mmmm.jjjj -index 9,0 -string } 9,0 test FormatCell-4.43 {Set Cell} { $spreadsheet cell $sheet {2018-02-09 16:17:00} -index 9,1 -style $date3 } 9,1 test FormatCell-4.44 {Set Cell} { $spreadsheet cell $sheet 6 -index 9,2 } 9,2 test FormatCell-4.45 {Set Cell} { $spreadsheet cell $sheet 168 -index 9,3 } 9,3 test FormatCell-4.46 {Set Cell} { $spreadsheet cell $sheet {[$-407]d/\ mmmm\ yyyy;@} -index 9,4 -string } 9,4 test FormatCell-4.47 {Set Cell} { $spreadsheet cell $sheet hh:mm:ss -index 10,0 -string } 10,0 test FormatCell-4.48 {Set Cell} { $spreadsheet cell $sheet {2018-02-09 16:17:00} -index 10,1 -style $time2 } 10,1 test FormatCell-4.49 {Set Cell} { $spreadsheet cell $sheet 7 -index 10,2 } 10,2 test FormatCell-4.50 {Set Cell} { $spreadsheet cell $sheet 169 -index 10,3 } 10,3 test FormatCell-4.51 {Set Cell} { $spreadsheet cell $sheet {[$-F400]h:mm:ss\ AM/PM} -index 10,4 -string } 10,4 test FormatCell-4.52 {Set Cell} { $spreadsheet cell $sheet hh:mm -index 11,0 -string } 11,0 test FormatCell-4.53 {Set Cell} { $spreadsheet cell $sheet {2018-02-09 16:17:00} -index 11,1 -style $time } 11,1 test FormatCell-4.54 {Set Cell} { $spreadsheet cell $sheet 8 -index 11,2 } 11,2 test FormatCell-4.55 {Set Cell} { $spreadsheet cell $sheet 170 -index 11,3 } 11,3 test FormatCell-4.56 {Set Cell} { $spreadsheet cell $sheet {h:mm;@} -index 11,4 -string } 11,4 test FormatCell-4.57 {Set Cell} { $spreadsheet cell $sheet {jjjj-mm-tt hh:mm:ss} -index 12,0 -string } 12,0 test FormatCell-4.58 {Set Cell} { $spreadsheet cell $sheet {2018-02-09 16:17:00} -index 12,1 -style $iso8601 } 12,1 test FormatCell-4.59 {Set Cell} { $spreadsheet cell $sheet 9 -index 12,2 } 12,2 test FormatCell-4.60 {Set Cell} { $spreadsheet cell $sheet 171 -index 12,3 } 12,3 test FormatCell-4.61 {Set Cell} { $spreadsheet cell $sheet {yyyy\-mm\-dd\ hh:mm:ss;@} -index 12,4 -string } 12,4 test FormatCell-4.62 {Set Cell} { $spreadsheet cell $sheet {Prozent 2} -index 13,0 -string } 13,0 test FormatCell-4.63 {Set Cell} { $spreadsheet cell $sheet 3.1415 -index 13,1 -style $percent2 } 13,1 test FormatCell-4.64 {Set Cell} { $spreadsheet cell $sheet 10 -index 13,2 } 13,2 test FormatCell-4.65 {Set Cell} { $spreadsheet cell $sheet 10 -index 13,3 } 13,3 test FormatCell-4.66 {Set Cell} { $spreadsheet cell $sheet 0.00% -index 13,4 -string } 13,4 test FormatCell-4.67 {Set Cell} { $spreadsheet cell $sheet {Bruch 1} -index 14,0 -string } 14,0 test FormatCell-4.68 {Set Cell} { $spreadsheet cell $sheet 3.1415 -index 14,1 -style $fraction } 14,1 test FormatCell-4.69 {Set Cell} { $spreadsheet cell $sheet 12 -index 14,2 } 14,2 test FormatCell-4.70 {Set Cell} { $spreadsheet cell $sheet 12 -index 14,3 } 14,3 test FormatCell-4.71 {Set Cell} { $spreadsheet cell $sheet {# ?/?} -index 14,4 -string } 14,4 test FormatCell-4.72 {Set Cell} { $spreadsheet cell $sheet {Bruch 2} -index 15,0 -string } 15,0 test FormatCell-4.73 {Set Cell} { $spreadsheet cell $sheet 3.1415 -index 15,1 -style $fraction2 } 15,1 test FormatCell-4.74 {Set Cell} { $spreadsheet cell $sheet 13 -index 15,2 } 15,2 test FormatCell-4.75 {Set Cell} { $spreadsheet cell $sheet 13 -index 15,3 } 15,3 test FormatCell-4.76 {Set Cell} { $spreadsheet cell $sheet {# ??/??} -index 15,4 -string } 15,4 test FormatCell-4.77 {Set Cell} { $spreadsheet cell $sheet {Wissenschaftl. 2} -index 16,0 -string } 16,0 test FormatCell-4.78 {Set Cell} { $spreadsheet cell $sheet 3.1415 -index 16,1 -style $scientific } 16,1 test FormatCell-4.79 {Set Cell} { $spreadsheet cell $sheet 14 -index 16,2 } 16,2 test FormatCell-4.80 {Set Cell} { $spreadsheet cell $sheet 11 -index 16,3 } 16,3 test FormatCell-4.81 {Set Cell} { $spreadsheet cell $sheet 0.00E+00 -index 16,4 -string } 16,4 test FormatCell-4.82 {Set Cell} { $spreadsheet cell $sheet Text -index 17,0 -string } 17,0 test FormatCell-4.83 {Set Cell} { $spreadsheet cell $sheet 3,1415 -index 17,1 -string -style $text } 17,1 test FormatCell-4.84 {Set Cell} { $spreadsheet cell $sheet 15 -index 17,2 } 17,2 test FormatCell-4.85 {Set Cell} { $spreadsheet cell $sheet 49 -index 17,3 } 17,3 test FormatCell-4.86 {Set Cell} { $spreadsheet cell $sheet @ -index 17,4 -string } 17,4 test FormatCell-4.87 {Set Cell} { $spreadsheet cell $sheet {Filter A} -index 19,5 -string ;# -style 19 } 19,5 test FormatCell-4.88 {Set Cell} { $spreadsheet cell $sheet {Filter B} -index 19,6 -string ;# -style 15 } 19,6 test FormatCell-4.89 {Set Cell} { $spreadsheet cell $sheet unten -index 20,0 -string } 20,0 test FormatCell-4.90 {Set Cell} { $spreadsheet cell $sheet {} -index 20,1 -style $bBottom } 20,1 test FormatCell-4.91 {Set Cell} { $spreadsheet cell $sheet links -index 21,0 -string } 21,0 test FormatCell-4.92 {Set Cell} { $spreadsheet cell $sheet {} -index 21,1 -style $bLeft } 21,1 test FormatCell-4.93 {Set Cell} { $spreadsheet cell $sheet fett -index 21,4 -string -style $bold } 21,4 test FormatCell-4.94 {Set Cell} { $spreadsheet cell $sheet {unten doppelt} -index 22,0 -string } 22,0 test FormatCell-4.95 {Set Cell} { $spreadsheet cell $sheet {} -index 22,1 -style $bBottom2 } 22,1 test FormatCell-4.96 {Set Cell} { $spreadsheet cell $sheet kursiv -index 22,4 -string -style $italic } 22,4 test FormatCell-4.97 {Set Cell} { $spreadsheet cell $sheet {unten mittel} -index 23,0 -string } 23,0 test FormatCell-4.98 {Set Cell} { $spreadsheet cell $sheet {} -index 23,1 -style $bBottomB } 23,1 test FormatCell-4.99 {Set Cell} { $spreadsheet cell $sheet unterstrichen -index 23,4 -string -style $underline } 23,4 test FormatCell-4.100 {Set Cell} { $spreadsheet cell $sheet {diagonal mittel} -index 24,0 -string } 24,0 test FormatCell-4.101 {Set Cell} { $spreadsheet cell $sheet {} -index 24,1 -style $bDiagonal } 24,1 test FormatCell-4.102 {Set Cell} { $spreadsheet cell $sheet {unten gestrichelt} -index 25,0 -string } 25,0 test FormatCell-4.103 {Set Cell} { $spreadsheet cell $sheet {} -index 25,1 -style $bBottomD } 25,1 test FormatCell-4.104 {Set Cell} { $spreadsheet cell $sheet {vorne rot} -index 27,0 -string } 27,0 test FormatCell-4.105 {Set Cell} { $spreadsheet cell $sheet rot -index 27,1 -string -style $red } 27,1 test FormatCell-4.106 {Set Cell} { $spreadsheet cell $sheet {hinten gelb} -index 28,0 -string } 28,0 test FormatCell-4.107 {Set Cell} { $spreadsheet cell $sheet gelb -index 28,1 -string -style $yellow } 28,1 test FormatCell-4.108 {Set Cell} { $spreadsheet cell $sheet links -index 30,0 -string } 30,0 test FormatCell-4.109 {Set Cell} { $spreadsheet cell $sheet links -index 30,1 -string -style $left } 30,1 test FormatCell-4.110 {Set Cell} { $spreadsheet cell $sheet mitte -index 31,0 -string } 31,0 test FormatCell-4.111 {Set Cell} { $spreadsheet cell $sheet mitte -index 31,1 -string -style $center } 31,1 test FormatCell-4.112 {Set Cell} { $spreadsheet cell $sheet rechts -index 32,0 -string } 32,0 test FormatCell-4.113 {Set Cell} { $spreadsheet cell $sheet rechts -index 32,1 -string -style $right } 32,1 test FormatCell-4.114 {Set Cell} { $spreadsheet cell $sheet oben -index 33,0 -string } 33,0 test FormatCell-4.115 {Set Cell} { $spreadsheet cell $sheet oben -index 33,1 -string -style $top } 33,1 test FormatCell-4.116 {Set Cell} { $spreadsheet cell $sheet mitte -index 34,0 -string } 34,0 test FormatCell-4.117 {Set Cell} { $spreadsheet cell $sheet mitte -index 34,1 -string -style $vcenter } 34,1 test FormatCell-4.118 {Set Cell} { $spreadsheet cell $sheet {Calibri 9} -index 34,4 -string -style $font9 } 34,4 test FormatCell-4.119 {Set Cell} { $spreadsheet cell $sheet unten -index 35,0 -string } 35,0 test FormatCell-4.120 {Set Cell} { $spreadsheet cell $sheet unten -index 35,1 -string -style $bottom } 35,1 test FormatCell-4.121 {Set Cell} { $spreadsheet cell $sheet {Text 90} -index 38,0 -string -style $rotate90 } 38,0 test FormatCell-4.122 {Set Cell} { $spreadsheet cell $sheet {Text 45} -index 38,1 -string -style $rotate45 } 38,1 test FormatCell-4.123 {Set Cell} { $spreadsheet cell $sheet {Calibri 18} -index 38,4 -string -style $font18 } 38,4 test FormatCell-4.124 {Set Cell} { $spreadsheet cell $sheet {12 Zellen} -index 39,3 -string -style $hvcenter } 39,3 test FormatCell-4.125 {Set Cell} { $spreadsheet cell $sheet {3 Spalten} -index 40,0 -string } 40,0 test FormatCell-4.126 {Set Cell} { $spreadsheet cell $sheet {3 Zeilen} -index 41,1 -string } 41,1 test FormatCell-4.127 {Set Cell} { $spreadsheet cell $sheet {this text will be automatically wrapped by excel} -index H27 -style $wrap } 26,7 test FormatCell-4.128 {Set Cell} { $spreadsheet cell $sheet a -index F21 -style $center } 20,5 test FormatCell-4.129 {Set Cell} { $spreadsheet cell $sheet a -index F22 -style $center } 21,5 test FormatCell-4.130 {Set Cell} { $spreadsheet cell $sheet b -index F23 -style $center } 22,5 test FormatCell-4.130 {Set Cell} { $spreadsheet cell $sheet 1 -index G21 -style $center } 20,6 test FormatCell-4.131 {Set Cell} { $spreadsheet cell $sheet 2 -index G22 -style $center } 21,6 test FormatCell-4.132 {Set Cell} { $spreadsheet cell $sheet 2 -index G23 -style $center } 22,6 test FormatCell-4.133 {Set Row} { $spreadsheet row $sheet -index 10 } 10 test FormatCell-4.134 {Set Cell} { $spreadsheet cell $sheet 3 -index G } 10,6 test FormatCell-4.135 {Set Cell} { $spreadsheet cell $sheet 5 } 10,7 test FormatCell-4.136 {Set Cell} { $spreadsheet cell $sheet {} -formula G11+H11 } 10,8 test FormatCell-4.137 {Hyperlink} { $spreadsheet cell $sheet {homepage} -index 45,0 -hyperlink {https://fossil.sowaswie.de/ooxml} -tooltip {weblink} } 45,0 test FormatCellFreeze-5.1 {Freeze} { $spreadsheet freeze $sheet 20,5 } 0 test FormatCellAutoFilter-5.2 {Auto Filter} { $spreadsheet autofilter $sheet 19,5 19,6 } 0 test FormatCellRowHeight-6.1 {Row Height} { $spreadsheet rowheight $sheet 33 20 } 33 test FormatCellRowHeight-6.2 {Row Height} { $spreadsheet rowheight $sheet 34 20 } 34 test FormatCellRowHeight-6.3 {Row Height} { $spreadsheet rowheight $sheet 35 20 } 35 test FormatCellMerge-7.1 {Merge} { $spreadsheet merge $sheet 40,0 40,2 } 0 test FormatCellMerge-7.2 {Merge} { $spreadsheet merge $sheet 41,1 43,1 } 0 test FormatCellMerge-7.3 {Merge} { $spreadsheet merge $sheet 39,3 42,5 } 0 foreach item {obj cells fonts numFmts styles fills borders cols view hlinks} { array set w_$item [array get ${spreadsheet}::$item] } test FormatCellWriteSpreatsheet-8.1 {Write Spreatsheet} { $spreadsheet write formatcell.xlsx } 0 test FormatCellDestroySpreatsheet-8.2 {Destroy Spreatsheet} { $spreadsheet destroy } 0 test FormatCellReadWorkbook-9.1 {Read Workbook} { array set workbook [ooxml::xl_read formatcell.xlsx] return [llength $workbook(sheets)] } 1 test FormatCellCheckBorders-9.2 {Check Borders} { set rc 1 unset -nocomplain r w for {set i 0} {$i < $w_obj(borders)} {incr i} { set dw $w_borders($i) set dr $workbook(s,borders,$i) foreach key {left right top bottom diagonal} { array set w [dict get $dw $key] array set r [dict get $dr $key] foreach {n v} [array get w] { if {![info exists r($n)] || $r($n) ne $v} { set rc 0 } } unset -nocomplain w r } unset -nocomplain dw dr } return $rc } 1 test FormatCellCheckFills-9.3 {Check Fills} { set rc 1 for {set i 0} {$i < $w_obj(fills)} {incr i} { array set w $w_fills($i) array set r $workbook(s,fills,$i) foreach {n v} [array get w] { if {![info exists r($n)] || $r($n) ne $v} { set rc 0 } } unset -nocomplain w r } return $rc } 1 test FormatCellCheckFonts-9.4 {Check Fonts} { set rc 1 for {set i 0} {$i < $w_obj(fonts)} {incr i} { array set w $w_fonts($i) array set r $workbook(s,fonts,$i) foreach {n v} [array get w] { if {![info exists r($n)] || $r($n) ne $v} { set rc 0 } } unset -nocomplain w r } return $rc } 1 test FormatCellCheckNumFmts-9.5 {Check NumFmts} { set rc 1 for {set i 166} {$i < $w_obj(numFmts)} {incr i} { if {![info exists workbook(s,numFmts,$i)] || $workbook(s,numFmts,$i) ne $w_numFmts($i)} { set rc 0 } } return $rc } 1 test FormatCellCheckStyles-9.6 {Check Styles} { set rc 1 for {set i 0} {$i < $w_obj(styles)} {incr i} { array set w $w_styles($i) array set r $workbook(s,styles,$i) foreach {n v} [array get w] { if {![info exists r($n)] || $r($n) ne $v} { set rc 0 } } unset -nocomplain w r } return $rc } 1 test FormatCellCheckColumns-10.1 {Check Worksheet Columns} { set rc 1 set idxList {} foreach n [array names w_cols 1,*] { lappend idxList [lindex [split $n ,] end] } foreach i $idxList { array set w $w_cols(1,$i) array set r $workbook(0,col,$i) foreach {n v} [array get w] { if {![info exists r($n)] || $r($n) ne $v} { set rc 0 } } unset -nocomplain w r } return $rc } 1 test FormatCellCheckFilter-10.2 {Check Worksheet Filter} { set rc 1 if {![info exists workbook(0,filter)] || $workbook(0,filter) ne $w_obj(autofilter,1)} { set rc 0 } return $rc } 1 test FormatCellCheckFreeze-10.3 {Check Worksheet Freeze} { set rc 1 if {![info exists workbook(0,freeze)] || $workbook(0,freeze) ne $w_obj(freeze,1)} { set rc 0 } return $rc } 1 test FormatCellCheckMerge-10.4 {Check Worksheet Merge} { set rc 1 if {![info exists workbook(0,merge)]} { set rc 0 } else { foreach item $workbook(0,merge) { if {$item ni $w_obj(merge,1)} { set rc 0 } } } return $rc } 1 test FormatCellCheckRowHeight-10.5 {Check Worksheet RowHeight} { set rc 1 array set w $w_obj(rowHeight,1) array set r $workbook(0,rowheight) foreach {n v} [array get w] { if {![info exists r($n)] || $r($n) ne $v} { set rc 0 } } unset -nocomplain w r return $rc } 1 test FormatCellCheckCells-10.6 {Check Cells} { set rc 1 foreach item [lsort -dictionary [array names w_cells 1,*,*]] { lassign [split $item ,] sheet row col incr sheet -1 array set w $w_cells($item) array unset w t array set r {} foreach tag {f s t v d} { if {[info exists workbook($sheet,$tag,$row,$col)]} { if {$tag eq {d}} { # overwrite datetime string with ole date array set r [list v $workbook($sheet,$tag,$row,$col)] } elseif {$tag eq {f}} { if {[dict exists $workbook($sheet,$tag,$row,$col) f]} { array set r [list $tag [dict get $workbook($sheet,$tag,$row,$col) f]] } else { array set r [list $tag {}] } } else { array set r [list $tag $workbook($sheet,$tag,$row,$col)] } } } foreach {n v} [array get w] { if {![info exists r($n)] || $r($n) ne $v} { puts stderr "err [info exists r($n)] w 'r($n)' '$v' / r '$r($n)'" set rc 0 } } unset -nocomplain w r } return $rc } 1 test FormatCellCheckCells-10.7 {Check Hyperlinks} { set rc 1 foreach item [lsort -dictionary [array names w_hlinks 1,*,*]] { lassign [split $item ,] sheet row col incr sheet -1 array unset w r array set w $w_hlinks($item) array set r {} foreach tag {l} { if {[info exists workbook($sheet,$tag,$row,$col)]} { foreach key {l t} { if {[dict exists $workbook($sheet,$tag,$row,$col) $key]} { array set r [list $key [dict get $workbook($sheet,$tag,$row,$col) $key]] } else { array set r [list $key {}] } } } } foreach {n v} [array get w] { if {![info exists r($n)] || $r($n) ne $v} { puts stderr "err [info exists r($n)] w 'r($n)' '$v' / r '$r($n)'" set rc 0 } } unset -nocomplain w r } return $rc #w_hlinks(1,45,0) = l https://fossil.sowaswie.de/ooxml t weblink #workbook(0,l,45,0) = l https://fossil.sowaswie.de/ooxml t weblink } 1 test FormatCellCheckView-11.1 {Check View} { set rc 1 array set w [array get w_view] array set r $workbook(view) foreach {n v} [array get w] { if {![info exists r($n)] || $r($n) ne $v} { set rc 0 } } unset -nocomplain w r return $rc } 1 file delete -force formatcell.xlsx # cleanup ::tcltest::cleanupTests return # Local Variables: # tcl-indent-level: 2 # End: ooxml/tests/docx-features.test000664 000765 000024 00000053016 15213015413 017126 0ustar00alexstaff000000 000000 # feature-exercise.test -- # # Runs the comprehensive feature-exercise script inside the test # harness. All .docx output goes to docxtest_tmp so the ecma-99.1 # sweep validates every generated file against the ECMA-376 schema. # # The test is intentionally a single large body rather than many # small tests, because its purpose is to produce a complex real-world # document and verify that the library does not error out. Per-feature # unit tests live in the other .test files. package require tcltest 2.5 namespace import ::tcltest::* package require ooxml::docx # ── Lorem ipsum texts ──────────────────────────────────────────── namespace eval ::featuretest { variable lorem array set lorem { short "Lorem ipsum dolor sit amet, consectetur adipiscing elit." medium "Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat." long "Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Curabitur pretium tincidunt lacus. Nulla gravida orci a odio. Nullam varius, turpis et commodo pharetra, est eros bibendum elit, nec luctus magna felis sollicitudin mauris." list1 "Pellentesque habitant morbi tristique senectus." list2 "Netus et malesuada fames ac turpis egestas." list3 "Vestibulum tortor quam, feugiat vitae, ultricies eget." fn1 "Fusce dapibus, tellus ac cursus commodo." fn2 "Tortor mauris condimentum nibh, ut fermentum massa." en1 "Maecenas sed diam eget risus varius blandit sit amet non." cmt1 "Aenean lacinia bibendum nulla sed consectetur." cmt2 "Praesent commodo cursus magna, vel scelerisque nisl." math "The quadratic formula is given by" matrix "Consider the rotation matrix" } } # ══════════════════════════════════════════════════════════════════ # Main feature-exercise test # ══════════════════════════════════════════════════════════════════ test feature-1.0 {comprehensive feature exercise produces valid docx} -body { array set lorem [array get ::featuretest::lorem] set outfile [tmpfile .docx] set imgfile [writeTinyPng] set doc [newdoc] # ── 1. Document properties ─────────────────────────────────── $doc configure \ -title "OOXML Feature Exercise" \ -creator "ooxml test suite" \ -subject "Comprehensive feature test" \ -description "Exercises every supported feature." \ -keywords "ooxml test" \ -category "Testing" \ -language "en-US" # ── 2. Settings ────────────────────────────────────────────── $doc settings \ -defaultTabStop 720 \ -autoHyphenation on \ -hideSpellingErrors on \ -hideGrammaticalErrors on # ── 3. Styles ──────────────────────────────────────────────── $doc style paragraph "Title" \ -bold on -fontsize 56 -align center -color 1F3864 $doc style paragraph "Heading 1" \ -bold on -fontsize 36 -color 2E75B6 \ -spacing {before 360 after 120} $doc style paragraph "Heading 2" \ -bold on -italic on -fontsize 28 -color 2E75B6 \ -spacing {before 240 after 80} $doc style paragraph "Body Text" \ -fontsize 22 \ -spacing {after 120 line 276 lineRule auto} $doc style paragraph "Indented" \ -basedon "Body Text" \ -indentation {start 720 end 720} $doc style character "Emphasis" -italic on -color C00000 $doc style character "Strong" -bold on $doc style character "Code" -font "Courier New" -fontsize 20 -color 333333 $doc style table "GridTable" -bold on # ── 4. Numbering ───────────────────────────────────────────── $doc numbering abstractNum 1 { {-numberFormat decimal -levelText "%1." -align start -start 1} {-numberFormat lowerLetter -levelText "%2)" -align start} } $doc numbering abstractNum 2 { {-numberFormat bullet -levelText "\u2022" -align start} {-numberFormat bullet -levelText "\u2013" -align start} } # ── 5. Header and Footer ───────────────────────────────────── set hId [$doc header { $doc paragraph "OOXML Feature Exercise" \ -align center -fontsize 16 -color 888888 }] set fId [$doc footer { $doc paragraph "Page " -align center -fontsize 16 -color 888888 $doc field PAGE $doc append " of " $doc field NUMPAGES }] $doc pagesetup \ -defaultHeader $hId \ -defaultFooter $fId \ -margins {top 1440 bottom 1440 left 1440 right 1440 header 720 footer 720} \ -sizeAndOrientation {width 12240 height 15840} # ── 6. Character formatting ────────────────────────────────── $doc paragraph "OOXML Feature Exercise" -pstyle "Title" $doc paragraph "" $doc paragraph "1. Character Formatting" -pstyle "Heading 1" $doc paragraph "$lorem(short)" -pstyle "Body Text" -bold on $doc paragraph "$lorem(short)" -pstyle "Body Text" -italic on $doc paragraph "$lorem(short)" -pstyle "Body Text" -underline single $doc paragraph "$lorem(short)" -pstyle "Body Text" -underline double $doc paragraph "$lorem(short)" -pstyle "Body Text" -underline dotted $doc paragraph "$lorem(short)" -pstyle "Body Text" -strike on $doc paragraph "$lorem(short)" -pstyle "Body Text" -dstrike on $doc paragraph "$lorem(short)" -pstyle "Body Text" -emboss on $doc paragraph "$lorem(short)" -pstyle "Body Text" -color FF0000 $doc paragraph "$lorem(short)" -pstyle "Body Text" -color 0000FF -highlight yellow $doc paragraph "$lorem(short)" -pstyle "Body Text" -fontsize 48 $doc paragraph "$lorem(short)" -pstyle "Body Text" -fontsize 16 -noProof on $doc paragraph "$lorem(short)" -pstyle "Body Text" -verticalAlign superscript $doc paragraph "$lorem(short)" -pstyle "Body Text" -verticalAlign subscript $doc paragraph "$lorem(short)" -pstyle "Body Text" -font "Georgia" $doc paragraph "$lorem(short)" -pstyle "Body Text" \ -bold on -italic on -underline single -color C00000 -fontsize 28 # Append and character styles $doc paragraph "This uses " -pstyle "Body Text" $doc append "emphasis" -cstyle "Emphasis" $doc append " and " $doc append "strong" -cstyle "Strong" $doc append " and " $doc append "code" -cstyle "Code" $doc append " character styles." # ── 7. Paragraph formatting ────────────────────────────────── $doc paragraph "2. Paragraph Formatting" -pstyle "Heading 1" $doc paragraph "$lorem(medium)" -align start -spacing {before 120 after 120} $doc paragraph "$lorem(short)" -align center $doc paragraph "$lorem(short)" -align end $doc paragraph "$lorem(medium)" -align both $doc paragraph "$lorem(medium)" -pstyle "Indented" $doc paragraph "$lorem(medium)" \ -spacing {before 240 after 240 line 360 lineRule exact} $doc paragraph "$lorem(short)" -background FFFF00 $doc paragraph "$lorem(short)" -shading {type clear fill DDEEFF} $doc paragraph "$lorem(short)" -shading {type pct10 color 000000 fill FFFFFF} $doc paragraph "$lorem(short)" -keepNext on -keepLines on $doc paragraph "$lorem(short)" -widowControl on $doc paragraph "$lorem(short)" -suppressLineNumbers on $doc paragraph "$lorem(short)" -indentation {start 1440 firstLine 720} $doc paragraph "$lorem(short)" -indentation {hanging 360 start 720} # ── 8. Breaks and tabs ─────────────────────────────────────── $doc paragraph "3. Breaks and Tabs" -pstyle "Heading 1" $doc paragraph "Line one." $doc br $doc append "Line two." $doc br 2 $doc append "Line four." $doc paragraph "Col A" $doc tab $doc append "Col B" $doc tab 2 $doc append "Col C" # ── 9. Fields ──────────────────────────────────────────────── $doc paragraph "4. Fields" -pstyle "Heading 1" foreach ftype {PAGE NUMPAGES DATE TIME AUTHOR TITLE} { $doc paragraph "$ftype: " $doc field $ftype } # ── 10. Bookmarks and links ────────────────────────────────── $doc paragraph "5. Bookmarks and Links" -pstyle "Heading 1" $doc paragraph "Point bookmark." $doc mark bookmark1 $doc markstart "RangeBookmark" $doc paragraph "$lorem(short)" $doc markend "RangeBookmark" $doc paragraph "" $doc jumpto "Jump to bookmark" bookmark1 -color 0000FF -underline single $doc paragraph "" $doc url "Example.com" "https://example.com" -color 0563C1 -underline single # ── 11. Lists ──────────────────────────────────────────────── $doc paragraph "6. Lists" -pstyle "Heading 1" $doc paragraph "$lorem(list1)" -numberingStyle 1 -level 0 $doc paragraph "$lorem(list2)" -numberingStyle 1 -level 0 $doc paragraph "Sub-item." -numberingStyle 1 -level 1 $doc paragraph "$lorem(list3)" -numberingStyle 1 -level 0 $doc paragraph "" $doc paragraph "$lorem(list1)" -numberingStyle 2 -level 0 $doc paragraph "$lorem(list2)" -numberingStyle 2 -level 0 $doc paragraph "Nested dash." -numberingStyle 2 -level 1 $doc paragraph "$lorem(list3)" -numberingStyle 2 -level 0 # ── 12. Tables ─────────────────────────────────────────────── $doc pagebreak $doc paragraph "7. Tables" -pstyle "Heading 1" $doc table \ -columnwidths {3120 3120 3120} \ -width {type dxa value 9360} \ -align center \ -look {firstRow on lastRow off firstColumn on lastColumn off noHBand off noVBand on} \ -topBorder {type single borderwidth 8 color 2E75B6} \ -bottomBorder {type single borderwidth 8 color 2E75B6} \ -insideHBorder {type single borderwidth 4 color CCCCCC} \ -insideVBorder {type single borderwidth 4 color CCCCCC} \ { $doc tablerow -headerrow on { $doc tablecell -background 2E75B6 { $doc paragraph "Header A" -bold on -color FFFFFF -align center } $doc tablecell -background 2E75B6 { $doc paragraph "Header B" -bold on -color FFFFFF -align center } $doc tablecell -background 2E75B6 { $doc paragraph "Header C" -bold on -color FFFFFF -align center } } $doc tablerow { $doc tablecell -shading {type clear fill F2F2F2} { $doc paragraph "Row 1, A" } $doc tablecell -vAlign center { $doc paragraph "Row 1, B" -align center } $doc tablecell { $doc paragraph "Row 1, C" } } $doc tablerow { $doc tablecell { $doc paragraph "Row 2, A" } $doc tablecell -textDirection btLr { $doc paragraph "Vertical" -align center } $doc tablecell -vAlign bottom { $doc paragraph "Bottom-aligned" -align end } } $doc tablerow { $doc tablecell -span 2 -background DDEEFF { $doc paragraph "Spanning two columns" -bold on } $doc tablecell { $doc paragraph "Single cell" } } } $doc paragraph "" $doc simpletable { {"Name" "Role" "Location"} {"Marcus" "Developer" "Roma"} {"Claudia" "Designer" "Mediolanum"} {"Gaius" "Architect" "Carthago"} } # ── 13. Footnotes, endnotes ────────────────────────────────── $doc paragraph "8. Footnotes and Endnotes" -pstyle "Heading 1" $doc paragraph "$lorem(medium)" $doc footnote { $doc paragraph "$lorem(fn1)" } $doc paragraph "$lorem(short)" $doc footnote { $doc paragraph "$lorem(fn2)" } $doc paragraph "$lorem(short)" $doc endnote { $doc paragraph "$lorem(en1)" } # ── 14. Comments ───────────────────────────────────────────── $doc paragraph "9. Comments" -pstyle "Heading 1" $doc paragraph "$lorem(short)" $doc comment -author "Reviewer A" -initials "RA" { $doc paragraph "$lorem(cmt1)" } $doc paragraph "$lorem(medium)" $doc simplecomment "$lorem(cmt2)" -author "Reviewer B" set rangeId [$doc commentrangestart] $doc paragraph "$lorem(short)" $doc commentrangeend $rangeId -author "Reviewer C" { $doc paragraph "Range comment." } set rid2 [$doc commentrangestart] $doc paragraph "$lorem(short)" $doc simplecommentrangeend $rid2 "Simple range comment." -author "Reviewer D" # ── 15. Images ─────────────────────────────────────────────── $doc paragraph "10. Images" -pstyle "Heading 1" $doc paragraph "Inline image:" $doc image $imgfile inline -dimension {width 914400 height 914400} $doc paragraph "Anchor image:" $doc image $imgfile anchor \ -dimension {width 457200 height 457200} \ -positionH column -posOffsetH 4572000 \ -positionV paragraph -posOffsetV 0 \ -wrapMode square -wrapData {wrapText bothSides} $doc paragraph "$lorem(medium)" # ── 16. Textbox ────────────────────────────────────────────── $doc paragraph "11. Textbox" -pstyle "Heading 1" $doc textbox \ -name "Sample Textbox" \ -dimension {width 3657600 height 1371600} \ -bodyAtts {wrap square} { $doc paragraph "Inside the textbox" -bold on -color 2E75B6 $doc paragraph "$lorem(short)" -fontsize 18 } $doc paragraph "$lorem(medium)" # ── 17. Math ───────────────────────────────────────────────── $doc pagebreak $doc paragraph "12. Mathematics" -pstyle "Heading 1" # Inline fraction $doc paragraph "Inline: " -pstyle "Body Text" $doc math { $doc mfrac { $doc mrun "a + b" } { $doc mrun "c" } } $doc append " ratio." # Display: quadratic formula $doc math -display 1 -jc center { $doc mrun "x = " $doc mfrac { $doc mrun "\u2212b \u00B1 " $doc msqrt { $doc msup { $doc mrun "b" } { $doc mrun "2" } $doc mrun " \u2212 4ac" } } { $doc mrun "2a" } } # Sub / sup / subsup $doc math -display 1 -jc center { $doc msub { $doc mrun "x" } { $doc mrun "i" } $doc mrun " + " $doc msup { $doc mrun "y" } { $doc mrun "2" } $doc mrun " + " $doc msubsup { $doc mrun "z" } { $doc mrun "i" } { $doc mrun "n" } } # Roots $doc math -display 1 -jc center { $doc msqrt { $doc mrun "a\u00B2 + b\u00B2" } $doc mrun " and " $doc mroot { $doc mrun "3" } { $doc mrun "x + 1" } } # N-ary $doc math -display 1 -jc center { $doc mnary -char "\u2211" -limLoc undOvr -grow 1 \ -sub { $doc mrun "i=1" } -sup { $doc mrun "n" } { $doc msub { $doc mrun "a" } { $doc mrun "i" } } $doc mrun " = " $doc mnary -char "\u222B" -limLoc subSup \ -sub { $doc mrun "0" } -sup { $doc mrun "\u221E" } { $doc mrun "f(x) dx" } } # Function $doc math -display 1 -jc center { $doc mfunc { $doc mrun "sin" } { $doc mdelim { $doc mrun "\u03B8" } } $doc mrun " + " $doc mfunc { $doc mrun "cos" } { $doc mdelim { $doc mrun "\u03B8" } } } # Limits $doc math -display 1 -jc center { $doc mlimlow { $doc mrun "lim" } { $doc mrun "n\u2192\u221E" } $doc mdelim { $doc mrun "1 + " $doc mfrac { $doc mrun "1" } { $doc mrun "n" } } $doc msup {} { $doc mrun "n" } } $doc math -display 1 -jc center { $doc mlimupp { $doc mrun "x + y + z" } { $doc mrun "k terms" } } # Accent $doc math -display 1 -jc center { $doc maccent { $doc mrun "x" } $doc mrun " , " $doc maccent -char "\u0303" { $doc mrun "y" } $doc mrun " , " $doc maccent -char "\u0307" { $doc mrun "z" } $doc mrun " , " $doc maccent -char "\u20D7" { $doc mrun "v" } } # Bar $doc math -display 1 -jc center { $doc mbar { $doc mrun "X" } $doc mrun " and " $doc mbar -pos bot { $doc mrun "Y" } } # Delimiters $doc math -display 1 -jc center { $doc mdelim { $doc mrun "a + b" } $doc mrun " , " $doc mdelim -begChr "\[" -endChr "\]" { $doc mdelimarg { $doc mrun "x" } $doc mdelimarg { $doc mrun "y" } } $doc mrun " , " $doc mdelim -begChr "|" -endChr "|" { $doc mrun "z" } $doc mrun " , " $doc mdelim -begChr "\{" -endChr "\}" -grow 1 { $doc mfrac { $doc mrun "a" } { $doc mrun "b" } } } # Grouping character $doc math -display 1 -jc center { $doc mgroupchr { $doc mrun "a + b + c" } $doc mrun " + " $doc mgroupchr -char "\u23DE" -pos top -vertJc bot { $doc mrun "d + e" } } # Matrix $doc math -display 1 -jc center { $doc mrun "R = " $doc mdelim -begChr "\[" -endChr "\]" { $doc mmatrix -mcJc center { { $doc mmatcell { $doc mrun "cos \u03B8" } $doc mmatcell { $doc mrun "\u2212sin \u03B8" } } { $doc mmatcell { $doc mrun "sin \u03B8" } $doc mmatcell { $doc mrun "cos \u03B8" } } } } } # Math run styles + fraction types $doc math -display 1 -jc center { $doc mrun -sty b "F" $doc mrun " = m" $doc mrun -sty bi "a" } $doc math -display 1 -jc center { $doc mfrac { $doc mrun "a" } { $doc mrun "b" } $doc mrun " , " $doc mfrac -type lin { $doc mrun "c" } { $doc mrun "d" } $doc mrun " , " $doc mfrac -type noBar { $doc mrun "n" } { $doc mrun "k" } $doc mrun " , " $doc mfrac -type skw { $doc mrun "1" } { $doc mrun "2" } } # ── 18. Sections ───────────────────────────────────────────── $doc pagebreak $doc paragraph "13. Sections" -pstyle "Heading 1" $doc paragraph "$lorem(medium)" -pstyle "Body Text" $doc sectionstart -sectionType continuous $doc paragraph "$lorem(long)" -pstyle "Body Text" $doc sectionend $doc sectionstart -sectionType continuous $doc paragraph "Back to normal." -pstyle "Body Text" $doc sectionend # ── 19. Replace ────────────────────────────────────────────── $doc paragraph "14. Replacement" -pstyle "Heading 1" $doc paragraph "The word PLACEHOLDER will be replaced." $doc replace PLACEHOLDER "SUBSTITUTED" # ── 20. Inspection ─────────────────────────────────────────── set parts [$doc xmlparts] set paraCount [expr {int([$doc xpath {count(//w:p)}])}] set firstText [$doc selectNodes {string(//w:p[1]//w:t)}] # ── Write v1 ───────────────────────────────────────────────── $doc write $outfile # ── Post-write: writepart, readpart, import ────────────────── set settingsFile [tmpfile .xml] $doc writepart word/settings.xml $settingsFile $doc readpart word/settings.xml $settingsFile set outfile2 [tmpfile .docx] $doc import styles $outfile $doc paragraph "Post-import content." -pstyle "Body Text" $doc write $outfile2 # Clean up file delete -force $imgfile $doc destroy # Return success indicator list ok [llength $parts] $paraCount [expr {$firstText ne ""}] } -match glob -result {ok * * 1} cleanupTests ooxml/tests/docx-settings.test000664 000765 000024 00000004170 15213015413 017145 0ustar00alexstaff000000 000000 # settings.test -- # # Tests for settings method, reorder algorithm, and # multiply-occurring elements. package require tcltest 2.5 namespace import ::tcltest::* package require ooxml::docx test settings-1.1 {basic setting} -body { withDoc doc { $doc settings -defaultTabStop 720 xpath $doc {string(//w:defaultTabStop/@w:val)} word/settings.xml } } -result 720 test settings-1.2 {multiple settings} -body { withDoc doc { $doc settings -autoHyphenation off -hideSpellingErrors on set hyp [xpath $doc {string(//w:autoHyphenation/@w:val)} word/settings.xml] set spell [xpath $doc {string(//w:hideSpellingErrors/@w:val)} word/settings.xml] list $hyp $spell } } -result {0 1} test settings-1.3 {settings replaces existing value} -body { withDoc doc { # Default settings.xml has autoHyphenation=true $doc settings -autoHyphenation off xpath $doc {string(//w:autoHyphenation/@w:val)} word/settings.xml } } -result 0 test settings-1.4 {incremental settings calls} -body { withDoc doc { $doc settings -defaultTabStop 360 $doc settings -hideSpellingErrors on set tab [xpath $doc {string(//w:defaultTabStop/@w:val)} word/settings.xml] set spell [xpath $doc {string(//w:hideSpellingErrors/@w:val)} word/settings.xml] list $tab $spell } } -result {360 1} # Handling of multiple settings child is not implemented so far # test settings-2.1 {repeating element attachedSchema} -body { # withDoc doc { # $doc settings -attachedSchema "urn:schema:one" # $doc settings -attachedSchema "urn:schema:two" # countNodes $doc {//w:attachedSchema} word/settings.xml # } # } -result 2 test settings-2.2 {evenAndOddHeaders} -body { withDoc doc { $doc settings -evenAndOddHeaders on xpath $doc {string(//w:evenAndOddHeaders/@w:val)} word/settings.xml } } -result 1 test settings-3.1 {reset settings} -body { withDoc doc { $doc settings -reset on -defaultTabStop 500 xpath $doc {string(//w:defaultTabStop/@w:val)} word/settings.xml } } -result 500 cleanupTests ooxml/tests/docx-reg.test000664 000765 000024 00000023051 15213015413 016061 0ustar00alexstaff000000 000000 # regression.test -- # # Regression tests for all bugs identified and fixed during # code review rounds. Each test is tagged with the original # finding number. package require tcltest 2.5 namespace import ::tcltest::* package require ooxml::docx # ══════════════════════════════════════════════════════════════════ # Round 1 — Math module fixes # ══════════════════════════════════════════════════════════════════ test reg-R1-baseJc {-baseJc accepts vertical values not horizontal} -body { withDoc doc { $doc math -display 1 { $doc mmatrix -baseJc center { { $doc mmatcell { $doc mrun "a" } } } } xpath $doc {string(//m:mPr/m:baseJc/@m:val)} } } -result center test reg-R1-baseJc-rejects-horizontal {-baseJc rejects horizontal values} -body { withDoc doc { $doc math -display 1 { $doc mmatrix -baseJc left { { $doc mmatcell { $doc mrun "a" } } } } } } -returnCodes error -match glob -result {*unknown*} test reg-R1-mdelim-empty {empty mdelim still has m:e} -body { withDoc doc { $doc math -display 1 { $doc mdelim { } } countNodes $doc {//m:d/m:e} } } -result 1 test reg-R1-msqrt-degHide {msqrt has degHide and empty deg} -body { withDoc doc { $doc math -display 1 { $doc msqrt { $doc mrun "x" } } set dh [xpath $doc {string(//m:radPr/m:degHide/@m:val)}] set deg [countNodes $doc {//m:rad/m:deg}] list $dh $deg } } -result {1 1} test reg-R1-mroot-no-empty-radPr {mroot omits radPr when no properties} -body { withDoc doc { $doc math -display 1 { $doc mroot { $doc mrun "3" } { $doc mrun "x" } } countNodes $doc {//m:rad/m:radPr} } } -result 0 test reg-R1-ST_Integer255 {ST_Integer255 rejects 0} -body { ::ooxml::docx::lib::ST_Integer255 0 } -returnCodes error -match glob -result {*1..255*} # ══════════════════════════════════════════════════════════════════ # Round 2 — Production review blocker fixes # ══════════════════════════════════════════════════════════════════ test reg-R2-configure-EatOption {configure -ignorable uses my EatOption} -body { # This would crash with "invalid command name EatOption" if bare withDoc doc { $doc configure -ignorable "w14" expr {1} } } -result 1 test reg-R2-formatting-attr {documentProtection uses formatting not formating} -body { withDoc doc { $doc settings -documentProtection {edit readOnly formatting 1 enforcement 1} set xml [$doc xpath {string(//w:documentProtection/@w:formatting)} word/settings.xml] set xml } } -result 1 # ══════════════════════════════════════════════════════════════════ # Round 3 — Style consistency fixes # ══════════════════════════════════════════════════════════════════ test reg-R3-styleId-derived {styleId derived by stripping non-alnum} -body { withDoc doc { $doc style paragraph "Heading (Level 1)" set ids [$doc style ids paragraph] expr {"HeadingLevel1" in $ids} } } -result 1 test reg-R3-styleId-collision {duplicate derived styleId rejected} -body { withDoc doc { $doc style paragraph "My Heading" $doc style paragraph "My-Heading" } } -returnCodes error -match glob -result {*styleId*already*} test reg-R3-basedon-resolves {-basedon resolves through StyleCheck} -body { withDoc doc { $doc style paragraph "Parent Style" -bold on $doc style paragraph "Child Style" -basedon "Parent Style" xpath $doc { string(//w:style[@w:styleId='ChildStyle']/w:basedOn/@w:val) } word/styles.xml } } -result ParentStyle test reg-R3-delete-by-name {style delete uses display name} -body { withDoc doc { $doc style paragraph "To Delete" $doc style deleteByName paragraph "To Delete" set ids [$doc style ids paragraph] expr {"ToDelete" ni $ids} } } -result 1 # ══════════════════════════════════════════════════════════════════ # Round 4 — Settings reorder # ══════════════════════════════════════════════════════════════════ # Handling of multiple settings child is not implemented so far # test reg-R4-settings-repeating {attachedSchema allows multiple values} -body { # withDoc doc { # $doc settings -attachedSchema "urn:one" # $doc settings -attachedSchema "urn:two" # $doc settings -attachedSchema "urn:three" # countNodes $doc {//w:attachedSchema} word/settings.xml # } # } -result 3 # ══════════════════════════════════════════════════════════════════ # Round 5 — Production review fixes # ══════════════════════════════════════════════════════════════════ test reg-R5-footnote-separators {footnote part has separator entries} -body { withDoc doc { $doc paragraph "Text" $doc footnote { $doc paragraph "Note." } set sep [countNodes $doc {//w:footnote[@w:type='separator']} word/footnotes.xml] set cont [countNodes $doc {//w:footnote[@w:type='continuationSeparator']} word/footnotes.xml] list $sep $cont } } -result {1 1} test reg-R5-comment-rollback-on-bad-option {comment rollback on unknown option} -constraints mutation -body { withDoc doc { $doc paragraph "Text" catch { $doc comment -author "A" -badOption x { $doc paragraph "X" } } if {[haspart $doc word/comments.xml]} { countNodes $doc {//w:comment} word/comments.xml } else { expr {0} } } } -result 0 test reg-R5-hf-rollback {header rollback on script error} -constraints mutation -body { withDoc doc { catch { $doc header { error "fail" } } expr {![haspart $doc word/header1.xml]} } } -result 1 test reg-R5-sectPr-cleanup-in-finally {sectPr cleaned up even on write concepts} -body { # Verify cleanup is inside finally by writing, then adding content withDoc doc { $doc paragraph "Before" writedoc $doc $doc paragraph "After" # After write+cleanup, last body child should be the new paragraph set last [xpath $doc {local-name(//w:body/*[last()])}] set last } } -result p test reg-R5-footnote-option-validation {unknown footnote option rejected} -body { withDoc doc { $doc paragraph "Text" $doc footnote -badopt xyz { $doc paragraph "Note." } } } -returnCodes error -match glob -result {*unknown*badopt*} # ══════════════════════════════════════════════════════════════════ # Round 6 — Paragraph background # ══════════════════════════════════════════════════════════════════ test reg-R6-paragraph-background {paragraph -background creates shd} -body { withDoc doc { $doc paragraph "Yellow" -background FFFF00 set val [xpath $doc {string(//w:pPr/w:shd/@w:val)}] set fill [xpath $doc {string(//w:pPr/w:shd/@w:fill)}] list $val $fill } } -result {clear FFFF00} # ══════════════════════════════════════════════════════════════════ # Round 7 — Final audit fixes # ══════════════════════════════════════════════════════════════════ test reg-R7-cd-count-init {write initializes cd and count} -body { # This is implicitly tested by any successful write, but verify # explicitly that multiple writes don't accumulate stale cd/count withDoc doc { $doc paragraph "First" writedoc $doc $doc paragraph "Second" set f [writedoc $doc] # If cd/count weren't re-initialized, the second write would # have double entries. Check that zip has expected part count. set parts [ziplist $f] # Should have standard parts, not duplicates expr {[llength $parts] == [llength [lsort -unique $parts]]} } } -result 1 cleanupTests ooxml/tests/docx-lib.test000664 000765 000024 00000002244 15213015413 016053 0ustar00alexstaff000000 000000 # # Covers the type function lib # # (c) 2025 Rolf Ade # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # if {[lsearch [namespace children] ::tcltest] == -1} { package require tcltest 2 namespace import -force ::tcltest::* loadTestedCommands } source [file join [file dir [info script]] ../ooxml-docx-lib.tcl] namespace import ::ooxml::docx::lib::* test docxlib-1.1 {ST_TwipsMeasure} { set result "" foreach {value} { 3 1pt 2.3pt 0pt 2.33pt 2.32pt " 3" " 2.34pt " } { lappend result [ST_TwipsMeasure $value] } set result } {3 20 46 0 47 46 3 47} test docxlib-1.2 {ST_TwipsMeasure} { set result "" foreach {value} { 3,1 .2 -3 -.3pt 0PT "1 pt" 2Cm } { if {![catch {ST_TwipsMeasure $value}]} { lappend result "\"$value\" dit not raise error but should" } } set result } {} test docxlib-1.3 {ST_SignedTwipsMeasure} { ST_SignedTwipsMeasure -2.3pt } -46 # cleanup ::tcltest::cleanupTests return n ooxml/tests/docx-ecma.test000664 000765 000024 00000035176 15213015413 016224 0ustar00alexstaff000000 000000 # validate.test -- # # Structural validation of generated .docx files against # ECMA-376 / ISO 29500 constraints. # # Each test generates a document with specific features, writes # it to disk, then runs the ECMA-376 structural validator. # A passing test means zero validation errors. package require tcltest 2.5 namespace import ::tcltest::* package require ooxml::docx # Load the validator source [file join [file dirname [info script]] ecma376 validate.tcl] # ── Helper ────────────────────────────────────────────────────── proc validateDocx {doc} { set f [writedoc $doc] set errors [ecma376::validate::docx $f] return $errors } # ══════════════════════════════════════════════════════════════════ # Minimal document # ══════════════════════════════════════════════════════════════════ test ecma-1.1 {minimal document passes ECMA validation} -body { withDoc doc { $doc paragraph "Hello" validateDocx $doc } } -result {} test ecma-1.2 {empty paragraph document passes} -body { withDoc doc { $doc paragraph "" validateDocx $doc } } -result {} test ecma-1.3 {multiple paragraphs pass} -body { withDoc doc { $doc paragraph "One" $doc paragraph "Two" -bold on $doc paragraph "Three" -italic on -color FF0000 validateDocx $doc } } -result {} # ══════════════════════════════════════════════════════════════════ # Formatted content # ══════════════════════════════════════════════════════════════════ test ecma-2.1 {paragraph with all run formatting passes} -body { withDoc doc { $doc paragraph "Bold" -bold on $doc paragraph "Italic" -italic on $doc paragraph "Underline" -underline single $doc paragraph "Strike" -strike on $doc paragraph "Color" -color 00FF00 $doc paragraph "Size" -fontsize 48 $doc paragraph "Combo" -bold on -italic on -color FF0000 -fontsize 28 validateDocx $doc } } -result {} test ecma-2.2 {paragraph with alignment and spacing} -body { withDoc doc { $doc paragraph "Left" -align start $doc paragraph "Center" -align center $doc paragraph "Right" -align end $doc paragraph "Spaced" -spacing {before 240 after 120} validateDocx $doc } } -result {} test ecma-2.3 {append creates valid runs} -body { withDoc doc { $doc paragraph "Start " $doc append "middle " -bold on $doc append "end" -italic on validateDocx $doc } } -result {} # ══════════════════════════════════════════════════════════════════ # Tables # ══════════════════════════════════════════════════════════════════ test ecma-3.1 {table structure valid} -body { withDoc doc { $doc table { $doc tablerow { $doc tablecell { $doc paragraph "A" } $doc tablecell { $doc paragraph "B" } } $doc tablerow { $doc tablecell { $doc paragraph "C" } $doc tablecell { $doc paragraph "D" } } } validateDocx $doc } } -result {} test ecma-3.2 {simpletable valid} -body { withDoc doc { $doc simpletable {{A B C} {D E F}} validateDocx $doc } } -result {} # ══════════════════════════════════════════════════════════════════ # Styles # ══════════════════════════════════════════════════════════════════ test ecma-4.1 {custom styles with inheritance pass} -body { withDoc doc { $doc style paragraph "Base" -bold on $doc style paragraph "Child" -basedon "Base" -italic on $doc style character "Emph" -color FF0000 $doc paragraph "Styled" -pstyle "Child" validateDocx $doc } } -result {} # ══════════════════════════════════════════════════════════════════ # Footnotes and endnotes # ══════════════════════════════════════════════════════════════════ test ecma-5.1 {footnote has separators and valid structure} -body { withDoc doc { $doc paragraph "Text with footnote." $doc footnote { $doc paragraph "The footnote text." } validateDocx $doc } } -result {} test ecma-5.2 {multiple footnotes valid} -body { withDoc doc { $doc paragraph "First." $doc footnote { $doc paragraph "Note one." } $doc paragraph "Second." $doc footnote { $doc paragraph "Note two." } validateDocx $doc } } -result {} test ecma-5.3 {endnote valid} -body { withDoc doc { $doc paragraph "Text" $doc endnote { $doc paragraph "End note." } validateDocx $doc } } -result {} test ecma-5.4 {both footnotes and endnotes valid} -body { withDoc doc { $doc paragraph "Text" $doc footnote { $doc paragraph "Foot." } $doc endnote { $doc paragraph "End." } validateDocx $doc } } -result {} # ══════════════════════════════════════════════════════════════════ # Comments # ══════════════════════════════════════════════════════════════════ test ecma-6.1 {comment produces valid package} -body { withDoc doc { $doc paragraph "Commented." $doc comment -author "Reviewer" { $doc paragraph "A comment." } validateDocx $doc } } -result {} test ecma-6.2 {range comment valid} -body { withDoc doc { $doc paragraph "Before" set id [$doc commentrangestart] $doc paragraph "Inside range" $doc commentrangeend $id -author "R" { $doc paragraph "Range note." } validateDocx $doc } } -result {} # ══════════════════════════════════════════════════════════════════ # Headers and footers # ══════════════════════════════════════════════════════════════════ test ecma-7.1 {header and footer produce valid package} -body { withDoc doc { set hId [$doc header { $doc paragraph "Header" }] set fId [$doc footer { $doc paragraph "Footer" }] $doc pagesetup -defaultHeader $hId -defaultFooter $fId $doc paragraph "Body" validateDocx $doc } } -result {} # ══════════════════════════════════════════════════════════════════ # Math # ══════════════════════════════════════════════════════════════════ test ecma-8.1 {inline math valid} -body { withDoc doc { $doc paragraph "Eq: " $doc math { $doc mfrac { $doc mrun "a" } { $doc mrun "b" } } validateDocx $doc } } -result {} test ecma-8.2 {display math valid} -body { withDoc doc { $doc math -display 1 { $doc msub { $doc mrun "x" } { $doc mrun "i" } } validateDocx $doc } } -result {} # ══════════════════════════════════════════════════════════════════ # Write + reuse # ══════════════════════════════════════════════════════════════════ test ecma-9.1 {second write still valid} -body { withDoc doc { $doc paragraph "First" validateDocx $doc $doc paragraph "Second" validateDocx $doc } } -result {} # ══════════════════════════════════════════════════════════════════ # Complex document # ══════════════════════════════════════════════════════════════════ test ecma-10.1 {complex document with many features passes} -body { withDoc doc { $doc style paragraph "Heading1" -bold on -fontsize 32 $doc style character "Strong" -bold on -color 0000FF set hId [$doc header { $doc paragraph "Doc Header" }] set fId [$doc footer { $doc paragraph "Doc Footer" }] $doc pagesetup -defaultHeader $hId -defaultFooter $fId $doc paragraph "Introduction" -pstyle "Heading1" $doc paragraph "This is the body text." -spacing {before 120 after 120} $doc paragraph "A centered paragraph." -align center $doc table { $doc tablerow { $doc tablecell { $doc paragraph "Col A" } $doc tablecell { $doc paragraph "Col B" } } $doc tablerow { $doc tablecell { $doc paragraph "Data 1" } $doc tablecell { $doc paragraph "Data 2" } } } $doc paragraph "Text with a footnote." $doc footnote { $doc paragraph "The footnote." } $doc paragraph "Math: " $doc math { $doc mfrac { $doc mrun "x" } { $doc mrun "y" } } $doc paragraph "See " $doc url "example" "https://example.com" $doc paragraph "Comment target." $doc comment -author "Reviewer" { $doc paragraph "Needs revision." } validateDocx $doc } } -result {} # ══════════════════════════════════════════════════════════════════ # Schema: element ordering # ══════════════════════════════════════════════════════════════════ test ecma-11.1 {pPr children in schema order} -body { withDoc doc { # Exercise many pPr children to test ordering $doc paragraph "Complex" \ -bold on -italic on -fontsize 28 \ -align center \ -spacing {before 240 after 120} \ -shading {type clear fill FFFF00} validateDocx $doc } } -result {} test ecma-11.2 {rPr children in schema order} -body { withDoc doc { $doc paragraph "Multi-formatted" \ -bold on -italic on -underline single -strike on \ -color FF0000 -fontsize 24 -highlight yellow validateDocx $doc } } -result {} test ecma-11.3 {settings children in schema order after multiple calls} -body { withDoc doc { $doc settings -defaultTabStop 720 $doc settings -hideSpellingErrors on $doc settings -autoHyphenation off $doc paragraph "Body" validateDocx $doc } } -result {} # ══════════════════════════════════════════════════════════════════ # Schema: attribute enum values # ══════════════════════════════════════════════════════════════════ test ecma-12.1 {alignment values are valid ST_Jc} -body { withDoc doc { $doc paragraph "Left" -align start $doc paragraph "Center" -align center $doc paragraph "Right" -align end $doc paragraph "Both" -align both validateDocx $doc } } -result {} test ecma-12.2 {underline values are valid ST_Underline} -body { withDoc doc { $doc paragraph "Single" -underline single $doc paragraph "Double" -underline double $doc paragraph "Dotted" -underline dotted validateDocx $doc } } -result {} test ecma-12.3 {shading values are valid ST_Shd} -body { withDoc doc { $doc paragraph "Clear" -shading {type clear fill CCCCCC} $doc paragraph "Solid" -shading {type solid color 000000 fill FFFFFF} validateDocx $doc } } -result {} # ══════════════════════════════════════════════════════════════════ # Sweep: validate ALL .docx files produced by the entire test suite # ══════════════════════════════════════════════════════════════════ test ecma-99.1 {all test-generated docx files pass ECMA validation} -body { set allErrors [list] set docxFiles [glob -nocomplain -directory $::docxtest::tmpdir *.docx] set count 0 foreach f [lsort $docxFiles] { incr count set errors [ecma376::validate::docx $f] if {[llength $errors]} { lappend allErrors "[file tail $f]: [join $errors {; }]" } } if {[llength $allErrors]} { set allErrors } else { list } } -result {} cleanupTests ooxml/tests/docx-write.test000664 000765 000024 00000012154 15213015413 016440 0ustar00alexstaff000000 000000 # write.test -- # # Tests for write, writepart, object reuse after write, # atomic write behavior, and sectPr lifecycle. package require tcltest 2.5 namespace import ::tcltest::* package require ooxml::docx # ────────────────────────────────────────────────────────────────── # Basic write # ────────────────────────────────────────────────────────────────── test write-1.1 {write creates file} -body { withDoc doc { $doc paragraph "Test" set f [writedoc $doc] expr {[file exists $f] && [file size $f] > 0} } } -result 1 test write-1.2 {write adds .docx extension} -body { withDoc doc { $doc paragraph "Test" set f [tmpfile ""] set f [string trimright $f .] $doc write $f file exists "${f}.docx" } } -result 1 # ────────────────────────────────────────────────────────────────── # Object reuse after write # ────────────────────────────────────────────────────────────────── test write-2.1 {add content after write} -body { withDoc doc { $doc paragraph "First" writedoc $doc $doc paragraph "Second" countNodes $doc {//w:p} } } -result 2 test write-2.2 {second write produces larger file} -body { withDoc doc { $doc paragraph "First" set f1 [writedoc $doc] $doc paragraph "Second paragraph added" set f2 [writedoc $doc] expr {[file size $f2] > [file size $f1]} } } -result 1 test write-2.3 {sectPr not stale after write} -body { # After write, no synthetic sectPr should remain as body's last child # so new paragraphs don't end up after sectPr withDoc doc { $doc paragraph "Before write" writedoc $doc $doc paragraph "After write" # The last paragraph should be a w:p, not followed by a stale sectPr # (the sectPr will be added at next write time) set lastChild [xpath $doc {local-name(//w:body/*[last()])}] set lastChild } } -result p test write-2.4 {repeated write cycle} -body { withDoc doc { for {set i 1} {$i <= 5} {incr i} { $doc paragraph "Iteration $i" writedoc $doc } countNodes $doc {//w:p} } } -result 5 # ────────────────────────────────────────────────────────────────── # Write failure recovery # ────────────────────────────────────────────────────────────────── test write-3.1 {write to unwritable path fails gracefully} -body { withDoc doc { $doc paragraph "Test" set failed 0 catch { $doc write "/no/such/directory/test.docx" } err set failed 1 # Object should still be usable $doc paragraph "Still works" countNodes $doc {//w:p} } } -result 2 # ────────────────────────────────────────────────────────────────── # Atomic write (temp file) # ────────────────────────────────────────────────────────────────── test write-4.1 {no temp file remains after successful write} -body { withDoc doc { $doc paragraph "Test" set f [tmpfile] $doc write $f set dir [file dirname $f] set tmps [glob -nocomplain -directory $dir *.tmp] llength $tmps } } -result 0 # ────────────────────────────────────────────────────────────────── # writepart # ────────────────────────────────────────────────────────────────── test write-5.1 {writepart writes XML part} -body { withDoc doc { $doc paragraph "Test" set f [tmpfile .xml] $doc writepart word/document.xml $f set data [open $f r] set xml [read $data] close $data expr {[string match *w:document* $xml]} } } -result 1 test write-5.2 {writepart unknown part raises error} -body { withDoc doc { $doc writepart word/nonexistent.xml /tmp/test.xml } } -returnCodes error -match glob -result {*unknown part*} cleanupTests ooxml/tests/docx-val.test000664 000765 000024 00000014453 15213015413 016074 0ustar00alexstaff000000 000000 # validators.test -- # # Tests for validator edge cases, bounds, and error messages. package require tcltest 2.5 namespace import ::tcltest::* package require ooxml::docx # ────────────────────────────────────────────────────────────────── # Boolean validators # ────────────────────────────────────────────────────────────────── test val-1.1 {CT_OnOff true} -body { ::ooxml::docx::lib::CT_OnOff true } -result 1 test val-1.2 {CT_OnOff false} -body { ::ooxml::docx::lib::CT_OnOff false } -result 0 test val-1.3 {CT_OnOff yes} -body { ::ooxml::docx::lib::CT_OnOff yes } -result 1 test val-1.4 {CT_OnOff invalid} -body { ::ooxml::docx::lib::CT_OnOff "maybe" } -returnCodes error -match glob -result {*boolean*} # ────────────────────────────────────────────────────────────────── # Integer validators # ────────────────────────────────────────────────────────────────── test val-2.1 {ST_Integer255 minimum} -body { ::ooxml::docx::lib::ST_Integer255 1 } -result 1 test val-2.2 {ST_Integer255 maximum} -body { ::ooxml::docx::lib::ST_Integer255 255 } -result 255 test val-2.3 {ST_Integer255 zero rejected} -body { ::ooxml::docx::lib::ST_Integer255 0 } -returnCodes error -match glob -result {*1..255*} test val-2.4 {ST_Integer255 256 rejected} -body { ::ooxml::docx::lib::ST_Integer255 256 } -returnCodes error -match glob -result {*1..255*} test val-2.5 {ST_DecimalNumber} -body { ::ooxml::docx::lib::ST_DecimalNumber 42 } -result 42 test val-2.6 {ST_DecimalNumber non-integer rejected} -body { ::ooxml::docx::lib::ST_DecimalNumber "abc" } -returnCodes error -match glob -result *integer* test val-2.7 {CT_UnsignedInt} -body { ::ooxml::docx::lib::CT_UnsignedInt 0 } -result 0 test val-2.8 {CT_UnsignedInt non-numeric rejected} -body { ::ooxml::docx::lib::CT_UnsignedInt abc } -returnCodes error -match glob -result *unsigned* # ────────────────────────────────────────────────────────────────── # Enum validators # ────────────────────────────────────────────────────────────────── test val-3.1 {ST_Jc center} -body { ::ooxml::docx::lib::ST_Jc center } -result center test val-3.2 {ST_Jc invalid} -body { ::ooxml::docx::lib::ST_Jc middle } -returnCodes error -match glob -result {*unknown*} test val-3.3 {ST_MathStyle values} -body { list \ [::ooxml::docx::lib::ST_MathStyle p] \ [::ooxml::docx::lib::ST_MathStyle b] \ [::ooxml::docx::lib::ST_MathStyle i] \ [::ooxml::docx::lib::ST_MathStyle bi] } -result {p b i bi} test val-3.4 {ST_MathStyle invalid} -body { ::ooxml::docx::lib::ST_MathStyle bold } -returnCodes error -match glob -result {*unknown*} test val-3.5 {ST_BaseJc values} -body { list \ [::ooxml::docx::lib::ST_BaseJc top] \ [::ooxml::docx::lib::ST_BaseJc center] \ [::ooxml::docx::lib::ST_BaseJc bottom] } -result {top center bottom} test val-3.6 {ST_McJc values} -body { list \ [::ooxml::docx::lib::ST_McJc left] \ [::ooxml::docx::lib::ST_McJc center] \ [::ooxml::docx::lib::ST_McJc right] } -result {left center right} test val-3.7 {ST_SectionMark values} -body { ::ooxml::docx::lib::ST_SectionMark continuous } -result continuous test val-3.8 {ST_LineSpacingRule values} -body { list \ [::ooxml::docx::lib::ST_LineSpacingRule auto] \ [::ooxml::docx::lib::ST_LineSpacingRule exact] \ [::ooxml::docx::lib::ST_LineSpacingRule atLeast] } -result {auto exact atLeast} test val-3.9 {ST_VerticalJc values} -body { list \ [::ooxml::docx::lib::ST_VerticalJc top] \ [::ooxml::docx::lib::ST_VerticalJc center] \ [::ooxml::docx::lib::ST_VerticalJc bottom] \ [::ooxml::docx::lib::ST_VerticalJc both] } -result {top center bottom both} # ────────────────────────────────────────────────────────────────── # Measurement validators # ────────────────────────────────────────────────────────────────── test val-4.1 {ST_TwipsMeasure integer passthrough} -body { ::ooxml::docx::lib::ST_TwipsMeasure 1440 } -result 1440 test val-4.2 {ST_TwipsMeasure 1in = 1440 twips} -body { ::ooxml::docx::lib::ST_TwipsMeasure 1in } -result 1440 test val-4.3 {ST_TwipsMeasure 2.54cm = 1440 twips} -body { ::ooxml::docx::lib::ST_TwipsMeasure 2.54cm } -result 1440 test val-4.4 {ST_TwipsMeasure 25.4mm = 1440 twips} -body { ::ooxml::docx::lib::ST_TwipsMeasure 25.4mm } -result 1440 test val-4.5 {ST_TwipsMeasure 72pt = 1440 twips} -body { ::ooxml::docx::lib::ST_TwipsMeasure 72pt } -result 1440 test val-4.6 {ST_HpsMeasure integer passthrough} -body { ::ooxml::docx::lib::ST_HpsMeasure 24 } -result 24 test val-4.7 {ST_Emu valid} -body { ::ooxml::docx::lib::ST_Emu 914400 } -result 914400 # ────────────────────────────────────────────────────────────────── # Color validators # ────────────────────────────────────────────────────────────────── test val-5.1 {ST_HexColor valid} -body { ::ooxml::docx::lib::ST_HexColor FF00FF } -result FF00FF test val-5.2 {ST_HexColor auto} -body { ::ooxml::docx::lib::ST_HexColor auto } -result auto cleanupTests ooxml/tests/docx.test000664 000765 000024 00000014650 15213015413 015313 0ustar00alexstaff000000 000000 # # Commands covered: docx # # # (c) 2025 Rolf Ade # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # if {[lsearch [namespace children] ::tcltest] == -1} { package require tcltest 2 namespace import -force ::tcltest::* loadTestedCommands } package require ooxml namespace import ::ooxml::docx::docx set docx [docx new] test docx-1.1 {paragraph argument check} { catch {$docx paragraph} } 1 test docx-1.2 {paragraph argument check} { catch {$docx paragraph "some text"} } 0 test docx-1.3 {paragraph argument check} { catch {$docx paragraph "some text" -style} errMsg } 1 test docx-1.4 {mutually exclusive options} { set result [catch { $docx math { $docx mrun -sty p -nor 1 "some" } } errMsg] list $result $errMsg } {1 {The options -scr -sty and -nor are mutually exclusive.}} set counter 0 foreach {method fixedArguments postOptions} { append text "" comment "" {""} commentrangeend id script configure "" "" endnote "" script footnote "" script image "file type" "" jumpto "text mark" "" pagesetup "" "" paragraph text "" sectionstart "" "" settings "" "" simplecomment text "" simplecommentrangeend "id text" "" simpletable tabledata "" style paragraphdefault "" style characterdefault "" style "character name" "" style "paragraph name" "" style "table name" "" table "" script textbox "" script url "text url" "" } { incr counter set bodyScript "$docx $method" set expectedResult "invalid arguments, expected:" foreach fixedArgument $fixedArguments { append bodyScript " $fixedArgument" append expectedResult " $fixedArgument" } append bodyScript " -optionWithoutValue" append expectedResult " ?-option value? ?-option value? .." foreach postOption $postOptions { append bodyScript " {}" append expectedResult " $postOption" } test docx-1.5.$counter "Method $method - not paired option value list" \ -body $bodyScript \ -returnCodes error \ -result $expectedResult } set mathbodytmpl {$docx math {$bodyScript}} foreach {mathmethod fixedArguments postOptions} { maccent "" baseScript mbar "" baseScript mdelim "" script mfrac "" {numScript denScript} mgroupchr "" baseScript mmatrix "" rowScripts mnary "" baseScript mrun "" text } { set bodyScript "$docx $mathmethod" set expectedResult "invalid arguments, expected:" foreach fixedArgument $fixedArguments { append bodyScript " $fixedArgument" append expectedResult " $fixedArgument" } append bodyScript " -optionWithoutValue" append expectedResult " ?-option value? ?-option value? .." foreach postOption $postOptions { append bodyScript " {}" append expectedResult " $postOption" } test docx-1.5.$counter "Method $mathmethod - not paired option value list" \ -body [subst $mathbodytmpl] \ -returnCodes error \ -result $expectedResult } set counter 0 set expectedResult "unknown option: -notExistingOption, known option.*" foreach {method fixedArguments postOptions} { append text "" comment "" {""} configure "" "" endnote "" script footnote "" script jumpto "text mark" "" pagesetup "" "" paragraph text "" sectionstart "" "" settings "" "" simplecomment text "" simpletable tabledata "" style paragraphdefault "" style characterdefault "" style "character name" "" style "paragraph name" "" style "table name" "" table "" script url "text url" "" } { incr counter set bodyScript "$docx $method" foreach fixedArgument $fixedArguments { append bodyScript " $fixedArgument" } append bodyScript " -notExistingOption dummyValue" foreach postOption $postOptions { append bodyScript " {}" } test docx-1.6.$counter "Method $method - unknown option" \ -body $bodyScript \ -returnCodes error \ -match regexp \ -result $expectedResult } set mathbodytmpl {$docx math {$bodyScript}} foreach {mathmethod fixedArguments postOptions} { maccent "" baseScript mbar "" baseScript mdelim "" script mfrac "" {numScript denScript} mgroupchr "" baseScript mnary "" baseScript mrun "" text } { incr counter set bodyScript "$docx $mathmethod" foreach fixedArgument $fixedArguments { append bodyScript " $fixedArgument" } append bodyScript " -notExistingOption dummyValue" foreach postOption $postOptions { append bodyScript " {}" } test docx-1.6.$counter "Method $mathmethod - unknown option" \ -body [subst $mathbodytmpl] \ -returnCodes error \ -match regexp \ -result $expectedResult } $docx destroy test docx-2.1 {settings} { set docx [docx new] $docx settings -reset 1 set result [$docx xpath count(*) settings] $docx destroy set result } 0 test docx-2.2 {settings} { set docx [docx new] $docx settings -reset 1 $docx settings -defaultTabStop 400 -zoom {type bestFit percent 100} -autoHyphenation off set result "" foreach node [$docx xpath * settings] { lappend result [$node localName] } $docx destroy set result } {zoom defaultTabStop autoHyphenation} test docx-2.3 {settings} { set docx [docx new] $docx settings -reset 1 $docx settings -defaultTabStop 400 -zoom {type bestFit percent 100} -autoHyphenation off $docx settings -evenAndOddHeaders on -view outline -embedSystemFonts on \ -doNotEmbedSmartTags on -zoom {type textFit percent 200} set result [$docx xpath {* local-name()} settings -list] $docx destroy set result } {view zoom embedSystemFonts defaultTabStop autoHyphenation evenAndOddHeaders doNotEmbedSmartTags} test docx-2.4 {settings} { set docx [docx new] $docx settings -reset 1 $docx settings -defaultTabStop 400 -zoom {type bestFit percent 100} -autoHyphenation off $docx settings -evenAndOddHeaders on -view outline -embedSystemFonts on \ -doNotEmbedSmartTags on -zoom {type textFit percent 200} set result [$docx xpath string(w:zoom/@w:val) settings] lappend result [$docx xpath string(w:zoom/@w:percent) settings] $docx destroy set result } {textFit 200} # cleanup ::tcltest::cleanupTests return ooxml/tests/test_sheet1_xml_no_utf8.xlsx000644 000765 000024 00000016722 14764622263 021170 0ustar00alexstaff000000 000000 PK! '0docProps/app.xml (n0 n@VQzذq{gd:*KIgomɟqY1 1"CoBeϋ"K<I\ϟ*#YL[TQ26f,{V NVoyjГo=qGM`zPZ֪  \SnYħ׿!{Nɩz)Z:T 8\@]K䩠eƤUG % Zĸ}ۘ kE}7h)mܿDQ~󡁃`aᜳ0W{`G6Sy+ehZ/}[[ |yQw8nXPwzB@ϯfwRSPK!-=]docProps/core.xml (N0HC{8RYI*JHqm6}{ A;ή/Z$E(EzݬgJF+(ZW97k VrUHPAi+OdžKL0pHD'#|ڦ ;Lt6)k4aS)[AWƶmv ~[?Ƶn[`^RCU1I;_Ü_KjuV}B:D?+f,nbBb2ߐhwwᆂ<6π2PK!"Zxl/sharedStrings.xml\A 0Ew "hB;@3.3̢B'2HҴ\R^&WCFr(׫jHba jp37ZoÿBO PK!@|Ԇ xl/styles.xmlTmo0>iwj!K"Z"UI}u$Vl%w:m{szs=3cVB*u>_`uTUTh2|bߥ֝s fE-LR{OT'1V_a8'r{,DR6AeCqݩH҆P=F3Z;V k^,dI)OkEnZzR*/o~GT%$OK-A*:TޭSo+'9 V'<8fT S47N gٔ?;T9O+NZQSA.S2!~/5R,2 cp!AzOz7âc'_Gvd*Z.W q,B{lwāZTpO⭌/^vDG*, 5f/Nل1pNݘkJPI\'A16vҤ4ާp.F4ݗCaLJU 9B8cvd&` /}'<Ó?f;(_|ٟ_㹎O~s;&[x{W# >$1U|`1Mydc!b@ض^] ju[) xy~sA,#_b+r,y2u lc(1B۟@Ydau8‘!Ɩ&pn%Cr`$Ri -˨m=|d"@B~h.Pl39D1Dd#HG:Dz)sc̹ϵ ={tTC]Ę0Bʙ$B":63yq@p"BptUT$|2O->.a2 $9SONԳtZ;)Z;|?(=4Ocxg ;~^7څPuv7.'}x;4@Vj+72(iT'e#"`_U)MO3cVYm)j08۱VrwGhvm 4]ʼNnyI@'$Lu Ʋw$΅E¢)/C@mX?9j Qr_{PK!L|4xl/workbook.xmlTn0?zXJR?( p/4SJRޕTn}I^%,9=U|cV) >%΅ڧqa4:r&w6ʦtN<*fǺ;6s85{XnKWI/+bB!1oE!8,5o*P1 m)j;U-p3q]R'҆$>t%VnP^_ !ᩗ̪Id֭r ON~[0M=o BzO+ ɡ`t4axaV5a/Jl 'lg+IcdJ"df{pޞ. ozH/$~pdl,T) rg2t~ľtv0g]HT@JwbZJIf#g%atprf8"A]7_MQ4 Gh2\׫j݌'ÃVasf{BX'z1T ePK qpY$ Nxl/worksheets/sheet1.xmlPK!>xl/_rels/workbook.xml.rels (RMK0 0wvt/"Uɴ)&!3~*]XK/oyv5+zl;obG s>,8(%"D҆4j0u2jsMY˴S쭂 )fCy I< y!+EfMyk K5=|t G)s墙UtB),fPK!bh^[Content_Types].xml (N0EHC-Jܲ@5*Q>ēƪc[iiBj7{2hnmƻR U^7/%rZY@1__fqR4DAJh>Vƹ Z9NV8ʩji){^-I"{v^P!XS)bRrKs(3`c07M4ZƐk+|\|z(P6h_-[@!Pk2n}?L %ddN"m,ǞDO97*~ɸ8Oc|nEB!$};{[2PK!U0#L _rels/.rels (MO0 HݐBKwAH!T~I$ݿ'TG~)xl/_rels/workbook.xml.relsPK-!bh^\[Content_Types].xmlPK-!U0#L _rels/.relsPK ooxml/tests/xlsx-bigpart.test000644 000765 000024 00000002340 15221664315 017003 0ustar00alexstaff000000 000000 # # Commands covered: xl_read (built-in zip reader) # # Regression test for ticket a308a654f0: the built-in zip reader passed # the uncompressed size of a zip member as buffer size hint to # [zlib inflate], which only accepts 16 to 65536 - reading any file # with an XML part larger than 64 KB failed. # # # (c) 2026 Alexander Schoepe # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # if {[lsearch [namespace children] ::tcltest] == -1} { package require tcltest 2 namespace import -force ::tcltest::* loadTestedCommands } package require ooxml test BigPart-1.1 {read a workbook whose sheet XML exceeds 64 KB} { set spreadsheet [::ooxml::xl_write new] set sheet [$spreadsheet worksheet Big] for {set row 0} {$row < 2000} {incr row} { $spreadsheet row $sheet $spreadsheet cell $sheet "row $row [string repeat x 40]" -string $spreadsheet cell $sheet $row } $spreadsheet write bigpart.xlsx $spreadsheet destroy array set wb [::ooxml::xl_read bigpart.xlsx] set result [list $wb(0,max_row) $wb(0,v,1999,1)] array unset wb set result } {1999 1999} file delete -force bigpart.xlsx # cleanup ::tcltest::cleanupTests return ooxml/tests/ecma376/shared-commonSimpleTypes.rnc000664 000765 000024 00000005365 15213015413 022264 0ustar00alexstaff000000 000000 namespace o = "urn:schemas-microsoft-com:office:office" namespace s = "http://schemas.openxmlformats.org/officeDocument/2006/sharedTypes" namespace v = "urn:schemas-microsoft-com:vml" namespace w10 = "urn:schemas-microsoft-com:office:word" namespace x = "urn:schemas-microsoft-com:office:excel" s_ST_Lang = xsd:string s_ST_HexColorRGB = xsd:hexBinary { length = "3" } s_ST_Panose = xsd:hexBinary { length = "10" } s_ST_CalendarType = string "gregorian" | string "gregorianUs" | string "gregorianMeFrench" | string "gregorianArabic" | string "hijri" | string "hebrew" | string "taiwan" | string "japan" | string "thai" | string "korea" | string "saka" | string "gregorianXlitEnglish" | string "gregorianXlitFrench" | string "none" s_ST_AlgClass = string "hash" | string "custom" s_ST_CryptProv = string "rsaAES" | string "rsaFull" | string "custom" s_ST_AlgType = string "typeAny" | string "custom" s_ST_ColorType = xsd:string s_ST_Guid = xsd:token { pattern = "\{[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}\}" } s_ST_OnOff = xsd:boolean | s_ST_OnOff1 s_ST_OnOff1 = string "on" | string "off" s_ST_String = xsd:string s_ST_XmlName = xsd:NCName { minLength = "1" maxLength = "255" } s_ST_TrueFalse = string "t" | string "f" | string "true" | string "false" s_ST_TrueFalseBlank = string "t" | string "f" | string "true" | string "false" | string "" | string "True" | string "False" s_ST_UnsignedDecimalNumber = xsd:unsignedLong s_ST_TwipsMeasure = s_ST_UnsignedDecimalNumber | s_ST_PositiveUniversalMeasure s_ST_VerticalAlignRun = string "baseline" | string "superscript" | string "subscript" s_ST_Xstring = xsd:string s_ST_XAlign = string "left" | string "center" | string "right" | string "inside" | string "outside" s_ST_YAlign = string "inline" | string "top" | string "center" | string "bottom" | string "inside" | string "outside" s_ST_ConformanceClass = string "strict" | string "transitional" s_ST_UniversalMeasure = xsd:string { pattern = "-?[0-9]+(\.[0-9]+)?(mm|cm|in|pt|pc|pi)" } s_ST_PositiveUniversalMeasure = xsd:string { pattern = "-?[0-9]+(\.[0-9]+)?(mm|cm|in|pt|pc|pi)" pattern = "[0-9]+(\.[0-9]+)?(mm|cm|in|pt|pc|pi)" } s_ST_Percentage = xsd:string { pattern = "-?[0-9]+(\.[0-9]+)?%" } s_ST_FixedPercentage = xsd:string { pattern = "-?[0-9]+(\.[0-9]+)?%" pattern = "-?((100)|([0-9][0-9]?))(\.[0-9][0-9]?)?%" } s_ST_PositivePercentage = xsd:string { pattern = "-?[0-9]+(\.[0-9]+)?%" pattern = "[0-9]+(\.[0-9]+)?%" } s_ST_PositiveFixedPercentage = xsd:string { pattern = "-?[0-9]+(\.[0-9]+)?%" pattern = "((100)|([0-9][0-9]?))(\.[0-9][0-9]?)?%" } ooxml/tests/ecma376/validate.tcl000664 000765 000024 00000074232 15213015413 017121 0ustar00alexstaff000000 000000 # ecma376/validate.tcl -- # # Structural validator for OOXML .docx packages. # Encodes key constraints from: # - ECMA-376 5th Edition Part 1 (WML) # - ECMA-376 5th Edition Part 2 (OPC) # - ISO/IEC 29500-1:2016 and 29500-2:2021 # # Usage: # source ecma376/validate.tcl # set errors [ecma376::validate::docx /path/to/file.docx] # # Returns list of error strings; empty list = valid # # Requires: tdom 0.9.6+, Tcl 8.6.7+ package require tdom namespace eval ecma376::validate { # ── Namespace URIs (ECMA-376 §22.1, §11.3) ────────────────── variable ns array set ns { w http://schemas.openxmlformats.org/wordprocessingml/2006/main r http://schemas.openxmlformats.org/officeDocument/2006/relationships rel http://schemas.openxmlformats.org/package/2006/relationships ct http://schemas.openxmlformats.org/package/2006/content-types m http://schemas.openxmlformats.org/officeDocument/2006/math wp http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing a http://schemas.openxmlformats.org/drawingml/2006/main mc http://schemas.openxmlformats.org/markup-compatibility/2006 dc http://purl.org/dc/elements/1.1/ cp http://schemas.openxmlformats.org/package/2006/metadata/core-properties } # ── OPC required relationship types (§9.3, §11.3) ─────────── variable relTypes array set relTypes { officeDocument http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument styles http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles settings http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings fontTable http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable footnotes http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes endnotes http://schemas.openxmlformats.org/officeDocument/2006/relationships/endnotes comments http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments header http://schemas.openxmlformats.org/officeDocument/2006/relationships/header footer http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer numbering http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering image http://schemas.openxmlformats.org/officeDocument/2006/relationships/image hyperlink http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink coreProperties http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties } # ── Content types (§13.2, §11.3.6) ────────────────────────── variable contentTypes array set contentTypes { word/document.xml application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml word/styles.xml application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml word/settings.xml application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml word/fontTable.xml application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml word/footnotes.xml application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml word/endnotes.xml application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml word/comments.xml application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml word/numbering.xml application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml docProps/core.xml application/vnd.openxmlformats-package.core-properties+xml docProps/app.xml application/vnd.openxmlformats-officedocument.extended-properties+xml } # ── WML block-level elements (§17.2.2 CT_Body) ────────────── # These are the only elements allowed as direct children of w:body # (besides w:sectPr which must be last). variable bodyChildren { p tbl sdt customXml altChunk bookmarkStart bookmarkEnd commentRangeStart commentRangeEnd moveFromRangeStart moveFromRangeEnd moveToRangeStart moveToRangeEnd permStart permEnd proofErr ins del moveFrom moveTo } # ── WML sectPr child ordering (§17.6.17 CT_SectPr) ───────── # Per ECMA-376, children of w:sectPr must appear in this order. variable sectPrOrder { headerReference footerReference endnotePr footnotePr type pgSz pgMar paperSrc pgBorders lnNumType pgNumType cols formProt vAlign noEndnote titlePg textDirection bidi rtlGutter docGrid printerSettings sectPrChange } } # ── Main validation entry point ───────────────────────────────── proc ecma376::validate::docx {zipfile} { set errors [list] set parts [dict create] set ct "" set packageRels "" set docRels "" # ── Phase 1: Read zip contents ────────────────────────────── set zipEntries [list] if {![catch {set data [exec unzip -Z1 $zipfile]}]} { foreach e [split $data \n] { set e [string trim $e] if {$e ne ""} { lappend zipEntries $e } } } else { lappend errors "FATAL: cannot list zip contents" return $errors } foreach entry $zipEntries { dict set parts $entry 1 } # ── Phase 2: OPC — required parts (§9.1, §9.3) ───────────── foreach req { {[Content_Types].xml} _rels/.rels word/document.xml word/_rels/document.xml.rels } { if {![dict exists $parts $req]} { lappend errors "OPC: required part missing: $req" } } # Read XML parts for further checks if {[catch { regsub -all {\[} {[Content_Types].xml} {\\[} esc regsub -all {\]} $esc {\\]} esc set ct [exec unzip -p $zipfile $esc] }]} { lappend errors "OPC: cannot read [Content_Types].xml" } if {[catch {set packageRels [exec unzip -p $zipfile _rels/.rels]}]} { lappend errors "OPC: cannot read _rels/.rels" } if {[catch {set docRels [exec unzip -p $zipfile word/_rels/document.xml.rels]}]} { lappend errors "OPC: cannot read word/_rels/document.xml.rels" } if {[catch {set docXml [exec unzip -p $zipfile word/document.xml]}]} { lappend errors "OPC: cannot read word/document.xml" return $errors } # ── Phase 3: OPC — Content Types validation (§10.1.2) ─────── if {$ct ne ""} { lappend errors {*}[validateContentTypes $ct $parts] } # ── Phase 4: OPC — Relationships validation (§9.3) ────────── if {$packageRels ne ""} { lappend errors {*}[validatePackageRels $packageRels] } if {$docRels ne ""} { lappend errors {*}[validateDocRels $docRels $parts $zipfile] } # ── Phase 5: WML — Document structure (§17.2.2) ───────────── lappend errors {*}[validateDocument $docXml] # ── Phase 6: WML — Optional parts ──────────────────────────── foreach notePart {word/footnotes.xml word/endnotes.xml} { if {[dict exists $parts $notePart]} { if {[catch {set xml [exec unzip -p $zipfile $notePart]}]} { lappend errors "WML: cannot read $notePart" } else { lappend errors {*}[validateNotes $xml $notePart] } } } if {[dict exists $parts word/styles.xml]} { if {![catch {set xml [exec unzip -p $zipfile word/styles.xml]}]} { lappend errors {*}[validateStyles $xml] } } if {[dict exists $parts word/settings.xml]} { if {![catch {set xml [exec unzip -p $zipfile word/settings.xml]}]} { lappend errors {*}[validateSettings $xml] } } # ── Phase 7: Schema — Element child ordering (§17.3, §17.6) ── lappend errors {*}[validateElementOrdering $docXml] # ── Phase 8: Schema — Attribute enum values ────────────────── lappend errors {*}[validateAttributeEnums $docXml] foreach optPart {word/styles.xml word/settings.xml word/footnotes.xml word/endnotes.xml} { if {[dict exists $parts $optPart]} { if {![catch {set xml [exec unzip -p $zipfile $optPart]}]} { lappend errors {*}[validateAttributeEnums $xml $optPart] } } } return $errors } # ── Content Types validation ──────────────────────────────────── proc ecma376::validate::validateContentTypes {xml parts} { variable ns variable contentTypes set errors [list] if {[catch {set doc [dom parse $xml]} err]} { lappend errors "CT: malformed XML: $err" return $errors } set root [$doc documentElement] $doc selectNodesNamespaces [list ct $ns(ct)] # Root element must be ct:Types if {[$root localName] ne "Types"} { lappend errors "CT: root element must be Types, got [$root localName]" } # Every XML part should have an Override or matching Default set overrides [dict create] foreach node [$root selectNodes ct:Override] { dict set overrides [$node @PartName ""] [$node @ContentType ""] } set defaults [dict create] foreach node [$root selectNodes ct:Default] { dict set defaults [$node @Extension ""] [$node @ContentType ""] } # Check known parts have correct content types foreach {part expectedCT} [array get contentTypes] { if {![dict exists $parts $part]} continue set partName "/$part" if {[dict exists $overrides $partName]} { set actualCT [dict get $overrides $partName] if {$actualCT ne $expectedCT} { lappend errors "CT: $part has content type '$actualCT', expected '$expectedCT'" } } else { # Check extension default set ext [string range [file extension $part] 1 end] if {![dict exists $defaults $ext]} { lappend errors "CT: $part has no Override and no Default for .$ext" } } } # Check for duplicate PartName values (OPC §10.1.2.4) set seen [dict create] foreach node [$root selectNodes ct:Override] { set pn [$node @PartName ""] if {[dict exists $seen $pn]} { lappend errors "CT: duplicate Override for $pn" } dict set seen $pn 1 } $doc delete return $errors } # ── Package-level relationships (.rels) ───────────────────────── proc ecma376::validate::validatePackageRels {xml} { variable ns variable relTypes set errors [list] if {[catch {set doc [dom parse $xml]} err]} { lappend errors "PKG-RELS: malformed XML: $err" return $errors } set root [$doc documentElement] $doc selectNodesNamespaces [list r $ns(rel)] # Must have officeDocument relationship (§9.3.2) set officeDocRels [$root selectNodes { r:Relationship[contains(@Type,'officeDocument')] }] if {![llength $officeDocRels]} { lappend errors "PKG-RELS: missing officeDocument relationship" } # Must have core-properties with package/ relationship type (§9.3.4) set cpRels [$root selectNodes { r:Relationship[contains(@Type,'core-properties')] }] if {[llength $cpRels]} { set cpType [[lindex $cpRels 0] @Type ""] if {![string match *package/2006/relationships* $cpType]} { lappend errors "PKG-RELS: core-properties uses wrong relationship type prefix: $cpType" } } # Every Relationship must have Id and Type attributes (§9.3.1) foreach rel [$root selectNodes r:Relationship] { if {[$rel @Id ""] eq ""} { lappend errors "PKG-RELS: Relationship missing Id attribute" } if {[$rel @Type ""] eq ""} { lappend errors "PKG-RELS: Relationship missing Type attribute" } if {[$rel @Target ""] eq ""} { lappend errors "PKG-RELS: Relationship missing Target attribute" } } # Check for duplicate Id values set ids [dict create] foreach rel [$root selectNodes r:Relationship] { set id [$rel @Id ""] if {$id ne "" && [dict exists $ids $id]} { lappend errors "PKG-RELS: duplicate Relationship Id '$id'" } dict set ids $id 1 } $doc delete return $errors } # ── Document-level relationships ──────────────────────────────── proc ecma376::validate::validateDocRels {xml parts zipfile} { variable ns set errors [list] if {[catch {set doc [dom parse $xml]} err]} { lappend errors "DOC-RELS: malformed XML: $err" return $errors } set root [$doc documentElement] $doc selectNodesNamespaces [list r $ns(rel)] # Every Id must be unique set ids [dict create] foreach rel [$root selectNodes r:Relationship] { set id [$rel @Id ""] if {$id ne "" && [dict exists $ids $id]} { lappend errors "DOC-RELS: duplicate Relationship Id '$id'" } dict set ids $id 1 } # Every internal Target must resolve to an existing part foreach rel [$root selectNodes r:Relationship] { set mode [$rel @TargetMode ""] if {$mode eq "External"} continue set target [$rel @Target ""] if {$target eq ""} continue # Resolve relative to word/ set resolved "word/$target" if {![dict exists $parts $resolved]} { lappend errors "DOC-RELS: dangling target '$target' (resolved to $resolved)" } } # Every r:id referenced in document.xml must exist in rels if {![catch {set docXml [exec unzip -p $zipfile word/document.xml]}]} { if {![catch {set ddoc [dom parse $docXml]}]} { $ddoc selectNodesNamespaces [list \ w $ns(w) r $ns(r) wp $ns(wp)] set refIds [list] foreach attr {r:id r:embed} { foreach node [$ddoc selectNodes "//*\[@$attr\]"] { lappend refIds [$node getAttribute $attr ""] } } foreach rid $refIds { if {$rid ne "" && ![dict exists $ids $rid]} { lappend errors "DOC-RELS: document.xml references r:id '$rid' not in .rels" } } $ddoc delete } } $doc delete return $errors } # ── WML Document structure (§17.2.2 CT_Body) ─────────────────── proc ecma376::validate::validateDocument {xml} { variable ns variable bodyChildren set errors [list] if {[catch {set doc [dom parse $xml]} err]} { lappend errors "WML-DOC: malformed XML: $err" return $errors } set root [$doc documentElement] $doc selectNodesNamespaces [list w $ns(w) m $ns(m) mc $ns(mc)] # Root element must be w:document (§17.2.3) if {[$root localName] ne "document"} { lappend errors "WML-DOC: root must be w:document, got [$root localName]" } set rootNS [$root namespaceURI] if {$rootNS ne $ns(w)} { lappend errors "WML-DOC: root namespace must be $ns(w), got $rootNS" } # w:body must be sole child element of w:document (§17.2.2) set bodies [$root selectNodes w:body] if {[llength $bodies] != 1} { lappend errors "WML-DOC: w:document must contain exactly one w:body, found [llength $bodies]" $doc delete return $errors } set body [lindex $bodies 0] # w:sectPr must be last child of w:body if present (§17.6.17) set lastChild [$body lastChild] if {$lastChild ne ""} { set children [$body childNodes] set foundSectPr 0 set sectPrIdx -1 set idx 0 foreach child $children { if {[$child nodeType] eq "ELEMENT_NODE" && [$child localName] eq "sectPr"} { set foundSectPr 1 set sectPrIdx $idx } incr idx } if {$foundSectPr} { set lastElemIdx [expr {$idx - 1}] # Walk back to find last element for {set i [expr {[llength $children] - 1}]} {$i >= 0} {incr i -1} { if {[[lindex $children $i] nodeType] eq "ELEMENT_NODE"} { set lastElemIdx $i break } } if {$sectPrIdx != $lastElemIdx} { lappend errors "WML-DOC: w:sectPr must be last element child of w:body (found at position $sectPrIdx, last element at $lastElemIdx)" } } } # Body children must be block-level elements (§17.2.2) foreach child [$body childNodes] { if {[$child nodeType] ne "ELEMENT_NODE"} continue set ln [$child localName] if {$ln eq "sectPr"} continue if {$ln ni $bodyChildren} { lappend errors "WML-DOC: illegal w:body child element w:$ln" } } # Every w:p must have at most one w:pPr as first child (§17.3.1.26) foreach p [$root selectNodes {//w:p}] { set pprCount 0 foreach child [$p childNodes] { if {[$child nodeType] ne "ELEMENT_NODE"} continue if {[$child localName] eq "pPr"} { incr pprCount if {$pprCount > 1} { lappend errors "WML-DOC: w:p has multiple w:pPr children" } } } } # Every w:r must have at most one w:rPr as first child (§17.3.2.28) foreach r [$root selectNodes {//w:r}] { set rprCount 0 foreach child [$r childNodes] { if {[$child nodeType] ne "ELEMENT_NODE"} continue if {[$child localName] eq "rPr"} { incr rprCount if {$rprCount > 1} { lappend errors "WML-DOC: w:r has multiple w:rPr children" } } } } $doc delete return $errors } # ── Footnotes / Endnotes (§17.11.15, §17.11.2) ──────────────── proc ecma376::validate::validateNotes {xml partName} { variable ns set errors [list] if {[catch {set doc [dom parse $xml]} err]} { lappend errors "WML-NOTES($partName): malformed XML: $err" return $errors } set root [$doc documentElement] $doc selectNodesNamespaces [list w $ns(w)] set rootLN [$root localName] set isFootnotes [expr {$rootLN eq "footnotes"}] set isEndnotes [expr {$rootLN eq "endnotes"}] set noteTag [expr {$isFootnotes ? "footnote" : "endnote"}] if {!$isFootnotes && !$isEndnotes} { lappend errors "WML-NOTES($partName): root must be w:footnotes or w:endnotes, got w:$rootLN" $doc delete return $errors } # Must have separator (id=0) and continuationSeparator (id=1) # per §17.11.3 and §17.11.6 set hasSep 0 set hasCont 0 foreach note [$root selectNodes w:$noteTag] { set ntype [$note @w:type ""] set nid [$note @w:id ""] if {$ntype eq "separator" && $nid eq "0"} { set hasSep 1 } if {$ntype eq "continuationSeparator" && $nid eq "1"} { set hasCont 1 } } if {!$hasSep} { lappend errors "WML-NOTES($partName): missing separator $noteTag (w:type='separator' w:id='0')" } if {!$hasCont} { lappend errors "WML-NOTES($partName): missing continuationSeparator $noteTag (w:type='continuationSeparator' w:id='1')" } # Every note must have a w:id attribute (§17.11.15) foreach note [$root selectNodes w:$noteTag] { if {[$note @w:id ""] eq ""} { lappend errors "WML-NOTES($partName): w:$noteTag missing required w:id attribute" } } # Note ids must be unique (§17.11.15) set ids [dict create] foreach note [$root selectNodes w:$noteTag] { set nid [$note @w:id ""] if {$nid ne ""} { if {[dict exists $ids $nid]} { lappend errors "WML-NOTES($partName): duplicate w:$noteTag w:id='$nid'" } dict set ids $nid 1 } } # User notes (id >= 2) must contain at least one w:p (§17.11.15) foreach note [$root selectNodes w:$noteTag] { set nid [$note @w:id ""] if {$nid ne "" && $nid > 1} { set pcount [llength [$note selectNodes w:p]] if {$pcount == 0} { lappend errors "WML-NOTES($partName): user $noteTag id=$nid has no w:p child" } } } $doc delete return $errors } # ── Styles (§17.7.4) ─────────────────────────────────────────── proc ecma376::validate::validateStyles {xml} { variable ns set errors [list] if {[catch {set doc [dom parse $xml]} err]} { lappend errors "WML-STYLES: malformed XML: $err" return $errors } set root [$doc documentElement] $doc selectNodesNamespaces [list w $ns(w)] if {[$root localName] ne "styles"} { lappend errors "WML-STYLES: root must be w:styles, got [$root localName]" } # Every w:style must have w:type and w:styleId (§17.7.4.17) foreach style [$root selectNodes w:style] { set stype [$style @w:type ""] set sid [$style @w:styleId ""] if {$stype eq ""} { lappend errors "WML-STYLES: w:style missing w:type attribute" } if {$sid eq ""} { lappend errors "WML-STYLES: w:style missing w:styleId attribute" } if {$stype ni {paragraph character numbering table}} { if {$stype ne ""} { lappend errors "WML-STYLES: w:style has invalid w:type='$stype'" } } } # styleId values must be unique within a type (§17.7.4.17) set typeIds [dict create] foreach style [$root selectNodes w:style] { set stype [$style @w:type ""] set sid [$style @w:styleId ""] if {$stype eq "" || $sid eq ""} continue set key "${stype}:${sid}" if {[dict exists $typeIds $key]} { lappend errors "WML-STYLES: duplicate styleId '$sid' for type '$stype'" } dict set typeIds $key 1 } # basedOn must reference an existing styleId of the same type (§17.7.4.3) foreach style [$root selectNodes w:style] { set stype [$style @w:type ""] set basedOn [$style selectNodes {string(w:basedOn/@w:val)}] if {$basedOn ne ""} { set key "${stype}:${basedOn}" if {![dict exists $typeIds $key]} { set sid [$style @w:styleId ""] lappend errors "WML-STYLES: style '$sid' basedOn '$basedOn' does not exist as $stype style" } } } $doc delete return $errors } # ── Settings (§17.15.1) ──────────────────────────────────────── proc ecma376::validate::validateSettings {xml} { variable ns set errors [list] if {[catch {set doc [dom parse $xml]} err]} { lappend errors "WML-SETTINGS: malformed XML: $err" return $errors } set root [$doc documentElement] $doc selectNodesNamespaces [list w $ns(w)] if {[$root localName] ne "settings"} { lappend errors "WML-SETTINGS: root must be w:settings, got [$root localName]" } $doc delete return $errors } # ── Schema data loading ───────────────────────────────────────── # Load the machine-generated schema data (enums, child orderings, # attribute→enum mappings) extracted from the ECMA-376 RNC schemas. source [file join [file dirname [info script]] schema-data.tcl] # ── Element child ordering validation (§17.3, §17.6, §17.15) ─── # # ECMA-376 defines xsd:sequence for pPr, rPr, tblPr, and settings # children. Elements appearing out of order produce a schema- # invalid document even though Word may tolerate it. proc ecma376::validate::validateElementOrdering {xml {partName word/document.xml}} { variable ns set errors [list] if {[catch {set doc [dom parse $xml]} err]} { return $errors } $doc selectNodesNamespaces [list w $ns(w) m $ns(m)] # Check ordering for each container type foreach {containerTag orderKey} { pPr pPr rPr rPr tblPr tblPr } { if {![info exists ::ecma376::schema::childOrder($orderKey)]} continue set expected $::ecma376::schema::childOrder($orderKey) foreach container [$doc selectNodes "//w:$containerTag"] { set children [list] foreach child [$container childNodes] { if {[$child nodeType] ne "ELEMENT_NODE"} continue lappend children [$child localName] } # Check that children appear in schema order # (not all need to be present, but those present must be ordered) set lastIdx -1 foreach childName $children { set idx [lsearch -exact $expected $childName] if {$idx == -1} continue ;# unknown child, skip (may be extension) if {$idx < $lastIdx} { lappend errors "SCHEMA-ORDER($partName): w:$containerTag child w:$childName appears out of ECMA-376 sequence order (after w:[lindex $expected $lastIdx])" break } set lastIdx $idx } } } $doc delete return $errors } # ── Attribute enum validation ─────────────────────────────────── # # For every w:val attribute (and other enum-typed attributes) in # the output XML, verify the value is in the ECMA-376 enumeration. proc ecma376::validate::validateAttributeEnums {xml {partName word/document.xml}} { variable ns set errors [list] if {[catch {set doc [dom parse $xml]} err]} { return $errors } $doc selectNodesNamespaces [list w $ns(w) m $ns(m)] # Map of element localName → attribute localName → enum type # Built from the schema: when element X has attribute w:Y typed as ST_Z, # we validate the value against the enum. # # We focus on the high-value w:val attributes where the element name # tells us which enum to check. variable attrChecks if {![info exists attrChecks]} { array set attrChecks {} # Build element-specific checks from the schema attribute map # Format: elementLocalName:attrLocalName → enumTypeName foreach {attr enumType} [array get ::ecma376::schema::attrEnum] { # These attributes are used on many elements with different types # Only check w:val which is the most common pattern set attrChecks($attr) $enumType } } # Check w:val on elements where the parent context determines the type set elemToEnum { jc w_ST_Jc u w_ST_Underline highlight w_ST_HighlightColor vertAlign w_ST_VerticalAlignRun shd w_ST_Shd pStyle {} rStyle {} tblStyle {} } # Direct element → w:val enum checks foreach {elem enumName} $elemToEnum { if {$enumName eq ""} continue if {![info exists ::ecma376::schema::enums($enumName)]} continue set allowed $::ecma376::schema::enums($enumName) foreach node [$doc selectNodes "//w:$elem"] { set val [$node @w:val ""] if {$val eq ""} continue if {$val ni $allowed} { lappend errors "SCHEMA-ENUM($partName): w:$elem/@w:val='$val' is not a valid $enumName value" } } } # Check shading w:val (on w:shd elements) if {[info exists ::ecma376::schema::enums(w_ST_Shd)]} { set allowed $::ecma376::schema::enums(w_ST_Shd) foreach node [$doc selectNodes {//w:shd}] { set val [$node @w:val ""] if {$val ne "" && $val ni $allowed} { lappend errors "SCHEMA-ENUM($partName): w:shd/@w:val='$val' is not a valid w_ST_Shd value" } } } # Check border w:val (on border elements) if {[info exists ::ecma376::schema::enums(w_ST_Border)]} { set allowed $::ecma376::schema::enums(w_ST_Border) foreach borderElem {top bottom left right insideH insideV start end tl2br tr2bl between bar} { foreach node [$doc selectNodes "//w:$borderElem"] { set val [$node @w:val ""] if {$val ne "" && $val ni $allowed} { lappend errors "SCHEMA-ENUM($partName): w:$borderElem/@w:val='$val' is not a valid w_ST_Border value" } } } } # Check w:type on sectPr (section mark) if {[info exists ::ecma376::schema::enums(w_ST_SectionMark)]} { set allowed $::ecma376::schema::enums(w_ST_SectionMark) foreach node [$doc selectNodes {//w:type}] { set parent [$node parentNode] if {[$parent localName] ne "sectPr"} continue set val [$node @w:val ""] if {$val ne "" && $val ni $allowed} { lappend errors "SCHEMA-ENUM($partName): w:type/@w:val='$val' is not a valid w_ST_SectionMark value" } } } # Check w:orient on pgSz (page orientation) if {[info exists ::ecma376::schema::enums(w_ST_PageOrientation)]} { set allowed $::ecma376::schema::enums(w_ST_PageOrientation) foreach node [$doc selectNodes {//w:pgSz}] { set val [$node @w:orient ""] if {$val ne "" && $val ni $allowed} { lappend errors "SCHEMA-ENUM($partName): w:pgSz/@w:orient='$val' is not a valid w_ST_PageOrientation value" } } } $doc delete return $errors } ooxml/tests/ecma376/RULES.txt000664 000765 000024 00000012273 15213015413 016254 0ustar00alexstaff000000 000000 # ECMA-376 5th Edition / ISO 29500 — Validation Rules Reference # # This file documents the specific ECMA-376 constraints that # ecma376/validate.tcl checks. Each rule cites the normative # spec section. # # ══════════════════════════════════════════════════════════════ # OPC — Open Packaging Convention (Part 2) # ══════════════════════════════════════════════════════════════ # # §8.1.1 Every package SHALL contain [Content_Types].xml # §8.1.3 The content type of each part SHALL be specified # via either a Default or Override entry # §9.1 Every package MAY contain package-level relationships # stored in _rels/.rels # §9.3.1 Each Relationship element SHALL have Id, Type, Target # §9.3.2 Relationship Ids SHALL be unique within a .rels file # §9.3.4 Internal targets SHALL resolve to existing parts # §10.1.2.3 Override/@PartName SHALL be unique # §10.1.2.4 Default/@Extension SHALL be unique # §M.4.1 Part names SHALL NOT contain: whitespace, reserved # URI characters outside percent-encoding # # ══════════════════════════════════════════════════════════════ # WML — WordprocessingML (Part 1) # ══════════════════════════════════════════════════════════════ # # §17.2.2 CT_Body: w:body contains block-level elements # followed by optional w:sectPr as last child # §17.2.3 CT_Document: w:document root element with exactly # one w:body child # §17.3.1.26 CT_P: w:p may contain at most one w:pPr (first child) # §17.3.2.28 CT_R: w:r may contain at most one w:rPr (first child) # §17.6.17 CT_SectPr: section properties, ordering of children # §17.7.4.3 CT_Style.basedOn: must reference an existing styleId # of the same type # §17.7.4.17 CT_Style: required attributes w:type, w:styleId; # w:type values: paragraph, character, numbering, table; # styleId unique within type # §17.11.3 w:footnote[@w:type='separator'] id=0 required # §17.11.6 w:footnote[@w:type='continuationSeparator'] id=1 required # §17.11.15 CT_FtnEdn: w:id required; user notes must contain w:p # # ══════════════════════════════════════════════════════════════ # Content Types (Part 1 §11.3.6, Part 2 §10.1.2) # ══════════════════════════════════════════════════════════════ # # Each known part type has a defined content type string. # The validator checks Override entries against the normative # content type values from ECMA-376 Part 1 §11.3.6. # # ══════════════════════════════════════════════════════════════ # Relationship Types (Part 1 §11.3, Part 2 §9.3) # ══════════════════════════════════════════════════════════════ # # Each relationship type has a normative URI. # core-properties uses the package/ form (not officeDocument/). # officeDocument relationship is required in _rels/.rels. # Internal targets must resolve to existing zip entries. # External targets must have TargetMode="External". # ══════════════════════════════════════════════════════════════ # Schema-derived checks (from wml.rnc + shared-commonSimpleTypes.rnc) # ══════════════════════════════════════════════════════════════ # # Element child ordering (Phase 7): # - w:pPr children must follow CT_PPrBase sequence (§17.3.1.26) # - w:rPr children must follow EG_RPrBase sequence (§17.3.2.28) # - w:tblPr children must follow CT_TblPrBase sequence (§17.4.59) # # 95 enumeration types extracted from RNC schemas. # 62 attribute→enum mappings for output validation. # # Attribute enum validation (Phase 8): # - w:jc/@w:val checked against ST_Jc (12 values) # - w:u/@w:val checked against ST_Underline (18 values) # - w:highlight/@w:val checked against ST_HighlightColor (17 values) # - w:vertAlign/@w:val checked against ST_VerticalAlignRun (3 values) # - w:shd/@w:val checked against ST_Shd (38 values) # - Border elements/@w:val checked against ST_Border (193 values) # - w:type/@w:val in sectPr checked against ST_SectionMark (5 values) # - w:pgSz/@w:orient checked against ST_PageOrientation (2 values) ooxml/tests/ecma376/schema-data.tcl000664 000765 000024 00000036462 15213015413 017502 0ustar00alexstaff000000 000000 # ecma376/schema-data.tcl -- # # Machine-generated from ECMA-376 5th Edition RNC schemas: # wml.rnc (WordprocessingML) # shared-commonSimpleTypes.rnc (shared simple types) # # DO NOT EDIT — regenerate from RNC sources. namespace eval ecma376::schema { # ── Enumeration types ({name} → {allowed values}) ──────── variable enums array set enums { s_ST_AlgClass {hash custom} s_ST_AlgType {typeAny custom} s_ST_CalendarType {gregorian gregorianUs gregorianMeFrench gregorianArabic hijri hebrew taiwan japan thai korea saka gregorianXlitEnglish gregorianXlitFrench none} s_ST_ConformanceClass {strict transitional} s_ST_CryptProv {rsaAES rsaFull custom} s_ST_OnOff1 {on off} s_ST_TrueFalse {t f true false} s_ST_TrueFalseBlank {t f true false True False} s_ST_VerticalAlignRun {baseline superscript subscript} s_ST_XAlign {left center right inside outside} s_ST_YAlign {inline top center bottom inside outside} w_ST_AnnotationVMerge {cont rest} w_ST_Border {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 apples archedScallops babyPacifier babyRattle balloons3Colors balloonsHotAir basicBlackDashes basicBlackDots basicBlackSquares basicThinLines basicWhiteDashes basicWhiteDots basicWhiteSquares basicWideInline basicWideMidline basicWideOutline bats birds birdsFlight cabins cakeSlice candyCorn celticKnotwork certificateBanner chainLink champagneBottle checkedBarBlack checkedBarColor checkered christmasTree circlesLines circlesRectangles classicalWave clocks compass confetti confettiGrays confettiOutline confettiStreamers confettiWhite cornerTriangles couponCutoutDashes couponCutoutDots crazyMaze creaturesButterfly creaturesFish creaturesInsects creaturesLadyBug crossStitch cup decoArch decoArchColor decoBlocks diamondsGray doubleD doubleDiamonds earth1 earth2 earth3 eclipsingSquares1 eclipsingSquares2 eggsBlack fans film firecrackers flowersBlockPrint flowersDaisies flowersModern1 flowersModern2 flowersPansy flowersRedRose flowersRoses flowersTeacup flowersTiny gems gingerbreadMan gradient handmade1 handmade2 heartBalloon heartGray hearts heebieJeebies holly houseFunky hypnotic iceCreamCones lightBulb lightning1 lightning2 mapPins mapleLeaf mapleMuffins marquee marqueeToothed moons mosaic musicNotes northwest ovals packages palmsBlack palmsColor paperClips papyrus partyFavor partyGlass pencils people peopleWaving peopleHats poinsettias postageStamp pumpkin1 pushPinNote2 pushPinNote1 pyramids pyramidsAbove quadrants rings safari sawtooth sawtoothGray scaredCat seattle shadowedSquares sharksTeeth shorebirdTracks skyrocket snowflakeFancy snowflakes sombrero southwest stars starsTop stars3d starsBlack starsShadowed sun swirligig tornPaper tornPaperBlack trees triangleParty triangles triangle1 triangle2 triangleCircle1 triangleCircle2 shapes1 shapes2 twistedLines1 twistedLines2 vine waveline weavingAngles weavingBraid weavingRibbon weavingStrips whiteFlowers woodwork xIllusions zanyTriangles zigZag zigZagStitch custom} w_ST_BrClear {none left right all} w_ST_BrType {page column textWrapping} w_ST_CaptionPos {above below left right} w_ST_ChapterSep {hyphen period colon emDash enDash} w_ST_CharacterSpacing {doNotCompress compressPunctuation compressPunctuationAndJapaneseKana} w_ST_CombineBrackets {none round square angle curly} w_ST_Direction {ltr rtl} w_ST_DisplacedByCustomXml {next prev} w_ST_DocGrid {default lines linesAndChars snapToChars} w_ST_DocPartBehavior {content p pg} w_ST_DocPartGallery {placeholder any default docParts coverPg eq ftrs hdrs pgNum tbls watermarks autoTxt txtBox pgNumT pgNumB pgNumMargins tblOfContents bib custQuickParts custCoverPg custEq custFtrs custHdrs custPgNum custTbls custWatermarks custAutoTxt custTxtBox custPgNumT custPgNumB custPgNumMargins custTblOfContents custBib custom1 custom2 custom3 custom4 custom5} w_ST_DocPartType {none normal autoExp toolbar speller formFld bbPlcHdr} w_ST_DocProtect {none readOnly comments trackedChanges forms} w_ST_DropCap {none drop margin} w_ST_EdGrp {none everyone administrators contributors editors owners current} w_ST_EdnPos {sectEnd docEnd} w_ST_Em {none dot comma circle underDot} w_ST_FFTextType {regular number date currentTime currentDate calculated} w_ST_FldCharType {begin separate end} w_ST_FontFamily {decorative modern roman script swiss auto} w_ST_FrameLayout {rows cols none} w_ST_FrameScrollbar {on off auto} w_ST_FtnEdn {normal separator continuationSeparator continuationNotice} w_ST_FtnPos {pageBottom beneathText sectEnd docEnd} w_ST_HAnchor {text margin page} w_ST_HdrFtr {even default first} w_ST_HeightRule {auto exact atLeast} w_ST_HighlightColor {black blue cyan green magenta red yellow white darkBlue darkCyan darkGreen darkMagenta darkRed darkYellow darkGray lightGray none} w_ST_Hint {default eastAsia} w_ST_InfoTextType {text autoText} w_ST_Jc {start center end both mediumKashida distribute numTab highKashida lowKashida thaiDistribute left right} w_ST_JcTable {center end left right start} w_ST_LevelSuffix {tab space nothing} w_ST_LineNumberRestart {newPage newSection continuous} w_ST_LineSpacingRule {auto exact atLeast} w_ST_Lock {sdtLocked contentLocked unlocked sdtContentLocked} w_ST_MailMergeDest {newDocument printer email fax} w_ST_MailMergeDocType {catalog envelopes mailingLabels formLetters email fax} w_ST_MailMergeOdsoFMDFieldType {null dbColumn} w_ST_MailMergeSourceType {database addressBook document1 document2 text email native legacy master} w_ST_Merge {continue restart} w_ST_MultiLevelType {singleLevel multilevel hybridMultilevel} w_ST_NumberFormat {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} w_ST_ObjectDrawAspect {content icon} w_ST_ObjectUpdateMode {always onCall} w_ST_PTabAlignment {left center right} w_ST_PTabLeader {none dot hyphen underscore middleDot} w_ST_PTabRelativeTo {margin indent} w_ST_PageBorderDisplay {allPages firstPage notFirstPage} w_ST_PageBorderOffset {page text} w_ST_PageBorderZOrder {front back} w_ST_PageOrientation {portrait landscape} w_ST_Pitch {fixed variable default} w_ST_Proof {clean dirty} w_ST_ProofErr {spellStart spellEnd gramStart gramEnd} w_ST_RestartNumber {continuous eachSect eachPage} w_ST_RubyAlign {center distributeLetter distributeSpace left right rightVertical} w_ST_SdtDateMappingType {text date dateTime} w_ST_SectionMark {nextPage nextColumn continuous evenPage oddPage} w_ST_Shd {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} w_ST_StyleSort {name priority default font basedOn type 0000 0001 0002 0003 0004 0005} w_ST_StyleType {paragraph character table numbering} w_ST_TabJc {clear start center end decimal bar num left right} w_ST_TabTlc {none dot hyphen underscore heavy middleDot} w_ST_TargetScreenSz {544x376 640x480 720x512 800x600 1024x768 1152x882 1152x900 1280x1024 1600x1200 1800x1440 1920x1200} w_ST_TblLayoutType {fixed autofit} w_ST_TblOverlap {never overlap} w_ST_TblStyleOverrideType {wholeTable firstRow lastRow firstCol lastCol band1Vert band2Vert band1Horz band2Horz neCell nwCell seCell swCell} w_ST_TblWidth {nil pct dxa auto} w_ST_TextAlignment {top center baseline bottom auto} w_ST_TextDirection {tb rl lr tbV rlV lrV btLr lrTb lrTbV tbLrV tbRl tbRlV} w_ST_TextEffect {blinkBackground lights antsBlack antsRed shimmer sparkle none} w_ST_TextboxTightWrap {none allLines firstAndLastLine firstLineOnly lastLineOnly} w_ST_Theme {majorEastAsia majorBidi majorAscii majorHAnsi minorEastAsia minorBidi minorAscii minorHAnsi} w_ST_ThemeColor {dark1 light1 dark2 light2 accent1 accent2 accent3 accent4 accent5 accent6 hyperlink followedHyperlink none background1 text1 background2 text2} w_ST_Underline {single words double thick dotted dottedHeavy dash dashedHeavy dashLong dashLongHeavy dotDash dashDotHeavy dotDotDash dashDotDotHeavy wave wavyHeavy wavyDouble none} w_ST_VAnchor {text margin page} w_ST_VerticalJc {top center both bottom} w_ST_View {none print outline masterPages normal web} w_ST_WmlColorSchemeIndex {dark1 light1 dark2 light2 accent1 accent2 accent3 accent4 accent5 accent6 hyperlink followedHyperlink} w_ST_Wrap {auto notBeside around tight through none} w_ST_Zoom {none fullPage bestFit textFit} } # ── Element child ordering (ECMA-376 sequence constraints) ── variable childOrder array set childOrder { pPr {pStyle keepNext keepLines pageBreakBefore framePr widowControl numPr suppressLineNumbers pBdr shd tabs suppressAutoHyphens kinsoku wordWrap overflowPunct topLinePunct autoSpaceDE autoSpaceDN bidi adjustRightInd snapToGrid spacing ind contextualSpacing mirrorIndents suppressOverlap jc textDirection textAlignment textboxTightWrap outlineLvl divId cnfStyle} rPr {rStyle rFonts b bCs i iCs caps smallCaps strike dstrike outline shadow emboss imprint noProof snapToGrid vanish webHidden color spacing w kern position sz szCs highlight u effect bdr shd fitText vertAlign rtl cs em lang eastAsianLayout specVanish oMath} sectPrContents {footnotePr endnotePr type pgSz pgMar paperSrc pgBorders lnNumType pgNumType cols formProt vAlign noEndnote titlePg textDirection bidi rtlGutter docGrid printerSettings} tblPr {tblStyle tblpPr tblOverlap bidiVisual tblStyleRowBandSize tblStyleColBandSize tblW jc tblCellSpacing tblInd tblBorders shd tblLayout tblCellMar tblLook tblCaption tblDescription} settings {writeProtection view zoom removePersonalInformation removeDateAndTime doNotDisplayPageBoundaries displayBackgroundShape printPostScriptOverText printFractionalCharacterWidth printFormsData embedTrueTypeFonts embedSystemFonts saveSubsetFonts saveFormsData mirrorMargins alignBordersAndEdges bordersDoNotSurroundHeader bordersDoNotSurroundFooter gutterAtTop hideSpellingErrors hideGrammaticalErrors activeWritingStyle proofState formsDesign attachedTemplate linkStyles stylePaneFormatFilter stylePaneSortMethod documentType mailMerge revisionView trackRevisions doNotTrackMoves doNotTrackFormatting documentProtection autoFormatOverride styleLockTheme styleLockQFSet defaultTabStop autoHyphenation consecutiveHyphenLimit hyphenationZone doNotHyphenateCaps showEnvelope summaryLength clickAndTypeStyle defaultTableStyle evenAndOddHeaders bookFoldRevPrinting bookFoldPrinting bookFoldPrintingSheets drawingGridHorizontalSpacing drawingGridVerticalSpacing displayHorizontalDrawingGridEvery displayVerticalDrawingGridEvery doNotUseMarginsForDrawingGridOrigin drawingGridHorizontalOrigin drawingGridVerticalOrigin doNotShadeFormData noPunctuationKerning characterSpacingControl printTwoOnOne strictFirstAndLastChars noLineBreaksAfter noLineBreaksBefore savePreviewPicture doNotValidateAgainstSchema saveInvalidXml ignoreMixedContent alwaysShowPlaceholderText doNotDemarcateInvalidXml saveXmlDataOnly useXSLTWhenSaving saveThroughXslt showXMLTags alwaysMergeEmptyNamespace updateFields hdrShapeDefaults footnotePr endnotePr compat docVars rsids attachedSchema themeFontLang clrSchemeMapping doNotIncludeSubdocsInStats doNotAutoCompressPictures forceUpgrade captions readModeInkLockDown smartTagType shapeDefaults doNotEmbedSmartTags decimalSymbol listSeparator} } # ── Attribute → enum type mapping ────────────────────────── # Maps w:attrName → enum type name for attributes that # take enumerated values. variable attrEnum array set attrEnum { accent1 w_ST_WmlColorSchemeIndex accent2 w_ST_WmlColorSchemeIndex accent3 w_ST_WmlColorSchemeIndex accent4 w_ST_WmlColorSchemeIndex accent5 w_ST_WmlColorSchemeIndex accent6 w_ST_WmlColorSchemeIndex alignment w_ST_PTabAlignment asciiTheme w_ST_Theme bg1 w_ST_WmlColorSchemeIndex bg2 w_ST_WmlColorSchemeIndex chapSep w_ST_ChapterSep clear w_ST_BrClear combineBrackets w_ST_CombineBrackets conformance s_ST_ConformanceClass cryptAlgorithmClass s_ST_AlgClass cryptAlgorithmType s_ST_AlgType cryptProviderType s_ST_CryptProv cstheme w_ST_Theme displacedByCustomXml w_ST_DisplacedByCustomXml display w_ST_PageBorderDisplay drawAspect w_ST_ObjectDrawAspect dropCap w_ST_DropCap eastAsiaTheme w_ST_Theme edGrp w_ST_EdGrp edit w_ST_DocProtect fldCharType w_ST_FldCharType fmt w_ST_NumberFormat followedHyperlink w_ST_WmlColorSchemeIndex grammar w_ST_Proof hAnchor w_ST_HAnchor hAnsiTheme w_ST_Theme hRule w_ST_HeightRule hint w_ST_Hint horzAnchor w_ST_HAnchor hyperlink w_ST_WmlColorSchemeIndex leader w_ST_TabTlc lineRule w_ST_LineSpacingRule numFmt w_ST_NumberFormat offsetFrom w_ST_PageBorderOffset orient w_ST_PageOrientation pos w_ST_CaptionPos relativeTo w_ST_PTabRelativeTo restart w_ST_LineNumberRestart sep w_ST_ChapterSep spelling w_ST_Proof t1 w_ST_WmlColorSchemeIndex t2 w_ST_WmlColorSchemeIndex tblpXSpec s_ST_XAlign tblpYSpec s_ST_YAlign themeColor w_ST_ThemeColor themeFill w_ST_ThemeColor type w_ST_TblStyleOverrideType updateMode w_ST_ObjectUpdateMode vAnchor w_ST_VAnchor vMerge w_ST_AnnotationVMerge vMergeOrig w_ST_AnnotationVMerge val w_ST_Border vertAnchor w_ST_VAnchor wrap w_ST_Wrap xAlign s_ST_XAlign yAlign s_ST_YAlign zOrder w_ST_PageBorderZOrder } } ooxml/tests/ecma376/wml.rnc000664 000765 000024 00000241400 15213015413 016120 0ustar00alexstaff000000 000000 namespace m = "http://schemas.openxmlformats.org/officeDocument/2006/math" namespace o = "urn:schemas-microsoft-com:office:office" namespace r = "http://schemas.openxmlformats.org/officeDocument/2006/relationships" namespace s = "http://schemas.openxmlformats.org/officeDocument/2006/sharedTypes" namespace sl = "http://schemas.openxmlformats.org/schemaLibrary/2006/main" namespace v = "urn:schemas-microsoft-com:vml" default namespace w = "http://schemas.openxmlformats.org/wordprocessingml/2006/main" namespace w10 = "urn:schemas-microsoft-com:office:word" namespace wp = "http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" namespace x = "urn:schemas-microsoft-com:office:excel" w_CT_Empty = empty w_CT_OnOff = attribute w:val { s_ST_OnOff }? w_ST_LongHexNumber = xsd:hexBinary { length = "4" } w_CT_LongHexNumber = attribute w:val { w_ST_LongHexNumber } w_ST_ShortHexNumber = xsd:hexBinary { length = "2" } w_ST_UcharHexNumber = xsd:hexBinary { length = "1" } w_CT_Charset = attribute w:val { w_ST_UcharHexNumber }?, attribute w:characterSet { s_ST_String }? ## default value: ISO-8859-1 w_ST_DecimalNumberOrPercent = w_ST_UnqualifiedPercentage | s_ST_Percentage w_ST_UnqualifiedPercentage = xsd:integer w_ST_DecimalNumber = xsd:integer w_CT_DecimalNumber = attribute w:val { w_ST_DecimalNumber } w_CT_UnsignedDecimalNumber = attribute w:val { s_ST_UnsignedDecimalNumber } w_CT_DecimalNumberOrPrecent = attribute w:val { w_ST_DecimalNumberOrPercent } w_CT_TwipsMeasure = attribute w:val { s_ST_TwipsMeasure } w_ST_SignedTwipsMeasure = xsd:integer | s_ST_UniversalMeasure w_CT_SignedTwipsMeasure = attribute w:val { w_ST_SignedTwipsMeasure } w_ST_PixelsMeasure = s_ST_UnsignedDecimalNumber w_CT_PixelsMeasure = attribute w:val { w_ST_PixelsMeasure } w_ST_HpsMeasure = s_ST_UnsignedDecimalNumber | s_ST_PositiveUniversalMeasure w_CT_HpsMeasure = attribute w:val { w_ST_HpsMeasure } w_ST_SignedHpsMeasure = xsd:integer | s_ST_UniversalMeasure w_CT_SignedHpsMeasure = attribute w:val { w_ST_SignedHpsMeasure } w_ST_DateTime = xsd:dateTime w_ST_MacroName = xsd:string { maxLength = "33" } w_CT_MacroName = attribute w:val { w_ST_MacroName } w_ST_EighthPointMeasure = s_ST_UnsignedDecimalNumber w_ST_PointMeasure = s_ST_UnsignedDecimalNumber w_CT_String = attribute w:val { s_ST_String } w_ST_TextScale = w_ST_TextScalePercent | w_ST_TextScaleDecimal w_ST_TextScalePercent = xsd:string { pattern = "0*(600|([0-5]?[0-9]?[0-9]))%" } w_ST_TextScaleDecimal = xsd:integer { minInclusive = "0" maxInclusive = "600" } w_CT_TextScale = attribute w:val { w_ST_TextScale }? w_ST_HighlightColor = string "black" | string "blue" | string "cyan" | string "green" | string "magenta" | string "red" | string "yellow" | string "white" | string "darkBlue" | string "darkCyan" | string "darkGreen" | string "darkMagenta" | string "darkRed" | string "darkYellow" | string "darkGray" | string "lightGray" | string "none" w_CT_Highlight = attribute w:val { w_ST_HighlightColor } w_ST_HexColorAuto = string "auto" w_ST_HexColor = w_ST_HexColorAuto | s_ST_HexColorRGB w_CT_Color = attribute w:val { w_ST_HexColor }, attribute w:themeColor { w_ST_ThemeColor }?, attribute w:themeTint { w_ST_UcharHexNumber }?, attribute w:themeShade { w_ST_UcharHexNumber }? w_CT_Lang = attribute w:val { s_ST_Lang } w_CT_Guid = attribute w:val { s_ST_Guid }? w_ST_Underline = string "single" | string "words" | string "double" | string "thick" | string "dotted" | string "dottedHeavy" | string "dash" | string "dashedHeavy" | string "dashLong" | string "dashLongHeavy" | string "dotDash" | string "dashDotHeavy" | string "dotDotDash" | string "dashDotDotHeavy" | string "wave" | string "wavyHeavy" | string "wavyDouble" | string "none" w_CT_Underline = attribute w:val { w_ST_Underline }?, attribute w:color { w_ST_HexColor }?, ## default value: auto attribute w:themeColor { w_ST_ThemeColor }?, attribute w:themeTint { w_ST_UcharHexNumber }?, attribute w:themeShade { w_ST_UcharHexNumber }? w_ST_TextEffect = string "blinkBackground" | string "lights" | string "antsBlack" | string "antsRed" | string "shimmer" | string "sparkle" | string "none" w_CT_TextEffect = attribute w:val { w_ST_TextEffect } w_ST_Border = string "nil" | string "none" | string "single" | string "thick" | string "double" | string "dotted" | string "dashed" | string "dotDash" | string "dotDotDash" | string "triple" | string "thinThickSmallGap" | string "thickThinSmallGap" | string "thinThickThinSmallGap" | string "thinThickMediumGap" | string "thickThinMediumGap" | string "thinThickThinMediumGap" | string "thinThickLargeGap" | string "thickThinLargeGap" | string "thinThickThinLargeGap" | string "wave" | string "doubleWave" | string "dashSmallGap" | string "dashDotStroked" | string "threeDEmboss" | string "threeDEngrave" | string "outset" | string "inset" | string "apples" | string "archedScallops" | string "babyPacifier" | string "babyRattle" | string "balloons3Colors" | string "balloonsHotAir" | string "basicBlackDashes" | string "basicBlackDots" | string "basicBlackSquares" | string "basicThinLines" | string "basicWhiteDashes" | string "basicWhiteDots" | string "basicWhiteSquares" | string "basicWideInline" | string "basicWideMidline" | string "basicWideOutline" | string "bats" | string "birds" | string "birdsFlight" | string "cabins" | string "cakeSlice" | string "candyCorn" | string "celticKnotwork" | string "certificateBanner" | string "chainLink" | string "champagneBottle" | string "checkedBarBlack" | string "checkedBarColor" | string "checkered" | string "christmasTree" | string "circlesLines" | string "circlesRectangles" | string "classicalWave" | string "clocks" | string "compass" | string "confetti" | string "confettiGrays" | string "confettiOutline" | string "confettiStreamers" | string "confettiWhite" | string "cornerTriangles" | string "couponCutoutDashes" | string "couponCutoutDots" | string "crazyMaze" | string "creaturesButterfly" | string "creaturesFish" | string "creaturesInsects" | string "creaturesLadyBug" | string "crossStitch" | string "cup" | string "decoArch" | string "decoArchColor" | string "decoBlocks" | string "diamondsGray" | string "doubleD" | string "doubleDiamonds" | string "earth1" | string "earth2" | string "earth3" | string "eclipsingSquares1" | string "eclipsingSquares2" | string "eggsBlack" | string "fans" | string "film" | string "firecrackers" | string "flowersBlockPrint" | string "flowersDaisies" | string "flowersModern1" | string "flowersModern2" | string "flowersPansy" | string "flowersRedRose" | string "flowersRoses" | string "flowersTeacup" | string "flowersTiny" | string "gems" | string "gingerbreadMan" | string "gradient" | string "handmade1" | string "handmade2" | string "heartBalloon" | string "heartGray" | string "hearts" | string "heebieJeebies" | string "holly" | string "houseFunky" | string "hypnotic" | string "iceCreamCones" | string "lightBulb" | string "lightning1" | string "lightning2" | string "mapPins" | string "mapleLeaf" | string "mapleMuffins" | string "marquee" | string "marqueeToothed" | string "moons" | string "mosaic" | string "musicNotes" | string "northwest" | string "ovals" | string "packages" | string "palmsBlack" | string "palmsColor" | string "paperClips" | string "papyrus" | string "partyFavor" | string "partyGlass" | string "pencils" | string "people" | string "peopleWaving" | string "peopleHats" | string "poinsettias" | string "postageStamp" | string "pumpkin1" | string "pushPinNote2" | string "pushPinNote1" | string "pyramids" | string "pyramidsAbove" | string "quadrants" | string "rings" | string "safari" | string "sawtooth" | string "sawtoothGray" | string "scaredCat" | string "seattle" | string "shadowedSquares" | string "sharksTeeth" | string "shorebirdTracks" | string "skyrocket" | string "snowflakeFancy" | string "snowflakes" | string "sombrero" | string "southwest" | string "stars" | string "starsTop" | string "stars3d" | string "starsBlack" | string "starsShadowed" | string "sun" | string "swirligig" | string "tornPaper" | string "tornPaperBlack" | string "trees" | string "triangleParty" | string "triangles" | string "triangle1" | string "triangle2" | string "triangleCircle1" | string "triangleCircle2" | string "shapes1" | string "shapes2" | string "twistedLines1" | string "twistedLines2" | string "vine" | string "waveline" | string "weavingAngles" | string "weavingBraid" | string "weavingRibbon" | string "weavingStrips" | string "whiteFlowers" | string "woodwork" | string "xIllusions" | string "zanyTriangles" | string "zigZag" | string "zigZagStitch" | string "custom" w_CT_Border = attribute w:val { w_ST_Border }, attribute w:color { w_ST_HexColor }?, ## default value: auto attribute w:themeColor { w_ST_ThemeColor }?, attribute w:themeTint { w_ST_UcharHexNumber }?, attribute w:themeShade { w_ST_UcharHexNumber }?, attribute w:sz { w_ST_EighthPointMeasure }?, attribute w:space { w_ST_PointMeasure }?, ## default value: 0 attribute w:shadow { s_ST_OnOff }?, attribute w:frame { s_ST_OnOff }? w_ST_Shd = string "nil" | string "clear" | string "solid" | string "horzStripe" | string "vertStripe" | string "reverseDiagStripe" | string "diagStripe" | string "horzCross" | string "diagCross" | string "thinHorzStripe" | string "thinVertStripe" | string "thinReverseDiagStripe" | string "thinDiagStripe" | string "thinHorzCross" | string "thinDiagCross" | string "pct5" | string "pct10" | string "pct12" | string "pct15" | string "pct20" | string "pct25" | string "pct30" | string "pct35" | string "pct37" | string "pct40" | string "pct45" | string "pct50" | string "pct55" | string "pct60" | string "pct62" | string "pct65" | string "pct70" | string "pct75" | string "pct80" | string "pct85" | string "pct87" | string "pct90" | string "pct95" w_CT_Shd = attribute w:val { w_ST_Shd }, attribute w:color { w_ST_HexColor }?, attribute w:themeColor { w_ST_ThemeColor }?, attribute w:themeTint { w_ST_UcharHexNumber }?, attribute w:themeShade { w_ST_UcharHexNumber }?, attribute w:fill { w_ST_HexColor }?, attribute w:themeFill { w_ST_ThemeColor }?, attribute w:themeFillTint { w_ST_UcharHexNumber }?, attribute w:themeFillShade { w_ST_UcharHexNumber }? w_CT_VerticalAlignRun = attribute w:val { s_ST_VerticalAlignRun } w_CT_FitText = attribute w:val { s_ST_TwipsMeasure }, attribute w:id { w_ST_DecimalNumber }? w_ST_Em = string "none" | string "dot" | string "comma" | string "circle" | string "underDot" w_CT_Em = attribute w:val { w_ST_Em } w_CT_Language = attribute w:val { s_ST_Lang }?, attribute w:eastAsia { s_ST_Lang }?, attribute w:bidi { s_ST_Lang }? w_ST_CombineBrackets = string "none" | string "round" | string "square" | string "angle" | string "curly" w_CT_EastAsianLayout = attribute w:id { w_ST_DecimalNumber }?, attribute w:combine { s_ST_OnOff }?, attribute w:combineBrackets { w_ST_CombineBrackets }?, attribute w:vert { s_ST_OnOff }?, attribute w:vertCompress { s_ST_OnOff }? w_ST_HeightRule = string "auto" | string "exact" | string "atLeast" w_ST_Wrap = string "auto" | string "notBeside" | string "around" | string "tight" | string "through" | string "none" w_ST_VAnchor = string "text" | string "margin" | string "page" w_ST_HAnchor = string "text" | string "margin" | string "page" w_ST_DropCap = string "none" | string "drop" | string "margin" w_CT_FramePr = attribute w:dropCap { w_ST_DropCap }?, attribute w:lines { w_ST_DecimalNumber }?, attribute w:w { s_ST_TwipsMeasure }?, attribute w:h { s_ST_TwipsMeasure }?, attribute w:vSpace { s_ST_TwipsMeasure }?, attribute w:hSpace { s_ST_TwipsMeasure }?, attribute w:wrap { w_ST_Wrap }?, attribute w:hAnchor { w_ST_HAnchor }?, attribute w:vAnchor { w_ST_VAnchor }?, attribute w:x { w_ST_SignedTwipsMeasure }?, attribute w:xAlign { s_ST_XAlign }?, attribute w:y { w_ST_SignedTwipsMeasure }?, attribute w:yAlign { s_ST_YAlign }?, attribute w:hRule { w_ST_HeightRule }?, attribute w:anchorLock { s_ST_OnOff }? w_ST_TabJc = string "clear" | string "start" | string "center" | string "end" | string "decimal" | string "bar" | string "num" | string "left" | string "right" w_ST_TabTlc = string "none" | string "dot" | string "hyphen" | string "underscore" | string "heavy" | string "middleDot" w_CT_TabStop = attribute w:val { w_ST_TabJc }, attribute w:leader { w_ST_TabTlc }?, attribute w:pos { w_ST_SignedTwipsMeasure } w_ST_LineSpacingRule = string "auto" | string "exact" | string "atLeast" w_CT_Spacing = attribute w:before { s_ST_TwipsMeasure }?, ## default value: 0 attribute w:beforeLines { w_ST_DecimalNumber }?, ## default value: 0 attribute w:beforeAutospacing { s_ST_OnOff }?, ## default value: off attribute w:after { s_ST_TwipsMeasure }?, ## default value: 0 attribute w:afterLines { w_ST_DecimalNumber }?, ## default value: 0 attribute w:afterAutospacing { s_ST_OnOff }?, ## default value: off attribute w:line { w_ST_SignedTwipsMeasure }?, ## default value: 0 attribute w:lineRule { w_ST_LineSpacingRule }? ## default value: auto w_CT_Ind = attribute w:start { w_ST_SignedTwipsMeasure }?, attribute w:startChars { w_ST_DecimalNumber }?, attribute w:end { w_ST_SignedTwipsMeasure }?, attribute w:endChars { w_ST_DecimalNumber }?, attribute w:left { w_ST_SignedTwipsMeasure }?, attribute w:leftChars { w_ST_DecimalNumber }?, attribute w:right { w_ST_SignedTwipsMeasure }?, attribute w:rightChars { w_ST_DecimalNumber }?, attribute w:hanging { s_ST_TwipsMeasure }?, attribute w:hangingChars { w_ST_DecimalNumber }?, attribute w:firstLine { s_ST_TwipsMeasure }?, attribute w:firstLineChars { w_ST_DecimalNumber }? w_ST_Jc = string "start" | string "center" | string "end" | string "both" | string "mediumKashida" | string "distribute" | string "numTab" | string "highKashida" | string "lowKashida" | string "thaiDistribute" | string "left" | string "right" w_ST_JcTable = string "center" | string "end" | string "left" | string "right" | string "start" w_CT_Jc = attribute w:val { w_ST_Jc } w_CT_JcTable = attribute w:val { w_ST_JcTable } w_ST_View = string "none" | string "print" | string "outline" | string "masterPages" | string "normal" | string "web" w_CT_View = attribute w:val { w_ST_View } w_ST_Zoom = string "none" | string "fullPage" | string "bestFit" | string "textFit" w_CT_Zoom = attribute w:val { w_ST_Zoom }?, attribute w:percent { w_ST_DecimalNumberOrPercent } w_CT_WritingStyle = attribute w:lang { s_ST_Lang }, attribute w:vendorID { s_ST_String }, attribute w:dllVersion { s_ST_String }, attribute w:nlCheck { s_ST_OnOff }?, ## default value: off attribute w:checkStyle { s_ST_OnOff }, attribute w:appName { s_ST_String } w_ST_Proof = string "clean" | string "dirty" w_CT_Proof = attribute w:spelling { w_ST_Proof }?, attribute w:grammar { w_ST_Proof }? w_ST_DocType = xsd:string w_CT_DocType = attribute w:val { w_ST_DocType } w_ST_DocProtect = string "none" | string "readOnly" | string "comments" | string "trackedChanges" | string "forms" w_AG_Password = attribute w:algorithmName { s_ST_String }?, attribute w:hashValue { xsd:base64Binary }?, attribute w:saltValue { xsd:base64Binary }?, attribute w:spinCount { w_ST_DecimalNumber }? w_AG_TransitionalPassword = attribute w:cryptProviderType { s_ST_CryptProv }?, attribute w:cryptAlgorithmClass { s_ST_AlgClass }?, attribute w:cryptAlgorithmType { s_ST_AlgType }?, attribute w:cryptAlgorithmSid { w_ST_DecimalNumber }?, attribute w:cryptSpinCount { w_ST_DecimalNumber }?, attribute w:cryptProvider { s_ST_String }?, attribute w:algIdExt { w_ST_LongHexNumber }?, attribute w:algIdExtSource { s_ST_String }?, attribute w:cryptProviderTypeExt { w_ST_LongHexNumber }?, attribute w:cryptProviderTypeExtSource { s_ST_String }?, attribute w:hash { xsd:base64Binary }?, attribute w:salt { xsd:base64Binary }? w_CT_DocProtect = attribute w:edit { w_ST_DocProtect }?, attribute w:formatting { s_ST_OnOff }?, attribute w:enforcement { s_ST_OnOff }?, w_AG_Password, w_AG_TransitionalPassword w_ST_MailMergeDocType = string "catalog" | string "envelopes" | string "mailingLabels" | string "formLetters" | string "email" | string "fax" w_CT_MailMergeDocType = attribute w:val { w_ST_MailMergeDocType } w_ST_MailMergeDataType = xsd:string w_CT_MailMergeDataType = attribute w:val { w_ST_MailMergeDataType } w_ST_MailMergeDest = string "newDocument" | string "printer" | string "email" | string "fax" w_CT_MailMergeDest = attribute w:val { w_ST_MailMergeDest } w_ST_MailMergeOdsoFMDFieldType = string "null" | string "dbColumn" w_CT_MailMergeOdsoFMDFieldType = attribute w:val { w_ST_MailMergeOdsoFMDFieldType } w_CT_TrackChangesView = attribute w:markup { s_ST_OnOff }?, attribute w:comments { s_ST_OnOff }?, attribute w:insDel { s_ST_OnOff }?, attribute w:formatting { s_ST_OnOff }?, attribute w:inkAnnotations { s_ST_OnOff }? w_CT_Kinsoku = attribute w:lang { s_ST_Lang }, attribute w:val { s_ST_String } w_ST_TextDirection = string "tb" | string "rl" | string "lr" | string "tbV" | string "rlV" | string "lrV" | string "btLr" | string "lrTb" | string "lrTbV" | string "tbLrV" | string "tbRl" | string "tbRlV" w_CT_TextDirection = attribute w:val { w_ST_TextDirection } w_ST_TextAlignment = string "top" | string "center" | string "baseline" | string "bottom" | string "auto" w_CT_TextAlignment = attribute w:val { w_ST_TextAlignment } w_ST_DisplacedByCustomXml = string "next" | string "prev" w_ST_AnnotationVMerge = string "cont" | string "rest" w_CT_Markup = attribute w:id { w_ST_DecimalNumber } w_CT_TrackChange = w_CT_Markup, attribute w:author { s_ST_String }, attribute w:date { w_ST_DateTime }? w_CT_CellMergeTrackChange = w_CT_TrackChange, attribute w:vMerge { w_ST_AnnotationVMerge }?, attribute w:vMergeOrig { w_ST_AnnotationVMerge }? w_CT_TrackChangeRange = w_CT_TrackChange, attribute w:displacedByCustomXml { w_ST_DisplacedByCustomXml }? w_CT_MarkupRange = w_CT_Markup, attribute w:displacedByCustomXml { w_ST_DisplacedByCustomXml }? w_CT_BookmarkRange = w_CT_MarkupRange, attribute w:colFirst { w_ST_DecimalNumber }?, attribute w:colLast { w_ST_DecimalNumber }? w_CT_Bookmark = w_CT_BookmarkRange, attribute w:name { s_ST_String } w_CT_MoveBookmark = w_CT_Bookmark, attribute w:author { s_ST_String }, attribute w:date { w_ST_DateTime } w_CT_Comment = w_CT_TrackChange, w_EG_BlockLevelElts*, attribute w:initials { s_ST_String }? w_CT_TrackChangeNumbering = w_CT_TrackChange, attribute w:original { s_ST_String }? w_CT_TblPrExChange = w_CT_TrackChange, element tblPrEx { w_CT_TblPrExBase } w_CT_TcPrChange = w_CT_TrackChange, element tcPr { w_CT_TcPrInner } w_CT_TrPrChange = w_CT_TrackChange, element trPr { w_CT_TrPrBase } w_CT_TblGridChange = w_CT_Markup, element tblGrid { w_CT_TblGridBase } w_CT_TblPrChange = w_CT_TrackChange, element tblPr { w_CT_TblPrBase } w_CT_SectPrChange = w_CT_TrackChange, element sectPr { w_CT_SectPrBase }? w_CT_PPrChange = w_CT_TrackChange, element pPr { w_CT_PPrBase } w_CT_RPrChange = w_CT_TrackChange, element rPr { w_CT_RPrOriginal } w_CT_ParaRPrChange = w_CT_TrackChange, element rPr { w_CT_ParaRPrOriginal } w_CT_RunTrackChange = w_CT_TrackChange, (w_EG_ContentRunContent | m_EG_OMathMathElements)* w_EG_PContentMath = w_EG_PContentBase* | w_EG_ContentRunContentBase* w_EG_PContentBase = element customXml { w_CT_CustomXmlRun } | element fldSimple { w_CT_SimpleField }* | element hyperlink { w_CT_Hyperlink } w_EG_ContentRunContentBase = element smartTag { w_CT_SmartTagRun } | element sdt { w_CT_SdtRun } | w_EG_RunLevelElts* w_EG_CellMarkupElements = element cellIns { w_CT_TrackChange }? | element cellDel { w_CT_TrackChange }? | element cellMerge { w_CT_CellMergeTrackChange }? w_EG_RangeMarkupElements = element bookmarkStart { w_CT_Bookmark } | element bookmarkEnd { w_CT_MarkupRange } | element moveFromRangeStart { w_CT_MoveBookmark } | element moveFromRangeEnd { w_CT_MarkupRange } | element moveToRangeStart { w_CT_MoveBookmark } | element moveToRangeEnd { w_CT_MarkupRange } | element commentRangeStart { w_CT_MarkupRange } | element commentRangeEnd { w_CT_MarkupRange } | element customXmlInsRangeStart { w_CT_TrackChange } | element customXmlInsRangeEnd { w_CT_Markup } | element customXmlDelRangeStart { w_CT_TrackChange } | element customXmlDelRangeEnd { w_CT_Markup } | element customXmlMoveFromRangeStart { w_CT_TrackChange } | element customXmlMoveFromRangeEnd { w_CT_Markup } | element customXmlMoveToRangeStart { w_CT_TrackChange } | element customXmlMoveToRangeEnd { w_CT_Markup } w_CT_NumPr = element ilvl { w_CT_DecimalNumber }?, element numId { w_CT_DecimalNumber }?, element numberingChange { w_CT_TrackChangeNumbering }?, element ins { w_CT_TrackChange }? w_CT_PBdr = element top { w_CT_Border }?, element left { w_CT_Border }?, element bottom { w_CT_Border }?, element right { w_CT_Border }?, element between { w_CT_Border }?, element bar { w_CT_Border }? w_CT_Tabs = element tab { w_CT_TabStop }+ w_ST_TextboxTightWrap = string "none" | string "allLines" | string "firstAndLastLine" | string "firstLineOnly" | string "lastLineOnly" w_CT_TextboxTightWrap = attribute w:val { w_ST_TextboxTightWrap } w_CT_PPr = w_CT_PPrBase, element rPr { w_CT_ParaRPr }?, element sectPr { w_CT_SectPr }?, element pPrChange { w_CT_PPrChange }? w_CT_PPrBase = element pStyle { w_CT_String }?, element keepNext { w_CT_OnOff }?, element keepLines { w_CT_OnOff }?, element pageBreakBefore { w_CT_OnOff }?, element framePr { w_CT_FramePr }?, element widowControl { w_CT_OnOff }?, element numPr { w_CT_NumPr }?, element suppressLineNumbers { w_CT_OnOff }?, element pBdr { w_CT_PBdr }?, element shd { w_CT_Shd }?, element tabs { w_CT_Tabs }?, element suppressAutoHyphens { w_CT_OnOff }?, element kinsoku { w_CT_OnOff }?, element wordWrap { w_CT_OnOff }?, element overflowPunct { w_CT_OnOff }?, element topLinePunct { w_CT_OnOff }?, element autoSpaceDE { w_CT_OnOff }?, element autoSpaceDN { w_CT_OnOff }?, element bidi { w_CT_OnOff }?, element adjustRightInd { w_CT_OnOff }?, element snapToGrid { w_CT_OnOff }?, element spacing { w_CT_Spacing }?, element ind { w_CT_Ind }?, element contextualSpacing { w_CT_OnOff }?, element mirrorIndents { w_CT_OnOff }?, element suppressOverlap { w_CT_OnOff }?, element jc { w_CT_Jc }?, element textDirection { w_CT_TextDirection }?, element textAlignment { w_CT_TextAlignment }?, element textboxTightWrap { w_CT_TextboxTightWrap }?, element outlineLvl { w_CT_DecimalNumber }?, element divId { w_CT_DecimalNumber }?, element cnfStyle { w_CT_Cnf }? w_CT_PPrGeneral = w_CT_PPrBase, element pPrChange { w_CT_PPrChange }? w_CT_Control = attribute w:name { s_ST_String }?, attribute w:shapeid { s_ST_String }?, r_id? w_CT_Background = attribute w:color { w_ST_HexColor }?, ## default value: auto attribute w:themeColor { w_ST_ThemeColor }?, attribute w:themeTint { w_ST_UcharHexNumber }?, attribute w:themeShade { w_ST_UcharHexNumber }?, (w_any_vml_vml*, w_any_vml_office*)+, element drawing { w_CT_Drawing }? w_CT_Rel = r_id w_CT_Object = attribute w:dxaOrig { s_ST_TwipsMeasure }?, attribute w:dyaOrig { s_ST_TwipsMeasure }?, (w_any_vml_vml*, w_any_vml_office*)+, element drawing { w_CT_Drawing }?, (element control { w_CT_Control } | element objectLink { w_CT_ObjectLink } | element objectEmbed { w_CT_ObjectEmbed } | element movie { w_CT_Rel })? w_CT_Picture = (w_any_vml_vml*, w_any_vml_office*)+, element movie { w_CT_Rel }?, element control { w_CT_Control }? w_CT_ObjectEmbed = attribute w:drawAspect { w_ST_ObjectDrawAspect }?, r_id, attribute w:progId { s_ST_String }?, attribute w:shapeId { s_ST_String }?, attribute w:fieldCodes { s_ST_String }? w_ST_ObjectDrawAspect = string "content" | string "icon" w_CT_ObjectLink = w_CT_ObjectEmbed, attribute w:updateMode { w_ST_ObjectUpdateMode }, attribute w:lockedField { s_ST_OnOff }? w_ST_ObjectUpdateMode = string "always" | string "onCall" w_CT_Drawing = (wp_anchor? | wp_inline?)+ w_CT_SimpleField = attribute w:instr { s_ST_String }, attribute w:fldLock { s_ST_OnOff }?, attribute w:dirty { s_ST_OnOff }?, element fldData { w_CT_Text }?, w_EG_PContent* w_ST_FldCharType = string "begin" | string "separate" | string "end" w_ST_InfoTextType = string "text" | string "autoText" w_ST_FFHelpTextVal = xsd:string { maxLength = "256" } w_ST_FFStatusTextVal = xsd:string { maxLength = "140" } w_ST_FFName = xsd:string { maxLength = "65" } w_ST_FFTextType = string "regular" | string "number" | string "date" | string "currentTime" | string "currentDate" | string "calculated" w_CT_FFTextType = attribute w:val { w_ST_FFTextType } w_CT_FFName = attribute w:val { w_ST_FFName }? w_CT_FldChar = attribute w:fldCharType { w_ST_FldCharType }, attribute w:fldLock { s_ST_OnOff }?, attribute w:dirty { s_ST_OnOff }?, (element fldData { w_CT_Text }? | element ffData { w_CT_FFData }? | element numberingChange { w_CT_TrackChangeNumbering }?) w_CT_Hyperlink = attribute w:tgtFrame { s_ST_String }?, attribute w:tooltip { s_ST_String }?, attribute w:docLocation { s_ST_String }?, attribute w:history { s_ST_OnOff }?, attribute w:anchor { s_ST_String }?, r_id?, w_EG_PContent* w_CT_FFData = (element name { w_CT_FFName } | element label { w_CT_DecimalNumber }? | element tabIndex { w_CT_UnsignedDecimalNumber }? | element enabled { w_CT_OnOff } | element calcOnExit { w_CT_OnOff } | element entryMacro { w_CT_MacroName }? | element exitMacro { w_CT_MacroName }? | element helpText { w_CT_FFHelpText }? | element statusText { w_CT_FFStatusText }? | (element checkBox { w_CT_FFCheckBox } | element ddList { w_CT_FFDDList } | element textInput { w_CT_FFTextInput }))+ w_CT_FFHelpText = attribute w:type { w_ST_InfoTextType }?, attribute w:val { w_ST_FFHelpTextVal }? w_CT_FFStatusText = attribute w:type { w_ST_InfoTextType }?, attribute w:val { w_ST_FFStatusTextVal }? w_CT_FFCheckBox = (element size { w_CT_HpsMeasure } | element sizeAuto { w_CT_OnOff }), element default { w_CT_OnOff }?, element checked { w_CT_OnOff }? w_CT_FFDDList = element result { w_CT_DecimalNumber }?, element default { w_CT_DecimalNumber }?, element listEntry { w_CT_String }* w_CT_FFTextInput = element type { w_CT_FFTextType }?, element default { w_CT_String }?, element maxLength { w_CT_DecimalNumber }?, element format { w_CT_String }? w_ST_SectionMark = string "nextPage" | string "nextColumn" | string "continuous" | string "evenPage" | string "oddPage" w_CT_SectType = attribute w:val { w_ST_SectionMark }? w_CT_PaperSource = attribute w:first { w_ST_DecimalNumber }?, attribute w:other { w_ST_DecimalNumber }? w_ST_NumberFormat = string "decimal" | string "upperRoman" | string "lowerRoman" | string "upperLetter" | string "lowerLetter" | string "ordinal" | string "cardinalText" | string "ordinalText" | string "hex" | string "chicago" | string "ideographDigital" | string "japaneseCounting" | string "aiueo" | string "iroha" | string "decimalFullWidth" | string "decimalHalfWidth" | string "japaneseLegal" | string "japaneseDigitalTenThousand" | string "decimalEnclosedCircle" | string "decimalFullWidth2" | string "aiueoFullWidth" | string "irohaFullWidth" | string "decimalZero" | string "bullet" | string "ganada" | string "chosung" | string "decimalEnclosedFullstop" | string "decimalEnclosedParen" | string "decimalEnclosedCircleChinese" | string "ideographEnclosedCircle" | string "ideographTraditional" | string "ideographZodiac" | string "ideographZodiacTraditional" | string "taiwaneseCounting" | string "ideographLegalTraditional" | string "taiwaneseCountingThousand" | string "taiwaneseDigital" | string "chineseCounting" | string "chineseLegalSimplified" | string "chineseCountingThousand" | string "koreanDigital" | string "koreanCounting" | string "koreanLegal" | string "koreanDigital2" | string "vietnameseCounting" | string "russianLower" | string "russianUpper" | string "none" | string "numberInDash" | string "hebrew1" | string "hebrew2" | string "arabicAlpha" | string "arabicAbjad" | string "hindiVowels" | string "hindiConsonants" | string "hindiNumbers" | string "hindiCounting" | string "thaiLetters" | string "thaiNumbers" | string "thaiCounting" | string "bahtText" | string "dollarText" | string "custom" w_ST_PageOrientation = string "portrait" | string "landscape" w_CT_PageSz = attribute w:w { s_ST_TwipsMeasure }?, attribute w:h { s_ST_TwipsMeasure }?, attribute w:orient { w_ST_PageOrientation }?, attribute w:code { w_ST_DecimalNumber }? w_CT_PageMar = attribute w:top { w_ST_SignedTwipsMeasure }, attribute w:right { s_ST_TwipsMeasure }, attribute w:bottom { w_ST_SignedTwipsMeasure }, attribute w:left { s_ST_TwipsMeasure }, attribute w:header { s_ST_TwipsMeasure }, attribute w:footer { s_ST_TwipsMeasure }, attribute w:gutter { s_ST_TwipsMeasure } w_ST_PageBorderZOrder = string "front" | string "back" w_ST_PageBorderDisplay = string "allPages" | string "firstPage" | string "notFirstPage" w_ST_PageBorderOffset = string "page" | string "text" w_CT_PageBorders = attribute w:zOrder { w_ST_PageBorderZOrder }?, ## default value: front attribute w:display { w_ST_PageBorderDisplay }?, attribute w:offsetFrom { w_ST_PageBorderOffset }?, ## default value: text element top { w_CT_TopPageBorder }?, element left { w_CT_PageBorder }?, element bottom { w_CT_BottomPageBorder }?, element right { w_CT_PageBorder }? w_CT_PageBorder = w_CT_Border, r_id? w_CT_BottomPageBorder = w_CT_PageBorder, r_bottomLeft?, r_bottomRight? w_CT_TopPageBorder = w_CT_PageBorder, r_topLeft?, r_topRight? w_ST_ChapterSep = string "hyphen" | string "period" | string "colon" | string "emDash" | string "enDash" w_ST_LineNumberRestart = string "newPage" | string "newSection" | string "continuous" w_CT_LineNumber = attribute w:countBy { w_ST_DecimalNumber }?, attribute w:start { w_ST_DecimalNumber }?, ## default value: 1 attribute w:distance { s_ST_TwipsMeasure }?, attribute w:restart { w_ST_LineNumberRestart }? ## default value: newPage w_CT_PageNumber = attribute w:fmt { w_ST_NumberFormat }?, ## default value: decimal attribute w:start { w_ST_DecimalNumber }?, attribute w:chapStyle { w_ST_DecimalNumber }?, attribute w:chapSep { w_ST_ChapterSep }? ## default value: hyphen w_CT_Column = attribute w:w { s_ST_TwipsMeasure }?, attribute w:space { s_ST_TwipsMeasure }? ## default value: 0 w_CT_Columns = attribute w:equalWidth { s_ST_OnOff }?, attribute w:space { s_ST_TwipsMeasure }?, ## default value: 720 attribute w:num { w_ST_DecimalNumber }?, ## default value: 1 attribute w:sep { s_ST_OnOff }?, element col { w_CT_Column }* w_ST_VerticalJc = string "top" | string "center" | string "both" | string "bottom" w_CT_VerticalJc = attribute w:val { w_ST_VerticalJc } w_ST_DocGrid = string "default" | string "lines" | string "linesAndChars" | string "snapToChars" w_CT_DocGrid = attribute w:type { w_ST_DocGrid }?, attribute w:linePitch { w_ST_DecimalNumber }?, attribute w:charSpace { w_ST_DecimalNumber }? w_ST_HdrFtr = string "even" | string "default" | string "first" w_ST_FtnEdn = string "normal" | string "separator" | string "continuationSeparator" | string "continuationNotice" w_CT_HdrFtrRef = w_CT_Rel, attribute w:type { w_ST_HdrFtr } w_EG_HdrFtrReferences = element headerReference { w_CT_HdrFtrRef }? | element footerReference { w_CT_HdrFtrRef }? w_CT_HdrFtr = w_EG_BlockLevelElts+ w_EG_SectPrContents = element footnotePr { w_CT_FtnProps }?, element endnotePr { w_CT_EdnProps }?, element type { w_CT_SectType }?, element pgSz { w_CT_PageSz }?, element pgMar { w_CT_PageMar }?, element paperSrc { w_CT_PaperSource }?, element pgBorders { w_CT_PageBorders }?, element lnNumType { w_CT_LineNumber }?, element pgNumType { w_CT_PageNumber }?, element cols { w_CT_Columns }?, element formProt { w_CT_OnOff }?, element vAlign { w_CT_VerticalJc }?, element noEndnote { w_CT_OnOff }?, element titlePg { w_CT_OnOff }?, element textDirection { w_CT_TextDirection }?, element bidi { w_CT_OnOff }?, element rtlGutter { w_CT_OnOff }?, element docGrid { w_CT_DocGrid }?, element printerSettings { w_CT_Rel }? w_AG_SectPrAttributes = attribute w:rsidRPr { w_ST_LongHexNumber }?, attribute w:rsidDel { w_ST_LongHexNumber }?, attribute w:rsidR { w_ST_LongHexNumber }?, attribute w:rsidSect { w_ST_LongHexNumber }? w_CT_SectPrBase = w_AG_SectPrAttributes, w_EG_SectPrContents? w_CT_SectPr = w_AG_SectPrAttributes, w_EG_HdrFtrReferences*, w_EG_SectPrContents?, element sectPrChange { w_CT_SectPrChange }? w_ST_BrType = string "page" | string "column" | string "textWrapping" w_ST_BrClear = string "none" | string "left" | string "right" | string "all" w_CT_Br = attribute w:type { w_ST_BrType }?, attribute w:clear { w_ST_BrClear }? w_ST_PTabAlignment = string "left" | string "center" | string "right" w_ST_PTabRelativeTo = string "margin" | string "indent" w_ST_PTabLeader = string "none" | string "dot" | string "hyphen" | string "underscore" | string "middleDot" w_CT_PTab = attribute w:alignment { w_ST_PTabAlignment }, attribute w:relativeTo { w_ST_PTabRelativeTo }, attribute w:leader { w_ST_PTabLeader } w_CT_Sym = attribute w:font { s_ST_String }?, attribute w:char { w_ST_ShortHexNumber }? w_ST_ProofErr = string "spellStart" | string "spellEnd" | string "gramStart" | string "gramEnd" w_CT_ProofErr = attribute w:type { w_ST_ProofErr } w_ST_EdGrp = string "none" | string "everyone" | string "administrators" | string "contributors" | string "editors" | string "owners" | string "current" w_CT_Perm = attribute w:id { s_ST_String }, attribute w:displacedByCustomXml { w_ST_DisplacedByCustomXml }? w_CT_PermStart = w_CT_Perm, attribute w:edGrp { w_ST_EdGrp }?, attribute w:ed { s_ST_String }?, attribute w:colFirst { w_ST_DecimalNumber }?, attribute w:colLast { w_ST_DecimalNumber }? w_CT_Text = s_ST_String, xml_space? w_EG_RunInnerContent = element br { w_CT_Br } | element t { w_CT_Text } | element contentPart { w_CT_Rel } | element delText { w_CT_Text } | element instrText { w_CT_Text } | element delInstrText { w_CT_Text } | element noBreakHyphen { w_CT_Empty } | element softHyphen { w_CT_Empty }? | element dayShort { w_CT_Empty }? | element monthShort { w_CT_Empty }? | element yearShort { w_CT_Empty }? | element dayLong { w_CT_Empty }? | element monthLong { w_CT_Empty }? | element yearLong { w_CT_Empty }? | element annotationRef { w_CT_Empty }? | element footnoteRef { w_CT_Empty }? | element endnoteRef { w_CT_Empty }? | element separator { w_CT_Empty }? | element continuationSeparator { w_CT_Empty }? | element sym { w_CT_Sym }? | element pgNum { w_CT_Empty }? | element cr { w_CT_Empty }? | element tab { w_CT_Empty }? | element object { w_CT_Object } | element pict { w_CT_Picture } | element fldChar { w_CT_FldChar } | element ruby { w_CT_Ruby } | element footnoteReference { w_CT_FtnEdnRef } | element endnoteReference { w_CT_FtnEdnRef } | element commentReference { w_CT_Markup } | element drawing { w_CT_Drawing } | element ptab { w_CT_PTab }? | element lastRenderedPageBreak { w_CT_Empty }? w_CT_R = attribute w:rsidRPr { w_ST_LongHexNumber }?, attribute w:rsidDel { w_ST_LongHexNumber }?, attribute w:rsidR { w_ST_LongHexNumber }?, w_EG_RPr?, w_EG_RunInnerContent* w_ST_Hint = string "default" | string "eastAsia" w_ST_Theme = string "majorEastAsia" | string "majorBidi" | string "majorAscii" | string "majorHAnsi" | string "minorEastAsia" | string "minorBidi" | string "minorAscii" | string "minorHAnsi" w_CT_Fonts = attribute w:hint { w_ST_Hint }?, attribute w:ascii { s_ST_String }?, attribute w:hAnsi { s_ST_String }?, attribute w:eastAsia { s_ST_String }?, attribute w:cs { s_ST_String }?, attribute w:asciiTheme { w_ST_Theme }?, attribute w:hAnsiTheme { w_ST_Theme }?, attribute w:eastAsiaTheme { w_ST_Theme }?, attribute w:cstheme { w_ST_Theme }? w_EG_RPrBase = element rStyle { w_CT_String }?& element rFonts { w_CT_Fonts }?& element b { w_CT_OnOff }?& element bCs { w_CT_OnOff }?& element i { w_CT_OnOff }?& element iCs { w_CT_OnOff }?& element caps { w_CT_OnOff }?& element smallCaps { w_CT_OnOff }?& element strike { w_CT_OnOff }?& element dstrike { w_CT_OnOff }?& element outline { w_CT_OnOff }?& element shadow { w_CT_OnOff }?& element emboss { w_CT_OnOff }?& element imprint { w_CT_OnOff }?& element noProof { w_CT_OnOff }?& element snapToGrid { w_CT_OnOff }?& element vanish { w_CT_OnOff }?& element webHidden { w_CT_OnOff }?& element color { w_CT_Color }?& element spacing { w_CT_SignedTwipsMeasure }?& element w { w_CT_TextScale }?& element kern { w_CT_HpsMeasure }?& element position { w_CT_SignedHpsMeasure }?& element sz { w_CT_HpsMeasure }?& element szCs { w_CT_HpsMeasure }?& element highlight { w_CT_Highlight }?& element u { w_CT_Underline }?& element effect { w_CT_TextEffect }?& element bdr { w_CT_Border }?& element shd { w_CT_Shd }?& element fitText { w_CT_FitText }?& element vertAlign { w_CT_VerticalAlignRun }?& element rtl { w_CT_OnOff }?& element cs { w_CT_OnOff }?& element em { w_CT_Em }?& element lang { w_CT_Language }?& element eastAsianLayout { w_CT_EastAsianLayout }?& element specVanish { w_CT_OnOff }?& element oMath { w_CT_OnOff }? w_EG_RPrContent = w_EG_RPrBase?, element rPrChange { w_CT_RPrChange }? w_CT_RPr = w_EG_RPrContent? w_EG_RPr = element rPr { w_CT_RPr }? w_EG_RPrMath = w_EG_RPr | element ins { w_CT_MathCtrlIns } | element del { w_CT_MathCtrlDel } w_CT_MathCtrlIns = w_CT_TrackChange, (element del { w_CT_RPrChange } | element rPr { w_CT_RPr })? w_CT_MathCtrlDel = w_CT_TrackChange, (element rPr { w_CT_RPr })? w_CT_RPrOriginal = w_EG_RPrBase* w_CT_ParaRPrOriginal = w_EG_ParaRPrTrackChanges?, w_EG_RPrBase* w_CT_ParaRPr = w_EG_ParaRPrTrackChanges?, w_EG_RPrBase?, element rPrChange { w_CT_ParaRPrChange }? w_EG_ParaRPrTrackChanges = element ins { w_CT_TrackChange }?, element del { w_CT_TrackChange }?, element moveFrom { w_CT_TrackChange }?, element moveTo { w_CT_TrackChange }? w_CT_AltChunk = r_id?, element altChunkPr { w_CT_AltChunkPr }? w_CT_AltChunkPr = element matchSrc { w_CT_OnOff }? w_ST_RubyAlign = string "center" | string "distributeLetter" | string "distributeSpace" | string "left" | string "right" | string "rightVertical" w_CT_RubyAlign = attribute w:val { w_ST_RubyAlign } w_CT_RubyPr = element rubyAlign { w_CT_RubyAlign }, element hps { w_CT_HpsMeasure }, element hpsRaise { w_CT_HpsMeasure }, element hpsBaseText { w_CT_HpsMeasure }, element lid { w_CT_Lang }, element dirty { w_CT_OnOff }? w_EG_RubyContent = element r { w_CT_R } | w_EG_RunLevelElts* w_CT_RubyContent = w_EG_RubyContent* w_CT_Ruby = element rubyPr { w_CT_RubyPr }, element rt { w_CT_RubyContent }, element rubyBase { w_CT_RubyContent } w_ST_Lock = string "sdtLocked" | string "contentLocked" | string "unlocked" | string "sdtContentLocked" w_CT_Lock = attribute w:val { w_ST_Lock }? w_CT_SdtListItem = attribute w:displayText { s_ST_String }?, attribute w:value { s_ST_String }? w_ST_SdtDateMappingType = string "text" | string "date" | string "dateTime" w_CT_SdtDateMappingType = attribute w:val { w_ST_SdtDateMappingType }? w_CT_CalendarType = attribute w:val { s_ST_CalendarType }? w_CT_SdtDate = attribute w:fullDate { w_ST_DateTime }?, element dateFormat { w_CT_String }?, element lid { w_CT_Lang }?, element storeMappedDataAs { w_CT_SdtDateMappingType }?, element calendar { w_CT_CalendarType }? w_CT_SdtComboBox = attribute w:lastValue { s_ST_String }?, ## default value: element listItem { w_CT_SdtListItem }* w_CT_SdtDocPart = element docPartGallery { w_CT_String }?, element docPartCategory { w_CT_String }?, element docPartUnique { w_CT_OnOff }? w_CT_SdtDropDownList = attribute w:lastValue { s_ST_String }?, ## default value: element listItem { w_CT_SdtListItem }* w_CT_Placeholder = element docPart { w_CT_String } w_CT_SdtText = attribute w:multiLine { s_ST_OnOff }? w_CT_DataBinding = attribute w:prefixMappings { s_ST_String }?, attribute w:xpath { s_ST_String }, attribute w:storeItemID { s_ST_String } w_CT_SdtPr = element rPr { w_CT_RPr }?, element alias { w_CT_String }?, element tag { w_CT_String }?, element id { w_CT_DecimalNumber }?, element lock { w_CT_Lock }?, element placeholder { w_CT_Placeholder }?, element temporary { w_CT_OnOff }?, element showingPlcHdr { w_CT_OnOff }?, element dataBinding { w_CT_DataBinding }?, element label { w_CT_DecimalNumber }?, element tabIndex { w_CT_UnsignedDecimalNumber }?, (element equation { w_CT_Empty } | element comboBox { w_CT_SdtComboBox } | element date { w_CT_SdtDate } | element docPartObj { w_CT_SdtDocPart } | element docPartList { w_CT_SdtDocPart } | element dropDownList { w_CT_SdtDropDownList } | element picture { w_CT_Empty } | element richText { w_CT_Empty } | element text { w_CT_SdtText } | element citation { w_CT_Empty } | element group { w_CT_Empty } | element bibliography { w_CT_Empty })? w_CT_SdtEndPr = (element rPr { w_CT_RPr }?)+ w_EG_ContentRunContent = element customXml { w_CT_CustomXmlRun } | element smartTag { w_CT_SmartTagRun } | element sdt { w_CT_SdtRun } | element dir { w_CT_DirContentRun } | element bdo { w_CT_BdoContentRun } | element r { w_CT_R } | w_EG_RunLevelElts* w_CT_DirContentRun = attribute w:val { w_ST_Direction }?, w_EG_PContent* w_CT_BdoContentRun = attribute w:val { w_ST_Direction }?, w_EG_PContent* w_ST_Direction = string "ltr" | string "rtl" w_CT_SdtContentRun = w_EG_PContent* w_EG_ContentBlockContent = element customXml { w_CT_CustomXmlBlock } | element sdt { w_CT_SdtBlock } | element p { w_CT_P }* | element tbl { w_CT_Tbl }* | w_EG_RunLevelElts* w_CT_SdtContentBlock = w_EG_ContentBlockContent* w_EG_ContentRowContent = element tr { w_CT_Row }* | element customXml { w_CT_CustomXmlRow } | element sdt { w_CT_SdtRow } | w_EG_RunLevelElts* w_CT_SdtContentRow = w_EG_ContentRowContent* w_EG_ContentCellContent = element tc { w_CT_Tc }* | element customXml { w_CT_CustomXmlCell } | element sdt { w_CT_SdtCell } | w_EG_RunLevelElts* w_CT_SdtContentCell = w_EG_ContentCellContent* w_CT_SdtBlock = element sdtPr { w_CT_SdtPr }?, element sdtEndPr { w_CT_SdtEndPr }?, element sdtContent { w_CT_SdtContentBlock }? w_CT_SdtRun = element sdtPr { w_CT_SdtPr }?, element sdtEndPr { w_CT_SdtEndPr }?, element sdtContent { w_CT_SdtContentRun }? w_CT_SdtCell = element sdtPr { w_CT_SdtPr }?, element sdtEndPr { w_CT_SdtEndPr }?, element sdtContent { w_CT_SdtContentCell }? w_CT_SdtRow = element sdtPr { w_CT_SdtPr }?, element sdtEndPr { w_CT_SdtEndPr }?, element sdtContent { w_CT_SdtContentRow }? w_CT_Attr = attribute w:uri { s_ST_String }?, attribute w:name { s_ST_String }, attribute w:val { s_ST_String } w_CT_CustomXmlRun = attribute w:uri { s_ST_String }?, attribute w:element { s_ST_XmlName }, element customXmlPr { w_CT_CustomXmlPr }?, w_EG_PContent* w_CT_SmartTagRun = attribute w:uri { s_ST_String }?, attribute w:element { s_ST_XmlName }, element smartTagPr { w_CT_SmartTagPr }?, w_EG_PContent* w_CT_CustomXmlBlock = attribute w:uri { s_ST_String }?, attribute w:element { s_ST_XmlName }, element customXmlPr { w_CT_CustomXmlPr }?, w_EG_ContentBlockContent* w_CT_CustomXmlPr = element placeholder { w_CT_String }?, element attr { w_CT_Attr }* w_CT_CustomXmlRow = attribute w:uri { s_ST_String }?, attribute w:element { s_ST_XmlName }, element customXmlPr { w_CT_CustomXmlPr }?, w_EG_ContentRowContent* w_CT_CustomXmlCell = attribute w:uri { s_ST_String }?, attribute w:element { s_ST_XmlName }, element customXmlPr { w_CT_CustomXmlPr }?, w_EG_ContentCellContent* w_CT_SmartTagPr = element attr { w_CT_Attr }* w_EG_PContent = w_EG_ContentRunContent* | element fldSimple { w_CT_SimpleField }* | element hyperlink { w_CT_Hyperlink } | element subDoc { w_CT_Rel } w_CT_P = attribute w:rsidRPr { w_ST_LongHexNumber }?, attribute w:rsidR { w_ST_LongHexNumber }?, attribute w:rsidDel { w_ST_LongHexNumber }?, attribute w:rsidP { w_ST_LongHexNumber }?, attribute w:rsidRDefault { w_ST_LongHexNumber }?, element pPr { w_CT_PPr }?, w_EG_PContent* w_ST_TblWidth = string "nil" | string "pct" | string "dxa" | string "auto" w_CT_Height = attribute w:val { s_ST_TwipsMeasure }?, attribute w:hRule { w_ST_HeightRule }? w_ST_MeasurementOrPercent = w_ST_DecimalNumberOrPercent | s_ST_UniversalMeasure w_CT_TblWidth = attribute w:w { w_ST_MeasurementOrPercent }?, attribute w:type { w_ST_TblWidth }? w_CT_TblGridCol = attribute w:w { s_ST_TwipsMeasure }? w_CT_TblGridBase = element gridCol { w_CT_TblGridCol }* w_CT_TblGrid = w_CT_TblGridBase, element tblGridChange { w_CT_TblGridChange }? w_CT_TcBorders = element top { w_CT_Border }?, element start { w_CT_Border }?, element left { w_CT_Border }?, element bottom { w_CT_Border }?, element end { w_CT_Border }?, element right { w_CT_Border }?, element insideH { w_CT_Border }?, element insideV { w_CT_Border }?, element tl2br { w_CT_Border }?, element tr2bl { w_CT_Border }? w_CT_TcMar = element top { w_CT_TblWidth }?, element start { w_CT_TblWidth }?, element left { w_CT_TblWidth }?, element bottom { w_CT_TblWidth }?, element end { w_CT_TblWidth }?, element right { w_CT_TblWidth }? w_ST_Merge = string "continue" | string "restart" w_CT_VMerge = attribute w:val { w_ST_Merge }? w_CT_HMerge = attribute w:val { w_ST_Merge }? w_CT_TcPrBase = element cnfStyle { w_CT_Cnf }?, element tcW { w_CT_TblWidth }?, element gridSpan { w_CT_DecimalNumber }?, element hMerge { w_CT_HMerge }?, element vMerge { w_CT_VMerge }?, element tcBorders { w_CT_TcBorders }?, element shd { w_CT_Shd }?, element noWrap { w_CT_OnOff }?, element tcMar { w_CT_TcMar }?, element textDirection { w_CT_TextDirection }?, element tcFitText { w_CT_OnOff }?, element vAlign { w_CT_VerticalJc }?, element hideMark { w_CT_OnOff }?, element headers { w_CT_Headers }? w_CT_TcPr = w_CT_TcPrInner, element tcPrChange { w_CT_TcPrChange }? w_CT_TcPrInner = w_CT_TcPrBase, w_EG_CellMarkupElements? w_CT_Tc = attribute w:id { s_ST_String }?, element tcPr { w_CT_TcPr }?, w_EG_BlockLevelElts+ w_ST_Cnf = xsd:string { length = "12" pattern = "[01]*" } w_CT_Cnf = attribute w:val { w_ST_Cnf }?, attribute w:firstRow { s_ST_OnOff }?, attribute w:lastRow { s_ST_OnOff }?, attribute w:firstColumn { s_ST_OnOff }?, attribute w:lastColumn { s_ST_OnOff }?, attribute w:oddVBand { s_ST_OnOff }?, attribute w:evenVBand { s_ST_OnOff }?, attribute w:oddHBand { s_ST_OnOff }?, attribute w:evenHBand { s_ST_OnOff }?, attribute w:firstRowFirstColumn { s_ST_OnOff }?, attribute w:firstRowLastColumn { s_ST_OnOff }?, attribute w:lastRowFirstColumn { s_ST_OnOff }?, attribute w:lastRowLastColumn { s_ST_OnOff }? w_CT_Headers = element header { w_CT_String }* w_CT_TrPrBase = (element cnfStyle { w_CT_Cnf }? | element divId { w_CT_DecimalNumber }? | element gridBefore { w_CT_DecimalNumber }? | element gridAfter { w_CT_DecimalNumber }? | element wBefore { w_CT_TblWidth }? | element wAfter { w_CT_TblWidth }? | element cantSplit { w_CT_OnOff }? | element trHeight { w_CT_Height }? | element tblHeader { w_CT_OnOff }? | element tblCellSpacing { w_CT_TblWidth }? | element jc { w_CT_JcTable }? | element hidden { w_CT_OnOff }?)+ w_CT_TrPr = w_CT_TrPrBase, element ins { w_CT_TrackChange }?, element del { w_CT_TrackChange }?, element trPrChange { w_CT_TrPrChange }? w_CT_Row = attribute w:rsidRPr { w_ST_LongHexNumber }?, attribute w:rsidR { w_ST_LongHexNumber }?, attribute w:rsidDel { w_ST_LongHexNumber }?, attribute w:rsidTr { w_ST_LongHexNumber }?, element tblPrEx { w_CT_TblPrEx }?, element trPr { w_CT_TrPr }?, w_EG_ContentCellContent* w_ST_TblLayoutType = string "fixed" | string "autofit" w_CT_TblLayoutType = attribute w:type { w_ST_TblLayoutType }? w_ST_TblOverlap = string "never" | string "overlap" w_CT_TblOverlap = attribute w:val { w_ST_TblOverlap } w_CT_TblPPr = attribute w:leftFromText { s_ST_TwipsMeasure }?, attribute w:rightFromText { s_ST_TwipsMeasure }?, attribute w:topFromText { s_ST_TwipsMeasure }?, attribute w:bottomFromText { s_ST_TwipsMeasure }?, attribute w:vertAnchor { w_ST_VAnchor }?, attribute w:horzAnchor { w_ST_HAnchor }?, attribute w:tblpXSpec { s_ST_XAlign }?, attribute w:tblpX { w_ST_SignedTwipsMeasure }?, attribute w:tblpYSpec { s_ST_YAlign }?, attribute w:tblpY { w_ST_SignedTwipsMeasure }? w_CT_TblCellMar = element top { w_CT_TblWidth }?, element start { w_CT_TblWidth }?, element left { w_CT_TblWidth }?, element bottom { w_CT_TblWidth }?, element end { w_CT_TblWidth }?, element right { w_CT_TblWidth }? w_CT_TblBorders = element top { w_CT_Border }?, element start { w_CT_Border }?, element left { w_CT_Border }?, element bottom { w_CT_Border }?, element end { w_CT_Border }?, element right { w_CT_Border }?, element insideH { w_CT_Border }?, element insideV { w_CT_Border }? w_CT_TblPrBase = element tblStyle { w_CT_String }?, element tblpPr { w_CT_TblPPr }?, element tblOverlap { w_CT_TblOverlap }?, element bidiVisual { w_CT_OnOff }?, element tblStyleRowBandSize { w_CT_DecimalNumber }?, element tblStyleColBandSize { w_CT_DecimalNumber }?, element tblW { w_CT_TblWidth }?, element jc { w_CT_JcTable }?, element tblCellSpacing { w_CT_TblWidth }?, element tblInd { w_CT_TblWidth }?, element tblBorders { w_CT_TblBorders }?, element shd { w_CT_Shd }?, element tblLayout { w_CT_TblLayoutType }?, element tblCellMar { w_CT_TblCellMar }?, element tblLook { w_CT_TblLook }?, element tblCaption { w_CT_String }?, element tblDescription { w_CT_String }? w_CT_TblPr = w_CT_TblPrBase, element tblPrChange { w_CT_TblPrChange }? w_CT_TblPrExBase = element tblW { w_CT_TblWidth }?, element jc { w_CT_JcTable }?, element tblCellSpacing { w_CT_TblWidth }?, element tblInd { w_CT_TblWidth }?, element tblBorders { w_CT_TblBorders }?, element shd { w_CT_Shd }?, element tblLayout { w_CT_TblLayoutType }?, element tblCellMar { w_CT_TblCellMar }?, element tblLook { w_CT_TblLook }? w_CT_TblPrEx = w_CT_TblPrExBase, element tblPrExChange { w_CT_TblPrExChange }? w_CT_Tbl = w_EG_RangeMarkupElements*, element tblPr { w_CT_TblPr }, element tblGrid { w_CT_TblGrid }, w_EG_ContentRowContent* w_CT_TblLook = attribute w:firstRow { s_ST_OnOff }?, attribute w:lastRow { s_ST_OnOff }?, attribute w:firstColumn { s_ST_OnOff }?, attribute w:lastColumn { s_ST_OnOff }?, attribute w:noHBand { s_ST_OnOff }?, attribute w:noVBand { s_ST_OnOff }?, attribute w:val { w_ST_ShortHexNumber }? w_ST_FtnPos = string "pageBottom" | string "beneathText" | string "sectEnd" | string "docEnd" w_CT_FtnPos = attribute w:val { w_ST_FtnPos } w_ST_EdnPos = string "sectEnd" | string "docEnd" w_CT_EdnPos = attribute w:val { w_ST_EdnPos } w_CT_NumFmt = attribute w:val { w_ST_NumberFormat }, attribute w:format { s_ST_String }? w_ST_RestartNumber = string "continuous" | string "eachSect" | string "eachPage" w_CT_NumRestart = attribute w:val { w_ST_RestartNumber } w_CT_FtnEdnRef = attribute w:customMarkFollows { s_ST_OnOff }?, attribute w:id { w_ST_DecimalNumber } w_CT_FtnEdnSepRef = attribute w:id { w_ST_DecimalNumber } w_CT_FtnEdn = attribute w:type { w_ST_FtnEdn }?, attribute w:id { w_ST_DecimalNumber }, w_EG_BlockLevelElts+ w_EG_FtnEdnNumProps = element numStart { w_CT_DecimalNumber }?, element numRestart { w_CT_NumRestart }? w_CT_FtnProps = element pos { w_CT_FtnPos }?, element numFmt { w_CT_NumFmt }?, w_EG_FtnEdnNumProps? w_CT_EdnProps = element pos { w_CT_EdnPos }?, element numFmt { w_CT_NumFmt }?, w_EG_FtnEdnNumProps? w_CT_FtnDocProps = w_CT_FtnProps, element footnote { w_CT_FtnEdnSepRef }* w_CT_EdnDocProps = w_CT_EdnProps, element endnote { w_CT_FtnEdnSepRef }* w_CT_RecipientData = element active { w_CT_OnOff }?, element column { w_CT_DecimalNumber }, element uniqueTag { w_CT_Base64Binary } w_CT_Base64Binary = attribute w:val { xsd:base64Binary } w_CT_Recipients = element recipientData { w_CT_RecipientData }+ w_recipients = element recipients { w_CT_Recipients } w_CT_OdsoFieldMapData = element type { w_CT_MailMergeOdsoFMDFieldType }?, element name { w_CT_String }?, element mappedName { w_CT_String }?, element column { w_CT_DecimalNumber }?, element lid { w_CT_Lang }?, element dynamicAddress { w_CT_OnOff }? w_ST_MailMergeSourceType = string "database" | string "addressBook" | string "document1" | string "document2" | string "text" | string "email" | string "native" | string "legacy" | string "master" w_CT_MailMergeSourceType = attribute w:val { w_ST_MailMergeSourceType } w_CT_Odso = element udl { w_CT_String }?, element table { w_CT_String }?, element src { w_CT_Rel }?, element colDelim { w_CT_DecimalNumber }?, element type { w_CT_MailMergeSourceType }?, element fHdr { w_CT_OnOff }?, element fieldMapData { w_CT_OdsoFieldMapData }*, element recipientData { w_CT_Rel }* w_CT_MailMerge = element mainDocumentType { w_CT_MailMergeDocType }, element linkToQuery { w_CT_OnOff }?, element dataType { w_CT_MailMergeDataType }, element connectString { w_CT_String }?, element query { w_CT_String }?, element dataSource { w_CT_Rel }?, element headerSource { w_CT_Rel }?, element doNotSuppressBlankLines { w_CT_OnOff }?, element destination { w_CT_MailMergeDest }?, element addressFieldName { w_CT_String }?, element mailSubject { w_CT_String }?, element mailAsAttachment { w_CT_OnOff }?, element viewMergedData { w_CT_OnOff }?, element activeRecord { w_CT_DecimalNumber }?, element checkErrors { w_CT_DecimalNumber }?, element odso { w_CT_Odso }? w_ST_TargetScreenSz = string "544x376" | string "640x480" | string "720x512" | string "800x600" | string "1024x768" | string "1152x882" | string "1152x900" | string "1280x1024" | string "1600x1200" | string "1800x1440" | string "1920x1200" w_CT_TargetScreenSz = attribute w:val { w_ST_TargetScreenSz } w_CT_Compat = element useSingleBorderforContiguousCells { w_CT_OnOff }?, element wpJustification { w_CT_OnOff }?, element noTabHangInd { w_CT_OnOff }?, element noLeading { w_CT_OnOff }?, element spaceForUL { w_CT_OnOff }?, element noColumnBalance { w_CT_OnOff }?, element balanceSingleByteDoubleByteWidth { w_CT_OnOff }?, element noExtraLineSpacing { w_CT_OnOff }?, element doNotLeaveBackslashAlone { w_CT_OnOff }?, element ulTrailSpace { w_CT_OnOff }?, element doNotExpandShiftReturn { w_CT_OnOff }?, element spacingInWholePoints { w_CT_OnOff }?, element lineWrapLikeWord6 { w_CT_OnOff }?, element printBodyTextBeforeHeader { w_CT_OnOff }?, element printColBlack { w_CT_OnOff }?, element wpSpaceWidth { w_CT_OnOff }?, element showBreaksInFrames { w_CT_OnOff }?, element subFontBySize { w_CT_OnOff }?, element suppressBottomSpacing { w_CT_OnOff }?, element suppressTopSpacing { w_CT_OnOff }?, element suppressSpacingAtTopOfPage { w_CT_OnOff }?, element suppressTopSpacingWP { w_CT_OnOff }?, element suppressSpBfAfterPgBrk { w_CT_OnOff }?, element swapBordersFacingPages { w_CT_OnOff }?, element convMailMergeEsc { w_CT_OnOff }?, element truncateFontHeightsLikeWP6 { w_CT_OnOff }?, element mwSmallCaps { w_CT_OnOff }?, element usePrinterMetrics { w_CT_OnOff }?, element doNotSuppressParagraphBorders { w_CT_OnOff }?, element wrapTrailSpaces { w_CT_OnOff }?, element footnoteLayoutLikeWW8 { w_CT_OnOff }?, element shapeLayoutLikeWW8 { w_CT_OnOff }?, element alignTablesRowByRow { w_CT_OnOff }?, element forgetLastTabAlignment { w_CT_OnOff }?, element adjustLineHeightInTable { w_CT_OnOff }?, element autoSpaceLikeWord95 { w_CT_OnOff }?, element noSpaceRaiseLower { w_CT_OnOff }?, element doNotUseHTMLParagraphAutoSpacing { w_CT_OnOff }?, element layoutRawTableWidth { w_CT_OnOff }?, element layoutTableRowsApart { w_CT_OnOff }?, element useWord97LineBreakRules { w_CT_OnOff }?, element doNotBreakWrappedTables { w_CT_OnOff }?, element doNotSnapToGridInCell { w_CT_OnOff }?, element selectFldWithFirstOrLastChar { w_CT_OnOff }?, element applyBreakingRules { w_CT_OnOff }?, element doNotWrapTextWithPunct { w_CT_OnOff }?, element doNotUseEastAsianBreakRules { w_CT_OnOff }?, element useWord2002TableStyleRules { w_CT_OnOff }?, element growAutofit { w_CT_OnOff }?, element useFELayout { w_CT_OnOff }?, element useNormalStyleForList { w_CT_OnOff }?, element doNotUseIndentAsNumberingTabStop { w_CT_OnOff }?, element useAltKinsokuLineBreakRules { w_CT_OnOff }?, element allowSpaceOfSameStyleInTable { w_CT_OnOff }?, element doNotSuppressIndentation { w_CT_OnOff }?, element doNotAutofitConstrainedTables { w_CT_OnOff }?, element autofitToFirstFixedWidthCell { w_CT_OnOff }?, element underlineTabInNumList { w_CT_OnOff }?, element displayHangulFixedWidth { w_CT_OnOff }?, element splitPgBreakAndParaMark { w_CT_OnOff }?, element doNotVertAlignCellWithSp { w_CT_OnOff }?, element doNotBreakConstrainedForcedTable { w_CT_OnOff }?, element doNotVertAlignInTxbx { w_CT_OnOff }?, element useAnsiKerningPairs { w_CT_OnOff }?, element cachedColBalance { w_CT_OnOff }?, element compatSetting { w_CT_CompatSetting }* w_CT_CompatSetting = attribute w:name { s_ST_String }?, attribute w:uri { s_ST_String }?, attribute w:val { s_ST_String }? w_CT_DocVar = attribute w:name { s_ST_String }, attribute w:val { s_ST_String } w_CT_DocVars = element docVar { w_CT_DocVar }* w_CT_DocRsids = element rsidRoot { w_CT_LongHexNumber }?, element rsid { w_CT_LongHexNumber }* w_ST_CharacterSpacing = string "doNotCompress" | string "compressPunctuation" | string "compressPunctuationAndJapaneseKana" w_CT_CharacterSpacing = attribute w:val { w_ST_CharacterSpacing } w_CT_SaveThroughXslt = r_id?, attribute w:solutionID { s_ST_String }? w_CT_RPrDefault = element rPr { w_CT_RPr }? w_CT_PPrDefault = element pPr { w_CT_PPrGeneral }? w_CT_DocDefaults = element rPrDefault { w_CT_RPrDefault }?, element pPrDefault { w_CT_PPrDefault }? w_ST_WmlColorSchemeIndex = string "dark1" | string "light1" | string "dark2" | string "light2" | string "accent1" | string "accent2" | string "accent3" | string "accent4" | string "accent5" | string "accent6" | string "hyperlink" | string "followedHyperlink" w_CT_ColorSchemeMapping = attribute w:bg1 { w_ST_WmlColorSchemeIndex }?, attribute w:t1 { w_ST_WmlColorSchemeIndex }?, attribute w:bg2 { w_ST_WmlColorSchemeIndex }?, attribute w:t2 { w_ST_WmlColorSchemeIndex }?, attribute w:accent1 { w_ST_WmlColorSchemeIndex }?, attribute w:accent2 { w_ST_WmlColorSchemeIndex }?, attribute w:accent3 { w_ST_WmlColorSchemeIndex }?, attribute w:accent4 { w_ST_WmlColorSchemeIndex }?, attribute w:accent5 { w_ST_WmlColorSchemeIndex }?, attribute w:accent6 { w_ST_WmlColorSchemeIndex }?, attribute w:hyperlink { w_ST_WmlColorSchemeIndex }?, attribute w:followedHyperlink { w_ST_WmlColorSchemeIndex }? w_CT_ReadingModeInkLockDown = attribute w:actualPg { s_ST_OnOff }, attribute w:w { w_ST_PixelsMeasure }, attribute w:h { w_ST_PixelsMeasure }, attribute w:fontSz { w_ST_DecimalNumberOrPercent } w_CT_WriteProtection = attribute w:recommended { s_ST_OnOff }?, w_AG_Password, w_AG_TransitionalPassword w_CT_Settings = element writeProtection { w_CT_WriteProtection }?, element view { w_CT_View }?, element zoom { w_CT_Zoom }?, element removePersonalInformation { w_CT_OnOff }?, element removeDateAndTime { w_CT_OnOff }?, element doNotDisplayPageBoundaries { w_CT_OnOff }?, element displayBackgroundShape { w_CT_OnOff }?, element printPostScriptOverText { w_CT_OnOff }?, element printFractionalCharacterWidth { w_CT_OnOff }?, element printFormsData { w_CT_OnOff }?, element embedTrueTypeFonts { w_CT_OnOff }?, element embedSystemFonts { w_CT_OnOff }?, element saveSubsetFonts { w_CT_OnOff }?, element saveFormsData { w_CT_OnOff }?, element mirrorMargins { w_CT_OnOff }?, element alignBordersAndEdges { w_CT_OnOff }?, element bordersDoNotSurroundHeader { w_CT_OnOff }?, element bordersDoNotSurroundFooter { w_CT_OnOff }?, element gutterAtTop { w_CT_OnOff }?, element hideSpellingErrors { w_CT_OnOff }?, element hideGrammaticalErrors { w_CT_OnOff }?, element activeWritingStyle { w_CT_WritingStyle }*, element proofState { w_CT_Proof }?, element formsDesign { w_CT_OnOff }?, element attachedTemplate { w_CT_Rel }?, element linkStyles { w_CT_OnOff }?, element stylePaneFormatFilter { w_CT_StylePaneFilter }?, element stylePaneSortMethod { w_CT_StyleSort }?, element documentType { w_CT_DocType }?, element mailMerge { w_CT_MailMerge }?, element revisionView { w_CT_TrackChangesView }?, element trackRevisions { w_CT_OnOff }?, element doNotTrackMoves { w_CT_OnOff }?, element doNotTrackFormatting { w_CT_OnOff }?, element documentProtection { w_CT_DocProtect }?, element autoFormatOverride { w_CT_OnOff }?, element styleLockTheme { w_CT_OnOff }?, element styleLockQFSet { w_CT_OnOff }?, element defaultTabStop { w_CT_TwipsMeasure }?, element autoHyphenation { w_CT_OnOff }?, element consecutiveHyphenLimit { w_CT_DecimalNumber }?, element hyphenationZone { w_CT_TwipsMeasure }?, element doNotHyphenateCaps { w_CT_OnOff }?, element showEnvelope { w_CT_OnOff }?, element summaryLength { w_CT_DecimalNumberOrPrecent }?, element clickAndTypeStyle { w_CT_String }?, element defaultTableStyle { w_CT_String }?, element evenAndOddHeaders { w_CT_OnOff }?, element bookFoldRevPrinting { w_CT_OnOff }?, element bookFoldPrinting { w_CT_OnOff }?, element bookFoldPrintingSheets { w_CT_DecimalNumber }?, element drawingGridHorizontalSpacing { w_CT_TwipsMeasure }?, element drawingGridVerticalSpacing { w_CT_TwipsMeasure }?, element displayHorizontalDrawingGridEvery { w_CT_DecimalNumber }?, element displayVerticalDrawingGridEvery { w_CT_DecimalNumber }?, element doNotUseMarginsForDrawingGridOrigin { w_CT_OnOff }?, element drawingGridHorizontalOrigin { w_CT_TwipsMeasure }?, element drawingGridVerticalOrigin { w_CT_TwipsMeasure }?, element doNotShadeFormData { w_CT_OnOff }?, element noPunctuationKerning { w_CT_OnOff }?, element characterSpacingControl { w_CT_CharacterSpacing }?, element printTwoOnOne { w_CT_OnOff }?, element strictFirstAndLastChars { w_CT_OnOff }?, element noLineBreaksAfter { w_CT_Kinsoku }?, element noLineBreaksBefore { w_CT_Kinsoku }?, element savePreviewPicture { w_CT_OnOff }?, element doNotValidateAgainstSchema { w_CT_OnOff }?, element saveInvalidXml { w_CT_OnOff }?, element ignoreMixedContent { w_CT_OnOff }?, element alwaysShowPlaceholderText { w_CT_OnOff }?, element doNotDemarcateInvalidXml { w_CT_OnOff }?, element saveXmlDataOnly { w_CT_OnOff }?, element useXSLTWhenSaving { w_CT_OnOff }?, element saveThroughXslt { w_CT_SaveThroughXslt }?, element showXMLTags { w_CT_OnOff }?, element alwaysMergeEmptyNamespace { w_CT_OnOff }?, element updateFields { w_CT_OnOff }?, element hdrShapeDefaults { w_CT_ShapeDefaults }?, element footnotePr { w_CT_FtnDocProps }?, element endnotePr { w_CT_EdnDocProps }?, element compat { w_CT_Compat }?, element docVars { w_CT_DocVars }?, element rsids { w_CT_DocRsids }?, m_mathPr?, element attachedSchema { w_CT_String }*, element themeFontLang { w_CT_Language }?, element clrSchemeMapping { w_CT_ColorSchemeMapping }?, element doNotIncludeSubdocsInStats { w_CT_OnOff }?, element doNotAutoCompressPictures { w_CT_OnOff }?, element forceUpgrade { w_CT_Empty }?, element captions { w_CT_Captions }?, element readModeInkLockDown { w_CT_ReadingModeInkLockDown }?, element smartTagType { w_CT_SmartTagType }*, sl_schemaLibrary?, element shapeDefaults { w_CT_ShapeDefaults }?, element doNotEmbedSmartTags { w_CT_OnOff }?, element decimalSymbol { w_CT_String }?, element listSeparator { w_CT_String }? w_CT_StyleSort = attribute w:val { w_ST_StyleSort } w_CT_StylePaneFilter = attribute w:allStyles { s_ST_OnOff }?, attribute w:customStyles { s_ST_OnOff }?, attribute w:latentStyles { s_ST_OnOff }?, attribute w:stylesInUse { s_ST_OnOff }?, attribute w:headingStyles { s_ST_OnOff }?, attribute w:numberingStyles { s_ST_OnOff }?, attribute w:tableStyles { s_ST_OnOff }?, attribute w:directFormattingOnRuns { s_ST_OnOff }?, attribute w:directFormattingOnParagraphs { s_ST_OnOff }?, attribute w:directFormattingOnNumbering { s_ST_OnOff }?, attribute w:directFormattingOnTables { s_ST_OnOff }?, attribute w:clearFormatting { s_ST_OnOff }?, attribute w:top3HeadingStyles { s_ST_OnOff }?, attribute w:visibleStyles { s_ST_OnOff }?, attribute w:alternateStyleNames { s_ST_OnOff }?, attribute w:val { w_ST_ShortHexNumber }? w_ST_StyleSort = string "name" | string "priority" | string "default" | string "font" | string "basedOn" | string "type" | string "0000" | string "0001" | string "0002" | string "0003" | string "0004" | string "0005" w_CT_WebSettings = element frameset { w_CT_Frameset }?, element divs { w_CT_Divs }?, element encoding { w_CT_String }?, element optimizeForBrowser { w_CT_OptimizeForBrowser }?, element relyOnVML { w_CT_OnOff }?, element allowPNG { w_CT_OnOff }?, element doNotRelyOnCSS { w_CT_OnOff }?, element doNotSaveAsSingleFile { w_CT_OnOff }?, element doNotOrganizeInFolder { w_CT_OnOff }?, element doNotUseLongFileNames { w_CT_OnOff }?, element pixelsPerInch { w_CT_DecimalNumber }?, element targetScreenSz { w_CT_TargetScreenSz }?, element saveSmartTagsAsXml { w_CT_OnOff }? w_ST_FrameScrollbar = string "on" | string "off" | string "auto" w_CT_FrameScrollbar = attribute w:val { w_ST_FrameScrollbar } w_CT_OptimizeForBrowser = w_CT_OnOff, attribute w:target { s_ST_String }? w_CT_Frame = element sz { w_CT_String }?, element name { w_CT_String }?, element title { w_CT_String }?, element longDesc { w_CT_Rel }?, element sourceFileName { w_CT_Rel }?, element marW { w_CT_PixelsMeasure }?, element marH { w_CT_PixelsMeasure }?, element scrollbar { w_CT_FrameScrollbar }?, element noResizeAllowed { w_CT_OnOff }?, element linkedToFile { w_CT_OnOff }? w_ST_FrameLayout = string "rows" | string "cols" | string "none" w_CT_FrameLayout = attribute w:val { w_ST_FrameLayout } w_CT_FramesetSplitbar = element w { w_CT_TwipsMeasure }?, element color { w_CT_Color }?, element noBorder { w_CT_OnOff }?, element flatBorders { w_CT_OnOff }? w_CT_Frameset = element sz { w_CT_String }?, element framesetSplitbar { w_CT_FramesetSplitbar }?, element frameLayout { w_CT_FrameLayout }?, element title { w_CT_String }?, (element frameset { w_CT_Frameset }* | element frame { w_CT_Frame }*)* w_CT_NumPicBullet = attribute w:numPicBulletId { w_ST_DecimalNumber }, (element pict { w_CT_Picture } | element drawing { w_CT_Drawing }) w_ST_LevelSuffix = string "tab" | string "space" | string "nothing" w_CT_LevelSuffix = attribute w:val { w_ST_LevelSuffix } w_CT_LevelText = attribute w:val { s_ST_String }?, attribute w:null { s_ST_OnOff }? w_CT_LvlLegacy = attribute w:legacy { s_ST_OnOff }?, attribute w:legacySpace { s_ST_TwipsMeasure }?, attribute w:legacyIndent { w_ST_SignedTwipsMeasure }? w_CT_Lvl = attribute w:ilvl { w_ST_DecimalNumber }, attribute w:tplc { w_ST_LongHexNumber }?, attribute w:tentative { s_ST_OnOff }?, element start { w_CT_DecimalNumber }?, element numFmt { w_CT_NumFmt }?, element lvlRestart { w_CT_DecimalNumber }?, element pStyle { w_CT_String }?, element isLgl { w_CT_OnOff }?, element suff { w_CT_LevelSuffix }?, element lvlText { w_CT_LevelText }?, element lvlPicBulletId { w_CT_DecimalNumber }?, element legacy { w_CT_LvlLegacy }?, element lvlJc { w_CT_Jc }?, element pPr { w_CT_PPrGeneral }?, element rPr { w_CT_RPr }? w_ST_MultiLevelType = string "singleLevel" | string "multilevel" | string "hybridMultilevel" w_CT_MultiLevelType = attribute w:val { w_ST_MultiLevelType } w_CT_AbstractNum = attribute w:abstractNumId { w_ST_DecimalNumber }, element nsid { w_CT_LongHexNumber }?, element multiLevelType { w_CT_MultiLevelType }?, element tmpl { w_CT_LongHexNumber }?, element name { w_CT_String }?, element styleLink { w_CT_String }?, element numStyleLink { w_CT_String }?, element lvl { w_CT_Lvl }* w_CT_NumLvl = attribute w:ilvl { w_ST_DecimalNumber }, element startOverride { w_CT_DecimalNumber }?, element lvl { w_CT_Lvl }? w_CT_Num = attribute w:numId { w_ST_DecimalNumber }, element abstractNumId { w_CT_DecimalNumber }, element lvlOverride { w_CT_NumLvl }* w_CT_Numbering = element numPicBullet { w_CT_NumPicBullet }*, element abstractNum { w_CT_AbstractNum }*, element num { w_CT_Num }*, element numIdMacAtCleanup { w_CT_DecimalNumber }? w_ST_TblStyleOverrideType = string "wholeTable" | string "firstRow" | string "lastRow" | string "firstCol" | string "lastCol" | string "band1Vert" | string "band2Vert" | string "band1Horz" | string "band2Horz" | string "neCell" | string "nwCell" | string "seCell" | string "swCell" w_CT_TblStylePr = attribute w:type { w_ST_TblStyleOverrideType }, element pPr { w_CT_PPrGeneral }?, element rPr { w_CT_RPr }?, element tblPr { w_CT_TblPrBase }?, element trPr { w_CT_TrPr }?, element tcPr { w_CT_TcPr }? w_ST_StyleType = string "paragraph" | string "character" | string "table" | string "numbering" w_CT_Style = attribute w:type { w_ST_StyleType }?, attribute w:styleId { s_ST_String }?, attribute w:default { s_ST_OnOff }?, attribute w:customStyle { s_ST_OnOff }?, element name { w_CT_String }?, element aliases { w_CT_String }?, element basedOn { w_CT_String }?, element next { w_CT_String }?, element link { w_CT_String }?, element autoRedefine { w_CT_OnOff }?, element hidden { w_CT_OnOff }?, element uiPriority { w_CT_DecimalNumber }?, element semiHidden { w_CT_OnOff }?, element unhideWhenUsed { w_CT_OnOff }?, element qFormat { w_CT_OnOff }?, element locked { w_CT_OnOff }?, element personal { w_CT_OnOff }?, element personalCompose { w_CT_OnOff }?, element personalReply { w_CT_OnOff }?, element rsid { w_CT_LongHexNumber }?, element pPr { w_CT_PPrGeneral }?, element rPr { w_CT_RPr }?, element tblPr { w_CT_TblPrBase }?, element trPr { w_CT_TrPr }?, element tcPr { w_CT_TcPr }?, element tblStylePr { w_CT_TblStylePr }* w_CT_LsdException = attribute w:name { s_ST_String }, attribute w:locked { s_ST_OnOff }?, attribute w:uiPriority { w_ST_DecimalNumber }?, attribute w:semiHidden { s_ST_OnOff }?, attribute w:unhideWhenUsed { s_ST_OnOff }?, attribute w:qFormat { s_ST_OnOff }? w_CT_LatentStyles = attribute w:defLockedState { s_ST_OnOff }?, attribute w:defUIPriority { w_ST_DecimalNumber }?, attribute w:defSemiHidden { s_ST_OnOff }?, attribute w:defUnhideWhenUsed { s_ST_OnOff }?, attribute w:defQFormat { s_ST_OnOff }?, attribute w:count { w_ST_DecimalNumber }?, element lsdException { w_CT_LsdException }* w_CT_Styles = element docDefaults { w_CT_DocDefaults }?, element latentStyles { w_CT_LatentStyles }?, element style { w_CT_Style }* w_CT_Panose = attribute w:val { s_ST_Panose } w_ST_FontFamily = string "decorative" | string "modern" | string "roman" | string "script" | string "swiss" | string "auto" w_CT_FontFamily = attribute w:val { w_ST_FontFamily } w_ST_Pitch = string "fixed" | string "variable" | string "default" w_CT_Pitch = attribute w:val { w_ST_Pitch } w_CT_FontSig = attribute w:usb0 { w_ST_LongHexNumber }, attribute w:usb1 { w_ST_LongHexNumber }, attribute w:usb2 { w_ST_LongHexNumber }, attribute w:usb3 { w_ST_LongHexNumber }, attribute w:csb0 { w_ST_LongHexNumber }, attribute w:csb1 { w_ST_LongHexNumber } w_CT_FontRel = w_CT_Rel, attribute w:fontKey { s_ST_Guid }?, attribute w:subsetted { s_ST_OnOff }? w_CT_Font = attribute w:name { s_ST_String }, element altName { w_CT_String }?, element panose1 { w_CT_Panose }?, element charset { w_CT_Charset }?, element family { w_CT_FontFamily }?, element notTrueType { w_CT_OnOff }?, element pitch { w_CT_Pitch }?, element sig { w_CT_FontSig }?, element embedRegular { w_CT_FontRel }?, element embedBold { w_CT_FontRel }?, element embedItalic { w_CT_FontRel }?, element embedBoldItalic { w_CT_FontRel }? w_CT_FontsList = element font { w_CT_Font }* w_CT_DivBdr = element top { w_CT_Border }?, element left { w_CT_Border }?, element bottom { w_CT_Border }?, element right { w_CT_Border }? w_CT_Div = attribute w:id { w_ST_DecimalNumber }, element blockQuote { w_CT_OnOff }?, element bodyDiv { w_CT_OnOff }?, element marLeft { w_CT_SignedTwipsMeasure }, element marRight { w_CT_SignedTwipsMeasure }, element marTop { w_CT_SignedTwipsMeasure }, element marBottom { w_CT_SignedTwipsMeasure }, element divBdr { w_CT_DivBdr }?, element divsChild { w_CT_Divs }* w_CT_Divs = element div { w_CT_Div }+ w_CT_TxbxContent = w_EG_BlockLevelElts+ w_txbxContent = element txbxContent { w_CT_TxbxContent } w_EG_MathContent = m_oMathPara | m_oMath w_EG_BlockLevelChunkElts = w_EG_ContentBlockContent* w_EG_BlockLevelElts = w_EG_BlockLevelChunkElts* | element altChunk { w_CT_AltChunk }* w_EG_RunLevelElts = element proofErr { w_CT_ProofErr }? | element permStart { w_CT_PermStart }? | element permEnd { w_CT_Perm }? | w_EG_RangeMarkupElements* | element ins { w_CT_RunTrackChange }? | element del { w_CT_RunTrackChange }? | element moveFrom { w_CT_RunTrackChange } | element moveTo { w_CT_RunTrackChange } | w_EG_MathContent* w_CT_Body = w_EG_BlockLevelElts*, element sectPr { w_CT_SectPr }? w_CT_ShapeDefaults = (w_any_vml_office*)+ w_CT_Comments = element comment { w_CT_Comment }* w_comments = element comments { w_CT_Comments } w_CT_Footnotes = element footnote { w_CT_FtnEdn }* w_footnotes = element footnotes { w_CT_Footnotes } w_CT_Endnotes = element endnote { w_CT_FtnEdn }* w_endnotes = element endnotes { w_CT_Endnotes } w_hdr = element hdr { w_CT_HdrFtr } w_ftr = element ftr { w_CT_HdrFtr } w_CT_SmartTagType = attribute w:namespaceuri { s_ST_String }?, attribute w:name { s_ST_String }?, attribute w:url { s_ST_String }? w_ST_ThemeColor = string "dark1" | string "light1" | string "dark2" | string "light2" | string "accent1" | string "accent2" | string "accent3" | string "accent4" | string "accent5" | string "accent6" | string "hyperlink" | string "followedHyperlink" | string "none" | string "background1" | string "text1" | string "background2" | string "text2" w_ST_DocPartBehavior = string "content" | string "p" | string "pg" w_CT_DocPartBehavior = attribute w:val { w_ST_DocPartBehavior } w_CT_DocPartBehaviors = element behavior { w_CT_DocPartBehavior }+ w_ST_DocPartType = string "none" | string "normal" | string "autoExp" | string "toolbar" | string "speller" | string "formFld" | string "bbPlcHdr" w_CT_DocPartType = attribute w:val { w_ST_DocPartType } w_CT_DocPartTypes = attribute w:all { s_ST_OnOff }?, (element type { w_CT_DocPartType }+) w_ST_DocPartGallery = string "placeholder" | string "any" | string "default" | string "docParts" | string "coverPg" | string "eq" | string "ftrs" | string "hdrs" | string "pgNum" | string "tbls" | string "watermarks" | string "autoTxt" | string "txtBox" | string "pgNumT" | string "pgNumB" | string "pgNumMargins" | string "tblOfContents" | string "bib" | string "custQuickParts" | string "custCoverPg" | string "custEq" | string "custFtrs" | string "custHdrs" | string "custPgNum" | string "custTbls" | string "custWatermarks" | string "custAutoTxt" | string "custTxtBox" | string "custPgNumT" | string "custPgNumB" | string "custPgNumMargins" | string "custTblOfContents" | string "custBib" | string "custom1" | string "custom2" | string "custom3" | string "custom4" | string "custom5" w_CT_DocPartGallery = attribute w:val { w_ST_DocPartGallery } w_CT_DocPartCategory = element name { w_CT_String }, element gallery { w_CT_DocPartGallery } w_CT_DocPartName = attribute w:val { s_ST_String }, attribute w:decorated { s_ST_OnOff }? w_CT_DocPartPr = element name { w_CT_DocPartName }& element style { w_CT_String }?& element category { w_CT_DocPartCategory }?& element types { w_CT_DocPartTypes }?& element behaviors { w_CT_DocPartBehaviors }?& element description { w_CT_String }?& element guid { w_CT_Guid }? w_CT_DocPart = element docPartPr { w_CT_DocPartPr }?, element docPartBody { w_CT_Body }? w_CT_DocParts = element docPart { w_CT_DocPart }+ w_settings = element settings { w_CT_Settings } w_webSettings = element webSettings { w_CT_WebSettings } w_fonts = element fonts { w_CT_FontsList } w_numbering = element numbering { w_CT_Numbering } w_styles = element styles { w_CT_Styles } w_ST_CaptionPos = string "above" | string "below" | string "left" | string "right" w_CT_Caption = attribute w:name { s_ST_String }, attribute w:pos { w_ST_CaptionPos }?, attribute w:chapNum { s_ST_OnOff }?, attribute w:heading { w_ST_DecimalNumber }?, attribute w:noLabel { s_ST_OnOff }?, attribute w:numFmt { w_ST_NumberFormat }?, attribute w:sep { w_ST_ChapterSep }? w_CT_AutoCaption = attribute w:name { s_ST_String }, attribute w:caption { s_ST_String } w_CT_AutoCaptions = element autoCaption { w_CT_AutoCaption }+ w_CT_Captions = element caption { w_CT_Caption }+, element autoCaptions { w_CT_AutoCaptions }? w_CT_DocumentBase = element background { w_CT_Background }? w_CT_Document = w_CT_DocumentBase, element body { w_CT_Body }?, attribute w:conformance { s_ST_ConformanceClass }? w_CT_GlossaryDocument = w_CT_DocumentBase, element docParts { w_CT_DocParts }? w_document = element document { w_CT_Document } w_glossaryDocument = element glossaryDocument { w_CT_GlossaryDocument } w_any_vml_office = o_shapedefaults | o_shapelayout | o_signatureline | o_ink | o_diagram | o_skew | o_extrusion | o_callout | o_lock | o_OLEObject | o_complex | o_left | o_top | o_right | o_bottom | o_column | o_clippath | o_fill w_any_vml_vml = v_shape | v_shapetype | v_group | v_background | v_fill | v_formulas | v_handles | v_imagedata | v_path | v_textbox | v_shadow | v_stroke | v_textpath | v_arc | v_curve | v_image | v_line | v_oval | v_polyline | v_rect | v_roundrect ooxml/claude/skills/000775 000765 000024 00000000000 15172101247 015050 5ustar00alexstaff000000 000000 ooxml/claude/skills/ooxml/000775 000765 000024 00000000000 15221531027 016204 5ustar00alexstaff000000 000000 ooxml/claude/skills/ooxml/SKILL.md000644 000765 000024 00000046326 15221531027 017415 0ustar00alexstaff000000 000000 --- name: ooxml description: > Use this skill for all tasks involving the Tcl package `ooxml` (ECMA-376 Office Open XML: XLSX and DOCX). Triggers for XLSX: reading or writing Excel files in Tcl, using the ooxml package, generating XLSX files from Tcl, exporting Tcl data to Excel, exporting Tcl tablelist to Excel, cell formatting (font, color, border, number format), formulas in XLSX, hyperlinks in XLSX, calculating column widths, converting coordinates between numeric (row,col) and Excel notation (A1). Triggers for DOCX: creating or generating Word documents from Tcl, ooxml::docx, WordprocessingML, paragraphs and character/paragraph styles, tables in Word, images in docx, headers/footers, footnotes/endnotes, comments, fields (page numbers etc.), bookmarks and hyperlinks in docx, numbered/bulleted lists, textboxes, math formulas (OMML) in Word, docx templates, search and replace in docx. Always use when the user mentions ooxml, xl_read, xl_write, ooxml::docx, XLSX, or DOCX in combination with Tcl. --- # ooxml – Tcl Package for XLSX + DOCX (ECMA-376) **Project:** https://fossil.sowaswie.de/ooxml/index **License:** BSD-3 **Author:** Alexander Schöpe (+ Rolf Ade, Harald Oehlmann, Miguel Bañón) Two subsystems: `package require ooxml` reads and writes Excel workbooks (XLSX), `package require ooxml::docx` (since ooxml 1.11) creates Word documents (DOCX / WordprocessingML). ## Dependencies - Tcl >= 8.6.7 - Reading XLSX: `tcllib` module `zipfile::decode` **or** `vfs::zip >= 1.0.4` (recommended); Tcl 9 uses `zipfs` - `tdom >= 0.9.0`; the docx writer (`ooxml::docx`) requires `tdom >= 0.9.6` --- ## Core Commands ### Reading ```tcl package require ooxml # Load all sheets → array array set workbook [::ooxml::xl_read file.xlsx] # Options: # -valuesonly Data only, no formatting # -keylist Return key list instead of array # -sheets PATTERN Load only sheet IDs matching pattern # -sheetnames PATTERN Load only sheets with matching names # -datefmt FORMAT Date format (default: "%Y-%m-%d %H:%M:%S") # -as array (currently the only output option) # Get sheet information set info [::ooxml::xl_sheets file.xlsx] # Delete a sheet from array ::ooxml::arrayDeleteSheet workbook 0 ::ooxml::arrayDeleteSheet workbook "Sheet1" -sheetname ``` > **Note:** `presetstyles`, `presetsheets` and `arrayDeleteSheet` expect the > **array name** (without `$`), not its value. ### Reading – Result Structure `xl_read` returns a flat array. Keys use `S`=sheet id (0-based), `R`,`C`=row,column (0-based): | Key | Content | |---|---| | `sheets` | List of sheet IDs that were read | | `S,n` | Sheet name | | `S,max_row` / `S,max_column` | Largest used row / column index | | `S,v,R,C` | **Cell value** (always present) | | `S,d,R,C` | Raw date/time serial (when value is a formatted date) | | `S,s,R,C` | Style ID of the cell | | `S,t,R,C` | Cell type (`s` = shared string) | | `S,c,R,C` | Excel A1 reference of the cell | | `S,f,R,C` | Formula dict: `f` formula, `i` shared idx, `r` shared ref | | `S,l,IDX` | Hyperlink dict: `l` URL, `t` tooltip | | `S,k` | Keylist dict row→columns (only with `-keylist`) | | `S,filter` `S,freeze` `S,merge` `S,printarea` `S,rowheight` `S,pageMargins` `S,pageSetup` | Sheet properties | | `S,cols` / `S,col,N` | Number of column definitions / dict with properties of column definition N | | `s,@` `s,styles,*` | Style metadata (consumed by `presetstyles`) | | `sheetmap` | Added by `presetsheets`: original sheet id → new worksheet handle | With `-valuesonly` only `S,v,R,C` plus `sheets` / `S,n` / `S,max_*` are present. ```tcl # Iterate all value cells of sheet 0 foreach key [lsort -dictionary [array names workbook 0,v,*]] { lassign [split $key ,] sheet tag row col set value $workbook($key) } ``` ### Writing – Basic Structure ```tcl package require ooxml set sp [::ooxml::xl_write new \ -creator "Author Name" \ -created [clock seconds] \ -modifiedby "Name" \ -modified [clock seconds] \ -application "MyApp"] set sheet [$sp worksheet "Sheet 1"] # Write cells and save file $sp write output.xlsx $sp destroy ``` --- ## Cell Addressing > **Recommendation:** When *writing* xlsx files, prefer the **autoincrement** > of rows and columns wherever possible: call `$sp row $sheet` once per row, > then write cells with bare `$sp cell $sheet ` (no `-index`). Reserve > explicit `-index` for deliberately jumping or skipping. Order-driven writing > avoids off-by-one and index-bookkeeping errors and keeps the code readable. Two equivalent methods: ```tcl # Numeric (row,col, 0-based) $sp cell $sheet 12.34 -index 0,0 $sp cell $sheet {Text} -index 1,0 -string # Excel notation (A1-style) $sp cell $sheet 5.6 -index B1 $sp cell $sheet {} -index C1 -formula {A1+B1} ``` **Using autoincrement** (without `-index`): ```tcl $sp row $sheet $sp cell $sheet Value1 $sp cell $sheet Value2 ;# next column automatically $sp row $sheet ;# next row $sp cell $sheet Value3 ``` Rows and columns are auto-incremented and can be skipped with `-index`: ```tcl $sp row $sheet $sp cell $sheet A ;# 0,0 $sp cell $sheet B -index 4 ;# 0,4 (columns 1-3 remain empty) $sp cell $sheet C ;# 0,5 $sp row $sheet -index 3 ;# jump to row 3 $sp cell $sheet D ;# 3,0 ``` Result: A at 0,0 (A1), B at 0,4 (E1), C at 0,5 (F1), D at 3,0 (A4). --- ## Helper Functions ```tcl # Coordinate conversion ::ooxml::StringToRowColumn A1 ;# → 0,0 ::ooxml::RowColumnToString 0,0 ;# → A1 ::ooxml::Column 0 ;# → A # Calculate column width based on character count ::ooxml::CalcColumnWidth 16 ;# → 16.7109375 # Set default path ::ooxml::Default path "/tmp" ``` --- ## Formatting All style elements are defined first, then referenced by their ID. ### Number Format (NUMFMTID) ```tcl set fmtDate [$sp numberformat -date] set fmtDateTime [$sp numberformat -datetime] set fmtIso [$sp numberformat -iso8601] set fmtDec [$sp numberformat -decimal -red -separator] set fmtPct [$sp numberformat -percent] set fmtText [$sp numberformat -string] set fmtCustom [$sp numberformat -format {#,##0.00 "€"}] # -tag NAME allows referencing by name instead of ID ``` ### Font (FONTID) ```tcl set fHeader [$sp font \ -name "Arial" \ -size 12 \ -bold \ -color Blue] ``` ### Fill Pattern (FILLID) ```tcl set fFill [$sp fill \ -patterntype solid \ -fgcolor Yellow] ``` ### Border (BORDERID) Sides: `-left` `-right` `-top` `-bottom` `-diagonal`, each with a `…style` and `…color` variant. Diagonal additionally takes `-diagonaldirection up|down`. ```tcl set fBorder [$sp border \ -bottomstyle thin \ -bottomcolor Black] set fDiag [$sp border -diagonalstyle medium -diagonaldirection up] ``` ### Cell Style (STYLEID) ```tcl set sHeader [$sp style \ -font $fHeader \ -fill $fFill \ -border $fBorder \ -numfmt $fmtDate \ -horizontal center \ -vertical top \ -rotate 0 \ -wrap] ;# -wrap is a flag: enable text wrapping # also: -xf XFID (base cell format record), -list, -tag NAME ``` Apply style to column or cell: ```tcl $sp column $sheet -index 0 -style $sHeader -width 20 $sp cell $sheet "Value" -index 0,0 -style $sHeader ``` --- ## Column and Row Definitions ```tcl # Column $sp column $sheet \ -index 0 \ -to 3 \ -width 15 \ -style $styleId \ -bestfit \ -customwidth \ -string \ -nozero \ -calcfit # Row $sp row $sheet -index 0 -height 20 ``` --- ## Cell Options | Option | Description | |---|---| | `-string` | Always store value as string | | `-nostring` | Override column-level `-string` for this cell | | `-nozero` | Do not output zero values | | `-zero` | Override column-level `-nozero` for this cell | | `-formula FORMULA` | Enter an Excel formula | | `-formulaidx N` | Shared formula index (integer starting at 0) | | `-formularef A1:B5` | Range of the shared formula | | `-hyperlink URL` | `http(s)://...` link | | `-tooltip TEXT` | Tooltip (only evaluated with `-hyperlink`) | | `-height H` | Set row height for this row | | `-style STYLEID` | Style for this cell | | `-globalstyle` | Apply the column/global style to this cell | --- ## Formulas Simple formula — the cell value stays empty, Excel computes it: ```tcl $sp row $sheet $sp cell $sheet 3 ;# A1 $sp cell $sheet 5 ;# B1 $sp cell $sheet {} -formula A1+B1 ;# C1 ``` **Shared formula:** define it once with `-formula` + `-formularef` (the range it spans) + `-formulaidx` (an integer id, starting at 0). Dependent cells reference only `-formulaidx`. `-formularef` accepts an A1 range *or* a numeric `r,c:r,c` range: ```tcl # Vertical shared formula C3:C5 $sp cell $sheet 1 -index 2,0 $sp cell $sheet 2 -index 2,1 $sp cell $sheet {} -index 2,2 -formula {A3+B3} -formularef C3:C5 -formulaidx 0 $sp cell $sheet {} -index 3,2 -formulaidx 0 ;# reuses idx 0 $sp cell $sheet {} -index C5 -formulaidx 0 # Horizontal shared formula, numeric ref $sp cell $sheet {} -index A9 -formula {A7+A8} -formularef 8,0:8,2 -formulaidx 1 $sp cell $sheet {} -index 8,1 -formulaidx 1 ``` --- ## Additional Features ```tcl # Autofilter $sp autofilter $sheet 0,0 0,5 # Freeze panes (row/column) $sp freeze $sheet 1,0 ;# freeze first row # Merge cells (corner indices, numeric or A1) $sp merge $sheet 40,0 40,2 $sp merge $sheet A42 A44 # Print area (per sheet, numeric or A1) $sp printarea $sheet A1 C3 $sp printarea $sheet 1,1 2,2 # Explicit row height (independent of `row -height`) $sp rowheight $sheet 33 20 ;# row index 33 -> height 20 # Page margins (doubles in inch) and page setup $sp pageMargins $sheet -left 0.5 -right 0.5 -top 1 -bottom 1 -header 0.5 -footer 0.5 $sp pageSetup $sheet -orientation landscape -paperSize 9 ;# 9 = A4, 1 = Letter # Workbook view $sp view -activetab 0 -x 100 -y 100 -width 14400 -height 9000 # Set default date style set dateStyle [$sp style -numfmt [$sp numberformat -datetime]] $sp defaultdatestyle $dateStyle # Read existing workbook and reuse styles/data array set wb [::ooxml::xl_read original.xlsx] set sp [::ooxml::xl_write new] $sp presetstyles wb ;# inherit styles $sp presetsheets wb ;# inherit styles + data ``` --- ## tablelist → XLSX ```tcl package require ooxml ::ooxml::tablelist_to_xl $lb \ -file output.xlsx \ -path /tmp \ -creator "Name" \ -name "Sheet 1" \ -rootonly \ -addtimestamp \ -globalstyle \ -callback myCallback # Callback signature: proc myCallback {sp sheet maxcol col title width align sortmode hide} { # col == -1: called once for the entire workbook if {$col == -1} { set dateStyle [$sp style -numfmt [$sp numberformat -datetime]] $sp defaultdatestyle $dateStyle } else { switch -- $align { center { $sp column $sheet -index $col -style [$sp style -horizontal center] } right { $sp column $sheet -index $col -style [$sp style -horizontal right] } default {} } } } ``` --- ## Color Constants (Selection) Named colors: `Aqua Black Blue Canary Fuchsia Gray Green Lime Maroon Navy Orange Olive Purple Red Silver Teal White Yellow` (and many more, indexed 0-65) Alternatively: `RGB` or `aRGB` notation. ## Border Line Styles `dashDot dashDotDot dashed dotted double hair medium mediumDashDot mediumDashDotDot none slantDashDot thick thin` ## Pattern Types `solid none darkDown darkGray darkGrid lightDown lightGray lightGrid lightHorizontal lightTrellis lightUp lightVertical mediumGray` --- ## Complete Example: Write File with Formatting ```tcl package require ooxml set sp [::ooxml::xl_write new -creator "Me"] set sheet [$sp worksheet "Report"] # Define styles set boldFont [$sp font -bold -size 12 -color White] set bgFill [$sp fill -patterntype solid -fgcolor Blue] set hdrStyle [$sp style -font $boldFont -fill $bgFill -horizontal center] set numStyle [$sp style -numfmt [$sp numberformat -decimal -separator]] set dateStyle [$sp style -numfmt [$sp numberformat -date]] # Configure columns $sp column $sheet -index 0 -width 20 -style $hdrStyle $sp column $sheet -index 1 -width 12 -style $numStyle $sp column $sheet -index 2 -width 14 -style $dateStyle # Header row $sp row $sheet $sp cell $sheet "Name" -index 0 -string $sp cell $sheet "Amount" -index 1 -string $sp cell $sheet "Date" -index 2 -string # Data row $sp row $sheet $sp cell $sheet "John Doe" -index 0 -string $sp cell $sheet 1234.56 -index 1 $sp cell $sheet [clock seconds] -index 2 # Autofilter + freeze first row $sp autofilter $sheet 0,0 0,2 $sp freeze $sheet 1,0 $sp write report.xlsx $sp destroy ``` --- # DOCX – Creating Word Documents (`ooxml::docx`, since 1.11) ```tcl package require ooxml::docx set doc [ooxml::docx::docx new] ;# empty document $doc paragraph "Hello, World!" $doc write hello.docx ;# suffix .docx appended if missing $doc destroy ``` Start from an existing file as template: `ooxml::docx::docx new template.docx`. Content is added top-down; methods take required arguments first, then `-option value` pairs. All option values are type checked, unknown options/keys raise a Tcl error. On/off options accept boolean values (`on`/`off`, `1`/`0`, `true`/`false`). Document properties: `$doc configure -creator "Me" -title "Report" -language de-DE ...` (also `-created -modified -subject -keywords -description -revision -version` …) ## Text, Styles, Formatting ```tcl $doc paragraph "Text" -pstyle StyleName -cstyle StyleName -align center -bold on $doc append " more text in the same paragraph" -italic on $doc br ;# line break $doc tab ;# tab $doc pagebreak ;# page break ``` **Character options** (for `paragraph`, `append`, `url`, `field`, …): `-bold -italic -underline single|double|dotted|wave|…` `-strike -dstrike -emboss -color RRGGBB -font Name -fontsize N -highlight yellow|red|… -verticalAlign baseline|superscript|subscript -rtl -noProof -cstyle Ref` **Paragraph options:** `-align start|center|end|both|…` `-background RRGGBB -shading {type clear fill RRGGBB} -indentation {start 1cm firstLine 5mm} -spacing {before 6pt after 6pt line 360 lineRule auto} -keepLines -keepNext -pageBreakBefore -widowControl -bidi -numberingStyle ID -level N -textframe {width … height … wrap …} -suppressLineNumbers` **Measurements:** integer plus unit `mm cm in pt pc pi` (or bare integer, unit depends on option, mostly twips; for image/textbox `-dimension` a bare integer means EMU, 914400 EMU = 1 inch). **Named styles** — define once, reference by display name or style ID (`-pstyle`, `-cstyle`, `-style`, `-basedon`, `-refstyle`): ```tcl $doc style paragraphdefault -fontsize 22 -font "Times New Roman" $doc style paragraph "Heading Blue" -bold on -color 0000FF -fontsize 28 $doc style character "Warn" -color FF0000 -bold on $doc style table "MyTable" -tableBorders {…} -conditional {firstRow {…}} $doc paragraph "Chapter 1" -pstyle "Heading Blue" ``` Subcommands: `ids|names styletype`, `delete styletype name`. ## Tables ```tcl # Quick: nested list, one element per row $doc simpletable {{A1 B1 C1} {A2 B2 C2}} -columnwidths {3cm 3cm 3cm} # Full control: table → tablerow → tablecell (cells hold any content, # even nested tables and images) $doc table -style MyTable -columnwidths {5cm 5cm} -width {type auto} { $doc tablerow -headerrow on { $doc tablecell -background DDDDDD {$doc paragraph "Head 1"} $doc tablecell {$doc paragraph "Head 2"} } $doc tablerow { $doc tablecell -span 2 -vAlign center {$doc paragraph "spans 2 cols"} } } ``` Cell options: `-span N` (grid columns), `-hspan/-vspan restart|continue` (merging), `-vAlign`, `-background RRGGBB` | `-shading {…}` (mutually exclusive), `-cellWidth {type dxa value 3cm}`, borders (`-topBorder {type single color 000000 borderwidth 4} …`), margins. Row options: `-rowHeight {value 1cm hRule atLeast}`, `-headerrow on` (repeat on every page), `-cantSplit on`. ## Images, Textboxes, Header/Footer, Sections ```tcl $doc image photo.jpg inline -dimension {width 3cm height 3cm} $doc image photo.jpg anchor -dimension {width 3cm height 3cm} -wrapMode square \ -positionH margin -alignH right -positionV paragraph -posOffsetV 0 $doc textbox -dimension {width 5cm height 2cm} {$doc paragraph "boxed"} $doc header {$doc paragraph "My Header"} hdrId hdrObjId $doc footer {$doc paragraph "Page "; $doc field PAGE; $doc append " of "; $doc field NUMPAGES} ftrId $doc pagesetup -defaultHeader $hdrId -defaultFooter $ftrId \ -sizeAndOrientation {width 29.7cm height 21cm orientation landscape} \ -margins {top 2cm bottom 2cm} # Sections: sectionstart … sectionend with the same options as pagesetup ``` ## Notes, Comments, Fields, Links, Lists ```tcl $doc footnote {$doc paragraph "footnote text"} ;# also: endnote $doc simplecomment "comment text" -author "Me" -initials AS set id [$doc commentrangestart] ;# comment a text range $doc paragraph "commented content" $doc simplecommentrangeend $id "range comment" $doc field PAGE ;# AUTHOR CREATEDATE DATE FILESIZE PAGE NUMPAGES ;# SAVEDATE SECTION TIME TITLE USERNAME (+ switches) $doc url "Tcl homepage" https://www.tcl-lang.org -color 0000FF -underline single $doc mark target1 ;# set jump target; markstart/markend for spans $doc jumpto "go to target" target1 $doc numbering abstractNum 0 { {-numberFormat decimal -levelText "%1." -align start} {-numberFormat bullet -levelText "•"} } $doc paragraph "first item" -numberingStyle 0 -level 0 ``` ## Math (OMML) ```tcl $doc math -display on -jc center { $doc mfrac {$doc mrun a} {$doc mrun b} $doc mnary -char "∑" -sub {$doc mrun i=1} -sup {$doc mrun n} {$doc mrun i} } ``` Math methods (only valid inside a `math` script): `mrun mfrac msub msup msubsup msqrt mroot mnary mfunc mlimlow mlimupp maccent mbar mdelim mdelimarg mgroupchr mmatrix mmatcell`. ## Document Settings and Power Tools ```tcl $doc settings -defaultTabStop 708 -autoHyphenation on -trackRevisions on \ -mirrorMargins on -evenAndOddHeaders on -documentProtection {edit readOnly enforcement on} $doc appendTo $objectId {…} ;# append content later to a created table/ ;# row/cell/header/footer/foot-/endnote/comment/textbox $doc replace "%%NAME%%" "John" ;# simple template substitution (uniform runs only) $doc addXML $xmlFragment ;# insert raw WordprocessingML $doc import styles other.docx ;# take over word/styles.xml (or numbering, …) $doc readpart word/settings.xml file.xml ;# writepart to export a part $doc xmlparts ;# list XML parts $doc selectNodes {//w:p} ?part? ;# XPath (alias: xpath), w:/r:/m:… prefixes predefined ``` --- ## References - **Man-Page (XLSX):** https://fossil.sowaswie.de/ooxml/wiki?name=man-page — in the source tree: `doc/ooxml.md` (complete command/method reference) - **DOCX documentation:** `doc/ooxml-docx.md` in the source tree (complete option/method reference) - **Examples:** https://fossil.sowaswie.de/ooxml/wiki?name=examples — in the source tree: `examples/xlsx-*.tcl` and `examples/docx-example*.tcl` - **Tools:** https://fossil.sowaswie.de/ooxml/wiki?name=tools - **Downloads:** https://fossil.sowaswie.de/ooxml/uv/download.htmlooxml/tclconfig/install-sh000755 000765 000024 00000033054 14764622263 016305 0ustar00alexstaff000000 000000 #!/bin/sh # install - install a program, script, or datafile scriptversion=2011-04-20.01; # UTC # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the # following copyright and license. # # Copyright (C) 1994 X Consortium # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to # deal in the Software without restriction, including without limitation the # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or # sell copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- # TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name of the X Consortium shall not # be used in advertising or otherwise to promote the sale, use or other deal- # ings in this Software without prior written authorization from the X Consor- # tium. # # # FSF changes to this file are in the public domain. # # Calling this script install-sh is preferred over install.sh, to prevent # `make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. nl=' ' IFS=" "" $nl" # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit=${DOITPROG-} if test -z "$doit"; then doit_exec=exec else doit_exec=$doit fi # Put in absolute file names if you don't have them in your path; # or use environment vars. chgrpprog=${CHGRPPROG-chgrp} chmodprog=${CHMODPROG-chmod} chownprog=${CHOWNPROG-chown} cmpprog=${CMPPROG-cmp} cpprog=${CPPROG-cp} mkdirprog=${MKDIRPROG-mkdir} mvprog=${MVPROG-mv} rmprog=${RMPROG-rm} stripprog=${STRIPPROG-strip} posix_glob='?' initialize_posix_glob=' test "$posix_glob" != "?" || { if (set -f) 2>/dev/null; then posix_glob= else posix_glob=: fi } ' posix_mkdir= # Desired mode of installed file. mode=0755 chgrpcmd= chmodcmd=$chmodprog chowncmd= mvcmd=$mvprog rmcmd="$rmprog -f" stripcmd= src= dst= dir_arg= dst_arg= copy_on_change=false no_target_directory= usage="\ Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE or: $0 [OPTION]... SRCFILES... DIRECTORY or: $0 [OPTION]... -t DIRECTORY SRCFILES... or: $0 [OPTION]... -d DIRECTORIES... In the 1st form, copy SRCFILE to DSTFILE. In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. In the 4th, create DIRECTORIES. Options: --help display this help and exit. --version display version info and exit. -c (ignored) -C install only if different (preserve the last data modification time) -d create directories instead of installing files. -g GROUP $chgrpprog installed files to GROUP. -m MODE $chmodprog installed files to MODE. -o USER $chownprog installed files to USER. -s $stripprog installed files. -S $stripprog installed files. -t DIRECTORY install into DIRECTORY. -T report an error if DSTFILE is a directory. Environment variables override the default commands: CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG " while test $# -ne 0; do case $1 in -c) ;; -C) copy_on_change=true;; -d) dir_arg=true;; -g) chgrpcmd="$chgrpprog $2" shift;; --help) echo "$usage"; exit $?;; -m) mode=$2 case $mode in *' '* | *' '* | *' '* | *'*'* | *'?'* | *'['*) echo "$0: invalid mode: $mode" >&2 exit 1;; esac shift;; -o) chowncmd="$chownprog $2" shift;; -s) stripcmd=$stripprog;; -S) stripcmd="$stripprog $2" shift;; -t) dst_arg=$2 shift;; -T) no_target_directory=true;; --version) echo "$0 $scriptversion"; exit $?;; --) shift break;; -*) echo "$0: invalid option: $1" >&2 exit 1;; *) break;; esac shift done if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then # When -d is used, all remaining arguments are directories to create. # When -t is used, the destination is already specified. # Otherwise, the last argument is the destination. Remove it from $@. for arg do if test -n "$dst_arg"; then # $@ is not empty: it contains at least $arg. set fnord "$@" "$dst_arg" shift # fnord fi shift # arg dst_arg=$arg done fi if test $# -eq 0; then if test -z "$dir_arg"; then echo "$0: no input file specified." >&2 exit 1 fi # It's OK to call `install-sh -d' without argument. # This can happen when creating conditional directories. exit 0 fi if test -z "$dir_arg"; then do_exit='(exit $ret); exit $ret' trap "ret=129; $do_exit" 1 trap "ret=130; $do_exit" 2 trap "ret=141; $do_exit" 13 trap "ret=143; $do_exit" 15 # Set umask so as not to create temps with too-generous modes. # However, 'strip' requires both read and write access to temps. case $mode in # Optimize common cases. *644) cp_umask=133;; *755) cp_umask=22;; *[0-7]) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw='% 200' fi cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; *) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw=,u+rw fi cp_umask=$mode$u_plus_rw;; esac fi for src do # Protect names starting with `-'. case $src in -*) src=./$src;; esac if test -n "$dir_arg"; then dst=$src dstdir=$dst test -d "$dstdir" dstdir_status=$? else # Waiting for this to be detected by the "$cpprog $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if test ! -f "$src" && test ! -d "$src"; then echo "$0: $src does not exist." >&2 exit 1 fi if test -z "$dst_arg"; then echo "$0: no destination specified." >&2 exit 1 fi dst=$dst_arg # Protect names starting with `-'. case $dst in -*) dst=./$dst;; esac # If destination is a directory, append the input filename; won't work # if double slashes aren't ignored. if test -d "$dst"; then if test -n "$no_target_directory"; then echo "$0: $dst_arg: Is a directory" >&2 exit 1 fi dstdir=$dst dst=$dstdir/`basename "$src"` dstdir_status=0 else # Prefer dirname, but fall back on a substitute if dirname fails. dstdir=` (dirname "$dst") 2>/dev/null || expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$dst" : 'X\(//\)[^/]' \| \ X"$dst" : 'X\(//\)$' \| \ X"$dst" : 'X\(/\)' \| . 2>/dev/null || echo X"$dst" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q' ` test -d "$dstdir" dstdir_status=$? fi fi obsolete_mkdir_used=false if test $dstdir_status != 0; then case $posix_mkdir in '') # Create intermediate dirs using mode 755 as modified by the umask. # This is like FreeBSD 'install' as of 1997-10-28. umask=`umask` case $stripcmd.$umask in # Optimize common cases. *[2367][2367]) mkdir_umask=$umask;; .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; *[0-7]) mkdir_umask=`expr $umask + 22 \ - $umask % 100 % 40 + $umask % 20 \ - $umask % 10 % 4 + $umask % 2 `;; *) mkdir_umask=$umask,go-w;; esac # With -d, create the new directory with the user-specified mode. # Otherwise, rely on $mkdir_umask. if test -n "$dir_arg"; then mkdir_mode=-m$mode else mkdir_mode= fi posix_mkdir=false case $umask in *[123567][0-7][0-7]) # POSIX mkdir -p sets u+wx bits regardless of umask, which # is incompatible with FreeBSD 'install' when (umask & 300) != 0. ;; *) tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 if (umask $mkdir_umask && exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 then if test -z "$dir_arg" || { # Check for POSIX incompatibilities with -m. # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or # other-writeable bit of parent directory when it shouldn't. # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. ls_ld_tmpdir=`ls -ld "$tmpdir"` case $ls_ld_tmpdir in d????-?r-*) different_mode=700;; d????-?--*) different_mode=755;; *) false;; esac && $mkdirprog -m$different_mode -p -- "$tmpdir" && { ls_ld_tmpdir_1=`ls -ld "$tmpdir"` test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" } } then posix_mkdir=: fi rmdir "$tmpdir/d" "$tmpdir" else # Remove any dirs left behind by ancient mkdir implementations. rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null fi trap '' 0;; esac;; esac if $posix_mkdir && ( umask $mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" ) then : else # The umask is ridiculous, or mkdir does not conform to POSIX, # or it failed possibly due to a race condition. Create the # directory the slow way, step by step, checking for races as we go. case $dstdir in /*) prefix='/';; -*) prefix='./';; *) prefix='';; esac eval "$initialize_posix_glob" oIFS=$IFS IFS=/ $posix_glob set -f set fnord $dstdir shift $posix_glob set +f IFS=$oIFS prefixes= for d do test -z "$d" && continue prefix=$prefix$d if test -d "$prefix"; then prefixes= else if $posix_mkdir; then (umask=$mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break # Don't fail if two instances are running concurrently. test -d "$prefix" || exit 1 else case $prefix in *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; *) qprefix=$prefix;; esac prefixes="$prefixes '$qprefix'" fi fi prefix=$prefix/ done if test -n "$prefixes"; then # Don't fail if two instances are running concurrently. (umask $mkdir_umask && eval "\$doit_exec \$mkdirprog $prefixes") || test -d "$dstdir" || exit 1 obsolete_mkdir_used=true fi fi fi if test -n "$dir_arg"; then { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 else # Make a couple of temp file names in the proper directory. dsttmp=$dstdir/_inst.$$_ rmtmp=$dstdir/_rm.$$_ # Trap to clean up those temp files at exit. trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 # Copy the file name to the temp name. (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && # and set any options; do chmod last to preserve setuid bits. # # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $cpprog $src $dsttmp" command. # { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && # If -C, don't bother to copy if it wouldn't change the file. if $copy_on_change && old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && eval "$initialize_posix_glob" && $posix_glob set -f && set X $old && old=:$2:$4:$5:$6 && set X $new && new=:$2:$4:$5:$6 && $posix_glob set +f && test "$old" = "$new" && $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 then rm -f "$dsttmp" else # Rename the file to the real destination. $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || # The rename failed, perhaps because mv can't rename something else # to itself, or perhaps because mv is so ancient that it does not # support -f. { # Now remove or move aside any old file at destination location. # We try this two ways since rm can't unlink itself on some # systems and the destination file might be busy for other # reasons. In this case, the final cleanup might fail but the new # file should still install successfully. { test ! -f "$dst" || $doit $rmcmd -f "$dst" 2>/dev/null || { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } } || { echo "$0: cannot unlink or rename $dst" >&2 (exit 1); exit 1 } } && # Now rename the file to the real destination. $doit $mvcmd "$dsttmp" "$dst" } fi || exit 1 trap '' 0 fi done # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: ooxml/tclconfig/ChangeLog000644 000765 000024 00000110112 14764622263 016042 0ustar00alexstaff000000 000000 2016-03-11 Sean Woods *tcl.m4 Fixed the search for Tcl and Wish shells under MinGW. Static builds and threaded builds get an "s" or "t" added to the name. 2015-08-28 Jan Nijtmans * tcl.m4: Rfe [00189c4afc]: Allow semi-static UCRT build on Windows with VC 14.0 2013-10-08 Jan Nijtmans * tcl.m4: Bug [172223e008]: Wrong filename in --disable-shared compile on MinGW 2013-10-04 Jan Nijtmans * tcl.m4: stub library is no longer linked with msvcrt??.dll. 2013-10-01 Jan Nijtmans * tcl.m4: Workaround for MinGW bug #2065: "gcc --shared" links with libgcc_s_dw2-1.dll when using 64-bit division in C 2013-07-04 Jan Nijtmans * tcl.m4: Bug [3324676]: AC_PROG_INSTALL incompat, Bug [3606445]: Unneeded -DHAVE_NO_SEH=1 when not building on Windows 2013-07-02 Jan Nijtmans * tcl.m4: Bug [32afa6e256]: dirent64 check is incorrect in tcl.m4 (thanks to Brian Griffin) 2013-06-20 Jan Nijtmans * tcl.m4: Use X11/Xlib.h for checking where X11 can be found in stead of X11/XIntrinsic.h. Suggested by Pietro Cerutti. 2013-06-04 Jan Nijtmans * tcl.m4: Eliminate NO_VIZ macro as current zlib uses HAVE_HIDDEN in stead. One more last-moment fix for FreeBSD by Pietro Cerutti 2013-05-19 Jan Nijtmans * tcl.m4: Fix for FreeBSD, and remove support for old FreeBSD versions. Patch by Pietro Cerutti 2013-03-12 Jan Nijtmans * tcl.m4: Patch by Andrew Shadura, providing better support for * three architectures they have in Debian. 2012-08-07 Stuart Cassoff * tcl.m4: Added "-DNDEBUG" to CFLAGS_DEFAULT when building with --disable-symbols. 2012-08-07 Stuart Cassoff * tcl.m4: [Bug 3555058]: Checkin [30736d63f0] broke CFLAGS_DEFAULT, LDFLAGS_DEFAULT 2012-08-07 Stuart Cassoff * tcl.m4: [Bug 3511806]: Checkin [30736d63f0] broke CFLAGS 2012-08-07 Jan Nijtmans * tcl.m4: [Bug 3511806]: Checkin [30736d63f0] broke CFLAGS 2012-07-25 Jan Nijtmans * tcl.m4: My previous commit (2012-04-03) broke the ActiveTcl build for AMD64, because of the quotes in "C://AMD64/cl.exe". It turns out that the AC_TRY_COMPILE macro cannot handle that. 2012-07-22 Stuart Cassoff * tcl.m4: Tidy: consistency, spelling, phrasing, whitespace. No functional change. 2012-04-03 Jan Nijtmans * tcl.m4: [Bug 3511806] Compiler checks too early This change allows to build the cygwin and mingw32 ports of Tcl/Tk extensions to build out-of-the-box using a native or cross-compiler, e.g. on Cygwin, Linux or Darwin. 2011-04-02 Jan Nijtmans * install-sh: Fix issue with library stripping in install-sh (backported from kevin_walzer's patch from Tcl 8.6 trunk) 2011-04-05 Andreas Kupries * tcl.m4: Applied patch by Jeff Lawson. Nicer error message when tclConfig.sh was not found. 2010-12-15 Stuart Cassoff * install-sh: Upgrade to newer install-sh and use it. * tcl.m4: 2010-12-14 Stuart Cassoff * tcl.m4: Better building on OpenBSD. 2010-12-14 Jan Nijtmans * tcl.m4: when using gcc, don't try to determine Win64 SDK 2010-12-12 Jan Nijtmans * tcl.m4: Determine correctly a cross-compiler-windres 2010-11-23 Jan Nijtmans * tcl.m4: add some cross-compile support, borrowed from Tcl 8.6 2010-09-16 Jeff Hobbs * tcl.m4: correct HP-UX LDFLAGS (only used when building big shell) 2010-09-14 Jeff Hobbs * tcl.m4: add extra if check for .manifest file generation Add notice about package name and version being built. 2010-09-09 Jan Nijtmans * tcl.m4: [FREQ #3058486] TEA_LOAD_CONFIG doesn't set all BUILD_ vars Slightly related: defining BUILD_$1 on all platforms - not only win - allows the -fvisibility feature to be used in extensions as well, at least if you compile against tcl >= 8.5. 2010-08-26 Jeff Hobbs * tcl.m4: ensure safe quoting for autoheader usage 2010-08-19 Jeff Hobbs * tcl.m4: add TEA_ADD_CLEANFILES macro to make adding cleanfiles easier, and add *.exp to CLEANFILES Windows default. (TEA_MAKE_LIB): Enhanced to check for MSVC that requires manifests and auto-embed it into proj DLL via MAKE_SHARED_LIB. Also define VC_MANIFEST_EMBED_DLL and VC_MANIFEST_EMBED_EXE that do the same magic in case it is needed for extended TEA projects. 2010-08-16 Jeff Hobbs *** Bump to TEA_VERSION 3.9 *** If upgrading from TEA_VERSION 3.8, copy over tcl.m4, change TEA_INIT to use 3.9 and reconfigure (ac-2.59+). BUILD_${PACKAGE_NAME} will be auto-defined on Windows for correct setting of TCL_STORAGE_CLASS. TEA_LOAD_CONFIG users should remove the SHLIB_LD_LIBS setting done in configure.in (LIBS will be automagically populated by TEA_LOAD_CONFIG). TEA_EXPORT_CONFIG has been added for ${pkg}Config.sh creators SHLIB_LD_FLAGS was deprecated a while ago, remove it if it is still in your Makefile.in. * tcl.m4: add /usr/lib64 to set of auto-search dirs. [Bug 1230554] Auto-define BUILD_$PACKAGE_NAME so users don't need to. This needs to correspond with $pkg.h define magic for TCL_STORAGE_CLASS. Auto-define CLEANFILES. Users can expand it. (SHLIB_LD_LIBS): define to '${LIBS}' default and change it only if necessary. Platforms not using this may simply not work or have very funky linkers. (TEA_LOAD_CONFIG): When loading config for another extension, auto-add stub libraries found with TEA_ADD_LIBS. Eases configure.in for modules like itk and img::*. (TEA_EXPORT_CONFIG): Add standardized function for exporting a ${pkg}Config.sh. See use by img::* and itcl. 2010-08-12 Jeff Hobbs *** Bump to TEA_VERSION 3.8 *** If upgrading from TEA_VERSION 3.7, copy over tcl.m4, change TEA_INIT to use 3.8 and reconfigure (ac-2.59+). No other changes should be necessary. * tcl.m4: remove more vestigial bits from removed platforms. Add back SCO_SV-3.2*. Remove use of DL_LIBS and DL_OBJS and related baggage - these are only needed by the core to support 'load'. Allow for macosx in TEA_ADD_SOURCES. Correct check for found_xincludes=no in TEA_PATH_UNIX_X. 2010-08-11 Jeff Hobbs * tcl.m4: remove the following old platform configurations: UNIX_SV*|UnixWare-5*, SunOS-4.*, SINIX*5.4*, SCO_SV-3.2*, OSF1-1.*, NEXTSTEP-*, NetBSD-1.*|FreeBSD-[[1-2]].*, MP-RAS-*, IRIX-5.*, HP-UX-*.08.*|HP-UX-*.09.*|HP-UX-*.10.*, dgux*, BSD/OS-2.1*|BSD/OS-3* (AIX): drop AIX-pre4 support and use of ldAix, use -bexpall/-brtl 2010-07-05 Jan Nijtmans * tcl.m4: [Patch #1055668] removal of exported internals from tclInt.h (EXTERN macro) 2010-04-14 Jan Nijtmans * tcl.m4 - Backport a lot of quoting fixes from tcl8.6/unix/tcl.m4 - Fix determination of CYGPATH for CYGWIN With those fixes, itcl and tdbc compile fine with CYGWIN 2010-04-06 Jan Nijtmans * install-sh [Bug 2982540] configure and install* script files should always have LF 2010-02-19 Stuart Cassoff * tcl.m4: Correct compiler/linker flags for threaded builds on OpenBSD. 2010-01-19 Jan Nijtmans * tcl.m4: Detect CYGWIN variant: win32 or unix 2010-01-03 Donal K. Fellows * unix/tcl.m4 (TEA_CONFIG_CFLAGS): [Tcl Bug 1636685]: Use the configuration for modern FreeBSD suggested by the FreeBSD porter. 2009-10-22 Jan Nijtmans * tcl.m4: [Tcl Patch #2883533] tcl.m4 support for Haiku OS 2009-04-27 Jeff Hobbs * tcl.m4 (TEA_CONFIG_CFLAGS): harden the check to add _r to CC on AIX with threads. 2009-04-10 Daniel Steffen * tcl.m4 (Darwin): check for 64-bit TkAqua. 2009-03-26 Jan Nijtmans * tclconfig/tcl.m4: Adapt LDFLAGS and LD_SEARCH_FLAGS together with SHLIB_LD definition to unbreak building on HPUX. 2009-03-20 Andreas Kupries * tclconfig/tcl.m4: Changed SHLIB_LD definition to unbreak building on HPUX. 2009-03-16 Joe English * tcl.m4(TEA_PUBLIC_TK_HEADERS): Look at ${TK_INCLUDE_SPEC} (found in tkConfig.sh) when trying to guess where tk.h might be [Patch 1960628]. 2009-03-11 Joe English * tcl.m4: Allow ${SHLIB_SUFFIX} to be overridden at configure-time [Patch 1960628]. Also fix some comment typos, and an uninitialized variable bug-waiting-to-happen. 2008-12-21 Jan Nijtmans * tcl.m4: [Bug 2073255] Tcl_GetString(NULL) doesn't crash on HP-UX (this bug report was for Tcl, but holds for TEA as well.) 2008-12-20 Daniel Steffen * tcl.m4: sync with tdbc tcl.m4 changes (SunOS-5.11): Sun cc SHLIB_LD: use LDFLAGS_DEFAULT instead of LDFLAGS 2008-12-02 Jeff Hobbs *** Bump to TEA_VERSION 3.7 *** * tcl.m4: in private header check, check for Port.h instead of Int.h to ensure all private headers are available. 2008-11-04 Daniel Steffen * tcl.m4 (Darwin): sync TEA_PRIVATE_TK_HEADERS handling of Tk.framework PrivateHeaders with TEA_PRIVATE_TCL_HEADERS. 2008-11-04 Jeff Hobbs * tcl.m4 (TEA_PATH_TCLCONFIG, TEA_PATH_TKCONFIG): exit with error when tclConfig.sh cannot be found. [Bug #1997760] (TEA_PRIVATE_TCL_HEADERS, TEA_PRIVATE_TK_HEADERS): allow for finding the headers installed in the public areas, e.g. a result of make install-private-headers. [Bug #1631922] 2008-08-12 Daniel Steffen * tcl.m4 (Darwin): link shlib with current and compatiblity version flags; look for libX11.dylib when searching for X11 libraries. 2008-06-12 Daniel Steffen * tcl.m4 (SunOS-5.11): fix 64bit amd64 support with gcc & Sun cc. 2008-03-27 Daniel Steffen * tcl.m4 (SunOS-5.1x): fix 64bit support for Sun cc. [Bug 1921166] 2008-02-01 Donal K. Fellows * tcl.m4 (TEA_CONFIG_CFLAGS): Updated to work at least in part with more modern VC versions. Currently just made the linker flags more flexible; more work may be needed. 2007-10-26 Daniel Steffen * tcl.m4 (Darwin): add support for 64-bit X11. 2007-10-23 Jeff Hobbs *** Tagged tea-3-branch to start TEA 4 development on HEAD *** 2007-09-17 Joe English * tcl.m4: use '${CC} -shared' instead of 'ld -Bshareable' to build shared libraries on current NetBSDs [Bug 1749251]. 2007-09-15 Daniel Steffen * tcl.m4: replace all direct references to compiler by ${CC} to enable CC overriding at configure & make time. (SunOS-5.1x): replace direct use of '/usr/ccs/bin/ld' in SHLIB_LD by 'cc' compiler driver. 2007-08-08 Jeff Hobbs * tcl.m4: check Ttk dir for Tk private headers (8.5). Add some comments to other bits. 2007-06-25 Jeff Hobbs * tcl.m4 (TEA_PROG_TCLSH, TEA_PROG_WISH): move where / is added. 2007-06-13 Jeff Hobbs * tcl.m4: fix --with-tkinclude alignment. [Bug 1506111] 2007-06-06 Daniel Steffen * tcl.m4 (Darwin): fix 64bit arch removal in fat 32&64bit builds. 2007-05-18 Donal K. Fellows * tcl.m4: Added quoting so that paths with spaces cause fewer problems. 2007-03-07 Daniel Steffen * tcl.m4 (Darwin): s/CFLAGS/CPPFLAGS/ in -mmacosx-version-min check. 2007-02-15 Jeff Hobbs * tcl.m4: correct private header check to search in generic subdir 2007-02-09 Jeff Hobbs *** Bump to TEA_VERSION 3.6 *** * tcl.m4: correct -d to -f (TEA_CONFIG_CFLAGS): SHLIB_SUFFIX is .so on HP ia64 [Bug 1615058] 2007-02-08 Jeff Hobbs * tcl.m4 (TEA_PRIVATE_TCL_HEADERS, TEA_PRIVATE_TK_HEADERS): check that the dirs actually have private headers. [Bug 1631922] 2007-02-04 Daniel Steffen * tcl.m4: add caching to -pipe check. 2007-01-25 Daniel Steffen * tcl.m4: integrate CPPFLAGS into CFLAGS as late as possible and move (rather than duplicate) -isysroot flags from CFLAGS to CPPFLAGS to avoid errors about multiple -isysroot flags from some older gcc builds. 2006-01-19 Daniel Steffen * tcl.m4: ensure CPPFLAGS env var is used when set. [Bug 1586861] (Darwin): add -isysroot and -mmacosx-version-min flags to CPPFLAGS when present in CFLAGS to avoid discrepancies between what headers configure sees during preprocessing tests and compiling tests. 2006-12-19 Daniel Steffen * tcl.m4 (Darwin): --enable-64bit: verify linking with 64bit -arch flag succeeds before enabling 64bit build. 2006-12-16 Daniel Steffen * tcl.m4 (Linux): fix previous change to use makefile variable LDFLAGS_DEFAULT instead of LDFLAGS in SHLIB_LD, to ensure linker flags in sampleextension Makefile are picked up. 2006-11-26 Daniel Steffen * tcl.m4 (Linux): --enable-64bit support. [Patch 1597389], [Bug 1230558] 2006-08-18 Daniel Steffen * tcl.m4 (Darwin): add support for --enable-64bit on x86_64, for universal builds including x86_64 and for use of -mmacosx-version-min instead of MACOSX_DEPLOYMENT_TARGET. For Tk extensions, remove 64-bit arch flags from CFLAGS like in the Tk configure, as neither TkAqua nor TkX11 can be built for 64-bit at present. 2006-03-28 Jeff Hobbs * tcl.m4: []-quote AC_DEFUN functions. (TEA_PATH_TKCONFIG): Fixed Windows-specific check for tkConfig.sh. (TEA_MAKE_LIB): Prepend 'lib' for Windows-gcc configs. 2006-03-07 Joe English * tcl.m4: Set SHLIB_LD_FLAGS='${LIBS}' on NetBSD, as per the other *BSD variants [Bug 1334613]. 2006-01-25 Jeff Hobbs *** Bump to TEA version 3.5 *** * tcl.m4: keep LD_SEARCH_FLAGS and CC_SEARCH_FLAGS synchronous with core tcl.m4 meaning. 2006-01-24 Daniel Steffen * tcl.m4 (Darwin): use makefile variable LDFLAGS_DEFAULT instead of LDFLAGS in SHLIB_LD, to ensure linker flags in sampleextension Makefile are picked up. [Bug 1403343] 2006-01-23 Jeff Hobbs * tcl.m4: add C:/Tcl/lib and C:/Progra~1/Tcl/lib dirs to check for *Config.sh on Windows. [Bug 1407544] 2006-01-23 Daniel Steffen * tcl.m4 (Darwin): for Tk extensions, remove -arch ppc64 from CFLAGS like in the Tk configure, as neither TkAqua nor TkX11 can be built for 64bit at present (no 64bit GUI libraries). 2006-01-22 Jeff Hobbs * tcl.m4: restore system=windows on Windows. Remove error if 'ar' isn't found (it may not be on Windows). Do not add -lxnet or define _XOPEN_SOURCE on HP-UX by default. Ensure the C|LDFLAGS_DEFAULT gets the fully sub'd value at configure time. 2006-01-10 Daniel Steffen * tcl.m4: add caching, use AC_CACHE_CHECK instead of AC_CACHE_VAL where possible, consistent message quoting, sync relevant tcl/unix/tcl.m4 HEAD changes and gratuitous formatting differences (notably sunc removal of support for for ancient BSD's, IRIX 4, RISCos and Ultrix by kennykb), Darwin improvements to TEA_LOAD_*CONFIG to make linking work against Tcl/Tk frameworks installed in arbitrary location, change TEA_PROG_* search order (look in *_BIN_DIR parents before *_PREFIX). 2006-01-05 Jeff Hobbs * tcl.m4: add dkf's system config refactor 2006-01-04 Jeff Hobbs * tcl.m4: remove extraneous ' that causes bash 3.1 to choke 2005-12-19 Joe English * tcl.m4 (TEA_PATH_TCLCONFIG &c): Look for tclConfig.sh &c in ${libdir}, where they are installed by default [Patch #1377407]. 2005-12-05 Don Porter * tcl.m4 (TEA_PUBLIC_*_HEADERS): Better support for finding header files for uninstalled Tcl and Tk. 2005-12-02 Jeff Hobbs * tcl.m4: correctly bump TEA_VERSION var to 3.4 2005-12-01 Daniel Steffen * unix/tcl.m4 (Darwin): fixed error when MACOSX_DEPLOYMENT_TARGET unset 2005-11-29 Jeff Hobbs * tcl.m4: *** Bump to TEA version 3.4 *** Add Windows x64 build support. Remove TEA_PATH_NOSPACE and handle the problem with ""s where necessary - the macro relied on TCLSH_PROG which didn't work for cross-compiles. 2005-11-27 Daniel Steffen * tcl.m4 (Darwin): add 64bit support, add CFLAGS to SHLIB_LD to support passing -isysroot in env(CFLAGS) to configure (flag can't be present twice, so can't be in both CFLAGS and LDFLAGS during configure), don't use -prebind when deploying on 10.4. (TEA_ENABLE_LANGINFO, TEA_TIME_HANDLER): add/fix caching. 2005-10-30 Daniel Steffen * tcl.m4: fixed two tests for TEA_WINDOWINGSYSTEM = "aqua" that should have been for `uname -s` = "Darwin" instead; added some missing quoting. (TEA_PROG_TCLSH, TEA_PROG_WISH): fix incorrect assumption that install location of tclConfig.sh/tkConfig.sh allows to determine the tclsh/wish install dir via ../bin. Indeed tcl/tk can be configured with arbitrary --libdir and --bindir (independent of prefix) and such a configuration is in fact standard with Darwin framework builds. At least now also check ${TCL_PREFIX}/bin resp. ${TK_PREFIX}/bin for presence of tclsh resp. wish (if tcl/tk have been configured with arbitrary --bindir, this will still not find them, for a general solution *Config.sh would need to contain the values of bindir/libdir/includedir passed to configure). 2005-10-07 Jeff Hobbs * tcl.m4: Fix Solaris 5.10 check and Solaris AMD64 64-bit builds. 2005-10-04 Jeff Hobbs * tcl.m4 (TEA_PRIVATE_TCL_HEADERS): add / to finish sed macro (TEA_ENABLE_THREADS): don't check for pthread_attr_setstacksize func 2005-09-13 Jeff Hobbs * tcl.m4: *** Update to TEA version 3.3 *** define TEA_WINDOWINGSYSTEM in TEA_LOAD_TKCONFIG. Make --enable-threads the default (users can --disable-threads). Improve AIX ${CC}_r fix to better check existing ${CC} value. Do the appropriate evals to not require the *TOP_DIR_NATIVE vars be set for extensions that use private headers. Make aqua check for Xlib compat headers the same as win32. 2005-07-26 Mo DeJong * tcl.m4 (TEA_PROG_TCLSH, TEA_BUILD_TCLSH, TEA_PROG_WISH, TEA_BUILD_WISH): Remove TEA_BUILD_TCLSH and TEA_BUILD_WISH because of complaints that it broke the build when only an installed version of Tcl was available at extension build time. The TEA_PROG_TCLSH and TEA_PROG_WISH macros will no longer search the path at all. The build tclsh or installed tclsh shell will now be found by TEA_PROG_TCLSH. 2005-07-24 Mo DeJong * tcl.m4 (TEA_PROG_TCLSH, TEA_BUILD_TCLSH, TEA_PROG_WISH, TEA_BUILD_WISH): Split confused search for tclsh on PATH and build and install locations into two macros. TEA_PROG_TCLSH and TEA_PROG_WISH search the system PATH for an installed tclsh or wish. The TEA_BUILD_TCLSH and TEA_BUILD_WISH macros determine the name of tclsh or wish in the Tcl or Tk build directory even if tclsh or wish has not yet been built. [Tcl bug 1160114] [Tcl patch 1244153] 2005-06-23 Daniel Steffen * tcl.m4 (TEA_PRIVATE_TK_HEADERS): add ${TK_SRC_DIR}/macosx to TK_INCLUDES when building against TkAqua. * tcl.m4 (TEA_PATH_X): fixed missing comma in AC_DEFINE * tcl.m4: changes to better support framework builds of Tcl and Tk out of the box: search framework install locations for *Config.sh, and if in presence of a framework build, use the framework's Headers and PrivateHeaders directories for public and private includes. [FR 947735] 2005-06-18 Daniel Steffen * tcl.m4 (Darwin): add -headerpad_max_install_names to LDFLAGS to ensure we can always relocate binaries with install_name_tool. 2005-06-04 Daniel Steffen * tcl.m4 (TEA_PATH_X): for TEA_WINDOWINGSYSTEM == aqua, check if xlib compat headers are available in tkheaders location, otherwise add xlib sourcedir to TK_XINCLUDES. 2005-04-25 Daniel Steffen * tcl.m4: added AC_DEFINE* descriptions (from core tcl.m4) to allow use with autoheader. (Darwin): added configure checks for recently added linker flags -single_module and -search_paths_first to allow building with older tools (and on Mac OS X 10.1), use -single_module in SHLIB_LD. (TEA_MISSING_POSIX_HEADERS): added caching of dirent.h check. (TEA_BUGGY_STRTOD): added caching (sync with core tcl.m4). 2005-03-24 Jeff Hobbs * tcl.m4 (TEA_TCL_64BIT_FLAGS): use Tcl header defaults for wide int type only on Windows when __int64 is detected as valid. 2005-03-24 Don Porter * README.txt: Update reference to "SC_* macros" to "TEA_* macros". * tcl.m4: Incorporated recent improvements in SC_PATH_TCLCONFIG and SC_PATH_TKCONFIG into TEA_PATH_TCLCONFIG and TEA_PATH_TKCONFIG. Corrected search path in TEA_PATH_CONFIG and added AC_SUBST($1_BIN_DIR) to TEA_LOAD_CONFIG so that packages that load the configuration of another package can know where they loaded it from. 2005-03-18 Jeff Hobbs * tcl.m4 (TEA_CONFIG_CFLAGS): correct 2005-03-17 change to have variant LD_SEARCH_FLAGS for gcc and cc builds. * tcl.m4 (TEA_PROG_TCLSH, TEA_PROG_WISH): correct x-compile check. 2005-03-17 Jeff Hobbs * tcl.m4: Correct gcc build and HP-UX-11. 2005-02-08 Jeff Hobbs * tcl.m4 (TEA_ADD_LIBS): don't touch lib args starting with -. (TEA_CONFIG_CFLAGS): only define _DLL for CE in shared build. (TEA_MAKE_LIB): set RANLIB* to : on Windows (it's not needed). 2005-02-01 Jeff Hobbs * tcl.m4: redo of 2005-01-27 changes to correctly handle paths with spaces. Win/CE and Win/64 builds now require a prebuilt tclsh to handle conversion to short pathnames. This is done in the new TEA_PATH_NOSPACE macro. For Win/CE|64, make CC just the compiler and move the necessary includes to CFLAGS. (TEA_CONFIG_CFLAGS): Add Solaris 64-bit gcc build support. (TEA_PROG_TCLSH, TEA_PROG_WISH): Allow TCLSH_PROG and WISH_PROG to be set in the env and prevent resetting. (TEA_ADD_LIBS): On Windows using GCC (mingw), convert foo.lib args to -lfoo, for use with mingw. *** POTENTIAL INCOMPATABILITY *** (TEA_CONFIG_CFLAGS): Fix AIX gcc builds to work out-of-box. Bumped TEA to 3.2. 2005-01-27 Jeff Hobbs * tcl.m4: remove cygpath calls to support msys. Update base CE build assumption to "420,ARMV4,ARM,Pocket PC 2003". Make STLIB_LD use $LINKBIN -lib. 2005-01-25 Daniel Steffen * tcl.m4 (Darwin): fixed bug with static build linking to dynamic library in /usr/lib etc instead of linking to static library earlier in search path. [Tcl Bug 956908] Removed obsolete references to Rhapsody. 2004-12-29 Jeff Hobbs * tcl.m4: Updates for VC7 compatibility, fixing CFLAGS and LDFLAGS options, using better default -O levels. [Bug 1092952, 1091967] 2004-12-29 Joe English * tcl.m4: Do not use ${DBGX} suffix when building shared libraries [patch #1081595, TIP #34] 2004-09-07 Jeff Hobbs * tcl.m4 (TEA_CONFIG_CFLAGS): support eVC4 Win/CE builds 2004-08-10 Jeff Hobbs * tcl.m4 (TEA_INIT, TEA_PREFIX): update handling of exec_prefix to work around subdir configures since autoconf only propagates the prefix (not exec_prefix). 2004-07-23 Daniel Steffen * tcl.m4 (TEA_CONFIG_CFLAGS): Darwin section: brought inline with Tcl 8.5 HEAD config, removed core specific & obsolete settings. 2004-07-22 Jeff Hobbs * tcl.m4 (TEA_PATH_X): check in TK_DEFS for MAC_OSX_TK to see if we are compiling on Aqua. Add TEA_WINDOWINGSYSTEM var that reflects 'tk windowingsystem' value. 2004-07-16 Jeff Hobbs * tcl.m4 (TEA_ENABLE_THREADS): force a threaded build when building against a threaded core. (CFLAGS_WARNING): Remove -Wconversion for gcc builds (TEA_CONFIG_CFLAGS): Reorder configure.in for better 64-bit build configuration, replacing EXTRA_CFLAGS with CFLAGS. [Bug #874058] Update to latest Tcl 8.5 head config settings. Call this TEA version 3.1. 2004-04-29 Jeff Hobbs * tcl.m4 (TEA_TCL_64BIT_FLAGS): replace AC_TRY_RUN test with AC_TRY_COMPILE for the long vs. long long check. (kenny) 2004-04-26 Jeff Hobbs * tcl.m4 (TEA_TCL_64BIT_FLAGS): update against core tcl.m4 to define TCL_WIDE_INT_IS_LONG if 'using long'. 2004-03-19 Jeff Hobbs * tcl.m4: correct Windows builds getting LDFLAGS info in MAKE_LIB 2004-02-11 Jeff Hobbs * tcl.m4: correct TCL_INCLUDES for private headers on Windows - it doesn't need the eval. 2004-02-10 Jeff Hobbs * tcl.m4: don't require TK_INCLUDES and TCL_INCLUDES to have the DIR_NATIVE vars defined when using private headers on unix. Allow $... to TEA_ADD_SOURCES for constructs like TEA_ADD_SOURCES([\$(WIN_OBJECTS)]), that allow the developer to place more in the Makefile.in. tkUnixPort.h checks for HAVE_LIMITS_H, so do both HAVE and CHECK on limits.h 2003-12-10 Jeff Hobbs * Makefile.in: added TEA_ADD_LIBS, TEA_ADD_INCLUDES and * configure: TEA_ADD_CFLAGS to configurable parameters with * configure.in: PKG_* equivs in the Makefile. This allows the * tclconfig/tcl.m4: user to worry less about actual magic VAR names. Corrected Makefile.in to note that TEA_ADD_TCL_SOURCES requires exact file names. 2003-12-09 Jeff Hobbs * tcl.m4: updated OpenBSD support based on [Patch #775246] (cassoff) 2003-12-05 Jeff Hobbs * configure: * configure.in: * Makefile.in (VPATH): readd $(srcdir) to front of VPATH as the first part of VPATH can get chopped off. Change .c.$(OBJEXT) rule to .c.@OBJEXT@ to support more makes. * tclconfig/tcl.m4: add TEA_ADD_STUB_SOURCES to support libstub generation and TEA_ADD_TCL_SOURCES to replace RUNTIME_SOURCES as the way the user specifies library files. 2003-12-03 Jeff Hobbs * configure: Update of TEA spec to (hopefully) simplify * configure.in: some aspects of TEA by making use of more * Makefile.in: AC 2.5x features. Use PACKAGE_NAME (instead * generic/tclsample.c: of PACKAGE) and PACKAGE_VERSION (instead of * tclconfig/tcl.m4: VERSION) arguments to AC_INIT as the TEA package name and version. Provide a version argument to TEA_INIT - starting with 3.0. Drop all use of interior shell substs that older makefiles didn't like. Use PKG_* naming convention instead. Move specification of source files and public headers into configure.in with TEA_ADD_SOURCES and TEA_ADD_HEADERS. These will be munged during ./configure into the right obj file names (no $(SOURCES:.c=.obj) needed). There is almost nothing that should be touched in Makefile.in now for the developer. May want to add a TEA_ADD_TCL_SOURCES for the RUNTIME_SOURCES that remains. Use SHLID_LD_FLAGS (instead of SHLID_LDFLAGS) as Tcl does. Only specify the user requested LDFLAGS/CFLAGS in the Makefile, don't mention the _OPTIMIZE/_DEBUG variants. 2003-10-15 Jeff Hobbs * tcl.m4: create a TEA_SETUP_COMPILER_CC the precedes the TEA_SETUP_COMPILER macro. They are split so the check for CC occurs before any use of CC. Also add AC_PROG_CPP to the compiler checks. 2003-10-06 Jeff Hobbs * tcl.m4: Updated for autoconf 2.5x prereq. Where TCL_WIDE_INT_TYPE would be __int64, defer to the code checks in tcl.h, which also handles TCL_LL_MODIFIER* properly. 2003-04-22 Jeff Hobbs * tcl.m4: correct default setting of ARCH for WinCE builds. Correct \ escaping for CE sed macros. 2003-04-10 Jeff Hobbs * tcl.m4: replace $(syscal) construct with older `syscall` for systems where sh != bash. 2003-04-09 Jeff Hobbs * tcl.m4 (TEA_WITH_CELIB): add --enable-wince and --with-celib options for Windows/CE compilation support. Requires the Microsoft eMbedded SDK and Keuchel's celib emulation layer. 2003-02-18 Jeff Hobbs * tcl.m4 (TEA_ENABLE_THREADS): Make sure -lpthread gets passed on the link line when checking for the pthread_attr_setstacksize symbol. (dejong) * tcl.m4 (TEA_SETUP_COMPILER): added default calls to TEA_TCL_EARLY_FLAGS, TEA_TCL_64BIT_FLAGS, TEA_MISSING_POSIX_HEADERS and TEA_BUGGY_STRTOD. 2003-02-14 Jeff Hobbs * tcl.m4: correct HP-UX ia64 --enable-64bit build flags 2003-01-29 Jeff Hobbs * tcl.m4: check $prefix/lib as well as $exec_prefix/lib when looking for tcl|tkConfig.sh, as this check is done before we would set exec_prefix when the user does not define it. 2003-01-21 Mo DeJong * tcl.m4 (TEA_CONFIG_CFLAGS): Fix build support for mingw, the previous implementation would use VC++ when compiling with mingw gcc. Don't pass -fPIC since gcc always compiles pic code under win32. Change some hard coded cases of gcc to ${CC}. 2002-10-15 Jeff Hobbs * tcl.m4: move the CFLAGS definition from TEA_ENABLE_SHARED to TEA_MAKE_LIB because setting too early confuses other AC_* macros. Correct the HP-11 SHLIB_LD_LIBS setting. * tcl.m4: add the CFLAGS definition into TEA_ENABLE_SHARED and make it pick up the env CFLAGS at configure time. 2002-10-09 Jeff Hobbs * tcl.m4: add --enable-symbols=mem option to enable TCL_MEM_DEBUG. Improved AIX 64-bit build support, allow it on AIX-4 as well. Enable 64-bit HP-11 compilation with gcc. Enable 64-bit IRIX64-6 cc build support. Correct FreeBSD thread library linkage. Add OSF1 static build support. Improve SunOS-5 shared build SHLIB_LD macro. 2002-07-20 Zoran Vasiljevic * tcl.m4: Added MINGW32 to list of systems checked for Windows build. Also, fixes some indentation issues with "--with-XXX" options. 2002-04-23 Jeff Hobbs * tcl.m4 (TEA_ENABLE_THREADS): added USE_THREAD_ALLOC define to use new threaded allocatory by default on Unix for Tcl 8.4. (TEA_CONFIG_CFLAGS): corrected LD_SEARCH_FLAGS for FreeBSD-3+. 2002-04-22 Jeff Hobbs * tcl.m4 (TEA_SETUP_COMPILER): removed call to AC_CYGWIN so that we can use autoconf 2.5x as well as 2.13. This prevents us from being able to warn against the use of cygwin gcc at configure time, but allows autoconf 2.5x, which is what is shipped with most newer systems. 2002-04-11 Jeff Hobbs * tcl.m4: Enabled COFF as well as CV style debug info with --enable-symbols to allow Dr. Watson users to see function info. More info on debugging levels can be obtained at: http://msdn.microsoft.com/library/en-us/dnvc60/html/gendepdebug.asp 2002-04-03 Jeff Hobbs * tcl.m4: change all SC_* macros to TEA_*. The SC_ was for Scriptics, which is no more. TEA represents a better, independent prefix that won't need changing. Added preliminary mingw gcc support. [Patch #538772] Added TEA_PREFIX macro that handles defaulting the prefix and exec_prefix vars to those used by Tcl if none were specified. Added TEA_SETUP_COMPILER macro that encompasses the AC_PROG_CC check and several other basic AC_PROG checks needed for making executables. This greatly simplifies user's configure.in files. Collapsed AIX-5 defines into AIX-* with extra checks for doing the ELF stuff on AIX-5-ia64. Updated TEA_ENABLE_THREADS to take an optional arg to allow switching it on by default (for Thread) and add sanity checking to warn the user if configuring threads incompatibly. 2002-03-29 Jeff Hobbs * tcl.m4: made sure that SHLIB_LDFLAGS was set to LDFLAGS_DEFAULT. Removed --enable-64bit support for AIX-4 because it wasn't correct. Added -MT or -MD Windows linker switches to properly support symbols-enabled builds. 2002-03-28 Jeff Hobbs * tcl.m4: called AC_MSG_ERROR when SC_TEA_INIT wasn't called first instead of calling it as that inlines it each time in shell code. Changed Windows CFLAGS_OPTIMIZE to use -O2 instead of -Oti. Noted TCL_LIB_VERSIONS_OK=nodots for Windows builds. A few changes to support itcl (and perhaps others): Added support for making your own stub libraries to SC_MAKE_LIB. New SC_PATH_CONFIG and SC_LOAD_CONFIG that take a package name arg and find that ${pkg}Config.sh file. itk uses this for itcl. 2002-03-27 Jeff Hobbs * tcl.m4: made SC_LOAD_TKCONFIG recognize when working with a Tk build dir setup. Added EXTRA_CFLAGS and SHLIB_LD_LIBS substs to SC_CONFIG_CFLAGS. Added XLIBSW onto LIBS when it is defined. Remove TCL_LIBS from MAKE_LIB and correctly use SHLIB_LD_LIBS instead to not rely as much on tclConfig.sh cached info. Add TK_BIN_DIR to paths to find wish in SC_PROG_WISH. These move towards making TEA much more independent of *Config.sh. 2002-03-19 Jeff Hobbs * tcl.m4: corrected forgotten (UN)SHARED_LIB_SUFFIX and SHLIB_SUFFIX defines for Win. (SC_PATH_X): made this only do the check on unix platforms. 2002-03-12 Jeff Hobbs * README.txt: updated to reflect fewer files 2002-03-06 Jeff Hobbs * config.guess (removed): * config.sub (removed): removed unnecessary files * installFile.tcl (removed): * mkinstalldirs (removed): these aren't really necessary for making TEA work * tcl.m4 (SC_PUBLIC_TCL_HEADERS, SC_PUBLIC_TK_HEADERS): don't check /usr(/local)/include for includes on Windows when not using gcc 2002-03-05 Jeff Hobbs * tcl.m4: added warnings on Windows, removed RELPATH define and added TCL_LIBS to MAKE_LIB macro. This import represents 2.0.0, or a new start at attempting to make TEA much easier for C extension developers. **** moved from tclpro project to core tcl project, **** **** renamed to 'tclconfig' **** 2001-03-15 Karl Lehenbauer * installFile.tcl: Added updating of the modification time of the target file whether we overwrote it or decided that it hadn't changed. This was necessary for us to be able to determine whether or not a module install touched the file. 2001-03-08 Karl Lehenbauer * installFile.tcl: Added support for converting new-style (1.1+) Cygnus drive paths to Tcl-style. 2001-01-15 * tcl.m4: Added FreeBSD clause. 2001-01-03 * tcl.m4: Fixed typo in SC_LIB_SPEC where it is checking for exec-prefix. 2000-12-01 * tcl.m4: Concatenated most of the Ajuba acsite.m4 file so we don't need to modify the autoconf installation. * config.guess: * config.sub: * installFile.tcl: Added files from the itcl config subdirectory, which should go away. 2000-7-29 * Fixed the use of TCL_SRC_DIR and TK_SRC_DIR within TCL_PRIVATE_INCLUDES and TK_PRIVATE_INCLUDES to match their recent change from $(srcdir) to $(srcdir)/.. ooxml/tclconfig/tcl.m4000644 000765 000024 00000406231 14764622263 015326 0ustar00alexstaff000000 000000 # tcl.m4 -- # # This file provides a set of autoconf macros to help TEA-enable # a Tcl extension. # # Copyright (c) 1999-2000 Ajuba Solutions. # Copyright (c) 2002-2005 ActiveState Corporation. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. AC_PREREQ([2.69]) # Possible values for key variables defined: # # TEA_WINDOWINGSYSTEM - win32 aqua x11 (mirrors 'tk windowingsystem') # TEA_PLATFORM - windows unix # TEA_TK_EXTENSION - True if this is a Tk extension # #------------------------------------------------------------------------ # TEA_PATH_TCLCONFIG -- # # Locate the tclConfig.sh file and perform a sanity check on # the Tcl compile flags # # Arguments: # none # # Results: # # Adds the following arguments to configure: # --with-tcl=... # # Defines the following vars: # TCL_BIN_DIR Full path to the directory containing # the tclConfig.sh file #------------------------------------------------------------------------ AC_DEFUN([TEA_PATH_TCLCONFIG], [ dnl TEA specific: Make sure we are initialized AC_REQUIRE([TEA_INIT]) # # Ok, lets find the tcl configuration # First, look for one uninstalled. # the alternative search directory is invoked by --with-tcl # if test x"${no_tcl}" = x ; then # we reset no_tcl in case something fails here no_tcl=true AC_ARG_WITH(tcl, AS_HELP_STRING([--with-tcl], [directory containing tcl configuration (tclConfig.sh)]), [with_tclconfig="${withval}"]) AC_ARG_WITH(tcl8, AS_HELP_STRING([--with-tcl8], [Compile for Tcl8 in Tcl9 environment]), [with_tcl8="${withval}"]) AC_MSG_CHECKING([for Tcl configuration]) AC_CACHE_VAL(ac_cv_c_tclconfig,[ # First check to see if --with-tcl was specified. if test x"${with_tclconfig}" != x ; then case "${with_tclconfig}" in */tclConfig.sh ) if test -f "${with_tclconfig}"; then AC_MSG_WARN([--with-tcl argument should refer to directory containing tclConfig.sh, not to tclConfig.sh itself]) with_tclconfig="`echo "${with_tclconfig}" | sed 's!/tclConfig\.sh$!!'`" fi ;; esac if test -f "${with_tclconfig}/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd "${with_tclconfig}"; pwd)`" else AC_MSG_ERROR([${with_tclconfig} directory doesn't contain tclConfig.sh]) fi fi # then check for a private Tcl installation if test x"${ac_cv_c_tclconfig}" = x ; then for i in \ ../tcl \ `ls -dr ../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ `ls -dr ../tcl[[8-9]].[[0-9]] 2>/dev/null` \ `ls -dr ../tcl[[8-9]].[[0-9]]* 2>/dev/null` \ ../../tcl \ `ls -dr ../../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ `ls -dr ../../tcl[[8-9]].[[0-9]] 2>/dev/null` \ `ls -dr ../../tcl[[8-9]].[[0-9]]* 2>/dev/null` \ ../../../tcl \ `ls -dr ../../../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ `ls -dr ../../../tcl[[8-9]].[[0-9]] 2>/dev/null` \ `ls -dr ../../../tcl[[8-9]].[[0-9]]* 2>/dev/null` ; do if test "${TEA_PLATFORM}" = "windows" \ -a -f "$i/win/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i/win; pwd)`" break fi if test -f "$i/unix/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i/unix; pwd)`" break fi done fi # on Darwin, check in Framework installation locations if test "`uname -s`" = "Darwin" -a x"${ac_cv_c_tclconfig}" = x ; then for i in `ls -d ~/Library/Frameworks 2>/dev/null` \ `ls -d /Library/Frameworks 2>/dev/null` \ `ls -d /Network/Library/Frameworks 2>/dev/null` \ `ls -d /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/Library/Frameworks/Tcl.framework 2>/dev/null` \ `ls -d /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/Network/Library/Frameworks/Tcl.framework 2>/dev/null` \ `ls -d /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/Tcl.framework 2>/dev/null` \ ; do if test -f "$i/Tcl.framework/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i/Tcl.framework; pwd)`" break fi done fi # TEA specific: on Windows, check in common installation locations if test "${TEA_PLATFORM}" = "windows" \ -a x"${ac_cv_c_tclconfig}" = x ; then for i in `ls -d C:/Tcl/lib 2>/dev/null` \ `ls -d C:/Progra~1/Tcl/lib 2>/dev/null` \ ; do if test -f "$i/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i; pwd)`" break fi done fi # check in a few common install locations if test x"${ac_cv_c_tclconfig}" = x ; then for i in `ls -d ${libdir} 2>/dev/null` \ `ls -d ${exec_prefix}/lib 2>/dev/null` \ `ls -d ${prefix}/lib 2>/dev/null` \ `ls -d /usr/local/lib 2>/dev/null` \ `ls -d /usr/contrib/lib 2>/dev/null` \ `ls -d /usr/pkg/lib 2>/dev/null` \ `ls -d /usr/lib 2>/dev/null` \ `ls -d /usr/lib64 2>/dev/null` \ `ls -d /usr/lib/tcl8.6 2>/dev/null` \ `ls -d /usr/lib/tcl8.5 2>/dev/null` \ `ls -d /usr/local/lib/tcl8.6 2>/dev/null` \ `ls -d /usr/local/lib/tcl8.5 2>/dev/null` \ `ls -d /usr/local/lib/tcl/tcl8.6 2>/dev/null` \ `ls -d /usr/local/lib/tcl/tcl8.5 2>/dev/null` \ ; do if test -f "$i/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i; pwd)`" break fi done fi # check in a few other private locations if test x"${ac_cv_c_tclconfig}" = x ; then for i in \ ${srcdir}/../tcl \ `ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ `ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]] 2>/dev/null` \ `ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]]* 2>/dev/null` ; do if test "${TEA_PLATFORM}" = "windows" \ -a -f "$i/win/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i/win; pwd)`" break fi if test -f "$i/unix/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i/unix; pwd)`" break fi done fi ]) if test x"${ac_cv_c_tclconfig}" = x ; then TCL_BIN_DIR="# no Tcl configs found" AC_MSG_ERROR([Can't find Tcl configuration definitions. Use --with-tcl to specify a directory containing tclConfig.sh]) else no_tcl= TCL_BIN_DIR="${ac_cv_c_tclconfig}" AC_MSG_RESULT([found ${TCL_BIN_DIR}/tclConfig.sh]) fi fi ]) #------------------------------------------------------------------------ # TEA_PATH_TKCONFIG -- # # Locate the tkConfig.sh file # # Arguments: # none # # Results: # # Adds the following arguments to configure: # --with-tk=... # # Defines the following vars: # TK_BIN_DIR Full path to the directory containing # the tkConfig.sh file #------------------------------------------------------------------------ AC_DEFUN([TEA_PATH_TKCONFIG], [ # # Ok, lets find the tk configuration # First, look for one uninstalled. # the alternative search directory is invoked by --with-tk # if test x"${no_tk}" = x ; then # we reset no_tk in case something fails here no_tk=true AC_ARG_WITH(tk, AS_HELP_STRING([--with-tk], [directory containing tk configuration (tkConfig.sh)]), [with_tkconfig="${withval}"]) AC_MSG_CHECKING([for Tk configuration]) AC_CACHE_VAL(ac_cv_c_tkconfig,[ # First check to see if --with-tkconfig was specified. if test x"${with_tkconfig}" != x ; then case "${with_tkconfig}" in */tkConfig.sh ) if test -f "${with_tkconfig}"; then AC_MSG_WARN([--with-tk argument should refer to directory containing tkConfig.sh, not to tkConfig.sh itself]) with_tkconfig="`echo "${with_tkconfig}" | sed 's!/tkConfig\.sh$!!'`" fi ;; esac if test -f "${with_tkconfig}/tkConfig.sh" ; then ac_cv_c_tkconfig="`(cd "${with_tkconfig}"; pwd)`" else AC_MSG_ERROR([${with_tkconfig} directory doesn't contain tkConfig.sh]) fi fi # then check for a private Tk library if test x"${ac_cv_c_tkconfig}" = x ; then for i in \ ../tk \ `ls -dr ../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ `ls -dr ../tk[[8-9]].[[0-9]] 2>/dev/null` \ `ls -dr ../tk[[8-9]].[[0-9]]* 2>/dev/null` \ ../../tk \ `ls -dr ../../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ `ls -dr ../../tk[[8-9]].[[0-9]] 2>/dev/null` \ `ls -dr ../../tk[[8-9]].[[0-9]]* 2>/dev/null` \ ../../../tk \ `ls -dr ../../../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ `ls -dr ../../../tk[[8-9]].[[0-9]] 2>/dev/null` \ `ls -dr ../../../tk[[8-9]].[[0-9]]* 2>/dev/null` ; do if test "${TEA_PLATFORM}" = "windows" \ -a -f "$i/win/tkConfig.sh" ; then ac_cv_c_tkconfig="`(cd $i/win; pwd)`" break fi if test -f "$i/unix/tkConfig.sh" ; then ac_cv_c_tkconfig="`(cd $i/unix; pwd)`" break fi done fi # on Darwin, check in Framework installation locations if test "`uname -s`" = "Darwin" -a x"${ac_cv_c_tkconfig}" = x ; then for i in `ls -d ~/Library/Frameworks 2>/dev/null` \ `ls -d /Library/Frameworks 2>/dev/null` \ `ls -d /Network/Library/Frameworks 2>/dev/null` \ ; do if test -f "$i/Tk.framework/tkConfig.sh" ; then ac_cv_c_tkconfig="`(cd $i/Tk.framework; pwd)`" break fi done fi # check in a few common install locations if test x"${ac_cv_c_tkconfig}" = x ; then for i in `ls -d ${libdir} 2>/dev/null` \ `ls -d ${exec_prefix}/lib 2>/dev/null` \ `ls -d ${prefix}/lib 2>/dev/null` \ `ls -d /usr/local/lib 2>/dev/null` \ `ls -d /usr/contrib/lib 2>/dev/null` \ `ls -d /usr/pkg/lib 2>/dev/null` \ `ls -d /usr/lib/tk8.6 2>/dev/null` \ `ls -d /usr/lib/tk8.5 2>/dev/null` \ `ls -d /usr/lib 2>/dev/null` \ `ls -d /usr/lib64 2>/dev/null` \ `ls -d /usr/local/lib/tk8.6 2>/dev/null` \ `ls -d /usr/local/lib/tk8.5 2>/dev/null` \ `ls -d /usr/local/lib/tcl/tk8.6 2>/dev/null` \ `ls -d /usr/local/lib/tcl/tk8.5 2>/dev/null` \ ; do if test -f "$i/tkConfig.sh" ; then ac_cv_c_tkconfig="`(cd $i; pwd)`" break fi done fi # TEA specific: on Windows, check in common installation locations if test "${TEA_PLATFORM}" = "windows" \ -a x"${ac_cv_c_tkconfig}" = x ; then for i in `ls -d C:/Tcl/lib 2>/dev/null` \ `ls -d C:/Progra~1/Tcl/lib 2>/dev/null` \ ; do if test -f "$i/tkConfig.sh" ; then ac_cv_c_tkconfig="`(cd $i; pwd)`" break fi done fi # check in a few other private locations if test x"${ac_cv_c_tkconfig}" = x ; then for i in \ ${srcdir}/../tk \ `ls -dr ${srcdir}/../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ `ls -dr ${srcdir}/../tk[[8-9]].[[0-9]] 2>/dev/null` \ `ls -dr ${srcdir}/../tk[[8-9]].[[0-9]]* 2>/dev/null` ; do if test "${TEA_PLATFORM}" = "windows" \ -a -f "$i/win/tkConfig.sh" ; then ac_cv_c_tkconfig="`(cd $i/win; pwd)`" break fi if test -f "$i/unix/tkConfig.sh" ; then ac_cv_c_tkconfig="`(cd $i/unix; pwd)`" break fi done fi ]) if test x"${ac_cv_c_tkconfig}" = x ; then TK_BIN_DIR="# no Tk configs found" AC_MSG_ERROR([Can't find Tk configuration definitions. Use --with-tk to specify a directory containing tkConfig.sh]) else no_tk= TK_BIN_DIR="${ac_cv_c_tkconfig}" AC_MSG_RESULT([found ${TK_BIN_DIR}/tkConfig.sh]) fi fi ]) #------------------------------------------------------------------------ # TEA_LOAD_TCLCONFIG -- # # Load the tclConfig.sh file # # Arguments: # # Requires the following vars to be set: # TCL_BIN_DIR # # Results: # # Substitutes the following vars: # TCL_BIN_DIR # TCL_SRC_DIR # TCL_LIB_FILE # TCL_ZIP_FILE # TCL_ZIPFS_SUPPORT #------------------------------------------------------------------------ AC_DEFUN([TEA_LOAD_TCLCONFIG], [ AC_MSG_CHECKING([for existence of ${TCL_BIN_DIR}/tclConfig.sh]) if test -f "${TCL_BIN_DIR}/tclConfig.sh" ; then AC_MSG_RESULT([loading]) . "${TCL_BIN_DIR}/tclConfig.sh" else AC_MSG_RESULT([could not find ${TCL_BIN_DIR}/tclConfig.sh]) fi # If the TCL_BIN_DIR is the build directory (not the install directory), # then set the common variable name to the value of the build variables. # For example, the variable TCL_LIB_SPEC will be set to the value # of TCL_BUILD_LIB_SPEC. An extension should make use of TCL_LIB_SPEC # instead of TCL_BUILD_LIB_SPEC since it will work with both an # installed and uninstalled version of Tcl. if test -f "${TCL_BIN_DIR}/Makefile" ; then TCL_LIB_SPEC="${TCL_BUILD_LIB_SPEC}" TCL_STUB_LIB_SPEC="${TCL_BUILD_STUB_LIB_SPEC}" TCL_STUB_LIB_PATH="${TCL_BUILD_STUB_LIB_PATH}" elif test "`uname -s`" = "Darwin"; then # If Tcl was built as a framework, attempt to use the libraries # from the framework at the given location so that linking works # against Tcl.framework installed in an arbitrary location. case ${TCL_DEFS} in *TCL_FRAMEWORK*) if test -f "${TCL_BIN_DIR}/${TCL_LIB_FILE}"; then for i in "`cd "${TCL_BIN_DIR}"; pwd`" \ "`cd "${TCL_BIN_DIR}"/../..; pwd`"; do if test "`basename "$i"`" = "${TCL_LIB_FILE}.framework"; then TCL_LIB_SPEC="-F`dirname "$i" | sed -e 's/ /\\\\ /g'` -framework ${TCL_LIB_FILE}" break fi done fi if test -f "${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}"; then TCL_STUB_LIB_SPEC="-L`echo "${TCL_BIN_DIR}" | sed -e 's/ /\\\\ /g'` ${TCL_STUB_LIB_FLAG}" TCL_STUB_LIB_PATH="${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}" fi ;; esac fi AC_SUBST(TCL_VERSION) AC_SUBST(TCL_PATCH_LEVEL) AC_SUBST(TCL_BIN_DIR) AC_SUBST(TCL_SRC_DIR) AC_SUBST(TCL_LIB_FILE) AC_SUBST(TCL_LIB_FLAG) AC_SUBST(TCL_LIB_SPEC) AC_SUBST(TCL_STUB_LIB_FILE) AC_SUBST(TCL_STUB_LIB_FLAG) AC_SUBST(TCL_STUB_LIB_SPEC) AC_MSG_CHECKING([platform]) hold_cc=$CC; CC="$TCL_CC" AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[ #ifdef _WIN32 #error win32 #endif ]])],[ # first test we've already retrieved platform (cross-compile), fallback to unix otherwise: TEA_PLATFORM="${TEA_PLATFORM-unix}" CYGPATH=echo ],[ TEA_PLATFORM="windows" AC_CHECK_PROG(CYGPATH, cygpath, cygpath -m, echo) ]) CC=$hold_cc AC_MSG_RESULT($TEA_PLATFORM) # The BUILD_$pkg is to define the correct extern storage class # handling when making this package AC_DEFINE_UNQUOTED(BUILD_${PACKAGE_NAME}, [], [Building extension source?]) # Do this here as we have fully defined TEA_PLATFORM now if test "${TEA_PLATFORM}" = "windows" ; then EXEEXT=".exe" CLEANFILES="$CLEANFILES *.lib *.dll *.pdb *.exp" fi # TEA specific: AC_SUBST(CLEANFILES) AC_SUBST(TCL_LIBS) AC_SUBST(TCL_DEFS) AC_SUBST(TCL_EXTRA_CFLAGS) AC_SUBST(TCL_LD_FLAGS) AC_SUBST(TCL_SHLIB_LD_LIBS) ]) #------------------------------------------------------------------------ # TEA_LOAD_TKCONFIG -- # # Load the tkConfig.sh file # # Arguments: # # Requires the following vars to be set: # TK_BIN_DIR # # Results: # # Sets the following vars that should be in tkConfig.sh: # TK_BIN_DIR #------------------------------------------------------------------------ AC_DEFUN([TEA_LOAD_TKCONFIG], [ AC_MSG_CHECKING([for existence of ${TK_BIN_DIR}/tkConfig.sh]) if test -f "${TK_BIN_DIR}/tkConfig.sh" ; then AC_MSG_RESULT([loading]) . "${TK_BIN_DIR}/tkConfig.sh" else AC_MSG_RESULT([could not find ${TK_BIN_DIR}/tkConfig.sh]) fi # If the TK_BIN_DIR is the build directory (not the install directory), # then set the common variable name to the value of the build variables. # For example, the variable TK_LIB_SPEC will be set to the value # of TK_BUILD_LIB_SPEC. An extension should make use of TK_LIB_SPEC # instead of TK_BUILD_LIB_SPEC since it will work with both an # installed and uninstalled version of Tcl. if test -f "${TK_BIN_DIR}/Makefile" ; then TK_LIB_SPEC="${TK_BUILD_LIB_SPEC}" TK_STUB_LIB_SPEC="${TK_BUILD_STUB_LIB_SPEC}" TK_STUB_LIB_PATH="${TK_BUILD_STUB_LIB_PATH}" elif test "`uname -s`" = "Darwin"; then # If Tk was built as a framework, attempt to use the libraries # from the framework at the given location so that linking works # against Tk.framework installed in an arbitrary location. case ${TK_DEFS} in *TK_FRAMEWORK*) if test -f "${TK_BIN_DIR}/${TK_LIB_FILE}"; then for i in "`cd "${TK_BIN_DIR}"; pwd`" \ "`cd "${TK_BIN_DIR}"/../..; pwd`"; do if test "`basename "$i"`" = "${TK_LIB_FILE}.framework"; then TK_LIB_SPEC="-F`dirname "$i" | sed -e 's/ /\\\\ /g'` -framework ${TK_LIB_FILE}" break fi done fi if test -f "${TK_BIN_DIR}/${TK_STUB_LIB_FILE}"; then TK_STUB_LIB_SPEC="-L` echo "${TK_BIN_DIR}" | sed -e 's/ /\\\\ /g'` ${TK_STUB_LIB_FLAG}" TK_STUB_LIB_PATH="${TK_BIN_DIR}/${TK_STUB_LIB_FILE}" fi ;; esac fi # TEA specific: Ensure windowingsystem is defined if test "${TEA_PLATFORM}" = "unix" ; then case ${TK_DEFS} in *MAC_OSX_TK*) AC_DEFINE(MAC_OSX_TK, 1, [Are we building against Mac OS X TkAqua?]) TEA_WINDOWINGSYSTEM="aqua" ;; *) TEA_WINDOWINGSYSTEM="x11" ;; esac elif test "${TEA_PLATFORM}" = "windows" ; then TEA_WINDOWINGSYSTEM="win32" fi AC_SUBST(TK_VERSION) AC_SUBST(TK_BIN_DIR) AC_SUBST(TK_SRC_DIR) AC_SUBST(TK_LIB_FILE) AC_SUBST(TK_LIB_FLAG) AC_SUBST(TK_LIB_SPEC) AC_SUBST(TK_STUB_LIB_FILE) AC_SUBST(TK_STUB_LIB_FLAG) AC_SUBST(TK_STUB_LIB_SPEC) # TEA specific: AC_SUBST(TK_LIBS) AC_SUBST(TK_XINCLUDES) ]) #------------------------------------------------------------------------ # TEA_PROG_TCLSH # Determine the fully qualified path name of the tclsh executable # in the Tcl build directory or the tclsh installed in a bin # directory. This macro will correctly determine the name # of the tclsh executable even if tclsh has not yet been # built in the build directory. The tclsh found is always # associated with a tclConfig.sh file. This tclsh should be used # only for running extension test cases. It should never be # or generation of files (like pkgIndex.tcl) at build time. # # Arguments: # none # # Results: # Substitutes the following vars: # TCLSH_PROG #------------------------------------------------------------------------ AC_DEFUN([TEA_PROG_TCLSH], [ AC_MSG_CHECKING([for tclsh]) if test -f "${TCL_BIN_DIR}/Makefile" ; then # tclConfig.sh is in Tcl build directory if test "${TEA_PLATFORM}" = "windows"; then if test -f "${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${EXEEXT}" ; then TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${EXEEXT}" elif test -f "${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}s${EXEEXT}" ; then TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}s${EXEEXT}" elif test -f "${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}t${EXEEXT}" ; then TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}t${EXEEXT}" elif test -f "${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}st${EXEEXT}" ; then TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}st${EXEEXT}" fi else TCLSH_PROG="${TCL_BIN_DIR}/tclsh" fi else # tclConfig.sh is in install location if test "${TEA_PLATFORM}" = "windows"; then TCLSH_PROG="tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${EXEEXT}" else TCLSH_PROG="tclsh${TCL_MAJOR_VERSION}.${TCL_MINOR_VERSION}" fi list="`ls -d ${TCL_BIN_DIR}/../bin 2>/dev/null` \ `ls -d ${TCL_BIN_DIR}/.. 2>/dev/null` \ `ls -d ${TCL_PREFIX}/bin 2>/dev/null`" for i in $list ; do if test -f "$i/${TCLSH_PROG}" ; then REAL_TCL_BIN_DIR="`cd "$i"; pwd`/" break fi done TCLSH_PROG="${REAL_TCL_BIN_DIR}${TCLSH_PROG}" fi AC_MSG_RESULT([${TCLSH_PROG}]) AC_SUBST(TCLSH_PROG) ]) #------------------------------------------------------------------------ # TEA_PROG_WISH # Determine the fully qualified path name of the wish executable # in the Tk build directory or the wish installed in a bin # directory. This macro will correctly determine the name # of the wish executable even if wish has not yet been # built in the build directory. The wish found is always # associated with a tkConfig.sh file. This wish should be used # only for running extension test cases. It should never be # or generation of files (like pkgIndex.tcl) at build time. # # Arguments: # none # # Results: # Substitutes the following vars: # WISH_PROG #------------------------------------------------------------------------ AC_DEFUN([TEA_PROG_WISH], [ AC_MSG_CHECKING([for wish]) if test -f "${TK_BIN_DIR}/Makefile" ; then # tkConfig.sh is in Tk build directory if test "${TEA_PLATFORM}" = "windows"; then if test -f "${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${EXEEXT}" ; then WISH_PROG="${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${EXEEXT}" elif test -f "${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}s${EXEEXT}" ; then WISH_PROG="${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}$s{EXEEXT}" elif test -f "${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}t${EXEEXT}" ; then WISH_PROG="${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}t${EXEEXT}" elif test -f "${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}st${EXEEXT}" ; then WISH_PROG="${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}st${EXEEXT}" fi else WISH_PROG="${TK_BIN_DIR}/wish" fi else # tkConfig.sh is in install location if test "${TEA_PLATFORM}" = "windows"; then WISH_PROG="wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${EXEEXT}" else WISH_PROG="wish${TK_MAJOR_VERSION}.${TK_MINOR_VERSION}" fi list="`ls -d ${TK_BIN_DIR}/../bin 2>/dev/null` \ `ls -d ${TK_BIN_DIR}/.. 2>/dev/null` \ `ls -d ${TK_PREFIX}/bin 2>/dev/null`" for i in $list ; do if test -f "$i/${WISH_PROG}" ; then REAL_TK_BIN_DIR="`cd "$i"; pwd`/" break fi done WISH_PROG="${REAL_TK_BIN_DIR}${WISH_PROG}" fi AC_MSG_RESULT([${WISH_PROG}]) AC_SUBST(WISH_PROG) ]) #------------------------------------------------------------------------ # TEA_ENABLE_SHARED -- # # Allows the building of shared libraries # # Arguments: # none # # Results: # # Adds the following arguments to configure: # --enable-shared=yes|no # --enable-stubs=yes|no # # Defines the following vars: # STATIC_BUILD Used for building import/export libraries # on Windows. # # Sets the following vars: # SHARED_BUILD Value of 1 or 0 # STUBS_BUILD Value if 1 or 0 # USE_TCL_STUBS Value true: if SHARED_BUILD or --enable-stubs # USE_TCLOO_STUBS Value true: if SHARED_BUILD or --enable-stubs # USE_TK_STUBS Value true: if SHARED_BUILD or --enable-stubs # AND TEA_WINDOWING_SYSTEM != "" #------------------------------------------------------------------------ AC_DEFUN([TEA_ENABLE_SHARED], [ AC_MSG_CHECKING([how to build libraries]) AC_ARG_ENABLE(shared, AS_HELP_STRING([--enable-shared], [build and link with shared libraries (default: on)]), [shared_ok=$enableval], [shared_ok=yes]) if test "${enable_shared+set}" = set; then enableval="$enable_shared" shared_ok=$enableval else shared_ok=yes fi AC_ARG_ENABLE(stubs, AS_HELP_STRING([--enable-stubs], [build and link with stub libraries. Always true for shared builds (default: on)]), [stubs_ok=$enableval], [stubs_ok=yes]) if test "${enable_stubs+set}" = set; then enableval="$enable_stubs" stubs_ok=$enableval else stubs_ok=yes fi # Stubs are always enabled for shared builds if test "$shared_ok" = "yes" ; then AC_MSG_RESULT([shared]) SHARED_BUILD=1 STUBS_BUILD=1 else AC_MSG_RESULT([static]) SHARED_BUILD=0 AC_DEFINE(STATIC_BUILD, 1, [This a static build]) if test "$stubs_ok" = "yes" ; then STUBS_BUILD=1 else STUBS_BUILD=0 fi fi if test "${STUBS_BUILD}" = "1" ; then AC_DEFINE(USE_TCL_STUBS, 1, [Use Tcl stubs]) AC_DEFINE(USE_TCLOO_STUBS, 1, [Use TclOO stubs]) if test "${TEA_WINDOWINGSYSTEM}" != ""; then AC_DEFINE(USE_TK_STUBS, 1, [Use Tk stubs]) fi fi AC_SUBST(SHARED_BUILD) AC_SUBST(STUBS_BUILD) ]) #------------------------------------------------------------------------ # TEA_ENABLE_THREADS -- # # Specify if thread support should be enabled. If "yes" is specified # as an arg (optional), threads are enabled by default, "no" means # threads are disabled. "yes" is the default. # # TCL_THREADS is checked so that if you are compiling an extension # against a threaded core, your extension must be compiled threaded # as well. # # Note that it is legal to have a thread enabled extension run in a # threaded or non-threaded Tcl core, but a non-threaded extension may # only run in a non-threaded Tcl core. # # Arguments: # none # # Results: # # Adds the following arguments to configure: # --enable-threads # # Sets the following vars: # THREADS_LIBS Thread library(s) # # Defines the following vars: # TCL_THREADS # _REENTRANT # _THREAD_SAFE #------------------------------------------------------------------------ AC_DEFUN([TEA_ENABLE_THREADS], [ AC_ARG_ENABLE(threads, AS_HELP_STRING([--enable-threads], [build with threads (default: on)]), [tcl_ok=$enableval], [tcl_ok=yes]) if test "${enable_threads+set}" = set; then enableval="$enable_threads" tcl_ok=$enableval else tcl_ok=yes fi if test "$tcl_ok" = "yes" -o "${TCL_THREADS}" = 1; then TCL_THREADS=1 if test "${TEA_PLATFORM}" != "windows" ; then # We are always OK on Windows, so check what this platform wants: # USE_THREAD_ALLOC tells us to try the special thread-based # allocator that significantly reduces lock contention AC_DEFINE(USE_THREAD_ALLOC, 1, [Do we want to use the threaded memory allocator?]) AC_DEFINE(_REENTRANT, 1, [Do we want the reentrant OS API?]) if test "`uname -s`" = "SunOS" ; then AC_DEFINE(_POSIX_PTHREAD_SEMANTICS, 1, [Do we really want to follow the standard? Yes we do!]) fi AC_DEFINE(_THREAD_SAFE, 1, [Do we want the thread-safe OS API?]) AC_CHECK_LIB(pthread,pthread_mutex_init,tcl_ok=yes,tcl_ok=no) if test "$tcl_ok" = "no"; then # Check a little harder for __pthread_mutex_init in the same # library, as some systems hide it there until pthread.h is # defined. We could alternatively do an AC_TRY_COMPILE with # pthread.h, but that will work with libpthread really doesn't # exist, like AIX 4.2. [Bug: 4359] AC_CHECK_LIB(pthread, __pthread_mutex_init, tcl_ok=yes, tcl_ok=no) fi if test "$tcl_ok" = "yes"; then # The space is needed THREADS_LIBS=" -lpthread" else AC_CHECK_LIB(pthreads, pthread_mutex_init, tcl_ok=yes, tcl_ok=no) if test "$tcl_ok" = "yes"; then # The space is needed THREADS_LIBS=" -lpthreads" else AC_CHECK_LIB(c, pthread_mutex_init, tcl_ok=yes, tcl_ok=no) if test "$tcl_ok" = "no"; then AC_CHECK_LIB(c_r, pthread_mutex_init, tcl_ok=yes, tcl_ok=no) if test "$tcl_ok" = "yes"; then # The space is needed THREADS_LIBS=" -pthread" else TCL_THREADS=0 AC_MSG_WARN([Do not know how to find pthread lib on your system - thread support disabled]) fi fi fi fi fi else TCL_THREADS=0 fi # Do checking message here to not mess up interleaved configure output AC_MSG_CHECKING([for building with threads]) if test "${TCL_THREADS}" = 1; then AC_DEFINE(TCL_THREADS, 1, [Are we building with threads enabled?]) AC_MSG_RESULT([yes (default)]) else AC_MSG_RESULT([no]) fi # TCL_THREADS sanity checking. See if our request for building with # threads is the same as the way Tcl was built. If not, warn the user. case ${TCL_DEFS} in *THREADS=1*) if test "${TCL_THREADS}" = "0"; then AC_MSG_WARN([ Building ${PACKAGE_NAME} without threads enabled, but building against Tcl that IS thread-enabled. It is recommended to use --enable-threads.]) fi ;; esac AC_SUBST(TCL_THREADS) ]) #------------------------------------------------------------------------ # TEA_ENABLE_SYMBOLS -- # # Specify if debugging symbols should be used. # Memory (TCL_MEM_DEBUG) debugging can also be enabled. # # Arguments: # none # # TEA varies from core Tcl in that C|LDFLAGS_DEFAULT receives # the value of C|LDFLAGS_OPTIMIZE|DEBUG already substituted. # Requires the following vars to be set in the Makefile: # CFLAGS_DEFAULT # LDFLAGS_DEFAULT # # Results: # # Adds the following arguments to configure: # --enable-symbols # # Defines the following vars: # CFLAGS_DEFAULT Sets to $(CFLAGS_DEBUG) if true # Sets to "$(CFLAGS_OPTIMIZE) -DNDEBUG" if false # LDFLAGS_DEFAULT Sets to $(LDFLAGS_DEBUG) if true # Sets to $(LDFLAGS_OPTIMIZE) if false #------------------------------------------------------------------------ AC_DEFUN([TEA_ENABLE_SYMBOLS], [ dnl TEA specific: Make sure we are initialized AC_REQUIRE([TEA_CONFIG_CFLAGS]) AC_MSG_CHECKING([for build with symbols]) AC_ARG_ENABLE(symbols, AS_HELP_STRING([--enable-symbols], [build with debugging symbols (default: off)]), [tcl_ok=$enableval], [tcl_ok=no]) if test "$tcl_ok" = "no"; then CFLAGS_DEFAULT="${CFLAGS_OPTIMIZE} -DNDEBUG" LDFLAGS_DEFAULT="${LDFLAGS_OPTIMIZE}" AC_MSG_RESULT([no]) AC_DEFINE(TCL_CFG_OPTIMIZED, 1, [Is this an optimized build?]) else CFLAGS_DEFAULT="${CFLAGS_DEBUG}" LDFLAGS_DEFAULT="${LDFLAGS_DEBUG}" if test "$tcl_ok" = "yes"; then AC_MSG_RESULT([yes (standard debugging)]) fi fi AC_SUBST(CFLAGS_DEFAULT) AC_SUBST(LDFLAGS_DEFAULT) if test "$tcl_ok" = "mem" -o "$tcl_ok" = "all"; then AC_DEFINE(TCL_MEM_DEBUG, 1, [Is memory debugging enabled?]) fi if test "$tcl_ok" != "yes" -a "$tcl_ok" != "no"; then if test "$tcl_ok" = "all"; then AC_MSG_RESULT([enabled symbols mem debugging]) else AC_MSG_RESULT([enabled $tcl_ok debugging]) fi fi ]) #------------------------------------------------------------------------ # TEA_ENABLE_LANGINFO -- # # Allows use of modern nl_langinfo check for better l10n. # This is only relevant for Unix. # # Arguments: # none # # Results: # # Adds the following arguments to configure: # --enable-langinfo=yes|no (default is yes) # # Defines the following vars: # HAVE_LANGINFO Triggers use of nl_langinfo if defined. #------------------------------------------------------------------------ AC_DEFUN([TEA_ENABLE_LANGINFO], [ AC_ARG_ENABLE(langinfo, AS_HELP_STRING([--enable-langinfo], [use nl_langinfo if possible to determine encoding at startup, otherwise use old heuristic (default: on)]), [langinfo_ok=$enableval], [langinfo_ok=yes]) HAVE_LANGINFO=0 if test "$langinfo_ok" = "yes"; then AC_CHECK_HEADER(langinfo.h,[langinfo_ok=yes],[langinfo_ok=no]) fi AC_MSG_CHECKING([whether to use nl_langinfo]) if test "$langinfo_ok" = "yes"; then AC_CACHE_VAL(tcl_cv_langinfo_h, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[nl_langinfo(CODESET);]])], [tcl_cv_langinfo_h=yes],[tcl_cv_langinfo_h=no])]) AC_MSG_RESULT([$tcl_cv_langinfo_h]) if test $tcl_cv_langinfo_h = yes; then AC_DEFINE(HAVE_LANGINFO, 1, [Do we have nl_langinfo()?]) fi else AC_MSG_RESULT([$langinfo_ok]) fi ]) #-------------------------------------------------------------------- # TEA_CONFIG_SYSTEM # # Determine what the system is (some things cannot be easily checked # on a feature-driven basis, alas). This can usually be done via the # "uname" command. # # Arguments: # none # # Results: # Defines the following var: # # system - System/platform/version identification code. # #-------------------------------------------------------------------- AC_DEFUN([TEA_CONFIG_SYSTEM], [ AC_CACHE_CHECK([system version], tcl_cv_sys_version, [ # TEA specific: if test "${TEA_PLATFORM}" = "windows" ; then tcl_cv_sys_version=windows else tcl_cv_sys_version=`uname -s`-`uname -r` if test "$?" -ne 0 ; then AC_MSG_WARN([can't find uname command]) tcl_cv_sys_version=unknown else if test "`uname -s`" = "AIX" ; then tcl_cv_sys_version=AIX-`uname -v`.`uname -r` fi if test "`uname -s`" = "NetBSD" -a -f /etc/debian_version ; then tcl_cv_sys_version=NetBSD-Debian fi fi fi ]) system=$tcl_cv_sys_version ]) #-------------------------------------------------------------------- # TEA_CONFIG_CFLAGS # # Try to determine the proper flags to pass to the compiler # for building shared libraries and other such nonsense. # # Arguments: # none # # Results: # # Defines and substitutes the following vars: # # DL_OBJS, DL_LIBS - removed for TEA, only needed by core. # LDFLAGS - Flags to pass to the compiler when linking object # files into an executable application binary such # as tclsh. # LD_SEARCH_FLAGS-Flags to pass to ld, such as "-R /usr/local/tcl/lib", # that tell the run-time dynamic linker where to look # for shared libraries such as libtcl.so. Depends on # the variable LIB_RUNTIME_DIR in the Makefile. Could # be the same as CC_SEARCH_FLAGS if ${CC} is used to link. # CC_SEARCH_FLAGS-Flags to pass to ${CC}, such as "-Wl,-rpath,/usr/local/tcl/lib", # that tell the run-time dynamic linker where to look # for shared libraries such as libtcl.so. Depends on # the variable LIB_RUNTIME_DIR in the Makefile. # SHLIB_CFLAGS - Flags to pass to cc when compiling the components # of a shared library (may request position-independent # code, among other things). # SHLIB_LD - Base command to use for combining object files # into a shared library. # SHLIB_LD_LIBS - Dependent libraries for the linker to scan when # creating shared libraries. This symbol typically # goes at the end of the "ld" commands that build # shared libraries. The value of the symbol defaults to # "${LIBS}" if all of the dependent libraries should # be specified when creating a shared library. If # dependent libraries should not be specified (as on # SunOS 4.x, where they cause the link to fail, or in # general if Tcl and Tk aren't themselves shared # libraries), then this symbol has an empty string # as its value. # SHLIB_SUFFIX - Suffix to use for the names of dynamically loadable # extensions. An empty string means we don't know how # to use shared libraries on this platform. # LIB_SUFFIX - Specifies everything that comes after the "libfoo" # in a static or shared library name, using the $PACKAGE_VERSION variable # to put the version in the right place. This is used # by platforms that need non-standard library names. # Examples: ${PACKAGE_VERSION}.so.1.1 on NetBSD, since it needs # to have a version after the .so, and ${PACKAGE_VERSION}.a # on AIX, since a shared library needs to have # a .a extension whereas shared objects for loadable # extensions have a .so extension. Defaults to # ${PACKAGE_VERSION}${SHLIB_SUFFIX}. # CFLAGS_DEBUG - # Flags used when running the compiler in debug mode # CFLAGS_OPTIMIZE - # Flags used when running the compiler in optimize mode # CFLAGS - Additional CFLAGS added as necessary (usually 64-bit) #-------------------------------------------------------------------- AC_DEFUN([TEA_CONFIG_CFLAGS], [ dnl TEA specific: Make sure we are initialized AC_REQUIRE([TEA_INIT]) # Step 0.a: Enable 64 bit support? AC_MSG_CHECKING([if 64bit support is requested]) AC_ARG_ENABLE(64bit, AS_HELP_STRING([--enable-64bit], [enable 64bit support (default: off)]), [do64bit=$enableval], [do64bit=no]) AC_MSG_RESULT([$do64bit]) # Step 0.b: Enable Solaris 64 bit VIS support? AC_MSG_CHECKING([if 64bit Sparc VIS support is requested]) AC_ARG_ENABLE(64bit-vis, AS_HELP_STRING([--enable-64bit-vis], [enable 64bit Sparc VIS support (default: off)]), [do64bitVIS=$enableval], [do64bitVIS=no]) AC_MSG_RESULT([$do64bitVIS]) # Force 64bit on with VIS AS_IF([test "$do64bitVIS" = "yes"], [do64bit=yes]) # Step 0.c: Check if visibility support is available. Do this here so # that platform specific alternatives can be used below if this fails. AC_CACHE_CHECK([if compiler supports visibility "hidden"], tcl_cv_cc_visibility_hidden, [ hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Werror" AC_LINK_IFELSE([AC_LANG_PROGRAM([[ extern __attribute__((__visibility__("hidden"))) void f(void); void f(void) {}]], [[f();]])],[tcl_cv_cc_visibility_hidden=yes], [tcl_cv_cc_visibility_hidden=no]) CFLAGS=$hold_cflags]) AS_IF([test $tcl_cv_cc_visibility_hidden = yes], [ AC_DEFINE(MODULE_SCOPE, [extern __attribute__((__visibility__("hidden")))], [Compiler support for module scope symbols]) AC_DEFINE(HAVE_HIDDEN, [1], [Compiler support for module scope symbols]) ]) # Step 0.d: Disable -rpath support? AC_MSG_CHECKING([if rpath support is requested]) AC_ARG_ENABLE(rpath, AS_HELP_STRING([--disable-rpath], [disable rpath support (default: on)]), [doRpath=$enableval], [doRpath=yes]) AC_MSG_RESULT([$doRpath]) # Set the variable "system" to hold the name and version number # for the system. TEA_CONFIG_SYSTEM # Require ranlib early so we can override it in special cases below. AC_REQUIRE([AC_PROG_RANLIB]) # Set configuration options based on system name and version. # This is similar to Tcl's unix/tcl.m4 except that we've added a # "windows" case and removed some core-only vars. do64bit_ok=no # default to '{$LIBS}' and set to "" on per-platform necessary basis SHLIB_LD_LIBS='${LIBS}' # When ld needs options to work in 64-bit mode, put them in # LDFLAGS_ARCH so they eventually end up in LDFLAGS even if [load] # is disabled by the user. [Bug 1016796] LDFLAGS_ARCH="" UNSHARED_LIB_SUFFIX="" # TEA specific: use PACKAGE_VERSION instead of VERSION TCL_TRIM_DOTS='`echo ${PACKAGE_VERSION} | tr -d .`' ECHO_VERSION='`echo ${PACKAGE_VERSION}`' TCL_LIB_VERSIONS_OK=ok CFLAGS_DEBUG=-g AS_IF([test "$GCC" = yes], [ CFLAGS_OPTIMIZE=-O2 CFLAGS_WARNING="-Wall" ], [ CFLAGS_OPTIMIZE=-O CFLAGS_WARNING="" ]) AC_CHECK_TOOL(AR, ar) STLIB_LD='${AR} cr' LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH" AS_IF([test "x$SHLIB_VERSION" = x],[SHLIB_VERSION=""],[SHLIB_VERSION=".$SHLIB_VERSION"]) case $system in # TEA specific: windows) MACHINE="X86" if test "$do64bit" != "no" ; then case "$do64bit" in amd64|x64|yes) MACHINE="AMD64" ; # default to AMD64 64-bit build ;; arm64|aarch64) MACHINE="ARM64" ;; ia64) MACHINE="IA64" ;; esac fi if test "$GCC" != "yes" ; then if test "${SHARED_BUILD}" = "0" ; then runtime=-MT else runtime=-MD fi case "x`echo \${VisualStudioVersion}`" in x1[[4-9]]*) lflags="${lflags} -nodefaultlib:libucrt.lib" TEA_ADD_LIBS([ucrt.lib]) ;; *) ;; esac if test "$do64bit" != "no" ; then CC="cl.exe" RC="rc.exe" lflags="${lflags} -nologo -MACHINE:${MACHINE} " LINKBIN="link.exe" CFLAGS_DEBUG="-nologo -Zi -Od -W3 ${runtime}d" CFLAGS_OPTIMIZE="-nologo -O2 -W2 ${runtime}" # Avoid 'unresolved external symbol __security_cookie' # errors, c.f. http://support.microsoft.com/?id=894573 TEA_ADD_LIBS([bufferoverflowU.lib]) else RC="rc" lflags="${lflags} -nologo" LINKBIN="link" CFLAGS_DEBUG="-nologo -Z7 -Od -W3 -WX ${runtime}d" CFLAGS_OPTIMIZE="-nologo -O2 -W2 ${runtime}" fi fi if test "$GCC" = "yes"; then # mingw gcc mode AC_CHECK_TOOL(RC, windres) CFLAGS_DEBUG="-g" CFLAGS_OPTIMIZE="-O2 -fomit-frame-pointer" SHLIB_LD='${CC} -shared' UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' LDFLAGS_CONSOLE="-wl,--subsystem,console ${lflags}" LDFLAGS_WINDOW="-wl,--subsystem,windows ${lflags}" AC_CACHE_CHECK(for cross-compile version of gcc, ac_cv_cross, AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #ifdef _WIN32 #error cross-compiler #endif ]], [[]])], [ac_cv_cross=yes], [ac_cv_cross=no]) ) if test "$ac_cv_cross" = "yes"; then case "$do64bit" in amd64|x64|yes) CC="x86_64-w64-mingw32-${CC}" LD="x86_64-w64-mingw32-ld" AR="x86_64-w64-mingw32-ar" RANLIB="x86_64-w64-mingw32-ranlib" RC="x86_64-w64-mingw32-windres" ;; arm64|aarch64) CC="aarch64-w64-mingw32-clang" LD="aarch64-w64-mingw32-ld" AR="aarch64-w64-mingw32-ar" RANLIB="aarch64-w64-mingw32-ranlib" RC="aarch64-w64-mingw32-windres" ;; *) CC="i686-w64-mingw32-${CC}" LD="i686-w64-mingw32-ld" AR="i686-w64-mingw32-ar" RANLIB="i686-w64-mingw32-ranlib" RC="i686-w64-mingw32-windres" ;; esac fi else SHLIB_LD="${LINKBIN} -dll ${lflags}" # link -lib only works when -lib is the first arg STLIB_LD="${LINKBIN} -lib ${lflags}" UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.lib' PATHTYPE=-w # For information on what debugtype is most useful, see: # http://msdn.microsoft.com/library/en-us/dnvc60/html/gendepdebug.asp # and also # http://msdn2.microsoft.com/en-us/library/y0zzbyt4%28VS.80%29.aspx # This essentially turns it all on. LDFLAGS_DEBUG="-debug -debugtype:cv" LDFLAGS_OPTIMIZE="-release" LDFLAGS_CONSOLE="-link -subsystem:console ${lflags}" LDFLAGS_WINDOW="-link -subsystem:windows ${lflags}" fi SHLIB_SUFFIX=".dll" SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.dll' TCL_LIB_VERSIONS_OK=nodots ;; AIX-*) AS_IF([test "$GCC" != "yes"], [ # AIX requires the _r compiler when gcc isn't being used case "${CC}" in *_r|*_r\ *) # ok ... ;; *) # Make sure only first arg gets _r CC=`echo "$CC" | sed -e 's/^\([[^ ]]*\)/\1_r/'` ;; esac AC_MSG_RESULT([Using $CC for compiling with threads]) ]) LIBS="$LIBS -lc" SHLIB_CFLAGS="" SHLIB_SUFFIX=".so" LD_LIBRARY_PATH_VAR="LIBPATH" # Check to enable 64-bit flags for compiler/linker AS_IF([test "$do64bit" = yes], [ AS_IF([test "$GCC" = yes], [ AC_MSG_WARN([64bit mode not supported with GCC on $system]) ], [ do64bit_ok=yes CFLAGS="$CFLAGS -q64" LDFLAGS_ARCH="-q64" RANLIB="${RANLIB} -X64" AR="${AR} -X64" SHLIB_LD_FLAGS="-b64" ]) ]) AS_IF([test "`uname -m`" = ia64], [ # AIX-5 uses ELF style dynamic libraries on IA-64, but not PPC SHLIB_LD="/usr/ccs/bin/ld -G -z text" AS_IF([test "$GCC" = yes], [ CC_SEARCH_FLAGS='"-Wl,-R,${LIB_RUNTIME_DIR}"' ], [ CC_SEARCH_FLAGS='"-R${LIB_RUNTIME_DIR}"' ]) LD_SEARCH_FLAGS='-R "${LIB_RUNTIME_DIR}"' ], [ AS_IF([test "$GCC" = yes], [ SHLIB_LD='${CC} -shared -Wl,-bexpall' ], [ SHLIB_LD="/bin/ld -bhalt:4 -bM:SRE -bexpall -H512 -T512 -bnoentry" LDFLAGS="$LDFLAGS -brtl" ]) SHLIB_LD="${SHLIB_LD} ${SHLIB_LD_FLAGS}" CC_SEARCH_FLAGS='"-L${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} ]) ;; BeOS*) SHLIB_CFLAGS="-fPIC" SHLIB_LD='${CC} -nostart' SHLIB_SUFFIX=".so" #----------------------------------------------------------- # Check for inet_ntoa in -lbind, for BeOS (which also needs # -lsocket, even if the network functions are in -lnet which # is always linked to, for compatibility. #----------------------------------------------------------- AC_CHECK_LIB(bind, inet_ntoa, [LIBS="$LIBS -lbind -lsocket"]) ;; BSD/OS-2.1*|BSD/OS-3*) SHLIB_CFLAGS="" SHLIB_LD="shlicc -r" SHLIB_SUFFIX=".so" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; BSD/OS-4.*) SHLIB_CFLAGS="-export-dynamic -fPIC" SHLIB_LD='${CC} -shared' SHLIB_SUFFIX=".so" LDFLAGS="$LDFLAGS -export-dynamic" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; CYGWIN_*) SHLIB_CFLAGS="" SHLIB_LD='${CC} -shared' SHLIB_SUFFIX=".dll" SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -Wl,--out-implib,\$[@].a" EXEEXT=".exe" do64bit_ok=yes CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; dgux*) SHLIB_CFLAGS="-K PIC" SHLIB_LD='${CC} -G' SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; Haiku*) LDFLAGS="$LDFLAGS -Wl,--export-dynamic" SHLIB_CFLAGS="-fPIC" SHLIB_SUFFIX=".so" SHLIB_LD='${CC} ${CFLAGS} ${LDFLAGS} -shared' AC_CHECK_LIB(network, inet_ntoa, [LIBS="$LIBS -lnetwork"]) ;; HP-UX-*.11.*) # Use updated header definitions where possible AC_DEFINE(_XOPEN_SOURCE_EXTENDED, 1, [Do we want to use the XOPEN network library?]) # TEA specific: Needed by Tcl, but not most extensions #AC_DEFINE(_XOPEN_SOURCE, 1, [Do we want to use the XOPEN network library?]) #LIBS="$LIBS -lxnet" # Use the XOPEN network library AS_IF([test "`uname -m`" = ia64], [ SHLIB_SUFFIX=".so" ], [ SHLIB_SUFFIX=".sl" ]) AC_CHECK_LIB(dld, shl_load, tcl_ok=yes, tcl_ok=no) AS_IF([test "$tcl_ok" = yes], [ SHLIB_CFLAGS="+z" SHLIB_LD="ld -b" LDFLAGS="$LDFLAGS -Wl,-E" CC_SEARCH_FLAGS='"-Wl,+s,+b,${LIB_RUNTIME_DIR}:."' LD_SEARCH_FLAGS='+s +b "${LIB_RUNTIME_DIR}:."' LD_LIBRARY_PATH_VAR="SHLIB_PATH" ]) AS_IF([test "$GCC" = yes], [ SHLIB_LD='${CC} -shared' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} ], [ CFLAGS="$CFLAGS -z" ]) # Check to enable 64-bit flags for compiler/linker AS_IF([test "$do64bit" = "yes"], [ AS_IF([test "$GCC" = yes], [ case `${CC} -dumpmachine` in hppa64*) # 64-bit gcc in use. Fix flags for GNU ld. do64bit_ok=yes SHLIB_LD='${CC} -shared' AS_IF([test $doRpath = yes], [ CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"']) LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} ;; *) AC_MSG_WARN([64bit mode not supported with GCC on $system]) ;; esac ], [ do64bit_ok=yes CFLAGS="$CFLAGS +DD64" LDFLAGS_ARCH="+DD64" ]) ]) ;; HP-UX-*.08.*|HP-UX-*.09.*|HP-UX-*.10.*) SHLIB_SUFFIX=".sl" AC_CHECK_LIB(dld, shl_load, tcl_ok=yes, tcl_ok=no) AS_IF([test "$tcl_ok" = yes], [ SHLIB_CFLAGS="+z" SHLIB_LD="ld -b" SHLIB_LD_LIBS="" LDFLAGS="$LDFLAGS -Wl,-E" CC_SEARCH_FLAGS='"-Wl,+s,+b,${LIB_RUNTIME_DIR}:."' LD_SEARCH_FLAGS='+s +b "${LIB_RUNTIME_DIR}:."' LD_LIBRARY_PATH_VAR="SHLIB_PATH" ]) ;; IRIX-5.*) SHLIB_CFLAGS="" SHLIB_LD="ld -shared -rdata_shared" SHLIB_SUFFIX=".so" AC_LIBOBJ(mkstemp) AS_IF([test $doRpath = yes], [ CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS='-rpath "${LIB_RUNTIME_DIR}"']) ;; IRIX-6.*) SHLIB_CFLAGS="" SHLIB_LD="ld -n32 -shared -rdata_shared" SHLIB_SUFFIX=".so" AS_IF([test $doRpath = yes], [ CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS='-rpath "${LIB_RUNTIME_DIR}"']) AS_IF([test "$GCC" = yes], [ CFLAGS="$CFLAGS -mabi=n32" LDFLAGS="$LDFLAGS -mabi=n32" ], [ case $system in IRIX-6.3) # Use to build 6.2 compatible binaries on 6.3. CFLAGS="$CFLAGS -n32 -D_OLD_TERMIOS" ;; *) CFLAGS="$CFLAGS -n32" ;; esac LDFLAGS="$LDFLAGS -n32" ]) ;; IRIX64-6.*) SHLIB_CFLAGS="" SHLIB_LD="ld -n32 -shared -rdata_shared" SHLIB_SUFFIX=".so" AS_IF([test $doRpath = yes], [ CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS='-rpath "${LIB_RUNTIME_DIR}"']) # Check to enable 64-bit flags for compiler/linker AS_IF([test "$do64bit" = yes], [ AS_IF([test "$GCC" = yes], [ AC_MSG_WARN([64bit mode not supported by gcc]) ], [ do64bit_ok=yes SHLIB_LD="ld -64 -shared -rdata_shared" CFLAGS="$CFLAGS -64" LDFLAGS_ARCH="-64" ]) ]) ;; Linux*|GNU*|NetBSD-Debian|DragonFly-*|FreeBSD-*) SHLIB_CFLAGS="-fPIC" SHLIB_SUFFIX=".so" # TEA specific: CFLAGS_OPTIMIZE="-O2 -fomit-frame-pointer" # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS SHLIB_LD='${CC} ${CFLAGS} ${LDFLAGS_DEFAULT} -shared' LDFLAGS="$LDFLAGS -Wl,--export-dynamic" case $system in DragonFly-*|FreeBSD-*) AS_IF([test "${TCL_THREADS}" = "1"], [ # The -pthread needs to go in the LDFLAGS, not LIBS LIBS=`echo $LIBS | sed s/-pthread//` CFLAGS="$CFLAGS $PTHREAD_CFLAGS" LDFLAGS="$LDFLAGS $PTHREAD_LIBS"]) ;; esac AS_IF([test $doRpath = yes], [ CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"']) LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} AS_IF([test "`uname -m`" = "alpha"], [CFLAGS="$CFLAGS -mieee"]) AS_IF([test $do64bit = yes], [ AC_CACHE_CHECK([if compiler accepts -m64 flag], tcl_cv_cc_m64, [ hold_cflags=$CFLAGS CFLAGS="$CFLAGS -m64" AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])], [tcl_cv_cc_m64=yes],[tcl_cv_cc_m64=no]) CFLAGS=$hold_cflags]) AS_IF([test $tcl_cv_cc_m64 = yes], [ CFLAGS="$CFLAGS -m64" do64bit_ok=yes ]) ]) # The combo of gcc + glibc has a bug related to inlining of # functions like strtod(). The -fno-builtin flag should address # this problem but it does not work. The -fno-inline flag is kind # of overkill but it works. Disable inlining only when one of the # files in compat/*.c is being linked in. AS_IF([test x"${USE_COMPAT}" != x],[CFLAGS="$CFLAGS -fno-inline"]) ;; Lynx*) SHLIB_CFLAGS="-fPIC" SHLIB_SUFFIX=".so" CFLAGS_OPTIMIZE=-02 SHLIB_LD='${CC} -shared' LD_FLAGS="-Wl,--export-dynamic" AS_IF([test $doRpath = yes], [ CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"']) ;; OpenBSD-*) arch=`arch -s` case "$arch" in alpha|sparc64) SHLIB_CFLAGS="-fPIC" ;; *) SHLIB_CFLAGS="-fpic" ;; esac SHLIB_LD='${CC} ${SHLIB_CFLAGS} -shared' SHLIB_SUFFIX=".so" AS_IF([test $doRpath = yes], [ CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"']) LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so${SHLIB_VERSION}' LDFLAGS="$LDFLAGS -Wl,-export-dynamic" CFLAGS_OPTIMIZE="-O2" # On OpenBSD: Compile with -pthread # Don't link with -lpthread LIBS=`echo $LIBS | sed s/-lpthread//` CFLAGS="$CFLAGS -pthread" # OpenBSD doesn't do version numbers with dots. UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' TCL_LIB_VERSIONS_OK=nodots ;; NetBSD-*) # NetBSD has ELF and can use 'cc -shared' to build shared libs SHLIB_CFLAGS="-fPIC" SHLIB_LD='${CC} ${SHLIB_CFLAGS} -shared' SHLIB_SUFFIX=".so" LDFLAGS="$LDFLAGS -export-dynamic" AS_IF([test $doRpath = yes], [ CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"']) LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} # The -pthread needs to go in the CFLAGS, not LIBS LIBS=`echo $LIBS | sed s/-pthread//` CFLAGS="$CFLAGS -pthread" LDFLAGS="$LDFLAGS -pthread" ;; Darwin-*) CFLAGS_OPTIMIZE="-Os" SHLIB_CFLAGS="-fno-common" # To avoid discrepancies between what headers configure sees during # preprocessing tests and compiling tests, move any -isysroot and # -mmacosx-version-min flags from CFLAGS to CPPFLAGS: CPPFLAGS="${CPPFLAGS} `echo " ${CFLAGS}" | \ awk 'BEGIN {FS=" +-";ORS=" "}; {for (i=2;i<=NF;i++) \ if ([$]i~/^(isysroot|mmacosx-version-min)/) print "-"[$]i}'`" CFLAGS="`echo " ${CFLAGS}" | \ awk 'BEGIN {FS=" +-";ORS=" "}; {for (i=2;i<=NF;i++) \ if (!([$]i~/^(isysroot|mmacosx-version-min)/)) print "-"[$]i}'`" AS_IF([test $do64bit = yes], [ case `arch` in ppc) AC_CACHE_CHECK([if compiler accepts -arch ppc64 flag], tcl_cv_cc_arch_ppc64, [ hold_cflags=$CFLAGS CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5" AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])], [tcl_cv_cc_arch_ppc64=yes],[tcl_cv_cc_arch_ppc64=no]) CFLAGS=$hold_cflags]) AS_IF([test $tcl_cv_cc_arch_ppc64 = yes], [ CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5" do64bit_ok=yes ]);; i386) AC_CACHE_CHECK([if compiler accepts -arch x86_64 flag], tcl_cv_cc_arch_x86_64, [ hold_cflags=$CFLAGS CFLAGS="$CFLAGS -arch x86_64" AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])], [tcl_cv_cc_arch_x86_64=yes],[tcl_cv_cc_arch_x86_64=no]) CFLAGS=$hold_cflags]) AS_IF([test $tcl_cv_cc_arch_x86_64 = yes], [ CFLAGS="$CFLAGS -arch x86_64" do64bit_ok=yes ]);; *) AC_MSG_WARN([Don't know how enable 64-bit on architecture `arch`]);; esac ], [ # Check for combined 32-bit and 64-bit fat build AS_IF([echo "$CFLAGS " |grep -E -q -- '-arch (ppc64|x86_64) ' \ && echo "$CFLAGS " |grep -E -q -- '-arch (ppc|i386) '], [ fat_32_64=yes]) ]) # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS SHLIB_LD='${CC} -dynamiclib ${CFLAGS} ${LDFLAGS_DEFAULT}' AC_CACHE_CHECK([if ld accepts -single_module flag], tcl_cv_ld_single_module, [ hold_ldflags=$LDFLAGS LDFLAGS="$LDFLAGS -dynamiclib -Wl,-single_module" AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[int i;]])], [tcl_cv_ld_single_module=yes],[tcl_cv_ld_single_module=no]) LDFLAGS=$hold_ldflags]) AS_IF([test $tcl_cv_ld_single_module = yes], [ SHLIB_LD="${SHLIB_LD} -Wl,-single_module" ]) # TEA specific: link shlib with current and compatibility version flags vers=`echo ${PACKAGE_VERSION} | sed -e 's/^\([[0-9]]\{1,5\}\)\(\(\.[[0-9]]\{1,3\}\)\{0,2\}\).*$/\1\2/p' -e d` SHLIB_LD="${SHLIB_LD} -current_version ${vers:-0} -compatibility_version ${vers:-0}" SHLIB_SUFFIX=".dylib" LDFLAGS="$LDFLAGS -headerpad_max_install_names" AC_CACHE_CHECK([if ld accepts -search_paths_first flag], tcl_cv_ld_search_paths_first, [ hold_ldflags=$LDFLAGS LDFLAGS="$LDFLAGS -Wl,-search_paths_first" AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[int i;]])], [tcl_cv_ld_search_paths_first=yes],[tcl_cv_ld_search_paths_first=no]) LDFLAGS=$hold_ldflags]) AS_IF([test $tcl_cv_ld_search_paths_first = yes], [ LDFLAGS="$LDFLAGS -Wl,-search_paths_first" ]) AS_IF([test "$tcl_cv_cc_visibility_hidden" != yes], [ AC_DEFINE(MODULE_SCOPE, [__private_extern__], [Compiler support for module scope symbols]) tcl_cv_cc_visibility_hidden=yes ]) CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" LD_LIBRARY_PATH_VAR="DYLD_LIBRARY_PATH" # TEA specific: for combined 32 & 64 bit fat builds of Tk # extensions, verify that 64-bit build is possible. AS_IF([test "$fat_32_64" = yes && test -n "${TK_BIN_DIR}"], [ AS_IF([test "${TEA_WINDOWINGSYSTEM}" = x11], [ AC_CACHE_CHECK([for 64-bit X11], tcl_cv_lib_x11_64, [ for v in CFLAGS CPPFLAGS LDFLAGS; do eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc / /g" -e "s/-arch i386 / /g"`"' done CPPFLAGS="$CPPFLAGS -I/usr/X11R6/include" LDFLAGS="$LDFLAGS -L/usr/X11R6/lib -lX11" AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], [[XrmInitialize();]])], [tcl_cv_lib_x11_64=yes],[tcl_cv_lib_x11_64=no]) for v in CFLAGS CPPFLAGS LDFLAGS; do eval $v'="$hold_'$v'"' done]) ]) AS_IF([test "${TEA_WINDOWINGSYSTEM}" = aqua], [ AC_CACHE_CHECK([for 64-bit Tk], tcl_cv_lib_tk_64, [ for v in CFLAGS CPPFLAGS LDFLAGS; do eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc / /g" -e "s/-arch i386 / /g"`"' done CPPFLAGS="$CPPFLAGS -DUSE_TCL_STUBS=1 -DUSE_TK_STUBS=1 ${TCL_INCLUDES} ${TK_INCLUDES}" LDFLAGS="$LDFLAGS ${TCL_STUB_LIB_SPEC} ${TK_STUB_LIB_SPEC}" AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], [[Tk_InitStubs(NULL, "", 0);]])], [tcl_cv_lib_tk_64=yes],[tcl_cv_lib_tk_64=no]) for v in CFLAGS CPPFLAGS LDFLAGS; do eval $v'="$hold_'$v'"' done]) ]) # remove 64-bit arch flags from CFLAGS et al. if configuration # does not support 64-bit. AS_IF([test "$tcl_cv_lib_tk_64" = no -o "$tcl_cv_lib_x11_64" = no], [ AC_MSG_NOTICE([Removing 64-bit architectures from compiler & linker flags]) for v in CFLAGS CPPFLAGS LDFLAGS; do eval $v'="`echo "$'$v' "|sed -e "s/-arch ppc64 / /g" -e "s/-arch x86_64 / /g"`"' done]) ]) ;; OS/390-*) CFLAGS_OPTIMIZE="" # Optimizer is buggy AC_DEFINE(_OE_SOCKETS, 1, # needed in sys/socket.h [Should OS/390 do the right thing with sockets?]) ;; OSF1-V*) # Digital OSF/1 SHLIB_CFLAGS="" AS_IF([test "$SHARED_BUILD" = 1], [ SHLIB_LD='ld -shared -expect_unresolved "*"' ], [ SHLIB_LD='ld -non_shared -expect_unresolved "*"' ]) SHLIB_SUFFIX=".so" AS_IF([test $doRpath = yes], [ CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}']) AS_IF([test "$GCC" = yes], [CFLAGS="$CFLAGS -mieee"], [ CFLAGS="$CFLAGS -DHAVE_TZSET -std1 -ieee"]) # see pthread_intro(3) for pthread support on osf1, k.furukawa CFLAGS="$CFLAGS -DHAVE_PTHREAD_ATTR_SETSTACKSIZE" CFLAGS="$CFLAGS -DTCL_THREAD_STACK_MIN=PTHREAD_STACK_MIN*64" LIBS=`echo $LIBS | sed s/-lpthreads//` AS_IF([test "$GCC" = yes], [ LIBS="$LIBS -lpthread -lmach -lexc" ], [ CFLAGS="$CFLAGS -pthread" LDFLAGS="$LDFLAGS -pthread" ]) ;; QNX-6*) # QNX RTP # This may work for all QNX, but it was only reported for v6. SHLIB_CFLAGS="-fPIC" SHLIB_LD="ld -Bshareable -x" SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; SCO_SV-3.2*) AS_IF([test "$GCC" = yes], [ SHLIB_CFLAGS="-fPIC -melf" LDFLAGS="$LDFLAGS -melf -Wl,-Bexport" ], [ SHLIB_CFLAGS="-Kpic -belf" LDFLAGS="$LDFLAGS -belf -Wl,-Bexport" ]) SHLIB_LD="ld -G" SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; SunOS-5.[[0-6]]) # Careful to not let 5.10+ fall into this case # Note: If _REENTRANT isn't defined, then Solaris # won't define thread-safe library routines. AC_DEFINE(_REENTRANT, 1, [Do we want the reentrant OS API?]) AC_DEFINE(_POSIX_PTHREAD_SEMANTICS, 1, [Do we really want to follow the standard? Yes we do!]) SHLIB_CFLAGS="-KPIC" SHLIB_SUFFIX=".so" AS_IF([test "$GCC" = yes], [ SHLIB_LD='${CC} -shared' CC_SEARCH_FLAGS='"-Wl,-R,${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} ], [ SHLIB_LD="/usr/ccs/bin/ld -G -z text" CC_SEARCH_FLAGS='-R "${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} ]) ;; SunOS-5*) # Note: If _REENTRANT isn't defined, then Solaris # won't define thread-safe library routines. AC_DEFINE(_REENTRANT, 1, [Do we want the reentrant OS API?]) AC_DEFINE(_POSIX_PTHREAD_SEMANTICS, 1, [Do we really want to follow the standard? Yes we do!]) SHLIB_CFLAGS="-KPIC" # Check to enable 64-bit flags for compiler/linker AS_IF([test "$do64bit" = yes], [ arch=`isainfo` AS_IF([test "$arch" = "sparcv9 sparc"], [ AS_IF([test "$GCC" = yes], [ AS_IF([test "`${CC} -dumpversion | awk -F. '{print [$]1}'`" -lt 3], [ AC_MSG_WARN([64bit mode not supported with GCC < 3.2 on $system]) ], [ do64bit_ok=yes CFLAGS="$CFLAGS -m64 -mcpu=v9" LDFLAGS="$LDFLAGS -m64 -mcpu=v9" SHLIB_CFLAGS="-fPIC" ]) ], [ do64bit_ok=yes AS_IF([test "$do64bitVIS" = yes], [ CFLAGS="$CFLAGS -xarch=v9a" LDFLAGS_ARCH="-xarch=v9a" ], [ CFLAGS="$CFLAGS -xarch=v9" LDFLAGS_ARCH="-xarch=v9" ]) # Solaris 64 uses this as well #LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH_64" ]) ], [AS_IF([test "$arch" = "amd64 i386"], [ AS_IF([test "$GCC" = yes], [ case $system in SunOS-5.1[[1-9]]*|SunOS-5.[[2-9]][[0-9]]*) do64bit_ok=yes CFLAGS="$CFLAGS -m64" LDFLAGS="$LDFLAGS -m64";; *) AC_MSG_WARN([64bit mode not supported with GCC on $system]);; esac ], [ do64bit_ok=yes case $system in SunOS-5.1[[1-9]]*|SunOS-5.[[2-9]][[0-9]]*) CFLAGS="$CFLAGS -m64" LDFLAGS="$LDFLAGS -m64";; *) CFLAGS="$CFLAGS -xarch=amd64" LDFLAGS="$LDFLAGS -xarch=amd64";; esac ]) ], [AC_MSG_WARN([64bit mode not supported for $arch])])]) ]) SHLIB_SUFFIX=".so" AS_IF([test "$GCC" = yes], [ SHLIB_LD='${CC} -shared' CC_SEARCH_FLAGS='"-Wl,-R,${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} AS_IF([test "$do64bit_ok" = yes], [ AS_IF([test "$arch" = "sparcv9 sparc"], [ # We need to specify -static-libgcc or we need to # add the path to the sparv9 libgcc. # JH: static-libgcc is necessary for core Tcl, but may # not be necessary for extensions. SHLIB_LD="$SHLIB_LD -m64 -mcpu=v9 -static-libgcc" # for finding sparcv9 libgcc, get the regular libgcc # path, remove so name and append 'sparcv9' #v9gcclibdir="`gcc -print-file-name=libgcc_s.so` | ..." #CC_SEARCH_FLAGS="${CC_SEARCH_FLAGS},-R,$v9gcclibdir" ], [AS_IF([test "$arch" = "amd64 i386"], [ # JH: static-libgcc is necessary for core Tcl, but may # not be necessary for extensions. SHLIB_LD="$SHLIB_LD -m64 -static-libgcc" ])]) ]) ], [ case $system in SunOS-5.[[1-9]][[0-9]]*) # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS SHLIB_LD='${CC} -G -z text ${LDFLAGS_DEFAULT}';; *) SHLIB_LD='/usr/ccs/bin/ld -G -z text';; esac CC_SEARCH_FLAGS='"-Wl,-R,${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS='-R "${LIB_RUNTIME_DIR}"' ]) ;; UNIX_SV* | UnixWare-5*) SHLIB_CFLAGS="-KPIC" SHLIB_LD='${CC} -G' SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" # Some UNIX_SV* systems (unixware 1.1.2 for example) have linkers # that don't grok the -Bexport option. Test that it does. AC_CACHE_CHECK([for ld accepts -Bexport flag], tcl_cv_ld_Bexport, [ hold_ldflags=$LDFLAGS LDFLAGS="$LDFLAGS -Wl,-Bexport" AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[int i;]])], [tcl_cv_ld_Bexport=yes],[tcl_cv_ld_Bexport=no]) LDFLAGS=$hold_ldflags]) AS_IF([test $tcl_cv_ld_Bexport = yes], [ LDFLAGS="$LDFLAGS -Wl,-Bexport" ]) CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; esac AS_IF([test "$do64bit" = yes -a "$do64bit_ok" = no], [ AC_MSG_WARN([64bit support being disabled -- don't know magic for this platform]) ]) dnl # Add any CPPFLAGS set in the environment to our CFLAGS, but delay doing so dnl # until the end of configure, as configure's compile and link tests use dnl # both CPPFLAGS and CFLAGS (unlike our compile and link) but configure's dnl # preprocessing tests use only CPPFLAGS. AC_CONFIG_COMMANDS_PRE([CFLAGS="${CFLAGS} ${CPPFLAGS}"; CPPFLAGS=""]) # Add in the arch flags late to ensure it wasn't removed. # Not necessary in TEA, but this is aligned with core LDFLAGS="$LDFLAGS $LDFLAGS_ARCH" # If we're running gcc, then change the C flags for compiling shared # libraries to the right flags for gcc, instead of those for the # standard manufacturer compiler. AS_IF([test "$GCC" = yes], [ case $system in AIX-*) ;; BSD/OS*) ;; CYGWIN_*|MINGW32_*|MINGW64_*|MSYS_*) ;; IRIX*) ;; NetBSD-*|DragonFly-*|FreeBSD-*|OpenBSD-*) ;; Darwin-*) ;; SCO_SV-3.2*) ;; windows) ;; *) SHLIB_CFLAGS="-fPIC" ;; esac]) AS_IF([test "$tcl_cv_cc_visibility_hidden" != yes], [ AC_DEFINE(MODULE_SCOPE, [extern], [No Compiler support for module scope symbols]) ]) AS_IF([test "$SHARED_LIB_SUFFIX" = ""], [ # TEA specific: use PACKAGE_VERSION instead of VERSION SHARED_LIB_SUFFIX='${PACKAGE_VERSION}${SHLIB_SUFFIX}']) AS_IF([test "$UNSHARED_LIB_SUFFIX" = ""], [ # TEA specific: use PACKAGE_VERSION instead of VERSION UNSHARED_LIB_SUFFIX='${PACKAGE_VERSION}.a']) if test "${GCC}" = "yes" -a ${SHLIB_SUFFIX} = ".dll"; then AC_CACHE_CHECK(for SEH support in compiler, tcl_cv_seh, AC_RUN_IFELSE([AC_LANG_SOURCE([[ #define WIN32_LEAN_AND_MEAN #include #undef WIN32_LEAN_AND_MEAN int main(int argc, char** argv) { int a, b = 0; __try { a = 666 / b; } __except (EXCEPTION_EXECUTE_HANDLER) { return 0; } return 1; } ]])], [tcl_cv_seh=yes], [tcl_cv_seh=no], [tcl_cv_seh=no]) ) if test "$tcl_cv_seh" = "no" ; then AC_DEFINE(HAVE_NO_SEH, 1, [Defined when mingw does not support SEH]) fi # # Check to see if the excpt.h include file provided contains the # definition for EXCEPTION_DISPOSITION; if not, which is the case # with Cygwin's version as of 2002-04-10, define it to be int, # sufficient for getting the current code to work. # AC_CACHE_CHECK(for EXCEPTION_DISPOSITION support in include files, tcl_cv_eh_disposition, AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ # define WIN32_LEAN_AND_MEAN # include # undef WIN32_LEAN_AND_MEAN ]], [[ EXCEPTION_DISPOSITION x; ]])], [tcl_cv_eh_disposition=yes], [tcl_cv_eh_disposition=no]) ) if test "$tcl_cv_eh_disposition" = "no" ; then AC_DEFINE(EXCEPTION_DISPOSITION, int, [Defined when cygwin/mingw does not support EXCEPTION DISPOSITION]) fi # Check to see if winnt.h defines CHAR, SHORT, and LONG # even if VOID has already been #defined. The win32api # used by mingw and cygwin is known to do this. AC_CACHE_CHECK(for winnt.h that ignores VOID define, tcl_cv_winnt_ignore_void, AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #define VOID void #define WIN32_LEAN_AND_MEAN #include #undef WIN32_LEAN_AND_MEAN ]], [[ CHAR c; SHORT s; LONG l; ]])], [tcl_cv_winnt_ignore_void=yes], [tcl_cv_winnt_ignore_void=no]) ) if test "$tcl_cv_winnt_ignore_void" = "yes" ; then AC_DEFINE(HAVE_WINNT_IGNORE_VOID, 1, [Defined when cygwin/mingw ignores VOID define in winnt.h]) fi fi # See if the compiler supports casting to a union type. # This is used to stop gcc from printing a compiler # warning when initializing a union member. AC_CACHE_CHECK(for cast to union support, tcl_cv_cast_to_union, AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[ union foo { int i; double d; }; union foo f = (union foo) (int) 0; ]])], [tcl_cv_cast_to_union=yes], [tcl_cv_cast_to_union=no]) ) if test "$tcl_cv_cast_to_union" = "yes"; then AC_DEFINE(HAVE_CAST_TO_UNION, 1, [Defined when compiler supports casting to union type.]) fi AC_CHECK_HEADER(stdbool.h, [AC_DEFINE(HAVE_STDBOOL_H, 1, [Do we have ?])],) AC_SUBST(CFLAGS_DEBUG) AC_SUBST(CFLAGS_OPTIMIZE) AC_SUBST(CFLAGS_WARNING) AC_SUBST(LDFLAGS_DEBUG) AC_SUBST(LDFLAGS_OPTIMIZE) AC_SUBST(STLIB_LD) AC_SUBST(SHLIB_LD) AC_SUBST(SHLIB_LD_LIBS) AC_SUBST(SHLIB_CFLAGS) AC_SUBST(LD_LIBRARY_PATH_VAR) # These must be called after we do the basic CFLAGS checks and # verify any possible 64-bit or similar switches are necessary TEA_TCL_EARLY_FLAGS TEA_TCL_64BIT_FLAGS ]) #-------------------------------------------------------------------- # TEA_SERIAL_PORT # # Determine which interface to use to talk to the serial port. # Note that #include lines must begin in leftmost column for # some compilers to recognize them as preprocessor directives, # and some build environments have stdin not pointing at a # pseudo-terminal (usually /dev/null instead.) # # Arguments: # none # # Results: # # Defines only one of the following vars: # HAVE_SYS_MODEM_H # USE_TERMIOS # USE_TERMIO # USE_SGTTY #-------------------------------------------------------------------- AC_DEFUN([TEA_SERIAL_PORT], [ AC_CHECK_HEADERS(sys/modem.h) AC_CACHE_CHECK([termios vs. termio vs. sgtty], tcl_cv_api_serial, [ AC_RUN_IFELSE([AC_LANG_SOURCE([[ #include int main() { struct termios t; if (tcgetattr(0, &t) == 0) { cfsetospeed(&t, 0); t.c_cflag |= PARENB | PARODD | CSIZE | CSTOPB; return 0; } return 1; }]])],[tcl_cv_api_serial=termios],[tcl_cv_api_serial=no],[tcl_cv_api_serial=no]) if test $tcl_cv_api_serial = no ; then AC_RUN_IFELSE([AC_LANG_SOURCE([[ #include int main() { struct termio t; if (ioctl(0, TCGETA, &t) == 0) { t.c_cflag |= CBAUD | PARENB | PARODD | CSIZE | CSTOPB; return 0; } return 1; }]])],[tcl_cv_api_serial=termio],[tcl_cv_api_serial=no],[tcl_cv_api_serial=no]) fi if test $tcl_cv_api_serial = no ; then AC_RUN_IFELSE([AC_LANG_SOURCE([[ #include int main() { struct sgttyb t; if (ioctl(0, TIOCGETP, &t) == 0) { t.sg_ospeed = 0; t.sg_flags |= ODDP | EVENP | RAW; return 0; } return 1; }]])],[tcl_cv_api_serial=sgtty],[tcl_cv_api_serial=no],[tcl_cv_api_serial=no]) fi if test $tcl_cv_api_serial = no ; then AC_RUN_IFELSE([AC_LANG_SOURCE([[ #include #include int main() { struct termios t; if (tcgetattr(0, &t) == 0 || errno == ENOTTY || errno == ENXIO || errno == EINVAL) { cfsetospeed(&t, 0); t.c_cflag |= PARENB | PARODD | CSIZE | CSTOPB; return 0; } return 1; }]])],[tcl_cv_api_serial=termios],[tcl_cv_api_serial=no],[tcl_cv_api_serial=no]) fi if test $tcl_cv_api_serial = no; then AC_RUN_IFELSE([AC_LANG_SOURCE([[ #include #include int main() { struct termio t; if (ioctl(0, TCGETA, &t) == 0 || errno == ENOTTY || errno == ENXIO || errno == EINVAL) { t.c_cflag |= CBAUD | PARENB | PARODD | CSIZE | CSTOPB; return 0; } return 1; }]])],[tcl_cv_api_serial=termio],[tcl_cv_api_serial=no],[tcl_cv_api_serial=no]) fi if test $tcl_cv_api_serial = no; then AC_RUN_IFELSE([AC_LANG_SOURCE([[ #include #include int main() { struct sgttyb t; if (ioctl(0, TIOCGETP, &t) == 0 || errno == ENOTTY || errno == ENXIO || errno == EINVAL) { t.sg_ospeed = 0; t.sg_flags |= ODDP | EVENP | RAW; return 0; } return 1; }]])],[tcl_cv_api_serial=sgtty],[tcl_cv_api_serial=none],[tcl_cv_api_serial=none]) fi]) case $tcl_cv_api_serial in termios) AC_DEFINE(USE_TERMIOS, 1, [Use the termios API for serial lines]);; termio) AC_DEFINE(USE_TERMIO, 1, [Use the termio API for serial lines]);; sgtty) AC_DEFINE(USE_SGTTY, 1, [Use the sgtty API for serial lines]);; esac ]) #-------------------------------------------------------------------- # TEA_PATH_X # # Locate the X11 header files and the X11 library archive. Try # the ac_path_x macro first, but if it doesn't find the X stuff # (e.g. because there's no xmkmf program) then check through # a list of possible directories. Under some conditions the # autoconf macro will return an include directory that contains # no include files, so double-check its result just to be safe. # # This should be called after TEA_CONFIG_CFLAGS as setting the # LIBS line can confuse some configure macro magic. # # Arguments: # none # # Results: # # Sets the following vars: # XINCLUDES # XLIBSW # PKG_LIBS (appends to) #-------------------------------------------------------------------- AC_DEFUN([TEA_PATH_X], [ if test "${TEA_WINDOWINGSYSTEM}" = "x11" ; then TEA_PATH_UNIX_X fi ]) AC_DEFUN([TEA_PATH_UNIX_X], [ AC_PATH_X not_really_there="" if test "$no_x" = ""; then if test "$x_includes" = ""; then AC_PREPROC_IFELSE([AC_LANG_SOURCE([[#include ]])],[],[not_really_there="yes"]) else if test ! -r $x_includes/X11/Xlib.h; then not_really_there="yes" fi fi fi if test "$no_x" = "yes" -o "$not_really_there" = "yes"; then AC_MSG_CHECKING([for X11 header files]) found_xincludes="no" AC_PREPROC_IFELSE([AC_LANG_SOURCE([[#include ]])],[found_xincludes="yes"],[found_xincludes="no"]) if test "$found_xincludes" = "no"; then dirs="/usr/unsupported/include /usr/local/include /usr/X386/include /usr/X11R6/include /usr/X11R5/include /usr/include/X11R5 /usr/include/X11R4 /usr/openwin/include /usr/X11/include /usr/sww/include" for i in $dirs ; do if test -r $i/X11/Xlib.h; then AC_MSG_RESULT([$i]) XINCLUDES=" -I$i" found_xincludes="yes" break fi done fi else if test "$x_includes" != ""; then XINCLUDES="-I$x_includes" found_xincludes="yes" fi fi if test "$found_xincludes" = "no"; then AC_MSG_RESULT([couldn't find any!]) fi if test "$no_x" = yes; then AC_MSG_CHECKING([for X11 libraries]) XLIBSW=nope dirs="/usr/unsupported/lib /usr/local/lib /usr/X386/lib /usr/X11R6/lib /usr/X11R5/lib /usr/lib/X11R5 /usr/lib/X11R4 /usr/openwin/lib /usr/X11/lib /usr/sww/X11/lib" for i in $dirs ; do if test -r $i/libX11.a -o -r $i/libX11.so -o -r $i/libX11.sl -o -r $i/libX11.dylib; then AC_MSG_RESULT([$i]) XLIBSW="-L$i -lX11" x_libraries="$i" break fi done else if test "$x_libraries" = ""; then XLIBSW=-lX11 else XLIBSW="-L$x_libraries -lX11" fi fi if test "$XLIBSW" = nope ; then AC_CHECK_LIB(Xwindow, XCreateWindow, XLIBSW=-lXwindow) fi if test "$XLIBSW" = nope ; then AC_MSG_RESULT([could not find any! Using -lX11.]) XLIBSW=-lX11 fi # TEA specific: if test x"${XLIBSW}" != x ; then PKG_LIBS="${PKG_LIBS} ${XLIBSW}" fi ]) #-------------------------------------------------------------------- # TEA_BLOCKING_STYLE # # The statements below check for systems where POSIX-style # non-blocking I/O (O_NONBLOCK) doesn't work or is unimplemented. # On these systems (mostly older ones), use the old BSD-style # FIONBIO approach instead. # # Arguments: # none # # Results: # # Defines some of the following vars: # HAVE_SYS_IOCTL_H # HAVE_SYS_FILIO_H # USE_FIONBIO # O_NONBLOCK #-------------------------------------------------------------------- AC_DEFUN([TEA_BLOCKING_STYLE], [ AC_CHECK_HEADERS(sys/ioctl.h) AC_CHECK_HEADERS(sys/filio.h) TEA_CONFIG_SYSTEM AC_MSG_CHECKING([FIONBIO vs. O_NONBLOCK for nonblocking I/O]) case $system in OSF*) AC_DEFINE(USE_FIONBIO, 1, [Should we use FIONBIO?]) AC_MSG_RESULT([FIONBIO]) ;; *) AC_MSG_RESULT([O_NONBLOCK]) ;; esac ]) #-------------------------------------------------------------------- # TEA_TIME_HANDLER # # Checks how the system deals with time.h, what time structures # are used on the system, and what fields the structures have. # # Arguments: # none # # Results: # # Defines some of the following vars: # USE_DELTA_FOR_TZ # HAVE_TM_GMTOFF # HAVE_TM_TZADJ # HAVE_TIMEZONE_VAR # #-------------------------------------------------------------------- AC_DEFUN([TEA_TIME_HANDLER], [ AC_CHECK_HEADERS(sys/time.h) AC_HEADER_TIME AC_STRUCT_TIMEZONE AC_CHECK_FUNCS(gmtime_r localtime_r mktime) AC_CACHE_CHECK([tm_tzadj in struct tm], tcl_cv_member_tm_tzadj, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[struct tm tm; (void)tm.tm_tzadj;]])], [tcl_cv_member_tm_tzadj=yes], [tcl_cv_member_tm_tzadj=no])]) if test $tcl_cv_member_tm_tzadj = yes ; then AC_DEFINE(HAVE_TM_TZADJ, 1, [Should we use the tm_tzadj field of struct tm?]) fi AC_CACHE_CHECK([tm_gmtoff in struct tm], tcl_cv_member_tm_gmtoff, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[struct tm tm; (void)tm.tm_gmtoff;]])], [tcl_cv_member_tm_gmtoff=yes], [tcl_cv_member_tm_gmtoff=no])]) if test $tcl_cv_member_tm_gmtoff = yes ; then AC_DEFINE(HAVE_TM_GMTOFF, 1, [Should we use the tm_gmtoff field of struct tm?]) fi # # Its important to include time.h in this check, as some systems # (like convex) have timezone functions, etc. # AC_CACHE_CHECK([long timezone variable], tcl_cv_timezone_long, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include #include ]], [[extern long timezone; timezone += 1; exit (0);]])], [tcl_cv_timezone_long=yes], [tcl_cv_timezone_long=no])]) if test $tcl_cv_timezone_long = yes ; then AC_DEFINE(HAVE_TIMEZONE_VAR, 1, [Should we use the global timezone variable?]) else # # On some systems (eg IRIX 6.2), timezone is a time_t and not a long. # AC_CACHE_CHECK([time_t timezone variable], tcl_cv_timezone_time, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include #include ]], [[extern time_t timezone; timezone += 1; exit (0);]])], [tcl_cv_timezone_time=yes], [tcl_cv_timezone_time=no])]) if test $tcl_cv_timezone_time = yes ; then AC_DEFINE(HAVE_TIMEZONE_VAR, 1, [Should we use the global timezone variable?]) fi fi ]) #-------------------------------------------------------------------- # TEA_BUGGY_STRTOD # # Under Solaris 2.4, strtod returns the wrong value for the # terminating character under some conditions. Check for this # and if the problem exists use a substitute procedure # "fixstrtod" (provided by Tcl) that corrects the error. # Also, on Compaq's Tru64 Unix 5.0, # strtod(" ") returns 0.0 instead of a failure to convert. # # Arguments: # none # # Results: # # Might defines some of the following vars: # strtod (=fixstrtod) #-------------------------------------------------------------------- AC_DEFUN([TEA_BUGGY_STRTOD], [ AC_CHECK_FUNC(strtod, tcl_strtod=1, tcl_strtod=0) if test "$tcl_strtod" = 1; then AC_CACHE_CHECK([for Solaris2.4/Tru64 strtod bugs], tcl_cv_strtod_buggy,[ AC_RUN_IFELSE([AC_LANG_SOURCE([[ #include extern double strtod(); int main() { char *infString="Inf", *nanString="NaN", *spaceString=" "; char *term; double value; value = strtod(infString, &term); if ((term != infString) && (term[-1] == 0)) { exit(1); } value = strtod(nanString, &term); if ((term != nanString) && (term[-1] == 0)) { exit(1); } value = strtod(spaceString, &term); if (term == (spaceString+1)) { exit(1); } exit(0); }]])], [tcl_cv_strtod_buggy=ok], [tcl_cv_strtod_buggy=buggy], [tcl_cv_strtod_buggy=buggy])]) if test "$tcl_cv_strtod_buggy" = buggy; then AC_LIBOBJ([fixstrtod]) USE_COMPAT=1 AC_DEFINE(strtod, fixstrtod, [Do we want to use the strtod() in compat?]) fi fi ]) #-------------------------------------------------------------------- # TEA_TCL_LINK_LIBS # # Search for the libraries needed to link the Tcl shell. # Things like the math library (-lm), socket stuff (-lsocket vs. # -lnsl), zlib (-lz) and libtommath (-ltommath) are dealt with here. # # Arguments: # None. # # Results: # # Might append to the following vars: # LIBS # MATH_LIBS # # Might define the following vars: # HAVE_NET_ERRNO_H # #-------------------------------------------------------------------- AC_DEFUN([TEA_TCL_LINK_LIBS], [ #-------------------------------------------------------------------- # On a few very rare systems, all of the libm.a stuff is # already in libc.a. Set compiler flags accordingly. #-------------------------------------------------------------------- AC_CHECK_FUNC(sin, MATH_LIBS="", MATH_LIBS="-lm") #-------------------------------------------------------------------- # Interactive UNIX requires -linet instead of -lsocket, plus it # needs net/errno.h to define the socket-related error codes. #-------------------------------------------------------------------- AC_CHECK_LIB(inet, main, [LIBS="$LIBS -linet"]) AC_CHECK_HEADER(net/errno.h, [ AC_DEFINE(HAVE_NET_ERRNO_H, 1, [Do we have ?])]) #-------------------------------------------------------------------- # Check for the existence of the -lsocket and -lnsl libraries. # The order here is important, so that they end up in the right # order in the command line generated by make. Here are some # special considerations: # 1. Use "connect" and "accept" to check for -lsocket, and # "gethostbyname" to check for -lnsl. # 2. Use each function name only once: can't redo a check because # autoconf caches the results of the last check and won't redo it. # 3. Use -lnsl and -lsocket only if they supply procedures that # aren't already present in the normal libraries. This is because # IRIX 5.2 has libraries, but they aren't needed and they're # bogus: they goof up name resolution if used. # 4. On some SVR4 systems, can't use -lsocket without -lnsl too. # To get around this problem, check for both libraries together # if -lsocket doesn't work by itself. #-------------------------------------------------------------------- tcl_checkBoth=0 AC_CHECK_FUNC(connect, tcl_checkSocket=0, tcl_checkSocket=1) if test "$tcl_checkSocket" = 1; then AC_CHECK_FUNC(setsockopt, , [AC_CHECK_LIB(socket, setsockopt, LIBS="$LIBS -lsocket", tcl_checkBoth=1)]) fi if test "$tcl_checkBoth" = 1; then tk_oldLibs=$LIBS LIBS="$LIBS -lsocket -lnsl" AC_CHECK_FUNC(accept, tcl_checkNsl=0, [LIBS=$tk_oldLibs]) fi AC_CHECK_FUNC(gethostbyname, , [AC_CHECK_LIB(nsl, gethostbyname, [LIBS="$LIBS -lnsl"])]) AC_CHECK_FUNC(mp_log_u32, , [AC_CHECK_LIB(tommath, mp_log_u32, [LIBS="$LIBS -ltommath"])]) AC_CHECK_FUNC(deflateSetHeader, , [AC_CHECK_LIB(z, deflateSetHeader, [LIBS="$LIBS -lz"])]) ]) #-------------------------------------------------------------------- # TEA_TCL_EARLY_FLAGS # # Check for what flags are needed to be passed so the correct OS # features are available. # # Arguments: # None # # Results: # # Might define the following vars: # _ISOC99_SOURCE # _FILE_OFFSET_BITS # #-------------------------------------------------------------------- AC_DEFUN([TEA_TCL_EARLY_FLAG],[ AC_CACHE_VAL([tcl_cv_flag_]translit($1,[A-Z],[a-z]), AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[$2]], [[$3]])], [tcl_cv_flag_]translit($1,[A-Z],[a-z])=no,[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[[#define ]$1[ ]m4_default([$4],[1])[ ]$2]], [[$3]])], [tcl_cv_flag_]translit($1,[A-Z],[a-z])=yes, [tcl_cv_flag_]translit($1,[A-Z],[a-z])=no)])) if test ["x${tcl_cv_flag_]translit($1,[A-Z],[a-z])[}" = "xyes"] ; then AC_DEFINE($1, m4_default([$4],[1]), [Add the ]$1[ flag when building]) tcl_flags="$tcl_flags $1" fi ]) AC_DEFUN([TEA_TCL_EARLY_FLAGS],[ AC_MSG_CHECKING([for required early compiler flags]) tcl_flags="" TEA_TCL_EARLY_FLAG(_ISOC99_SOURCE,[#include ], [char *p = (char *)strtoll; char *q = (char *)strtoull;]) if test "${TCL_MAJOR_VERSION}" -ne 8 ; then TEA_TCL_EARLY_FLAG(_FILE_OFFSET_BITS,[#include ], [switch (0) { case 0: case (sizeof(off_t)==sizeof(long long)): ; }],64) fi if test "x${tcl_flags}" = "x" ; then AC_MSG_RESULT([none]) else AC_MSG_RESULT([${tcl_flags}]) fi ]) #-------------------------------------------------------------------- # TEA_TCL_64BIT_FLAGS # # Check for what is defined in the way of 64-bit features. # # Arguments: # None # # Results: # # Might define the following vars: # TCL_WIDE_INT_IS_LONG # TCL_WIDE_INT_TYPE # HAVE_STRUCT_DIRENT64, HAVE_DIR64 # HAVE_STRUCT_STAT64 # HAVE_TYPE_OFF64_T # _TIME_BITS # #-------------------------------------------------------------------- AC_DEFUN([TEA_TCL_64BIT_FLAGS], [ AC_MSG_CHECKING([for 64-bit integer type]) AC_CACHE_VAL(tcl_cv_type_64bit,[ tcl_cv_type_64bit=none # See if the compiler knows natively about __int64 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[__int64 value = (__int64) 0;]])], [tcl_type_64bit=__int64],[tcl_type_64bit="long long"]) # See if we could use long anyway Note that we substitute in the # type that is our current guess for a 64-bit type inside this check # program, so it should be modified only carefully... AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[switch (0) { case 1: case (sizeof(${tcl_type_64bit})==sizeof(long)): ; }]])],[tcl_cv_type_64bit=${tcl_type_64bit}],[])]) if test "${tcl_cv_type_64bit}" = none ; then AC_DEFINE(TCL_WIDE_INT_IS_LONG, 1, [Do 'long' and 'long long' have the same size (64-bit)?]) AC_MSG_RESULT([yes]) elif test "${tcl_cv_type_64bit}" = "__int64" \ -a "${TEA_PLATFORM}" = "windows" ; then # TEA specific: We actually want to use the default tcl.h checks in # this case to handle both TCL_WIDE_INT_TYPE and TCL_LL_MODIFIER* AC_MSG_RESULT([using Tcl header defaults]) else AC_DEFINE_UNQUOTED(TCL_WIDE_INT_TYPE,${tcl_cv_type_64bit}, [What type should be used to define wide integers?]) AC_MSG_RESULT([${tcl_cv_type_64bit}]) # Now check for auxiliary declarations if test "${TCL_MAJOR_VERSION}" -ne 8 ; then AC_CACHE_CHECK([for 64-bit time_t], tcl_cv_time_t_64,[ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[switch (0) {case 0: case (sizeof(time_t)==sizeof(long long)): ;}]])], [tcl_cv_time_t_64=yes],[tcl_cv_time_t_64=no])]) if test "x${tcl_cv_time_t_64}" = "xno" ; then # Note that _TIME_BITS=64 requires _FILE_OFFSET_BITS=64 # which SC_TCL_EARLY_FLAGS has defined if necessary. AC_CACHE_CHECK([if _TIME_BITS=64 enables 64-bit time_t], tcl_cv__time_bits,[ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#define _TIME_BITS 64 #include ]], [[switch (0) {case 0: case (sizeof(time_t)==sizeof(long long)): ;}]])], [tcl_cv__time_bits=yes],[tcl_cv__time_bits=no])]) if test "x${tcl_cv__time_bits}" = "xyes" ; then AC_DEFINE(_TIME_BITS, 64, [_TIME_BITS=64 enables 64-bit time_t.]) fi fi fi AC_CACHE_CHECK([for struct dirent64], tcl_cv_struct_dirent64,[ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include #include ]], [[struct dirent64 p;]])], [tcl_cv_struct_dirent64=yes],[tcl_cv_struct_dirent64=no])]) if test "x${tcl_cv_struct_dirent64}" = "xyes" ; then AC_DEFINE(HAVE_STRUCT_DIRENT64, 1, [Is 'struct dirent64' in ?]) fi AC_CACHE_CHECK([for DIR64], tcl_cv_DIR64,[ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include #include ]], [[struct dirent64 *p; DIR64 d = opendir64("."); p = readdir64(d); rewinddir64(d); closedir64(d);]])], [tcl_cv_DIR64=yes], [tcl_cv_DIR64=no])]) if test "x${tcl_cv_DIR64}" = "xyes" ; then AC_DEFINE(HAVE_DIR64, 1, [Is 'DIR64' in ?]) fi AC_CACHE_CHECK([for struct stat64], tcl_cv_struct_stat64,[ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[struct stat64 p; ]])], [tcl_cv_struct_stat64=yes], [tcl_cv_struct_stat64=no])]) if test "x${tcl_cv_struct_stat64}" = "xyes" ; then AC_DEFINE(HAVE_STRUCT_STAT64, 1, [Is 'struct stat64' in ?]) fi AC_CHECK_FUNCS(open64 lseek64) AC_MSG_CHECKING([for off64_t]) AC_CACHE_VAL(tcl_cv_type_off64_t,[ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[off64_t offset; ]])], [tcl_cv_type_off64_t=yes], [tcl_cv_type_off64_t=no])]) dnl Define HAVE_TYPE_OFF64_T only when the off64_t type and the dnl functions lseek64 and open64 are defined. if test "x${tcl_cv_type_off64_t}" = "xyes" && \ test "x${ac_cv_func_lseek64}" = "xyes" && \ test "x${ac_cv_func_open64}" = "xyes" ; then AC_DEFINE(HAVE_TYPE_OFF64_T, 1, [Is off64_t in ?]) AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi fi ]) ## ## Here ends the standard Tcl configuration bits and starts the ## TEA specific functions ## #------------------------------------------------------------------------ # TEA_INIT -- # # Init various Tcl Extension Architecture (TEA) variables. # This should be the first called TEA_* macro. # # Arguments: # none # # Results: # # Defines and substs the following vars: # CYGPATH # EXEEXT # Defines only: # TEA_VERSION # TEA_INITED # TEA_PLATFORM (windows or unix) # # "cygpath" is used on windows to generate native path names for include # files. These variables should only be used with the compiler and linker # since they generate native path names. # # EXEEXT # Select the executable extension based on the host type. This # is a lightweight replacement for AC_EXEEXT that doesn't require # a compiler. #------------------------------------------------------------------------ AC_DEFUN([TEA_INIT], [ TEA_VERSION="3.13" AC_MSG_CHECKING([TEA configuration]) if test x"${PACKAGE_NAME}" = x ; then AC_MSG_ERROR([ The PACKAGE_NAME variable must be defined by your TEA configure.ac]) fi AC_MSG_RESULT([ok (TEA ${TEA_VERSION})]) # If the user did not set CFLAGS, set it now to keep macros # like AC_PROG_CC and AC_TRY_COMPILE from adding "-g -O2". if test "${CFLAGS+set}" != "set" ; then CFLAGS="" fi case "`uname -s`" in *win32*|*WIN32*|*MINGW32_*|*MINGW64_*|*MSYS_*) AC_CHECK_PROG(CYGPATH, cygpath, cygpath -m, echo) EXEEXT=".exe" TEA_PLATFORM="windows" ;; *CYGWIN_*) EXEEXT=".exe" # CYGPATH and TEA_PLATFORM are determined later in LOAD_TCLCONFIG ;; *) CYGPATH=echo # Maybe we are cross-compiling.... case ${host_alias} in *mingw32*) EXEEXT=".exe" TEA_PLATFORM="windows" ;; *) EXEEXT="" TEA_PLATFORM="unix" ;; esac ;; esac # Check if exec_prefix is set. If not use fall back to prefix. # Note when adjusted, so that TEA_PREFIX can correct for this. # This is needed for recursive configures, since autoconf propagates # $prefix, but not $exec_prefix (doh!). if test x$exec_prefix = xNONE ; then exec_prefix_default=yes exec_prefix=$prefix fi AC_MSG_NOTICE([configuring ${PACKAGE_NAME} ${PACKAGE_VERSION}]) AC_SUBST(EXEEXT) AC_SUBST(CYGPATH) # This package name must be replaced statically for AC_SUBST to work AC_SUBST(PKG_LIB_FILE) AC_SUBST(PKG_LIB_FILE8) AC_SUBST(PKG_LIB_FILE9) # We AC_SUBST these here to ensure they are subst'ed, # in case the user doesn't call TEA_ADD_... AC_SUBST(PKG_STUB_SOURCES) AC_SUBST(PKG_STUB_OBJECTS) AC_SUBST(PKG_TCL_SOURCES) AC_SUBST(PKG_HEADERS) AC_SUBST(PKG_INCLUDES) AC_SUBST(PKG_LIBS) AC_SUBST(PKG_CFLAGS) # Configure the installer. TEA_INSTALLER ]) #------------------------------------------------------------------------ # TEA_ADD_SOURCES -- # # Specify one or more source files. Users should check for # the right platform before adding to their list. # It is not important to specify the directory, as long as it is # in the generic, win or unix subdirectory of $(srcdir). # # Arguments: # one or more file names # # Results: # # Defines and substs the following vars: # PKG_SOURCES # PKG_OBJECTS #------------------------------------------------------------------------ AC_DEFUN([TEA_ADD_SOURCES], [ vars="$@" for i in $vars; do case $i in [\$]*) # allow $-var names PKG_SOURCES="$PKG_SOURCES $i" PKG_OBJECTS="$PKG_OBJECTS $i" ;; *) # check for existence - allows for generic/win/unix VPATH # To add more dirs here (like 'src'), you have to update VPATH # in Makefile.in as well if test ! -f "${srcdir}/$i" -a ! -f "${srcdir}/generic/$i" \ -a ! -f "${srcdir}/win/$i" -a ! -f "${srcdir}/unix/$i" \ -a ! -f "${srcdir}/macosx/$i" \ ; then AC_MSG_ERROR([could not find source file '$i']) fi PKG_SOURCES="$PKG_SOURCES $i" # this assumes it is in a VPATH dir i=`basename $i` # handle user calling this before or after TEA_SETUP_COMPILER if test x"${OBJEXT}" != x ; then j="`echo $i | sed -e 's/\.[[^.]]*$//'`.${OBJEXT}" else j="`echo $i | sed -e 's/\.[[^.]]*$//'`.\${OBJEXT}" fi PKG_OBJECTS="$PKG_OBJECTS $j" ;; esac done AC_SUBST(PKG_SOURCES) AC_SUBST(PKG_OBJECTS) ]) #------------------------------------------------------------------------ # TEA_ADD_STUB_SOURCES -- # # Specify one or more source files. Users should check for # the right platform before adding to their list. # It is not important to specify the directory, as long as it is # in the generic, win or unix subdirectory of $(srcdir). # # Arguments: # one or more file names # # Results: # # Defines and substs the following vars: # PKG_STUB_SOURCES # PKG_STUB_OBJECTS #------------------------------------------------------------------------ AC_DEFUN([TEA_ADD_STUB_SOURCES], [ vars="$@" for i in $vars; do # check for existence - allows for generic/win/unix VPATH if test ! -f "${srcdir}/$i" -a ! -f "${srcdir}/generic/$i" \ -a ! -f "${srcdir}/win/$i" -a ! -f "${srcdir}/unix/$i" \ -a ! -f "${srcdir}/macosx/$i" \ ; then AC_MSG_ERROR([could not find stub source file '$i']) fi PKG_STUB_SOURCES="$PKG_STUB_SOURCES $i" # this assumes it is in a VPATH dir i=`basename $i` # handle user calling this before or after TEA_SETUP_COMPILER if test x"${OBJEXT}" != x ; then j="`echo $i | sed -e 's/\.[[^.]]*$//'`.${OBJEXT}" else j="`echo $i | sed -e 's/\.[[^.]]*$//'`.\${OBJEXT}" fi PKG_STUB_OBJECTS="$PKG_STUB_OBJECTS $j" done AC_SUBST(PKG_STUB_SOURCES) AC_SUBST(PKG_STUB_OBJECTS) ]) #------------------------------------------------------------------------ # TEA_ADD_TCL_SOURCES -- # # Specify one or more Tcl source files. These should be platform # independent runtime files. # # Arguments: # one or more file names # # Results: # # Defines and substs the following vars: # PKG_TCL_SOURCES #------------------------------------------------------------------------ AC_DEFUN([TEA_ADD_TCL_SOURCES], [ vars="$@" for i in $vars; do # check for existence, be strict because it is installed if test ! -f "${srcdir}/$i" ; then AC_MSG_ERROR([could not find tcl source file '${srcdir}/$i']) fi PKG_TCL_SOURCES="$PKG_TCL_SOURCES $i" done AC_SUBST(PKG_TCL_SOURCES) ]) #------------------------------------------------------------------------ # TEA_ADD_HEADERS -- # # Specify one or more source headers. Users should check for # the right platform before adding to their list. # # Arguments: # one or more file names # # Results: # # Defines and substs the following vars: # PKG_HEADERS #------------------------------------------------------------------------ AC_DEFUN([TEA_ADD_HEADERS], [ vars="$@" for i in $vars; do # check for existence, be strict because it is installed if test ! -f "${srcdir}/$i" ; then AC_MSG_ERROR([could not find header file '${srcdir}/$i']) fi PKG_HEADERS="$PKG_HEADERS $i" done AC_SUBST(PKG_HEADERS) ]) #------------------------------------------------------------------------ # TEA_ADD_INCLUDES -- # # Specify one or more include dirs. Users should check for # the right platform before adding to their list. # # Arguments: # one or more file names # # Results: # # Defines and substs the following vars: # PKG_INCLUDES #------------------------------------------------------------------------ AC_DEFUN([TEA_ADD_INCLUDES], [ vars="$@" for i in $vars; do PKG_INCLUDES="$PKG_INCLUDES $i" done AC_SUBST(PKG_INCLUDES) ]) #------------------------------------------------------------------------ # TEA_ADD_LIBS -- # # Specify one or more libraries. Users should check for # the right platform before adding to their list. For Windows, # libraries provided in "foo.lib" format will be converted to # "-lfoo" when using GCC (mingw). # # Arguments: # one or more file names # # Results: # # Defines and substs the following vars: # PKG_LIBS #------------------------------------------------------------------------ AC_DEFUN([TEA_ADD_LIBS], [ vars="$@" for i in $vars; do if test "${TEA_PLATFORM}" = "windows" -a "$GCC" = "yes" ; then # Convert foo.lib to -lfoo for GCC. No-op if not *.lib i=`echo "$i" | sed -e 's/^\([[^-]].*\)\.[[lL]][[iI]][[bB]][$]/-l\1/'` fi PKG_LIBS="$PKG_LIBS $i" done AC_SUBST(PKG_LIBS) ]) #------------------------------------------------------------------------ # TEA_ADD_CFLAGS -- # # Specify one or more CFLAGS. Users should check for # the right platform before adding to their list. # # Arguments: # one or more file names # # Results: # # Defines and substs the following vars: # PKG_CFLAGS #------------------------------------------------------------------------ AC_DEFUN([TEA_ADD_CFLAGS], [ PKG_CFLAGS="$PKG_CFLAGS $@" AC_SUBST(PKG_CFLAGS) ]) #------------------------------------------------------------------------ # TEA_ADD_CLEANFILES -- # # Specify one or more CLEANFILES. # # Arguments: # one or more file names to clean target # # Results: # # Appends to CLEANFILES, already defined for subst in LOAD_TCLCONFIG #------------------------------------------------------------------------ AC_DEFUN([TEA_ADD_CLEANFILES], [ CLEANFILES="$CLEANFILES $@" ]) #------------------------------------------------------------------------ # TEA_PREFIX -- # # Handle the --prefix=... option by defaulting to what Tcl gave # # Arguments: # none # # Results: # # If --prefix or --exec-prefix was not specified, $prefix and # $exec_prefix will be set to the values given to Tcl when it was # configured. #------------------------------------------------------------------------ AC_DEFUN([TEA_PREFIX], [ if test "${prefix}" = "NONE"; then prefix_default=yes if test x"${TCL_PREFIX}" != x; then AC_MSG_NOTICE([--prefix defaulting to TCL_PREFIX ${TCL_PREFIX}]) prefix=${TCL_PREFIX} else AC_MSG_NOTICE([--prefix defaulting to /usr/local]) prefix=/usr/local fi fi if test "${exec_prefix}" = "NONE" -a x"${prefix_default}" = x"yes" \ -o x"${exec_prefix_default}" = x"yes" ; then if test x"${TCL_EXEC_PREFIX}" != x; then AC_MSG_NOTICE([--exec-prefix defaulting to TCL_EXEC_PREFIX ${TCL_EXEC_PREFIX}]) exec_prefix=${TCL_EXEC_PREFIX} else AC_MSG_NOTICE([--exec-prefix defaulting to ${prefix}]) exec_prefix=$prefix fi fi ]) #------------------------------------------------------------------------ # TEA_SETUP_COMPILER_CC -- # # Do compiler checks the way we want. This is just a replacement # for AC_PROG_CC in TEA configure.ac files to make them cleaner. # # Arguments: # none # # Results: # # Sets up CC var and other standard bits we need to make executables. #------------------------------------------------------------------------ AC_DEFUN([TEA_SETUP_COMPILER_CC], [ # Don't put any macros that use the compiler (e.g. AC_TRY_COMPILE) # in this macro, they need to go into TEA_SETUP_COMPILER instead. AC_PROG_CC AC_PROG_CPP #-------------------------------------------------------------------- # Checks to see if the make program sets the $MAKE variable. #-------------------------------------------------------------------- AC_PROG_MAKE_SET #-------------------------------------------------------------------- # Find ranlib #-------------------------------------------------------------------- AC_CHECK_TOOL(RANLIB, ranlib) #-------------------------------------------------------------------- # Determines the correct binary file extension (.o, .obj, .exe etc.) #-------------------------------------------------------------------- AC_OBJEXT AC_EXEEXT ]) #------------------------------------------------------------------------ # TEA_SETUP_COMPILER -- # # Do compiler checks that use the compiler. This must go after # TEA_SETUP_COMPILER_CC, which does the actual compiler check. # # Arguments: # none # # Results: # # Sets up CC var and other standard bits we need to make executables. #------------------------------------------------------------------------ AC_DEFUN([TEA_SETUP_COMPILER], [ # Any macros that use the compiler (e.g. AC_TRY_COMPILE) have to go here. AC_REQUIRE([TEA_SETUP_COMPILER_CC]) #------------------------------------------------------------------------ # If we're using GCC, see if the compiler understands -pipe. If so, use it. # It makes compiling go faster. (This is only a performance feature.) #------------------------------------------------------------------------ if test -z "$no_pipe" -a -n "$GCC"; then AC_CACHE_CHECK([if the compiler understands -pipe], tcl_cv_cc_pipe, [ hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -pipe" AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])],[tcl_cv_cc_pipe=yes],[tcl_cv_cc_pipe=no]) CFLAGS=$hold_cflags]) if test $tcl_cv_cc_pipe = yes; then CFLAGS="$CFLAGS -pipe" fi fi if test "${TCL_MAJOR_VERSION}" -lt 9 -a "${TCL_MINOR_VERSION}" -lt 7; then AC_DEFINE(Tcl_Size, int, [Is 'Tcl_Size' in ?]) fi #-------------------------------------------------------------------- # Common compiler flag setup #-------------------------------------------------------------------- AC_C_BIGENDIAN(,,,[#]) ]) #------------------------------------------------------------------------ # TEA_MAKE_LIB -- # # Generate a line that can be used to build a shared/unshared library # in a platform independent manner. # # Arguments: # none # # Requires: # # Results: # # Defines the following vars: # CFLAGS - Done late here to note disturb other AC macros # MAKE_LIB - Command to execute to build the Tcl library; # differs depending on whether or not Tcl is being # compiled as a shared library. # MAKE_SHARED_LIB Makefile rule for building a shared library # MAKE_STATIC_LIB Makefile rule for building a static library # MAKE_STUB_LIB Makefile rule for building a stub library # VC_MANIFEST_EMBED_DLL Makefile rule for embedded VC manifest in DLL # VC_MANIFEST_EMBED_EXE Makefile rule for embedded VC manifest in EXE #------------------------------------------------------------------------ AC_DEFUN([TEA_MAKE_LIB], [ if test "${TEA_PLATFORM}" = "windows" -a "$GCC" != "yes"; then MAKE_STATIC_LIB="\${STLIB_LD} -out:\[$]@ \$(PKG_OBJECTS)" MAKE_SHARED_LIB="\${SHLIB_LD} \${LDFLAGS} \${LDFLAGS_DEFAULT} -out:\[$]@ \$(PKG_OBJECTS) \${SHLIB_LD_LIBS}" AC_EGREP_CPP([manifest needed], [ #if defined(_MSC_VER) && _MSC_VER >= 1400 print("manifest needed") #endif ], [ # Could do a CHECK_PROG for mt, but should always be with MSVC8+ VC_MANIFEST_EMBED_DLL="if test -f \[$]@.manifest ; then mt.exe -nologo -manifest \[$]@.manifest -outputresource:\[$]@\;2 ; fi" VC_MANIFEST_EMBED_EXE="if test -f \[$]@.manifest ; then mt.exe -nologo -manifest \[$]@.manifest -outputresource:\[$]@\;1 ; fi" MAKE_SHARED_LIB="${MAKE_SHARED_LIB} ; ${VC_MANIFEST_EMBED_DLL}" TEA_ADD_CLEANFILES([*.manifest]) ]) MAKE_STUB_LIB="\${STLIB_LD} -nodefaultlib -out:\[$]@ \$(PKG_STUB_OBJECTS)" else MAKE_STATIC_LIB="\${STLIB_LD} \[$]@ \$(PKG_OBJECTS)" MAKE_SHARED_LIB="\${SHLIB_LD} \${LDFLAGS} \${LDFLAGS_DEFAULT} -o \[$]@ \$(PKG_OBJECTS) \${SHLIB_LD_LIBS}" MAKE_STUB_LIB="\${STLIB_LD} \[$]@ \$(PKG_STUB_OBJECTS)" fi if test "${SHARED_BUILD}" = "1" ; then MAKE_LIB="${MAKE_SHARED_LIB} " else MAKE_LIB="${MAKE_STATIC_LIB} " fi #-------------------------------------------------------------------- # Shared libraries and static libraries have different names. # Use the double eval to make sure any variables in the suffix is # substituted. (@@@ Might not be necessary anymore) #-------------------------------------------------------------------- PACKAGE_LIB_PREFIX8="${PACKAGE_LIB_PREFIX}" PACKAGE_LIB_PREFIX9="${PACKAGE_LIB_PREFIX}tcl9" if test "${TCL_MAJOR_VERSION}" -gt 8 -a x"${with_tcl8}" == x; then PACKAGE_LIB_PREFIX="${PACKAGE_LIB_PREFIX9}" else PACKAGE_LIB_PREFIX="${PACKAGE_LIB_PREFIX8}" AC_DEFINE(TCL_MAJOR_VERSION, 8, [Compile for Tcl8?]) fi if test "${TEA_PLATFORM}" = "windows" ; then if test "${SHARED_BUILD}" = "1" ; then # We force the unresolved linking of symbols that are really in # the private libraries of Tcl and Tk. if test x"${TK_BIN_DIR}" != x ; then SHLIB_LD_LIBS="${SHLIB_LD_LIBS} \"`${CYGPATH} ${TK_BIN_DIR}/${TK_STUB_LIB_FILE}`\"" fi SHLIB_LD_LIBS="${SHLIB_LD_LIBS} \"`${CYGPATH} ${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}`\"" if test "$GCC" = "yes"; then SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -static-libgcc" fi eval eval "PKG_LIB_FILE8=${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" eval eval "PKG_LIB_FILE9=${PACKAGE_LIB_PREFIX9}${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" eval eval "PKG_LIB_FILE=${PACKAGE_LIB_PREFIX}${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" else if test "$GCC" = "yes"; then PACKAGE_LIB_PREFIX=lib${PACKAGE_LIB_PREFIX} fi eval eval "PKG_LIB_FILE8=${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" eval eval "PKG_LIB_FILE9=${PACKAGE_LIB_PREFIX9}${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" eval eval "PKG_LIB_FILE=${PACKAGE_LIB_PREFIX}${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" fi # Some packages build their own stubs libraries if test "${TCL_MAJOR_VERSION}" -gt 8 -a x"${with_tcl8}" == x; then eval eval "PKG_STUB_LIB_FILE=${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}stub.a" else eval eval "PKG_STUB_LIB_FILE=${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}stub${UNSHARED_LIB_SUFFIX}" fi if test "$GCC" = "yes"; then PKG_STUB_LIB_FILE=lib${PKG_STUB_LIB_FILE} fi # These aren't needed on Windows (either MSVC or gcc) RANLIB=: RANLIB_STUB=: else RANLIB_STUB="${RANLIB}" if test "${SHARED_BUILD}" = "1" ; then SHLIB_LD_LIBS="${SHLIB_LD_LIBS} ${TCL_STUB_LIB_SPEC}" if test x"${TK_BIN_DIR}" != x ; then SHLIB_LD_LIBS="${SHLIB_LD_LIBS} ${TK_STUB_LIB_SPEC}" fi eval eval "PKG_LIB_FILE8=lib${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" eval eval "PKG_LIB_FILE9=lib${PACKAGE_LIB_PREFIX9}${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" eval eval "PKG_LIB_FILE=lib${PACKAGE_LIB_PREFIX}${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" RANLIB=: else eval eval "PKG_LIB_FILE8=lib${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" eval eval "PKG_LIB_FILE9=lib${PACKAGE_LIB_PREFIX9}${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" eval eval "PKG_LIB_FILE=lib${PACKAGE_LIB_PREFIX}${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" fi # Some packages build their own stubs libraries if test "${TCL_MAJOR_VERSION}" -gt 8 -a x"${with_tcl8}" == x; then eval eval "PKG_STUB_LIB_FILE=lib${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}stub.a" else eval eval "PKG_STUB_LIB_FILE=lib${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}stub${UNSHARED_LIB_SUFFIX}" fi fi # These are escaped so that only CFLAGS is picked up at configure time. # The other values will be substituted at make time. CFLAGS="${CFLAGS} \${CFLAGS_DEFAULT} \${CFLAGS_WARNING}" if test "${SHARED_BUILD}" = "1" ; then CFLAGS="${CFLAGS} \${SHLIB_CFLAGS}" fi AC_SUBST(MAKE_LIB) AC_SUBST(MAKE_SHARED_LIB) AC_SUBST(MAKE_STATIC_LIB) AC_SUBST(MAKE_STUB_LIB) # Substitute STUB_LIB_FILE in case package creates a stub library too. AC_SUBST(PKG_STUB_LIB_FILE) AC_SUBST(RANLIB_STUB) AC_SUBST(VC_MANIFEST_EMBED_DLL) AC_SUBST(VC_MANIFEST_EMBED_EXE) ]) #------------------------------------------------------------------------ # TEA_LIB_SPEC -- # # Compute the name of an existing object library located in libdir # from the given base name and produce the appropriate linker flags. # # Arguments: # basename The base name of the library without version # numbers, extensions, or "lib" prefixes. # extra_dir Extra directory in which to search for the # library. This location is used first, then # $prefix/$exec-prefix, then some defaults. # # Requires: # TEA_INIT and TEA_PREFIX must be called first. # # Results: # # Defines the following vars: # ${basename}_LIB_NAME The computed library name. # ${basename}_LIB_SPEC The computed linker flags. #------------------------------------------------------------------------ AC_DEFUN([TEA_LIB_SPEC], [ AC_MSG_CHECKING([for $1 library]) # Look in exec-prefix for the library (defined by TEA_PREFIX). tea_lib_name_dir="${exec_prefix}/lib" # Or in a user-specified location. if test x"$2" != x ; then tea_extra_lib_dir=$2 else tea_extra_lib_dir=NONE fi for i in \ `ls -dr ${tea_extra_lib_dir}/$1[[0-9]]*.lib 2>/dev/null ` \ `ls -dr ${tea_extra_lib_dir}/lib$1[[0-9]]* 2>/dev/null ` \ `ls -dr ${tea_lib_name_dir}/$1[[0-9]]*.lib 2>/dev/null ` \ `ls -dr ${tea_lib_name_dir}/lib$1[[0-9]]* 2>/dev/null ` \ `ls -dr /usr/lib/$1[[0-9]]*.lib 2>/dev/null ` \ `ls -dr /usr/lib/lib$1[[0-9]]* 2>/dev/null ` \ `ls -dr /usr/lib64/$1[[0-9]]*.lib 2>/dev/null ` \ `ls -dr /usr/lib64/lib$1[[0-9]]* 2>/dev/null ` \ `ls -dr /usr/local/lib/$1[[0-9]]*.lib 2>/dev/null ` \ `ls -dr /usr/local/lib/lib$1[[0-9]]* 2>/dev/null ` ; do if test -f "$i" ; then tea_lib_name_dir=`dirname $i` $1_LIB_NAME=`basename $i` $1_LIB_PATH_NAME=$i break fi done if test "${TEA_PLATFORM}" = "windows"; then $1_LIB_SPEC=\"`${CYGPATH} ${$1_LIB_PATH_NAME} 2>/dev/null`\" else # Strip off the leading "lib" and trailing ".a" or ".so" tea_lib_name_lib=`echo ${$1_LIB_NAME}|sed -e 's/^lib//' -e 's/\.[[^.]]*$//' -e 's/\.so.*//'` $1_LIB_SPEC="-L${tea_lib_name_dir} -l${tea_lib_name_lib}" fi if test "x${$1_LIB_NAME}" = x ; then AC_MSG_ERROR([not found]) else AC_MSG_RESULT([${$1_LIB_SPEC}]) fi ]) #------------------------------------------------------------------------ # TEA_PRIVATE_TCL_HEADERS -- # # Locate the private Tcl include files # # Arguments: # # Requires: # TCL_SRC_DIR Assumes that TEA_LOAD_TCLCONFIG has # already been called. # # Results: # # Substitutes the following vars: # TCL_TOP_DIR_NATIVE # TCL_INCLUDES #------------------------------------------------------------------------ AC_DEFUN([TEA_PRIVATE_TCL_HEADERS], [ # Allow for --with-tclinclude to take effect and define ${ac_cv_c_tclh} AC_REQUIRE([TEA_PUBLIC_TCL_HEADERS]) AC_MSG_CHECKING([for Tcl private include files]) TCL_SRC_DIR_NATIVE=`${CYGPATH} ${TCL_SRC_DIR}` TCL_TOP_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}\" # Check to see if tclPort.h isn't already with the public headers # Don't look for tclInt.h because that resides with tcl.h in the core # sources, but the Port headers are in a different directory if test "${TEA_PLATFORM}" = "windows" -a \ -f "${ac_cv_c_tclh}/tclWinPort.h"; then result="private headers found with public headers" elif test "${TEA_PLATFORM}" = "unix" -a \ -f "${ac_cv_c_tclh}/tclUnixPort.h"; then result="private headers found with public headers" else TCL_GENERIC_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/generic\" if test "${TEA_PLATFORM}" = "windows"; then TCL_PLATFORM_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/win\" else TCL_PLATFORM_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/unix\" fi # Overwrite the previous TCL_INCLUDES as this should capture both # public and private headers in the same set. # We want to ensure these are substituted so as not to require # any *_NATIVE vars be defined in the Makefile TCL_INCLUDES="-I${TCL_GENERIC_DIR_NATIVE} -I${TCL_PLATFORM_DIR_NATIVE}" if test "`uname -s`" = "Darwin"; then # If Tcl was built as a framework, attempt to use # the framework's Headers and PrivateHeaders directories case ${TCL_DEFS} in *TCL_FRAMEWORK*) if test -d "${TCL_BIN_DIR}/Headers" -a \ -d "${TCL_BIN_DIR}/PrivateHeaders"; then TCL_INCLUDES="-I\"${TCL_BIN_DIR}/Headers\" -I\"${TCL_BIN_DIR}/PrivateHeaders\" ${TCL_INCLUDES}" else TCL_INCLUDES="${TCL_INCLUDES} ${TCL_INCLUDE_SPEC} `echo "${TCL_INCLUDE_SPEC}" | sed -e 's/Headers/PrivateHeaders/'`" fi ;; esac result="Using ${TCL_INCLUDES}" else if test ! -f "${TCL_SRC_DIR}/generic/tclInt.h" ; then AC_MSG_ERROR([Cannot find private header tclInt.h in ${TCL_SRC_DIR}]) fi result="Using srcdir found in tclConfig.sh: ${TCL_SRC_DIR}" fi fi AC_SUBST(TCL_TOP_DIR_NATIVE) AC_SUBST(TCL_INCLUDES) AC_MSG_RESULT([${result}]) ]) #------------------------------------------------------------------------ # TEA_PUBLIC_TCL_HEADERS -- # # Locate the installed public Tcl header files # # Arguments: # None. # # Requires: # CYGPATH must be set # # Results: # # Adds a --with-tclinclude switch to configure. # Result is cached. # # Substitutes the following vars: # TCL_INCLUDES #------------------------------------------------------------------------ AC_DEFUN([TEA_PUBLIC_TCL_HEADERS], [ AC_MSG_CHECKING([for Tcl public headers]) AC_ARG_WITH(tclinclude, [ --with-tclinclude directory containing the public Tcl header files], with_tclinclude=${withval}) AC_CACHE_VAL(ac_cv_c_tclh, [ # Use the value from --with-tclinclude, if it was given if test x"${with_tclinclude}" != x ; then if test -f "${with_tclinclude}/tcl.h" ; then ac_cv_c_tclh=${with_tclinclude} else AC_MSG_ERROR([${with_tclinclude} directory does not contain tcl.h]) fi else list="" if test "`uname -s`" = "Darwin"; then # If Tcl was built as a framework, attempt to use # the framework's Headers directory case ${TCL_DEFS} in *TCL_FRAMEWORK*) list="`ls -d ${TCL_BIN_DIR}/Headers 2>/dev/null`" ;; esac fi # Look in the source dir only if Tcl is not installed, # and in that situation, look there before installed locations. if test -f "${TCL_BIN_DIR}/Makefile" ; then list="$list `ls -d ${TCL_SRC_DIR}/generic 2>/dev/null`" fi # Check order: pkg --prefix location, Tcl's --prefix location, # relative to directory of tclConfig.sh. eval "temp_includedir=${includedir}" list="$list \ `ls -d ${temp_includedir} 2>/dev/null` \ `ls -d ${TCL_PREFIX}/include 2>/dev/null` \ `ls -d ${TCL_BIN_DIR}/../include 2>/dev/null`" if test "${TEA_PLATFORM}" != "windows" -o "$GCC" = "yes"; then list="$list /usr/local/include /usr/include" if test x"${TCL_INCLUDE_SPEC}" != x ; then d=`echo "${TCL_INCLUDE_SPEC}" | sed -e 's/^-I//'` list="$list `ls -d ${d} 2>/dev/null`" fi fi for i in $list ; do if test -f "$i/tcl.h" ; then ac_cv_c_tclh=$i break fi done fi ]) # Print a message based on how we determined the include path if test x"${ac_cv_c_tclh}" = x ; then AC_MSG_ERROR([tcl.h not found. Please specify its location with --with-tclinclude]) else AC_MSG_RESULT([${ac_cv_c_tclh}]) fi # Convert to a native path and substitute into the output files. INCLUDE_DIR_NATIVE=`${CYGPATH} ${ac_cv_c_tclh}` TCL_INCLUDES=-I\"${INCLUDE_DIR_NATIVE}\" AC_SUBST(TCL_INCLUDES) ]) #------------------------------------------------------------------------ # TEA_PRIVATE_TK_HEADERS -- # # Locate the private Tk include files # # Arguments: # # Requires: # TK_SRC_DIR Assumes that TEA_LOAD_TKCONFIG has # already been called. # # Results: # # Substitutes the following vars: # TK_INCLUDES #------------------------------------------------------------------------ AC_DEFUN([TEA_PRIVATE_TK_HEADERS], [ # Allow for --with-tkinclude to take effect and define ${ac_cv_c_tkh} AC_REQUIRE([TEA_PUBLIC_TK_HEADERS]) AC_MSG_CHECKING([for Tk private include files]) TK_SRC_DIR_NATIVE=`${CYGPATH} ${TK_SRC_DIR}` TK_TOP_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}\" # Check to see if tkPort.h isn't already with the public headers # Don't look for tkInt.h because that resides with tk.h in the core # sources, but the Port headers are in a different directory if test "${TEA_PLATFORM}" = "windows" -a \ -f "${ac_cv_c_tkh}/tkWinPort.h"; then result="private headers found with public headers" elif test "${TEA_PLATFORM}" = "unix" -a \ -f "${ac_cv_c_tkh}/tkUnixPort.h"; then result="private headers found with public headers" else TK_GENERIC_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}/generic\" TK_XLIB_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}/xlib\" if test "${TEA_PLATFORM}" = "windows"; then TK_PLATFORM_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}/win\" else TK_PLATFORM_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}/unix\" fi # Overwrite the previous TK_INCLUDES as this should capture both # public and private headers in the same set. # We want to ensure these are substituted so as not to require # any *_NATIVE vars be defined in the Makefile TK_INCLUDES="-I${TK_GENERIC_DIR_NATIVE} -I${TK_PLATFORM_DIR_NATIVE}" # Detect and add ttk subdir if test -d "${TK_SRC_DIR}/generic/ttk"; then TK_INCLUDES="${TK_INCLUDES} -I\"${TK_SRC_DIR_NATIVE}/generic/ttk\"" fi if test "${TEA_WINDOWINGSYSTEM}" != "x11"; then TK_INCLUDES="${TK_INCLUDES} -I\"${TK_XLIB_DIR_NATIVE}\"" fi if test "${TEA_WINDOWINGSYSTEM}" = "aqua"; then TK_INCLUDES="${TK_INCLUDES} -I\"${TK_SRC_DIR_NATIVE}/macosx\"" fi if test "`uname -s`" = "Darwin"; then # If Tk was built as a framework, attempt to use # the framework's Headers and PrivateHeaders directories case ${TK_DEFS} in *TK_FRAMEWORK*) if test -d "${TK_BIN_DIR}/Headers" -a \ -d "${TK_BIN_DIR}/PrivateHeaders"; then TK_INCLUDES="-I\"${TK_BIN_DIR}/Headers\" -I\"${TK_BIN_DIR}/PrivateHeaders\" ${TK_INCLUDES}" else TK_INCLUDES="${TK_INCLUDES} ${TK_INCLUDE_SPEC} `echo "${TK_INCLUDE_SPEC}" | sed -e 's/Headers/PrivateHeaders/'`" fi ;; esac result="Using ${TK_INCLUDES}" else if test ! -f "${TK_SRC_DIR}/generic/tkInt.h" ; then AC_MSG_ERROR([Cannot find private header tkInt.h in ${TK_SRC_DIR}]) fi result="Using srcdir found in tkConfig.sh: ${TK_SRC_DIR}" fi fi AC_SUBST(TK_TOP_DIR_NATIVE) AC_SUBST(TK_XLIB_DIR_NATIVE) AC_SUBST(TK_INCLUDES) AC_MSG_RESULT([${result}]) ]) #------------------------------------------------------------------------ # TEA_PUBLIC_TK_HEADERS -- # # Locate the installed public Tk header files # # Arguments: # None. # # Requires: # CYGPATH must be set # # Results: # # Adds a --with-tkinclude switch to configure. # Result is cached. # # Substitutes the following vars: # TK_INCLUDES #------------------------------------------------------------------------ AC_DEFUN([TEA_PUBLIC_TK_HEADERS], [ AC_MSG_CHECKING([for Tk public headers]) AC_ARG_WITH(tkinclude, [ --with-tkinclude directory containing the public Tk header files], with_tkinclude=${withval}) AC_CACHE_VAL(ac_cv_c_tkh, [ # Use the value from --with-tkinclude, if it was given if test x"${with_tkinclude}" != x ; then if test -f "${with_tkinclude}/tk.h" ; then ac_cv_c_tkh=${with_tkinclude} else AC_MSG_ERROR([${with_tkinclude} directory does not contain tk.h]) fi else list="" if test "`uname -s`" = "Darwin"; then # If Tk was built as a framework, attempt to use # the framework's Headers directory. case ${TK_DEFS} in *TK_FRAMEWORK*) list="`ls -d ${TK_BIN_DIR}/Headers 2>/dev/null`" ;; esac fi # Look in the source dir only if Tk is not installed, # and in that situation, look there before installed locations. if test -f "${TK_BIN_DIR}/Makefile" ; then list="$list `ls -d ${TK_SRC_DIR}/generic 2>/dev/null`" fi # Check order: pkg --prefix location, Tk's --prefix location, # relative to directory of tkConfig.sh, Tcl's --prefix location, # relative to directory of tclConfig.sh. eval "temp_includedir=${includedir}" list="$list \ `ls -d ${temp_includedir} 2>/dev/null` \ `ls -d ${TK_PREFIX}/include 2>/dev/null` \ `ls -d ${TK_BIN_DIR}/../include 2>/dev/null` \ `ls -d ${TCL_PREFIX}/include 2>/dev/null` \ `ls -d ${TCL_BIN_DIR}/../include 2>/dev/null`" if test "${TEA_PLATFORM}" != "windows" -o "$GCC" = "yes"; then list="$list /usr/local/include /usr/include" if test x"${TK_INCLUDE_SPEC}" != x ; then d=`echo "${TK_INCLUDE_SPEC}" | sed -e 's/^-I//'` list="$list `ls -d ${d} 2>/dev/null`" fi fi for i in $list ; do if test -f "$i/tk.h" ; then ac_cv_c_tkh=$i break fi done fi ]) # Print a message based on how we determined the include path if test x"${ac_cv_c_tkh}" = x ; then AC_MSG_ERROR([tk.h not found. Please specify its location with --with-tkinclude]) else AC_MSG_RESULT([${ac_cv_c_tkh}]) fi # Convert to a native path and substitute into the output files. INCLUDE_DIR_NATIVE=`${CYGPATH} ${ac_cv_c_tkh}` TK_INCLUDES=-I\"${INCLUDE_DIR_NATIVE}\" AC_SUBST(TK_INCLUDES) if test "${TEA_WINDOWINGSYSTEM}" != "x11"; then # On Windows and Aqua, we need the X compat headers AC_MSG_CHECKING([for X11 header files]) if test ! -r "${INCLUDE_DIR_NATIVE}/X11/Xlib.h"; then INCLUDE_DIR_NATIVE="`${CYGPATH} ${TK_SRC_DIR}/xlib`" TK_XINCLUDES=-I\"${INCLUDE_DIR_NATIVE}\" AC_SUBST(TK_XINCLUDES) fi AC_MSG_RESULT([${INCLUDE_DIR_NATIVE}]) fi ]) #------------------------------------------------------------------------ # TEA_PATH_CONFIG -- # # Locate the ${1}Config.sh file and perform a sanity check on # the ${1} compile flags. These are used by packages like # [incr Tk] that load *Config.sh files from more than Tcl and Tk. # # Arguments: # none # # Results: # # Adds the following arguments to configure: # --with-$1=... # # Defines the following vars: # $1_BIN_DIR Full path to the directory containing # the $1Config.sh file #------------------------------------------------------------------------ AC_DEFUN([TEA_PATH_CONFIG], [ # # Ok, lets find the $1 configuration # First, look for one uninstalled. # the alternative search directory is invoked by --with-$1 # if test x"${no_$1}" = x ; then # we reset no_$1 in case something fails here no_$1=true AC_ARG_WITH($1, [ --with-$1 directory containing $1 configuration ($1Config.sh)], with_$1config=${withval}) AC_MSG_CHECKING([for $1 configuration]) AC_CACHE_VAL(ac_cv_c_$1config,[ # First check to see if --with-$1 was specified. if test x"${with_$1config}" != x ; then case ${with_$1config} in */$1Config.sh ) if test -f ${with_$1config}; then AC_MSG_WARN([--with-$1 argument should refer to directory containing $1Config.sh, not to $1Config.sh itself]) with_$1config=`echo ${with_$1config} | sed 's!/$1Config\.sh$!!'` fi;; esac if test -f "${with_$1config}/$1Config.sh" ; then ac_cv_c_$1config=`(cd ${with_$1config}; pwd)` else AC_MSG_ERROR([${with_$1config} directory doesn't contain $1Config.sh]) fi fi # then check for a private $1 installation if test x"${ac_cv_c_$1config}" = x ; then for i in \ ../$1 \ `ls -dr ../$1*[[0-9]].[[0-9]]*.[[0-9]]* 2>/dev/null` \ `ls -dr ../$1*[[0-9]].[[0-9]][[0-9]] 2>/dev/null` \ `ls -dr ../$1*[[0-9]].[[0-9]] 2>/dev/null` \ `ls -dr ../$1*[[0-9]].[[0-9]]* 2>/dev/null` \ ../../$1 \ `ls -dr ../../$1*[[0-9]].[[0-9]]*.[[0-9]]* 2>/dev/null` \ `ls -dr ../../$1*[[0-9]].[[0-9]][[0-9]] 2>/dev/null` \ `ls -dr ../../$1*[[0-9]].[[0-9]] 2>/dev/null` \ `ls -dr ../../$1*[[0-9]].[[0-9]]* 2>/dev/null` \ ../../../$1 \ `ls -dr ../../../$1*[[0-9]].[[0-9]]*.[[0-9]]* 2>/dev/null` \ `ls -dr ../../../$1*[[0-9]].[[0-9]][[0-9]] 2>/dev/null` \ `ls -dr ../../../$1*[[0-9]].[[0-9]] 2>/dev/null` \ `ls -dr ../../../$1*[[0-9]].[[0-9]]* 2>/dev/null` \ ${srcdir}/../$1 \ `ls -dr ${srcdir}/../$1*[[0-9]].[[0-9]]*.[[0-9]]* 2>/dev/null` \ `ls -dr ${srcdir}/../$1*[[0-9]].[[0-9]][[0-9]] 2>/dev/null` \ `ls -dr ${srcdir}/../$1*[[0-9]].[[0-9]] 2>/dev/null` \ `ls -dr ${srcdir}/../$1*[[0-9]].[[0-9]]* 2>/dev/null` \ ; do if test -f "$i/$1Config.sh" ; then ac_cv_c_$1config=`(cd $i; pwd)` break fi if test -f "$i/unix/$1Config.sh" ; then ac_cv_c_$1config=`(cd $i/unix; pwd)` break fi done fi # check in a few common install locations if test x"${ac_cv_c_$1config}" = x ; then for i in `ls -d ${libdir} 2>/dev/null` \ `ls -d ${exec_prefix}/lib 2>/dev/null` \ `ls -d ${prefix}/lib 2>/dev/null` \ `ls -d /usr/local/lib 2>/dev/null` \ `ls -d /usr/contrib/lib 2>/dev/null` \ `ls -d /usr/pkg/lib 2>/dev/null` \ `ls -d /usr/lib 2>/dev/null` \ `ls -d /usr/lib64 2>/dev/null` \ ; do if test -f "$i/$1Config.sh" ; then ac_cv_c_$1config=`(cd $i; pwd)` break fi done fi ]) if test x"${ac_cv_c_$1config}" = x ; then $1_BIN_DIR="# no $1 configs found" AC_MSG_WARN([Cannot find $1 configuration definitions]) exit 0 else no_$1= $1_BIN_DIR=${ac_cv_c_$1config} AC_MSG_RESULT([found $$1_BIN_DIR/$1Config.sh]) fi fi ]) #------------------------------------------------------------------------ # TEA_LOAD_CONFIG -- # # Load the $1Config.sh file # # Arguments: # # Requires the following vars to be set: # $1_BIN_DIR # # Results: # # Substitutes the following vars: # $1_SRC_DIR # $1_LIB_FILE # $1_LIB_SPEC #------------------------------------------------------------------------ AC_DEFUN([TEA_LOAD_CONFIG], [ AC_MSG_CHECKING([for existence of ${$1_BIN_DIR}/$1Config.sh]) if test -f "${$1_BIN_DIR}/$1Config.sh" ; then AC_MSG_RESULT([loading]) . "${$1_BIN_DIR}/$1Config.sh" else AC_MSG_RESULT([file not found]) fi # # If the $1_BIN_DIR is the build directory (not the install directory), # then set the common variable name to the value of the build variables. # For example, the variable $1_LIB_SPEC will be set to the value # of $1_BUILD_LIB_SPEC. An extension should make use of $1_LIB_SPEC # instead of $1_BUILD_LIB_SPEC since it will work with both an # installed and uninstalled version of Tcl. # if test -f "${$1_BIN_DIR}/Makefile" ; then AC_MSG_WARN([Found Makefile - using build library specs for $1]) $1_LIB_SPEC=${$1_BUILD_LIB_SPEC} $1_STUB_LIB_SPEC=${$1_BUILD_STUB_LIB_SPEC} $1_STUB_LIB_PATH=${$1_BUILD_STUB_LIB_PATH} $1_INCLUDE_SPEC=${$1_BUILD_INCLUDE_SPEC} $1_LIBRARY_PATH=${$1_LIBRARY_PATH} fi AC_SUBST($1_VERSION) AC_SUBST($1_BIN_DIR) AC_SUBST($1_SRC_DIR) AC_SUBST($1_LIB_FILE) AC_SUBST($1_LIB_SPEC) AC_SUBST($1_STUB_LIB_FILE) AC_SUBST($1_STUB_LIB_SPEC) AC_SUBST($1_STUB_LIB_PATH) # Allow the caller to prevent this auto-check by specifying any 2nd arg AS_IF([test "x$2" = x], [ # Check both upper and lower-case variants # If a dev wanted non-stubs libs, this function could take an option # to not use _STUB in the paths below AS_IF([test "x${$1_STUB_LIB_SPEC}" = x], [TEA_LOAD_CONFIG_LIB(translit($1,[a-z],[A-Z])_STUB)], [TEA_LOAD_CONFIG_LIB($1_STUB)]) ]) ]) #------------------------------------------------------------------------ # TEA_LOAD_CONFIG_LIB -- # # Helper function to load correct library from another extension's # ${PACKAGE}Config.sh. # # Results: # Adds to LIBS the appropriate extension library #------------------------------------------------------------------------ AC_DEFUN([TEA_LOAD_CONFIG_LIB], [ AC_MSG_CHECKING([For $1 library for LIBS]) # This simplifies the use of stub libraries by automatically adding # the stub lib to your path. Normally this would add to SHLIB_LD_LIBS, # but this is called before CONFIG_CFLAGS. More importantly, this adds # to PKG_LIBS, which becomes LIBS, and that is only used by SHLIB_LD. if test "x${$1_LIB_SPEC}" != "x" ; then if test "${TEA_PLATFORM}" = "windows" -a "$GCC" != "yes" ; then TEA_ADD_LIBS([\"`${CYGPATH} ${$1_LIB_PATH}`\"]) AC_MSG_RESULT([using $1_LIB_PATH ${$1_LIB_PATH}]) else TEA_ADD_LIBS([${$1_LIB_SPEC}]) AC_MSG_RESULT([using $1_LIB_SPEC ${$1_LIB_SPEC}]) fi else AC_MSG_RESULT([file not found]) fi ]) #------------------------------------------------------------------------ # TEA_EXPORT_CONFIG -- # # Define the data to insert into the ${PACKAGE}Config.sh file # # Arguments: # # Requires the following vars to be set: # $1 # # Results: # Substitutes the following vars: #------------------------------------------------------------------------ AC_DEFUN([TEA_EXPORT_CONFIG], [ #-------------------------------------------------------------------- # These are for $1Config.sh #-------------------------------------------------------------------- # pkglibdir must be a fully qualified path and (not ${exec_prefix}/lib) eval pkglibdir="[$]{libdir}/$1${PACKAGE_VERSION}" if test "${TCL_LIB_VERSIONS_OK}" = "ok"; then eval $1_LIB_FLAG="-l$1${PACKAGE_VERSION}" eval $1_STUB_LIB_FLAG="-l$1stub${PACKAGE_VERSION}" else eval $1_LIB_FLAG="-l$1`echo ${PACKAGE_VERSION} | tr -d .`" eval $1_STUB_LIB_FLAG="-l$1stub`echo ${PACKAGE_VERSION} | tr -d .`" fi if test "${TCL_MAJOR_VERSION}" -gt 8 -a x"${with_tcl8}" == x; then eval $1_STUB_LIB_FLAG="-l$1stub" fi $1_BUILD_LIB_SPEC="-L`$CYGPATH $(pwd)` ${$1_LIB_FLAG}" $1_LIB_SPEC="-L`$CYGPATH ${pkglibdir}` ${$1_LIB_FLAG}" $1_BUILD_STUB_LIB_SPEC="-L`$CYGPATH $(pwd)` [$]{$1_STUB_LIB_FLAG}" $1_STUB_LIB_SPEC="-L`$CYGPATH ${pkglibdir}` [$]{$1_STUB_LIB_FLAG}" $1_BUILD_STUB_LIB_PATH="`$CYGPATH $(pwd)`/[$]{PKG_STUB_LIB_FILE}" $1_STUB_LIB_PATH="`$CYGPATH ${pkglibdir}`/[$]{PKG_STUB_LIB_FILE}" AC_SUBST($1_BUILD_LIB_SPEC) AC_SUBST($1_LIB_SPEC) AC_SUBST($1_BUILD_STUB_LIB_SPEC) AC_SUBST($1_STUB_LIB_SPEC) AC_SUBST($1_BUILD_STUB_LIB_PATH) AC_SUBST($1_STUB_LIB_PATH) AC_SUBST(MAJOR_VERSION) AC_SUBST(MINOR_VERSION) AC_SUBST(PATCHLEVEL) ]) #------------------------------------------------------------------------ # TEA_INSTALLER -- # # Configure the installer. # # Arguments: # none # # Results: # Substitutes the following vars: # INSTALL # INSTALL_DATA_DIR # INSTALL_DATA # INSTALL_PROGRAM # INSTALL_SCRIPT # INSTALL_LIBRARY #------------------------------------------------------------------------ AC_DEFUN([TEA_INSTALLER], [ INSTALL='$(SHELL) $(srcdir)/tclconfig/install-sh -c' INSTALL_DATA_DIR='${INSTALL} -d -m 755' INSTALL_DATA='${INSTALL} -m 644' INSTALL_PROGRAM='${INSTALL} -m 755' INSTALL_SCRIPT='${INSTALL} -m 755' TEA_CONFIG_SYSTEM case $system in HP-UX-*) INSTALL_LIBRARY='${INSTALL} -m 755' ;; *) INSTALL_LIBRARY='${INSTALL} -m 644' ;; esac AC_SUBST(INSTALL) AC_SUBST(INSTALL_DATA_DIR) AC_SUBST(INSTALL_DATA) AC_SUBST(INSTALL_PROGRAM) AC_SUBST(INSTALL_SCRIPT) AC_SUBST(INSTALL_LIBRARY) ]) ### # Tip 430 - ZipFS Modifications ### #------------------------------------------------------------------------ # TEA_ZIPFS_SUPPORT # Locate a zip encoder installed on the system path, or none. # # Arguments: # none # # Results: # Substitutes the following vars: # MACHER_PROG # ZIP_PROG # ZIP_PROG_OPTIONS # ZIP_PROG_VFSSEARCH # ZIP_INSTALL_OBJS #------------------------------------------------------------------------ AC_DEFUN([TEA_ZIPFS_SUPPORT], [ MACHER_PROG="" ZIP_PROG="" ZIP_PROG_OPTIONS="" ZIP_PROG_VFSSEARCH="" ZIP_INSTALL_OBJS="" AC_MSG_CHECKING([for macher]) AC_CACHE_VAL(ac_cv_path_macher, [ search_path=`echo ${PATH} | sed -e 's/:/ /g'` for dir in $search_path ; do for j in `ls -r $dir/macher 2> /dev/null` \ `ls -r $dir/macher 2> /dev/null` ; do if test x"$ac_cv_path_macher" = x ; then if test -f "$j" ; then ac_cv_path_macher=$j break fi fi done done ]) if test -f "$ac_cv_path_macher" ; then MACHER_PROG="$ac_cv_path_macher" AC_MSG_RESULT([$MACHER_PROG]) AC_MSG_RESULT([Found macher in environment]) fi AC_MSG_CHECKING([for zip]) AC_CACHE_VAL(ac_cv_path_zip, [ search_path=`echo ${PATH} | sed -e 's/:/ /g'` for dir in $search_path ; do for j in `ls -r $dir/zip 2> /dev/null` \ `ls -r $dir/zip 2> /dev/null` ; do if test x"$ac_cv_path_zip" = x ; then if test -f "$j" ; then ac_cv_path_zip=$j break fi fi done done ]) if test -f "$ac_cv_path_zip" ; then ZIP_PROG="$ac_cv_path_zip" AC_MSG_RESULT([$ZIP_PROG]) ZIP_PROG_OPTIONS="-rq" ZIP_PROG_VFSSEARCH="*" AC_MSG_RESULT([Found INFO Zip in environment]) # Use standard arguments for zip else # It is not an error if an installed version of Zip can't be located. # We can use the locally distributed minizip instead ZIP_PROG="./minizip${EXEEXT_FOR_BUILD}" ZIP_PROG_OPTIONS="-o -r" ZIP_PROG_VFSSEARCH="*" ZIP_INSTALL_OBJS="minizip${EXEEXT_FOR_BUILD}" AC_MSG_RESULT([No zip found on PATH. Building minizip]) fi AC_SUBST(MACHER_PROG) AC_SUBST(ZIP_PROG) AC_SUBST(ZIP_PROG_OPTIONS) AC_SUBST(ZIP_PROG_VFSSEARCH) AC_SUBST(ZIP_INSTALL_OBJS) ]) # Local Variables: # mode: autoconf # End: ooxml/tclconfig/README.txt000644 000765 000024 00000001454 14764622263 015776 0ustar00alexstaff000000 000000 These files comprise the basic building blocks for a Tcl Extension Architecture (TEA) extension. For more information on TEA see: http://www.tcl.tk/doc/tea/ This package is part of the Tcl project at SourceForge, and latest sources should be available there: http://tcl.sourceforge.net/ This package is a freely available open source package. You can do virtually anything you like with it, such as modifying it, redistributing it, and selling it either in whole or in part. CONTENTS ======== The following is a short description of the files you will find in the sample extension. README.txt This file install-sh Program used for copying binaries and script files to their install locations. tcl.m4 Collection of Tcl autoconf macros. Included by a package's aclocal.m4 to define TEA_* macros. ooxml/tools/mkversion.tcl000644 000765 000024 00000012457 15124267670 016214 0ustar00alexstaff000000 000000 #!/bin/sh #\ exec tclsh "$0" "$@" # # 2024-2025 Alexander Schöpe, Bochum, DE # mkversion.c from fossil-scm ported to vanilla tcl # set manifest {} set optDefines 0 set optPkgName 0 set pkgName {} # Note: # fossil GUI Settings Manifest = on. # If necessary, the fossil clone setting 'fossil settings manifest --value' must be checked # and set correctly using 'fossil settings manifest on'. proc hash {zIn N} { set zL {} foreach c [split $zIn {}] { lappend zL [scan $c %c] } lappend zL 0 set zIn $zL unset zL set s {} for {set m 0} {$m < 256} {incr m} { lappend s $m } lappend s 0 for {set t 0; set j 0; set n 0; set m 0} {$m < 256} {incr m; incr n} { set j [expr {($j + [lindex $s $m] + [lindex $zIn $n]) & 0xff}] if {[lindex $zIn $n] == 0} { set n -1 } set t [lindex $s $j] set s [lreplace $s $j $j [lindex $s $m]] set s [lreplace $s $m $m $t] } set i 0 set j 0 set zOut {} for {set n 0} {$n < $N-2} {incr n 2} { incr i set t [lindex $s $i] set j [expr {($j + $t) & 0xff}] set s [lreplace $s $i $i [lindex $s $j]] set s [lreplace $s $j $j $t] set t [expr {($t + [lindex $s $i]) & 0xff}] append zOut [string index 0123456789abcdef [expr {($t >> 4) & 0xf}]] append zOut [string index 0123456789abcdef [expr {$t & 0xf}]] } return $zOut } if {![catch {open manifest.uuid r} fd]} { if {![eof $fd]} { if {[gets $fd uuid] > 0} { lappend manifest MANIFEST_UUID $uuid lappend manifest MANIFEST_VERSION [format {%10.10s} $uuid] if {[info exists ::env(SOURCE_DATE_EPOCH)] && [string is wideinteger $::env(SOURCE_DATE_EPOCH)]} { set ctime $::env(SOURCE_DATE_EPOCH) } else { set ctime [clock seconds] } append uuid $ctime lappend manifest FOSSIL_BUILD_HASH [hash $uuid 33] } } close $fd } else { puts stderr "can't open file manifest.uuid" } if {![catch {open manifest r} fd]} { while {![eof $fd]} { if {[gets $fd line] > 0} { if {[string match {D *} $line]} { set ctime [clock scan [lindex [split [lindex $line 1] .] 0] -gmt 1] lappend manifest MANIFEST_DATE [clock format $ctime -format {%Y-%m-%d %H:%M:%S} -gmt 1] lappend manifest MANIFEST_YEAR [clock format $ctime -format {%Y} -gmt 1] lappend manifest MANIFEST_NUMERIC_DATE [clock format $ctime -format {%Y%m%d} -gmt 1] lappend manifest MANIFEST_NUMERIC_TIME [clock format $ctime -format {%H%M%S} -gmt 1] break } } } close $fd } else { puts stderr "can't open file manifest" } if {![catch {open configure.ac r} fd]} { while {![eof $fd]} { if {[gets $fd line] > 0} { if {[string match {AC_INIT*} $line]} { if {[regexp {AC_INIT\(\[([^\]]*)\]\s*,\s*\[(.*?)\]\)} $line match name version]} { set pkgName [string toupper $name] set versionList [lrange [split $version.0.0.0 .] 0 3] lappend manifest RELEASE_VERSION $version lappend manifest RELEASE_VERSION_NUMBER [format {%d%02d%d%d} {*}$versionList] lappend manifest RELEASE_RESOURCE_VERSION [format {%d,%d,%d,%d} {*}$versionList] } break } } } close $fd } else { puts stderr "can't open file configure.ac" } if {0} { # # Build Info Example Procedure # proc ::pkgname::build-info { {cmd {}} } { variable pkgPath # TIP 599: Extended build information # https://core.tcl-lang.org/tips/doc/trunk/tip/599.md set file [file join $pkgPath manifest.txt] if {[file readable $file] && ![catch {open $file r} fd]} { set manifest [read $fd] close $fd set uuid [dict get $manifest MANIFEST_UUID] set checkin [string map {[ {} ] {}} [dict get $manifest MANIFEST_VERSION]] set build [dict get $manifest FOSSIL_BUILD_HASH] set datetime [string map {{ } T} [dict get $manifest MANIFEST_DATE]]Z set version [dict get $manifest RELEASE_VERSION] set compiler {tcl.noarch} switch -- $cmd { commit { return $uuid } version - patchlevel { return $version } compiler { return $compiler } path { return $pkgPath } default { return ${version}+${checkin}.${datetime}.${compiler} } } } else { return {?.manifest_not_found} } } package provide 1.0 # info script ?filename? # If a Tcl script file is currently being evaluated (i.e. there is a call to Tcl_EvalFile active or there is an active invocation of the source command), # then this command returns the name of the innermost file being processed. If filename is specified, then the return value of this command will be modified # for the duration of the active invocation to return that name. This is useful in virtual file system applications. Otherwise the command returns an empty string. set ::pkgname::pkgPath [file dirname [info script]] } foreach arg $argv { switch -exact -- $arg { -defines { set optDefines 1 } -name { set optPkgName 1 } } } if {$optDefines} { foreach {n v} $manifest { if {$n ni {MANIFEST_NUMERIC_DATE MANIFEST_NUMERIC_TIME RELEASE_VERSION_NUMBER RELEASE_RESOURCE_VERSION}} { set v "\"$v\"" } if {$optPkgName && $pkgName ne {}} { puts "#define ${pkgName}_${n} $v" } else { puts "#define $n $v" } } } else { foreach {n v} $manifest { if {$optPkgName && $pkgName ne {}} { puts [list ${pkgName}_${n} $v] } else { puts [list $n $v] } } } ooxml/tools/archive.sh000755 000765 000024 00000005261 15221526101 015427 0ustar00alexstaff000000 000000 #!/bin/sh set -e if [ $# -lt 3 ]; then echo "usage: $0 PACKAGE_NAME PACKAGE_VERSION PKG_TCL_SOURCES" >&2 echo "intended to be called via 'make release' (or 'make archive')" >&2 exit 1 fi # CDPATH would make cd print the target directory unset CDPATH PACKAGE_NAME=$1 PACKAGE_VERSION=$2 # all remaining arguments are the Tcl source files, whether the caller # passed them as one quoted list or as individual words shift 2 PKG_TCL_SOURCES="$@" # ignore AppleDouble files # macOS 10.4 COPY_EXTENDED_ATTRIBUTES_DISABLE=1 export COPY_EXTENDED_ATTRIBUTES_DISABLE # macOS >= 10.5 COPYFILE_DISABLE=1 export COPYFILE_DISABLE rm -f uv/ooxml*.zip uv/ooxml*.tar.gz mkdir -p uv/${PACKAGE_NAME}${PACKAGE_VERSION} cp ${PKG_TCL_SOURCES} manifest.txt pkgIndex.tcl uv/${PACKAGE_NAME}${PACKAGE_VERSION} # xattr -r -d com.apple.provenance .: recursively (-r) deletes the extended attribute com.apple.provenance from the specified file or directory. com.apple.provenance: An extended attribute used by macOS (e.g., Finder or Gatekeeper) to track the origin of a file, such as downloaded sources. # tar --no-mac-metadata: Do not store or restore Mac extended metadata (e.g., resource forks, Finder info, and so forth). This metadata is stored in special “AppleDouble” files or as extended attributes. This option is useful when creating archives to be used on non-Mac platforms. # tar --disable-copyfile: This option is equivalent to setting the environment variable COPYFILE_DISABLE=1. It disables copying of extended attributes and resource forks by preventing the use of the copyfile() API. Use this when you want to avoid creation of ._* AppleDouble files or when those are not needed. # tar --no-xattrs: Do not store or restore extended file attributes (xattrs). These are often system or application metadata not relevant or supported on other systems. cd uv zip -x '.DS_Store' -x '*/.DS_Store' -qr ${PACKAGE_NAME}${PACKAGE_VERSION}.zip ${PACKAGE_NAME}${PACKAGE_VERSION} tar --no-xattrs --no-mac-metadata --disable-copyfile --exclude='.DS_Store' --exclude='*/.DS_Store' -czf ${PACKAGE_NAME}${PACKAGE_VERSION}.tar.gz ${PACKAGE_NAME}${PACKAGE_VERSION} rm -fr ${PACKAGE_NAME}${PACKAGE_VERSION} cp template-download.html download.html ex - download.html < text data ]]> ooxml/tools/gendoc.tcl000775 000765 000024 00000004222 15213015413 015413 0ustar00alexstaff000000 000000 #!/bin/sh #\ exec tclsh8.6 "$0" "$@" if {$argc < 1} { error "usage: $argv0 method ?prelist? ?postlist?" } namespace eval ooxml::docx { variable docgen 1 } source ../ooxml.tcl source ../ooxml-docx.tcl package require ooxml::docx lassign $argv method prelist postlist set docx [::ooxml::docx::docx new] if {![catch {eval $docx $method {*}$prelist -foo foo {*}$postlist} errMsg1]} { error "execution did not fail; no error message to parse" } if {![regexp {^.*===(.*)===(.*)$} $errMsg1 -> typename allowedOptions]} { error "could not parse the error message \"$errMsg1\"" } foreach allowedOption [split $allowedOptions |] { if {![catch {eval $docx $method {*}$prelist $allowedOption foo {*}$postlist} errMsg2]} { puts "$allowedOption string" continue } if {![regexp {^.*===(.*)===(.*)$} $errMsg2 -> typename allowedValues]} { if {[regexp {^.*expected a (.*)$} $errMsg2 -> expectedValue]} { puts "$allowedOption $expectedValue" continue } elseif {[regexp {^.*match the regular expression (.*)$} $errMsg2 -> expectedValue]} { puts "$allowedOption $expectedValue" continue } puts "$allowedOption could not parse the error message \"$errMsg2\"" continue } puts $allowedOption if {[regexp {expected is a key value pair} $errMsg2]} { foreach allowedValue [split $allowedValues |] { if {![catch {eval $docx $method {*}$prelist $allowedOption [list [list $allowedValue foo]] {*}$postlist} errMsg3]} { puts " $allowedValue string" continue } if {![regexp {^.*===(.*)===(.*)$} $errMsg3 -> keyType keyValues]} { puts "$allowedValue could not parse the error message \"$errMsg3\"" continue } puts " $allowedValue ($keyType)" foreach keyValue [split $keyValues |] { puts " $keyValue" } } } elseif {[regexp {expected one of} $errMsg2]} { foreach allowedValue [split $allowedValues |] { puts " $allowedValue" } } } ooxml/tools/pp.tcl000644 000765 000024 00000004045 15213015413 014571 0ustar00alexstaff000000 000000 # This tool unzips every zip archive into a directory and pretty # prints the XML files in this new directory hierarchy. If called # just with a zip archive (mainly meat for open office documents) the # directory to unpack the content is the base-name of the file name of # the archive. The second argument overwrites this default with an # directory name. If the directory exists, its content will be # removed! package require Tcl 9.0- package require tdom package require fileutil::traverse if {$argc < 1 || $argc > 2} { puts stderr "usage: $argv0 ??" } proc unzip {zipfile dir} { file mkdir $dir set base [file join [zipfs root] pp] set baselen [string length $base] zipfs mount $zipfile $base ::fileutil::traverse filesInZip $base filesInZip foreach file { set target [file join $dir [string range $file $baselen+1 end]] if {[file isdirectory $file]} { file mkdir $target continue } set in [open $file rb] set out [open $target wb] fcopy $in $out close $in close $out } zipfs unmount $base } proc pp {xmlfile} { if {[file isdirectory $xmlfile]} return set pathparts [file split $xmlfile] if {[lindex $pathparts end-1] eq "media" && [lindex $pathparts end-2] eq "word"} { return } if {[catch {set data [::tdom::xmlReadFile $xmlfile]} errMsg]} { puts "cannot parse $xmlfile as XML (perhaps a binary file?) - $errMsg" return } if {[catch {dom parse $data doc}]} { puts "$xmlfile failed to parse" return } set fd [open $xmlfile w+] $doc asXML -channel $fd close $fd } if {$argc == 1} { set file [lindex $argv 0] set basedir [file dirname $file] set name [file rootname [file tail $file]] set dir [file join $basedir $name] } else { set dir [lindex $argv 1] } if {[file exists $dir]} { file delete -force $dir } file mkdir $dir unzip $file $dir ::fileutil::traverse xmlfiles $dir xmlfiles foreach xmlfile { pp $xmlfile } ooxml/tools/languages/000755 000765 000024 00000000000 14764622263 015432 5ustar00alexstaff000000 000000 ooxml/tools/createTypeCode.tcl000775 000765 000024 00000002152 15221523476 017070 0ustar00alexstaff000000 000000 #!/bin/sh #\ exec tclsh "$0" "$@" # This script reads a simple xsd enumeration type definition from # stdin and generates a Tcl type check proc from it. # # It is intended to be called from emacs per shell-command-on-region # (M-|) with an xsd type definition as region. package require tdom set result "" set xml {} append xml [read stdin] append xml "" set doc [dom parse $xml] $doc selectNodesNamespaces {xsd http://www.w3.org/2001/XMLSchema} foreach simpleType [$doc selectNodes /xsd:umbrella/xsd:simpleType] { append result "proc ::ooxml::docx::lib::[$simpleType @name] {value} \{\n" append result " set values \{\n" foreach enumeration [$simpleType selectNodes xsd:restriction/xsd:enumeration] { append result " [$enumeration @value]\n" } append result " \}\n" append result " if {\$value in \$values} { return \$value } error \"unknown [$simpleType @name] value \\\"\$value\\\", expected one of\\ \[AllowedValues \$values\]\"\n" append result "\}\n" } puts $result ooxml/tools/mkversion.c000644 000765 000024 00000015774 14764622263 015663 0ustar00alexstaff000000 000000 /* ** This C program generates the "VERSION.h" header file from information ** extracted out of the "manifest", "manifest.uuid", and "VERSION" files. ** Call this program with three arguments: ** ** ./a.out manifest.uuid manifest VERSION ** ** Note that the manifest.uuid and manifest files are generated by Fossil. ** ** The output becomes the "VERSION.h" file. The output is a C-language ** header that contains #defines for various properties of the build: ** ** MANIFEST_UUID These values are text strings that ** MANIFEST_VERSION identify the Fossil check-in to which ** the source tree belongs. They do not ** take into account any uncommitted edits. ** ** FOSSIL_BUILD_HASH A hexadecimal string that is a strong hash ** of the MANIFEST_UUID together with the ** current time of the build. We normally want ** this to be different on each build, as the ** value is used to expire ETag: fields in ** HTTP requests. But if you need to do ** repeatable byte-for-byte identical builds, ** add the -DFOSSIL_BUILD_EPOCH=n option. ** ** MANIFEST_DATE The date/time of the source-code check-in ** MANIFEST_YEAR in various formats. ** MANIFEST_NUMERIC_DATE ** MANIFEST_NUMERIC_TIME ** ** RELEASE_VERSION The version number (from the VERSION source ** RELEASE_VERSION_NUMBER file) in various format. ** RELEASE_RESOURCE_VERSION ** ** New #defines may be added in the future. */ #include #include #include #include #include #if defined(_MSC_VER) && (_MSC_VER < 1800) /* MSVS 2013 */ # define strtoll _strtoi64 #endif static FILE *open_for_reading(const char *zFilename){ FILE *f = fopen(zFilename, "r"); if( f==0 ){ fprintf(stderr, "cannot open \"%s\" for reading\n", zFilename); exit(1); } return f; } /* ** Given an arbitrary-length input string key zIn, generate ** an N-byte hexadecimal hash of that string into zOut. */ static void hash(const char *zIn, int N, char *zOut){ unsigned char i, j, t; int m, n; unsigned char s[256]; fprintf(stderr, "zIn len %d\n", strlen(zIn)); for(m=0; m<256; m++){ s[m] = m; } for(j=0, m=n=0; m<256; m++, n++){ fprintf(stderr, "j %d n %d m %d t %d s[m] %d zIn[n] %d\n", j, n, m, t, s[m], zIn[n]); j += s[m] + zIn[n]; if( zIn[n]==0 ){ n = -1; } t = s[j]; s[j] = s[m]; s[m] = t; } fprintf(stderr, "++\n"); i = j = 0; for(n=0; n>4)&0xf]; zOut[n+1] = "0123456789abcdef"[t&0xf]; } fprintf(stderr, "++\n"); zOut[n] = 0; } int main(int argc, char *argv[]){ FILE *m,*u,*v; char *z; #if defined(__DMC__) /* e.g. 0x857 */ int i = 0; #endif int j = 0, x = 0, d = 0; size_t n; int vn[3]; char b[1000]; char vx[1000]; if( argc!=4 ){ fprintf(stderr, "Usage: %s manifest.uuid manifest VERSION\n", argv[0]); exit(1); } memset(b,0,sizeof(b)); memset(vx,0,sizeof(vx)); u = open_for_reading(argv[1]); if( fgets(b, sizeof(b)-1,u)==0 ){ fprintf(stderr, "malformed manifest.uuid file: %s\n", argv[1]); exit(1); } fclose(u); for(z=b; z[0] && z[0]!='\r' && z[0]!='\n'; z++){} *z = 0; printf("#define MANIFEST_UUID \"%s\"\n",b); printf("#define MANIFEST_VERSION \"[%10.10s]\"\n",b); n = strlen(b); fprintf(stderr, "n %d\n", n); if( n + 50 < sizeof(b) ){ #ifdef FOSSIL_BUILD_EPOCH fprintf(stderr, "FOSSIL_BUILD_EPOCH\n"); #define str(s) #s snprintf(b+n, sizeof(b)-n, "%d", (int)strtoll(str(FOSSIL_BUILD_EPOCH), 0, 10)); #else fprintf(stderr, "!FOSSIL_BUILD_EPOCH\n"); const char *zEpoch = getenv("SOURCE_DATE_EPOCH"); if( zEpoch && isdigit(zEpoch[0]) ){ fprintf(stderr, "a %d\n", (int)strtoll(zEpoch, 0, 10)); snprintf(b+n, sizeof(b)-n, "%d", (int)strtoll(zEpoch, 0, 10)); }else{ fprintf(stderr, "b %d\n", (int)time(0)); snprintf(b+n, sizeof(b)-n, "%d", (int)time(0)); } #endif hash(b,33,vx); printf("#define FOSSIL_BUILD_HASH \"%s\"\n", vx); } m = open_for_reading(argv[2]); while(b == fgets(b, sizeof(b)-1,m)){ if(0 == strncmp("D ",b,2)){ int k, n; char zDateNum[30]; printf("#define MANIFEST_DATE \"%.10s %.8s\"\n",b+2,b+13); printf("#define MANIFEST_YEAR \"%.4s\"\n",b+2); n = 0; for(k=0; k<10; k++){ if( isdigit(b[k+2]) ) zDateNum[n++] = b[k+2]; } zDateNum[n] = 0; printf("#define MANIFEST_NUMERIC_DATE %s\n", zDateNum); n = 0; for(k=0; k<8; k++){ if( isdigit(b[k+13]) ) zDateNum[n++] = b[k+13]; } zDateNum[n] = 0; for(k=0; zDateNum[k]=='0'; k++){} printf("#define MANIFEST_NUMERIC_TIME %s\n", zDateNum+k); } } fclose(m); v = open_for_reading(argv[3]); if( fgets(b, sizeof(b)-1,v)==0 ){ fprintf(stderr, "malformed VERSION file: %s\n", argv[3]); exit(1); } fclose(v); for(z=b; z[0] && z[0]!='\r' && z[0]!='\n'; z++){} *z = 0; printf("#define RELEASE_VERSION \"%s\"\n", b); z=b; vn[0] = vn[1] = vn[2] = 0; while(1){ if( z[0]>='0' && z[0]<='9' ){ x = x*10 + z[0] - '0'; }else{ if( j<3 ) vn[j++] = x; x = 0; if( z[0]==0 ) break; } z++; } for(z=vx; z[0]=='0'; z++){} printf("#define RELEASE_VERSION_NUMBER %d%02d%02d\n", vn[0], vn[1], vn[2]); memset(vx,0,sizeof(vx)); strcpy(vx,b); for(z=vx; z[0]; z++){ if( z[0]=='-' ){ z[0] = 0; break; } if( z[0]!='.' ) continue; if ( d<3 ){ z[0] = ','; d++; }else{ z[0] = '\0'; break; } } printf("#define RELEASE_RESOURCE_VERSION %s", vx); while( d<3 ){ printf(",0"); d++; } printf("\n"); #if defined(__DMC__) /* e.g. 0x857 */ d = (__DMC__ & 0xF00) >> 8; /* major */ x = (__DMC__ & 0x0F0) >> 4; /* minor */ i = (__DMC__ & 0x00F); /* revision */ printf("#define COMPILER_VERSION \"%d.%d.%d\"\n", d, x, i); #elif defined(__POCC__) /* e.g. 700 */ d = (__POCC__ / 100); /* major */ x = (__POCC__ % 100); /* minor */ printf("#define COMPILER_VERSION \"%d.%02d\"\n", d, x); #elif defined(_MSC_VER) /* e.g. 1800 */ /* _MSC_FULL_VER also defined, e.g. 193030709 */ d = (_MSC_VER / 100); /* major */ x = (_MSC_VER % 100); /* minor */ printf("#define COMPILER_VERSION \"%d.%02d.", d, x); printf("%05d\"\n",(int)(_MSC_FULL_VER % 100000)); /* build (patch) */ #endif return 0; } ooxml/tools/xmltotdom.tcl000755 000765 000024 00000007612 14764622263 016230 0ustar00alexstaff000000 000000 #!/bin/sh #\ exec tclsh8.6 "$0" "$@" # # xmltotdom.tcl # read xml file and build a source code to generate the original xml file # # Copyright (C) 2018 Alexander Schoepe, Bochum, 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 tdom 0.9.1- set file [lindex $argv 0] if {[catch {open $file r} fd]} { puts stderr "open: $fd" return } fconfigure $fd -encoding utf-8 if {[catch {dom parse -keepCDATA [read $fd]} doc]} { puts stderr "dom parse: $doc" return } proc Parse { node {level 0} } { set indent [string repeat { } [expr {2 * $level}]] if {$level == 0} { set cn \$root puts "package require tdom 0.9.0-" puts "set encoding utf-8" puts "set doc \[dom createDocument [list [$node nodeName]]\]" puts "set root \[\$doc documentElement\]" } else { if {$level == 1} { set pn \$root } else { set pn \$node[expr {$level - 2}] } set cn \$node[expr {$level - 1}] switch -- [$node nodeType] { ELEMENT_NODE { puts "[string range $indent 0 end-2]$pn appendChild \[set [string range $cn 1 end] \[\$doc createElement [list [$node nodeName]]\]\]" } TEXT_NODE { puts "[string range $indent 0 end-2]$pn appendChild \[\$doc createTextNode [list [$node nodeValue]]\]" } CDATA_SECTION_NODE { puts "[string range $indent 0 end-2]$pn appendChild \[\$doc createCDATASection [list [$node nodeValue]]\]" } COMMENT_NODE { puts "[string range $indent 0 end-2]$pn appendChild \[\$doc createComment [list [$node nodeValue]]\]" } PROCESSING_INSTRUCTION_NODE { puts "[string range $indent 0 end-2]$pn appendChild \[\$doc createProcessingInstruction [$node nodeName] [list [$node nodeValue]]\]" } } } foreach attr [$node attributes] { set attr0 [lindex $attr 0] set attr1 [lindex $attr 1] if {$attr0 ne {} && $attr1 ne {}} { if {$attr0 eq $attr1} { set attr xmlns:$attr0 } else { set attr $attr1:$attr0 } } else { set attr $attr0 } puts "$indent$cn setAttribute $attr [list [$node getAttribute $attr]]" } if {[$node hasChildNodes]} { foreach child [$node childNodes] { Parse $child [expr {$level + 1}] } } if {$level == 0} { puts "fconfigure stdout -encoding \$encoding" puts "puts \[$cn asXML -indent 2 -xmlDeclaration 1 -encString \[string toupper \$encoding\]\]" } } set root [$doc documentElement] Parse $root $doc delete ooxml/tools/re.tcl000644 000765 000024 00000022766 14771326136 014611 0ustar00alexstaff000000 000000 # alte re: # {^(\d+)\.(\d+)\.(\d+)T?\s*(\d+)?:?(\d+)?:?(\d+)?\.?(\d+)?\s*([+-])?(\d+)?:?(\d+)?$} $scan all d m y H M S F x a b # {^(\d+)-(\d+)-(\d+)T?\s*(\d+)?:?(\d+)?:?(\d+)?\.?(\d+)?\s*([+-])?(\d+)?:?(\d+)?$} $scan all y m d H M S F x a b # {^(\d+)-(\w+)-(\d+)T?\s*(\d+)?:?(\d+)?:?(\d+)?\.?(\d+)?\s*([+-])?(\d+)?:?(\d+)?$} $scan all d ml y H M S F x a b # {^(\d+)/(\d+)/(\d+)T?\s*(\d+)?:?(\d+)?:?(\d+)?\.?(\d+)?\s*([+-])?(\d+)?:?(\d+)?$} $scan all m d y H M S F x a b set strings { {2025-03-27} {date only} {2025-03-27-10} {too many separators} {2025-03-27T14:05:30} {with time (T)} {2025-03-27 14:05:30} {with time (space)} {2025-03-27T14:05:30.789} {with milliseconds (T)} {2025-03-27 14:05:30.789} {with milliseconds (space)} {2025-03-27T14:05:30Z} {with UTC timezone (T)} {2025-03-27 14:05:30Z} {with UTC timezone (space)} {2025-03-27T14:05:30.789Z} {with milliseconds and UTC (T)} {2025-03-27 14:05:30.789Z} {with milliseconds and UTC (space)} {2025-03-27T14:05:30+02:15} {with positive timezone (T)} {2025-03-27 14:05:30+02:15} {with positive timezone (space)} {2025-03-27T14:05:30-02:15} {with negative timezone (T)} {2025-03-27 14:05:30-02:15} {with negative timezone (space)} {2025-03-27T14:05:30.789+02:15} {with milliseconds & timezone (T)} {2025-03-27 14:05:30.789+02:15} {with milliseconds & timezone (space)} {2025-3-27T14:05} {month not two-digit} {2025-03-27T14:5:30} {minute not two-digit} {2025-03-27T14:05:30.} {dot without fractional part} {2025-03-27T14:05:30+2:15} {hour part of timezone not two-digit} {2025-03-27T14:05:30+0215} {timezone without colon} {2025-03-27 14:05} {seconds missing} {2025-03-27 14:05:} {colon and seconds missing} {2025-03-27T14:05:30Z+02:15} {two timezone specifications simultaneously} {2025-03-27T} {only "T" without time} {2025-03-27 14} {incomplete time specification} {2025-03-27T14:05:30-} {only minus without timezone} {27.03.2025} {date only} {27.03.2025.10} {too many separators} {27.03.2025T14:05:30} {with time (T)} {27.03.2025 14:05:30} {with time (space)} {27.03.2025T14:05:30.789} {with milliseconds (T)} {27.03.2025 14:05:30.789} {with milliseconds (space)} {27.03.2025T14:05:30Z} {with UTC timezone (T)} {27.03.2025 14:05:30Z} {with UTC timezone (space)} {27.03.2025T14:05:30.789Z} {with milliseconds and UTC (T)} {27.03.2025 14:05:30.789Z} {with milliseconds and UTC (space)} {27.03.2025T14:05:30+02:15} {with positive timezone (T)} {27.03.2025 14:05:30+02:15} {with positive timezone (space)} {27.03.2025T14:05:30-02:15} {with negative timezone (T)} {27.03.2025 14:05:30-02:15} {with negative timezone (space)} {27.03.2025T14:05:30.789+02:15} {with milliseconds & timezone (T)} {27.03.2025 14:05:30.789+02:15} {with milliseconds & timezone (space)} {27.3.2025 14:05:30} {month not two-digit} {27.03.2025T14:5:30} {minute not two-digit} {27.03.2025T14:05:30.} {dot without fractional part} {27.03.2025T14:05:30+2:15} {hour part of timezone not two-digit} {27.03.2025T14:05:30+0215} {timezone without colon} {27.03.2025 14:05:} {seconds missing} {27.03.2025T14:05:30Z+02:15} {two timezone specifications simultaneously} {27.03.2025T} {only "T" without time} {27.03.2025 14} {incomplete time specification} {27.03.2025T14:05:30-} {only minus without timezone} {27-mar-2025} {date only} {27-mar-2025-10} {too many separators} {27-mar-2025T14:05:30} {with time (T)} {27-mar-2025 14:05:30} {with time (space)} {27-mar-2025T14:05:30.789} {with milliseconds (T)} {27-mar-2025 14:05:30.789} {with milliseconds (space)} {27-mar-2025T14:05:30Z} {with UTC timezone (T)} {27-mar-2025 14:05:30Z} {with UTC timezone (space)} {27-mar-2025T14:05:30.789Z} {with milliseconds and UTC (T)} {27-mar-2025 14:05:30.789Z} {with milliseconds and UTC (space)} {27-mar-2025T14:05:30+02:15} {with positive timezone (T)} {27-mar-2025 14:05:30+02:15} {with positive timezone (space)} {27-mar-2025T14:05:30-02:15} {with negative timezone (T)} {27-mar-2025 14:05:30-02:15} {with negative timezone (space)} {27-mar-2025T14:05:30.789+02:15} {with milliseconds & timezone (T)} {27-mar-2025 14:05:30.789+02:15} {with milliseconds & timezone (space)} {27-mar-2025T14:5:30} {minute not two-digit} {27-mar-2025T14:05:30.} {dot without fractional part} {27-mar-2025T14:05:30+2:15} {hour part of timezone not two-digit} {27-mar-2025T14:05:30+0215} {timezone without colon} {27-mar-2025 14:05:} {seconds missing} {27-mar-2025T14:05:30Z+02:15} {two timezone specifications simultaneously} {27-mar-2025T} {only "T" without time} {27-mar-2025 14} {incomplete time specification} {27-mar-2025T14:05:30-} {only minus without timezone} {03/27/2025} {date only} {03/27/2025/10} {too many separators} {03/27/2025T14:05:30} {with time (T)} {03/27/2025 14:05:30} {with time (space)} {03/27/2025T14:05:30.789} {with milliseconds (T)} {03/27/2025 14:05:30.789} {with milliseconds (space)} {03/27/2025T14:05:30Z} {with UTC timezone (T)} {03/27/2025 14:05:30Z} {with UTC timezone (space)} {03/27/2025T14:05:30.789Z} {with milliseconds and UTC (T)} {03/27/2025 14:05:30.789Z} {with milliseconds and UTC (space)} {03/27/2025T14:05:30+02:15} {with positive timezone (T)} {03/27/2025 14:05:30+02:15} {with positive timezone (space)} {03/27/2025T14:05:30-02:15} {with negative timezone (T)} {03/27/2025 14:05:30-02:15} {with negative timezone (space)} {03/27/2025T14:05:30.789+02:15} {with milliseconds & timezone (T)} {03/27/2025 14:05:30.789+02:15} {with milliseconds & timezone (space)} {3/27/2025T14:05:30} {month not two-digit} {03/27/2025T14:5:30} {minute not two-digit} {03/27/2025T14:05:30.} {dot without fractional part} {03/27/2025T14:05:30+2:15} {hour part of timezone not two-digit} {03/27/2025T14:05:30+0215} {timezone without colon} {03/27/2025 14:05:} {seconds missing} {03/27/2025T14:05:30Z+02:15} {two timezone specifications simultaneously} {03/27/2025T} {only "T" without time} {03/27/2025 14} {incomplete time specification} {03/27/2025T14:05:30-} {only minus without timezone} } set re {^(\d{2,4})-(\d{2})-(\d{2})(?:[ T]|$)(?:(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?(?:([+-])(\d{2}):(\d{2})|(Z)$)?)?)?$} puts $re foreach {toScan comment} $strings { if {[regexp $re $toScan all y m d H M S F x a b z]} { puts [format "%-32s %-46s 1-all %-30s %-4s %-2s %-2s %-2s %-2s %-2s %-3s %-1s %-2s %-2s %s" $toScan $comment $all $y $m $d $H $M $S $F $x $a $b $z] } else { puts [format "%-32s %-46s 1-FAILED" $toScan $comment] } } set re {^(\d{1,2})\.(\d{1,2})\.(\d{2,4})(?:[ T]|$)(?:(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?(?:([+-])(\d{1,2}):(\d{1,2})|(Z))?)?)?$} puts $re foreach {toScan comment} $strings { if {[regexp $re $toScan all d m y H M S F x a b z]} { puts [format "%-32s %-46s 2-all %-30s %-4s %-2s %-2s %-2s %-2s %-2s %-3s %-1s %-2s %-2s %s" $toScan $comment $all $y $m $d $H $M $S $F $x $a $b $z] } else { puts [format "%-32s %-46s 2-FAILED" $toScan $comment] } } set re {^(\d{1,2})-(\w+)-(\d{2,4})(?:[ T]|$)(?:(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?(?:([+-])(\d{1,2}):(\d{1,2})|(Z))?)?)?$} puts $re foreach {toScan comment} $strings { if {[regexp $re $toScan all d m y H M S F x a b z]} { puts [format "%-32s %-46s 3-all %-30s %-4s %-2s %-2s %-2s %-2s %-2s %-3s %-1s %-2s %-2s %s" $toScan $comment $all $y $m $d $H $M $S $F $x $a $b $z] } else { puts [format "%-32s %-46s 3-FAILED" $toScan $comment] } } set re {^(\d{1,2})/(\d{1,2})/(\d{2,4})(?:[ T]|$)(?:(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?(?:([+-])(\d{1,2}):(\d{1,2})|(Z))?)?)?$} puts $re foreach {toScan comment} $strings { if {[regexp $re $toScan all m d y H M S F x a b z]} { puts [format "%-32s %-46s 4-all %-30s %-4s %-2s %-2s %-2s %-2s %-2s %-3s %-1s %-2s %-2s %s" $toScan $comment $all $y $m $d $H $M $S $F $x $a $b $z] } else { puts [format "%-32s %-46s 4-FAILED" $toScan $comment] } } ooxml/tools/xmltotdomnodecmd.tcl000755 000765 000024 00000011242 14764622263 017554 0ustar00alexstaff000000 000000 #!/bin/sh #\ exec tclsh8.6 "$0" "$@" # # xmltotdomnodecmd.tcl # read xml file and build a source code to generate the original xml file # # Copyright (C) 2018 Alexander Schoepe, Bochum, 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 tdom 0.9.1- set file [lindex $argv 0] set cmds {} if {[catch {open $file r} fd]} { puts stderr "open: $fd" return } fconfigure $fd -encoding utf-8 if {[catch {dom parse -keepCDATA [read $fd]} doc]} { puts stderr "dom parse: $doc" return } proc Preparse { node {level 0} } { global cmds if {$level != 0} { switch -- [$node nodeType] { ELEMENT_NODE { set name [$node nodeName] } TEXT_NODE { set name @textNode } CDATA_SECTION_NODE { set name @cdataNode } COMMENT_NODE { set name @commentNode } PROCESSING_INSTRUCTION_NODE { set name @piNode } } if {$name ni $cmds} { lappend cmds $name } } if {[$node hasChildNodes]} { foreach child [$node childNodes] { Preparse $child [expr {$level + 1}] } } } proc Parse { node {level 0} } { global cmds set brace 0 set indent [string repeat { } [expr {2 * $level}]] set attributes {} foreach attr [$node attributes] { set attr0 [lindex $attr 0] set attr1 [lindex $attr 1] if {$attr0 ne {} && $attr1 ne {}} { if {$attr0 eq $attr1} { set attr xmlns:$attr0 } else { set attr $attr1:$attr0 } } else { set attr $attr0 } lappend attributes $attr [$node getAttribute $attr] } if {$level == 0} { puts "set root \[\$doc documentElement\]" foreach {n v} $attributes { puts "\$root setAttribute [list $n] [list $v]" } puts "\$root appendFromScript \{" } else { switch -- [$node nodeType] { ELEMENT_NODE { set cmd "Tag_[$node nodeName] $attributes" puts "${indent}[string trim $cmd] \{" set brace 1 } TEXT_NODE { puts "${indent}Text [$node nodeValue]" } CDATA_SECTION_NODE { puts "${indent}CData [list [$node nodeValue]]" } COMMENT_NODE { puts "${indent}Comment [list [$node nodeValue]]" } PROCESSING_INSTRUCTION_NODE { puts "${indent}PInstr [$node nodeName] [list [$node nodeValue]]" } } } if {[$node hasChildNodes]} { foreach child [$node childNodes] { Parse $child [expr {$level + 1}] } } if {$brace} { puts "${indent}\}" } if {$level == 0} { puts "\}" } } set root [$doc documentElement] puts "package require tdom 0.9.0-" puts "set encoding utf-8" Preparse $root foreach cmd [lsort $cmds] { switch -- $cmd { @textNode { puts "dom createNodeCmd textNode Text" } @cdataNode { puts "dom createNodeCmd cdataNode CData" } @commentNode { puts "dom createNodeCmd commentNode Comment" } @piNode { puts "dom createNodeCmd piNode PInstr" } default { puts "dom createNodeCmd -tagName $cmd elementNode Tag_$cmd" } } } puts "set doc \[dom createDocument [$root nodeName]\]" Parse $root puts "fconfigure stdout -encoding \$encoding" puts "puts \[\$root asXML -indent 2 -xmlDeclaration 1 -encString \[string toupper \$encoding\]\]" $doc delete ooxml/tools/getlanguageinfo.tcl000644 000765 000024 00000003766 14764622263 017343 0ustar00alexstaff000000 000000 #!/bin/sh #\ exec tclsh8.6 "$0" "$@" package require vfs::zip package require tdom 0.9.0- proc UnicodeCharsToHex { txt } { set new {} foreach {a b c d} [split [binary encode hex [encoding convertto unicode $txt]] {}] { if {[expr 0x${c}${d}${a}${b}] <= 0x7f} { append new [binary decode hex ${c}${d}${a}${b}] } else { append new \\u $c $d $a $b } } return [string map {\0 {}} $new] } foreach file [glob -directory languages *.xlsx] { set lang [lindex [split $file -.] 2] set files($lang) $file } set maptable {} foreach lang [lsort [array names files]] { set file $files($lang) set mnt [vfs::zip::Mount $file xlsx] set name [lindex [split [UnicodeCharsToHex $file] -.] 0] set translation [string trim [file tail $name] 1] if {[regexp -all {\s+} $translation]} { set translation \"$translation\" } puts "msgcat::mcset $lang [string trim Book1 1] $translation" if {![catch {open xlsx/docProps/app.xml r} fd]} { fconfigure $fd -encoding utf-8 if {![catch {dom parse [read $fd]} doc]} { set root [$doc documentElement] set idx -1 foreach node [$root selectNodes -namespaces [list X [$root namespaceURI] vt http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes] {/X:Properties/X:HeadingPairs/vt:vector/vt:variant/vt:lpstr/text()}] { set translation [UnicodeCharsToHex [$node nodeValue]] if {[regexp -all {\s+} $translation]} { set translation \"$translation\" } puts "msgcat::mcset $lang Worksheets $translation" } foreach node [$root selectNodes -namespaces [list X [$root namespaceURI] vt http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes] {/X:Properties/X:TitlesOfParts/vt:vector/vt:lpstr/text()}] { set translation [string trim [UnicodeCharsToHex [$node nodeValue]] 1] if {[regexp -all {\s+} $translation]} { set translation \"$translation\" } puts "msgcat::mcset $lang [string trim Sheet1 1] $translation" } $doc delete } close $fd } vfs::zip::Unmount $mnt xlsx } ooxml/tools/BUILD-PACKAGE.md000644 000765 000024 00000006223 15221526153 015667 0ustar00alexstaff000000 000000 # Building the Download Packages How to create the download packages for a new release and publish them as unversioned files (uv) in the Fossil repository. Starting point: the new version has been checked in and tagged (e.g. `version-1.11`). The version number itself is maintained in one place only: `AC_INIT([ooxml],[x.y])` in `configure.ac`. ## Prerequisites * A Fossil checkout of the release check-in: fossil update version-1.11 * The Fossil setting `manifest` must be enabled, so that the files `manifest` and `manifest.uuid` exist in the checkout and are kept up to date on every update: fossil settings manifest on * A configured build directory (`./configure` has been run at least once), `tclsh`, `autoconf`, `zip` and `tar` in the PATH. ## 1. Build the packages make release That is all. The target resolves its prerequisites automatically: * `configure`, `Makefile` and `pkgIndex.tcl` are regenerated if `configure.ac` or their templates changed (so a version bump in `configure.ac` propagates without a manual `./configure` run), * `manifest.txt` — the version and build information (check-in UUID, check-in date, release version) — is regenerated from `manifest`, `manifest.uuid` and `configure.ac` by `tools/mkversion.tcl`, * `tools/archive.sh` then creates the artifacts in `uv/`: | File | Content | |-------------------------|------------------------------------------------------| | `ooxml.zip` | Installable package: Tcl sources, `pkgIndex.tcl`, `manifest.txt` | | `ooxml.tar.gz` | Same content as the zip | | `ooxml-src.tar.gz` | Complete source tree (without build artifacts) | | `download.html` | Download page, generated from `template-download.html` | The archives are created without macOS metadata (AppleDouble files, extended attributes, `.DS_Store`). Check the result before publishing, e.g.: unzip -l uv/ooxml.zip tar tzf uv/ooxml.tar.gz ## 2. Publish as Fossil unversioned files make publish This uploads the four artifacts into the uv space of the repository (`fossil uv add ...`), syncs them to the server (`fossil uv sync`) and shows the resulting file list (`fossil uv list`). The packages are then available for download at . ## Notes * `make archive` still exists as the bare packaging step; `make release` is `archive` plus the dependency chain and a summary. * `tools/archive.sh` is not meant to be called directly; it expects `PACKAGE_NAME PACKAGE_VERSION PKG_TCL_SOURCES...` as arguments and exits with a usage message otherwise. ## Troubleshooting * **`can't open file manifest.uuid`** (from `mkversion.tcl`) — the Fossil `manifest` setting is off; enable it as described under Prerequisites. * **`make: *** No rule to make target 'release'`** — the `Makefile` in the build directory predates this target; run `./configure` once to regenerate it. * **Wrong version in the archive names** — the checkout is not on the release check-in (`fossil status`), or `configure.ac` does not carry the new version yet. ooxml/tools/languages/PaxHeader/Classeur1-französisch-fr.xlsx000644 000765 000024 00000000132 14764622263 025527 xustar00alexstaff000000 000000 61 path=ooxml/tools/languages/Classeur1-französisch-fr.xlsx 29 mtime=1741890739.24794708 ooxml/tools/languages/Classeur1-französisch-fr.xlsx000644 000765 000024 00000017257 14764622263 023576 0ustar00alexstaff000000 000000 PK!SN[Content_Types].xml (N0EHC-ݲ@5(`Ib/y=@j7bs=36kؘXJbSxfVK)< uV"4>Z7"z)[уKRz 6@#W&9`ϻU1ѵLTE)N9;l01HO>4Q+(2wiɆ%?-27AzeCHr+;>(2~YD[2geϢԯyir#~> $1i8PD R"PK!U0#L _rels/.rels (MO0 HݐBKwAH!T~I$ݿ'TG~ m $ EՒ1/ ( ֕"`WD PjGєB!,{0l+ +L@h|_h|\)ܱҖBV˛N5>I7Хz!B7|y8(\ixd'ɢ)‡md ahOWWWҸ#Χ/V:A.jvhBEfjGbZǯxŚ[qӘJ[*1)D8|DFΡk\Ih G[%;Gh1Dd0/|<&Nfj[m_DSx!\9!A~%<|DY*PK!!3 xl/styles.xmlT[k0~?8K451h{Ul9HJlȗĥcuwsSzJ\ G!FLjE:**b>2R뎂s ޹fE-LR{OT#1V_a8'r{,DRxhRˆ:傻c,W; F3Z6xЙ^4](uK, -H:(!a'V΢R'zT*/o@OT%$OK-A Fޢd5|k7Trqݽ?P-E @4Yt kүݽzZP},5`/Zx J>4;=[^j_"J5t)Uծ Ff LylXeb)bt"IO.fxF]D'Fx30åJiP 7Q!Kڐ#Nf_yOͭUYr(r/o?J>&O?x=?|I,:$"@Cu_Fpo or`e~8fp1a+j.y2uO&:BG(ܟπ^Ke7–(J$KO1v!_wɈ3&һE"N ɁH6!. j77U𑍄m!/DKt)돱.k 0;tH.ɡKbDa7Bi3I"8E5&]]f q@p$ iR 9wf~\ .ib6'̧Vj`L1caA,F_U+.#;Wst]N;DX)l=ij@I&{u+usRU::4{?S a$wk.,V^gdoZ 3DP`D"\bs޴y0Ꝙ$,~N=S S(x܊ߥD)' M`YCdΪW5Y-sV˜2R T6yG|- t_.(#fVqJj79%2H7VkD2H7# #xβlfyH-+!7xV$rhb2M_p2B?1|g;Bu!:{fq!{HD5lGIW@!ڶr5 A' ZJ!;s~Ar8( [Y'vͫ(C8e'I)\ƒ:`}Q`ַ6s[naL-S0JP MpQE:Au,F! =̟[_ZX JV.H J/`M8scZVNuڬ9_Wh+ّV%Ѷ(Yjz7Iv_hiYWkVo5034q1+uI42$bLI,W5a?ZPK! ?V<YdocProps/core.xml (N0HC{-(Tqmj;mH8? A;ήmXѨ%QPBU9z)anm뫌iO`xc CyqI k>hxǷX:;`'"MHi$(gq%HgC̜R;qlqrmF'mܯ ݊*23@]ci\==>bCE"N0NdUkr 68?zF< _|PK!nF#docProps/app.xml (n0 n(@V1+zXI{ge:&Kɞ~NSo$'Jzc.R.l\ؗiwML*1`)OIoR0,"R6DJll!/X1@u,E{h1.GPau՝ 飦U_~ޝ:6{ygsI[ooxml/tools/languages/Bok1-schwedisch-sv.xlsx000644 000765 000024 00000017250 14764622263 021723 0ustar00alexstaff000000 000000 PK!SN[Content_Types].xml (N0EHC-ݲ@5(`Ib/y=@j7bs=36kؘXJbSxfVK)< uV"4>Z7"z)[уKRz 6@#W&9`ϻU1ѵLTE)N9;l01HO>4Q+(2wiɆ%?-27AzeCHr+;>(2~YD[2geϢԯyir#~> $1i8PD R"PK!U0#L _rels/.rels (MO0 HݐBKwAH!T~I$ݿ'TG~;+fYRM}ms=\;} 2L|bouTTj3-߿KڜZ(ʹ&!IJNtAh6VZgB!1oe)h\pIo+fo9tAH{PjJz@#2Lkt"CW|@9OK! ;M]m x9[0mj&wt{0a2@V:nu| zJ;ily _zwU52yݴڿ-CIOy5gK.D' }p,F<ԟAx7D ?zYűr<ŮW·LTJ"]])F&01;Xƿ ,\SV5\N>Y0"߂ȿ؋[D[GpϷ*;\OG+ e'xZy:~uӱj2PK!!3 xl/styles.xmlT[k0~?8K451h{Ul9HJlȗĥcuwsSzJ\ G!FLjE:**b>2R뎂s ޹fE-LR{OT#1V_a8'r{,DRxhRˆ:傻c,W; F3Z6xЙ^4](uK, -H:(!a'V΢R'zT*/o@OT%$OK-A Fޢd5|k7Trqݽ?P-E9`5iAүT~_[4JS[lJ7Ȱ(ݫe o诮kP?X]נNӳkPv/[5($9\CZ\ 2at o^ɔ(ȆUv)&,r-Fw@)$b'hIEpi7C 0\*W@E[.D ){<1d&[Ϟ=ߞ?z/Z%)ǯ _xtxa_xzXq>yɋmLXxwŰ@Nb!bIt;Ted-u:vm,^ߵlݏ\W1F;;pUexx8OD5w%V+qF2EDS`!Ǝ!q&DzwA!9)!1e2BmfaԵ>-u?re4(vE2r#"=Ŕy1%sz_q}.b%9tE;F(9m&Idb?Ȼ !([~3r5MD2X^ޏ :A2m[ęJ]):Fc[9,谙+v%dzNk)r+emgoqx(ߤDJ]8TzM5)0IYgz|]p+~o`_=|j QkekZAj|&O3!ŻBw}ь0Q'j"5,ܔ#-q&?'2ڏ ZCeLTx3&cu'ЭNxNg x)\CJZ=ޭ~TwY(aLfQuQ_B^g^ٙXtXPꗡZFq 0mxEAAfc ΙFz3Pb/3 tSٺqyjuiE-#t00,;͖Yƺ2Obr3kE"'&&S;nj*#4kx#[SuInwaD:\N1{-_- 4m+W>Z@+qt;x2#iQNSp$½:7XX/+r1w`h׼9#:Pvd5O+Oٚ.<O7sig*t; CԲ*nN-rk.yJ}0-2MYNÊQ۴3, O6muF8='?ȝZu@,Jܼfw2_{]PK!4LZlxl/worksheets/sheet1.xmlMO0 H(-Bu1Mp@B|m%qx{V ]vsY~0eGL+*Bm&ZeX>`ַ6s[naL-S0JP MpQE:Au,F! =̟[_ZX JV.H J/`M8scZVNuڬ9_Wh+ّV%Ѷ(Yjz7Iv_hiYWkVo5034q1+uI42$bLI,W5a?ZPK!t<YdocProps/core.xml (_K0C{dRBہʞVBr4$nje{s/GUG_`]фhd9z)7q"繖n4L& O1`}. $09:xoN@q⮱{l{ Bn%wLD4"=@ 5(aP`WfNU ;ql)qr]5۶Me#mܯWTdR0a%8Y;^͝߆;*wsY> l}V^ BӘ1]0rÖn.PPWx 7PK!]ndocProps/app.xml (MO0דּPj l,;hï$KxCcbEބ}!v?ο,\Xg_&#YL[T]IL =w N^ykГ+B_by M`[m5@JhM )T=BNɹL1[\yy%TmƤUG %  $ AٔkEk^J`*\;W  ;KӯjA st9b:4-~l󴨶5D,>=/2d]c1\tzy/sYMϣֿPK-!SN[Content_Types].xmlPK-!U0#L _rels/.relsPK-!p-xl/_rels/workbook.xml.relsPK-!R;xl/workbook.xmlPK-!!3 4 xl/styles.xmlPK-!6 R  xl/theme/theme1.xmlPK-!4LZlxxl/worksheets/sheet1.xmlPK-!t<YdocProps/core.xmlPK-!]ndocProps/app.xmlPK >Tooxml/tools/languages/PaxHeader/Mappe1-dänisch-da.xlsx000644 000765 000024 00000000123 14764622263 024041 xustar00alexstaff000000 000000 54 path=ooxml/tools/languages/Mappe1-dänisch-da.xlsx 29 mtime=1741890739.24888121 ooxml/tools/languages/Mappe1-dänisch-da.xlsx000644 000765 000024 00000017253 14764622263 022104 0ustar00alexstaff000000 000000 PK!SN[Content_Types].xml (N0EHC-ݲ@5(`Ib/y=@j7bs=36kؘXJbSxfVK)< uV"4>Z7"z)[уKRz 6@#W&9`ϻU1ѵLTE)N9;l01HO>4Q+(2wiɆ%?-27AzeCHr+;>(2~YD[2geϢԯyir#~> $1i8PD R"PK!U0#L _rels/.rels (MO0 HݐBKwAH!T~I$ݿ'TG~|pD/k<Fؔ*Cn_ּ]c)Fv!abwm8Sm$Fh^[ >a'mRqOcAmo4 ` h2R뎂s ޹fE-LR{OT#1V_a8'r{,DRxhRˆ:傻c,W; F3Z6xЙ^4](uK, -H:(!a'V΢R'zT*/o@OT%$OK-A Fޢd5|k7Trqݽ?P-E4;=[^j_"J5t)Uծ Ff LyhXEb)bt"IO.fxF]D>'Fx30åJiP (ȐVXR|<1d&[Uϟ?zvǏͭUYr(r~WOI>&_שxӗϞ?zh߄IwyX ttKEۡ/# x} p2.=^8fp1aikj.y2uO&B(ܟ n-7)J$KO=c;Vwˮdę`%^Id \h ڲèk=|h#@A~e+h.QR9D15 d"#<=Ŕy1%sz _ v.]6Krҹ3=vЍPB{ccg6lAVƮXU uz! =h(ݓ\g\f & 7Hxω"4PY70"S=ތ aI't^ WХ)Vϻw+:]%%{d6D}9^x 3ath(KW-2P[y>=PoavX)m&/sdLjF=T\7.O. E7|giܥ=eېӨ7>U9hbf xG-V Pef-cg;B}u!:SL2)̸=$ZE b"1([Z*hsV@Bh5!|l鶓dGt1,BOswdsp^4>Bba 8&ʩ5NV,Svͣ(C8e;SN+:ne.[3t݄SJYHiek V&jJSyk.ssxîA-̢aQ%j#xםNF u|}bnj{`ַ6s[naL-S0JP MpQE:Au,F! =̟[_ZX JV.H J/`M8scZVNuڬ9_Wh+ّV%Ѷ(Yjz7Iv_hiYWkVo5034q1+uI42$bLI,W5a?ZPK!=YdocProps/core.xml (_K0C{dc=98| VlҐD}{?c9wϽ$]T}ue3D"Т>d+9ϵU!Cgphޤ0Q[xKpQ iDŽ{0v$8tU܇=`? œB{; wޗ σ8]2 AX gb颠[,۱`}A OcL@ϐPK!bdocProps/app.xml (n0 n(@VQzX`I{d:"Kɞ~κn$'عǔmX.JQ7~_ݷ/=벼x$5Wl(&UOkZ3)2Vw1:kњrhxc=_6Ŝ[4/IJS5p#t.o0o6ezZh("߼kQX%zH<16%cb#,O1wcY/. K%GD]yGv¹Kin|.y9n!?]U^ն5osA=L-=֯=;˛E?Ք|hPK-!SN[Content_Types].xmlPK-!U0#L _rels/.relsPK-!p-xl/_rels/workbook.xml.relsPK-!;HP:xl/workbook.xmlPK-!!3 3 xl/styles.xmlPK-!'#X  xl/theme/theme1.xmlPK-!4LZl}xl/worksheets/sheet1.xmlPK-!=YdocProps/core.xmlPK-!bdocProps/app.xmlPK >Wooxml/tools/languages/Book1-englisch-en.xlsx000644 000765 000024 00000017256 14764622263 021532 0ustar00alexstaff000000 000000 PK!SN[Content_Types].xml (N0EHC-ݲ@5(`Ib/y=@j7bs=36kؘXJbSxfVK)< uV"4>Z7"z)[уKRz 6@#W&9`ϻU1ѵLTE)N9;l01HO>4Q+(2wiɆ%?-27AzeCHr+;>(2~YD[2geϢԯyir#~> $1i8PD R"PK!U0#L _rels/.rels (MO0 HݐBKwAH!T~I$ݿ'TG~$aa0y3 o'c{cKp}x!J憦VrcK!*+X !|HR2q۷`<\ K}bbw\VjMY^*/-(F%m,+}WХ8!@+4 vE.xdG>9EaLz%x 9&l]-k`N0I_(9߁ =HO|pD/s<F0ٔꄶ6": XXn3"q88܄v$Fh^[ N`%?9. 24 n<x`*Zt,oqJ4eo˽ȗAwNЪ?PK!!3 xl/styles.xmlT[k0~?8K451h{Ul9HJlȗĥcuwsSzJ\ G!FLjE:**b>2R뎂s ޹fE-LR{OT#1V_a8'r{,DRxhRˆ:傻c,W; F3Z6xЙ^4](uK, -H:(!a'V΢R'zT*/o@OT%$OK-A Fޢd5|k7Trqݽ?P-E\Çfgנ_[K^PkPDIr.jwd A)Q RSLX"7Z2>R$I O(9%o&`T) JU>#02]`XRxbL+7 /={=_*Kn%SSՏ__7'Ŀ˗:/}}O!c&a?0BĒ@v^[ uXsXa3W"`J+U`ek)r+emgoqx(ߤDJ]8TzM5)0IYgz|]p+~o`_=|j QkekZAj|&O3!ŻBw}ь0Q'j"5,ܔ#-q&?'2ڏ ZCeLTx3&cu+ЭNxNg x)\CJZ=ޭ~TwY(aLfQuQ_B^g^ٙXtXPꗡZFq 0mxEAAfc ΙFz3Pb/3 tSٺqyjuiE-#t00,;͖Yƺ2Obr3kE"'&&S;nj*#4kx#[SvInwaD:\N1{-_- 4m+W>Z@+qt;x2#iQNSp$½:7XX/+r1w`h׼9#:Pvd5O+Oٚ.<O7sig*t; CԲ*nN-rk.yJ}0-2MYNÊQ۴3, O6muF8='?ȝZu@,Jܼfw+zLdrQ J<.?| .xIOjB*2ǕdZs i4}0ozWey+k/PL״fࣗ1f`ίO֤@ - :%29hޒ.jk: 8B%? aXl"z^h8쯼+Q=$ 3 1v8!RȤdL1k籽Qs`09βCl ?sap4s7>9O{wy^TN>cdrɺ]wc8vQ^_g5%?ZPK-!SN[Content_Types].xmlPK-!U0#L _rels/.relsPK-!p-xl/_rels/workbook.xml.relsPK-!TӸ;xl/workbook.xmlPK-!!3 4 xl/styles.xmlPK-!N  xl/theme/theme1.xmlPK-!&zwtxl/worksheets/sheet1.xmlPK-!=g <Y!docProps/core.xmlPK-!^YdocProps/app.xmlPK >Zooxml/tools/languages/PaxHeader/Munkafüzet1-ungarisch-hu.xlsx000644 000765 000024 00000000133 14764622263 025537 xustar00alexstaff000000 000000 61 path=ooxml/tools/languages/Munkafüzet1-ungarisch-hu.xlsx 30 mtime=1741890739.249032378 ooxml/tools/languages/Munkafüzet1-ungarisch-hu.xlsx000644 000765 000024 00000017272 14764622263 023602 0ustar00alexstaff000000 000000 PK!SN[Content_Types].xml (N0EHC-ݲ@5(`Ib/y=@j7bs=36kؘXJbSxfVK)< uV"4>Z7"z)[уKRz 6@#W&9`ϻU1ѵLTE)N9;l01HO>4Q+(2wiɆ%?-27AzeCHr+;>(2~YD[2geϢԯyir#~> $1i8PD R"PK!U0#L _rels/.rels (MO0 HݐBKwAH!T~I$ݿ'TG~xl/workbook.xmlT]o }xO1UfZm~<``/]s-/|=\X+MI5)g%+K݇ќ䠭)}g߭ 2zɘZ) `vNBK)CYESV2GX`آPB^YT҄I VUM=b O(%X^uH'2NO+%g"OqSV򡗝@]͢)&WA)ahԗҸ#Χe/V8ЄNxҞDR:Hg ȵ55aK[QNbSe+X@(ItJٽG, 76+ԿD˖!ݾ~'l6K6$Ger{HF< 8bx6Uʔ(yY(ծ ,ŶWLHLACT8q9@?h&Cwp/ahC3׸.d+QrgDhx2Jx4Oh\śls|]/-=>/]s:Qj6PK!1\ xl/styles.xmlj0{{WgI]B7`-'9{=^lGH\:Xұ|)l@XU#J]q"cdUZ ŗ7uGv9e3sn$Ė;&{OfK0ZYH HKYDRp{ - #Y.oJ DM43pCkzvVD5/s <2R0Z+gQAE/ ]yjG*c _#oQTn|c7Trqݹ5֢ojs֟"k .IiE!O! U$)(NFH{an>1Ly*X@۝w4iV+*+4wJ&ĝ/vS#ut7U|)8O;^1c)#ODG2O3Z5>wP5 g k>o}5B}gb}]<\̓%"YdzZEW?FFn9`5iAүT~_[4JS[lJ7Ȱ(ݫe o诮kP?X]נNӳkPv/[5($9\CZ\ 2at o^ɔ(ȆUv)&,r-F@)$b'hYEpi7C 0\*W@E[.D ){<1d&[egO<_>xZ%)/3_{txa~zXqg_?zѳoLJmLXx{ػbX~|Lb!bIt;Tedpl&q/o[G|.c+QlwƝ2<<'S|n#t䚻+ 蕸Tv#lyD)Nocnbu8l"[ tɐX mp|{0ZuH:bjKTQLM _ bʼ ᒹaFЯøþKt Ldv#Ϝ6$2CHQ]ceQl Mpn& ~sG,/af b6-vms̎|j1ލOtynXe2sU='X`O5Cx6س8A< ĈoҼQRN9'^CG|q:Fr7i!R nuo/A kf5A0CnA .U-6wMM #މID;e9ǭ]JM}ل5=4Oa8I9묪9j}Ui/2gY-zz/L^@ewyt'J>h(ݓ\g|Lnʑ8Ghn`NEz*1úO}yi\V]ԅ|ơK%StwVu?tKaLfQuQ_B^f^٩XtXPꗡZFq 0mxEAAfc ΩFz3Pb/3 tSٺqyjuiF-#t00,;͖iƺ2Obr3kE"'&&S;nj*#4kx#[SvInaD:\N1{-_- 4m+W>X@+qt;x2#iQNSp$½:XX/+r1w`h׼9#:Pvd5O+Oٚ.<OWsig*t; CԲ*nN-rk.yJ}0-2MYNÊQ۴S, O6muF8='?ȝZu@,Jܼf2_{]PK!4LZlxl/worksheets/sheet1.xmlMO0 H(-Bu1Mp@B|m%qx{V ]vsY~0eGL+*Bm&ZeX>`ַ6s[naL-S0JP MpQE:Au,F! =̟[_ZX JV.H J/`M8scZVNuڬ9_Wh+ّV%Ѷ(Yjz7Iv_hiYWkVo5034q1+uI42$bLI,W5a?ZPK!8:YdocProps/core.xml (MK0ަiEvAeO.Vo! 6${ӏ1;CQX'IRb KW(r*N[B'ph]__L[xڀ\HT)0v$8TwJgiz%xʩf& ٌ4ahA+ݟ pJO&4]9}tb6v]t#'m< ߊK fzm/oÝwi\g=€G!H1>+CAuUbrӐ YA~>XlA<_|PK!docProps/app.xml (Mo0  9P bH7`t,D11:NGsE)+1@oBmO۟7D | .x ן?u Y[\(.̦۞;MHi'CX:$oNXċ=}ԴfSd`W5)Pc=?Sb CtҥTm 8\݀˨[A=" [MY= /V/qDɂ'dcr]̔ ,p\ ׈[Kf C<Fkqj~čK}~.M k/Ln0YwXjm xl/workbook.xmlPK-!1\ 7 xl/styles.xmlPK-!@ɳpU  xl/theme/theme1.xmlPK-!4LZlxl/worksheets/sheet1.xmlPK-!8:Y1docProps/core.xmlPK-!docProps/app.xmlPK >fooxml/tools/languages/Livro1-portugiesisch-pt.xlsx000644 000765 000024 00000017263 14764622263 023046 0ustar00alexstaff000000 000000 PK!SN[Content_Types].xml (N0EHC-ݲ@5(`Ib/y=@j7bs=36kؘXJbSxfVK)< uV"4>Z7"z)[уKRz 6@#W&9`ϻU1ѵLTE)N9;l01HO>4Q+(2wiɆ%?-27AzeCHr+;>(2~YD[2geϢԯyir#~> $1i8PD R"PK!U0#L _rels/.rels (MO0 HݐBKwAH!T~I$ݿ'TG~$qw7a<SF_7ǽ1G% q%sCS ;%q,sT$ )ԸC{0LK.ֆץоB1BVG+{Jfu5বb/ۃ6>q +RrkHW_J;"JdjG[*+܊mc*F60یo)7C{p#n4'W68Χ Ao4 n<x`*Zt,/% f2~AK;P'hWMPK!!3 xl/styles.xmlT[k0~?8K451h{Ul9HJlȗĥcuwsSzJ\ G!FLjE:**b>2R뎂s ޹fE-LR{OT#1V_a8'r{,DRxhRˆ:傻c,W; F3Z6xЙ^4](uK, -H:(!a'V΢R'zT*/o@OT%$OK-A Fޢd5|k7Trqݽ?P-Es| CDHNPR I'|Jy'7Z SxJ:koq縉$|*p'ZrX^ o3.QS@oʵJQN0MԎAM9= ̑*&Li$ӓFȕ3N10ӔC :AkWx/bj%72\.0=9x3iFaoLmac3N_}߾O>ͦ>67>R+.\?O<ڻ1MDX~r,^NbcHt{TUo0zu},^_>pl=RQ7rz\xpSeyxL7wN+1ésoޥ!.Lw)auɘ;Tv|sx8z@N]$l <Ə sx/N|*8a}F H h8%Rdn X0U"'>s9'' 4mR;\!ӝO= Wۤ"A/Kub3L|,î]A[Ν> 3<%{cA/F߈U/n`7WsJ$A٦*="sÞ9Y4b[u'uRm69(/^ܖJ.wb]Yu%}e%Ȑbaߌ1s&(f-8/DjĖ^i0@a; M[+{0PRg+pve/;Nmκj._˗e-sY޾^K-S/P]Iv|f#b@7M;$7-E _ ld/5T5ιU%Zp #3lnwZ&|u:U\(*+fT*C7EnC˺6@˾du Dᯌ0+++ZZ:T(n\m^;AfdhAy>qʚ\hw9%:H;W D1J7+ cxγn_dEH+ֻ0z$rXj3KY'h#WE'A& ߺ0Dlÿ ,T,t26H"1tM6pZBZAwLf32Qvح> FZ/!G !ŢfU;pJ%\T3oN)܄mȿsSNUɡlE& nHtcyz v\}Q=gfqf:OM?C޲8D26Բ QsN8,ӊӴ49;uMDc6gzĺ4o.[m~cK %Y E_vl*Z ޫDݰ_J+zX)nԍzuU+^,*NQva?+ ʯ}2I+1\Wk}v f>@HFmԮ{RAUjҠoF~jԀn6RFEja 0>XyF/ƮkPK!4LZlxl/worksheets/sheet1.xmlMO0 H(-Bu1Mp@B|m%qx{V ]vsY~0eGL+*Bm&ZeX>`ַ6s[naL-S0JP MpQE:Au,F! =̟[_ZX JV.H J/`M8scZVNuڬ9_Wh+ّV%Ѷ(Yjz7Iv_hiYWkVo5034q1+uI42$bLI,W5a?ZPK! .;YdocProps/core.xml (_K0C{d1JہʞVBr4$nje{s/GUG_`lthBP7B}^MBL V7 tUM O1`v7:xo2?b. ]ci0, wLD4"=@p 5(aP`WfN%ɄƸs8NNƶm6cmUc[q@e.x-0زs<+tǫpqw=c0Q kzPmP tULo*J2f 68?t9#e/>C PK!}̦#docProps/app.xml (n0 n(@V1+zXI{d:&Kfϲmɟ=^E!+|_}" | Xfyk޿ӛ;L0  QR*[ +uL-ib];wZ F0TX]ugC99z_*ځ/?N뼳@|Kl9$@17ѢjަsL<[ <3jZ6R6Ub^K2`!9ĀC۔2%s}YT(ֿy{Q+n1Y \6 ;GzA u9ΓxcA8p#?ux/k,m +~M~0Y7X- yfy(>VPK-!SN[Content_Types].xmlPK-!U0#L _rels/.relsPK-!p-xl/_rels/workbook.xml.relsPK-!^{9<xl/workbook.xmlPK-!!3 5 xl/styles.xmlPK-!h<}V  xl/theme/theme1.xmlPK-!4LZl}xl/worksheets/sheet1.xmlPK-! .;YdocProps/core.xmlPK-!}̦#docProps/app.xmlPK >_ooxml/tools/languages/PaxHeader/Työkirja1-finnisch-fi.xlsx000644 000765 000024 00000000130 14764622263 024777 xustar00alexstaff000000 000000 58 path=ooxml/tools/languages/Työkirja1-finnisch-fi.xlsx 30 mtime=1741890739.249488297 ooxml/tools/languages/Työkirja1-finnisch-fi.xlsx000644 000765 000024 00000017272 14764622263 023045 0ustar00alexstaff000000 000000 PK!SN[Content_Types].xml (N0EHC-ݲ@5(`Ib/y=@j7bs=36kؘXJbSxfVK)< uV"4>Z7"z)[уKRz 6@#W&9`ϻU1ѵLTE)N9;l01HO>4Q+(2wiɆ%?-27AzeCHr+;>(2~YD[2geϢԯyir#~> $1i8PD R"PK!U0#L _rels/.rels (MO0 HݐBKwAH!T~I$ݿ'TG~cd %մk{bϽ KWa4:tb$47ԧ?>sg:chgMlly4D] %!bndja'7bB{"eWDa8%K 璋M%APC*ٲn RI܁bTeG/t2 gr?(yŗҞrʥgVYF9ˤYgm6 viHŊ;2F0tMړ@Vya5bc zu؛€;^|il /1_ƪndpӑWkBd[%?8_"!dF;VS-k/ƾ#0v ß)&Cwp-#n4o37.OΧ+Aro4og"xEqlmvzv98Y܋|t}WPK! xl/styles.xmlT[k0~?8K451h{Ul9HJlȗĥcuwsSzJ\ G!FLjE:**b>2R뎂s ޹fE-LR{OT#1V_a8'r{,DRxhRˆ:傻c,W; F3Z6xЙ^4](uK, -H:(!a'V΢R'zT*/o@OT%$OK-A Fޢd5|k7Trqݽ?P-E)}[;>,+X.-!'}"!ᇖ_~qbmeBTn5/Ƈ='& 0W5u\ޯk+}F#Xij^_{^l 5ۡXx Jk ^5|ivz~ J5|uKE$kRXv]A&80+ٰ.5ń%rS.( E$\ N]2 f(aKҠTo:h #CZ!e'Fd˿Z}ٳ>G?%[vP25^N}/L˟|S+]'/>yWءс  >nI #D, n꾌,.\.́e\󻖭Kj[=hq =9 p>z%.[fޠ(h,=;ر;X~##H:8]2$V"B;$,\B-:VG6㇘Zn.CSHF.#|dBB2?BdsX0El#$.1c3$LgRy7tC3%}`+o&[@Iy_˘qA'Xc]ۜ83Z1Ehw36|}%Vĺ\U u:Ea> -N%14_[ Jѡ F|q:Fr7i!R nm˻ݗ O-־"jM'A[ŸsU͝r{aȪwb9QN.`Πq+~Rg(p6eM͓Nu:jΫ_ly-s^˸޾>H-/P]7|&}xW讏7u;J$W-Y_re!kzP4)gC̜J;qlqrmfS{xWMnU9wqU >xV0v{ =we·^ն?y為F7;z> x>^,o9?֯PK-!SN[Content_Types].xmlPK-!U0#L _rels/.relsPK-!p-xl/_rels/workbook.xml.relsPK-!4=xl/workbook.xmlPK-! 6 xl/styles.xmlPK-!ʐS  xl/theme/theme1.xmlPK-!&zw|xl/worksheets/sheet1.xmlPK-!`r:Y)docProps/core.xmlPK-!uc$docProps/app.xmlPK >fooxml/tools/languages/PaxHeader/חוברת1-hebräisch-he.xlsx000644 000765 000024 00000000133 14764622263 027110 xustar00alexstaff000000 000000 61 path=ooxml/tools/languages/חוברת1-hebräisch-he.xlsx 30 mtime=1741890739.250109801 ooxml/tools/languages/חוברת1-hebräisch-he.xlsx000644 000765 000024 00000017443 14764622263 025153 0ustar00alexstaff000000 000000 PK!SN[Content_Types].xml (N0EHC-ݲ@5(`Ib/y=@j7bs=36kؘXJbSxfVK)< uV"4>Z7"z)[уKRz 6@#W&9`ϻU1ѵLTE)N9;l01HO>4Q+(2wiɆ%?-27AzeCHr+;>(2~YD[2geϢԯyir#~> $1i8PD R"PK!U0#L _rels/.rels (MO0 HݐBKwAH!T~I$ݿ'TG~|ߌ'RyeMJQD4flRzz3P 52ӓWu۵[Ƨ1E!KGwrJh 󕓐BPjGш f%6ϕVԥ4qRC}*ߣ%p%m] -+X+} JI)fc5ϠK%6Gź #yb+-o; T{([4%|Xf*,c4NVwyţWd2Zãh4'&ut<& ?WZ¢:Z~X m9A` v:c 3kg̦ \Ͽ D=T,MA*HmLS&NG]yP4qT"vԎĴp|zߗw4e5%np.3h7C8·vDUJ?$:Gd-d28'r8^^,φQYR4Qʁr-3X]B/GSPK!c xl/styles.xml[k0Bl7N`4M n ^[NDu 9;%qFbIOsSzH\ G!FLjᯏE0:**b>2R뎂w9e3sn Ė;&{OfK0ZYH H YDRt{ - #Y.J &DM45pCkzuVD5/ks2'<6R0Z+gQAE/ ]yjg*c _#oQTnǍTxSM%؝Qc!goj3֟+ .Ig%!O!U)(NFH{an:Ly*X@۝w$iV+*+4wJ&W:B* >[xֱߍEMđO#_[N@-9p``V9πt Db5=xABgZDh`{P^0y8Y0dI0O .WbQ7'OV@^lhokdixDaP\Q0Y0^&ADj:Y%E2ҞI F% %\ 24B`'Ȑ r~PK!`);n xl/theme/theme1.xmlY[7~_[U_C_=gli{ɣ[%H7,}!6#Uu4/20ts霣SG}0tJ<kt§4wQ p:Ō ޽o= ORrYN`k|ARmE>h |l4!!g>O`X8ԑ1Yak‡xszolj<ඞ˲xo>N Hԧ=S$% !սOcC:\BSk1=vڧ e#vls8z@N]$l <DŽ9f '>c0X>G+1qCs8N>k96d*qB̹~3Mc<W>!ww~?tR$WR &~\&,]z;}@gxJzA/oŐU/na7VsJ$ANT:!{D|Յiji.wN)MwޡP BxrW+ދsvgוp*{ ݗ C^[+f3A0c /݂BDFl镛pFNυ'es _)uv .`Y3d;g]U5WUM_WU-sU޾J-S/P]Iv|f#b@7M;$7-E _ ldTG1^@kjsK:FfشUݦL4tVPbUW8tTn4FMuM@˾ k2DC/ KahikW1Px^w(:Ќ|5ιTO2&#Junk;W+x!aK ^[vR6z74kD.ڙ4ܰL̠c _Ďo] fD$,T,&d h 7RC j ¯\ʯ8u2DnFGYj%}O1[B,jVTA5M&w`Ӯ}eb(lDy7ItC8(S˅wihL0]%l+0f6W亞,iPGLz̢&Z/rT(szT u la8>&28٭0[ٶ/+`g'Ŭd,n 50UWZLz(ŅV-h-PK!'NdocProps/core.xml (_K0C{vcZK=9(v 6H2MۭV&crK^˕,P(IrS2LQ`JB`ѼȩΨ2h8ͨ.9alwH/Vl&lO pGp @DG$RLP,N{a蔑Spwо1h/僱iv1|!(2g4S\qjU S wLGv5n_q`_fbWX#g}2[/Q940lv%[|[D'Yr="eϾMPK!3B1docProps/app.xml (SMk0Yy"+MJ ]M<^ؒ&f_@!!=`xy~fFgd hK|p̺mo6o^sQLAzB!HŔBh tQQ&Hǰ>ϭ o+p(Teգ  hM/n5VKk4Rښϑ]kcX˝R)M5`q)G6%P.#HW Q Ex{3F6z\j?ڇk~$"NN}=!|Qb ]|@a?Z~mq(= QbZ=%FֺxSoFxaP  KNdYhw PYrж'1)PK-!SN[Content_Types].xmlPK-!U0#L _rels/.relsPK-!p-xl/_rels/workbook.xml.relsPK-!ooxml/tools/languages/Bok1-norwegisch-no.xlsx000644 000765 000024 00000017245 14764622263 021737 0ustar00alexstaff000000 000000 PK!SN[Content_Types].xml (N0EHC-ݲ@5(`Ib/y=@j7bs=36kؘXJbSxfVK)< uV"4>Z7"z)[уKRz 6@#W&9`ϻU1ѵLTE)N9;l01HO>4Q+(2wiɆ%?-27AzeCHr+;>(2~YD[2geϢԯyir#~> $1i8PD R"PK!U0#L _rels/.rels (MO0 HݐBKwAH!T~I$ݿ'TG~|pD/k<Fؔ*Cn_ּ]c)Fv!abwm8Sm$Fh^[ >a'mRqOcAmo4 ` h2R뎂s ޹fE-LR{OT#1V_a8'r{,DRxhRˆ:傻c,W; F3Z6xЙ^4](uK, -H:(!a'V΢R'zT*/o@OT%$OK-A Fޢd5|k7Trqݽ?P-E9`5iAүT~_[4JS[lJ7Ȱ(ݫe o诮kP?X]נNӳkPv/[5($9\CZ\ 2at o^ɔ(ȆUv)&,r-Fw@)$b'hIEpi7C 0\*W@E[.D ){<1d&[Ϟ=ߞ?z/Z%)ǯ _xtxa_xzXq>yɋmLXxwŰ@Nb!bIt;Ted-u:vm,^ߵlݏ\W1F;;pUexx8OD5w%V+qF2EDS`!Ǝ!q&DzwA!9)!1e2BmfaԵ>-u?re4(vE2r#"=Ŕy1%sz_q}.b%9tE;F(9m&Idb?Ȼ !([~3r5MD2X^ޏ :A2m[ęJ]):Fc[9,谙+v%dzNk)r+emgoqx(ߤDJ]8TzM5)0IYgz|]p+~o`_=|j QkekZAj|&O3!ŻBw}ь0Q'j"5,ܔ#-q&?'2ڏ ZCeLTx3&cu'ЭNxNg x)\CJZ=ޭ~TwY(aLfQuQ_B^g^ٙXtXPꗡZFq 0mxEAAfc ΙFz3Pb/3 tSٺqyjuiE-#t00,;͖Yƺ2Obr3kE"'&&S;nj*#4kx#[SuInwaD:\N1{-_- 4m+W>Z@+qt;x2#iQNSp$½:7XX/+r1w`h׼9#:Pvd5O+Oٚ.<O7sig*t; CԲ*nN-rk.yJ}0-2MYNÊQ۴3, O6muF8='?ȝZu@,Jܼfw2_{]PK!4LZlxl/worksheets/sheet1.xmlMO0 H(-Bu1Mp@B|m%qx{V ]vsY~0eGL+*Bm&ZeX>`ַ6s[naL-S0JP MpQE:Au,F! =̟[_ZX JV.H J/`M8scZVNuڬ9_Wh+ّV%Ѷ(Yjz7Iv_hiYWkVo5034q1+uI42$bLI,W5a?ZPK!^Ф=YdocProps/core.xml (N0EHC}bYI*JHY6{GCPY;g9 AhJrREs-yhZ0L4lc \H1ar0؃. mciwpw`K9hDJ1!ͧ{jP4*gC̜GvR >j2m>FO_5tw+Ȥ`-Jp>óBw; wV 8}2 A.5*1IczUR-&_]'(2|oPK!bdocProps/app.xml (n0 n(@VQzX`I{d:"Kɞ~κn$'عǔmX.JQ7~_ݷ/=벼x$5Wl(&UOkZ3)2Vw1:kњrhxc=_6Ŝ[4/IJS5p#t.o0o6ezZh("߼kQX%zH<16%cb#,O1wcY/. K%GD]yGv¹Kin|.y9n!?]U^ն5osA=L-=֯=;˛E?Ք|hPK-!SN[Content_Types].xmlPK-!U0#L _rels/.relsPK-!p-xl/_rels/workbook.xml.relsPK-!;HP:xl/workbook.xmlPK-!!3 3 xl/styles.xmlPK-!6 R  xl/theme/theme1.xmlPK-!4LZlwxl/worksheets/sheet1.xmlPK-!^Ф=YdocProps/core.xmlPK-!bdocProps/app.xmlPK >Qooxml/tools/languages/PaxHeader/Kitap1-türkisch-tr.xlsx000644 000765 000024 00000000125 14764622263 024341 xustar00alexstaff000000 000000 55 path=ooxml/tools/languages/Kitap1-türkisch-tr.xlsx 30 mtime=1741890739.248103039 ooxml/tools/languages/Kitap1-türkisch-tr.xlsx000644 000765 000024 00000017305 14764622263 022400 0ustar00alexstaff000000 000000 PK!SN[Content_Types].xml (N0EHC-ݲ@5(`Ib/y=@j7bs=36kؘXJbSxfVK)< uV"4>Z7"z)[уKRz 6@#W&9`ϻU1ѵLTE)N9;l01HO>4Q+(2wiɆ%?-27AzeCHr+;>(2~YD[2geϢԯyir#~> $1i8PD R"PK!U0#L _rels/.rels (MO0 HݐBKwAH!T~I$ݿ'TG~,}ƑLPp&q2f'A:A OU{]Xtʯr-]vBAj=gM^H A4lJROM?(yDlBrzT&DŽoĹcP$4GE@ŧ#<ה"Ci8^V\7R ':-BLp3')ֈ9tr+ mSCV }BWh>Dx0l4&ގv5[m_DSx.9|[ne-q:Qj֟JPK!QQ xl/styles.xml[k0Bl7`,M n ^[NDu 9;%qFbIOsSvJ\G!FLUje0:j*b9>22뎂sx~IvLR{LFI,͖ؽa$ÔH KYDRx{  #Y-oJ fBmx3DhwPWYZI})JHY @JW"?`1)J m`(*Y 1*8܎ YQigr6"Om,'"$8fT 4{^zL8 ݅EѦii-sSҲkX<=ӛ;\d$A{Bd(Kp_`_Gіp=OjbQ`slmx$ @4bWA5@W^W-[xCus;T A` ?t^R|;N֯A)ڽnנp ] kr+Ȅm'z%S VѥDnf|HēqQrC %LpR_}M{madH+^D )>q2-2h ȳ'OOJ\*h^(h,=;ر[Xv%#H:8M2$V B$,\ՖmvozF]# Q!/DK4L\_HSXU5~2tH.ɡKbDa7Bə$DB"..wz?dolՉ$WR 9wf~\ ®,汕]ۜ83Z1EhwY6I_ lcW`]Fv U(A]"wBvO>gMV)LW(!^F*@MZE:Գp[{=Ko,m3DԚ !ÕnAr.U-6wMM #މID;e9ǭ]JM)eD ,kzh\p笳欪Uͦ|V˜2g2yM=xcgB(ݗ wx`PtOrE5k0Y)GZL~Jdʺ9fL@Hf*>[.rYu5S $R.Lѵz޽[Щ. (7!aLf:Hԗ+;MRtҋ+SWۃiqPfһ9MƤf@MuP{ O[$pIapf4}]jSXF>|ȉ@3S;nj*#4kx#[SxIn,3.d(5N:i6ܣ$njh![ %ׄNƓ Iƈt>_ۃ$w@: ee1pqPN9&pJdy8k^EJE(;Qdu]O+Oٚ&<OWrFL+SӝL!oQU;s]s P+N8 jd5x= N 0,Q`۞ w2j+uKsV܆у9BzAї@iՈ͛svЭB A5(aZha˥^r0]dz|>^Ҝ|QW^sV4NЬiZЫuA6{wA jFVv A7zPz2V`^?PK!4LZlxl/worksheets/sheet1.xmlMO0 H(-Bu1Mp@B|m%qx{V ]vsY~0eGL+*Bm&ZeX>`ַ6s[naL-S0JP MpQE:Au,F! =̟[_ZX JV.H J/`M8scZVNuڬ9_Wh+ّV%Ѷ(Yjz7Iv_hiYWkVo5034q1+uI42$bLI,W5a?ZPK!h<YdocProps/core.xml (_K0C{fQCہʞVBr4$nje{s/GUG_`ltH4oT8CL V7 tU 卅'^I;MP%kb><?"MWXgy;`l&"OHi 8h0Iz+3dNc9[AG''c۶IcmUc[q@e.8olY9mN;z(C6\$,&7Ii 68?x9 7PK!P&docProps/app.xml (n0 n(@V1zXI{d:*K^`g3{6:N(CcbEބ}!v>,\XoߨM -F25Q2H =+U q/CUYW<6I/ጌ9x{:4-ctl5D,1? /5d]c0"jJ~pPK-!SN[Content_Types].xmlPK-!U0#L _rels/.relsPK-!p-xl/_rels/workbook.xml.relsPK-!E֭;xl/workbook.xmlPK-!QQ 4 xl/styles.xmlPK-!U  xl/theme/theme1.xmlPK-!4LZlxl/worksheets/sheet1.xmlPK-!h<Y&docProps/core.xmlPK-!P&docProps/app.xmlPK >qooxml/tools/languages/PaxHeader/Map1-niederländisch-nl.xlsx000644 000765 000024 00000000131 14764622263 025103 xustar00alexstaff000000 000000 59 path=ooxml/tools/languages/Map1-niederländisch-nl.xlsx 30 mtime=1741890739.248562292 ooxml/tools/languages/Map1-niederländisch-nl.xlsx000644 000765 000024 00000017267 14764622263 023154 0ustar00alexstaff000000 000000 PK!SN[Content_Types].xml (N0EHC-ݲ@5(`Ib/y=@j7bs=36kؘXJbSxfVK)< uV"4>Z7"z)[уKRz 6@#W&9`ϻU1ѵLTE)N9;l01HO>4Q+(2wiɆ%?-27AzeCHr+;>(2~YD[2geϢԯyir#~> $1i8PD R"PK!U0#L _rels/.rels (MO0 HݐBKwAH!T~I$ݿ'TG~;+fYRM}ms=\;} 2L|bouTTj3-߿KڜZ(ʹ&!IJNtAh6VZgB!1oe)h\pIo+fo9tAH{PjJz@#2Lkt"CW|@9OK! ;M]m x9[0mj&wt{0a2@V:nu| zJ;ily _zwU52yݴڿ-CIOy5gK.D' }p,F<ԟAx7D ?zYűr<ŮW·LTJ"]])F&01;Xƿ ,\SV5\N>Y0"߂ȿ؋[D[GpϷ*;\OG+ e'xZy:~uӱj2PK!>o# xl/styles.xmlT[k0~?;8K45:(*$s6wKұ:;߹)n@XUISec1 XOԺ`=c;wXb=N)Sk#=F+/IA0IR"y:Ru|w #Y.vJ@DM435 "yiյ(uK,-G$}R0Z+gQAݓ^>)]7v^yjg*c ņ\#oQT 5k*8u^۟Or"GXą8=0)1 PP/?^lt0?w8@ڀyզY1TQw{:}V;-ӊӝVTT:Lo F( " "$ҋ^xKݰ_w7~;'09=p\0`VXweisXM=fx%,Uk!2VO T1GK*8Rz[UU"?f%PK>{&{ KEe%{?yx~LCaI/_(NFlLi˿='$JƈK~rmDlI9*f8wc$Oc@oLRVI|/A1W*iOaD 50|Oƶ "KwhˇhKߣHHxK_t2!*7r/='& 0W5u\ޯk+}F#Xjj^?{^l 5ۡAh5(Ňklkkz ~ (IХV.WLv›a0W29 a^j Kd=PH$I< Aw%x;dAP *A @!E[00E )<1d&[Uϟ?zvǏͭUYr(r~WOI>&_שxӗϞ?zh߄IwyX t؏$"@Cu_FQm@3.=ֽ%q|--.cø\dꞜM-]swQb?n-3oR l4 z0v.!_wɈ3&һK"N ɾH6!. j7wU𡍄m!DKtȽ)돱.k0;tH.ɁKbDA7Bi3I"8EM&]]f q@p! 6iR ͜;by3{?.a˴ylkgvtS+w01n氠fsF*ؕXW9{Y"S Y$F|u+usR ::0 /NH&7#d]Yu}yde7CD "(0\t "VsujSnbo< PYNL7?'ʞ){ekZAj|&oO3!;B}|Ҍ0R-j",ܔ#-q&?'2ڋ zCeœLTx3&eu7ЭOx^gx)\CJZ=߭T7Z(aLfQuQ_B^g^ٙXtXPꗡZFq 0m8n+zL_zjx},Lkpc%ōAmRb.JDq%e6-viB8M{ CO,%}E<q |iw ՗5@J`M 94To# 4 xl/styles.xmlPK-! W  xl/theme/theme1.xmlPK-!&zw}xl/worksheets/sheet1.xmlPK-!+;Y*docProps/core.xmlPK-!edocProps/app.xmlPK >cooxml/tools/languages/PaxHeader/Βιβλίο1-griechisch-el.xlsx000644 000765 000024 00000000135 14764622263 027560 xustar00alexstaff000000 000000 63 path=ooxml/tools/languages/Βιβλίο1-griechisch-el.xlsx 30 mtime=1741890739.249810174 ooxml/tools/languages/Βιβλίο1-griechisch-el.xlsx000644 000765 000024 00000017427 14764622263 025623 0ustar00alexstaff000000 000000 PK!SN[Content_Types].xml (N0EHC-ݲ@5(`Ib/y=@j7bs=36kؘXJbSxfVK)< uV"4>Z7"z)[уKRz 6@#W&9`ϻU1ѵLTE)N9;l01HO>4Q+(2wiɆ%?-27AzeCHr+;>(2~YD[2geϢԯyir#~> $1i8PD R"PK!U0#L _rels/.rels (MO0 HݐBKwAH!T~I$ݿ'TG~~of98 }IcLFBsJMoLL-b|/H^=9 .ƹsQ070[0WZR E I[} 2ڷ V(!}uh \*{%@줒Ũ^v hCt!5dPM/ -dI%n[+OQ):^1Ch[J*#L'+,JE*`B Gi8WK̋4`/skV@QԲ%s3>c;w|*bLn'MGI ۦ~Xt'uj1 ܈.#L}pDOcoG0X섦ᤦEqϏ_FWcS;IMJn/gu,S:+k%ĸ9[;9 '``؋&Ӱ7aop^Ç[{*sf2~Zd ['eM]PK!FLk" xl/styles.xmlj0{{W{I]Bv[ŖQ}I霍o {Nұ"t$?_J; S2CI<*KU1л#X"+•R/Rc^( cS DZiA,L28  $SQD}Ykbقqf- y^.dAjH5a %ZUbU׬NHHas>\~uc~v}abøeҁ^5`.ֵR}da1CZwewʶ W.ga2Ph6ed~QD8)I<|6 ?zݾ?y m75^⯏ &ZAP$JqiqrEFd4x=~0ܿ!MO-3>CC+$ q3{PK!M:Vn xl/theme/theme1.xmlY[~/@̻ی. ˁػ+Qz9Cv- 'yKi}C4A$ l~M#zi_.bWBC}9g8aIy *"Oi:ƣR+@RtOI'X{]{*& A = b{岜0ی+xT3ЛrRiL8矝~/'lF'$f`TI=0aHOBrY ;=j\>N3N٘ 4la@WAsP:xK}s7o@p ?ހ2|zo@oV7d ]zȌ}/f-W^ 6ѥT튵?b dXՂ⹏=y )0\UF:ן|3{[Қ0[CAyϞ~7>sU>NO=音/⥍^|/x/^||؆iB$C}=ɱx=q#cQ=Ṫׄd(KE=3ߎx9q5m=e2'KwS}:.^Oe?&{ IJҿB$czR!OG\!q[Hyȏ sx/N|*8a}$VbbRq4)}2wrm0~U"'>s9'' /g6=y!=|C ~Nw?qH6"@/KMb3L|Y+'vFGo9wB=_86/Hߊ!_`nHL]"tB> g]םЅSΛJɉ CxVpwic+UG/A $W3g"` _>W+7s7m(z'K eO){%<~ſٕR/8pe/{NuU\U5}Uk/_2WU-{z+LQ@eStyL'QƎԊi>h#4(ӓܴ1|Ln.AbP4;2W=h%t̰i MiiVuW33ĪDqR hݻz.뚀}d.Ds=^%fe¢a׮Z{qc r#xQQuT)k&seLfG(<\w.O. WC 71i/¥=mn(h4[o:\ ,3KY'h#_E'A& ߺ0DlÿIfYXƙMɲABѤo&n$,69pd2nhKg\Ո9XK%(c1XԬjNjf)M"+]*P6"b' n膎yz 6\}Q-g%t>5uXeۼS"׵׹{J}VLPӌӰK vۜ^KrVlFz(Q)Zv+ `4GIN 8ac*5~)lT4V kn춆aI^ʳkxPK!4LZlxl/worksheets/sheet1.xmlMO0 H(-Bu1Mp@B|m%qx{V ]vsY~0eGL+*Bm&ZeX>`ַ6s[naL-S0JP MpQE:Au,F! =̟[_ZX JV.H J/`M8scZVNuڬ9_Wh+ّV%Ѷ(Yjz7Iv_hiYWkVo5034q1+uI42$bLI,W5a?ZPK!6;YdocProps/core.xml (_K0C{f:BہʞVBr4$nje{s/6GUG_`ltH4oU^mFL V7rt6U 卅'^I;MP%ob>N DN{`PFC+BG q "APn){oʝ+!ŲTr~ #ʮ!.tIiۣw]PK-!SN[Content_Types].xmlPK-!U0#L _rels/.relsPK-!p-xl/_rels/workbook.xml.relsPK-!21Lxl/workbook.xmlPK-!FLk" E xl/styles.xmlPK-!M:Vn (xl/theme/theme1.xmlPK-!4LZlxl/worksheets/sheet1.xmlPK-!6;YidocProps/core.xmlPK-!1docProps/app.xmlPK >ooxml/tools/languages/Book1-japanisch-ja.xlsx000644 000765 000024 00000017414 14764622263 021662 0ustar00alexstaff000000 000000 PK!SN[Content_Types].xml (N0EHC-ݲ@5(`Ib/y=@j7bs=36kؘXJbSxfVK)< uV"4>Z7"z)[уKRz 6@#W&9`ϻU1ѵLTE)N9;l01HO>4Q+(2wiɆ%?-27AzeCHr+;>(2~YD[2geϢԯyir#~> $1i8PD R"PK!U0#L _rels/.rels (MO0 HݐBKwAH!T~I$ݿ'TG~c %Qk{bν ͹T蛰N`: 0LCv3g:chp&}.>{sD] !dnh*a%7dB{ e—A0!%w  璋u)@PCJc] )+K%ŨA hGt)5~P+/ 4ΥUgV6YF9ɤY퇭e-Ҁ &we"g;0<7;ԭjhT_jWwнZK+)/1_ڪnwӑWkBdv%u?qR/)c(@xjd3(4sM 2/mpŚqۘ]HmF[gns:ˆkk$M+i #- ln.mOΗB*` 8w`Ž= 4WR'˒ֱ7p~@ا!Mi\Jaˍ0 QHcѹ ƹdR9 i6"0'͎],1l,7WXi0MM-P4?5 ?aͫ2vHc0%28rZz= z0R: 1#(\ٯk]HcતqAR l csNޗqs^$^z7aL3p(Cs{;rƸ}NU~/@^}z Yl(3T4YT2Ecz]= T %0s_Latá!+ij2| t6}5e;#wpL"wMgn48fϽ~Sw45 jm&q8_Gf~x䎆ǑEA8gQGOp]hb('ΫΡ~L#Ix' PK!%Z xl/theme/theme1.xmlY[7~/? 6o5d7 Y'%Z[hW32S%  iKKPJ-BBB/?GGZͥҖ]⑿s霣3GW=w ,i+%ɈI2mBDQ¿[Wіp=OjbQ`+lmx$_~Iw xwY t$"@Cu_FQme\C~8fp1aij.y2uO&.BǮ(ܟ n-w(J$KOƎ0v!]Ȉ3&{@"N ɁH/ Ape^Qת{F¶@A~eh.QR9D15 d"#<=Ŕy1%sz ߄ v]6Krҹ3=vԍPƖτP/ F3nG8k`pSǙ|h?B3h us*2S͘T|N;=6N;j&Hp5]*k{RSe]PB˜&Qu/ EBBX4,JUK/LV^Wn^[~dhAy>V~JK*\7%2rO7׍SKC%XI9{?xt"^VԚc7aD߹)KUtYL)\' nƒ:`ZYHieuj; V!jJS~yk.sxA-̢aQ%j:#xݓG: u|}mnjCH=?S)+Κ#(4my(ysNZ{t+aPjBP JFخaX-rש=58ン g=\IKUƱ_Wl79k?G8ȌZze]RY]z(7,x;iN_V `e#E^wL0Ţ<6_GRUON,emAJ| =_PK!F1;YdocProps/core.xml (N0EHC}8EXI*JHQi?d=Σ!lXz3wFWGD_`]UHעVVx" tVU ³E@ HPAi+Odž-`F|ڦ ;Lt6)k2a1- N'c۶Ico7O/q[q@e.8׶ &yW?z(Cxx֨ReLn*R{7Wl(qY6#e/>C PK!EOU#docProps/app.xml (n0y{L9  N jN+uR$A^cm2vEBI#7jӘNrUv]gE[q Ȯ'c 1K6&3Σ8IMJBҰ殪kЖX!g-iTV[ (Ri\tew%F|&cдT,Q𷂸Eַ-ZTB3XZ,%mHHAwO~ gƱӾ!Ǎcԕ&{@O==,kDfIx]npi3׵Ųezq6Lg2|y/tarz9o[PK-!SN[Content_Types].xmlPK-!U0#L _rels/.relsPK-!p-xl/_rels/workbook.xml.relsPK-!).:xl/workbook.xmlPK-!_ 3 xl/styles.xmlPK-!%Z 5xl/theme/theme1.xmlPK-!RR|vxl/worksheets/sheet1.xmlPK-!F1;YldocProps/core.xmlPK-!EOU#docProps/app.xmlPK >ooxml/tools/languages/PaxHeader/Zošit1-slowakisch-sl.xlsx000644 000765 000024 00000000127 14764622263 024660 xustar00alexstaff000000 000000 57 path=ooxml/tools/languages/Zošit1-slowakisch-sl.xlsx 30 mtime=1741890739.249648215 ooxml/tools/languages/Zošit1-slowakisch-sl.xlsx000644 000765 000024 00000017335 14764622263 022720 0ustar00alexstaff000000 000000 PK!SN[Content_Types].xml (N0EHC-ݲ@5(`Ib/y=@j7bs=36kؘXJbSxfVK)< uV"4>Z7"z)[уKRz 6@#W&9`ϻU1ѵLTE)N9;l01HO>4Q+(2wiɆ%?-27AzeCHr+;>(2~YD[2geϢԯyir#~> $1i8PD R"PK!U0#L _rels/.rels (MO0 HݐBKwAH!T~I$ݿ'TG~c %߲?k{bϽ չT苰N`: 0LCw3g:ch'U]|27@W B/DTBNnl<@\e\!/ `BJ&5-&%kRh߁X]!+ף-p%ǺpSVJ/m,+}Х8!@ 4 v8J1Ly*X@۝w4iV+*+4wJ&ĝ/vS#ut7U|)8O;^1c)#ODG2O(TOA?hl՜$8Cm|NA0*VӃp>?$ZԮEd<Ɋfָ[ #:׫wup5dj.a^5+Z}xmi4ߝm-:mE< 'Q0 3:IIguR$# Dx4Qt\2Ր!Cc+$ q W= PK!d xl/theme/theme1.xmlY͏@]׌>}zcچWv#%QZ@Rs%@%@o=F4@^zȟbF}4䊊?.bWBC=>yӄs"$i'ިS><JIf<%`Cdѭ&>R1ITN+:*W$\$XXg_ބkJ`( =hُ/ݟ L*L9H.jag˪Fȍ310_S :A[7(bꀬ%72\.0[̜b1MQSas6v OҌY9e_=A-=He=h+:x>{WeY¦߀bF5jw9g^x; GZ@A4KO1:k ~Ȱ)R)s3:E )0\UF:ן|3G[Қ0{CSAWy/^~sU1NO_?fS_K^?V\՟{w|xb4!#!O`d"MbcHt{TUm0z5cY~p=ZQwrz\x pWeYxN=7wWSُCé o|IguPN|'0dL'N B4l|ՎmNgUȹm0njZħrfGl#6n(xzAG's_z-߅ w)$.R(<_ci؏B\!Ӄ~L7'G\mJE_ۄqLW$Nv ꍎz ! _!=rl^CV9&X)f?EPY|N7 4; 7gӥ GxVpi}cm'/A $3g"` _>W+7w7m(z'KeO){<~ſ9R/8peNu]\W5}Ush/_2׵u-{ LQ@eStyL'9SԆi>hf#4(ӓܵW1|Ln!AQxiv.dz!ъKaS%t:9峬YffBU1^vХR,w;0]--.$\uvs$ʮEâo]@mxF 0 C3SLzW;J=}Ș̎(Px\^]join. + cxΣn_ۅKzPh>uXjg NШGp2ūN01|MV;Ruaن̲R 3e*"I'EKM1ܪ5HZrmH+6rtd>'Seі!gkpY<@1XԬjΨjf]"+]*P6*b' n莎yz 7d_|֖fqf:YEdyUq:mީe\=%pŁ`Q+&siiX|ԥve%Qm]iܝ۷|LIJ2KEFoh-h'u~-*hX aԊR7aT zgp8Fٽ0&7{7Ɣ'enˆ֜|($OQ5JzwT VoJF9 Q=zs~Jj_ M.5Z6a}1,}^PK!&zwxl/worksheets/sheet1.xmln0 Ek9}7S v1`Z2m DCbvbl)R'(VzVZaԸUF;nyk="+!\ymrAFi)` Sg)xsVW&zO0mM{HB, @ 'iN-AwT`]_ ჳ2\=|knƉvLb26wV zHh=>K[Qj@5 @v` iYWn9ov+Vpq= : s1+TtUSBLz}UMQ/GYsYk!PPK!1;YdocProps/core.xml (]K0C}dS@eW+w!9ۂIۿ7V捐ssH>&%A hn=כt1JtEm΍Gg, '}m!cϢCGqgb!^[ 00H'pMC tfx8|+3dLc9[AG/'c۶YcnQS]q@U!x`\U5̇mN=z$ɇޠjA*%^Ք,[.PPc37*gPK!"docProps/app.xml (n0 n(@V1rXI{d:bKfϲmɟ?MaLֻB,_Zw('%WB$wj}HS.& +)`ٱRqW5KmI<˛p6㪣5- kњ蓯({cTg_N%m9wh^^JS3G J^ j0o 6&:Zuh,ٟ[X!:16%c܄DQo~^Ic׍5R{H]iG9^|g}?.jWCĒ6 &מC˻E!OՔPK-!SN[Content_Types].xmlPK-!U0#L _rels/.relsPK-!p-xl/_rels/workbook.xml.relsPK-!w-Bxl/workbook.xmlPK-!Gq ; xl/styles.xmlPK-!d xl/theme/theme1.xmlPK-!&zwxl/worksheets/sheet1.xmlPK-!1;YPdocProps/core.xmlPK-!"docProps/app.xmlPK >ooxml/tools/languages/PaxHeader/통합 문서1-koreanisch-ko.xlsx000644 000765 000024 00000000135 14764622263 027533 xustar00alexstaff000000 000000 64 path=ooxml/tools/languages/통합 문서1-koreanisch-ko.xlsx 29 mtime=1741890739.25075443 ooxml/tools/languages/통합 문서1-koreanisch-ko.xlsx000644 000765 000024 00000017435 14764622263 025575 0ustar00alexstaff000000 000000 PK!SN[Content_Types].xml (N0EHC-ݲ@5(`Ib/y=@j7bs=36kؘXJbSxfVK)< uV"4>Z7"z)[уKRz 6@#W&9`ϻU1ѵLTE)N9;l01HO>4Q+(2wiɆ%?-27AzeCHr+;>(2~YD[2geϢԯyir#~> $1i8PD R"PK!U0#L _rels/.rels (MO0 HݐBKwAH!T~I$ݿ'TG~:3߮4V;ml(7 3~b>s=: IcLFBsJUoLL-b|_%/_̏vh2"\M)4dChĕVBB0Ƥ`R!0Y&X^B ¹'·L͈t_JbS$L& Dw3zh6`č敵`Vb'd#.c\Oٰp: { -p=Wq=꞉Yqق9# buUTPK!T xl/styles.xmlUj1Bʞ?Krz"&+k7 bԚJX)T/}֔܏` $n&"A˕X30t)& Rp@rTCu u`VF@}U,O=>) jϒRIkP6Ҧ8M K{tI8a?KrŕF i."͎}n~J"6ljnSmR }'OMWe߭LT9LP;خc?{6&̒΃_dbT8{I|'˛럷WZ0nl(]Qw'e =;fAKb-F@3hwf)ޏϜqʞxERdb<;G(!qR$I OҸ(9!o&`T) JU>#02]`XRxbL7 O~>gskU6JG?~g?'OaŹ+Ó~xgСс  oxY t؏I #D, n꾌,Qm2.e~8fp1aj.y2uO&6BǮ(ܟπ^Ke7–(J$KOƎ0v=B,gM:8]2$V"B$,\B-:V6㇘Zn.CS;HF.#|dBB2?BdnrX0El#$G.;1cG3$L5q)[L!‒Kg WӤƖτP/F3nG8k`pSǙ|h?B3h us*2Sֽ͘T|F;]6N;j.Hp5]*k{RSe]d_c2ۈÈrOF蕝M ~eWVQWn^[~dhAy>VqJk79%2H7VsD2H7# #xβlgyH-+!7xV$rhb2M_p2B?1|g;Bu!:{fq!{HD5lGIW@!ڶr5 A' ZJ!;s~Ar8( [Ygvͫ(C8e'I)\ƒ:`_}Q,2az_?+ n}4bq6\ܗ+=~2hVZYm A(4NW{^7l4}XvBZIhAF?hXyJ/ڮ+PK!xl/worksheets/sheet1.xmln0 m N1(Ca[3-ӶI$i~r鍤ďO^W/EUkRǿgZ؁cWϟV;ʛ2"B,ҘbG P*J奧̓))#tsRK]7\2A},ސ|d]*GZțm: ZgV.HZ/s.=gTJp̗iL0ɮ2fyr+lAi5imTs{;k+ ^vwoݡF[``ez<ڼO"GkfK0Ţ<«Z{=ת%f Go@Y~]}RLCPK!];YdocProps/core.xml (N0EHC}-(Tik?d=Σ!lXz3wF.GD_`ЪD$IQi.ԾD/&PC PK!OkdocProps/app.xml (n0HC{ق*r\-*Vm3X8vdO]n\7GP;0I6 ͟O<uk\aL6BgЛPZ-+%_  $gjC,-|*DM.LҌ۞;U q+CUY6I/@D 6Q߿=|y×;%Y2pcȍ%}H`O77Q/Cӂscn77z\T"  ꒗]oo|/fooxml/tools/languages/Mappe1-deutsch-de.xlsx000644 000765 000024 00000017307 14764622263 021530 0ustar00alexstaff000000 000000 PK!SN[Content_Types].xml (N0EHC-ݲ@5(`Ib/y=@j7bs=36kؘXJbSxfVK)< uV"4>Z7"z)[уKRz 6@#W&9`ϻU1ѵLTE)N9;l01HO>4Q+(2wiɆ%?-27AzeCHr+;>(2~YD[2geϢԯyir#~> $1i8PD R"PK!U0#L _rels/.rels (MO0 HݐBKwAH!T~I$ݿ'TG~a!a<9SF? ogcOcNKq} RT̍L-4VChVܕBJ( 'bRaa߂aBr1=y(ߕvZW1{jꀛT?wU|;jcA Md^AW[LGE"ҐPSΖTⱗ̪6H1緹"OBs-ئ^5R. )`XqgQ. (x88̣= nV3/F{W. ŗFZMʖ-%jJ1yp@xF7y%1/DfeKn_R?zlQ%b˓Թ983C8''2,_> y,=(>a-U!S7"9X{+vمC~LqphNqyc-8wir>[zqx; qnIQ0Q76n7U8ؾ^YmŊ9h# Z UPK!f9 xl/styles.xmlT[k0~?8K456*b$s6wKұ:;߹)i@OXU#J]qׇ"X`dUZ 7wu'e3|pYb^)Sk#m qΉ\a%<Բaa$^iCwь&#tA$/vWJt]$KB `_%$YTrP~@WJW卽W Ęi6A![ ƚJ.Ng彈1.q!άbO y w̨4+S'H0OwT0S=FS V; jOsв<8kEO9 NɄyV?nk0L/(B"ǿD 9> ^~F~gxm`v;re@کҕjQ{8$f?JX Ү$>k' ':w]pf, z$fS,8uoSXfHv lPIwS //y1 `6`1N"|K{w"$Q4mLp5jХ_ c'PK!X7N xl/theme/theme1.xmlY͋7? sw5%l$dQV32%9R(Bo=@ $'#$lJZv G~ztҽzG ’_P=ؘ$Ӗk8(4|OHe n ,K۟~rmDlI9*f8&H#ޘ+R#^bP{}2!#o/)NP#RB,Drі3ߓGC/?}2!*7reÊOVA+@:_> @4Yt kүݽzZP},5`/Zx J>4;=[^j_"J5t)Uծ Fwf LylXeb)bt"IO.fxF]D'.Fx30åJiP 7Q!Kڐ#Nf_yO?GͭUYr;(r~WI>&_שx퓗O?zIw {7Y t؏$"@Cu_FQm2.]%q|5-cøW\dꞜMM\swQb?n-3oPH4 bXB,gMwxD.+rC\.!Ԗon{F]# QCL-7^Fsb!]$# >2q}!!SLc!\29U`w"\C]ĘnfD&3q)L{!‒M7- WӤύ`Wb]Av f"wRvO{'gMAԭԅSI^#PA8r]#ވuvg6{ Kbk &fp-XEԹNi0@ad;1IX({q0gPORvN8p ':gW5Uj6Z漖9e\o_l.[>B\P+tGx{,YM92gs"͠5TΩTO7c:FzX7Q ݺ48t˪P 8tdJNuui=dU DuF蕝M ~eWVQWn^[~dhAy>VqJi79%2H7V[D2H7# #xβleyH-+!7V$rhb2M_p2B?1|g;Bu!: fq!{HD5lGIW@!ڶr5 A' ZJ!;s~Ar8( [Y'vͫ(C8e'I)\ƒ:`}QQ9oIՐ3߮^ pN_u=靨Enw\ܾv)3@_!u.f屝J3,d4ղ\|\-51Se/Á2eA/(uvPK! >RA=YdocProps/core.xml (N0EHC}(VJ ;˞C!<ʂ9sg|}u %)@1ͅ+9OVP#8.//rf6`r7c KCq><>,MO9،D4 93 5HP,׃φN8GvNٜ>81Iy#sj,T{+9#ږ8I=^M w s^.v }R^w4[*UzC ~oo9 ?qIfS P3PK!8ַ docProps/app.xml (n0 n(@VѦzXI{gd:&Kɞolɟ7.0 Y.2& quCdKpc!HRV1"eS!jv!%Y}RƝ Ue ؠgy=qgM`z>zU:k-51P8c={NiJk4AJNS6pF uЯo6V/:4bF_Zȶ@؃hsd]KUܢeں'fJQilА`I)ƲCS )0B8ǙSiehZ$vneE!bcAݦuFכ,k;,_z _x?_oyzIMׯPK-!SN[Content_Types].xmlPK-!U0#L _rels/.relsPK-!p-xl/_rels/workbook.xml.relsPK-!x7.<xl/workbook.xmlPK-!f9 5 xl/styles.xmlPK-!X7N  xl/theme/theme1.xmlPK-!;vxl/worksheets/sheet1.xmlPK-! >RA=Y0docProps/core.xmlPK-!8ַ docProps/app.xmlPK >sooxml/tools/languages/PaxHeader/สมุดงาน1-thailändisch-th.xlsx000644 000765 000024 00000000151 14764622263 033751 xustar00alexstaff000000 000000 75 path=ooxml/tools/languages/สมุดงาน1-thailändisch-th.xlsx 30 mtime=1741890739.250441303 ooxml/tools/languages/สมุดงาน1-thailändisch-th.xlsx000644 000765 000024 00000017512 14764622263 032011 0ustar00alexstaff000000 000000 PK!SN[Content_Types].xml (N0EHC-ݲ@5(`Ib/y=@j7bs=36kؘXJbSxfVK)< uV"4>Z7"z)[уKRz 6@#W&9`ϻU1ѵLTE)N9;l01HO>4Q+(2wiɆ%?-27AzeCHr+;>(2~YD[2geϢԯyir#~> $1i8PD R"PK!U0#L _rels/.rels (MO0 HݐBKwAH!T~I$ݿ'TG~kY)R%AEW ]9Q:&m6)ڍ8C罙xW=X'N; IZTuB^$p+!!wʘM%$RDwG'5uFa8S eRUڷ e:B<vS=a!VRI׀6ޱAB kB6'|YHk)gTp|ˋEŝ_Cf mت\TR) #:U J+,B$ԑHDy{85ڣ?W`uKxWI l~>*B\:+1,U\+GIΟ/DfO~bk)|V7􍄭{vݭԩ&d"e!V>OH4f{AsqS*ff tOa.: TaS֐`W;^a4a:v͊˄|`qx2 'q/\x4-o aX.k5PK!PZg xl/styles.xmln0x)md"M iEM֚?*) +^>N$m2 nb\Ղ{Td‹yTdrܟ X"K•)Sׯcm( I cSl Bm?҂XX56[MIi!qc,%D?AnJle+ƙ7,bvJu8"WcnhLO.ʨ^b}u= #1,+NZ?НٽTe~9c+KpDgIҞ`H"hcI6Jg`|Zc $!EQckR Nb' g,Xe /[P$\ZLך(ͅYRCt2e 7nj ߕ%%#k% w)(w?Uuɝȅ-Sp#ݴ Z^]=q +?ÏTV;- G4|ǣbO(6h4sd tphy9ۉm),ZMi4aAdOƗa7q|>er&O:ehh$/NS&pgPK!Ivj xl/theme/theme1.xmlY[7~/? 6'mG-{Ռ$Ɣ@IJ_ >ҥ/+ ^~D4cK7-#9GGg.^SsAXJdo 1,-һ\D[21@>[GRζE1a$.N 1ȧ1GG7JT+ƈ$Ԟ?:9'ǏO?nL&dK˙KP#<87ヲBR"a1;(~h%/],L @erդAJP~mOh+M:na PաWU_]kP?X]נNӳkPv/[5($9XCZ\ 2at o^ɔ(Ut)&,b-F@)$b'h!Esi7C 0\*W@E[Ҋ0kC'Fd˿ Z}ç죏=>[Q25~?퇯txa_<ϿzXqn_>yGmMXxwŰ@_Ob!bIt;Ted/u:6Y2gq݋\ע2F;; pMeXx8OB5w%WRٍE&EDS`Ǝ%IJ.q&DzwAi!ٷ)&1e"l{0ZuH:1x%]*(w\$|dB2?BdnpXkanߥFrI\:wc&gN$L{By7twC3%}`/O!Q̹×W0Nve6 ):Bc9t̲yNjYe*cU='X`O5)r+dm೻8x(ߤ:x ]8圩jAQnaw֛.,^edk@be &fp[ܟsU͝r{nȪwb9UL.`Πq+;Φ}ل5=4Onb8IsyUs^f^>ekZVj|&O3!;Bw}ь0Q'j"5,ܔ#-q&'2ڋ ZCe윊LTx3&cu_ҭNxNg x)\CJZ=ޭ~TwY0&IT$A_+;MRtҋ+SWۃiqPfһ9gMƤf@MuP{O[$pIapf,}]jSXF6|ȩ@3S;jjW,#4kx#[SIn7,3.d(5N:i6ܣ$njh![ _K iFn;O&x$M##d4W8oVlދG>[B,DA9M*w`Үyc(GtD1y ItEG?l`>O1Q<1z8><)N`pc++p#L#巸>a vԍ[,+߸fe.lY 9^> vU'2/^C]l>IG9F= PK-!SN[Content_Types].xmlPK-!U0#L _rels/.relsPK-!p-xl/_rels/workbook.xml.relsPK-!Zxl/workbook.xmlPK-!PZg S xl/styles.xmlPK-!Ivj 1xl/theme/theme1.xmlPK-!10wxl/worksheets/sheet1.xmlPK-!?PNydocProps/core.xmlPK-!e{<docProps/app.xmlPK >ooxml/tools/languages/Libro1-spanisch-es.xlsx000644 000765 000024 00000017262 14764622263 021725 0ustar00alexstaff000000 000000 PK!SN[Content_Types].xml (N0EHC-ݲ@5(`Ib/y=@j7bs=36kؘXJbSxfVK)< uV"4>Z7"z)[уKRz 6@#W&9`ϻU1ѵLTE)N9;l01HO>4Q+(2wiɆ%?-27AzeCHr+;>(2~YD[2geϢԯyir#~> $1i8PD R"PK!U0#L _rels/.rels (MO0 HݐBKwAH!T~I$ݿ'TG~M;xl/workbook.xmlT]o }xO0)U154UU>c %Ѵk{bϽ ͹T諰N`: 0LCw3g:chp&}.>{sD] !dnh*a'7dB{ e—A0!%w  璋u)@PCJc] )+K%ŨA hGt)5~P+/ 4ΥOU'V6YF9ɤYmղ vi@Ŋ{2Zd@Vya5be zث€;A|li _l/PmUɣ7һ+ٵ!2 [tӸi')NMRg1(@xj7e zYPxP|bS« mCvDu|fnXs)مfLq0ڃpNGqym-Yt>ae(hlFA4Y4 hnz/G)`,GxZDd:uT}դ+PK!!3 xl/styles.xmlT[k0~?8K451h{Ul9HJlȗĥcuwsSzJ\ G!FLjE:**b>2R뎂s ޹fE-LR{OT#1V_a8'r{,DRxhRˆ:傻c,W; F3Z6xЙ^4](uK, -H:(!a'V΢R'zT*/o@OT%$OK-A Fޢd5|k7Trqݽ?P-Es| CDHNPR I'|Jy'7Z SxJ:koq縉$|*p'ZrX^ o3.QS@oʵJQN0MԎAM = ̑*&Li$ӓFȕ3N10ӔC :AkWx/bj%72\.0=9x3iFaoLmac3N_}߾O>ͦ>67>R+.\?O<ڻ1MDX~r,^NbcHt{TUo0zu},^_>pl=RQ7rz\xpSeyxL7wN+1ésoޥ!.Lw)auɘ;Tv|sx8z@N]$l <Ə sx/N|*8a}F H h8%Rdn X0U"'>s9'' 4mR;\!ӝO= Wۤ"A/Kub3L|,î]A[Ν> 3<%{cA/F߈U/n`7WsJ$A٦*="sÞ9Y4b[u'uRm69(/^ܖJ.wb]Yu%}e%Ȑbaߌ1s&(f-8/DjĖ^i0@a; M[+{0PRg+pve/;Nmκj._˗e-sY޾^K-S/P]Iv|f#b@7M;$7-E _ ld/5T5ιU%Zp #3lnwZ&|u:U\(*+fT*C7EnC˺6@˾du Dᯌ0+++ZZ:T(n\m^;AfdhAy>qʚ\hw9%:H;W D1J7+ cxγn_dEH+ֻ0z$rXj3KY'h#WE'A& ߺ0Dlÿ ,T,t26H"1tM6pZBZAwLf32Qvح> FZ/!G !ŢfU;pJ%\T3oN)܄mȿsSNUɡlE& nHtcyz v\}Q=gfqf:OM?C޲8D26Բ QsN8,ӊӴ49;uMDc6gzĺ4o.[m~cK %Y E_vl*Z ޫDݰ_J+zX)nԍzuU+^,*NQva?+ ʯ}2I+1\Wk}v f>@HFmԮ{RAUjҠoF~jԀn6RFEja 0>XyF/ƮkPK!4LZlxl/worksheets/sheet1.xmlMO0 H(-Bu1Mp@B|m%qx{V ]vsY~0eGL+*Bm&ZeX>`ַ6s[naL-S0JP MpQE:Au,F! =̟[_ZX JV.H J/`M8scZVNuڬ9_Wh+ّV%Ѷ(Yjz7Iv_hiYWkVo5034q1+uI42$bLI,W5a?ZPK!ai;YdocProps/core.xml (N0EHC}YI*JHQi?d=Σ!lXz3wFWGD_`]UHעVV8CL h:C*rmj@RrSb$sIp ̇c^`F|ڦ ;Lt6)k2a1- N'c۶Ico7O/q[q@e.8׶ &yW?z(C|x֨\$,&7IiJ(} 9q͈g@P~PK!Ԝ1!docProps/app.xml (n0 (@V1+rXI{d:&Kfϲlɟ|8uY:+v%>], wX#&>u#L,[T(,H,.+-PNN6޷HŽ'C>:.:_/n!+)k4Pz6:kbϠ#J1msz U!4 y&\+~}k01)ѢCM>d~p `% p1bE! RQil|heco0dtkbZ!?Sa>#xwKp,/H/amEi bSA>M Vo= gxϊ"&o?PK-!SN[Content_Types].xmlPK-!U0#L _rels/.relsPK-!p-xl/_rels/workbook.xml.relsPK-!Y>M;xl/workbook.xmlPK-!!3 4 xl/styles.xmlPK-!MlV  xl/theme/theme1.xmlPK-!4LZl|xl/worksheets/sheet1.xmlPK-!ai;YdocProps/core.xmlPK-!Ԝ1!docProps/app.xmlPK >^ooxml/tools/languages/PaxHeader/Книга1-russisch-ru.xlsx000644 000765 000024 00000000130 14764622263 026544 xustar00alexstaff000000 000000 59 path=ooxml/tools/languages/Книга1-russisch-ru.xlsx 29 mtime=1741890739.24996455 ooxml/tools/languages/Книга1-russisch-ru.xlsx000644 000765 000024 00000017417 14764622263 024613 0ustar00alexstaff000000 000000 PK!SN[Content_Types].xml (N0EHC-ݲ@5(`Ib/y=@j7bs=36kؘXJbSxfVK)< uV"4>Z7"z)[уKRz 6@#W&9`ϻU1ѵLTE)N9;l01HO>4Q+(2wiɆ%?-27AzeCHr+;>(2~YD[2geϢԯyir#~> $1i8PD R"PK!U0#L _rels/.rels (MO0 HݐBKwAH!T~I$ݿ'TG~ .V3/F{W ŇJZMQ˖91q@xF:7y&1;/DffKn[R;z2V%bӝԩ9xH'p#p <6w2yI=r{P|b]³ MCfDq/_)ܲblj_13 Iiə`r=4G0FZ0s ;1n2|2$1DrL^ {d& -U׫bv98?Yyق9# ruUPK!X"d  xl/styles.xmlIn0z{EC,6$uR@R[Zl" N]w;]v;87[AH6"D~Qm)O,T*nroD+ISe_%8^Sj IMTJ baWhJJ GA0a("nB l8(f+4YrZ#R:먿1=DB+*{P_U+SSHHaQxTJZ t'zv+'_YR(4l5tImwΖ9cEܞ[m k * FnS`Agn0bFN`9,P7m@zi1;^i xpo.̒%1F)K8,lvU.,)Y)Is&NA9v5zĮ+$"L1t B?Gik?cQ]=q @?=BUu(2np`1˄upDr{s-V@u޳;eD+p2Pf0f)r13]\7 otJco^<:/4󯃎~A?7O@ ם-ŃE+U=>8 4јL48"/HaaCC+$ q37PK!:| xl/theme/theme1.xmlYn7;4><׊-ن5v#5ÙnHa pN$]ed/{X/,6WP){I ǖ9.$R7bcuGbb.KZ~Rp2bcL[=!Q2F%/?іp=OjbQ`Klx6a%H$'3{ó>{lnʒFԔ{~/?S _?R+]/?C{}>$1 |f1,a?o&1$P27pl.q[E|.cQlwƝ2<<'S|nn#t蚻+ 藸Tv#lyD)N3vcuKF 6=uqdHDʅI qY P[ٽuum$:bj*KTQLM [ bʼ ᒹaFЯøþKt Ldt#Ϝ6$2HQbe!([~=r5MD=sG,bf :A2m[ęJ):Bc;;,谙k6v%5d窺Os)r+emgwqx(ߤDJ]TzL ")70IY{|]p+~gyོ%7b?oZ 3DP`D"j_bs~i0@d;1I^[*{?q0PRgl*p6˚'0$uQ\T5}U]e.jZNj|&P|ЄP'3nWE82k@Y)GZL~Bdʺ9fL@I+>[.rYu=S $RLѵz[ҩ. Pob1mDaD}9QyzebEaEC_jŕ+UT܃isPUf2*8MΤf@ɽ̀05C]?Uu_U+]Mn77Q˪7ȹ:HT.] aZ>exggiXmjpzmw~;jX֙:)y y`ַ6s[naL-S0JP MpQE:Au,F! =̟[_ZX JV.H J/`M8scZVNuڬ9_Wh+ّV%Ѷ(Yjz7Iv_hiYWkVo5034q1+uI42$bLI,W5a?ZPK!]=YdocProps/core.xml (N0EHC}T$uE%$@,{Fنh* {̝A6XWk#(ŵUrP!ͧmz$!JgC̜Gvق>z2m>FO_5Uw+%8Y;^Ü߆;jws^> t}R^t4% 68%(2|oPK!4docProps/app.xml (Mn0zrZA1(Y4;OET" r"ݵ1e$!d<8ukØwr3n["K;,oߨU#YL[T(,LҌێ;-q+}UYWܷH+< GC1:.:_қ/mBc RX}e7`#`Ts>Z\i\]AP為F׷V-:4c^ȾAD 7!Q~~~+ɂ8S4|pp* Fn"n,5V+ |J<0)jҷܞum+ |iQkX'7~,k^flze nebk'5%[?PK-!SN[Content_Types].xmlPK-!U0#L _rels/.relsPK-!p-xl/_rels/workbook.xml.relsPK-!zP9Jxl/workbook.xmlPK-!X"d  C xl/styles.xmlPK-!:| 'xl/theme/theme1.xmlPK-!4LZlxl/worksheets/sheet1.xmlPK-!]=YvdocProps/core.xmlPK-!4docProps/app.xmlPK >ooxml/tools/languages/PaxHeader/الكتاب1-arabisch-ar.xlsx000644 000765 000024 00000000133 14764622263 027123 xustar00alexstaff000000 000000 61 path=ooxml/tools/languages/الكتاب1-arabisch-ar.xlsx 30 mtime=1741890739.250277469 ooxml/tools/languages/الكتاب1-arabisch-ar.xlsx000644 000765 000024 00000017402 14764622263 025161 0ustar00alexstaff000000 000000 PK!SN[Content_Types].xml (N0EHC-ݲ@5(`Ib/y=@j7bs=36kؘXJbSxfVK)< uV"4>Z7"z)[уKRz 6@#W&9`ϻU1ѵLTE)N9;l01HO>4Q+(2wiɆ%?-27AzeCHr+;>(2~YD[2geϢԯyir#~> $1i8PD R"PK!U0#L _rels/.rels (MO0 HݐBKwAH!T~I$ݿ'TG~ ΕV3/F{W ĻJZMQ˖m%91v@xF:7y$1{_x͖ݶv'd^7K:D[SsNFp <42yI=r{P|b]£ MCfDq/w?}p˱$L: P7gS:+kĸ.F]q0zj0Ei؛Dj8^-WÏYXԅe|O̕.o9B YW5J~PK!.¸ xl/styles.xml[k0Bl7N`4M n ^[NDu 9;%qFbIOsSzH\ G!FLjᯏE0:**b>2R뎂w9e3sn Ė;&{OfK0ZYH H YDRt{ - #Y.J &DM45pCkzuVD5/ks2'<6R0Z+gQAE/ ]yjg*c _#oQTnǍTxSM%؝Qc!gj7OJF3nj*`qTKicc'0O7TP <v ΏNAtޕr;%b+[Hd!}aa ӎ-<LƢ~H ѧ둯 -'zp\A00gis"Q{\ xl/theme/theme1.xmlY[7~/? 6M Y'%Z[(Iލ @/B[R[Jio4ρ6=Ҍ=ZuSҲkX,+X.-&!#}"!ᇖ_~"ʄ k _& +zN>=XMaPkk~_V4F[g 2J:tjk6CAh5(Ňklkkz ~ (IХV.WLv›a0W29 a]j K\mP@$I< Aw%x;dAP *A 'tDF ,kCO8ɖGO?|r'h(ݓ\g|Lnʑ8GhnvNEz*1úO}yi\V]ԅ|ơK%StwVu?tKaLfQuQ_B^d^٩XtXPꗡZFq 0mxEAAfc ΩFz3Pb/3 tSٺqyjuiB-#t00,;͖iƺ2Obr3wkE"'&&S;nj*#4kx#[SwIn7aD:\N1{-_- 4m+W[@+qt;x2#iQNSp$½:XX/+r1w`h׼9#:Pvd5O+Oٚ.<Oݗsig*t; CԲ*nN-rk.yJ}0-2MYNÊQ۴S, O6muF8='?ȝZu@,Jܼf8(S˅wihL0]%l+0f6W亞,iPGLz̢&Z/rT(szT u la8>&28٭0[ٶ/+`g'Ŭd,n 50UWZLz(ŅV-h-PK!<=YdocProps/core.xml (N0EHC}b/UVJA v=m#bDz iT,=Ι;#/uhBPZԲԇ x"繖5d mۛT&j O6`} . $0:zoNAq⾶l3BVX{[`lF"RHi  h0M(z)*لS8OM$ͼS{|VKJS)}mO%Ȼ๮NBǾ(b똬c((atfv6X_PW,' OgȿPK!XY-docProps/app.xml (n0HC{ق*r\-*Vmƙl,;.ǪHđ#o f '.|??ό8U6i D]泔%ύfz K"*+dl˗/* I^pu 3J;>T [h4M8\I}dͽf_o^)>+CN|Z&s 6T+ZYXR Y(A𧀸ՏoLR4h@I4_h,"`kT0!e3ضdjtw }^p9mjr>q\ L8?+)0?cݵ?SaYj8X덿P>u䴓qI Ym!;xr~6K_IL;PK-!SN[Content_Types].xmlPK-!U0#L _rels/.relsPK-!p-xl/_rels/workbook.xml.relsPK-!3Pxl/workbook.xmlPK-!.¸ I xl/styles.xmlPK-!z>\ xl/theme/theme1.xmlPK-!҇O~xl/worksheets/sheet1.xmlPK-!<=YTdocProps/core.xmlPK-!XY-docProps/app.xmlPK >ooxml/tools/languages/Skoroszyt1-polnisch-pl.xlsx000644 000765 000024 00000017301 14764622263 022712 0ustar00alexstaff000000 000000 PK!SN[Content_Types].xml (N0EHC-ݲ@5(`Ib/y=@j7bs=36kؘXJbSxfVK)< uV"4>Z7"z)[уKRz 6@#W&9`ϻU1ѵLTE)N9;l01HO>4Q+(2wiɆ%?-27AzeCHr+;>(2~YD[2geϢԯyir#~> $1i8PD R"PK!U0#L _rels/.rels (MO0 HݐBKwAH!T~I$ݿ'TG~c %]k{bϽ KWa4:t`$47? f9tƔ"O\x_ń8^ؒy푸 B_*Lj!-&%Rh߁X]!+ף-p%pSVqJǻ6оq +RrkHW_J;"JdjG[Ǘ;\]*F60)7C{p#n4+װ6OΧ Apgi0v4Dy8Ep6v1RNm9e3w$Ė{&OfG0ZYH HKYDRx< N- #Y.vJ DM43pCkzqV D5/K :R0Z+gQAE/ ]yj'*c _#oQTn |k7Trqݹ=5֢ojs֟"k .YiE!O! U$)(NFH{an>/1Ly*X@ỽ>w4iN+*+<wJ&:B* >[xֱߌEMđg#_NSA#?Hj\8Bmx@,*Vӣp?%Z ҮEd2fָ{ #:៷mp5dj.a:}wmio. JAX"( I$ $׳6)oGHhx;(Y:.jՐ˿8ALˣPK!EPKc xl/theme/theme1.xmlY͏@]׌>}zc "GDihqIZ ΩҢ zcF}4zu{ݏ^$ !)O;AN%@$)MxTjH*N1)k"7wIBȧwXA,'0$)6" ż<&\T4@)N@1W J =6 ̔*&L)H.ybdl颪r-Ls:L;cBaNP1A2>ȅ#kɍ_. L53m' (lt ]ܰ9l [}'XpfY9e_=A-8x;Ѩ^t|k~|MGŌt%jn!3v\yl&bSuE%9#i<ÊHd'}虠cȿ%NJ2 ,> ؒArgHDХ@k`AW߿~ן}7F#wӹ-߾_~_ԗƿoϟR+.\O߾7__}̆iB$zD.=3q=q#cQ=T|ׅ̇xܱ4+E=3?x9quC=*'+s}:@ԧS$% >1.LO(auɘ9Tv|s 8z@]$l <Ə sxN|*8aÏ}F H h8%Rd X0u" #̹E?k3Mc\@bt•~!8gP\o[?r%ѿ' w0LW$vfGo5wR/c=t|^ V9$z\)f"tR{חg}AԝԅSKdaQ( !_Ny,A}ZOb]Yu-}dȵe7c̜ c(0|t "N }Wnn" P9NB+KeO){ <~?G) }òfW dn۪&W5m-s[2R T6EǴ~:?3ةZ3r$MG‹t9eۆ2y62Hp;/CT5йU%Zr #3ln~Z%|=U<)*+vU*C7E/otG1@^k2׈LjfSF݈m-~MӶQ7o ~2J8eMtupn4 J{EֽӫR"ak1i7o2"yPl}Xk. ,4\L̠q _%/_NfD߇YBqpC:$TM:^6Xj8V!bkҌA&(;ֈt qW#`-WxzJ`ַ6s[naL-S0JP MpQE:Au,F! =̟[_ZX JV.H J/`M8scZVNuڬ9_Wh+ّV%Ѷ(Yjz7Iv_hiYWkVo5034q1+uI42$bLI,W5a?ZPK!7l;YdocProps/core.xml (]K0C}d@eW+w!9ۂIۿ7V捐ssH>&%A hn=כt1JtEm΍Gg, '}m!cϢCGqgb!^[k 00H'pMC tfx8|+3dLc9[AG/'c۶YcnQS]q@U!x`\U5̇mN=z$ɇޠjA*%^Ք&]!. |/PK!adocProps/app.xml (n0 n(@VQzXI{d:*KI~Nn$'.J,( X7Q PT(nOjcL`hJJ-t,V;C潌M,G{ . GPC}Άbr\u>NK;k_cCţ.PĶ~)܂=dG']*9Ok|/06eԪUb.нE `Mv&mS2>!e}_N17cU/.K#٘L]qG v8 QױK&X8G?]xmEmM^x&ք=o= mooxml/tools/languages/PaxHeader/Sešit1-tschechisch-cs.xlsx000644 000765 000024 00000000130 14764622263 024741 xustar00alexstaff000000 000000 58 path=ooxml/tools/languages/Sešit1-tschechisch-cs.xlsx 30 mtime=1741890739.249186504 ooxml/tools/languages/Sešit1-tschechisch-cs.xlsx000644 000765 000024 00000017272 14764622263 023007 0ustar00alexstaff000000 000000 PK!SN[Content_Types].xml (N0EHC-ݲ@5(`Ib/y=@j7bs=36kؘXJbSxfVK)< uV"4>Z7"z)[уKRz 6@#W&9`ϻU1ѵLTE)N9;l01HO>4Q+(2wiɆ%?-27AzeCHr+;>(2~YD[2geϢԯyir#~> $1i8PD R"PK!U0#L _rels/.rels (MO0 HݐBKwAH!T~I$ݿ'TG~$qi0y3 oҏ'c{cKp}x!J憦vrcK!*+X !|HR2q`<\ K}bbw\VjMY^*/-(F%m,+}WХ8!@+4 vE.xdGɢ0RM&<Мo TKJ'V[N&pܜR +=hSի^Ak-hdKe1:TځP7[?:Z;iӊӍVTxW:iL/vS#t7U|SpvnCZ~55S>>]| d#4OAEshV9 ςMtDb5 ww^B>ZD[h`Pb0~x7[^q0 ` Q0i0Hx9/"hO^z$G%s%\su I_ LPK! V xl/theme/theme1.xmlY͋7? sw5%l$dQV32%9R(Bo=@ $'#$lJZv G~ztҽzG ’_P=ؘ$Ӗk8(4|OHe n ,K۟~rmDlI9*f8&H#ޘ+R#^bP$9O&d>)}gv|XV]ʽ#D[>3fC|OEB-"ʄ k _& +zN>=XMaPkk~_V4F[g 2J:tjk6CAh5(Ňklkkz ~ (IХV.WLq›a0W29 a]j K\]P@$I< Aw%xdAP *A 'tDF ,kCO8ɖųg>}=K6Vedjʽ뿿^=&$^??^VŷO^>}⻯C{>$15|d1,a?>৓FX(}Yk D]]x˸w-[#>1({N\UsΓ{r>7q7:rE|J\*̼AQ"'Xz7vcuwGF 6uqdHDʅvH qY P[ٻuul$l D1x%]*(w\F/HO1e^p\^#WaaߣFrI]:wc&gNI!(n01{gJ66VL\MQ̹#1NvL9qfGg>R{ccg :lf<7J]uٹ,u%J}&J9Ql˚'70$u^՜W5ٴkZ漖q}}Z&/_ɻ<olLrA]o4 vIZf & 7Hxω#4PY7;"S=ތ aJ't^ WХ)Vϻw+:]֥J4FFTFԗWv&V4V4eQ\L[E^=xQoavX)m&/sLjf #Tn\Z]joi#l#4E8N~n!SX܌zCZ n4[~­Z:5Aօ]F]eƅ!פAL$%qW_eM4h ָ&f2LHa7FG`+jw+I6pGcM)ʁc"⠜zsL&lEdy825t"(&pM+sSfp }SGAi:5dyêJ[SKDuo8u@0L'LSӰl6  ~[NOr'V˺R'27o] Ω:pg} dJEɬFoޜn%J_AB; ~X.:p(.u0"kˆEp}q_X57T7Gt*f٩:B[zn7uFs48hWA(n!fT*nܫPK!4LZlxl/worksheets/sheet1.xmlMO0 H(-Bu1Mp@B|m%qx{V ]vsY~0eGL+*Bm&ZeX>`ַ6s[naL-S0JP MpQE:Au,F! =̟[_ZX JV.H J/`M8scZVNuڬ9_Wh+ّV%Ѷ(Yjz7Iv_hiYWkVo5034q1+uI42$bLI,W5a?ZPK!4-;YdocProps/core.xml (N0EHC}T$uE%$@,{Fنh*{̝A6XWk#(ŵUrP!ͧmz$!JgC̜Gvق>z2m>FO_5Uw+%8Y;^Ü߆;jws^> t}R^t4 68?bF< }PK!;KdocProps/app.xml (n0 v(@V1zhI{ge:fK~&NSo$'6Y1Y \"Cg|iݾO?E\ wX߿M#YL[T(L҂eJc iK_U7-:y~-@J,/PLjZz3]X_!4+5'_Q:%m9h^^JS5G J aXlLZuАYx"{X!:16%c܄DQ?DMc獃9ROH.#Äz›Fwkp= )--򼨶5D,yE wd]cQyr^W9謦PK-!SN[Content_Types].xmlPK-!U0#L _rels/.relsPK-!p-xl/_rels/workbook.xml.relsPK-!x2;xl/workbook.xmlPK-!磬 4 xl/styles.xmlPK-! V  xl/theme/theme1.xmlPK-!4LZlxl/worksheets/sheet1.xmlPK-!4-;Y4docProps/core.xmlPK-!;KdocProps/app.xmlPK >fooxml/tools/languages/PaxHeader/工作簿1-chinesisch-zh.xlsx000644 000765 000024 00000000132 14764622263 026540 xustar00alexstaff000000 000000 60 path=ooxml/tools/languages/工作簿1-chinesisch-zh.xlsx 30 mtime=1741890739.250600304 ooxml/tools/languages/工作簿1-chinesisch-zh.xlsx000644 000765 000024 00000017440 14764622263 024601 0ustar00alexstaff000000 000000 PK!SN[Content_Types].xml (N0EHC-ݲ@5(`Ib/y=@j7bs=36kؘXJbSxfVK)< uV"4>Z7"z)[уKRz 6@#W&9`ϻU1ѵLTE)N9;l01HO>4Q+(2wiɆ%?-27AzeCHr+;>(2~YD[2geϢԯyir#~> $1i8PD R"PK!U0#L _rels/.rels (MO0 HݐBKwAH!T~I$ݿ'TG~fNxl/workbook.xmlTˎ0#]5MJF8UC[6,V H|7 7Ͻk.Boun$R"|yc< SFg1{E8x&r溦VRcs!; +X2!|HC3q0O0i*X^B <2Y-O˙ݗETҟjPr>]ﴱlZdA[LE"ҀPPgTⶑx*H1W"Bse1/UP:$~ʢDT~&q8j'T^XͼXAß^5"3oJi4E%[(\f+c1S NhLqppB{qyi-שѿr>.`ޠOθ ;2\ Fj>mOۗ*["K-TV\iY$ /%bCWQoZHW Bm1.&ghMH8-Բ6'Ⱥ%,<"㐢$cxRr'Lb y?xטACbi)TBZ̉;qVcNY+ qH=vsjeOi4Q<DW-d.pskQ 0OWRUpGPugSFjQto#\IcbiEZ lzNtJإwĎ\TEHS3hQ.ׯ|^Sk9HN={]30AQfpcCEcǺ-Y:|Q~M*0ݩ7Z"CGv414xx1[? S<"?KK?-b٧~yviwa’k;Huv_m(.Cg$|D_OԟNF_$QI bO }DPN} $PH";4oPK!^ xl/theme/theme1.xmlY[7~/? 6o5d7 Y'Z[(Iލ >BJ_PJ -4/ݒˏfr]s>9ΝzG ’_P=ؘ$Ӗs8(4|OHe n ,w~"ڒB-?rU, #qpMG>-9:1-VJZ1F$ŠdBF/|>?{9GDj`D[;>,+X.-!#}"!ዖ_?~qbmeBTn5'Ƈ='& 0W5u\ޯk+}F#Xij^{^l 5ۡAh5(Ňklkkz ~ (IХV.WLq›a0W29 a]j K\mP@$I< A2w%xdAP *A o?鈢- ieX"ֆ=q2-2h GNxr?<]6Vedj_txa|ѓ}zXqǟ?o89:0Cc] bKEۡ/# xu oq`e~8fp1a+j.y2uO&BG(ܟπ^Ke7–)J$KO}1v}B,gM>:8]2$V"B;$,\B-:VG6㇘Zn.CSHF.#|dBB2?BdqX+0El#$.1c3$LRyיtC3%}`+&@IyoKqA'Xc]ۜ83Z1Ehw]6|}9Vĺ\U u:Ea> -N%14_[ Jѡ J |q:Fr7i!R ny//A sf5A0CnA .U-6wMM #މIT;e9ǭUJMsل5=4Oc8I9뼪9j}Ui/2y-zz-L^@ewyt'J]>h(ݓ\g|Lnʑ8Ghn`NEz*1úO}yi\V]ԅ|ơK%StwVu?tKaLfQuQ_Bf^ٙXtXPꗡZFq 0mxEAAfc ΙFz3Pb/3 tSٺqyjui=G-#t00,;͖Yƺ2Obr3kE"&&S;nj+#4kx#[S}InaD:\N1{-_- 4m+WX@+oqt;x2#iQNSp~_$½:7XX/+r1w`h׼9#:Pvd5O+Oٚ.<Ogsig*t; CԲ*nN-rk.yJ<}0-2MYNÊQ۴3, O6muF8='?ȝZu@,JܼfysNZR[(5~!B#lW 0aT" ^[ #/j}⺿y#@:wkA j{PzF٭u Za9{GݠojnJFP*vPo7A^VS|vmPK!1꓁xl/worksheets/sheet1.xmln0 m N1(C3-ӶI$i޾r鍤ďO^W/EUkRϷg?* OǢ֟?v7eDd%X=21ŎT0KO9SRF͗0\2A},ސ|d]*GZțm: ZgV.HZ/s.=gTJp̗iL0ɮ2fpWC-c';jҾ%L$TO$v! ^: ;GB7,ы7 4Yy*$yDH͔`{ȃEyWWߵl39zUK(Gљz?PK!&=YdocProps/core.xml (N0HC{b-PYI*JHqm;mH8? A;ή AhQR3Z%Z֐8ʯRa-<ڀ%(cda;q]:* Y5g.c颠9c`nB<_|PK!3isdocProps/app.xml (n0 n(@V1zXI{d:fKɞe v۬@cNn$'b6Y1Y 1"Cg|iݶ7'"K;,Я_U#YL[T(,LҌeJc iJ_U7w-:y~&qGJ,OP״K}``ޅXįD|E5ȧ:{3(9mS̹Fs-u4Uk .yIsA]![I1K+/Td!aVG ط7!Q?!NcVχ{cӧj< # qqx5O{mg}K  O=.u KuˌMom|[/vfNxl/workbook.xmlPK-!-',} G xl/styles.xmlPK-!^ >xl/theme/theme1.xmlPK-!1꓁xl/worksheets/sheet1.xmlPK-!&=YdocProps/core.xmlPK-!3isdocProps/app.xmlPK >ooxml/tools/languages/Cartel1-italienisch-it.xlsx000644 000765 000024 00000017260 14764622263 022557 0ustar00alexstaff000000 000000 PK!SN[Content_Types].xml (N0EHC-ݲ@5(`Ib/y=@j7bs=36kؘXJbSxfVK)< uV"4>Z7"z)[уKRz 6@#W&9`ϻU1ѵLTE)N9;l01HO>4Q+(2wiɆ%?-27AzeCHr+;>(2~YD[2geϢԯyir#~> $1i8PD R"PK!U0#L _rels/.rels (MO0 HݐBKwAH!T~I$ݿ'TG~=xl/workbook.xmlT]o }xO0eŮj``/]s-/|=\XܜK #ɤ>$qw7a<SF_7ǽ1G% q%sCS ;%q,sT$ )ԸC{0LK.ֆץоB1BVG+{Jfu5বb/ۃ6>q +RrkHW_J;"JdjG[AIC5b۸%L6-Dgs:ˆkk$+F\&;i0f4Dy8Epf<ݬ7q=Yqy9# bUPK! xl/styles.xmlT[k0~?8K451h{Ul9HJlȗĥcuwsSzJ\ G!FLjE:**b>2R뎂s ޹fE-LR{OT#1V_a8'r{,DRxhRˆ:傻c,W; F3Z6xЙ^4](uK, -H:(!a'V΢R'zT*/o@OT%$OK-A Fޢd5|k7Trqݽ?P-Es| CDHNPR I'|Jy'7Z SxJ:koq縉$|*p'ZrX^ o3.QS@oʵJQN0MԎAM)= ̑*&Li$ӓFȕ3N10ӔC :AkWx/bj%72\.0=9x3iFaoLmac3N_}߾O>ͦ>67>R+.\?O<ڻ1MDX~r,^NbcHt{TUo0zu},^_>pl=RQ7rz\xpSeyxL7wN+1ésoޥ!.Lw)auɘ;Tv|sx8z@N]$l <Ə sx/N|*8a}F H h8%Rdn X0U"'>s9'' 4mR;\!ӝO= Wۤ"A/Kub3L|,î]A[Ν> 3<%{cA/F߈U/n`7WsJ$A٦*="sÞ9Y4b[u'uRm69(/^ܖJ.wb]Yu%}e%Ȑbaߌ1s&(f-8/DjĖ^i0@a; M[+{0PRg+pve/;Nmκj._˗e-sY޾^K-S/P]Iv|f#b@7M;$7-E _ ld/5T5ιU%Zp #3lnwZ&|u:U\(*+fT*C7EnC˺6@˾du Dᯌ0+++ZZ:T(n\m^;AfdhAy>qʚ\hw9%:H;W D1J7+ cxγn_dEH+ֻ0z$rXj3KY'h#WE'A& ߺ0Dlÿ ,T,t26H"1tM6pZBZAwLf32Qvح> FZ/!G !ŢfU;pJ%\T3oN)܄mȿsSNUɡlE& nHtcyz v\}Q=gfqf:OM?C޲8D26Բ QsN8,ӊӴ49;uMDc6gzĺ4o.[m~cK %Y E_vl*Z ޫDݰ_J+zX)nԍzuU+^,*NQva?+ ʯ}2I+1\Wk}v f>@HFmԮ{RAUjҠoF~jԀn6RFEja 0>XyF/ƮkPK!4LZlxl/worksheets/sheet1.xmlMO0 H(-Bu1Mp@B|m%qx{V ]vsY~0eGL+*Bm&ZeX>`ַ6s[naL-S0JP MpQE:Au,F! =̟[_ZX JV.H J/`M8scZVNuڬ9_Wh+ّV%Ѷ(Yjz7Iv_hiYWkVo5034q1+uI42$bLI,W5a?ZPK!$ g<YdocProps/core.xml (N0EHC}-Tik?d=Σ!lXz3wFGYG_`Ъ@Y\}^MDTqZk:C*g0mj pQ )G){C0v$8TwJKSOq HDi>m8PΒ x=Xl蔉S 2a!Y/iw1B mUc[1@ea׶O j6y'ߝe=p= x>Yy?TTl8[Tܬ|ގ rb5!e/>C PK!v̒!docProps/app.xml (n0 (@V1-zXI{d:&Kɞ~Nn$'Jzc.R.l\ؗexUL*1`)坹7)valr)nT ,VZ N^źv}k1*[Pauٝ Mh;v l-ͳ)Xx܈EռM3[rt4VTo-x\SϨGA?! ۀKV=ZIdx%O8 mS2ƾ˔c{'*'<1EkRp~`88o &9w<{9&hNjOv,./.Rϋz@ŠSA?>L =V= gx~Y._wVo?PK-!SN[Content_Types].xmlPK-!U0#L _rels/.relsPK-!p-xl/_rels/workbook.xml.relsPK-!ae>=xl/workbook.xmlPK-! 6 xl/styles.xmlPK-! V  xl/theme/theme1.xmlPK-!4LZlxl/worksheets/sheet1.xmlPK-!$ g<Y!docProps/core.xmlPK-!v̒!docProps/app.xmlPK >\ooxml/tools/debugging/builddiff.sh000644 000765 000024 00000002642 14764622263 017707 0ustar00alexstaff000000 000000 #!/bin/sh mkdir -p /Users/alex/src/ooxml/t rm -fr /Users/alex/src/ooxml/t/* cd /Users/alex/src/ooxml/t unzip -q /Users/alex/src/ooxml/examples/ok/export${1}.xlsx xmllint --format [Content_Types].xml > 0Content_Types.xml xmllint --format xl/workbook.xml > 0workbook.xml xmllint --format xl/_rels/workbook.xml.rels > 0workbook.xml.rels xmllint --format docProps/core.xml > 0core.xml xmllint --format xl/worksheets/sheet1.xml > 0sheet1.xml xmllint --format xl/theme/theme1.xml > 0theme1.xml xmllint --format _rels/.rels > 0rels xmllint --format docProps/app.xml > 0app.xml xmllint --format xl/sharedStrings.xml > 0sharedStrings.xml rm -fr [Content_Types].xml _rels docProps xl unzip -q /Users/alex/src/ooxml/examples/export${1}.xlsx xmllint --format [Content_Types].xml > 1Content_Types.xml xmllint --format xl/workbook.xml > 1workbook.xml xmllint --format xl/_rels/workbook.xml.rels > 1workbook.xml.rels xmllint --format docProps/core.xml > 1core.xml xmllint --format xl/worksheets/sheet1.xml > 1sheet1.xml xmllint --format xl/theme/theme1.xml > 1theme1.xml xmllint --format _rels/.rels > 1rels xmllint --format docProps/app.xml > 1app.xml xmllint --format xl/sharedStrings.xml > 1sharedStrings.xml rm -fr [Content_Types].xml _rels docProps xl > diff.txt for i in Content_Types.xml workbook.xml workbook.xml.rels core.xml sheet1.xml theme1.xml rels app.xml sharedStrings.xml do echo === $i === >> diff.txt diff 0$i 1$i >> diff.txt done